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