oreorenasass 3.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (268) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +11 -0
  3. data/CONTRIBUTING +3 -0
  4. data/MIT-LICENSE +20 -0
  5. data/README.md +221 -0
  6. data/Rakefile +370 -0
  7. data/VERSION +1 -0
  8. data/VERSION_NAME +1 -0
  9. data/bin/sass +13 -0
  10. data/bin/sass-convert +12 -0
  11. data/bin/scss +13 -0
  12. data/extra/update_watch.rb +13 -0
  13. data/init.rb +18 -0
  14. data/lib/sass/cache_stores/base.rb +88 -0
  15. data/lib/sass/cache_stores/chain.rb +34 -0
  16. data/lib/sass/cache_stores/filesystem.rb +60 -0
  17. data/lib/sass/cache_stores/memory.rb +47 -0
  18. data/lib/sass/cache_stores/null.rb +25 -0
  19. data/lib/sass/cache_stores.rb +15 -0
  20. data/lib/sass/callbacks.rb +67 -0
  21. data/lib/sass/css.rb +407 -0
  22. data/lib/sass/engine.rb +1181 -0
  23. data/lib/sass/environment.rb +191 -0
  24. data/lib/sass/error.rb +198 -0
  25. data/lib/sass/exec/base.rb +187 -0
  26. data/lib/sass/exec/sass_convert.rb +264 -0
  27. data/lib/sass/exec/sass_scss.rb +424 -0
  28. data/lib/sass/exec.rb +9 -0
  29. data/lib/sass/features.rb +47 -0
  30. data/lib/sass/importers/base.rb +182 -0
  31. data/lib/sass/importers/filesystem.rb +211 -0
  32. data/lib/sass/importers.rb +22 -0
  33. data/lib/sass/logger/base.rb +30 -0
  34. data/lib/sass/logger/log_level.rb +45 -0
  35. data/lib/sass/logger.rb +12 -0
  36. data/lib/sass/media.rb +210 -0
  37. data/lib/sass/plugin/compiler.rb +565 -0
  38. data/lib/sass/plugin/configuration.rb +118 -0
  39. data/lib/sass/plugin/generic.rb +15 -0
  40. data/lib/sass/plugin/merb.rb +48 -0
  41. data/lib/sass/plugin/rack.rb +60 -0
  42. data/lib/sass/plugin/rails.rb +47 -0
  43. data/lib/sass/plugin/staleness_checker.rb +199 -0
  44. data/lib/sass/plugin.rb +133 -0
  45. data/lib/sass/railtie.rb +10 -0
  46. data/lib/sass/repl.rb +57 -0
  47. data/lib/sass/root.rb +7 -0
  48. data/lib/sass/script/css_lexer.rb +33 -0
  49. data/lib/sass/script/css_parser.rb +34 -0
  50. data/lib/sass/script/functions.rb +2626 -0
  51. data/lib/sass/script/lexer.rb +449 -0
  52. data/lib/sass/script/parser.rb +637 -0
  53. data/lib/sass/script/tree/funcall.rb +306 -0
  54. data/lib/sass/script/tree/interpolation.rb +118 -0
  55. data/lib/sass/script/tree/list_literal.rb +77 -0
  56. data/lib/sass/script/tree/literal.rb +45 -0
  57. data/lib/sass/script/tree/map_literal.rb +64 -0
  58. data/lib/sass/script/tree/node.rb +109 -0
  59. data/lib/sass/script/tree/operation.rb +103 -0
  60. data/lib/sass/script/tree/selector.rb +26 -0
  61. data/lib/sass/script/tree/string_interpolation.rb +104 -0
  62. data/lib/sass/script/tree/unary_operation.rb +69 -0
  63. data/lib/sass/script/tree/variable.rb +57 -0
  64. data/lib/sass/script/tree.rb +16 -0
  65. data/lib/sass/script/value/arg_list.rb +36 -0
  66. data/lib/sass/script/value/base.rb +240 -0
  67. data/lib/sass/script/value/bool.rb +35 -0
  68. data/lib/sass/script/value/color.rb +680 -0
  69. data/lib/sass/script/value/helpers.rb +262 -0
  70. data/lib/sass/script/value/list.rb +113 -0
  71. data/lib/sass/script/value/map.rb +70 -0
  72. data/lib/sass/script/value/null.rb +44 -0
  73. data/lib/sass/script/value/number.rb +530 -0
  74. data/lib/sass/script/value/string.rb +97 -0
  75. data/lib/sass/script/value.rb +11 -0
  76. data/lib/sass/script.rb +66 -0
  77. data/lib/sass/scss/css_parser.rb +42 -0
  78. data/lib/sass/scss/parser.rb +1209 -0
  79. data/lib/sass/scss/rx.rb +141 -0
  80. data/lib/sass/scss/script_lexer.rb +15 -0
  81. data/lib/sass/scss/script_parser.rb +25 -0
  82. data/lib/sass/scss/static_parser.rb +368 -0
  83. data/lib/sass/scss.rb +16 -0
  84. data/lib/sass/selector/abstract_sequence.rb +109 -0
  85. data/lib/sass/selector/comma_sequence.rb +175 -0
  86. data/lib/sass/selector/pseudo.rb +256 -0
  87. data/lib/sass/selector/sequence.rb +600 -0
  88. data/lib/sass/selector/simple.rb +117 -0
  89. data/lib/sass/selector/simple_sequence.rb +325 -0
  90. data/lib/sass/selector.rb +326 -0
  91. data/lib/sass/shared.rb +76 -0
  92. data/lib/sass/source/map.rb +210 -0
  93. data/lib/sass/source/position.rb +39 -0
  94. data/lib/sass/source/range.rb +41 -0
  95. data/lib/sass/stack.rb +120 -0
  96. data/lib/sass/supports.rb +227 -0
  97. data/lib/sass/tree/at_root_node.rb +83 -0
  98. data/lib/sass/tree/charset_node.rb +22 -0
  99. data/lib/sass/tree/comment_node.rb +82 -0
  100. data/lib/sass/tree/content_node.rb +9 -0
  101. data/lib/sass/tree/css_import_node.rb +60 -0
  102. data/lib/sass/tree/debug_node.rb +18 -0
  103. data/lib/sass/tree/directive_node.rb +59 -0
  104. data/lib/sass/tree/each_node.rb +24 -0
  105. data/lib/sass/tree/error_node.rb +18 -0
  106. data/lib/sass/tree/extend_node.rb +43 -0
  107. data/lib/sass/tree/for_node.rb +36 -0
  108. data/lib/sass/tree/function_node.rb +39 -0
  109. data/lib/sass/tree/if_node.rb +52 -0
  110. data/lib/sass/tree/import_node.rb +74 -0
  111. data/lib/sass/tree/keyframe_rule_node.rb +15 -0
  112. data/lib/sass/tree/media_node.rb +48 -0
  113. data/lib/sass/tree/mixin_def_node.rb +38 -0
  114. data/lib/sass/tree/mixin_node.rb +52 -0
  115. data/lib/sass/tree/node.rb +238 -0
  116. data/lib/sass/tree/prop_node.rb +171 -0
  117. data/lib/sass/tree/return_node.rb +19 -0
  118. data/lib/sass/tree/root_node.rb +44 -0
  119. data/lib/sass/tree/rule_node.rb +145 -0
  120. data/lib/sass/tree/supports_node.rb +38 -0
  121. data/lib/sass/tree/trace_node.rb +33 -0
  122. data/lib/sass/tree/variable_node.rb +36 -0
  123. data/lib/sass/tree/visitors/base.rb +72 -0
  124. data/lib/sass/tree/visitors/check_nesting.rb +177 -0
  125. data/lib/sass/tree/visitors/convert.rb +334 -0
  126. data/lib/sass/tree/visitors/cssize.rb +369 -0
  127. data/lib/sass/tree/visitors/deep_copy.rb +107 -0
  128. data/lib/sass/tree/visitors/extend.rb +68 -0
  129. data/lib/sass/tree/visitors/perform.rb +539 -0
  130. data/lib/sass/tree/visitors/set_options.rb +139 -0
  131. data/lib/sass/tree/visitors/to_css.rb +381 -0
  132. data/lib/sass/tree/warn_node.rb +18 -0
  133. data/lib/sass/tree/while_node.rb +18 -0
  134. data/lib/sass/util/cross_platform_random.rb +19 -0
  135. data/lib/sass/util/multibyte_string_scanner.rb +157 -0
  136. data/lib/sass/util/normalized_map.rb +130 -0
  137. data/lib/sass/util/ordered_hash.rb +192 -0
  138. data/lib/sass/util/subset_map.rb +110 -0
  139. data/lib/sass/util/test.rb +9 -0
  140. data/lib/sass/util.rb +1318 -0
  141. data/lib/sass/version.rb +124 -0
  142. data/lib/sass.rb +102 -0
  143. data/rails/init.rb +1 -0
  144. data/test/sass/cache_test.rb +131 -0
  145. data/test/sass/callbacks_test.rb +61 -0
  146. data/test/sass/compiler_test.rb +232 -0
  147. data/test/sass/conversion_test.rb +2054 -0
  148. data/test/sass/css2sass_test.rb +477 -0
  149. data/test/sass/data/hsl-rgb.txt +319 -0
  150. data/test/sass/encoding_test.rb +219 -0
  151. data/test/sass/engine_test.rb +3301 -0
  152. data/test/sass/exec_test.rb +86 -0
  153. data/test/sass/extend_test.rb +1661 -0
  154. data/test/sass/fixtures/test_staleness_check_across_importers.css +1 -0
  155. data/test/sass/fixtures/test_staleness_check_across_importers.scss +1 -0
  156. data/test/sass/functions_test.rb +1926 -0
  157. data/test/sass/importer_test.rb +412 -0
  158. data/test/sass/logger_test.rb +58 -0
  159. data/test/sass/mock_importer.rb +49 -0
  160. data/test/sass/more_results/more1.css +9 -0
  161. data/test/sass/more_results/more1_with_line_comments.css +26 -0
  162. data/test/sass/more_results/more_import.css +29 -0
  163. data/test/sass/more_templates/_more_partial.sass +2 -0
  164. data/test/sass/more_templates/more1.sass +23 -0
  165. data/test/sass/more_templates/more_import.sass +11 -0
  166. data/test/sass/plugin_test.rb +554 -0
  167. data/test/sass/results/alt.css +4 -0
  168. data/test/sass/results/basic.css +9 -0
  169. data/test/sass/results/cached_import_option.css +3 -0
  170. data/test/sass/results/compact.css +5 -0
  171. data/test/sass/results/complex.css +86 -0
  172. data/test/sass/results/compressed.css +1 -0
  173. data/test/sass/results/expanded.css +19 -0
  174. data/test/sass/results/filename_fn.css +3 -0
  175. data/test/sass/results/if.css +3 -0
  176. data/test/sass/results/import.css +31 -0
  177. data/test/sass/results/import_charset.css +5 -0
  178. data/test/sass/results/import_charset_1_8.css +5 -0
  179. data/test/sass/results/import_charset_ibm866.css +5 -0
  180. data/test/sass/results/import_content.css +1 -0
  181. data/test/sass/results/line_numbers.css +49 -0
  182. data/test/sass/results/mixins.css +95 -0
  183. data/test/sass/results/multiline.css +24 -0
  184. data/test/sass/results/nested.css +22 -0
  185. data/test/sass/results/options.css +1 -0
  186. data/test/sass/results/parent_ref.css +13 -0
  187. data/test/sass/results/script.css +16 -0
  188. data/test/sass/results/scss_import.css +31 -0
  189. data/test/sass/results/scss_importee.css +2 -0
  190. data/test/sass/results/subdir/nested_subdir/nested_subdir.css +1 -0
  191. data/test/sass/results/subdir/subdir.css +3 -0
  192. data/test/sass/results/units.css +11 -0
  193. data/test/sass/results/warn.css +0 -0
  194. data/test/sass/results/warn_imported.css +0 -0
  195. data/test/sass/script_conversion_test.rb +328 -0
  196. data/test/sass/script_test.rb +1054 -0
  197. data/test/sass/scss/css_test.rb +1215 -0
  198. data/test/sass/scss/rx_test.rb +156 -0
  199. data/test/sass/scss/scss_test.rb +3900 -0
  200. data/test/sass/scss/test_helper.rb +37 -0
  201. data/test/sass/source_map_test.rb +977 -0
  202. data/test/sass/superselector_test.rb +191 -0
  203. data/test/sass/templates/_cached_import_option_partial.scss +1 -0
  204. data/test/sass/templates/_double_import_loop2.sass +1 -0
  205. data/test/sass/templates/_filename_fn_import.scss +11 -0
  206. data/test/sass/templates/_imported_charset_ibm866.sass +4 -0
  207. data/test/sass/templates/_imported_charset_utf8.sass +4 -0
  208. data/test/sass/templates/_imported_content.sass +3 -0
  209. data/test/sass/templates/_partial.sass +2 -0
  210. data/test/sass/templates/_same_name_different_partiality.scss +1 -0
  211. data/test/sass/templates/alt.sass +16 -0
  212. data/test/sass/templates/basic.sass +23 -0
  213. data/test/sass/templates/bork1.sass +2 -0
  214. data/test/sass/templates/bork2.sass +2 -0
  215. data/test/sass/templates/bork3.sass +2 -0
  216. data/test/sass/templates/bork4.sass +2 -0
  217. data/test/sass/templates/bork5.sass +3 -0
  218. data/test/sass/templates/cached_import_option.scss +3 -0
  219. data/test/sass/templates/compact.sass +17 -0
  220. data/test/sass/templates/complex.sass +305 -0
  221. data/test/sass/templates/compressed.sass +15 -0
  222. data/test/sass/templates/double_import_loop1.sass +1 -0
  223. data/test/sass/templates/expanded.sass +17 -0
  224. data/test/sass/templates/filename_fn.scss +18 -0
  225. data/test/sass/templates/if.sass +11 -0
  226. data/test/sass/templates/import.sass +12 -0
  227. data/test/sass/templates/import_charset.sass +9 -0
  228. data/test/sass/templates/import_charset_1_8.sass +6 -0
  229. data/test/sass/templates/import_charset_ibm866.sass +11 -0
  230. data/test/sass/templates/import_content.sass +4 -0
  231. data/test/sass/templates/importee.less +2 -0
  232. data/test/sass/templates/importee.sass +19 -0
  233. data/test/sass/templates/line_numbers.sass +13 -0
  234. data/test/sass/templates/mixin_bork.sass +5 -0
  235. data/test/sass/templates/mixins.sass +76 -0
  236. data/test/sass/templates/multiline.sass +20 -0
  237. data/test/sass/templates/nested.sass +25 -0
  238. data/test/sass/templates/nested_bork1.sass +2 -0
  239. data/test/sass/templates/nested_bork2.sass +2 -0
  240. data/test/sass/templates/nested_bork3.sass +2 -0
  241. data/test/sass/templates/nested_bork4.sass +2 -0
  242. data/test/sass/templates/nested_import.sass +2 -0
  243. data/test/sass/templates/nested_mixin_bork.sass +6 -0
  244. data/test/sass/templates/options.sass +2 -0
  245. data/test/sass/templates/parent_ref.sass +25 -0
  246. data/test/sass/templates/same_name_different_ext.sass +2 -0
  247. data/test/sass/templates/same_name_different_ext.scss +1 -0
  248. data/test/sass/templates/same_name_different_partiality.scss +1 -0
  249. data/test/sass/templates/script.sass +101 -0
  250. data/test/sass/templates/scss_import.scss +12 -0
  251. data/test/sass/templates/scss_importee.scss +1 -0
  252. data/test/sass/templates/single_import_loop.sass +1 -0
  253. data/test/sass/templates/subdir/import_up1.scss +1 -0
  254. data/test/sass/templates/subdir/import_up2.scss +1 -0
  255. data/test/sass/templates/subdir/nested_subdir/_nested_partial.sass +2 -0
  256. data/test/sass/templates/subdir/nested_subdir/nested_subdir.sass +3 -0
  257. data/test/sass/templates/subdir/subdir.sass +6 -0
  258. data/test/sass/templates/units.sass +11 -0
  259. data/test/sass/templates/warn.sass +3 -0
  260. data/test/sass/templates/warn_imported.sass +4 -0
  261. data/test/sass/test_helper.rb +8 -0
  262. data/test/sass/util/multibyte_string_scanner_test.rb +147 -0
  263. data/test/sass/util/normalized_map_test.rb +51 -0
  264. data/test/sass/util/subset_map_test.rb +91 -0
  265. data/test/sass/util_test.rb +467 -0
  266. data/test/sass/value_helpers_test.rb +179 -0
  267. data/test/test_helper.rb +109 -0
  268. metadata +386 -0
@@ -0,0 +1,76 @@
1
+ module Sass
2
+ # This module contains functionality that's shared between Haml and Sass.
3
+ module Shared
4
+ extend self
5
+
6
+ # Scans through a string looking for the interoplation-opening `#{`
7
+ # and, when it's found, yields the scanner to the calling code
8
+ # so it can handle it properly.
9
+ #
10
+ # The scanner will have any backslashes immediately in front of the `#{`
11
+ # as the second capture group (`scan[2]`),
12
+ # and the text prior to that as the first (`scan[1]`).
13
+ #
14
+ # @yieldparam scan [StringScanner] The scanner scanning through the string
15
+ # @return [String] The text remaining in the scanner after all `#{`s have been processed
16
+ def handle_interpolation(str)
17
+ scan = Sass::Util::MultibyteStringScanner.new(str)
18
+ yield scan while scan.scan(/(.*?)(\\*)\#\{/m)
19
+ scan.rest
20
+ end
21
+
22
+ # Moves a scanner through a balanced pair of characters.
23
+ # For example:
24
+ #
25
+ # Foo (Bar (Baz bang) bop) (Bang (bop bip))
26
+ # ^ ^
27
+ # from to
28
+ #
29
+ # @param scanner [StringScanner] The string scanner to move
30
+ # @param start [Character] The character opening the balanced pair.
31
+ # A `Fixnum` in 1.8, a `String` in 1.9
32
+ # @param finish [Character] The character closing the balanced pair.
33
+ # A `Fixnum` in 1.8, a `String` in 1.9
34
+ # @param count [Fixnum] The number of opening characters matched
35
+ # before calling this method
36
+ # @return [(String, String)] The string matched within the balanced pair
37
+ # and the rest of the string.
38
+ # `["Foo (Bar (Baz bang) bop)", " (Bang (bop bip))"]` in the example above.
39
+ def balance(scanner, start, finish, count = 0)
40
+ str = ''
41
+ scanner = Sass::Util::MultibyteStringScanner.new(scanner) unless scanner.is_a? StringScanner
42
+ regexp = Regexp.new("(.*?)[\\#{start.chr}\\#{finish.chr}]", Regexp::MULTILINE)
43
+ while scanner.scan(regexp)
44
+ str << scanner.matched
45
+ count += 1 if scanner.matched[-1] == start
46
+ count -= 1 if scanner.matched[-1] == finish
47
+ return [str, scanner.rest] if count == 0
48
+ end
49
+ end
50
+
51
+ # Formats a string for use in error messages about indentation.
52
+ #
53
+ # @param indentation [String] The string used for indentation
54
+ # @param was [Boolean] Whether or not to add `"was"` or `"were"`
55
+ # (depending on how many characters were in `indentation`)
56
+ # @return [String] The name of the indentation (e.g. `"12 spaces"`, `"1 tab"`)
57
+ def human_indentation(indentation, was = false)
58
+ if !indentation.include?(?\t)
59
+ noun = 'space'
60
+ elsif !indentation.include?(?\s)
61
+ noun = 'tab'
62
+ else
63
+ return indentation.inspect + (was ? ' was' : '')
64
+ end
65
+
66
+ singular = indentation.length == 1
67
+ if was
68
+ was = singular ? ' was' : ' were'
69
+ else
70
+ was = ''
71
+ end
72
+
73
+ "#{indentation.length} #{noun}#{'s' unless singular}#{was}"
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,210 @@
1
+ module Sass::Source
2
+ class Map
3
+ # A mapping from one source range to another. Indicates that `input` was
4
+ # compiled to `output`.
5
+ #
6
+ # @!attribute input
7
+ # @return [Sass::Source::Range] The source range in the input document.
8
+ #
9
+ # @!attribute output
10
+ # @return [Sass::Source::Range] The source range in the output document.
11
+ class Mapping < Struct.new(:input, :output)
12
+ # @return [String] A string representation of the mapping.
13
+ def inspect
14
+ "#{input.inspect} => #{output.inspect}"
15
+ end
16
+ end
17
+
18
+ # The mapping data ordered by the location in the target.
19
+ #
20
+ # @return [Array<Mapping>]
21
+ attr_reader :data
22
+
23
+ def initialize
24
+ @data = []
25
+ end
26
+
27
+ # Adds a new mapping from one source range to another. Multiple invocations
28
+ # of this method should have each `output` range come after all previous ranges.
29
+ #
30
+ # @param input [Sass::Source::Range]
31
+ # The source range in the input document.
32
+ # @param output [Sass::Source::Range]
33
+ # The source range in the output document.
34
+ def add(input, output)
35
+ @data.push(Mapping.new(input, output))
36
+ end
37
+
38
+ # Shifts all output source ranges forward one or more lines.
39
+ #
40
+ # @param delta [Fixnum] The number of lines to shift the ranges forward.
41
+ def shift_output_lines(delta)
42
+ return if delta == 0
43
+ @data.each do |m|
44
+ m.output.start_pos.line += delta
45
+ m.output.end_pos.line += delta
46
+ end
47
+ end
48
+
49
+ # Shifts any output source ranges that lie on the first line forward one or
50
+ # more characters on that line.
51
+ #
52
+ # @param delta [Fixnum] The number of characters to shift the ranges
53
+ # forward.
54
+ def shift_output_offsets(delta)
55
+ return if delta == 0
56
+ @data.each do |m|
57
+ break if m.output.start_pos.line > 1
58
+ m.output.start_pos.offset += delta
59
+ m.output.end_pos.offset += delta if m.output.end_pos.line > 1
60
+ end
61
+ end
62
+
63
+ # Returns the standard JSON representation of the source map.
64
+ #
65
+ # If the `:css_uri` option isn't specified, the `:css_path` and
66
+ # `:sourcemap_path` options must both be specified. Any options may also be
67
+ # specified alongside the `:css_uri` option. If `:css_uri` isn't specified,
68
+ # it will be inferred from `:css_path` and `:sourcemap_path` using the
69
+ # assumption that the local file system has the same layout as the server.
70
+ #
71
+ # Regardless of which options are passed to this method, source stylesheets
72
+ # that are imported using a non-default importer will only be linked to in
73
+ # the source map if their importers implement
74
+ # \{Sass::Importers::Base#public\_url\}.
75
+ #
76
+ # @option options :css_uri [String]
77
+ # The publicly-visible URI of the CSS output file.
78
+ # @option options :css_path [String]
79
+ # The local path of the CSS output file.
80
+ # @option options :sourcemap_path [String]
81
+ # The (eventual) local path of the sourcemap file.
82
+ # @option options :type [Symbol]
83
+ # `:auto` (default), `:file`, or `:inline`.
84
+ # @return [String] The JSON string.
85
+ # @raise [ArgumentError] If neither `:css_uri` nor `:css_path` and
86
+ # `:sourcemap_path` are specified.
87
+ # @comment
88
+ # rubocop:disable MethodLength
89
+ def to_json(options)
90
+ css_uri, css_path, sourcemap_path =
91
+ options[:css_uri], options[:css_path], options[:sourcemap_path]
92
+ unless css_uri || (css_path && sourcemap_path)
93
+ raise ArgumentError.new("Sass::Source::Map#to_json requires either " \
94
+ "the :css_uri option or both the :css_path and :soucemap_path options.")
95
+ end
96
+ css_path &&= Sass::Util.pathname(Sass::Util.absolute_path(css_path))
97
+ sourcemap_path &&= Sass::Util.pathname(Sass::Util.absolute_path(sourcemap_path))
98
+ css_uri ||= Sass::Util.file_uri_from_path(css_path.relative_path_from(sourcemap_path.dirname))
99
+
100
+ result = "{\n"
101
+ write_json_field(result, "version", 3, true)
102
+
103
+ source_uri_to_id = {}
104
+ id_to_source_uri = {}
105
+ id_to_contents = {} if options[:type] == :inline
106
+ next_source_id = 0
107
+ line_data = []
108
+ segment_data_for_line = []
109
+
110
+ # These track data necessary for the delta coding.
111
+ previous_target_line = nil
112
+ previous_target_offset = 1
113
+ previous_source_line = 1
114
+ previous_source_offset = 1
115
+ previous_source_id = 0
116
+
117
+ @data.each do |m|
118
+ file, importer = m.input.file, m.input.importer
119
+
120
+ if options[:type] == :inline
121
+ source_uri = file
122
+ else
123
+ sourcemap_dir = sourcemap_path && sourcemap_path.dirname.to_s
124
+ sourcemap_dir = nil if options[:type] == :file
125
+ source_uri = importer && importer.public_url(file, sourcemap_dir)
126
+ next unless source_uri
127
+ end
128
+
129
+ current_source_id = source_uri_to_id[source_uri]
130
+ unless current_source_id
131
+ current_source_id = next_source_id
132
+ next_source_id += 1
133
+
134
+ source_uri_to_id[source_uri] = current_source_id
135
+ id_to_source_uri[current_source_id] = source_uri
136
+
137
+ if options[:type] == :inline
138
+ id_to_contents[current_source_id] =
139
+ importer.find(file, {}).instance_variable_get('@template')
140
+ end
141
+ end
142
+
143
+ [
144
+ [m.input.start_pos, m.output.start_pos],
145
+ [m.input.end_pos, m.output.end_pos]
146
+ ].each do |source_pos, target_pos|
147
+ if previous_target_line != target_pos.line
148
+ line_data.push(segment_data_for_line.join(",")) unless segment_data_for_line.empty?
149
+ (target_pos.line - 1 - (previous_target_line || 0)).times {line_data.push("")}
150
+ previous_target_line = target_pos.line
151
+ previous_target_offset = 1
152
+ segment_data_for_line = []
153
+ end
154
+
155
+ # `segment` is a data chunk for a single position mapping.
156
+ segment = ""
157
+
158
+ # Field 1: zero-based starting offset.
159
+ segment << Sass::Util.encode_vlq(target_pos.offset - previous_target_offset)
160
+ previous_target_offset = target_pos.offset
161
+
162
+ # Field 2: zero-based index into the "sources" list.
163
+ segment << Sass::Util.encode_vlq(current_source_id - previous_source_id)
164
+ previous_source_id = current_source_id
165
+
166
+ # Field 3: zero-based starting line in the original source.
167
+ segment << Sass::Util.encode_vlq(source_pos.line - previous_source_line)
168
+ previous_source_line = source_pos.line
169
+
170
+ # Field 4: zero-based starting offset in the original source.
171
+ segment << Sass::Util.encode_vlq(source_pos.offset - previous_source_offset)
172
+ previous_source_offset = source_pos.offset
173
+
174
+ segment_data_for_line.push(segment)
175
+
176
+ previous_target_line = target_pos.line
177
+ end
178
+ end
179
+ line_data.push(segment_data_for_line.join(","))
180
+ write_json_field(result, "mappings", line_data.join(";"))
181
+
182
+ source_names = []
183
+ (0...next_source_id).each {|id| source_names.push(id_to_source_uri[id].to_s)}
184
+ write_json_field(result, "sources", source_names)
185
+
186
+ if options[:type] == :inline
187
+ write_json_field(result, "sourcesContent",
188
+ (0...next_source_id).map {|id| id_to_contents[id]})
189
+ end
190
+
191
+ write_json_field(result, "names", [])
192
+ write_json_field(result, "file", css_uri)
193
+
194
+ result << "\n}"
195
+ result
196
+ end
197
+ # @comment
198
+ # rubocop:enable MethodLength
199
+
200
+ private
201
+
202
+ def write_json_field(out, name, value, is_first = false)
203
+ out << (is_first ? "" : ",\n") <<
204
+ "\"" <<
205
+ Sass::Util.json_escape_string(name) <<
206
+ "\": " <<
207
+ Sass::Util.json_value_of(value)
208
+ end
209
+ end
210
+ end
@@ -0,0 +1,39 @@
1
+ module Sass::Source
2
+ class Position
3
+ # The one-based line of the document associated with the position.
4
+ #
5
+ # @return [Fixnum]
6
+ attr_accessor :line
7
+
8
+ # The one-based offset in the line of the document associated with the
9
+ # position.
10
+ #
11
+ # @return [Fixnum]
12
+ attr_accessor :offset
13
+
14
+ # @param line [Fixnum] The source line
15
+ # @param offset [Fixnum] The source offset
16
+ def initialize(line, offset)
17
+ @line = line
18
+ @offset = offset
19
+ end
20
+
21
+ # @return [String] A string representation of the source position.
22
+ def inspect
23
+ "#{line.inspect}:#{offset.inspect}"
24
+ end
25
+
26
+ # @param str [String] The string to move through.
27
+ # @return [Position] The source position after proceeding forward through
28
+ # `str`.
29
+ def after(str)
30
+ newlines = str.count("\n")
31
+ Position.new(line + newlines,
32
+ if newlines == 0
33
+ offset + str.length
34
+ else
35
+ str.length - str.rindex("\n") - 1
36
+ end)
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,41 @@
1
+ module Sass::Source
2
+ class Range
3
+ # The starting position of the range in the document (inclusive).
4
+ #
5
+ # @return [Sass::Source::Position]
6
+ attr_accessor :start_pos
7
+
8
+ # The ending position of the range in the document (exclusive).
9
+ #
10
+ # @return [Sass::Source::Position]
11
+ attr_accessor :end_pos
12
+
13
+ # The file in which this source range appears. This can be nil if the file
14
+ # is unknown or not yet generated.
15
+ #
16
+ # @return [String]
17
+ attr_accessor :file
18
+
19
+ # The importer that imported the file in which this source range appears.
20
+ # This is nil for target ranges.
21
+ #
22
+ # @return [Sass::Importers::Base]
23
+ attr_accessor :importer
24
+
25
+ # @param start_pos [Sass::Source::Position] See \{#start_pos}
26
+ # @param end_pos [Sass::Source::Position] See \{#end_pos}
27
+ # @param file [String] See \{#file}
28
+ # @param importer [Sass::Importers::Base] See \{#importer}
29
+ def initialize(start_pos, end_pos, file, importer = nil)
30
+ @start_pos = start_pos
31
+ @end_pos = end_pos
32
+ @file = file
33
+ @importer = importer
34
+ end
35
+
36
+ # @return [String] A string representation of the source range.
37
+ def inspect
38
+ "(#{start_pos.inspect} to #{end_pos.inspect}#{" in #{@file}" if @file})"
39
+ end
40
+ end
41
+ end
data/lib/sass/stack.rb ADDED
@@ -0,0 +1,120 @@
1
+ module Sass
2
+ # A class representing the stack when compiling a Sass file.
3
+ class Stack
4
+ # TODO: use this to generate stack information for Sass::SyntaxErrors.
5
+
6
+ # A single stack frame.
7
+ class Frame
8
+ # The filename of the file in which this stack frame was created.
9
+ #
10
+ # @return [String]
11
+ attr_reader :filename
12
+
13
+ # The line number on which this stack frame was created.
14
+ #
15
+ # @return [String]
16
+ attr_reader :line
17
+
18
+ # The type of this stack frame. This can be `:import`, `:mixin`, or
19
+ # `:base`.
20
+ #
21
+ # `:base` indicates that this is the bottom-most frame, meaning that it
22
+ # represents a single line of code rather than a nested context. The stack
23
+ # will only ever have one base frame, and it will always be the most
24
+ # deeply-nested frame.
25
+ #
26
+ # @return [Symbol?]
27
+ attr_reader :type
28
+
29
+ # The name of the stack frame. For mixin frames, this is the mixin name;
30
+ # otherwise, it's `nil`.
31
+ #
32
+ # @return [String?]
33
+ attr_reader :name
34
+
35
+ def initialize(filename, line, type, name = nil)
36
+ @filename = filename
37
+ @line = line
38
+ @type = type
39
+ @name = name
40
+ end
41
+
42
+ # Whether this frame represents an import.
43
+ #
44
+ # @return [Boolean]
45
+ def is_import?
46
+ type == :import
47
+ end
48
+
49
+ # Whether this frame represents a mixin.
50
+ #
51
+ # @return [Boolean]
52
+ def is_mixin?
53
+ type == :mixin
54
+ end
55
+
56
+ # Whether this is the base frame.
57
+ #
58
+ # @return [Boolean]
59
+ def is_base?
60
+ type == :base
61
+ end
62
+ end
63
+
64
+ # The stack frames. The last frame is the most deeply-nested.
65
+ #
66
+ # @return [Array<Frame>]
67
+ attr_reader :frames
68
+
69
+ def initialize
70
+ @frames = []
71
+ end
72
+
73
+ # Pushes a base frame onto the stack.
74
+ #
75
+ # @param filename [String] See \{Frame#filename}.
76
+ # @param line [String] See \{Frame#line}.
77
+ # @yield [] A block in which the new frame is on the stack.
78
+ def with_base(filename, line)
79
+ with_frame(filename, line, :base) {yield}
80
+ end
81
+
82
+ # Pushes an import frame onto the stack.
83
+ #
84
+ # @param filename [String] See \{Frame#filename}.
85
+ # @param line [String] See \{Frame#line}.
86
+ # @yield [] A block in which the new frame is on the stack.
87
+ def with_import(filename, line)
88
+ with_frame(filename, line, :import) {yield}
89
+ end
90
+
91
+ # Pushes a mixin frame onto the stack.
92
+ #
93
+ # @param filename [String] See \{Frame#filename}.
94
+ # @param line [String] See \{Frame#line}.
95
+ # @param name [String] See \{Frame#name}.
96
+ # @yield [] A block in which the new frame is on the stack.
97
+ def with_mixin(filename, line, name)
98
+ with_frame(filename, line, :mixin, name) {yield}
99
+ end
100
+
101
+ def to_s
102
+ Sass::Util.enum_with_index(Sass::Util.enum_cons(frames.reverse + [nil], 2)).
103
+ map do |(frame, caller), i|
104
+ "#{i == 0 ? "on" : "from"} line #{frame.line}" +
105
+ " of #{frame.filename || "an unknown file"}" +
106
+ (caller && caller.name ? ", in `#{caller.name}'" : "")
107
+ end.join("\n")
108
+ end
109
+
110
+ private
111
+
112
+ def with_frame(filename, line, type, name = nil)
113
+ @frames.pop if @frames.last && @frames.last.type == :base
114
+ @frames.push(Frame.new(filename, line, type, name))
115
+ yield
116
+ ensure
117
+ @frames.pop unless type == :base && @frames.last && @frames.last.type != :base
118
+ end
119
+ end
120
+ end