lightningcss 1.33.0 → 1.33.0.1
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 +4 -4
- data/README.md +109 -0
- data/ext/lightningcss/include/lightningcss.h +2 -0
- data/ext/lightningcss/lightningcss.c +7 -0
- data/lib/lightningcss/backend.rb +5 -0
- data/lib/lightningcss/node.rb +220 -0
- data/lib/lightningcss/options.rb +5 -0
- data/lib/lightningcss/parse_result.rb +52 -0
- data/lib/lightningcss/transformer.rb +5 -0
- data/lib/lightningcss/version.rb +1 -1
- data/lib/lightningcss/visitor.rb +37 -0
- data/lib/lightningcss.rb +16 -0
- data/rust/Cargo.lock +32 -0
- data/rust/Cargo.toml +1 -1
- data/rust/src/lib.rs +37 -2
- data/rust/src/options.rs +6 -0
- data/sig/lightningcss/backend.rbs +3 -0
- data/sig/lightningcss/node.rbs +104 -0
- data/sig/lightningcss/options.rbs +2 -0
- data/sig/lightningcss/parse_result.rbs +30 -0
- data/sig/lightningcss/transformer.rbs +3 -0
- data/sig/lightningcss/visitor.rbs +24 -0
- data/sig/lightningcss.rbs +8 -0
- metadata +7 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7b5579e4627956aba7821a46282bf3ee3bb2a3267c9c83932fd4a95633c44172
|
|
4
|
+
data.tar.gz: 9fc12ae254f802644a823671c253dbd6db169f5eb574a438b4a697c71b33e0be
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8aefa9384d3a4f5086869d5aa3aa4b7f5f0c7b99e0840fdfb1f076d7c129432de5ca145bf65e9af68cb71104d2ff5f7235dbfbb3fc68d7576702a6f1f154bca2
|
|
7
|
+
data.tar.gz: 60b8b2520cb4e0244ce8c0d5d72ad98d2fa81f1fa6fc5753a511e7850c2c45e030d90267a4acde99abce70bfb5ad662688023e431e9c22fab2617157dd2f1248
|
data/README.md
CHANGED
|
@@ -141,6 +141,113 @@ LightningCSS.transform_style_attribute("color: #ff0000; border: none", minify: t
|
|
|
141
141
|
|
|
142
142
|
Having no selectors and no names, it takes neither `scope` nor `css_modules`, and says so when given one.
|
|
143
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
|
+
|
|
144
251
|
#### Reusing options
|
|
145
252
|
|
|
146
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.
|
|
@@ -155,6 +262,8 @@ transformer.with(scope: "[s]")
|
|
|
155
262
|
|
|
156
263
|
It answers `call` as well, so it can be handed to anything expecting something callable.
|
|
157
264
|
|
|
265
|
+
`transformer.parse` reads with the `filename` and `error_recovery` it holds and leaves the rest, which only matter to printing.
|
|
266
|
+
|
|
158
267
|
### Options
|
|
159
268
|
|
|
160
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);
|
data/lib/lightningcss/backend.rb
CHANGED
|
@@ -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
|
data/lib/lightningcss/options.rb
CHANGED
|
@@ -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)
|
data/lib/lightningcss/version.rb
CHANGED
|
@@ -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"
|
|
@@ -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
|
|
|
@@ -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]]
|
|
@@ -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]]
|
|
@@ -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"
|
data/rust/Cargo.toml
CHANGED
|
@@ -15,7 +15,7 @@ path = "src/lib.rs"
|
|
|
15
15
|
crate-type = ["cdylib", "staticlib", "rlib"]
|
|
16
16
|
|
|
17
17
|
[dependencies]
|
|
18
|
-
lightningcss = { version = "=1.0.0-alpha.72", features = ["visitor"] }
|
|
18
|
+
lightningcss = { version = "=1.0.0-alpha.72", features = ["visitor", "serde"] }
|
|
19
19
|
serde = { version = "1", features = ["derive"] }
|
|
20
20
|
serde_json = "1"
|
|
21
21
|
|
data/rust/src/lib.rs
CHANGED
|
@@ -21,7 +21,7 @@ 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
27
|
pub const VERSION: &str = env!("GEM_VERSION");
|
|
@@ -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<
|
|
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
|
@@ -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
|
|
@@ -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,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: lightningcss
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.33.0
|
|
4
|
+
version: 1.33.0.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Marco Roth
|
|
@@ -26,10 +26,13 @@ files:
|
|
|
26
26
|
- lib/lightningcss.rb
|
|
27
27
|
- lib/lightningcss/backend.rb
|
|
28
28
|
- lib/lightningcss/errors.rb
|
|
29
|
+
- lib/lightningcss/node.rb
|
|
29
30
|
- lib/lightningcss/options.rb
|
|
31
|
+
- lib/lightningcss/parse_result.rb
|
|
30
32
|
- lib/lightningcss/result.rb
|
|
31
33
|
- lib/lightningcss/transformer.rb
|
|
32
34
|
- lib/lightningcss/version.rb
|
|
35
|
+
- lib/lightningcss/visitor.rb
|
|
33
36
|
- licenses/README.md
|
|
34
37
|
- licenses/lightningcss-MPL-2.0.txt
|
|
35
38
|
- lightningcss.gemspec
|
|
@@ -44,11 +47,14 @@ files:
|
|
|
44
47
|
- sig/lightningcss.rbs
|
|
45
48
|
- sig/lightningcss/backend.rbs
|
|
46
49
|
- sig/lightningcss/errors.rbs
|
|
50
|
+
- sig/lightningcss/node.rbs
|
|
47
51
|
- sig/lightningcss/options.rbs
|
|
52
|
+
- sig/lightningcss/parse_result.rbs
|
|
48
53
|
- sig/lightningcss/result.rbs
|
|
49
54
|
- sig/lightningcss/transformer.rbs
|
|
50
55
|
- sig/lightningcss/types.rbs
|
|
51
56
|
- sig/lightningcss/version.rbs
|
|
57
|
+
- sig/lightningcss/visitor.rbs
|
|
52
58
|
homepage: https://github.com/marcoroth/lightningcss-ruby
|
|
53
59
|
licenses:
|
|
54
60
|
- MIT
|