Skip to content

Commit 56bec82

Browse files
Fix css strategy
1 parent adc497c commit 56bec82

2 files changed

Lines changed: 58 additions & 10 deletions

File tree

crates/webui-parser/src/plugin/fast.rs

Lines changed: 53 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
77
use super::ParserPlugin;
88
use crate::component_registry::Component;
9-
use crate::Result;
9+
use crate::{CssStrategy, Result};
1010

1111
/// Information about a tracked component for `<f-template>` generation.
1212
struct TrackedComponent {
@@ -25,6 +25,8 @@ struct TrackedComponent {
2525
pub struct FastParserPlugin {
2626
/// Components tracked during parsing, in discovery order.
2727
components: Vec<TrackedComponent>,
28+
/// CSS delivery strategy for f-templates.
29+
css_strategy: CssStrategy,
2830
}
2931

3032
impl FastParserPlugin {
@@ -33,9 +35,15 @@ impl FastParserPlugin {
3335
pub fn new() -> Self {
3436
Self {
3537
components: Vec::new(),
38+
css_strategy: CssStrategy::Link,
3639
}
3740
}
3841

42+
/// Set the CSS delivery strategy for generated f-templates.
43+
pub fn set_css_strategy(&mut self, strategy: CssStrategy) {
44+
self.css_strategy = strategy;
45+
}
46+
3947
/// Take the individual component f-template strings, keyed by tag name.
4048
///
4149
/// Each value is a complete `<f-template name="tag-name">...</f-template>` string
@@ -50,6 +58,7 @@ impl FastParserPlugin {
5058
&comp.tag_name,
5159
&comp.html_content,
5260
comp.css_content.as_deref(),
61+
self.css_strategy,
5362
);
5463
(comp.tag_name.clone(), tmpl)
5564
})
@@ -116,6 +125,7 @@ pub fn generate_f_template(
116125
tag_name: &str,
117126
html_content: &str,
118127
css_content: Option<&str>,
128+
css_strategy: CssStrategy,
119129
) -> String {
120130
let mut output = String::with_capacity(256);
121131
output.push_str("<f-template name=\"");
@@ -125,24 +135,38 @@ pub fn generate_f_template(
125135
let converted = convert_btr_to_fast(html_content);
126136
let trimmed = minify_inter_tag_whitespace(converted.trim());
127137

138+
// Build the CSS injection string based on the configured strategy
139+
let css_injection = match css_strategy {
140+
CssStrategy::Link => css_content.map(|_| {
141+
let mut s = String::with_capacity(40 + tag_name.len());
142+
s.push_str("<link rel=\"stylesheet\" href=\"/");
143+
s.push_str(tag_name);
144+
s.push_str(".css\">");
145+
s
146+
}),
147+
CssStrategy::Style => css_content.map(|css| {
148+
let mut s = String::with_capacity(15 + css.len());
149+
s.push_str("<style>");
150+
s.push_str(css.trim());
151+
s.push_str("</style>");
152+
s
153+
}),
154+
};
155+
128156
if trimmed.starts_with("<template") {
129157
if let Some(close_pos) = trimmed.find('>') {
130158
output.push_str(&trimmed[..=close_pos]);
131-
if css_content.is_some() {
132-
output.push_str("<link rel=\"stylesheet\" href=\"/");
133-
output.push_str(tag_name);
134-
output.push_str(".css\">");
159+
if let Some(ref injection) = css_injection {
160+
output.push_str(injection);
135161
}
136162
output.push_str(&trimmed[close_pos + 1..]);
137163
} else {
138164
output.push_str(&trimmed);
139165
}
140166
} else {
141167
output.push_str("<template>");
142-
if css_content.is_some() {
143-
output.push_str("<link rel=\"stylesheet\" href=\"/");
144-
output.push_str(tag_name);
145-
output.push_str(".css\">");
168+
if let Some(ref injection) = css_injection {
169+
output.push_str(injection);
146170
}
147171
output.push_str(&trimmed);
148172
output.push_str("</template>");
@@ -692,6 +716,26 @@ mod tests {
692716
assert!(html.contains("<span>text</span>"));
693717
}
694718

719+
#[test]
720+
fn component_template_css_strategy_style() {
721+
let mut plugin = FastParserPlugin::new();
722+
plugin.set_css_strategy(crate::CssStrategy::Style);
723+
let comp = make_component("my-comp", "<div>hello</div>", Some("div { color: red; }"));
724+
plugin.on_parse_component("my-comp", &comp).unwrap();
725+
726+
let templates = plugin.take_component_templates();
727+
assert_eq!(templates.len(), 1);
728+
let (_, html) = &templates[0];
729+
assert!(
730+
html.contains("<style>div { color: red; }</style>"),
731+
"Style strategy should inline CSS, got: {html}"
732+
);
733+
assert!(
734+
!html.contains("<link"),
735+
"Style strategy should not emit <link> tags"
736+
);
737+
}
738+
695739
#[test]
696740
fn component_template_multiple_components() {
697741
let mut plugin = FastParserPlugin::new();

crates/webui/src/lib.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,11 @@ struct RawBuildOutput {
185185
/// Internal build logic shared by `build()` and `build_to_disk()`.
186186
fn build_protocol_inner(options: &BuildOptions) -> Result<RawBuildOutput, WebUIError> {
187187
let mut parser = match options.plugin.as_deref() {
188-
Some("fast") => HtmlParser::with_plugin(Box::new(FastParserPlugin::new())),
188+
Some("fast") => {
189+
let mut plugin = FastParserPlugin::new();
190+
plugin.set_css_strategy(options.css);
191+
HtmlParser::with_plugin(Box::new(plugin))
192+
}
189193
Some(unknown) => return Err(WebUIError::InvalidPlugin(unknown.to_string())),
190194
None => HtmlParser::new(),
191195
};

0 commit comments

Comments
 (0)