Skip to content

Commit cc51009

Browse files
committed
Parser: Parse CSS and <style> tags using Lightning CSS
1 parent 450c29b commit cc51009

File tree

50 files changed

+2496
-66
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+2496
-66
lines changed

.clang-format-ignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@ src/ast_pretty_print.c
55
src/errors.c
66
src/include/ast_nodes.h
77
src/include/ast_pretty_print.h
8+
src/include/css_parser.h
89
src/include/errors.h
910
src/visitor.c

.github/workflows/build-gems.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,14 @@ jobs:
7575
with:
7676
bundler-cache: false
7777

78+
- name: Set up Rust
79+
uses: dtolnay/rust-toolchain@stable
80+
with:
81+
toolchain: stable
82+
83+
- name: Build CSS Parser
84+
run: cd src/css && cargo build --release
85+
7886
- name: bundle install
7987
run: bundle install
8088

.github/workflows/build.yml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,26 @@ jobs:
3434
with:
3535
bundler-cache: true
3636

37+
- name: Set up Rust
38+
uses: dtolnay/rust-toolchain@stable
39+
with:
40+
toolchain: stable
41+
42+
- name: Install Rust WASM target
43+
run: rustup target add wasm32-unknown-emscripten
44+
45+
- name: Build CSS Parser
46+
run: cd src/css && cargo build --release
47+
3748
- name: bundle install
3849
run: bundle install
3950

4051
- name: Render Templates
4152
run: bundle exec rake templates
4253

54+
- name: make all
55+
run: make all
56+
4357
- name: Compile Herb
4458
run: bundle exec rake make
4559

.github/workflows/deploy.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,17 @@ jobs:
5353
with:
5454
bundler-cache: true
5555

56+
- name: Set up Rust
57+
uses: dtolnay/rust-toolchain@stable
58+
with:
59+
toolchain: stable
60+
61+
- name: Install Rust WASM target
62+
run: rustup target add wasm32-unknown-emscripten
63+
64+
- name: Build CSS Parser
65+
run: cd src/css && cargo build --release
66+
5667
- name: bundle install
5768
run: bundle install
5869

.github/workflows/javascript.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,17 @@ jobs:
4141
with:
4242
bundler-cache: true
4343

44+
- name: Set up Rust
45+
uses: dtolnay/rust-toolchain@stable
46+
with:
47+
toolchain: stable
48+
49+
- name: Install Rust WASM target
50+
run: rustup target add wasm32-unknown-emscripten
51+
52+
- name: Build CSS Parser
53+
run: cd src/css && cargo build --release
54+
4455
- name: bundle install
4556
run: bundle install
4657

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,3 +134,7 @@ docs/docs/public/c-reference
134134

135135
# NPM
136136
**/node_modules/**/*
137+
138+
# Rust (CSS Parser)
139+
src/css/target/
140+
src/include/css_parser.h

Makefile

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ prism_build = $(prism_path)/build
3737
prism_flags = -I$(prism_include)
3838
prism_ldflags = $(prism_build)/libprism.a
3939

40+
css_parser_dir = src/css
41+
css_parser_lib = $(css_parser_dir)/target/release/libherb_css_parser.a
42+
css_parser_flags = -I$(css_parser_dir)
43+
4044
# Enable strict warnings
4145
warning_flags = -Wall -Wextra -Werror -pedantic
4246

@@ -50,42 +54,44 @@ production_flags = $(warning_flags) -O3 -march=native -flto
5054
shared_library_flags = -fPIC
5155

5256
# Default build mode (change this as needed)
53-
flags = $(warning_flags) $(debug_flags) $(prism_flags) -std=c99
57+
flags = $(warning_flags) $(debug_flags) $(prism_flags) $(css_parser_flags) -std=c99
5458

5559
# Separate test compilation flags
56-
test_flags = $(debug_flags) $(prism_flags) -std=gnu99
60+
test_flags = $(debug_flags) $(prism_flags) $(css_parser_flags) -std=gnu99
5761

5862
# Shared library build (if needed)
59-
shared_flags = $(production_flags) $(shared_library_flags) $(prism_flags)
63+
shared_flags = $(production_flags) $(shared_library_flags) $(prism_flags) $(css_parser_flags)
6064

6165
ifeq ($(os),Linux)
66+
css_parser_ldflags = $(css_parser_lib) -ldl -lpthread -lm
6267
test_cflags = $(test_flags) -I/usr/include/check
63-
test_ldflags = -L/usr/lib/x86_64-linux-gnu -lcheck -lm -lsubunit $(prism_ldflags)
68+
test_ldflags = -L/usr/lib/x86_64-linux-gnu -lcheck -lm -lsubunit $(prism_ldflags) $(css_parser_ldflags)
6469
cc = clang-21
6570
clang_format = clang-format-21
6671
clang_tidy = clang-tidy-21
6772
endif
6873

6974
ifeq ($(os),Darwin)
75+
css_parser_ldflags = $(css_parser_lib) -lresolv -framework Security -framework CoreFoundation
7076
brew_prefix := $(shell brew --prefix check)
7177
test_cflags = $(test_flags) -I$(brew_prefix)/include
72-
test_ldflags = -L$(brew_prefix)/lib -lcheck -lm $(prism_ldflags)
78+
test_ldflags = -L$(brew_prefix)/lib -lcheck -lm $(prism_ldflags) $(css_parser_ldflags)
7379
llvm_path = $(shell brew --prefix llvm@21)
7480
cc = $(llvm_path)/bin/clang
7581
clang_format = $(llvm_path)/bin/clang-format
7682
clang_tidy = $(llvm_path)/bin/clang-tidy
7783
endif
7884

79-
all: templates prism $(exec) $(lib_name) $(static_lib_name) test wasm
85+
all: templates prism css_parser $(exec) $(lib_name) $(static_lib_name) test wasm
8086

81-
$(exec): $(objects)
82-
$(cc) $(objects) $(flags) $(ldflags) $(prism_ldflags) -o $(exec)
87+
$(exec): $(objects) $(css_parser_lib)
88+
$(cc) $(objects) $(flags) $(ldflags) $(prism_ldflags) $(css_parser_ldflags) -o $(exec)
8389

84-
$(lib_name): $(objects)
85-
$(cc) -shared $(objects) $(shared_flags) $(ldflags) $(prism_ldflags) -o $(lib_name)
90+
$(lib_name): $(objects) $(css_parser_lib)
91+
$(cc) -shared $(objects) $(shared_flags) $(ldflags) $(prism_ldflags) $(css_parser_ldflags) -o $(lib_name)
8692
# cp $(lib_name) $(ruby_extension)
8793

88-
$(static_lib_name): $(objects)
94+
$(static_lib_name): $(objects) $(css_parser_lib)
8995
ar rcs $(static_lib_name) $(objects)
9096

9197
src/%.o: src/%.c templates
@@ -102,6 +108,7 @@ clean:
102108
rm -rf $(objects) $(test_objects) $(extension_objects) lib/herb/*.bundle tmp
103109
rm -rf $(prism_path)
104110
rake prism:clean
111+
cd $(css_parser_dir) && cargo clean
105112

106113
bundle_install:
107114
bundle install
@@ -113,6 +120,12 @@ prism: bundle_install
113120
cd $(prism_path) && ruby templates/template.rb && make static && cd -
114121
rake prism:vendor
115122

123+
css_parser: $(css_parser_lib)
124+
125+
$(css_parser_lib):
126+
cd $(css_parser_dir) && cargo build --release
127+
cbindgen --config $(css_parser_dir)/cbindgen.toml --output src/include/css_parser.h $(css_parser_dir)
128+
116129
format:
117130
$(clang_format) -i $(project_and_extension_files)
118131

config.yml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -712,3 +712,35 @@ nodes:
712712
- name: statements
713713
type: array
714714
kind: Node
715+
716+
- name: CSSDeclarationNode
717+
fields:
718+
- name: property
719+
type: string
720+
721+
- name: value
722+
type: string
723+
724+
- name: CSSRuleNode
725+
fields:
726+
- name: selector
727+
type: string
728+
729+
- name: declarations
730+
type: array
731+
kind: CSSDeclarationNode
732+
733+
- name: CSSStyleNode
734+
fields:
735+
- name: content
736+
type: string
737+
738+
- name: rules
739+
type: array
740+
kind: CSSRuleNode
741+
742+
- name: valid
743+
type: boolean
744+
745+
- name: parse_error
746+
type: string

ext/herb/extconf.rb

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,13 @@
1010

1111
include_path = File.expand_path("../../src/include", __dir__)
1212
prism_path = File.expand_path("../../vendor/prism", __dir__)
13+
css_parser_path = File.expand_path("../../src/css", __dir__)
1314

1415
prism_src_path = "#{prism_path}/src"
1516
prism_include_path = "#{prism_path}/include"
1617

18+
css_parser_lib = "#{css_parser_path}/target/release/libherb_css_parser.a"
19+
1720
$VPATH << "$(srcdir)/../../src"
1821
$VPATH << "$(srcdir)/../../src/util"
1922
$VPATH << prism_src_path
@@ -23,9 +26,17 @@
2326
$INCFLAGS << " -I#{include_path}"
2427
$INCFLAGS << " -I#{prism_src_path}"
2528
$INCFLAGS << " -I#{prism_src_path}/util"
29+
$INCFLAGS << " -I#{css_parser_path}"
2630

2731
$CFLAGS << " -DPRISM_EXPORT_SYMBOLS=static "
2832

33+
$LDFLAGS << " #{css_parser_lib}"
34+
if RUBY_PLATFORM.match?(/darwin/)
35+
$LDFLAGS << " -lresolv -framework Security -framework CoreFoundation"
36+
elsif RUBY_PLATFORM.match?(/linux/)
37+
$LDFLAGS << " -ldl -lpthread -lm"
38+
end
39+
2940
herb_src_files = Dir.glob("#{$srcdir}/../../src/**/*.c").map { |file| file.delete_prefix("../../../../ext/herb/") }.sort
3041

3142
prism_main_files = %w[

javascript/packages/formatter/src/format-printer.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,9 @@ import {
9191
ERBInNode,
9292
XMLDeclarationNode,
9393
CDATANode,
94+
CSSStyleNode,
95+
CSSRuleNode,
96+
CSSDeclarationNode,
9497
Token
9598
} from "@herb-tools/core"
9699

@@ -1192,6 +1195,20 @@ export class FormatPrinter extends Printer {
11921195
if (node.end_node) this.visit(node.end_node)
11931196
}
11941197

1198+
visitCSSStyleNode(node: CSSStyleNode) {
1199+
if (node.content) {
1200+
this.push(node.content)
1201+
}
1202+
}
1203+
1204+
visitCSSRuleNode(_node: CSSRuleNode) {
1205+
// CSS rules are contained within CSSStyleNode, not rendered separately
1206+
}
1207+
1208+
visitCSSDeclarationNode(_node: CSSDeclarationNode) {
1209+
// CSS declarations are contained within CSSRuleNode, not rendered separately
1210+
}
1211+
11951212
// --- Element Formatting Analysis Helpers ---
11961213

11971214
/**

0 commit comments

Comments
 (0)