//! Large tests that exercise many features at once #[macro_use] mod macros; test!( /// https://github.com/kaj/rsass/issues/41 issue_41, "@function str-replace($string, $search, $replace: \"\") { $index: str-index($string, $search); @if $index { @return str-slice($string, 1, $index - 1)+$replace+str-replace(str-slice($string, $index + str-length($search)), $search, $replace); } @return $index; } $x: str-replace(url(\"a#b#c\"), \"#\", \":\"); a { color: $x; }", "a {\n color: url(\"a:b:;\n}\n" ); test!( base64_decode, r##" @use "sass:math"; @use "sass:map"; @function char-at($s, $idx) { @return str-slice($s, $idx, $idx); } @function bitwise-and($a, $b) { $x: null; $y: null; @if $a > $b { $x: $a; $y: $b; } @else { $x: $b; $y: $a; } $limit: math.floor(math.log($x, 2)); $result: 0; @for $n from 0 through $limit { $two-pow-n: math.pow(2, $n); $result: $result + $two-pow-n * (math.floor(math.div($x, $two-pow-n)) % 2) * (math.floor(math.div($y, $two-pow-n)) % 2); } @return $result; } @function bitwise-shift-left($n, $amt) { @return math.floor($n * math.pow(2, $amt)); } @function bitwise-shift-right($n, $amt) { @return math.floor(math.div($n, math.pow(2, $amt))); } @function bitwise-or($a, $b) { $x: null; $y: null; @if $a > $b { $x: $a; $y: $b; } @else { $x: $b; $y: $a; } $limit: math.floor(math.log($x, 2)); $result: 0; @for $n from 0 through $limit { $two-pow-n: math.pow(2, $n); $x-div-two-pow-n: math.floor(math.div($x, $two-pow-n)) % 2; $y-div-two-pow-n: math.floor(math.div($y, $two-pow-n)) % 2; $result: $result + $two-pow-n * ( ( ($x-div-two-pow-n + $y-div-two-pow-n) + $x-div-two-pow-n * $y-div-two-pow-n ) % 2 ); } @return $result; } @function letter-index-map() { $map: (); $chars: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; @for $i from 1 through str-length($chars) { $char: char-at($chars, $i); $map: map.set($map, $char, $i - 1); $map: map.set($map, $i - 1, $char); } @return $map; } @function ascii-map() { $map: (); $chars-upper: "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; @for $i from 1 through str-length($chars-upper) { $char: char-at($chars-upper, $i); $map: map.set($map, $char, $i - 1 + 65); $map: map.set($map, $i - 1 + 65, $char); } $chars-lower: "abcdefghijklmnopqrstuvwxyz"; @for $i from 1 through str-length($chars-lower) { $char: char-at($chars-lower, $i); $map: map.set($map, $char, $i - 1 + 97); $map: map.set($map, $i - 1 + 97, $char); } @return $map; } $letter-index-map: letter-index-map(); $ascii-map: ascii-map(); @function byte-at($str, $idx) { @return map-get($letter-index-map, char-at($str, $idx)); } @function chunk-string($str) { $chunks: []; @for $i from 1 through str-length($str) { @if ($i - 1) % 4 == 0 { $chunk: byte-at($str, $i) byte-at($str, $i + 1) byte-at($str, $i + 2) byte-at($str, $i + 3); $chunks: append($chunks, $chunk); } } @return $chunks; } @function decode-base64($str) { $result: ""; @if str-length($str) % 4 != 0 { @error "Invalid base64 string length"; } $chunks: chunk-string($str); @each $chunk in $chunks { $start: bitwise-or( bitwise-shift-left(nth($chunk, 1), 18), bitwise-shift-left(nth($chunk, 2), 12) ); @if bitwise-and(nth($chunk, 3), nth($chunk, 4)) == 64 { $result: "#{$result}#{map-get($ascii-map, bitwise-and(bitwise-shift-right($start, 16), 255))}"; } @else if nth($chunk, 4) == 64 { $start: bitwise-or($start, bitwise-shift-left(nth($chunk, 3), 6)); $result: "#{$result}#{map-get($ascii-map, bitwise-and(bitwise-shift-right($start, 16), 255))}"; $result: "#{$result}#{map-get($ascii-map, bitwise-and(bitwise-shift-right($start, 8), 255))}"; } @else { $val: bitwise-or(bitwise-shift-left(nth($chunk, 3), 6), nth($chunk, 4)); $start: bitwise-or($start, $val); $result: "#{$result}#{map-get($ascii-map, bitwise-and(bitwise-shift-right($start, 16), 255))}"; $result: "#{$result}#{map-get($ascii-map, bitwise-and(bitwise-shift-right($start, 8), 255))}"; $result: "#{$result}#{map-get($ascii-map, bitwise-and(bitwise-shift-right($start, 0), 255))}"; } } @return $result; } a { color: decode-base64("SGVsbG8="); } "##, "a {\n color: \"Hello\";\n}\n" ); test!( two_sum, r#" @use "sass:map"; @function two-sum($nums, $target) { $map: (); @for $i from 1 through length($nums) { $num: nth($nums, $i); $diff: $target - $num; @if map-get($map, $diff) { @return map-get($map, $diff) - 1 $i - 1; } @else { $map: map.set($map, $num, $i); } } @return null; } a { color: two-sum(2 7 11 15, 9); color: two-sum(3 2 4, 6); color: two-sum(3 3, 6); color: two-sum(3 2, 6); }"#, "a {\n color: 0 1;\n color: 1 2;\n color: 0 1;\n}\n" );