Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Update
  • Loading branch information
owjs3901 committed Jan 12, 2026
commit 7fdc5dc3525f00d33c654140175b37991049adc1
37 changes: 36 additions & 1 deletion libs/extractor/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ mod gen_style;
mod prop_modify_utils;
mod util_type;
mod utils;
mod vanilla_extract;
mod visit;
use crate::extract_style::extract_style_value::ExtractStyleValue;
use crate::visit::DevupVisitor;
Expand Down Expand Up @@ -111,6 +112,40 @@ pub fn extract(
});
}

// Handle vanilla-extract style files (.css.ts, .css.js)
let (processed_code, is_vanilla_extract) = if vanilla_extract::is_vanilla_extract_file(filename)
{
match vanilla_extract::execute_vanilla_extract(code, &option.package) {
Ok(collected) => {
let generated =
vanilla_extract::collected_styles_to_code(&collected, &option.package);
(generated, true)
}
Err(_) => {
// Fall back to treating as regular file if execution fails
(code.to_string(), false)
}
}
} else {
(code.to_string(), false)
};

// For vanilla-extract files, if no styles were collected, return early
if is_vanilla_extract && processed_code.is_empty() {
return Ok(ExtractOutput {
styles: HashSet::new(),
code: code.to_string(),
map: None,
css_file: None,
});
}

let code_to_parse = if is_vanilla_extract {
&processed_code
} else {
code
};

let source_type = SourceType::from_path(filename)?;
let css_file = if option.single_css {
format!("{}/devup-ui.css", option.css_dir)
Expand All @@ -131,7 +166,7 @@ pub fn extract(
mut program, // AST
panicked, // Parser encountered an error it couldn't recover from
..
} = Parser::new(&allocator, code, source_type).parse();
} = Parser::new(&allocator, code_to_parse, source_type).parse();
if panicked {
return Err("Parser panicked".into());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,61 @@ source: libs/extractor/src/lib.rs
expression: "ToBTreeSet::from(extract(\"composition.css.ts\",\nr#\"import { style } from '@devup-ui/react'\nconst base = style({\n padding: 12,\n borderRadius: 4\n})\nconst interactive = style({\n cursor: 'pointer',\n transition: 'all 0.2s'\n})\nexport const button = style([base, interactive, {\n background: 'blue',\n color: 'white'\n}])\n\"#,\nExtractOption\n{\n package: \"@devup-ui/react\".to_string(), css_dir:\n \"@devup-ui/react\".to_string(), single_css: true, import_main_css: false\n}).unwrap())"
---
ToBTreeSet {
styles: {},
code: "import { style } from \"@devup-ui/react\";\nconst base = style({\n\tpadding: 12,\n\tborderRadius: 4\n});\nconst interactive = style({\n\tcursor: \"pointer\",\n\ttransition: \"all 0.2s\"\n});\nexport const button = style([\n\tbase,\n\tinteractive,\n\t{\n\t\tbackground: \"blue\",\n\t\tcolor: \"white\"\n\t}\n]);\n",
styles: {
Static(
ExtractStaticStyle {
property: "background",
value: "blue",
level: 0,
selector: None,
style_order: None,
},
),
Static(
ExtractStaticStyle {
property: "border-radius",
value: "16px",
level: 0,
selector: None,
style_order: None,
},
),
Static(
ExtractStaticStyle {
property: "color",
value: "white",
level: 0,
selector: None,
style_order: None,
},
),
Static(
ExtractStaticStyle {
property: "cursor",
value: "pointer",
level: 0,
selector: None,
style_order: None,
},
),
Static(
ExtractStaticStyle {
property: "padding",
value: "48px",
level: 0,
selector: None,
style_order: None,
},
),
Static(
ExtractStaticStyle {
property: "transition",
value: "all .2s",
level: 0,
selector: None,
style_order: None,
},
),
},
code: "import \"@devup-ui/react/devup-ui.css\";\nconst base = \"a b\";\nexport const button = \"a b c d e f\";\nconst interactive = \"c d\";\n",
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,40 @@ source: libs/extractor/src/lib.rs
expression: "ToBTreeSet::from(extract(\"container.css.ts\",\nr#\"import { createContainer, style } from '@devup-ui/react'\nexport const sidebar = createContainer()\nexport const sidebarContainer = style({\n containerName: sidebar,\n containerType: 'inline-size'\n})\nexport const responsive = style({\n '@container': {\n [`${sidebar} (min-width: 400px)`]: {\n flexDirection: 'row'\n }\n }\n})\n\"#,\nExtractOption\n{\n package: \"@devup-ui/react\".to_string(), css_dir:\n \"@devup-ui/react\".to_string(), single_css: true, import_main_css: false\n}).unwrap())"
---
ToBTreeSet {
styles: {},
code: "import { createContainer, style } from \"@devup-ui/react\";\nexport const sidebar = createContainer();\nexport const sidebarContainer = style({\n\tcontainerName: sidebar,\n\tcontainerType: \"inline-size\"\n});\nexport const responsive = style({ \"@container\": { [`${sidebar} (min-width: 400px)`]: { flexDirection: \"row\" } } });\n",
styles: {
Static(
ExtractStaticStyle {
property: "container-name",
value: "__container_0__",
level: 0,
selector: None,
style_order: None,
},
),
Static(
ExtractStaticStyle {
property: "container-type",
value: "inline-size",
level: 0,
selector: None,
style_order: None,
},
),
Static(
ExtractStaticStyle {
property: "flex-direction",
value: "row",
level: 0,
selector: Some(
At {
kind: Container,
query: "__container_0__ (min-width: 400px)",
selector: None,
},
),
style_order: None,
},
),
},
code: "import \"@devup-ui/react/devup-ui.css\";\nexport const responsive = \"a\";\nexport const sidebarContainer = \"b c\";\nexport const sidebar = \"__container_0__\";\n",
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,16 @@ source: libs/extractor/src/lib.rs
expression: "ToBTreeSet::from(extract(\"fallback.css.ts\",\nr#\"import { createVar, fallbackVar, style } from '@devup-ui/react'\nexport const colorVar = createVar()\nexport const box = style({\n color: fallbackVar(colorVar, 'red')\n})\n\"#,\nExtractOption\n{\n package: \"@devup-ui/react\".to_string(), css_dir:\n \"@devup-ui/react\".to_string(), single_css: true, import_main_css: false\n}).unwrap())"
---
ToBTreeSet {
styles: {},
code: "import { createVar, fallbackVar, style } from \"@devup-ui/react\";\nexport const colorVar = createVar();\nexport const box = style({ color: fallbackVar(colorVar, \"red\") });\n",
styles: {
Static(
ExtractStaticStyle {
property: "color",
value: "var(--var0,red)",
level: 0,
selector: None,
style_order: None,
},
),
},
code: "import \"@devup-ui/react/devup-ui.css\";\nexport const box = \"a\";\nexport const colorVar = \"--var-0\";\n",
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,25 @@ source: libs/extractor/src/lib.rs
expression: "ToBTreeSet::from(extract(\"vars.css.ts\",\nr#\"import { createVar, style } from '@devup-ui/react'\nexport const colorVar = createVar()\nexport const box = style({\n vars: {\n [colorVar]: 'blue'\n },\n color: colorVar\n})\n\"#,\nExtractOption\n{\n package: \"@devup-ui/react\".to_string(), css_dir:\n \"@devup-ui/react\".to_string(), single_css: true, import_main_css: false\n}).unwrap())"
---
ToBTreeSet {
styles: {},
code: "import { createVar, style } from \"@devup-ui/react\";\nexport const colorVar = createVar();\nexport const box = style({\n\tvars: { [colorVar]: \"blue\" },\n\tcolor: colorVar\n});\n",
styles: {
Static(
ExtractStaticStyle {
property: "color",
value: "var(--var0)",
level: 0,
selector: None,
style_order: None,
},
),
Static(
ExtractStaticStyle {
property: "var(--var-0)",
value: "blue",
level: 0,
selector: None,
style_order: None,
},
),
},
code: "import \"@devup-ui/react/devup-ui.css\";\nexport const box = \"a b\";\nexport const colorVar = \"--var-0\";\n",
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,16 @@ source: libs/extractor/src/lib.rs
expression: "ToBTreeSet::from(extract(\"fonts-multi.css.ts\",\nr#\"import { fontFace, style } from '@devup-ui/react'\nconst roboto = fontFace({\n src: 'url(\"/fonts/Roboto.woff2\") format(\"woff2\")',\n fontWeight: 400,\n fontStyle: 'normal'\n})\nexport const body = style({\n fontFamily: roboto\n})\n\"#,\nExtractOption\n{\n package: \"@devup-ui/react\".to_string(), css_dir:\n \"@devup-ui/react\".to_string(), single_css: true, import_main_css: false\n}).unwrap())"
---
ToBTreeSet {
styles: {},
code: "import { fontFace, style } from \"@devup-ui/react\";\nconst roboto = fontFace({\n\tsrc: \"url(\\\"/fonts/Roboto.woff2\\\") format(\\\"woff2\\\")\",\n\tfontWeight: 400,\n\tfontStyle: \"normal\"\n});\nexport const body = style({ fontFamily: roboto });\n",
styles: {
Static(
ExtractStaticStyle {
property: "font-family",
value: "__font_1__",
level: 0,
selector: None,
style_order: None,
},
),
},
code: "import \"@devup-ui/react/devup-ui.css\";\nconst roboto = \"a\";\n",
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,16 @@ source: libs/extractor/src/lib.rs
expression: "ToBTreeSet::from(extract(\"fonts.css.ts\",\nr#\"import { fontFace, style } from '@devup-ui/react'\nconst myFont = fontFace({\n src: 'local(\"Comic Sans MS\")'\n})\nexport const text = style({\n fontFamily: myFont\n})\n\"#,\nExtractOption\n{\n package: \"@devup-ui/react\".to_string(), css_dir:\n \"@devup-ui/react\".to_string(), single_css: true, import_main_css: false\n}).unwrap())"
---
ToBTreeSet {
styles: {},
code: "import { fontFace, style } from \"@devup-ui/react\";\nconst myFont = fontFace({ src: \"local(\\\"Comic Sans MS\\\")\" });\nexport const text = style({ fontFamily: myFont });\n",
styles: {
Static(
ExtractStaticStyle {
property: "font-family",
value: "__font_1__",
level: 0,
selector: None,
style_order: None,
},
),
},
code: "import \"@devup-ui/react/devup-ui.css\";\nconst myFont = \"a\";\n",
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ expression: "ToBTreeSet::from(extract(\"global-theme.css.ts\",\nr#\"import { cre
---
ToBTreeSet {
styles: {},
code: "import { createGlobalTheme } from \"@devup-ui/react\";\nexport const vars = createGlobalTheme(\":root\", {\n\tcolor: {\n\t\tbrand: \"blue\",\n\t\ttext: \"black\",\n\t\tbackground: \"white\"\n\t},\n\tfont: { body: \"system-ui, sans-serif\" }\n});\n",
code: "export const vars = createGlobalTheme(\":root\", {\n\tcolor: {\n\t\tbrand: \"blue\",\n\t\ttext: \"black\",\n\t\tbackground: \"white\"\n\t},\n\tfont: { body: \"system-ui, sans-serif\" }\n});\n",
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,55 @@ source: libs/extractor/src/lib.rs
expression: "ToBTreeSet::from(extract(\"layers.css.ts\",\nr#\"import { layer, style, globalStyle } from '@devup-ui/react'\nexport const reset = layer('reset')\nexport const base = layer('base')\nexport const components = layer('components')\nglobalStyle('*', {\n '@layer': reset,\n margin: 0,\n padding: 0\n})\n\"#,\nExtractOption\n{\n package: \"@devup-ui/react\".to_string(), css_dir:\n \"@devup-ui/react\".to_string(), single_css: true, import_main_css: false\n}).unwrap())"
---
ToBTreeSet {
styles: {},
code: "import { layer, style, globalStyle } from \"@devup-ui/react\";\nexport const reset = layer(\"reset\");\nexport const base = layer(\"base\");\nexport const components = layer(\"components\");\nglobalStyle(\"*\", {\n\t\"@layer\": reset,\n\tmargin: 0,\n\tpadding: 0\n});\n",
styles: {
Static(
ExtractStaticStyle {
property: "@layer",
value: "reset",
level: 0,
selector: Some(
Global(
"*",
"layers.css.ts",
),
),
style_order: Some(
0,
),
},
),
Static(
ExtractStaticStyle {
property: "margin",
value: "0",
level: 0,
selector: Some(
Global(
"*",
"layers.css.ts",
),
),
style_order: Some(
0,
),
},
),
Static(
ExtractStaticStyle {
property: "padding",
value: "0",
level: 0,
selector: Some(
Global(
"*",
"layers.css.ts",
),
),
style_order: Some(
0,
),
},
),
},
code: "import \"@devup-ui/react/devup-ui.css\";\n;\nexport const base = \"base\";\nexport const components = \"components\";\nexport const reset = \"reset\";\n",
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,76 @@ source: libs/extractor/src/lib.rs
expression: "ToBTreeSet::from(extract(\"media.css.ts\",\nr#\"import { style } from '@devup-ui/react'\nexport const responsive = style({\n display: 'block',\n '@media': {\n 'screen and (min-width: 768px)': {\n display: 'flex'\n },\n 'screen and (min-width: 1024px)': {\n display: 'grid'\n },\n '(prefers-color-scheme: dark)': {\n background: 'black',\n color: 'white'\n }\n }\n})\n\"#,\nExtractOption\n{\n package: \"@devup-ui/react\".to_string(), css_dir:\n \"@devup-ui/react\".to_string(), single_css: true, import_main_css: false\n}).unwrap())"
---
ToBTreeSet {
styles: {},
code: "import { style } from \"@devup-ui/react\";\nexport const responsive = style({\n\tdisplay: \"block\",\n\t\"@media\": {\n\t\t\"screen and (min-width: 768px)\": { display: \"flex\" },\n\t\t\"screen and (min-width: 1024px)\": { display: \"grid\" },\n\t\t\"(prefers-color-scheme: dark)\": {\n\t\t\tbackground: \"black\",\n\t\t\tcolor: \"white\"\n\t\t}\n\t}\n});\n",
styles: {
Static(
ExtractStaticStyle {
property: "background",
value: "black",
level: 0,
selector: Some(
At {
kind: Media,
query: "(prefers-color-scheme: dark)",
selector: None,
},
),
style_order: None,
},
),
Static(
ExtractStaticStyle {
property: "color",
value: "white",
level: 0,
selector: Some(
At {
kind: Media,
query: "(prefers-color-scheme: dark)",
selector: None,
},
),
style_order: None,
},
),
Static(
ExtractStaticStyle {
property: "display",
value: "block",
level: 0,
selector: None,
style_order: None,
},
),
Static(
ExtractStaticStyle {
property: "display",
value: "flex",
level: 0,
selector: Some(
At {
kind: Media,
query: "screen and (min-width: 768px)",
selector: None,
},
),
style_order: None,
},
),
Static(
ExtractStaticStyle {
property: "display",
value: "grid",
level: 0,
selector: Some(
At {
kind: Media,
query: "screen and (min-width: 1024px)",
selector: None,
},
),
style_order: None,
},
),
},
code: "import \"@devup-ui/react/devup-ui.css\";\nexport const responsive = \"a b c d e\";\n",
}
Loading