Skip to content

Commit

Permalink
Move methods intended for public use one Crass
Browse files Browse the repository at this point in the history
  • Loading branch information
stoivo committed May 22, 2024
1 parent 91fe420 commit 6a71dd7
Show file tree
Hide file tree
Showing 9 changed files with 104 additions and 126 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ This returns a big beautiful parse tree, which looks like this:
If you want, you can stringify the parse tree:

```ruby
css = Crass::Parser.stringify(tree)
css = Crass.stringify(tree)
```

...which gives you back exactly what you put in!
Expand Down
94 changes: 92 additions & 2 deletions lib/crass.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,105 @@ module Crass
#
# See {Tokenizer#initialize} for _options_.
def self.parse(input, options = {})
Parser.parse_stylesheet(input, options)
parse_stylesheet(input, options)
end

# Parses _input_ as a string of CSS properties (such as the contents of an
# HTML element's `style` attribute) and returns a parse tree.
#
# See {Tokenizer#initialize} for _options_.
#
# 5.3.6. http://dev.w3.org/csswg/css-syntax/#parse-a-list-of-declarations
def self.parse_properties(input, options = {})
Parser.parse_properties(input, options)
Parser.new(input, options).parse_properties
end

# Parses CSS rules (such as the content of a `@media` block) and returns a
# parse tree. The only difference from {parse_stylesheet} is that CDO/CDC
# nodes (`<!--` and `-->`) aren't ignored.
#
# See {Tokenizer#initialize} for _options_.
#
# 5.3.3. https://dev.w3.org/csswg/css-syntax/#parse-a-list-of-rules
def self.parse_rules(input, options = {})
parser = Parser.new(input, options)
rules = parser.consume_rules

rules.map do |rule|
if rule[:node] == :qualified_rule
parser.create_style_rule(rule)
else
rule
end
end
end

# Parses a CSS stylesheet and returns a parse tree.
#
# See {Tokenizer#initialize} for _options_.
#
# 5.3.2. http://dev.w3.org/csswg/css-syntax/#parse-a-stylesheet
def self.parse_stylesheet(input, options = {})
parser = Parser.new(input, options)
rules = parser.consume_rules(:top_level => true)

rules.map do |rule|
if rule[:node] == :qualified_rule
parser.create_style_rule(rule)
else
rule
end
end
end

# Converts a node or array of nodes into a CSS string based on their
# original tokenized input.
#
# Options:
#
# * **:exclude_comments** - When `true`, comments will be excluded.
#
def self.stringify(nodes, options = {})
nodes = [nodes] unless nodes.is_a?(Array)
string = String.new

nodes.each do |node|
next if node.nil?

case node[:node]
when :at_rule
string << '@'
string << node[:name]
string << self.stringify(node[:prelude], options)

if node[:block]
string << '{' << self.stringify(node[:block], options) << '}'
else
string << ';'
end

when :comment
string << node[:raw] unless options[:exclude_comments]

when :simple_block
string << node[:start]
string << self.stringify(node[:value], options)
string << node[:end]

when :style_rule
string << self.stringify(node[:selector][:tokens], options)
string << '{' << self.stringify(node[:children], options) << '}'

else
if node.key?(:raw)
string << node[:raw]
elsif node.key?(:tokens)
string << self.stringify(node[:tokens], options)
end
end
end

string
end

end
100 changes: 0 additions & 100 deletions lib/crass/parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,106 +14,6 @@ class Parser
:'(' => :')'
}

# -- Class Methods ---------------------------------------------------------

# Parses CSS properties (such as the contents of an HTML element's `style`
# attribute) and returns a parse tree.
#
# See {Tokenizer#initialize} for _options_.
#
# 5.3.6. http://dev.w3.org/csswg/css-syntax/#parse-a-list-of-declarations
def self.parse_properties(input, options = {})
Parser.new(input, options).parse_properties
end

# Parses CSS rules (such as the content of a `@media` block) and returns a
# parse tree. The only difference from {parse_stylesheet} is that CDO/CDC
# nodes (`<!--` and `-->`) aren't ignored.
#
# See {Tokenizer#initialize} for _options_.
#
# 5.3.3. http://dev.w3.org/csswg/css-syntax/#parse-a-list-of-rules
def self.parse_rules(input, options = {})
parser = Parser.new(input, options)
rules = parser.consume_rules

rules.map do |rule|
if rule[:node] == :qualified_rule
parser.create_style_rule(rule)
else
rule
end
end
end

# Parses a CSS stylesheet and returns a parse tree.
#
# See {Tokenizer#initialize} for _options_.
#
# 5.3.2. http://dev.w3.org/csswg/css-syntax/#parse-a-stylesheet
def self.parse_stylesheet(input, options = {})
parser = Parser.new(input, options)
rules = parser.consume_rules(:top_level => true)

rules.map do |rule|
if rule[:node] == :qualified_rule
parser.create_style_rule(rule)
else
rule
end
end
end

# Converts a node or array of nodes into a CSS string based on their
# original tokenized input.
#
# Options:
#
# * **:exclude_comments** - When `true`, comments will be excluded.
#
def self.stringify(nodes, options = {})
nodes = [nodes] unless nodes.is_a?(Array)
string = String.new

nodes.each do |node|
next if node.nil?

case node[:node]
when :at_rule
string << '@'
string << node[:name]
string << self.stringify(node[:prelude], options)

if node[:block]
string << '{' << self.stringify(node[:block], options) << '}'
else
string << ';'
end

when :comment
string << node[:raw] unless options[:exclude_comments]

when :simple_block
string << node[:start]
string << self.stringify(node[:value], options)
string << node[:end]

when :style_rule
string << self.stringify(node[:selector][:tokens], options)
string << '{' << self.stringify(node[:children], options) << '}'

else
if node.key?(:raw)
string << node[:raw]
elsif node.key?(:tokens)
string << self.stringify(node[:tokens], options)
end
end
end

string
end

# -- Instance Methods ------------------------------------------------------

# {TokenScanner} wrapping the tokens generated from this parser's input.
Expand Down
16 changes: 2 additions & 14 deletions test/test_crass.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,14 @@
make_my_diffs_pretty!
parallelize_me!

it 'parse_properties() should call Crass::Parser.parse_properties' do
assert_equal(
CP.parse_properties("a:b; c:d 42!important;\n"),
Crass.parse_properties("a:b; c:d 42!important;\n")
)

assert_equal(
CP.parse_properties(";; /**/ ; ;", :preserve_comments => true),
Crass.parse_properties(";; /**/ ; ;", :preserve_comments => true)
)
end

it 'parse() should call Crass::Parser.parse_stylesheet' do
assert_equal(
CP.parse_stylesheet(" /**/ .foo {} #bar {}"),
Crass.parse_stylesheet(" /**/ .foo {} #bar {}"),
Crass.parse(" /**/ .foo {} #bar {}")
)

assert_equal(
CP.parse_stylesheet(" /**/ .foo {} #bar {}", :preserve_comments => true),
Crass.parse_stylesheet(" /**/ .foo {} #bar {}", :preserve_comments => true),
Crass.parse(" /**/ .foo {} #bar {}", :preserve_comments => true)
)
end
Expand Down
2 changes: 1 addition & 1 deletion test/test_css_parsing_tests.rb
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ def load_css_tests(filename)
css = test[0]
expected = test[1]

it "should parse: #{css.gsub("\n", "\\n")}" do
it "should parse: #{css.gsub("\n", "\\n").inspect}" do
parser = Crass::Parser.new(css)
rules = parser.consume_rules(:top_level => true)

Expand Down
2 changes: 1 addition & 1 deletion test/test_parse_properties.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

describe '#parse_properties' do
def parse(*args)
CP.parse_properties(*args)
Crass.parse_properties(*args)
end

it 'should return an empty tree when given an empty string' do
Expand Down
2 changes: 1 addition & 1 deletion test/test_parse_rules.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

describe '#parse_rules' do
def parse(*args)
CP.parse_rules(*args)
Crass.parse_rules(*args)
end

behaves_like 'parsing a list of rules'
Expand Down
2 changes: 1 addition & 1 deletion test/test_parse_stylesheet.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

describe '#parse_stylesheet' do
def parse(*args)
CP.parse_stylesheet(*args)
Crass.parse_stylesheet(*args)
end

behaves_like 'parsing a list of rules'
Expand Down
10 changes: 5 additions & 5 deletions test/test_serialization.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
:preserve_comments => true,
:preserve_hacks => true)

assert_equal(input, CP.stringify(tree))
assert_equal(input, Crass.stringify(tree))
end
end

Expand All @@ -24,7 +24,7 @@
css = '@charset "utf-8";'
tree = Crass.parse(css)

assert_equal(css, CP.stringify(tree))
assert_equal(css, Crass.stringify(tree))
end

it "should reflect modifications made to the block of an `:at_rule`" do
Expand All @@ -35,11 +35,11 @@
}
].strip)

tree[0][:block] = Crass::Parser.parse_rules(".piggy { color: pink; }")
tree[0][:block] = Crass.parse_rules(".piggy { color: pink; }")

assert_equal(
"@media (screen) {.piggy { color: pink; }}",
Crass::Parser.stringify(tree)
Crass.stringify(tree)
)
end

Expand All @@ -66,6 +66,6 @@
].strip

tree = Crass.parse(css)
assert_equal(css, Crass::Parser.stringify(tree))
assert_equal(css, Crass.stringify(tree))
end
end

0 comments on commit 6a71dd7

Please sign in to comment.