|
1 | 1 | import * as utils from './index.ts';
|
2 |
| -import MagicString from 'magic-string'; |
3 | 2 |
|
4 | 3 | type ParseBase = {
|
5 | 4 | source: string;
|
@@ -35,136 +34,13 @@ export function parseJson(source: string): { data: any } & ParseBase {
|
35 | 34 | return { data, source, generateCode };
|
36 | 35 | }
|
37 | 36 |
|
38 |
| -type SvelteGenerator = (code: { |
39 |
| - script?: string; |
40 |
| - module?: string; |
41 |
| - css?: string; |
42 |
| - template?: string; |
43 |
| -}) => string; |
44 |
| -export function parseSvelte( |
45 |
| - source: string, |
46 |
| - options?: { typescript?: boolean } |
47 |
| -): { |
48 |
| - script: ReturnType<typeof parseScript>; |
49 |
| - module: ReturnType<typeof parseScript>; |
50 |
| - css: ReturnType<typeof parseCss>; |
51 |
| - template: ReturnType<typeof parseHtml>; |
52 |
| - generateCode: SvelteGenerator; |
53 |
| -} { |
54 |
| - // `xTag` captures the whole tag block (ex: <script>...</script>) |
55 |
| - // `xSource` is the contents within the tags |
56 |
| - const scripts = extractScripts(source); |
57 |
| - // instance block |
58 |
| - const { tag: scriptTag = '', src: scriptSource = '' } = |
59 |
| - scripts.find(({ attrs }) => !attrs.includes('module')) ?? {}; |
60 |
| - // module block |
61 |
| - const { tag: moduleScriptTag = '', src: moduleSource = '' } = |
62 |
| - scripts.find(({ attrs }) => attrs.includes('module')) ?? {}; |
63 |
| - // style block |
64 |
| - const { styleTag, cssSource } = extractStyle(source); |
65 |
| - // rest of the template |
66 |
| - // TODO: needs more testing |
67 |
| - const templateSource = source |
68 |
| - .replace(moduleScriptTag, '') |
69 |
| - .replace(scriptTag, '') |
70 |
| - .replace(styleTag, '') |
71 |
| - .trim(); |
72 |
| - |
73 |
| - const script = parseScript(scriptSource); |
74 |
| - const module = parseScript(moduleSource); |
75 |
| - const css = parseCss(cssSource); |
76 |
| - const template = parseHtml(templateSource); |
77 |
| - |
78 |
| - const generateCode: SvelteGenerator = (code) => { |
79 |
| - const ms = new MagicString(source); |
80 |
| - // TODO: this is imperfect and needs adjustments |
81 |
| - if (code.script !== undefined) { |
82 |
| - if (scriptSource.length === 0) { |
83 |
| - const ts = options?.typescript ? ' lang="ts"' : ''; |
84 |
| - const indented = code.script.split('\n').join('\n\t'); |
85 |
| - const script = `<script${ts}>\n\t${indented}\n</script>\n\n`; |
86 |
| - ms.prepend(script); |
87 |
| - } else { |
88 |
| - const { start, end } = locations(source, scriptSource); |
89 |
| - const formatted = indent(code.script, ms.getIndentString()); |
90 |
| - ms.update(start, end, formatted); |
91 |
| - } |
92 |
| - } |
93 |
| - if (code.module !== undefined) { |
94 |
| - if (moduleSource.length === 0) { |
95 |
| - const ts = options?.typescript ? ' lang="ts"' : ''; |
96 |
| - const indented = code.module.split('\n').join('\n\t'); |
97 |
| - // TODO: make a svelte 5 variant |
98 |
| - const module = `<script${ts} context="module">\n\t${indented}\n</script>\n\n`; |
99 |
| - ms.prepend(module); |
100 |
| - } else { |
101 |
| - const { start, end } = locations(source, moduleSource); |
102 |
| - const formatted = indent(code.module, ms.getIndentString()); |
103 |
| - ms.update(start, end, formatted); |
104 |
| - } |
105 |
| - } |
106 |
| - if (code.css !== undefined) { |
107 |
| - if (cssSource.length === 0) { |
108 |
| - const indented = code.css.split('\n').join('\n\t'); |
109 |
| - const style = `\n<style>\n\t${indented}\n</style>\n`; |
110 |
| - ms.append(style); |
111 |
| - } else { |
112 |
| - const { start, end } = locations(source, cssSource); |
113 |
| - const formatted = indent(code.css, ms.getIndentString()); |
114 |
| - ms.update(start, end, formatted); |
115 |
| - } |
116 |
| - } |
117 |
| - if (code.template !== undefined) { |
118 |
| - if (templateSource.length === 0) { |
119 |
| - ms.appendLeft(0, code.template); |
120 |
| - } else { |
121 |
| - const { start, end } = locations(source, templateSource); |
122 |
| - ms.update(start, end, code.template); |
123 |
| - } |
124 |
| - } |
125 |
| - return ms.toString(); |
126 |
| - }; |
| 37 | +export function parseSvelte(source: string): { ast: utils.SvelteAst.Root } & ParseBase { |
| 38 | + const ast = utils.parseSvelte(source); |
| 39 | + const generateCode = () => utils.serializeSvelte(ast); |
127 | 40 |
|
128 | 41 | return {
|
129 |
| - script: { ...script, source: scriptSource }, |
130 |
| - module: { ...module, source: moduleSource }, |
131 |
| - css: { ...css, source: cssSource }, |
132 |
| - template: { ...template, source: templateSource }, |
| 42 | + ast, |
| 43 | + source, |
133 | 44 | generateCode
|
134 | 45 | };
|
135 | 46 | }
|
136 |
| - |
137 |
| -function locations(source: string, search: string): { start: number; end: number } { |
138 |
| - const start = source.indexOf(search); |
139 |
| - const end = start + search.length; |
140 |
| - return { start, end }; |
141 |
| -} |
142 |
| - |
143 |
| -function indent(content: string, indent: string): string { |
144 |
| - const indented = indent + content.split('\n').join(`\n${indent}`); |
145 |
| - return `\n${indented}\n`; |
146 |
| -} |
147 |
| - |
1
1241
48 |
| -// sourced from Svelte: https://github.com/sveltejs/svelte/blob/0d3d5a2a85c0f9eccb2c8dbbecc0532ec918b157/packages/svelte/src/compiler/preprocess/index.js#L253-L256 |
149 |
| -const regexScriptTags = |
150 |
| - /<!--[^]*?-->|<script((?:\s+[^=>'"/\s]+=(?:"[^"]*"|'[^']*'|[^>\s]+)|\s+[^=>'"/\s]+)*\s*)(?:\/>|>([\S\s]*?)<\/script>)/; |
151 |
| -const regexStyleTags = |
152 |
| - /<!--[^]*?-->|<style((?:\s+[^=>'"/\s]+=(?:"[^"]*"|'[^']*'|[^>\s]+)|\s+[^=>'"/\s]+)*\s*)(?:\/>|>([\S\s]*?)<\/style>)/; |
153 |
| - |
154 |
| -type Script = { tag: string; attrs: string; src: string }; |
155 |
| -function extractScripts(source: string): Script[] { |
156 |
| - const scripts = []; |
157 |
| - const [tag = '', attrs = '', src = ''] = regexScriptTags.exec(source) ?? []; |
158 |
| - if (tag) { |
159 |
| - const stripped = source.replace(tag, ''); |
160 |
| - scripts.push({ tag, attrs, src }, ...extractScripts(stripped)); |
161 |
| - return scripts; |
162 |
| - } |
163 |
| - |
164 |
| - return []; |
165 |
| -} |
166 |
| - |
167 |
| -function extractStyle(source: string) { |
168 |
| - const [styleTag = '', attributes = '', cssSource = ''] = regexStyleTags.exec(source) ?? []; |
169 |
| - return { styleTag, attributes, cssSource }; |
170 |
| -} |
0 commit comments