Skip to content

Commit 15075c8

Browse files
committed
fix(linter): parse second script block for svelte files
1 parent fa2d3f1 commit 15075c8

File tree

1 file changed

+47
-12
lines changed
  • crates/oxc_linter/src/loader/partial_loader

1 file changed

+47
-12
lines changed

crates/oxc_linter/src/loader/partial_loader/svelte.rs

Lines changed: 47 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,32 +16,46 @@ impl<'a> SveltePartialLoader<'a> {
1616
}
1717

1818
pub fn parse(self) -> Vec<JavaScriptSource<'a>> {
19-
self.parse_script().map_or_else(Vec::new, |source| vec![source])
19+
self.parse_scripts()
2020
}
2121

22-
fn parse_script(&self) -> Option<JavaScriptSource<'a>> {
22+
/// Each *.svelte file can contain at most
23+
/// * one `<script>` block
24+
/// * one `<script context="module">` or `<script module>` block
25+
/// <https://github.com/sveltejs/svelte.dev/blob/ba7ad256f786aa5bc67eac3a58608f3f50b59e91/apps/svelte.dev/content/tutorial/02-advanced-svelte/08-script-module/02-module-exports/index.md>
26+
fn parse_scripts(&self) -> Vec<JavaScriptSource<'a>> {
27+
let mut pointer = 0;
28+
let Some(result1) = self.parse_script(&mut pointer) else {
29+
return vec![];
30+
};
31+
let Some(result2) = self.parse_script(&mut pointer) else {
32+
return vec![result1];
33+
};
34+
vec![result1, result2]
35+
}
36+
37+
fn parse_script(&self, pointer: &mut usize) -> Option<JavaScriptSource<'a>> {
2338
let script_start_finder = Finder::new(SCRIPT_START);
2439
let script_end_finder = Finder::new(SCRIPT_END);
2540

26-
let mut pointer = 0;
27-
2841
// find opening "<script"
29-
let offset = script_start_finder.find(&self.source_text.as_bytes()[pointer..])?;
30-
pointer += offset + SCRIPT_START.len();
42+
let offset = script_start_finder.find(&self.source_text.as_bytes()[*pointer..])?;
43+
*pointer += offset + SCRIPT_START.len();
3144

3245
// find closing ">"
33-
let offset = find_script_closing_angle(self.source_text, pointer)?;
46+
let offset = find_script_closing_angle(self.source_text, *pointer)?;
3447

3548
// get lang="ts" attribute
36-
let content = &self.source_text[pointer..pointer + offset];
49+
let content = &self.source_text[*pointer..*pointer + offset];
3750
let is_ts = content.contains("ts");
3851

39-
pointer += offset + 1;
40-
let js_start = pointer;
52+
*pointer += offset + 1;
53+
let js_start = *pointer;
4154

4255
// find "</script>"
43-
let offset = script_end_finder.find(&self.source_text.as_bytes()[pointer..])?;
44-
let js_end = pointer + offset;
56+
let offset = script_end_finder.find(&self.source_text.as_bytes()[*pointer..])?;
57+
let js_end = *pointer + offset;
58+
*pointer += offset + SCRIPT_END.len();
4559

4660
let source_text = &self.source_text[js_start..js_end];
4761
let source_type = SourceType::mjs().with_typescript(is_ts);
@@ -86,4 +100,25 @@ mod test {
86100
let result = parse_svelte(source_text);
87101
assert_eq!(result.source_text.trim(), r#"console.log("hi");"#);
88102
}
103+
104+
#[test]
105+
fn test_parse_svelte_with_module_script() {
106+
let source_text = r#"
107+
<script module>
108+
export async function load() { /* some loading logic */ }
109+
</script>
110+
<script>
111+
console.log("hi");
112+
</script>
113+
<h1>Hello World</h1>
114+
"#;
115+
116+
let sources = SveltePartialLoader::new(source_text).parse();
117+
assert_eq!(sources.len(), 2);
118+
assert_eq!(
119+
sources[0].source_text.trim(),
120+
"export async function load() { /* some loading logic */ }"
121+
);
122+
assert_eq!(sources[1].source_text.trim(), r#"console.log("hi");"#);
123+
}
89124
}

0 commit comments

Comments
 (0)