lightningcss 0.2.0-x86_64-linux-gnu → 1.33.0.1-x86_64-linux-gnu

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 60b9bf5ff6f7226f2deb903411280800ba1bb5e4d270fd32cc7c28ae23f82e54
4
- data.tar.gz: 3199cdeaca6c86296bd0d05c7350d450694e00c71d26a72a9cfe70acbc71e249
3
+ metadata.gz: 1485fc29582d87b66d75264e0b773efe97357d3fdd8a63a57004b062d5d94b9a
4
+ data.tar.gz: 68231e8729126e916fc40002a6ec6ea9993e444a3552217152b1c2f22b903ada
5
5
  SHA512:
6
- metadata.gz: 562c17a0bedbc7c0c971b20df9da6352b108b1607321f9ada7021c6d696515e8a371003a78ed90b4bd69fd60c01b6027016414f834cb5d5e27206a5e6b4c57e3
7
- data.tar.gz: e0b92d822c7244d589aa00c021338c27455cbaf845494eeac942a01a29e8c346b47141d7a87c752337d2a52152a51a5332fbcf1277deabc7873492b4da211e3f
6
+ metadata.gz: 0ee7d7471fa4cdbcb3bf81a834d1bfa819c889bf584fa10e590b0357d43aca02ba746cdf663c51a3f2adec303921702aae5faf4e22e88b58f0918565cbb5f527
7
+ data.tar.gz: d7152c918ccf343be32fb4cd52e3aed525f36e5d02016522403390f696935ecbf2f47a4be61499cc34d07897981c54529caa69c56506afa976a9a6180fb11021
data/README.md CHANGED
@@ -27,6 +27,16 @@ bundle add lightningcss
27
27
 
28
28
  Precompiled gems are published for Linux (gnu and musl) and macOS, on x86_64, aarch64, and arm. On those platforms nothing is compiled at install time. Anywhere else the gem builds from source and needs the [Rust toolchain](https://rustup.rs).
29
29
 
30
+ ### Versioning
31
+
32
+ The gem carries the version of the Lightning CSS release it packages. Gem v1.33.0 bundles [Lightning CSS v1.33.0](https://github.com/parcel-bundler/lightningcss/releases/tag/v1.33.0).
33
+
34
+ Lightning CSS publishes its Rust crate under a different number than it releases under: v1.33.0 ships the crate as `1.0.0-alpha.72`. The gem follows the release, since that is the version everything else calls it. `LightningCSS.lightningcss_version` reports the crate version a given build was compiled against.
35
+
36
+ So the version tracks Lightning CSS, not the Ruby API here. A minor bump is a minor Lightning CSS release, and says nothing about whether this gem's own API moved. Pin on the Lightning CSS version you want.
37
+
38
+ If the gem needs releasing again for the same Lightning CSS version, that release adds a fourth digit, as in v1.33.0.1.
39
+
30
40
  ### Usage
31
41
 
32
42
  #### Transforming
@@ -131,6 +141,113 @@ LightningCSS.transform_style_attribute("color: #ff0000; border: none", minify: t
131
141
 
132
142
  Having no selectors and no names, it takes neither `scope` nor `css_modules`, and says so when given one.
133
143
 
144
+ #### Parsing
145
+
146
+ `parse` answers what Lightning CSS read a stylesheet as, without printing anything. It takes `filename` and `error_recovery`, the two options that change how a stylesheet is read.
147
+
148
+ ```ruby
149
+ parsed = LightningCSS.parse(".card .title:hover { color: #f00 }")
150
+
151
+ parsed.stylesheet #=> the AST exactly as Lightning CSS serializes it
152
+ parsed.warnings #=> []
153
+ parsed.source #=> ".card .title:hover { color: #f00 }"
154
+ ```
155
+
156
+ The AST is Lightning CSS's own, so its shapes are the ones its [JavaScript visitors](https://lightningcss.dev/transforms.html) see and [`lightningcss/node/ast.d.ts`](https://github.com/parcel-bundler/lightningcss/blob/master/node/ast.d.ts) describes. It is what Lightning CSS understood, not what was written: `#f00` reads as an `rgb` with `r` of `255.0`, and a `0` margin reads as `0px`.
157
+
158
+ #### Walking the AST
159
+
160
+ `root` answers the stylesheet as a `LightningCSS::Node`, which walks, reads its fields by name, and knows what it sits inside.
161
+
162
+ ```ruby
163
+ root = LightningCSS.parse(source).root
164
+
165
+ root.type #=> "stylesheet"
166
+ root.keys #=> the fields this node carries
167
+ root.fields #=> those fields and their values, without its type and location
168
+ root.child_nodes #=> the nodes directly under it
169
+ root.every("declaration") #=> every declaration in the stylesheet
170
+ root.each #=> an Enumerator over every node
171
+ ```
172
+
173
+ Every object in the tree is a node, so reads chain all the way down.
174
+
175
+ ```ruby
176
+ rule = root.rules.first
177
+
178
+ rule.type #=> "style"
179
+ rule.value.selectors.first.map(&:type) #=> ["class", "combinator", "class", "pseudo-class"]
180
+ rule.value.declarations.declarations.first.value.r
181
+ #=> 255.0
182
+ ```
183
+
184
+ Most objects say what they are with their own `type`. The stylesheet, a declaration block, and a declaration do not, so a node names those `"stylesheet"`, `"declaration-block"`, and `"declaration"` from where it sits. Anything else without a `type`, like the `value` a rule wraps, answers `nil`.
185
+
186
+ Inspecting a node shows every field it carries.
187
+
188
+ ```
189
+ #<LightningCSS::Node style value=#<LightningCSS::Node>>
190
+ #<LightningCSS::Node location=0:1 selectors=[... 1 item] declarations=#<LightningCSS::Node declaration-block> rules=[]>
191
+ #<LightningCSS::Node declaration property="color" value=#<LightningCSS::Node rgb>>
192
+ ```
193
+
194
+ Lightning CSS names its fields in camelCase, and a field answers to its snake_case name too.
195
+
196
+ ```ruby
197
+ block.important_declarations # the same field as block.importantDeclarations
198
+ query.media_queries # mediaQueries
199
+ ```
200
+
201
+ Lightning CSS records where each rule starts and nothing else, so `location` is a rule's line, counted from 0, and its column, counted from 1 in UTF-16 code units. There are no end positions, so a node has no `slice` and there is no `at(offset)`.
202
+
203
+ ```ruby
204
+ rule.value.location
205
+ #=> {"source_index" => 0, "line" => 0, "column" => 1}
206
+ ```
207
+
208
+ `ancestors` answers what a node sits inside, and `rule?` says whether it is a rule.
209
+
210
+ ```ruby
211
+ declaration = root.every("declaration").first
212
+ declaration.ancestors.find(&:rule?).type
213
+ #=> "style"
214
+ ```
215
+
216
+ Nodes pattern match, and nest, since a field holding an object comes back as a node. Patterns take snake_case names, and a node's `type` matches even when Lightning CSS gave it none.
217
+
218
+ ```ruby
219
+ declaration => { type: "declaration", property:, value: { type: "rgb", r: } }
220
+ property #=> "color"
221
+ r #=> 255.0
222
+ ```
223
+
224
+ `to_h` and `to_json` answer the AST the node wraps.
225
+
226
+ ```ruby
227
+ declaration.value.to_h
228
+ #=> {"type" => "rgb", "r" => 255.0, "g" => 0.0, "b" => 0.0, "alpha" => 1.0}
229
+ ```
230
+
231
+ `LightningCSS::Visitor` answers a node with the method named after its type, and walks through anything nothing answers.
232
+
233
+ ```ruby
234
+ class Colors < LightningCSS::Visitor
235
+ def visit_style_rule(node)
236
+ puts node.value.location["line"]
237
+
238
+ visit_children(node)
239
+ end
240
+
241
+ def visit_declaration(node)
242
+ puts node.property
243
+ end
244
+ end
245
+
246
+ Colors.new.visit(LightningCSS.parse(source))
247
+ ```
248
+
249
+ A rule is answered as one, as in `visit_style_rule`, `visit_media_rule`, or `visit_namespace_rule`. Lightning CSS calls the rule `style`, but `namespace` and `nesting` are also parts of a selector, so `visit_namespace` answers `svg|rect` and `visit_namespace_rule` answers `@namespace`. Hyphens become underscores, so a `pseudo-class` is answered by `visit_pseudo_class`.
250
+
134
251
  #### Reusing options
135
252
 
136
253
  `LightningCSS::Transformer` holds a set of options to use across many stylesheets. Options given to a call are merged over the ones it was built with.
@@ -145,6 +262,8 @@ transformer.with(scope: "[s]")
145
262
 
146
263
  It answers `call` as well, so it can be handed to anything expecting something callable.
147
264
 
265
+ `transformer.parse` reads with the `filename` and `error_recovery` it holds and leaves the rest, which only matter to printing.
266
+
148
267
  ### Options
149
268
 
150
269
  | Option | Type | Description |
@@ -23,6 +23,8 @@ typedef struct LightningCssResult {
23
23
 
24
24
  struct LightningCssResult lightningcss_transform(const char *code, const char *options_json);
25
25
 
26
+ struct LightningCssResult lightningcss_parse(const char *code, const char *options_json);
27
+
26
28
  struct LightningCssResult lightningcss_transform_style_attribute(const char *code,
27
29
  const char *options_json);
28
30
 
@@ -90,6 +90,12 @@ static VALUE rb_transform(VALUE self, VALUE code, VALUE options) {
90
90
  return call(lightningcss_transform, code, options);
91
91
  }
92
92
 
93
+ static VALUE rb_parse(VALUE self, VALUE code, VALUE options) {
94
+ (void) self;
95
+
96
+ return call(lightningcss_parse, code, options);
97
+ }
98
+
93
99
  static VALUE rb_transform_style_attribute(VALUE self, VALUE code, VALUE options) {
94
100
  (void) self;
95
101
 
@@ -123,6 +129,7 @@ void Init_lightningcss(void) {
123
129
  rb_eOptionError = rb_define_class_under(rb_mLightningCSS, "OptionError", rb_eError);
124
130
  rb_eBundleError = rb_define_class_under(rb_mLightningCSS, "BundleError", rb_eError);
125
131
 
132
+ rb_define_singleton_method(rb_mBackend, "parse", rb_parse, 2);
126
133
  rb_define_singleton_method(rb_mBackend, "transform", rb_transform, 2);
127
134
  rb_define_singleton_method(rb_mBackend, "transform_style_attribute", rb_transform_style_attribute, 2);
128
135
  rb_define_singleton_method(rb_mBackend, "bundle", rb_bundle, 2);
Binary file
Binary file
Binary file
Binary file
@@ -8,6 +8,11 @@ module LightningCSS
8
8
  unavailable(__method__)
9
9
  end
10
10
 
11
+ #: (String, String) -> String
12
+ def parse(_code, _options_json)
13
+ unavailable(__method__)
14
+ end
15
+
11
16
  #: (String, String) -> String
12
17
  def transform_style_attribute(_code, _options_json)
13
18
  unavailable(__method__)
@@ -0,0 +1,220 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LightningCSS
4
+ # One object in the AST Lightning CSS parsed a stylesheet to.
5
+ #
6
+ # root = LightningCSS.parse(".a { color: red }").root
7
+ #
8
+ # root.type #=> "stylesheet"
9
+ # root.every("declaration") #=> every declaration in the stylesheet
10
+ # root.rules.first.value.location #=> {"source_index" => 0, "line" => 0, "column" => 1}
11
+ #
12
+ # Every object in the tree is a node, so reads chain all the way down. Most say what they are
13
+ # with their own `type`. The stylesheet, a declaration block, and a declaration do not, so a node
14
+ # names those from where it sits.
15
+ #
16
+ class Node
17
+ include Enumerable #[LightningCSS::Node]
18
+
19
+ POSITION = ["type", "loc"].freeze #: Array[String]
20
+ DECLARATIONS = ["declarations", "importantDeclarations"].freeze #: Array[String]
21
+
22
+ attr_reader :parent #: LightningCSS::Node?
23
+ attr_reader :field #: String?
24
+
25
+ #: (Hash[String, untyped], ?LightningCSS::Node?, ?String?) -> void
26
+ def initialize(attributes, parent = nil, field = nil)
27
+ @attributes = attributes
28
+ @parent = parent
29
+ @field = field
30
+ end
31
+
32
+ #: () -> String?
33
+ def type
34
+ attributes.fetch("type") { inferred_type }
35
+ end
36
+
37
+ #: () -> String?
38
+ def underscored_type
39
+ return nil unless (name = type)
40
+
41
+ name = name.tr("-", "_").downcase
42
+
43
+ rule? ? "#{name}_rule" : name
44
+ end
45
+
46
+ #: () -> bool
47
+ def rule?
48
+ field == "rules" && attributes.key?("type")
49
+ end
50
+
51
+ #: () -> Hash[String, Integer]?
52
+ def location
53
+ attributes["loc"]
54
+ end
55
+
56
+ #: (String) -> untyped
57
+ def [](key)
58
+ attributes[key]
59
+ end
60
+
61
+ #: () -> Array[String]
62
+ def keys
63
+ attributes.keys
64
+ end
65
+
66
+ #: () -> Hash[String, untyped]
67
+ def to_h
68
+ attributes
69
+ end
70
+
71
+ #: (?untyped) -> String
72
+ def to_json(state = nil)
73
+ state ? attributes.to_json(state) : attributes.to_json
74
+ end
75
+
76
+ #: (Array[Symbol]?) -> Hash[Symbol, untyped]
77
+ def deconstruct_keys(keys)
78
+ found = {} #: Hash[Symbol, untyped]
79
+
80
+ if keys
81
+ keys.each do |name|
82
+ key = field_for(name.to_s)
83
+
84
+ if key
85
+ found[name] = wrap(attributes[key], key)
86
+ elsif name == :type && type
87
+ found[name] = type
88
+ end
89
+ end
90
+ else
91
+ found[:type] = type if type
92
+ attributes.each_key { |key| found[key.to_sym] = wrap(attributes[key], key) }
93
+ end
94
+
95
+ found
96
+ end
97
+
98
+ #: () -> Array[LightningCSS::Node]
99
+ def child_nodes
100
+ @child_nodes ||= attributes.flat_map { |key, value| key == "loc" ? [] : nodes_in(value, key) }.freeze
101
+ end
102
+
103
+ #: () { (LightningCSS::Node) -> void } -> void
104
+ #: () -> Enumerator[LightningCSS::Node, void]
105
+ def each(&)
106
+ return enum_for(:each) unless block_given?
107
+
108
+ yield self
109
+
110
+ child_nodes.each { |child| child.each(&) }
111
+ end
112
+
113
+ #: () -> Array[LightningCSS::Node]
114
+ def ancestors
115
+ parent ? [parent, *parent.ancestors] : []
116
+ end
117
+
118
+ #: (String) -> Array[LightningCSS::Node]
119
+ def every(type)
120
+ each.select { |node| node.type == type || node.underscored_type == type }
121
+ end
122
+
123
+ #: () -> Hash[String, untyped]
124
+ def fields
125
+ attributes.except(*POSITION)
126
+ end
127
+
128
+ #: () -> String
129
+ def inspect
130
+ described = fields.map { |key, value| described_field(key, value) }
131
+ position = location
132
+ described.unshift("location=#{position["line"]}:#{position["column"]}") if position
133
+
134
+ "#<#{self.class.name}#{" #{type}" if type}#{" #{described.join(" ")}" unless described.empty?}>"
135
+ end
136
+
137
+ #: (Symbol, *untyped) -> untyped
138
+ def method_missing(name, *arguments)
139
+ key = field_for(name.to_s)
140
+
141
+ return super unless key
142
+
143
+ wrap(attributes[key], key)
144
+ end
145
+
146
+ #: (Symbol, ?bool) -> bool
147
+ def respond_to_missing?(name, include_private = false)
148
+ !field_for(name.to_s).nil? || super
149
+ end
150
+
151
+ protected
152
+
153
+ attr_reader :attributes #: Hash[String, untyped]
154
+
155
+ private
156
+
157
+ #: () -> String?
158
+ def inferred_type
159
+ if parent.nil? && attributes.key?("rules") && attributes.key?("sources")
160
+ "stylesheet"
161
+ elsif attributes.key?("importantDeclarations")
162
+ "declaration-block"
163
+ elsif DECLARATIONS.include?(field) && attributes.key?("property")
164
+ "declaration"
165
+ end
166
+ end
167
+
168
+ #: (untyped, String) -> Array[LightningCSS::Node]
169
+ def nodes_in(value, key)
170
+ case value
171
+ when Hash
172
+ [Node.new(value, self, key)]
173
+ when Array
174
+ value.flat_map { |item| nodes_in(item, key) }
175
+ else
176
+ []
177
+ end
178
+ end
179
+
180
+ #: (String, untyped) -> String
181
+ def described_field(key, value)
182
+ case value
183
+ when Array
184
+ "#{key}=#{value.empty? ? "[]" : "[... #{counted(value)}]"}"
185
+ when Hash
186
+ type = Node.new(value, self, key).type
187
+
188
+ "#{key}=#<#{self.class.name}#{" #{type}" if type}>"
189
+ else
190
+ "#{key}=#{value.inspect}"
191
+ end
192
+ end
193
+
194
+ #: (Array[untyped]) -> String
195
+ def counted(items)
196
+ "#{items.length} #{items.length == 1 ? "item" : "items"}"
197
+ end
198
+
199
+ #: (String) -> String?
200
+ def field_for(name)
201
+ return name if attributes.key?(name)
202
+
203
+ camelized = name.gsub(/_([a-z\d])/) { Regexp.last_match(1).to_s.upcase }
204
+
205
+ camelized if attributes.key?(camelized)
206
+ end
207
+
208
+ #: (untyped, String) -> untyped
209
+ def wrap(value, key)
210
+ case value
211
+ when Hash
212
+ key == "loc" ? value : Node.new(value, self, key)
213
+ when Array
214
+ value.map { |item| wrap(item, key) }
215
+ else
216
+ value
217
+ end
218
+ end
219
+ end
220
+ end
@@ -26,6 +26,11 @@ module LightningCSS
26
26
  :targets
27
27
  ].freeze #: Array[Symbol]
28
28
 
29
+ PARSE = [
30
+ :filename,
31
+ :error_recovery
32
+ ].freeze #: Array[Symbol]
33
+
29
34
  BUNDLE = [
30
35
  :minify,
31
36
  :error_recovery,
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LightningCSS
4
+ # What a stylesheet parsed to.
5
+ #
6
+ # `stylesheet` is the AST exactly as Lightning CSS serializes it, and `root` is the same tree as a
7
+ # `LightningCSS::Node` to walk. `warnings` are the ones a transform would have reported.
8
+ #
9
+ class ParseResult
10
+ attr_reader :source #: String?
11
+ attr_reader :stylesheet #: Hash[String, untyped]
12
+ attr_reader :warnings #: Array[String]
13
+
14
+ #: (String, ?String?) -> LightningCSS::ParseResult
15
+ def self.from_json(payload, source = nil)
16
+ parsed = JSON.parse(payload)
17
+
18
+ new(
19
+ source: source,
20
+ stylesheet: parsed.fetch("stylesheet"),
21
+ warnings: parsed.fetch("warnings")
22
+ )
23
+ end
24
+
25
+ #: (stylesheet: Hash[String, untyped], warnings: Array[String], ?source: String?) -> void
26
+ def initialize(stylesheet:, warnings:, source: nil)
27
+ @source = source
28
+ @stylesheet = stylesheet.freeze
29
+ @warnings = warnings.freeze
30
+
31
+ freeze
32
+ end
33
+
34
+ #: () -> LightningCSS::Node
35
+ def root
36
+ Node.new(stylesheet)
37
+ end
38
+
39
+ #: () -> bool
40
+ def warnings?
41
+ !warnings.empty?
42
+ end
43
+
44
+ #: () -> String
45
+ def inspect
46
+ parts = ["rules=#{stylesheet.fetch("rules").length}"]
47
+ parts << "warnings=#{warnings.inspect}" if warnings?
48
+
49
+ "#<#{self.class.name} #{parts.join(" ")}>"
50
+ end
51
+ end
52
+ end
@@ -28,6 +28,11 @@ module LightningCSS
28
28
 
29
29
  alias call transform
30
30
 
31
+ #: (String, ?filename: String?, ?error_recovery: bool) -> LightningCSS::ParseResult
32
+ def parse(code, **overrides)
33
+ LightningCSS.parse(code, **options.slice(*Options::PARSE), **overrides)
34
+ end
35
+
31
36
  #: (String, ?minify: bool, ?error_recovery: bool, ?targets: browsers?, ?css_modules: css_modules?, ?scope: String?) -> LightningCSS::Result
32
37
  def bundle(path, **overrides)
33
38
  LightningCSS.bundle(path, **options, **overrides)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module LightningCSS
4
- VERSION = "0.2.0"
4
+ VERSION = "1.33.0.1"
5
5
  end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LightningCSS
4
+ # Walks an AST, answering each node with the method named after it and walking through anything
5
+ # nothing answers.
6
+ #
7
+ # class Colors < LightningCSS::Visitor
8
+ # def visit_declaration(node)
9
+ # puts node.value.type if node.property == "color"
10
+ # end
11
+ # end
12
+ #
13
+ # Colors.new.visit(LightningCSS.parse(".a { color: red }"))
14
+ #
15
+ # A rule is answered as one, as in `visit_style_rule` or `visit_media_rule`, since `style`,
16
+ # `nesting`, and `namespace` are also what a selector is made of.
17
+ #
18
+ class Visitor
19
+ #: (LightningCSS::Node | LightningCSS::ParseResult) -> void
20
+ def visit(node)
21
+ node = node.root if node.is_a?(ParseResult)
22
+
23
+ method_name = "visit_#{node.underscored_type}" if node.underscored_type
24
+
25
+ method_name && respond_to?(method_name) ? public_send(method_name, node) : visit_children(node)
26
+
27
+ nil
28
+ end
29
+
30
+ #: (LightningCSS::Node) -> void
31
+ def visit_children(node)
32
+ node.child_nodes.each { |child| visit(child) }
33
+
34
+ nil
35
+ end
36
+ end
37
+ end
data/lib/lightningcss.rb CHANGED
@@ -15,6 +15,9 @@ end
15
15
 
16
16
  require_relative "lightningcss/options"
17
17
  require_relative "lightningcss/result"
18
+ require_relative "lightningcss/node"
19
+ require_relative "lightningcss/parse_result"
20
+ require_relative "lightningcss/visitor"
18
21
  require_relative "lightningcss/transformer"
19
22
 
20
23
  # Ruby bindings for Lightning CSS.
@@ -28,14 +31,27 @@ require_relative "lightningcss/transformer"
28
31
  # LightningCSS.transform(".title { color: red }", scope: "[data-scope-abc]").code
29
32
  # #=> ".title[data-scope-abc]{color:red}"
30
33
  #
34
+ # `parse` returns the AST instead, to walk with `LightningCSS::Node` and `LightningCSS::Visitor`:
35
+ #
36
+ # LightningCSS.parse(".a { color: red }").root.every("declaration").first.property
37
+ # #=> "color"
38
+ #
31
39
  # `LightningCSS::Options` is what the options are read by, and `LightningCSS::Transformer` holds a
32
40
  # set of them to reuse across many stylesheets.
41
+ #
33
42
  module LightningCSS
34
43
  #: (String, ?filename: String?, ?minify: bool, ?error_recovery: bool, ?targets: browsers?, ?css_modules: css_modules?, ?scope: String?) -> LightningCSS::Result
35
44
  def self.transform(code, **options)
36
45
  Result.from_json(Backend.transform(code.to_s, Options.serialize(options)))
37
46
  end
38
47
 
48
+ #: (String, ?filename: String?, ?error_recovery: bool) -> LightningCSS::ParseResult
49
+ def self.parse(code, **options)
50
+ serialized = Options.serialize(options, Options::PARSE, "a parse")
51
+
52
+ ParseResult.from_json(Backend.parse(code.to_s, serialized), code.to_s)
53
+ end
54
+
39
55
  #: (String, ?minify: bool, ?error_recovery: bool, ?targets: browsers?, ?css_modules: css_modules?, ?scope: String?) -> LightningCSS::Result
40
56
  def self.bundle(path, **options)
41
57
  serialized = Options.serialize(options, Options::BUNDLE, "a bundle")
data/rust/Cargo.lock CHANGED
@@ -90,6 +90,9 @@ name = "bitflags"
90
90
  version = "2.13.1"
91
91
  source = "registry+https://github.com/rust-lang/crates.io-index"
92
92
  checksum = "b588b76d00fde79687d7646a9b5bdf3cc0f655e0bbd080335a95d7e96f3587da"
93
+ dependencies = [
94
+ "serde_core",
95
+ ]
93
96
 
94
97
  [[package]]
95
98
  name = "bitvec"
@@ -139,9 +142,9 @@ checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04"
139
142
 
140
143
  [[package]]
141
144
  name = "cbindgen"
142
- version = "0.28.0"
145
+ version = "0.29.4"
143
146
  source = "registry+https://github.com/rust-lang/crates.io-index"
144
- checksum = "eadd868a2ce9ca38de7eeafdcec9c7065ef89b42b32f0839278d55f35c54d1ff"
147
+ checksum = "2ecb53484c9c167ba674026b656d8a27d7657a58e6066aa902bfb1a4aa00ae20"
145
148
  dependencies = [
146
149
  "clap",
147
150
  "heck",
@@ -245,6 +248,7 @@ dependencies = [
245
248
  "dtoa-short",
246
249
  "itoa",
247
250
  "phf 0.13.1",
251
+ "serde",
248
252
  "smallvec",
249
253
  ]
250
254
 
@@ -425,9 +429,9 @@ checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a"
425
429
 
426
430
  [[package]]
427
431
  name = "heck"
428
- version = "0.4.1"
432
+ version = "0.5.0"
429
433
  source = "registry+https://github.com/rust-lang/crates.io-index"
430
- checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
434
+ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
431
435
 
432
436
  [[package]]
433
437
  name = "indexmap"
@@ -511,6 +515,7 @@ dependencies = [
511
515
  "serde",
512
516
  "serde-content",
513
517
  "smallvec",
518
+ "static-self",
514
519
  ]
515
520
 
516
521
  [[package]]
@@ -527,7 +532,7 @@ dependencies = [
527
532
 
528
533
  [[package]]
529
534
  name = "lightningcss-ffi"
530
- version = "0.2.0"
535
+ version = "0.0.0"
531
536
  dependencies = [
532
537
  "cbindgen",
533
538
  "lightningcss",
@@ -599,7 +604,9 @@ dependencies = [
599
604
  "phf_codegen",
600
605
  "precomputed-hash",
601
606
  "rustc-hash",
607
+ "serde",
602
608
  "smallvec",
609
+ "static-self",
603
610
  ]
604
611
 
605
612
  [[package]]
@@ -963,11 +970,11 @@ dependencies = [
963
970
 
964
971
  [[package]]
965
972
  name = "serde_spanned"
966
- version = "0.6.9"
973
+ version = "1.1.1"
967
974
  source = "registry+https://github.com/rust-lang/crates.io-index"
968
- checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3"
975
+ checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26"
969
976
  dependencies = [
970
- "serde",
977
+ "serde_core",
971
978
  ]
972
979
 
973
980
  [[package]]
@@ -1002,6 +1009,31 @@ name = "smallvec"
1002
1009
  version = "1.15.2"
1003
1010
  source = "registry+https://github.com/rust-lang/crates.io-index"
1004
1011
  checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90"
1012
+ dependencies = [
1013
+ "serde",
1014
+ ]
1015
+
1016
+ [[package]]
1017
+ name = "static-self"
1018
+ version = "0.1.2"
1019
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1020
+ checksum = "f6635404b73efc136af3a7956e53c53d4f34b2f16c95a15c438929add0f69412"
1021
+ dependencies = [
1022
+ "indexmap",
1023
+ "smallvec",
1024
+ "static-self-derive",
1025
+ ]
1026
+
1027
+ [[package]]
1028
+ name = "static-self-derive"
1029
+ version = "0.1.1"
1030
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1031
+ checksum = "5268c96d4b907c558a9a52d8492522d6c7b559651a5e1d8f2d551e461b9425d5"
1032
+ dependencies = [
1033
+ "proc-macro2",
1034
+ "quote",
1035
+ "syn 1.0.109",
1036
+ ]
1005
1037
 
1006
1038
  [[package]]
1007
1039
  name = "strsim"
@@ -1078,44 +1110,42 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
1078
1110
 
1079
1111
  [[package]]
1080
1112
  name = "toml"
1081
- version = "0.8.23"
1113
+ version = "0.9.12+spec-1.1.0"
1082
1114
  source = "registry+https://github.com/rust-lang/crates.io-index"
1083
- checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362"
1115
+ checksum = "cf92845e79fc2e2def6a5d828f0801e29a2f8acc037becc5ab08595c7d5e9863"
1084
1116
  dependencies = [
1085
- "serde",
1117
+ "indexmap",
1118
+ "serde_core",
1086
1119
  "serde_spanned",
1087
1120
  "toml_datetime",
1088
- "toml_edit",
1121
+ "toml_parser",
1122
+ "toml_writer",
1123
+ "winnow 0.7.15",
1089
1124
  ]
1090
1125
 
1091
1126
  [[package]]
1092
1127
  name = "toml_datetime"
1093
- version = "0.6.11"
1128
+ version = "0.7.5+spec-1.1.0"
1094
1129
  source = "registry+https://github.com/rust-lang/crates.io-index"
1095
- checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c"
1130
+ checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347"
1096
1131
  dependencies = [
1097
- "serde",
1132
+ "serde_core",
1098
1133
  ]
1099
1134
 
1100
1135
  [[package]]
1101
- name = "toml_edit"
1102
- version = "0.22.27"
1136
+ name = "toml_parser"
1137
+ version = "1.1.3+spec-1.1.0"
1103
1138
  source = "registry+https://github.com/rust-lang/crates.io-index"
1104
- checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a"
1139
+ checksum = "1d38ac1cf9b95face32296c0a3ede1fdc270627c9d9c02a7274dd6d960dc4d56"
1105
1140
  dependencies = [
1106
- "indexmap",
1107
- "serde",
1108
- "serde_spanned",
1109
- "toml_datetime",
1110
- "toml_write",
1111
- "winnow",
1141
+ "winnow 1.0.4",
1112
1142
  ]
1113
1143
 
1114
1144
  [[package]]
1115
- name = "toml_write"
1116
- version = "0.1.2"
1145
+ name = "toml_writer"
1146
+ version = "1.1.2+spec-1.1.0"
1117
1147
  source = "registry+https://github.com/rust-lang/crates.io-index"
1118
- checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801"
1148
+ checksum = "7d56353a2a665ad0f41a421187180aab746c8c325620617ad883a99a1cbe66d2"
1119
1149
 
1120
1150
  [[package]]
1121
1151
  name = "unicode-ident"
@@ -1237,9 +1267,12 @@ name = "winnow"
1237
1267
  version = "0.7.15"
1238
1268
  source = "registry+https://github.com/rust-lang/crates.io-index"
1239
1269
  checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945"
1240
- dependencies = [
1241
- "memchr",
1242
- ]
1270
+
1271
+ [[package]]
1272
+ name = "winnow"
1273
+ version = "1.0.4"
1274
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1275
+ checksum = "23b97319f7b8343df12cc98938e5c3eb436064524c8d2b4e30a1d3a36eecdf81"
1243
1276
 
1244
1277
  [[package]]
1245
1278
  name = "wit-bindgen"
data/rust/Cargo.toml CHANGED
@@ -2,7 +2,6 @@
2
2
 
3
3
  [package]
4
4
  name = "lightningcss-ffi"
5
- version = "0.2.0"
6
5
  edition = "2021"
7
6
  authors = ["Marco Roth <marco.roth@intergga.ch>"]
8
7
  description = "C FFI bindings for Lightning CSS, used by the lightningcss gem"
@@ -16,9 +15,9 @@ path = "src/lib.rs"
16
15
  crate-type = ["cdylib", "staticlib", "rlib"]
17
16
 
18
17
  [dependencies]
19
- lightningcss = { version = "1.0.0-alpha.68", features = ["visitor"] }
18
+ lightningcss = { version = "=1.0.0-alpha.72", features = ["visitor", "serde"] }
20
19
  serde = { version = "1", features = ["derive"] }
21
20
  serde_json = "1"
22
21
 
23
22
  [build-dependencies]
24
- cbindgen = "0.28"
23
+ cbindgen = "0.29"
data/rust/build.rs CHANGED
@@ -28,10 +28,32 @@ fn main() {
28
28
  PathBuf::from(&crate_dir).join("cbindgen.toml").display()
29
29
  );
30
30
 
31
+ let version_rb_path = PathBuf::from(&crate_dir).join("../lib/lightningcss/version.rb");
32
+
33
+ println!("cargo:rerun-if-changed={}", version_rb_path.display());
34
+
31
35
  println!(
32
36
  "cargo:rustc-env=LIGHTNINGCSS_VERSION={}",
33
37
  locked_version(&lock_path, "lightningcss")
34
38
  );
39
+
40
+ println!("cargo:rustc-env=GEM_VERSION={}", gem_version(&version_rb_path));
41
+ }
42
+
43
+ fn gem_version(version_rb_path: &PathBuf) -> String {
44
+ let Ok(source) = fs::read_to_string(version_rb_path) else {
45
+ return "unknown".to_string();
46
+ };
47
+
48
+ for line in source.lines() {
49
+ let Some(rest) = line.trim().strip_prefix("VERSION = ") else {
50
+ continue;
51
+ };
52
+
53
+ return rest.trim().trim_matches('"').to_string();
54
+ }
55
+
56
+ "unknown".to_string()
35
57
  }
36
58
 
37
59
  fn locked_version(lock_path: &PathBuf, package: &str) -> String {
data/rust/src/lib.rs CHANGED
@@ -21,10 +21,10 @@ use lightningcss::bundler::{BundleErrorKind, Bundler, FileProvider};
21
21
  use lightningcss::stylesheet::{MinifyOptions, ParserOptions, PrinterOptions, StyleAttribute, StyleSheet};
22
22
  use lightningcss::visitor::Visit;
23
23
 
24
- use crate::options::{TransformOptions, TransformResult};
24
+ use crate::options::{ParseResult, TransformOptions, TransformResult};
25
25
  use crate::scope::Scoper;
26
26
 
27
- pub const VERSION: &str = env!("CARGO_PKG_VERSION");
27
+ pub const VERSION: &str = env!("GEM_VERSION");
28
28
  pub const LIGHTNINGCSS_VERSION: &str = env!("LIGHTNINGCSS_VERSION");
29
29
 
30
30
  #[repr(C)]
@@ -125,6 +125,26 @@ unsafe fn borrow_options(pointer: *const c_char) -> Result<TransformOptions, Fai
125
125
  serde_json::from_str(json).map_err(|error| Failure::option(format!("Invalid options: {error}")))
126
126
  }
127
127
 
128
+ fn parse_source<'i>(code: &'i str, options: &TransformOptions) -> Result<ParseResult<StyleSheet<'i>>, Failure> {
129
+ let collected = Arc::new(RwLock::new(Vec::new()));
130
+
131
+ let parser_options = ParserOptions {
132
+ filename: options.filename.clone().unwrap_or_default(),
133
+ error_recovery: options.error_recovery,
134
+ warnings: Some(collected.clone()),
135
+ ..ParserOptions::default()
136
+ };
137
+
138
+ let stylesheet = StyleSheet::parse(code, parser_options).map_err(|error| Failure::parse(error.to_string()))?;
139
+
140
+ let warnings = collected
141
+ .read()
142
+ .map(|warnings| warnings.iter().map(|warning| warning.to_string()).collect())
143
+ .unwrap_or_default();
144
+
145
+ Ok(ParseResult { stylesheet, warnings })
146
+ }
147
+
128
148
  fn transform_source(code: &str, options: &TransformOptions) -> Result<TransformResult, Failure> {
129
149
  let filename = options.filename.clone().unwrap_or_default();
130
150
  let css_modules = match &options.css_modules {
@@ -295,7 +315,7 @@ fn transform_attribute(code: &str, options: &TransformOptions) -> Result<Transfo
295
315
  })
296
316
  }
297
317
 
298
- fn to_result(outcome: Result<TransformResult, Failure>) -> LightningCssResult {
318
+ fn to_result(outcome: Result<impl serde::Serialize, Failure>) -> LightningCssResult {
299
319
  match outcome {
300
320
  Ok(result) => match serde_json::to_string(&result) {
301
321
  Ok(json) => LightningCssResult::ok(json),
@@ -323,6 +343,21 @@ pub unsafe extern "C" fn lightningcss_transform(
323
343
  to_result(transform_source(code, &options))
324
344
  }
325
345
 
346
+ #[no_mangle]
347
+ pub unsafe extern "C" fn lightningcss_parse(code: *const c_char, options_json: *const c_char) -> LightningCssResult {
348
+ let code = match borrow_str(code, "code") {
349
+ Ok(code) => code,
350
+ Err(failure) => return LightningCssResult::err(failure),
351
+ };
352
+
353
+ let options = match borrow_options(options_json) {
354
+ Ok(options) => options,
355
+ Err(failure) => return LightningCssResult::err(failure),
356
+ };
357
+
358
+ to_result(parse_source(code, &options))
359
+ }
360
+
326
361
  #[no_mangle]
327
362
  pub unsafe extern "C" fn lightningcss_transform_style_attribute(
328
363
  code: *const c_char,
data/rust/src/options.rs CHANGED
@@ -89,6 +89,12 @@ impl TransformOptions {
89
89
  }
90
90
  }
91
91
 
92
+ #[derive(Debug, Serialize)]
93
+ pub struct ParseResult<T> {
94
+ pub stylesheet: T,
95
+ pub warnings: Vec<String>,
96
+ }
97
+
92
98
  #[derive(Debug, Serialize)]
93
99
  pub struct TransformResult {
94
100
  pub code: String,
@@ -6,6 +6,9 @@ module LightningCSS
6
6
  # : (String, String) -> String
7
7
  def transform: (String, String) -> String
8
8
 
9
+ # : (String, String) -> String
10
+ def parse: (String, String) -> String
11
+
9
12
  # : (String, String) -> String
10
13
  def transform_style_attribute: (String, String) -> String
11
14
 
@@ -0,0 +1,104 @@
1
+ # Generated from lib/lightningcss/node.rb with RBS::Inline
2
+
3
+ module LightningCSS
4
+ # One object in the AST Lightning CSS parsed a stylesheet to.
5
+ #
6
+ # root = LightningCSS.parse(".a { color: red }").root
7
+ #
8
+ # root.type #=> "stylesheet"
9
+ # root.every("declaration") #=> every declaration in the stylesheet
10
+ # root.rules.first.value.location #=> {"source_index" => 0, "line" => 0, "column" => 1}
11
+ #
12
+ # Every object in the tree is a node, so reads chain all the way down. Most say what they are
13
+ # with their own `type`. The stylesheet, a declaration block, and a declaration do not, so a node
14
+ # names those from where it sits.
15
+ class Node
16
+ include Enumerable[LightningCSS::Node]
17
+
18
+ POSITION: Array[String]
19
+
20
+ DECLARATIONS: Array[String]
21
+
22
+ attr_reader parent: LightningCSS::Node?
23
+
24
+ attr_reader field: String?
25
+
26
+ # : (Hash[String, untyped], ?LightningCSS::Node?, ?String?) -> void
27
+ def initialize: (Hash[String, untyped], ?LightningCSS::Node?, ?String?) -> void
28
+
29
+ # : () -> String?
30
+ def type: () -> String?
31
+
32
+ # : () -> String?
33
+ def underscored_type: () -> String?
34
+
35
+ # : () -> bool
36
+ def rule?: () -> bool
37
+
38
+ # : () -> Hash[String, Integer]?
39
+ def location: () -> Hash[String, Integer]?
40
+
41
+ # : (String) -> untyped
42
+ def []: (String) -> untyped
43
+
44
+ # : () -> Array[String]
45
+ def keys: () -> Array[String]
46
+
47
+ # : () -> Hash[String, untyped]
48
+ def to_h: () -> Hash[String, untyped]
49
+
50
+ # : (?untyped) -> String
51
+ def to_json: (?untyped) -> String
52
+
53
+ # : (Array[Symbol]?) -> Hash[Symbol, untyped]
54
+ def deconstruct_keys: (Array[Symbol]?) -> Hash[Symbol, untyped]
55
+
56
+ # : () -> Array[LightningCSS::Node]
57
+ def child_nodes: () -> Array[LightningCSS::Node]
58
+
59
+ # : () { (LightningCSS::Node) -> void } -> void
60
+ # : () -> Enumerator[LightningCSS::Node, void]
61
+ def each: () { (LightningCSS::Node) -> void } -> void
62
+ | () -> Enumerator[LightningCSS::Node, void]
63
+
64
+ # : () -> Array[LightningCSS::Node]
65
+ def ancestors: () -> Array[LightningCSS::Node]
66
+
67
+ # : (String) -> Array[LightningCSS::Node]
68
+ def every: (String) -> Array[LightningCSS::Node]
69
+
70
+ # : () -> Hash[String, untyped]
71
+ def fields: () -> Hash[String, untyped]
72
+
73
+ # : () -> String
74
+ def inspect: () -> String
75
+
76
+ # : (Symbol, *untyped) -> untyped
77
+ def method_missing: (Symbol, *untyped) -> untyped
78
+
79
+ # : (Symbol, ?bool) -> bool
80
+ def respond_to_missing?: (Symbol, ?bool) -> bool
81
+
82
+ attr_reader attributes: Hash[String, untyped]
83
+
84
+ private
85
+
86
+ # : () -> String?
87
+ def inferred_type: () -> String?
88
+
89
+ # : (untyped, String) -> Array[LightningCSS::Node]
90
+ def nodes_in: (untyped, String) -> Array[LightningCSS::Node]
91
+
92
+ # : (String, untyped) -> String
93
+ def described_field: (String, untyped) -> String
94
+
95
+ # : (Array[untyped]) -> String
96
+ def counted: (Array[untyped]) -> String
97
+
98
+ # : (String) -> String?
99
+ def field_for: (String) -> String?
100
+
101
+ # : (untyped, String) -> untyped
102
+ def wrap: (untyped, String) -> untyped
103
+ end
104
+ end
@@ -13,6 +13,8 @@ module LightningCSS
13
13
 
14
14
  STYLE_ATTRIBUTE: Array[Symbol]
15
15
 
16
+ PARSE: Array[Symbol]
17
+
16
18
  BUNDLE: Array[Symbol]
17
19
 
18
20
  attr_reader to_h: Hash[Symbol, untyped]
@@ -0,0 +1,30 @@
1
+ # Generated from lib/lightningcss/parse_result.rb with RBS::Inline
2
+
3
+ module LightningCSS
4
+ # What a stylesheet parsed to.
5
+ #
6
+ # `stylesheet` is the AST exactly as Lightning CSS serializes it, and `root` is the same tree as a
7
+ # `LightningCSS::Node` to walk. `warnings` are the ones a transform would have reported.
8
+ class ParseResult
9
+ attr_reader source: String?
10
+
11
+ attr_reader stylesheet: Hash[String, untyped]
12
+
13
+ attr_reader warnings: Array[String]
14
+
15
+ # : (String, ?String?) -> LightningCSS::ParseResult
16
+ def self.from_json: (String, ?String?) -> LightningCSS::ParseResult
17
+
18
+ # : (stylesheet: Hash[String, untyped], warnings: Array[String], ?source: String?) -> void
19
+ def initialize: (stylesheet: Hash[String, untyped], warnings: Array[String], ?source: String?) -> void
20
+
21
+ # : () -> LightningCSS::Node
22
+ def root: () -> LightningCSS::Node
23
+
24
+ # : () -> bool
25
+ def warnings?: () -> bool
26
+
27
+ # : () -> String
28
+ def inspect: () -> String
29
+ end
30
+ end
@@ -21,6 +21,9 @@ module LightningCSS
21
21
 
22
22
  alias call transform
23
23
 
24
+ # : (String, ?filename: String?, ?error_recovery: bool) -> LightningCSS::ParseResult
25
+ def parse: (String, ?filename: String?, ?error_recovery: bool) -> LightningCSS::ParseResult
26
+
24
27
  # : (String, ?minify: bool, ?error_recovery: bool, ?targets: browsers?, ?css_modules: css_modules?, ?scope: String?) -> LightningCSS::Result
25
28
  def bundle: (String, ?minify: bool, ?error_recovery: bool, ?targets: browsers?, ?css_modules: css_modules?, ?scope: String?) -> LightningCSS::Result
26
29
 
@@ -0,0 +1,24 @@
1
+ # Generated from lib/lightningcss/visitor.rb with RBS::Inline
2
+
3
+ module LightningCSS
4
+ # Walks an AST, answering each node with the method named after it and walking through anything
5
+ # nothing answers.
6
+ #
7
+ # class Colors < LightningCSS::Visitor
8
+ # def visit_declaration(node)
9
+ # puts node.value.type if node.property == "color"
10
+ # end
11
+ # end
12
+ #
13
+ # Colors.new.visit(LightningCSS.parse(".a { color: red }"))
14
+ #
15
+ # A rule is answered as one, as in `visit_style_rule` or `visit_media_rule`, since `style`,
16
+ # `nesting`, and `namespace` are also what a selector is made of.
17
+ class Visitor
18
+ # : (LightningCSS::Node | LightningCSS::ParseResult) -> void
19
+ def visit: (LightningCSS::Node | LightningCSS::ParseResult) -> void
20
+
21
+ # : (LightningCSS::Node) -> void
22
+ def visit_children: (LightningCSS::Node) -> void
23
+ end
24
+ end
data/sig/lightningcss.rbs CHANGED
@@ -11,12 +11,20 @@
11
11
  # LightningCSS.transform(".title { color: red }", scope: "[data-scope-abc]").code
12
12
  # #=> ".title[data-scope-abc]{color:red}"
13
13
  #
14
+ # `parse` returns the AST instead, to walk with `LightningCSS::Node` and `LightningCSS::Visitor`:
15
+ #
16
+ # LightningCSS.parse(".a { color: red }").root.every("declaration").first.property
17
+ # #=> "color"
18
+ #
14
19
  # `LightningCSS::Options` is what the options are read by, and `LightningCSS::Transformer` holds a
15
20
  # set of them to reuse across many stylesheets.
16
21
  module LightningCSS
17
22
  # : (String, ?filename: String?, ?minify: bool, ?error_recovery: bool, ?targets: browsers?, ?css_modules: css_modules?, ?scope: String?) -> LightningCSS::Result
18
23
  def self.transform: (String, ?filename: String?, ?minify: bool, ?error_recovery: bool, ?targets: browsers?, ?css_modules: css_modules?, ?scope: String?) -> LightningCSS::Result
19
24
 
25
+ # : (String, ?filename: String?, ?error_recovery: bool) -> LightningCSS::ParseResult
26
+ def self.parse: (String, ?filename: String?, ?error_recovery: bool) -> LightningCSS::ParseResult
27
+
20
28
  # : (String, ?minify: bool, ?error_recovery: bool, ?targets: browsers?, ?css_modules: css_modules?, ?scope: String?) -> LightningCSS::Result
21
29
  def self.bundle: (String, ?minify: bool, ?error_recovery: bool, ?targets: browsers?, ?css_modules: css_modules?, ?scope: String?) -> LightningCSS::Result
22
30
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lightningcss
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 1.33.0.1
5
5
  platform: x86_64-linux-gnu
6
6
  authors:
7
7
  - Marco Roth
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-08-30 00:00:00.000000000 Z
11
+ date: 2026-10-13 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Ruby bindings for Lightning CSS, an extremely fast CSS parser, transformer,
14
14
  bundler, and minifier.
@@ -30,10 +30,13 @@ files:
30
30
  - lib/lightningcss/4.0/lightningcss.so
31
31
  - lib/lightningcss/backend.rb
32
32
  - lib/lightningcss/errors.rb
33
+ - lib/lightningcss/node.rb
33
34
  - lib/lightningcss/options.rb
35
+ - lib/lightningcss/parse_result.rb
34
36
  - lib/lightningcss/result.rb
35
37
  - lib/lightningcss/transformer.rb
36
38
  - lib/lightningcss/version.rb
39
+ - lib/lightningcss/visitor.rb
37
40
  - licenses/README.md
38
41
  - licenses/lightningcss-MPL-2.0.txt
39
42
  - lightningcss.gemspec
@@ -48,11 +51,14 @@ files:
48
51
  - sig/lightningcss.rbs
49
52
  - sig/lightningcss/backend.rbs
50
53
  - sig/lightningcss/errors.rbs
54
+ - sig/lightningcss/node.rbs
51
55
  - sig/lightningcss/options.rbs
56
+ - sig/lightningcss/parse_result.rbs
52
57
  - sig/lightningcss/result.rbs
53
58
  - sig/lightningcss/transformer.rbs
54
59
  - sig/lightningcss/types.rbs
55
60
  - sig/lightningcss/version.rbs
61
+ - sig/lightningcss/visitor.rbs
56
62
  homepage: https://github.com/marcoroth/lightningcss-ruby
57
63
  licenses:
58
64
  - MIT