condenser 1.2 → 1.4

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 (51) hide show
  1. checksums.yaml +4 -4
  2. data/lib/condenser/asset.rb +69 -35
  3. data/lib/condenser/build_cache.rb +22 -9
  4. data/lib/condenser/context.rb +9 -25
  5. data/lib/condenser/helpers/parse_helpers.rb +8 -1
  6. data/lib/condenser/manifest.rb +3 -1
  7. data/lib/condenser/pipeline.rb +8 -3
  8. data/lib/condenser/processors/babel_processor.rb +9 -15
  9. data/lib/condenser/processors/css_media_combiner_processor.rb +81 -0
  10. data/lib/condenser/processors/js_analyzer.rb +41 -8
  11. data/lib/condenser/processors/node_processor.rb +1 -0
  12. data/lib/condenser/processors/purgecss_processor.rb +6 -4
  13. data/lib/condenser/processors/rollup_processor.rb +38 -36
  14. data/lib/condenser/resolve.rb +27 -6
  15. data/lib/condenser/templating_engine/ejs.rb +1 -1
  16. data/lib/condenser/transformers/dart_sass_transformer.rb +285 -0
  17. data/lib/condenser/transformers/jst_transformer.rb +67 -17
  18. data/lib/condenser/transformers/sass/functions.rb +133 -0
  19. data/lib/condenser/transformers/sass/importer.rb +48 -0
  20. data/lib/condenser/transformers/sass.rb +4 -0
  21. data/lib/condenser/transformers/sass_transformer.rb +124 -281
  22. data/lib/condenser/transformers/svg_transformer/base.rb +26 -0
  23. data/lib/condenser/transformers/svg_transformer/tag.rb +54 -0
  24. data/lib/condenser/transformers/svg_transformer/template.rb +151 -0
  25. data/lib/condenser/transformers/svg_transformer/template_error.rb +2 -0
  26. data/lib/condenser/transformers/svg_transformer/value.rb +13 -0
  27. data/lib/condenser/transformers/svg_transformer/var_generator.rb +10 -0
  28. data/lib/condenser/transformers/svg_transformer.rb +19 -0
  29. data/lib/condenser/version.rb +1 -1
  30. data/lib/condenser.rb +17 -5
  31. data/test/cache_test.rb +157 -18
  32. data/test/dependency_test.rb +51 -2
  33. data/test/manifest_test.rb +34 -0
  34. data/test/minifiers/terser_minifier_test.rb +0 -1
  35. data/test/minifiers/uglify_minifier_test.rb +0 -1
  36. data/test/postprocessors/css_media_combiner_test.rb +107 -0
  37. data/test/postprocessors/purgecss_test.rb +62 -0
  38. data/test/preprocessor/babel_test.rb +703 -298
  39. data/test/preprocessor/js_analyzer_test.rb +35 -2
  40. data/test/processors/rollup_test.rb +50 -20
  41. data/test/resolve_test.rb +18 -9
  42. data/test/server_test.rb +15 -10
  43. data/test/templates/ejs_test.rb +2 -11
  44. data/test/templates/erb_test.rb +0 -5
  45. data/test/test_helper.rb +8 -3
  46. data/test/transformers/dart_scss_test.rb +139 -0
  47. data/test/transformers/jst_test.rb +165 -21
  48. data/test/transformers/scss_test.rb +14 -0
  49. data/test/transformers/svg_test.rb +40 -0
  50. metadata +23 -6
  51. data/lib/condenser/transformers/sass_transformer/importer.rb +0 -50
@@ -0,0 +1,133 @@
1
+ # Public: Functions injected into Sass context during Condenser evaluation.
2
+ #
3
+ # This module may be extended to add global functionality to all Condenser
4
+ # Sass environments. Though, scoping your functions to just your environment
5
+ # is preferred.
6
+ #
7
+ # module Condenser::SassProcessor::Functions
8
+ # def asset_path(path, options = {})
9
+ # end
10
+ # end
11
+ module Condenser::Sass
12
+ module Functions
13
+
14
+ # Public: Generate a url for asset path.
15
+ #
16
+ # Defaults to Context#asset_path.
17
+ def asset_path(path, options = {})
18
+ condenser_context.link_asset(path)
19
+
20
+ path = condenser_context.asset_path(path, options)
21
+ query = "?#{query}" if query
22
+ fragment = "##{fragment}" if fragment
23
+ "#{path}#{query}#{fragment}"
24
+ end
25
+
26
+ def asset_path_signature
27
+ {
28
+ "$path" => "String",
29
+ "$options: ()" => 'Map'
30
+ }
31
+ end
32
+
33
+ # Public: Generate a asset url() link.
34
+ #
35
+ # path - String
36
+ def asset_url(path, options = {})
37
+ "url(#{asset_path(path, options)})"
38
+ end
39
+
40
+ def asset_url_signature
41
+ {
42
+ "$path" => "String",
43
+ "$options: ()" => 'Map'
44
+ }
45
+ end
46
+
47
+ # Public: Generate url for image path.
48
+ def image_path(path)
49
+ asset_path(path, type: :image)
50
+ end
51
+
52
+ # Public: Generate a image url() link.
53
+ def image_url(path)
54
+ asset_url(path, type: :image)
55
+ end
56
+
57
+ # Public: Generate url for video path.
58
+ def video_path(path)
59
+ asset_path(path, type: :video)
60
+ end
61
+
62
+ # Public: Generate a video url() link.
63
+ def video_url(path)
64
+ asset_url(path, type: :video)
65
+ end
66
+
67
+ # Public: Generate url for audio path.
68
+ def audio_path(path)
69
+ asset_path(path, type: :audio)
70
+ end
71
+
72
+ # Public: Generate a audio url() link.
73
+ def audio_url(path)
74
+ asset_url(path, type: :audio)
75
+ end
76
+
77
+ # Public: Generate url for font path.
78
+ def font_path(path)
79
+ asset_path(path, type: :font)
80
+ end
81
+
82
+ # Public: Generate a font url() link.
83
+ def font_url(path)
84
+ asset_url(path, type: :font)
85
+ end
86
+
87
+ # Public: Generate url for javascript path.
88
+ def javascript_path(path)
89
+ asset_path(path, type: :javascript)
90
+ end
91
+
92
+ # Public: Generate a javascript url() link.
93
+ def javascript_url(path)
94
+ asset_url(path, type: :javascript)
95
+ end
96
+
97
+ # Public: Generate url for stylesheet path.
98
+ def stylesheet_path(path)
99
+ asset_path(path, type: :stylesheet)
100
+ end
101
+
102
+ # Public: Generate a stylesheet url() link.
103
+ def stylesheet_url(path)
104
+ asset_url(path, type: :stylesheet)
105
+ end
106
+
107
+ # Public: Generate a data URI for asset path.
108
+ def asset_data_url(path)
109
+ url = condenser_environment.asset_data_uri(path.value)
110
+ Sass::Script::String.new("url(" + url + ")")
111
+ end
112
+
113
+ protected
114
+ # Public: The Environment.
115
+ #
116
+ # Returns Condenser::Environment.
117
+ def condenser_context
118
+ options[:condenser][:context]
119
+ end
120
+
121
+ def condenser_environment
122
+ options[:condenser][:environment]
123
+ end
124
+
125
+ # Public: Mutatable set of dependencies.
126
+ #
127
+ # Returns a Set.
128
+ def condenser_dependencies
129
+ options[:asset][:process_dependencies]
130
+ end
131
+
132
+ end
133
+ end
@@ -0,0 +1,48 @@
1
+ require "sassc"
2
+
3
+ class Condenser::Sass::Importer < SassC::Importer
4
+
5
+ def imports(name, base)
6
+ name = expand_path(name, base)
7
+ env = options[:condenser][:environment]
8
+ accept = extensions.keys.map { |x| options[:condenser][:environment].extensions[x] }
9
+
10
+ options[:asset][:process_dependencies] << [name, accept.map{ |i| [i] }]
11
+
12
+ imports = []
13
+ env.resolve(name, accept: accept).sort_by(&:filename).each do |asset|
14
+ next if asset.filename == options[:filename]
15
+ imports << Import.new(asset.filename, source: asset.source, source_map_path: nil)
16
+ end
17
+
18
+ if imports.empty? && env.npm_path
19
+ package = File.join(env.npm_path, name, 'package.json')
20
+ if File.exist?(package)
21
+ package = JSON.parse(File.read(package))
22
+ if package['style']
23
+ imports << Import.new(name, source: File.read(File.join(env.npm_path, name, package['style'])), source_map_path: nil)
24
+ end
25
+ end
26
+ end
27
+
28
+ raise Condenser::FileNotFound, "couldn't find file '#{name}'" if imports.empty?
29
+
30
+ imports
31
+ end
32
+
33
+ # Allow .css files to be @imported
34
+ def extensions
35
+ { '.sass' => :sass, '.scss' => :scss, '.css' => :scss }
36
+ end
37
+
38
+ private
39
+
40
+ def expand_path(path, base=nil)
41
+ if path.start_with?('.')
42
+ File.expand_path(path, File.dirname(base)).delete_prefix(File.expand_path('.') + '/')
43
+ else
44
+ File.expand_path(path).delete_prefix(File.expand_path('.') + '/')
45
+ end
46
+ end
47
+
48
+ end
@@ -0,0 +1,4 @@
1
+ module Condenser::Sass
2
+ autoload :Functions, 'condenser/transformers/sass/functions'
3
+ autoload :Importer, 'condenser/transformers/sass/importer'
4
+ end
@@ -1,309 +1,152 @@
1
- class Condenser
2
- # Transformer engine class for the SASS/SCSS compiler. Depends on the `sass`
3
- # gem.
4
- #
5
- # For more infomation see:
6
- #
7
- # https://github.com/sass/sass
8
- # https://github.com/rails/sass-rails
1
+ # Transformer engine class for the SASS/SCSS compiler. Depends on the `sass`
2
+ # gem.
3
+ #
4
+ # For more infomation see:
5
+ #
6
+ # https://github.com/sass/sass
7
+ # https://github.com/rails/sass-rails
8
+ #
9
+ class Condenser::SassTransformer
10
+
11
+ attr_accessor :options
12
+
13
+ # Internal: Defines default sass syntax to use. Exposed so the ScssProcessor
14
+ # may override it.
15
+ def self.syntax
16
+ :sass
17
+ end
18
+
19
+ def self.setup(environment)
20
+ require "sassc" unless defined?(::SassC::Engine)
21
+ end
22
+
23
+ # Public: Return singleton instance with default options.
9
24
  #
10
- class SassTransformer
11
- autoload :Importer, 'condenser/transformers/sass_transformer/importer'
25
+ # Returns SassProcessor object.
26
+ def self.instance
27
+ @instance ||= new
28
+ end
12
29
 
13
- attr_accessor :options
14
-
15
- # Internal: Defines default sass syntax to use. Exposed so the ScssProcessor
16
- # may override it.
17
- def self.syntax
18
- :sass
19
- end
30
+ def self.call(environment, input)
31
+ instance.call(environment, input)
32
+ end
20
33
 
21
- def self.setup(environment)
22
- require "sassc" unless defined?(::SassC::Engine)
23
- end
24
-
25
- # Public: Return singleton instance with default options.
26
- #
27
- # Returns SassProcessor object.
28
- def self.instance
29
- @instance ||= new
30
- end
34
+ def self.cache_key
35
+ instance.cache_key
36
+ end
31
37
 
32
- def self.call(environment, input)
33
- instance.call(environment, input)
34
- end
38
+ attr_reader :cache_key
35
39
 
36
- def self.cache_key
37
- instance.cache_key
40
+ def name
41
+ self.class.name
42
+ end
43
+
44
+ # Public: Initialize template with custom options.
45
+ #
46
+ # options - Hash
47
+ # cache_version - String custom cache version. Used to force a cache
48
+ # change after code changes are made to Sass Functions.
49
+ #
50
+ def initialize(options = {}, &block)
51
+ @options = options
52
+ @cache_version = options[:cache_version]
53
+ # @cache_key = "#{self.class.name}:#{VERSION}:#{Autoload::Sass::VERSION}:#{@cache_version}".freeze
54
+ @importer_class = options[:importer] || Condenser::Sass::Importer
55
+
56
+ @sass_config = options[:sass_config] || {}
57
+ @functions = Module.new do
58
+ include Functions
59
+ include options[:functions] if options[:functions]
60
+ class_eval(&block) if block_given?
38
61
  end
62
+ end
39
63
 
40
- attr_reader :cache_key
64
+ def call(environment, input)
65
+ context = environment.new_context_class
66
+ engine_options = merge_options({
67
+ syntax: self.class.syntax,
68
+ filename: input[:filename],
69
+ source_map_file: "#{input[:filename]}.map",
70
+ source_map_contents: true,
71
+ # cache_store: Cache.new(environment.cache),
72
+ load_paths: environment.path,
73
+ importer: @importer_class,
74
+ condenser: { context: context, environment: environment },
75
+ asset: input
76
+ })
77
+
78
+ engine = SassC::Engine.new(input[:source], engine_options)
41
79
 
42
- def name
43
- self.class.name
80
+ css = Condenser::Utils.module_include(SassC::Script::Functions, @functions) do
81
+ engine.render
44
82
  end
83
+ css.delete_suffix!("\n/*# sourceMappingURL=#{File.basename(input[:filename])}.map */")
84
+ # engine.source_map
85
+ # css = css.delete_suffix!("\n/*# sourceMappingURL= */\n")
45
86
 
46
- # Public: Initialize template with custom options.
47
- #
48
- # options - Hash
49
- # cache_version - String custom cache version. Used to force a cache
50
- # change after code changes are made to Sass Functions.
51
- #
52
- def initialize(options = {}, &block)
53
- @options = options
54
- @cache_version = options[:cache_version]
55
- # @cache_key = "#{self.class.name}:#{VERSION}:#{Autoload::Sass::VERSION}:#{@cache_version}".freeze
56
- @importer_class = options[:importer] || Condenser::SassTransformer::Importer
57
-
58
- @sass_config = options[:sass_config] || {}
59
- @functions = Module.new do
60
- include Functions
61
- include options[:functions] if options[:functions]
62
- class_eval(&block) if block_given?
63
- end
64
- # puts @functions.method(:asset_path).source_location
65
- end
87
+ input[:source] = css
88
+ # input[:map] = map.to_json({})
89
+ input[:linked_assets] += context.links
90
+ input[:process_dependencies] += context.dependencies
91
+ end
66
92
 
67
- def call(environment, input)
68
- # context = input[:environment].context_class.new(input)
69
- engine_options = merge_options({
70
- syntax: self.class.syntax,
71
- filename: input[:filename],
72
- source_map_file: "#{input[:filename]}.map",
73
- source_map_contents: true,
74
- # cache_store: Cache.new(environment.cache),
75
- load_paths: environment.path,
76
- importer: @importer_class,
77
- condenser: {
78
- context: environment.new_context_class,
79
- environment: environment
80
- },
81
- asset: input
82
- })
93
+ private
83
94
 
84
- engine = SassC::Engine.new(input[:source], engine_options)
85
-
86
- css = Utils.module_include(SassC::Script::Functions, @functions) do
87
- engine.render
88
- end
89
- css.delete_suffix!("\n/*# sourceMappingURL=#{File.basename(input[:filename])}.map */")
90
- # engine.source_map
91
- # css = css.delete_suffix!("\n/*# sourceMappingURL= */\n")
95
+ # Public: Build the cache store to be used by the Sass engine.
96
+ #
97
+ # input - the input hash.
98
+ # version - the cache version.
99
+ #
100
+ # Override this method if you need to use a different cache than the
101
+ # Condenser cache.
102
+ def build_cache_store(input, version)
103
+ CacheStore.new(input[:cache], version)
104
+ end
92
105
 
106
+ def merge_options(options)
107
+ defaults = @sass_config.dup
93
108
 
94
- input[:source] = css
95
- # input[:map] = map.to_json({})
109
+ if load_paths = defaults.delete(:load_paths)
110
+ options[:load_paths] += load_paths
96
111
  end
97
112
 
98
- private
99
-
100
- # Public: Build the cache store to be used by the Sass engine.
101
- #
102
- # input - the input hash.
103
- # version - the cache version.
104
- #
105
- # Override this method if you need to use a different cache than the
106
- # Condenser cache.
107
- def build_cache_store(input, version)
108
- CacheStore.new(input[:cache], version)
109
- end
113
+ options.merge!(defaults)
114
+ options
115
+ end
110
116
 
111
- def merge_options(options)
112
- defaults = @sass_config.dup
117
+ # Functions injected into Sass context during Condenser evaluation.
118
+ module Functions
119
+ include Condenser::Sass::Functions
113
120
 
114
- if load_paths = defaults.delete(:load_paths)
115
- options[:load_paths] += load_paths
116
- end
121
+ # Returns a Sass::Script::String.
122
+ def asset_path(path, options = {})
123
+ condenser_context.link_asset(path.value)
117
124
 
118
- options.merge!(defaults)
119
- options
125
+ path = condenser_context.asset_path(path.value, options)
126
+ query = "?#{query}" if query
127
+ fragment = "##{fragment}" if fragment
128
+ SassC::Script::Value::String.new("#{path}#{query}#{fragment}", :string)
120
129
  end
121
130
 
122
- # Public: Functions injected into Sass context during Condenser evaluation.
123
- #
124
- # This module may be extended to add global functionality to all Condenser
125
- # Sass environments. Though, scoping your functions to just your environment
126
- # is preferred.
127
- #
128
- # module Condenser::SassProcessor::Functions
129
- # def asset_path(path, options = {})
130
- # end
131
- # end
132
- #
133
- module Functions
134
- # Public: Generate a url for asset path.
135
- #
136
- # Default implementation is deprecated. Currently defaults to
137
- # Context#asset_path.
138
- #
139
- # Will raise NotImplementedError in the future. Users should provide their
140
- # own base implementation.
141
- #
142
- # Returns a Sass::Script::String.
143
- def asset_path(path, options = {})
144
- path = path.value
145
-
146
- path, _, query, fragment = URI.split(path)[5..8]
147
- asset = condenser_environment.find!(path)
148
- condenser_context.link_asset(path)
149
- path = condenser_context.asset_path(asset.path, options)
150
- query = "?#{query}" if query
151
- fragment = "##{fragment}" if fragment
152
- SassC::Script::Value::String.new("#{path}#{query}#{fragment}", :string)
153
- end
154
-
155
- # Public: Generate a asset url() link.
156
- #
157
- # path - Sass::Script::String URL path
158
- #
159
- # Returns a Sass::Script::String.
160
- def asset_url(path, options = {})
161
- SassC::Script::Value::String.new("url(#{asset_path(path, options).value})")
162
- end
163
-
164
- # Public: Generate url for image path.
165
- #
166
- # path - Sass::Script::String URL path
167
- #
168
- # Returns a Sass::Script::String.
169
- def image_path(path)
170
- asset_path(path, type: :image)
171
- end
172
-
173
- # Public: Generate a image url() link.
174
- #
175
- # path - Sass::Script::String URL path
176
- #
177
- # Returns a Sass::Script::String.
178
- def image_url(path)
179
- asset_url(path, type: :image)
180
- end
181
-
182
- # Public: Generate url for video path.
183
- #
184
- # path - Sass::Script::String URL path
185
- #
186
- # Returns a Sass::Script::String.
187
- def video_path(path)
188
- asset_path(path, type: :video)
189
- end
190
-
191
- # Public: Generate a video url() link.
192
- #
193
- # path - Sass::Script::String URL path
194
- #
195
- # Returns a Sass::Script::String.
196
- def video_url(path)
197
- asset_url(path, type: :video)
198
- end
199
-
200
- # Public: Generate url for audio path.
201
- #
202
- # path - Sass::Script::String URL path
203
- #
204
- # Returns a Sass::Script::String.
205
- def audio_path(path)
206
- asset_path(path, type: :audio)
207
- end
208
-
209
- # Public: Generate a audio url() link.
210
- #
211
- # path - Sass::Script::String URL path
212
- #
213
- # Returns a Sass::Script::String.
214
- def audio_url(path)
215
- asset_url(path, type: :audio)
216
- end
217
-
218
- # Public: Generate url for font path.
219
- #
220
- # path - Sass::Script::String URL path
221
- #
222
- # Returns a Sass::Script::String.
223
- def font_path(path)
224
- asset_path(path, type: :font)
225
- end
226
-
227
- # Public: Generate a font url() link.
228
- #
229
- # path - Sass::Script::String URL path
230
- #
231
- # Returns a Sass::Script::String.
232
- def font_url(path)
233
- asset_url(path, type: :font)
234
- end
235
-
236
- # Public: Generate url for javascript path.
237
- #
238
- # path - Sass::Script::String URL path
239
- #
240
- # Returns a Sass::Script::String.
241
- def javascript_path(path)
242
- asset_path(path, type: :javascript)
243
- end
244
-
245
- # Public: Generate a javascript url() link.
246
- #
247
- # path - Sass::Script::String URL path
248
- #
249
- # Returns a Sass::Script::String.
250
- def javascript_url(path)
251
- asset_url(path, type: :javascript)
252
- end
253
-
254
- # Public: Generate url for stylesheet path.
255
- #
256
- # path - Sass::Script::String URL path
257
- #
258
- # Returns a Sass::Script::String.
259
- def stylesheet_path(path)
260
- asset_path(path, type: :stylesheet)
261
- end
262
-
263
- # Public: Generate a stylesheet url() link.
264
- #
265
- # path - Sass::Script::String URL path
266
- #
267
- # Returns a Sass::Script::String.
268
- def stylesheet_url(path)
269
- asset_url(path, type: :stylesheet)
270
- end
271
-
272
- # Public: Generate a data URI for asset path.
273
- #
274
- # path - Sass::Script::String logical asset path
275
- #
276
- # Returns a Sass::Script::String.
277
- def asset_data_url(path)
278
- url = condenser_environment.asset_data_uri(path.value)
279
- Sass::Script::String.new("url(" + url + ")")
280
- end
281
-
282
- protected
283
- # Public: The Environment.
284
- #
285
- # Returns Condenser::Environment.
286
- def condenser_context
287
- options[:condenser][:context]
288
- end
289
-
290
- def condenser_environment
291
- options[:condenser][:environment]
292
- end
131
+ # Returns a Sass::Script::String.
132
+ def asset_url(path, options = {})
133
+ SassC::Script::Value::String.new("url(#{asset_path(path, options).value})")
134
+ end
293
135
 
294
- # Public: Mutatable set of dependencies.
295
- #
296
- # Returns a Set.
297
- def condenser_dependencies
298
- options[:condenser][:process_dependencies]
299
- end
136
+ protected
300
137
 
138
+ def condenser_context
139
+ options[:condenser][:context]
140
+ end
141
+
142
+ def condenser_environment
143
+ options[:condenser][:environment]
301
144
  end
302
145
  end
146
+ end
303
147
 
304
- class ScssTransformer < SassTransformer
305
- def self.syntax
306
- :scss
307
- end
148
+ class Condenser::ScssTransformer < Condenser::SassTransformer
149
+ def self.syntax
150
+ :scss
308
151
  end
309
152
  end
@@ -0,0 +1,26 @@
1
+ class Condenser::SVGTransformer::Base
2
+
3
+ attr_accessor :children
4
+
5
+ def initialize(escape: nil)
6
+ @children = []
7
+ end
8
+
9
+ def to_module()
10
+ var_generator = Condenser::SVGTransformer::VarGenerator.new
11
+
12
+ <<~JS
13
+ export default function (svgAttributes) {
14
+ #{@children.last.to_js(var_generator: var_generator)}
15
+ if (svgAttributes) {
16
+ Object.keys(svgAttributes).forEach(function (key) {
17
+ __a.setAttribute(key, svgAttributes[key]);
18
+ });
19
+ }
20
+
21
+ return __a;
22
+ }
23
+ JS
24
+ end
25
+
26
+ end
@@ -0,0 +1,54 @@
1
+ class Condenser::SVGTransformer::Tag
2
+
3
+ attr_accessor :tag_name, :attrs, :children, :namespace
4
+
5
+ def initialize(name)
6
+ @tag_name = name
7
+ @attrs = []
8
+ @children = []
9
+ end
10
+
11
+ def to_s
12
+ @value
13
+ end
14
+
15
+ def inspect
16
+ "#<SVG::Tag:#{self.object_id} @tag_name=#{tag_name}>"
17
+ end
18
+
19
+ def to_js(append: nil, var_generator:, indentation: 4, namespace: nil)
20
+ namespace ||= self.namespace
21
+
22
+ output_var = var_generator.next
23
+ js = "#{' '*indentation}var #{output_var} = document.createElement"
24
+ js << if namespace
25
+ "NS(#{namespace.to_js}, #{JSON.generate(tag_name)});\n"
26
+ else
27
+ "(#{JSON.generate(tag_name)});\n"
28
+ end
29
+
30
+ @attrs.each do |attr|
31
+ if attr.is_a?(Hash)
32
+ attr.each do |k, v|
33
+ js << "#{' '*indentation}#{output_var}.setAttribute(#{JSON.generate(k)}, #{v.is_a?(String) ? v : v.to_js});\n"
34
+ end
35
+ else
36
+ js << "#{' '*indentation}#{output_var}.setAttribute(#{JSON.generate(attr)}, \"\");\n"
37
+ end
38
+ end
39
+
40
+ @children.each do |child|
41
+ js << if child.is_a?(Condenser::SVGTransformer::Tag)
42
+ child.to_js(var_generator: var_generator, indentation: indentation, append: output_var, namespace: namespace)
43
+ else
44
+ child.to_js(var_generator: var_generator, indentation: indentation, append: output_var)
45
+ end
46
+ end
47
+
48
+ js << "#{' '*indentation}#{append}.append(#{output_var});\n" if append
49
+
50
+ js
51
+ end
52
+
53
+ end
54
+