| module Sass |
| # This module contains functionality that's shared between Haml and Sass. |
| module Shared |
| extend self |
| |
| # Scans through a string looking for the interoplation-opening `#{` |
| # and, when it's found, yields the scanner to the calling code |
| # so it can handle it properly. |
| # |
| # The scanner will have any backslashes immediately in front of the `#{` |
| # as the second capture group (`scan[2]`), |
| # and the text prior to that as the first (`scan[1]`). |
| # |
| # @yieldparam scan [StringScanner] The scanner scanning through the string |
| # @return [String] The text remaining in the scanner after all `#{`s have been processed |
| def handle_interpolation(str) |
| scan = Sass::Util::MultibyteStringScanner.new(str) |
| yield scan while scan.scan(/(.*?)(\\*)\#\{/m) |
| scan.rest |
| end |
| |
| # Moves a scanner through a balanced pair of characters. |
| # For example: |
| # |
| # Foo (Bar (Baz bang) bop) (Bang (bop bip)) |
| # ^ ^ |
| # from to |
| # |
| # @param scanner [StringScanner] The string scanner to move |
| # @param start [Character] The character opening the balanced pair. |
| # A `Fixnum` in 1.8, a `String` in 1.9 |
| # @param finish [Character] The character closing the balanced pair. |
| # A `Fixnum` in 1.8, a `String` in 1.9 |
| # @param count [Integer] The number of opening characters matched |
| # before calling this method |
| # @return [(String, String)] The string matched within the balanced pair |
| # and the rest of the string. |
| # `["Foo (Bar (Baz bang) bop)", " (Bang (bop bip))"]` in the example above. |
| def balance(scanner, start, finish, count = 0) |
| str = '' |
| scanner = Sass::Util::MultibyteStringScanner.new(scanner) unless scanner.is_a? StringScanner |
| regexp = Regexp.new("(.*?)[\\#{start.chr}\\#{finish.chr}]", Regexp::MULTILINE) |
| while scanner.scan(regexp) |
| str << scanner.matched |
| count += 1 if scanner.matched[-1] == start |
| count -= 1 if scanner.matched[-1] == finish |
| return [str, scanner.rest] if count == 0 |
| end |
| end |
| |
| # Formats a string for use in error messages about indentation. |
| # |
| # @param indentation [String] The string used for indentation |
| # @param was [Boolean] Whether or not to add `"was"` or `"were"` |
| # (depending on how many characters were in `indentation`) |
| # @return [String] The name of the indentation (e.g. `"12 spaces"`, `"1 tab"`) |
| def human_indentation(indentation, was = false) |
| if !indentation.include?(?\t) |
| noun = 'space' |
| elsif !indentation.include?(?\s) |
| noun = 'tab' |
| else |
| return indentation.inspect + (was ? ' was' : '') |
| end |
| |
| singular = indentation.length == 1 |
| if was |
| was = singular ? ' was' : ' were' |
| else |
| was = '' |
| end |
| |
| "#{indentation.length} #{noun}#{'s' unless singular}#{was}" |
| end |
| end |
| end |