diff --git a/packages/addons/common.ts b/packages/addons/common.ts index a1a8f2ce5..2ea48eae4 100644 --- a/packages/addons/common.ts +++ b/packages/addons/common.ts @@ -1,4 +1,5 @@ import { imports, exports, common } from '@sveltejs/cli-core/js'; +import { toSvelteFragment, type SvelteAst } from '@sveltejs/cli-core/html'; import { parseScript, parseSvelte } from '@sveltejs/cli-core/parsers'; import process from 'node:process'; @@ -64,17 +65,29 @@ export function addEslintConfigPrettier(content: string): string { } export function addToDemoPage(content: string, path: string): string { - const { template, generateCode } = parseSvelte(content); - - for (const node of template.ast.childNodes) { - if (node.type === 'tag' && node.attribs['href'] === `/demo/${path}`) { - return content; + const { ast, generateCode } = parseSvelte(content); + + for (const node of ast.fragment.nodes) { + if (node.type === 'RegularElement') { + const hrefAttribute = node.attributes.find( + (x) => x.type === 'Attribute' && x.name === 'href' + ) as SvelteAst.Attribute; + if (!hrefAttribute || !hrefAttribute.value) continue; + + if (!Array.isArray(hrefAttribute.value)) continue; + + const hasDemo = hrefAttribute.value.find( + (x) => x.type === 'Text' && x.data === `/demo/${path}` + ); + if (hasDemo) { + return content; + } } } - const newLine = template.source ? '\n' : ''; - const src = template.source + `${newLine}${path}`; - return generateCode({ template: src }); + ast.fragment.nodes.push(...toSvelteFragment(`${path}`)); + + return generateCode(); } /** diff --git a/packages/addons/eslint/index.ts b/packages/addons/eslint/index.ts index c40406c4e..f24b6d9d1 100644 --- a/packages/addons/eslint/index.ts +++ b/packages/addons/eslint/index.ts @@ -53,7 +53,7 @@ export default defineAddon({ }); sv.file('eslint.config.js', (content) => { - const { ast, generateCode } = parseScript(content); + const { ast, additionalComments, generateCode } = parseScript(content); const eslintConfigs: Array = []; imports.addDefault(ast, { from: './svelte.config.js', as: 'svelteConfig' }); @@ -85,18 +85,20 @@ export default defineAddon({ if (rules.properties[0].type !== 'Property') { throw new Error('rules.properties[0].type !== "Property"'); } - rules.properties[0].key.leadingComments = [ + additionalComments.set(rules.properties[0].key, [ { type: 'Line', value: - ' typescript-eslint strongly recommend that you do not use the no-undef lint rule on TypeScript projects.' + ' typescript-eslint strongly recommend that you do not use the no-undef lint rule on TypeScript projects.', + position: 'leading' }, { type: 'Line', value: - ' see: https://typescript-eslint.io/troubleshooting/faqs/eslint/#i-get-errors-from-the-no-undef-rule-about-global-variables-not-being-defined-even-though-there-are-no-typescript-errors' + ' see: https://typescript-eslint.io/troubleshooting/faqs/eslint/#i-get-errors-from-the-no-undef-rule-about-global-variables-not-being-defined-even-though-there-are-no-typescript-errors', + position: 'leading' } - ]; + ]); const globalsConfig = object.create({ languageOptions: { @@ -153,7 +155,9 @@ export default defineAddon({ // type annotate config if (!typescript) - common.addJsDocTypeComment(astNode, { type: "import('eslint').Linter.Config[]" }); + common.addJsDocTypeComment(astNode, additionalComments, { + type: "import('eslint').Linter.Config[]" + }); if (typescript) imports.addDefault(ast, { from: 'typescript-eslint', as: 'ts' }); imports.addDefault(ast, { from: 'globals', as: 'globals' }); diff --git a/packages/addons/paraglide/index.ts b/packages/addons/paraglide/index.ts index 02663e041..90298f38b 100644 --- a/packages/addons/paraglide/index.ts +++ b/packages/addons/paraglide/index.ts @@ -1,4 +1,3 @@ -import MagicString from 'magic-string'; import { colors, defineAddon, defineAddonOptions, log } from '@sveltejs/cli-core'; import { common, imports, variables, exports, kit as kitJs, vite } from '@sveltejs/cli-core/js'; import * as html from '@sveltejs/cli-core/html'; @@ -183,35 +182,46 @@ export default defineAddon({ // add usage example sv.file(`${kit.routesDirectory}/demo/paraglide/+page.svelte`, (content) => { - const { script, template, generateCode } = parseSvelte(content, { typescript }); - imports.addNamed(script.ast, { from: '$lib/paraglide/messages.js', imports: ['m'] }); - imports.addNamed(script.ast, { from: '$app/navigation', imports: ['goto'] }); - imports.addNamed(script.ast, { from: '$app/state', imports: ['page'] }); - imports.addNamed(script.ast, { from: '$lib/paraglide/runtime', imports: ['setLocale'] }); - - const scriptCode = new MagicString(script.generateCode()); + const { ast, generateCode } = parseSvelte(content); + + let scriptAst = ast.instance?.content; + if (!scriptAst) { + scriptAst = parseScript('').ast; + ast.instance = { + type: 'Script', + start: 0, + end: 0, + context: 'default', + attributes: [], + content: scriptAst + }; + } - const templateCode = new MagicString(template.source); + imports.addNamed(scriptAst, { imports: { m: 'm' }, from: '$lib/paraglide/messages.js' }); + imports.addNamed(scriptAst, { + imports: { + setLocale: 'setLocale' + }, + from: '$lib/paraglide/runtime' + }); // add localized message - templateCode.append("\n\n

{m.hello_world({ name: 'SvelteKit User' })}

\n"); + let templateCode = "

{m.hello_world({ name: 'SvelteKit User' })}

"; // add links to other localized pages, the first one is the default // language, thus it does not require any localized route const { validLanguageTags } = parseLanguageTagInput(options.languageTags); const links = validLanguageTags - .map( - (x) => - `${templateCode.getIndentString()}` - ) - .join('\n'); - templateCode.append(`
\n${links}\n
`); - - templateCode.append( - '

\nIf you use VSCode, install the Sherlock i18n extension for a better i18n experience.\n

' - ); + .map((x) => ``) + .join(''); + templateCode += `
${links}
`; - return generateCode({ script: scriptCode.toString(), template: templateCode.toString() }); + templateCode += + '

If you use VSCode, install the Sherlock i18n extension for a better i18n experience.

'; + + ast.fragment.nodes.push(...html.toSvelteFragment(templateCode)); + + return generateCode(); }); } diff --git a/packages/addons/sveltekit-adapter/index.ts b/packages/addons/sveltekit-adapter/index.ts index 7c12859b7..1650966f4 100644 --- a/packages/addons/sveltekit-adapter/index.ts +++ b/packages/addons/sveltekit-adapter/index.ts @@ -49,7 +49,7 @@ export default defineAddon({ sv.devDependency(adapter.package, adapter.version); sv.file('svelte.config.js', (content) => { - const { ast, generateCode } = parseScript(content); + const { ast, comments, generateCode } = parseScript(content); // finds any existing adapter's import declaration const importDecls = ast.body.filter((n) => n.type === 'ImportDeclaration'); @@ -86,8 +86,21 @@ export default defineAddon({ if (adapter.package !== '@sveltejs/adapter-auto') { const fallback = object.create({}); const cfgKitValue = object.property(config, { name: 'kit', fallback }); - const cfgAdapter = object.propertyNode(cfgKitValue, { name: 'adapter', fallback }); - cfgAdapter.leadingComments = []; + + // removes any existing adapter auto comments + const adapterAutoComments = comments.filter( + (c) => + c.loc && + cfgKitValue.loc && + c.loc.start.line >= cfgKitValue.loc.start.line && + c.loc.end.line <= cfgKitValue.loc.end.line + ); + // modify the array in place + comments.splice( + 0, + comments.length, + ...comments.filter((c) => !adapterAutoComments.includes(c)) + ); } return generateCode(); diff --git a/packages/core/package.json b/packages/core/package.json index 1138f0314..ddaeab0fa 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -34,12 +34,13 @@ "dom-serializer": "^2.0.0", "domhandler": "^5.0.3", "domutils": "^3.2.2", - "esrap": "^1.4.9", + "esrap": "https://pkg.pr.new/sveltejs/esrap@af12b38", "htmlparser2": "^9.1.0", "magic-string": "^0.30.17", "picocolors": "^1.1.1", "postcss": "^8.5.6", "silver-fleece": "^1.2.1", + "svelte": "https://pkg.pr.new/sveltejs/svelte@1377c40", "yaml": "^2.8.1", "zimmerframe": "^1.1.2" }, diff --git a/packages/core/tests/js/common/jsdoc-comment/run.ts b/packages/core/tests/js/common/jsdoc-comment/run.ts index c0b6c06f1..15d0369b9 100644 --- a/packages/core/tests/js/common/jsdoc-comment/run.ts +++ b/packages/core/tests/js/common/jsdoc-comment/run.ts @@ -1,9 +1,9 @@ -import { common, type AstTypes } from '@sveltejs/cli-core/js'; +import { common, type AdditionalCommentMap, type AstTypes } from '@sveltejs/cli-core/js'; -export function run(ast: AstTypes.Program): void { +export function run(ast: AstTypes.Program, additionalComments: AdditionalCommentMap): void { const functionDeclaration = ast.body[0] as AstTypes.FunctionDeclaration; - common.addJsDocComment(functionDeclaration, { + common.addJsDocComment(functionDeclaration, additionalComments, { params: { 'import("$lib/paraglide/runtime").AvailableLanguageTag': 'newLanguage' } }); } diff --git a/packages/core/tests/js/common/jsdoc-type-comment/output.ts b/packages/core/tests/js/common/jsdoc-type-comment/output.ts index 1aa734391..e8a715681 100644 --- a/packages/core/tests/js/common/jsdoc-type-comment/output.ts +++ b/packages/core/tests/js/common/jsdoc-type-comment/output.ts @@ -1,2 +1 @@ -/** @type {number} */ -const foo = 42; +/** @type {number} */ const foo = 42; diff --git a/packages/core/tests/js/common/jsdoc-type-comment/run.ts b/packages/core/tests/js/common/jsdoc-type-comment/run.ts index 9b5e5a065..5074afd58 100644 --- a/packages/core/tests/js/common/jsdoc-type-comment/run.ts +++ b/packages/core/tests/js/common/jsdoc-type-comment/run.ts @@ -1,13 +1,13 @@ -import { common, variables, type AstTypes } from '@sveltejs/cli-core/js'; +import { common, variables, type AdditionalCommentMap, type AstTypes } from '@sveltejs/cli-core/js'; -export function run(ast: AstTypes.Program): void { +export function run(ast: AstTypes.Program, additionalComments: AdditionalCommentMap): void { const declaration = variables.declaration(ast, { kind: 'const', name: 'foo', value: { type: 'Literal', value: 42 } }); - common.addJsDocTypeComment(declaration, { + common.addJsDocTypeComment(declaration, additionalComments, { type: 'number' }); diff --git a/packages/core/tests/js/index.ts b/packages/core/tests/js/index.ts index c7f2021e6..bc32a5c83 100644 --- a/packages/core/tests/js/index.ts +++ b/packages/core/tests/js/index.ts @@ -16,13 +16,13 @@ for (const categoryDirectory of categoryDirectories) { const inputFilePath = join(testDirectoryPath, 'input.ts'); const input = fs.existsSync(inputFilePath) ? fs.readFileSync(inputFilePath, 'utf8') : ''; - const ast = parseScript(input); + const { ast, comments, additionalComments } = parseScript(input); // dynamic imports always need to provide the path inline for static analysis const module = await import(`./${categoryDirectory}/${testName}/run.ts`); - module.run(ast); + module.run(ast, additionalComments); - let output = serializeScript(ast, input); + let output = serializeScript(ast, comments, input, additionalComments); if (!output.endsWith('\n')) output += '\n'; await expect(output).toMatchFileSnapshot(`${testDirectoryPath}/output.ts`); }); diff --git a/packages/core/tests/js/object/create/output.ts b/packages/core/tests/js/object/create/output.ts index 28ad96e4f..df190f0f4 100644 --- a/packages/core/tests/js/object/create/output.ts +++ b/packages/core/tests/js/object/create/output.ts @@ -1,15 +1,9 @@ const empty = {}; const created = { foo: 1, bar: 'string' }; -// prettier-ignore const created2 = { foo: 1, bar: 'string', object: { foo: 'hello', nested: { bar: 'world' } }, - array: [ - 123, - 'hello', - { foo: 'bar', bool: true }, - [456, '789'] - ] + array: [123, 'hello', { foo: 'bar', bool: true }, [456, '789']] }; diff --git a/packages/core/tests/js/object/create/run.ts b/packages/core/tests/js/object/create/run.ts index 8bdd272f5..5b19937e0 100644 --- a/packages/core/tests/js/object/create/run.ts +++ b/packages/core/tests/js/object/create/run.ts @@ -37,6 +37,5 @@ export function run(ast: AstTypes.Program): void { name: 'created2', value: createdObject2 }); - createdVariable2.leadingComments = [{ type: 'Line', value: ' prettier-ignore' }]; ast.body.push(createdVariable2); } diff --git a/packages/core/tests/js/object/ensure-nested-property/output.ts b/packages/core/tests/js/object/ensure-nested-property/output.ts index 08bd5fbf9..b3824d36a 100644 --- a/packages/core/tests/js/object/ensure-nested-property/output.ts +++ b/packages/core/tests/js/object/ensure-nested-property/output.ts @@ -1 +1,8 @@ -const test = { a: { /** a comment */ keep: 'you', b: { c: '007' } } }; +const test = { + a: { + /** a comment */ + keep: 'you', + + b: { c: '007' } + } +}; diff --git a/packages/core/tests/js/object/override-property/output.ts b/packages/core/tests/js/object/override-property/output.ts index fbdef76fe..987c50888 100644 --- a/packages/core/tests/js/object/override-property/output.ts +++ b/packages/core/tests/js/object/override-property/output.ts @@ -1 +1,7 @@ -const test = { /** a comment */ foo: 2, bar: 'string2', lorem: false }; +const test = { + /** a comment */ + foo: 2, + + bar: 'string2', + lorem: false +}; diff --git a/packages/core/tests/js/object/property-node/output.ts b/packages/core/tests/js/object/property-node/output.ts index 98da8dea4..3719acb91 100644 --- a/packages/core/tests/js/object/property-node/output.ts +++ b/packages/core/tests/js/object/property-node/output.ts @@ -1 +1,6 @@ -const test = { /*a comment updated*/ foo: 1, /*aka: bond, james bond*/ james: '007' }; +const test = { + /** a comment */ + foo: 1, + + james: '007' +}; diff --git a/packages/core/tests/js/vite/add-plugin-mode/output.ts b/packages/core/tests/js/vite/add-plugin-mode/output.ts index f112d5fcc..df6d4692a 100644 --- a/packages/core/tests/js/vite/add-plugin-mode/output.ts +++ b/packages/core/tests/js/vite/add-plugin-mode/output.ts @@ -7,8 +7,10 @@ import { defineConfig } from 'vite'; export default defineConfig({ plugins: [ firstPlugin(), + // a default plugin sveltekit(), + middlePlugin(), lastPlugin() ] diff --git a/packages/core/tests/js/vite/with-satisfies/output.ts b/packages/core/tests/js/vite/with-satisfies/output.ts index 4d6ed36e0..9c43348e2 100644 --- a/packages/core/tests/js/vite/with-satisfies/output.ts +++ b/packages/core/tests/js/vite/with-satisfies/output.ts @@ -18,23 +18,24 @@ const config = defineConfig({ plugins: [ // all plugins examples, + tailwindcss(), sveltekit(), kitRoutes(), myPlugin() ], + resolve: { alias: { $lib, $routes, $scripts, $actions } }, - build: { - sourcemap: true, - target: 'esnext', - cssMinify: 'lightningcss' - }, + build: { sourcemap: true, target: 'esnext', cssMinify: 'lightningcss' }, + css: { transformer: 'lightningcss', + lightningcss: { targets: browserslistToTargets(browserslist('defaults, not ie 11')) } }, + experimental: { enableNativePlugin: true } }) satisfies UserConfig; diff --git a/packages/core/tests/utils.ts b/packages/core/tests/utils.ts index 01139fbc4..88e95f125 100644 --- a/packages/core/tests/utils.ts +++ b/packages/core/tests/utils.ts @@ -4,7 +4,6 @@ import { parseScript, serializeScript, guessIndentString, - guessQuoteStyle, type AstTypes, serializeYaml, parseYaml @@ -50,57 +49,6 @@ test('guessIndentString - eight spaces', () => { expect(guessIndentString(code)).toBe(' '); }); -test('guessQuoteStyle - single simple', () => { - const code = dedent` - console.log('asd'); - `; - const ast = parseScript(code); - - expect(guessQuoteStyle(ast)).toBe('single'); -}); - -test('guessQuoteStyle - single complex', () => { - const code = dedent` - import foo from 'bar'; - - console.log("bar"); - const foobar = 'foo'; - `; - const ast = parseScript(code); - - expect(guessQuoteStyle(ast)).toBe('single'); -}); - -test('guessQuoteStyle - double simple', () => { - const code = dedent` - console.log("asd"); - `; - const ast = parseScript(code); - - expect(guessQuoteStyle(ast)).toBe('double'); -}); - -test('guessQuoteStyle - double complex', () => { - const code = dedent` - import foo from 'bar'; - - console.log("bar"); - const foobar = "foo"; - `; - const ast = parseScript(code); - - expect(guessQuoteStyle(ast)).toBe('double'); -}); - -test('guessQuoteStyle - no quotes', () => { - const code = dedent` - const foo = true; - `; - const ast = parseScript(code); - - expect(guessQuoteStyle(ast)).toBe(undefined); -}); - const newVariableDeclaration: AstTypes.VariableDeclaration = { type: 'VariableDeclaration', kind: 'const', @@ -128,20 +76,20 @@ test('integration - simple', () => { const foobar = "foo"; } `; - const ast = parseScript(code); + const { ast, comments } = parseScript(code); const method = ast.body[1] as AstTypes.FunctionDeclaration; method.body.body.push(newVariableDeclaration); // new variable is added with correct indentation and matching quotes - expect(serializeScript(ast, code)).toMatchInlineSnapshot(` + expect(serializeScript(ast, comments, code)).toMatchInlineSnapshot(` "import foo from 'bar'; function bar() { console.log("bar"); const foobar = "foo"; - const foobar2 = "test"; + const foobar2 = 'test'; }" `); }); @@ -155,13 +103,13 @@ test('integration - simple 2', () => { const foobar = 'foo'; } `; - const ast = parseScript(code); + const { ast, comments } = parseScript(code); const method = ast.body[1] as AstTypes.FunctionDeclaration; method.body.body.push(newVariableDeclaration); // new variable is added with correct indentation and matching quotes - expect(serializeScript(ast, code)).toMatchInlineSnapshot(` + expect(serializeScript(ast, comments, code)).toMatchInlineSnapshot(` "import foo from 'bar'; function bar() { @@ -178,9 +126,9 @@ test('integration - preserves comments', () => { /** @type {string} */ let foo = 'bar'; `; - const ast = parseScript(code); + const { ast, comments } = parseScript(code); - expect(serializeScript(ast, code)).toMatchInlineSnapshot(` + expect(serializeScript(ast, comments, code)).toMatchInlineSnapshot(` "/** @type {string} */ let foo = 'bar';" `); diff --git a/packages/core/tooling/html/index.ts b/packages/core/tooling/html/index.ts index 60b2ae078..e245c3bd9 100644 --- a/packages/core/tooling/html/index.ts +++ b/packages/core/tooling/html/index.ts @@ -7,9 +7,11 @@ import { parseHtml } from '../index.ts'; import { appendFromString } from '../js/common.ts'; +import { parseSvelte } from '../parsers.ts'; +import type { AST as SvelteAst } from 'svelte/compiler'; export { HtmlElement, HtmlElementType }; -export type { HtmlDocument }; +export type { HtmlDocument, SvelteAst }; export function createDiv(attributes: Record = {}): HtmlElement { return createElement('div', attributes); @@ -58,3 +60,9 @@ export function addSlot( }); addFromRawHtml(options.htmlAst.childNodes, '{@render children()}'); } + +export function toSvelteFragment(content: string): SvelteAst.Fragment['nodes'] { + // TODO write test + const { ast } = parseSvelte(content); + return ast.fragment.nodes; +} diff --git a/packages/core/tooling/index.ts b/packages/core/tooling/index.ts index 68f3dc0b4..bcc9e04a1 100644 --- a/packages/core/tooling/index.ts +++ b/packages/core/tooling/index.ts @@ -14,10 +14,14 @@ import { } from 'postcss'; import * as fleece from 'silver-fleece'; import { print as esrapPrint } from 'esrap'; +import ts, { type AdditionalComment } from 'esrap/languages/ts'; import * as acorn from 'acorn'; import { tsPlugin } from '@sveltejs/acorn-typescript'; +import { parse as svelteParse, type AST as SvelteAst, print as sveltePrint } from 'svelte/compiler'; import * as yaml from 'yaml'; +type AdditionalCommentMap = WeakMap; + export { // html Document as HtmlDocument, @@ -38,9 +42,11 @@ export { export type { // html ChildNode as HtmlChildNode, + SvelteAst, // js TsEstree as AstTypes, + AdditionalCommentMap, //css CssChildNode @@ -48,19 +54,22 @@ export type { /** * Parses as string to an AST. Code below is taken from `esrap` to ensure compatibilty. - * https://github.com/sveltejs/esrap/blob/9daf5dd43b31f17f596aa7da91678f2650666dd0/test/common.js#L12 + * https://github.com/sveltejs/esrap/blob/920491535d31484ac5fae2327c7826839d851aed/test/common.js#L14 */ -export function parseScript(content: string): TsEstree.Program { +export function parseScript(content: string): { + ast: TsEstree.Program; + comments: TsEstree.Comment[]; + additionalComments: AdditionalCommentMap; +} { const comments: TsEstree.Comment[] = []; const acornTs = acorn.Parser.extend(tsPlugin()); - // Acorn doesn't add comments to the AST by itself. This factory returns the capabilities to add them after the fact. const ast = acornTs.parse(content, { ecmaVersion: 'latest', sourceType: 'module', locations: true, - onComment: (block, value, start, end) => { + onComment: (block, value, start, end, startLoc, endLoc) => { if (block && /\n/.test(value)) { let a = start; while (a > 0 && content[a - 1] !== '\n') a -= 1; @@ -72,38 +81,33 @@ export function parseScript(content: string): TsEstree.Program { value = value.replace(new RegExp(`^${indentation}`, 'gm'), ''); } - comments.push({ type: block ? 'Block' : 'Line', value, start, end }); + comments.push({ + type: block ? 'Block' : 'Line', + value, + start, + end, + loc: { start: startLoc as TsEstree.Position, end: endLoc as TsEstree.Position } + }); } }) as TsEstree.Program; - Walker.walk(ast as TsEstree.Node, null, { - _(commentNode, { next }) { - let comment: TsEstree.Comment; - - while (comments[0] && commentNode.start && comments[0].start! < commentNode.start) { - comment = comments.shift()!; - (commentNode.leadingComments ??= []).push(comment); - } - - next(); - - if (comments[0]) { - const slice = content.slice(commentNode.end, comments[0].start); - - if (/^[,) \t]*$/.test(slice)) { - commentNode.trailingComments = [comments.shift()!]; - } - } - } - }); - - return ast; + return { + ast, + comments, + additionalComments: new WeakMap() + }; } -export function serializeScript(ast: TsEstree.Node, previousContent?: string): string { - const { code } = esrapPrint(ast, { - indent: guessIndentString(previousContent), - quotes: guessQuoteStyle(ast) +export function serializeScript( + ast: TsEstree.Node, + comments: TsEstree.Comment[], + previousContent?: string, + additionalComments?: AdditionalCommentMap +): string { + // @ts-expect-error we are still using `estree` while `esrap` is using `@typescript-eslint/types` + // which is causing these errors. But they are simmilar enough to work together. + const { code } = esrapPrint(ast, ts({ comments, additionalComments }), { + indent: guessIndentString(previousContent) }); return code; } @@ -207,39 +211,6 @@ export function guessIndentString(str: string | undefined): string { } } -export function guessQuoteStyle(ast: TsEstree.Node): 'single' | 'double' | undefined { - let singleCount = 0; - let doubleCount = 0; - - Walker.walk(ast, null, { - Literal(node) { - if (node.raw && node.raw.length >= 2) { - // we have at least two characters in the raw string that could represent both quotes - const quotes = [node.raw[0], node.raw[node.raw.length - 1]]; - for (const quote of quotes) { - switch (quote) { - case "'": - singleCount++; - break; - case '"': - doubleCount++; - break; - default: - break; - } - } - } - } - }); - - if (singleCount === 0 && doubleCount === 0) { - // new file or file without any quotes - return undefined; - } - - return singleCount > doubleCount ? 'single' : 'double'; -} - export function parseYaml(content: string): ReturnType { return yaml.parseDocument(content); } @@ -247,3 +218,11 @@ export function parseYaml(content: string): ReturnType): string { return yaml.stringify(data, { singleQuote: true }); } + +export function parseSvelte(content: string): SvelteAst.Root { + return svelteParse(content, { modern: true }); +} + +export function serializeSvelte(ast: SvelteAst.Root): string { + return sveltePrint(ast).code; +} diff --git a/packages/core/tooling/js/common.ts b/packages/core/tooling/js/common.ts index 8812660e2..1f51dcf6a 100644 --- a/packages/core/tooling/js/common.ts +++ b/packages/core/tooling/js/common.ts @@ -1,18 +1,30 @@ -import { type AstTypes, Walker, parseScript, serializeScript, stripAst } from '../index.ts'; +import { + type AdditionalCommentMap, + type AstTypes, + Walker, + parseScript, + serializeScript, + stripAst +} from '../index.ts'; import decircular from 'decircular'; import dedent from 'dedent'; -export function addJsDocTypeComment(node: AstTypes.Node, options: { type: string }): void { +export function addJsDocTypeComment( + node: AstTypes.Node, + additionalComments: AdditionalCommentMap, + options: { type: string } +): void { const comment: AstTypes.Comment = { type: 'Block', value: `* @type {${options.type}} ` }; - addComment(node, comment); + addComment(node, additionalComments, comment); } export function addJsDocComment( node: AstTypes.Node, + additionalComments: AdditionalCommentMap, options: { params: Record } ): void { const commentLines: string[] = []; @@ -25,16 +37,23 @@ export function addJsDocComment( value: `*\n * ${commentLines.join('\n * ')}\n ` }; - addComment(node, comment); + addComment(node, additionalComments, comment); } -function addComment(node: AstTypes.Node, comment: AstTypes.Comment) { - node.leadingComments ??= []; - - const found = node.leadingComments.find( - (item) => item.type === 'Block' && item.value === comment.value - ); - if (!found) node.leadingComments.push(comment); +function addComment( + node: AstTypes.Node, + additionalComments: AdditionalCommentMap, + comment: AstTypes.Comment +) { + const found = additionalComments + .get(node) + ?.find((item) => item.type === 'Block' && item.value === comment.value); + + if (!found) { + const comments = additionalComments.get(node) ?? []; + comments.push({ ...comment, position: 'leading' }); + additionalComments.set(node, comments); + } } export function typeAnnotate( @@ -93,7 +112,7 @@ export function areNodesEqual(node: AstTypes.Node, otherNode: AstTypes.Node): bo const nodeClone = stripAst(decircular(node), ['loc', 'raw']); const otherNodeClone = stripAst(decircular(otherNode), ['loc', 'raw']); - return serializeScript(nodeClone) === serializeScript(otherNodeClone); + return serializeScript(nodeClone, []) === serializeScript(otherNodeClone, []); } export function createBlockStatement(): AstTypes.BlockStatement { @@ -118,18 +137,18 @@ export function appendFromString( node: AstTypes.BlockStatement | AstTypes.Program, options: { code: string } ): void { - const program = parseScript(dedent(options.code)); + const { ast } = parseScript(dedent(options.code)); - for (const childNode of program.body) { + for (const childNode of ast.body) { // @ts-expect-error node.body.push(childNode); } } export function parseExpression(code: string): AstTypes.Expression { - const program = parseScript(dedent(code)); - stripAst(program, ['raw']); - const statement = program.body[0]!; + const { ast } = parseScript(dedent(code)); + stripAst(ast, ['raw']); + const statement = ast.body[0]!; if (statement.type !== 'ExpressionStatement') { throw new Error('Code provided was not an expression'); } @@ -142,8 +161,8 @@ export function parseStatement(code: string): AstTypes.Statement { } export function parseFromString(code: string): T { - const program = parseScript(dedent(code)); - const statement = program.body[0]!; + const { ast } = parseScript(dedent(code)); + const statement = ast.body[0]!; return statement as T; } diff --git a/packages/core/tooling/js/index.ts b/packages/core/tooling/js/index.ts index 0b4c6e632..206d49d5a 100644 --- a/packages/core/tooling/js/index.ts +++ b/packages/core/tooling/js/index.ts @@ -7,4 +7,4 @@ export * as variables from './variables.ts'; export * as exports from './exports.ts'; export * as kit from './kit.ts'; export * as vite from './vite.ts'; -export type { AstTypes } from '../index.ts'; +export type { AstTypes, AdditionalCommentMap } from '../index.ts'; diff --git a/packages/core/tooling/parsers.ts b/packages/core/tooling/parsers.ts index 21b6b0993..b030a16b5 100644 --- a/packages/core/tooling/parsers.ts +++ b/packages/core/tooling/parsers.ts @@ -1,16 +1,19 @@ import * as utils from './index.ts'; -import MagicString from 'magic-string'; type ParseBase = { source: string; generateCode(): string; }; -export function parseScript(source: string): { ast: utils.AstTypes.Program } & ParseBase { - const ast = utils.parseScript(source); - const generateCode = () => utils.serializeScript(ast, source); +export function parseScript(source: string): { + ast: utils.AstTypes.Program; + comments: utils.AstTypes.Comment[]; + additionalComments: utils.AdditionalCommentMap; +} & ParseBase { + const { ast, comments, additionalComments } = utils.parseScript(source); + const generateCode = () => utils.serializeScript(ast, comments, source, additionalComments); - return { ast, source, generateCode }; + return { ast, comments, additionalComments, source, generateCode }; } export function parseCss(source: string): { ast: utils.CssAst } & ParseBase { @@ -45,136 +48,13 @@ export function parseYaml( return { data, source, generateCode }; } -type SvelteGenerator = (code: { - script?: string; - module?: string; - css?: string; - template?: string; -}) => string; -export function parseSvelte( - source: string, - options?: { typescript?: boolean } -): { - script: ReturnType; - module: ReturnType; - css: ReturnType; - template: ReturnType; - generateCode: SvelteGenerator; -} { - // `xTag` captures the whole tag block (ex: ) - // `xSource` is the contents within the tags - const scripts = extractScripts(source); - // instance block - const { tag: scriptTag = '', src: scriptSource = '' } = - scripts.find(({ attrs }) => !attrs.includes('module')) ?? {}; - // module block - const { tag: moduleScriptTag = '', src: moduleSource = '' } = - scripts.find(({ attrs }) => attrs.includes('module')) ?? {}; - // style block - const { styleTag, cssSource } = extractStyle(source); - // rest of the template - // TODO: needs more testing - const templateSource = source - .replace(moduleScriptTag, '') - .replace(scriptTag, '') - .replace(styleTag, '') - .trim(); - - const script = parseScript(scriptSource); - const module = parseScript(moduleSource); - const css = parseCss(cssSource); - const template = parseHtml(templateSource); - - const generateCode: SvelteGenerator = (code) => { - const ms = new MagicString(source); - // TODO: this is imperfect and needs adjustments - if (code.script !== undefined) { - if (scriptSource.length === 0) { - const ts = options?.typescript ? ' lang="ts"' : ''; - const indented = code.script.split('\n').join('\n\t'); - const script = `\n\t${indented}\n\n\n`; - ms.prepend(script); - } else { - const { start, end } = locations(source, scriptSource); - const formatted = indent(code.script, ms.getIndentString()); - ms.update(start, end, formatted); - } - } - if (code.module !== undefined) { - if (moduleSource.length === 0) { - const ts = options?.typescript ? ' lang="ts"' : ''; - const indented = code.module.split('\n').join('\n\t'); - // TODO: make a svelte 5 variant - const module = `\n\t${indented}\n\n\n`; - ms.prepend(module); - } else { - const { start, end } = locations(source, moduleSource); - const formatted = indent(code.module, ms.getIndentString()); - ms.update(start, end, formatted); - } - } - if (code.css !== undefined) { - if (cssSource.length === 0) { - const indented = code.css.split('\n').join('\n\t'); - const style = `\n\n`; - ms.append(style); - } else { - const { start, end } = locations(source, cssSource); - const formatted = indent(code.css, ms.getIndentString()); - ms.update(start, end, formatted); - } - } - if (code.template !== undefined) { - if (templateSource.length === 0) { - ms.appendLeft(0, code.template); - } else { - const { start, end } = locations(source, templateSource); - ms.update(start, end, code.template); - } - } - return ms.toString(); - }; +export function parseSvelte(source: string): { ast: utils.SvelteAst.Root } & ParseBase { + const ast = utils.parseSvelte(source); + const generateCode = () => utils.serializeSvelte(ast); return { - script: { ...script, source: scriptSource }, - module: { ...module, source: moduleSource }, - css: { ...css, source: cssSource }, - template: { ...template, source: templateSource }, + ast, + source, generateCode }; } - -function locations(source: string, search: string): { start: number; end: number } { - const start = source.indexOf(search); - const end = start + search.length; - return { start, end }; -} - -function indent(content: string, indent: string): string { - const indented = indent + content.split('\n').join(`\n${indent}`); - return `\n${indented}\n`; -} - -// sourced from Svelte: https://github.com/sveltejs/svelte/blob/0d3d5a2a85c0f9eccb2c8dbbecc0532ec918b157/packages/svelte/src/compiler/preprocess/index.js#L253-L256 -const regexScriptTags = - /|'"/\s]+=(?:"[^"]*"|'[^']*'|[^>\s]+)|\s+[^=>'"/\s]+)*\s*)(?:\/>|>([\S\s]*?)<\/script>)/; -const regexStyleTags = - /|'"/\s]+=(?:"[^"]*"|'[^']*'|[^>\s]+)|\s+[^=>'"/\s]+)*\s*)(?:\/>|>([\S\s]*?)<\/style>)/; - -type Script = { tag: string; attrs: string; src: string }; -function extractScripts(source: string): Script[] { - const scripts = []; - const [tag = '', attrs = '', src = ''] = regexScriptTags.exec(source) ?? []; - if (tag) { - const stripped = source.replace(tag, ''); - scripts.push({ tag, attrs, src }, ...extractScripts(stripped)); - return scripts; - } - - return []; -} - -function extractStyle(source: string) { - const [styleTag = '', attributes = '', cssSource = ''] = regexStyleTags.exec(source) ?? []; - return { styleTag, attributes, cssSource }; -} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9bc730637..9192faee6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -167,8 +167,8 @@ importers: specifier: ^3.2.2 version: 3.2.2 esrap: - specifier: ^1.4.9 - version: 1.4.9 + specifier: https://pkg.pr.new/sveltejs/esrap@af12b38 + version: https://pkg.pr.new/sveltejs/esrap@af12b38 htmlparser2: specifier: ^9.1.0 version: 9.1.0 @@ -184,6 +184,9 @@ importers: silver-fleece: specifier: ^1.2.1 version: 1.2.1 + svelte: + specifier: https://pkg.pr.new/sveltejs/svelte@1377c40 + version: https://pkg.pr.new/sveltejs/svelte@1377c40 yaml: specifier: ^2.8.1 version: 2.8.1 @@ -600,8 +603,8 @@ packages: '@manypkg/get-packages@1.1.3': resolution: {integrity: sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A==} - '@napi-rs/wasm-runtime@1.0.5': - resolution: {integrity: sha512-TBr9Cf9onSAS2LQ2+QHx6XcC6h9+RIzJgbqG3++9TUZSH204AwEy5jg3BTQ0VATsyoGj4ee49tN/y6rvaOOtcg==} + '@napi-rs/wasm-runtime@1.0.7': + resolution: {integrity: sha512-SeDnOO0Tk7Okiq6DbXmmBODgOAb9dp9gjlphokTUxmt8U3liIP1ZsozBahH69j/RJv+Rfs6IwUKHTgQYJ/HBAw==} '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} @@ -615,8 +618,8 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} - '@oxc-project/types@0.93.0': - resolution: {integrity: sha512-yNtwmWZIBtJsMr5TEfoZFDxIWV6OdScOpza/f5YxbqUMJk+j6QX3Cf3jgZShGEFYWQJ5j9mJ6jM0tZHu2J9Yrg==} + '@oxc-project/types@0.95.0': + resolution: {integrity: sha512-vACy7vhpMPhjEJhULNxrdR0D943TkA/MigMpJCHmBHvMXxRStRi/dPtTlfQ3uDwWSzRpT8z+7ImjZVf8JWBocQ==} '@pkgjs/parseargs@0.11.0': resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} @@ -637,91 +640,91 @@ packages: '@quansync/fs@0.1.5': resolution: {integrity: sha512-lNS9hL2aS2NZgNW7BBj+6EBl4rOf8l+tQ0eRY6JWCI8jI2kc53gSoqbjojU0OnAWhzoXiOjFyGsHcDGePB3lhA==} - '@rolldown/binding-android-arm64@1.0.0-beta.41': - resolution: {integrity: sha512-Edflndd9lU7JVhVIvJlZhdCj5DkhYDJPIRn4Dx0RUdfc8asP9xHOI5gMd8MesDDx+BJpdIT/uAmVTearteU/mQ==} + '@rolldown/binding-android-arm64@1.0.0-beta.44': + resolution: {integrity: sha512-g9ejDOehJFhxC1DIXQuZQ9bKv4lRDioOTL42cJjFjqKPl1L7DVb9QQQE1FxokGEIMr6FezLipxwnzOXWe7DNPg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [android] - '@rolldown/binding-darwin-arm64@1.0.0-beta.41': - resolution: {integrity: sha512-XGCzqfjdk7550PlyZRTBKbypXrB7ATtXhw/+bjtxnklLQs0mKP/XkQVOKyn9qGKSlvH8I56JLYryVxl0PCvSNw==} + '@rolldown/binding-darwin-arm64@1.0.0-beta.44': + resolution: {integrity: sha512-PxAW1PXLPmCzfhfKIS53kwpjLGTUdIfX4Ht+l9mj05C3lYCGaGowcNsYi2rdxWH24vSTmeK+ajDNRmmmrK0M7g==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] - '@rolldown/binding-darwin-x64@1.0.0-beta.41': - resolution: {integrity: sha512-Ho6lIwGJed98zub7n0xcRKuEtnZgbxevAmO4x3zn3C3N4GVXZD5xvCvTVxSMoeBJwTcIYzkVDRTIhylQNsTgLQ==} + '@rolldown/binding-darwin-x64@1.0.0-beta.44': + resolution: {integrity: sha512-/CtQqs1oO9uSb5Ju60rZvsdjE7Pzn8EK2ISAdl2jedjMzeD/4neNyCbwyJOAPzU+GIQTZVyrFZJX+t7HXR1R/g==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] - '@rolldown/binding-freebsd-x64@1.0.0-beta.41': - resolution: {integrity: sha512-ijAZETywvL+gACjbT4zBnCp5ez1JhTRs6OxRN4J+D6AzDRbU2zb01Esl51RP5/8ZOlvB37xxsRQ3X4YRVyYb3g==} + '@rolldown/binding-freebsd-x64@1.0.0-beta.44': + resolution: {integrity: sha512-V5Q5W9c4+2GJ4QabmjmVV6alY97zhC/MZBaLkDtHwGy3qwzbM4DYgXUbun/0a8AH5hGhuU27tUIlYz6ZBlvgOA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [freebsd] - '@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.41': - resolution: {integrity: sha512-EgIOZt7UildXKFEFvaiLNBXm+4ggQyGe3E5Z1QP9uRcJJs9omihOnm897FwOBQdCuMvI49iBgjFrkhH+wMJ2MA==} + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.44': + resolution: {integrity: sha512-X6adjkHeFqKsTU0FXdNN9HY4LDozPqIfHcnXovE5RkYLWIjMWuc489mIZ6iyhrMbCqMUla9IOsh5dvXSGT9o9A==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] - '@rolldown/binding-linux-arm64-gnu@1.0.0-beta.41': - resolution: {integrity: sha512-F8bUwJq8v/JAU8HSwgF4dztoqJ+FjdyjuvX4//3+Fbe2we9UktFeZ27U4lRMXF1vxWtdV4ey6oCSqI7yUrSEeg==} + '@rolldown/binding-linux-arm64-gnu@1.0.0-beta.44': + resolution: {integrity: sha512-kRRKGZI4DXWa6ANFr3dLA85aSVkwPdgXaRjfanwY84tfc3LncDiIjyWCb042e3ckPzYhHSZ3LmisO+cdOIYL6Q==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] - '@rolldown/binding-linux-arm64-musl@1.0.0-beta.41': - resolution: {integrity: sha512-MioXcCIX/wB1pBnBoJx8q4OGucUAfC1+/X1ilKFsjDK05VwbLZGRgOVD5OJJpUQPK86DhQciNBrfOKDiatxNmg==} + '@rolldown/binding-linux-arm64-musl@1.0.0-beta.44': + resolution: {integrity: sha512-hMtiN9xX1NhxXBa2U3Up4XkVcsVp2h73yYtMDY59z9CDLEZLrik9RVLhBL5QtoX4zZKJ8HZKJtWuGYvtmkCbIQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] - '@rolldown/binding-linux-x64-gnu@1.0.0-beta.41': - resolution: {integrity: sha512-m66M61fizvRCwt5pOEiZQMiwBL9/y0bwU/+Kc4Ce/Pef6YfoEkR28y+DzN9rMdjo8Z28NXjsDPq9nH4mXnAP0g==} + '@rolldown/binding-linux-x64-gnu@1.0.0-beta.44': + resolution: {integrity: sha512-rd1LzbpXQuR8MTG43JB9VyXDjG7ogSJbIkBpZEHJ8oMKzL6j47kQT5BpIXrg3b5UVygW9QCI2fpFdMocT5Kudg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] - '@rolldown/binding-linux-x64-musl@1.0.0-beta.41': - resolution: {integrity: sha512-yRxlSfBvWnnfrdtJfvi9lg8xfG5mPuyoSHm0X01oiE8ArmLRvoJGHUTJydCYz+wbK2esbq5J4B4Tq9WAsOlP1Q==} + '@rolldown/binding-linux-x64-musl@1.0.0-beta.44': + resolution: {integrity: sha512-qI2IiPqmPRW25exXkuQr3TlweCDc05YvvbSDRPCuPsWkwb70dTiSoXn8iFxT4PWqTi71wWHg1Wyta9PlVhX5VA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] - '@rolldown/binding-openharmony-arm64@1.0.0-beta.41': - resolution: {integrity: sha512-PHVxYhBpi8UViS3/hcvQQb9RFqCtvFmFU1PvUoTRiUdBtgHA6fONNHU4x796lgzNlVSD3DO/MZNk1s5/ozSMQg==} + '@rolldown/binding-openharmony-arm64@1.0.0-beta.44': + resolution: {integrity: sha512-+vHvEc1pL5iJRFlldLC8mjm6P4Qciyfh2bh5ZI6yxDQKbYhCHRKNURaKz1mFcwxhVL5YMYsLyaqM3qizVif9MQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] - '@rolldown/binding-wasm32-wasi@1.0.0-beta.41': - resolution: {integrity: sha512-OAfcO37ME6GGWmj9qTaDT7jY4rM0T2z0/8ujdQIJQ2x2nl+ztO32EIwURfmXOK0U1tzkyuaKYvE34Pug/ucXlQ==} + '@rolldown/binding-wasm32-wasi@1.0.0-beta.44': + resolution: {integrity: sha512-XSgLxRrtFj6RpTeMYmmQDAwHjKseYGKUn5LPiIdW4Cq+f5SBSStL2ToBDxkbdxKPEbCZptnLPQ/nfKcAxrC8Xg==} engines: {node: '>=14.0.0'} cpu: [wasm32] - '@rolldown/binding-win32-arm64-msvc@1.0.0-beta.41': - resolution: {integrity: sha512-NIYGuCcuXaq5BC4Q3upbiMBvmZsTsEPG9k/8QKQdmrch+ocSy5Jv9tdpdmXJyighKqm182nh/zBt+tSJkYoNlg==} + '@rolldown/binding-win32-arm64-msvc@1.0.0-beta.44': + resolution: {integrity: sha512-cF1LJdDIX02cJrFrX3wwQ6IzFM7I74BYeKFkzdcIA4QZ0+2WA7/NsKIgjvrunupepWb1Y6PFWdRlHSaz5AW1Wg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [win32] - '@rolldown/binding-win32-ia32-msvc@1.0.0-beta.41': - resolution: {integrity: sha512-kANdsDbE5FkEOb5NrCGBJBCaZ2Sabp3D7d4PRqMYJqyLljwh9mDyYyYSv5+QNvdAmifj+f3lviNEUUuUZPEFPw==} + '@rolldown/binding-win32-ia32-msvc@1.0.0-beta.44': + resolution: {integrity: sha512-5uaJonDafhHiMn+iEh7qUp3QQ4Gihv3lEOxKfN8Vwadpy0e+5o28DWI42DpJ9YBYMrVy4JOWJ/3etB/sptpUwA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ia32] os: [win32] - '@rolldown/binding-win32-x64-msvc@1.0.0-beta.41': - resolution: {integrity: sha512-UlpxKmFdik0Y2VjZrgUCgoYArZJiZllXgIipdBRV1hw6uK45UbQabSTW6Kp6enuOu7vouYWftwhuxfpE8J2JAg==} + '@rolldown/binding-win32-x64-msvc@1.0.0-beta.44': + resolution: {integrity: sha512-vsqhWAFJkkmgfBN/lkLCWTXF1PuPhMjfnAyru48KvF7mVh2+K7WkKYHezF3Fjz4X/mPScOcIv+g6cf6wnI6eWg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] - '@rolldown/pluginutils@1.0.0-beta.41': - resolution: {integrity: sha512-ycMEPrS3StOIeb87BT3/+bu+blEtyvwQ4zmo2IcJQy0Rd1DAAhKksA0iUZ3MYSpJtjlPhg0Eo6mvVS6ggPhRbw==} + '@rolldown/pluginutils@1.0.0-beta.44': + resolution: {integrity: sha512-g6eW7Zwnr2c5RADIoqziHoVs6b3W5QTQ4+qbpfjbkMJ9x+8Og211VW/oot2dj9dVwaK/UyC6Yo+02gV+wWQVNg==} '@rollup/rollup-android-arm-eabi@4.46.2': resolution: {integrity: sha512-Zj3Hl6sN34xJtMv7Anwb5Gu01yujyE/cLBDB2gnHTAHaWS1Z38L7kuSG+oAh0giZMqG060f/YBStXtMH6FvPMA==} @@ -1339,6 +1342,13 @@ packages: esrap@1.4.9: resolution: {integrity: sha512-3OMlcd0a03UGuZpPeUC1HxR3nA23l+HEyCiZw3b3FumJIN9KphoGzDJKMXI1S72jVS1dsenDyQC0kJlO1U9E1g==} + esrap@2.1.0: + resolution: {integrity: sha512-yzmPNpl7TBbMRC5Lj2JlJZNPml0tzqoqP5B1JXycNUwtqma9AKCO0M2wHrdgsHcy1WRW7S9rJknAMtByg3usgA==} + + esrap@https://pkg.pr.new/sveltejs/esrap@af12b38: + resolution: {tarball: https://pkg.pr.new/sveltejs/esrap@af12b38} + version: 2.1.0 + esrecurse@4.3.0: resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} engines: {node: '>=4.0'} @@ -1928,8 +1938,8 @@ packages: vue-tsc: optional: true - rolldown@1.0.0-beta.41: - resolution: {integrity: sha512-U+NPR0Bkg3wm61dteD2L4nAM1U9dtaqVrpDXwC36IKRHpEO/Ubpid4Nijpa2imPchcVNHfxVFwSSMJdwdGFUbg==} + rolldown@1.0.0-beta.44: + resolution: {integrity: sha512-gcqgyCi3g93Fhr49PKvymE8PoaGS0sf6ajQrsYaQ8o5de6aUEbD6rJZiJbhOfpcqOnycgsAsUNPYri1h25NgsQ==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true @@ -2056,6 +2066,11 @@ packages: resolution: {integrity: sha512-5PEg+QQKce4t1qiOtVUhUS3AQRTtxJyGBTpxLcNWnr0Ve8q4r06bMo0Gv8uhtCPWlztZHoi3Ye7elLhu+PCTMg==} engines: {node: '>=18'} + svelte@https://pkg.pr.new/sveltejs/svelte@1377c40: + resolution: {tarball: https://pkg.pr.new/sveltejs/svelte@1377c40} + version: 5.34.9 + engines: {node: '>=18'} + synckit@0.11.8: resolution: {integrity: sha512-+XZ+r1XGIJGeQk3VvXhT6xx/VpbHsRzsTkGgF6E5RX9TTXD0118l87puaEBZ566FhqblC6U0d4XnubznJDm30A==} engines: {node: ^14.18.0 || >=16.0.0} @@ -2697,7 +2712,7 @@ snapshots: globby: 11.1.0 read-yaml-file: 1.1.0 - '@napi-rs/wasm-runtime@1.0.5': + '@napi-rs/wasm-runtime@1.0.7': dependencies: '@emnapi/core': 1.5.0 '@emnapi/runtime': 1.5.0 @@ -2716,7 +2731,7 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.19.1 - '@oxc-project/types@0.93.0': {} + '@oxc-project/types@0.95.0': {} '@pkgjs/parseargs@0.11.0': optional: true @@ -2733,51 +2748,51 @@ snapshots: dependencies: quansync: 0.2.11 - '@rolldown/binding-android-arm64@1.0.0-beta.41': + '@rolldown/binding-android-arm64@1.0.0-beta.44': optional: true - '@rolldown/binding-darwin-arm64@1.0.0-beta.41': + '@rolldown/binding-darwin-arm64@1.0.0-beta.44': optional: true - '@rolldown/binding-darwin-x64@1.0.0-beta.41': + '@rolldown/binding-darwin-x64@1.0.0-beta.44': optional: true - '@rolldown/binding-freebsd-x64@1.0.0-beta.41': + '@rolldown/binding-freebsd-x64@1.0.0-beta.44': optional: true - '@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.41': + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.44': optional: true - '@rolldown/binding-linux-arm64-gnu@1.0.0-beta.41': + '@rolldown/binding-linux-arm64-gnu@1.0.0-beta.44': optional: true - '@rolldown/binding-linux-arm64-musl@1.0.0-beta.41': + '@rolldown/binding-linux-arm64-musl@1.0.0-beta.44': optional: true - '@rolldown/binding-linux-x64-gnu@1.0.0-beta.41': + '@rolldown/binding-linux-x64-gnu@1.0.0-beta.44': optional: true - '@rolldown/binding-linux-x64-musl@1.0.0-beta.41': + '@rolldown/binding-linux-x64-musl@1.0.0-beta.44': optional: true - '@rolldown/binding-openharmony-arm64@1.0.0-beta.41': + '@rolldown/binding-openharmony-arm64@1.0.0-beta.44': optional: true - '@rolldown/binding-wasm32-wasi@1.0.0-beta.41': + '@rolldown/binding-wasm32-wasi@1.0.0-beta.44': dependencies: - '@napi-rs/wasm-runtime': 1.0.5 + '@napi-rs/wasm-runtime': 1.0.7 optional: true - '@rolldown/binding-win32-arm64-msvc@1.0.0-beta.41': + '@rolldown/binding-win32-arm64-msvc@1.0.0-beta.44': optional: true - '@rolldown/binding-win32-ia32-msvc@1.0.0-beta.41': + '@rolldown/binding-win32-ia32-msvc@1.0.0-beta.44': optional: true - '@rolldown/binding-win32-x64-msvc@1.0.0-beta.41': + '@rolldown/binding-win32-x64-msvc@1.0.0-beta.44': optional: true - '@rolldown/pluginutils@1.0.0-beta.41': {} + '@rolldown/pluginutils@1.0.0-beta.44': {} '@rollup/rollup-android-arm-eabi@4.46.2': optional: true @@ -3398,6 +3413,14 @@ snapshots: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 + esrap@2.1.0: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + + esrap@https://pkg.pr.new/sveltejs/esrap@af12b38: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + esrecurse@4.3.0: dependencies: estraverse: 5.3.0 @@ -3874,7 +3897,7 @@ snapshots: reusify@1.1.0: {} - rolldown-plugin-dts@0.16.9(rolldown@1.0.0-beta.41)(typescript@5.8.3): + rolldown-plugin-dts@0.16.9(rolldown@1.0.0-beta.44)(typescript@5.8.3): dependencies: '@babel/generator': 7.28.3 '@babel/parser': 7.28.4 @@ -3885,33 +3908,32 @@ snapshots: dts-resolver: 2.1.2 get-tsconfig: 4.10.1 magic-string: 0.30.19 - rolldown: 1.0.0-beta.41 + rolldown: 1.0.0-beta.44 optionalDependencies: typescript: 5.8.3 transitivePeerDependencies: - oxc-resolver - supports-color - rolldown@1.0.0-beta.41: + rolldown@1.0.0-beta.44: dependencies: - '@oxc-project/types': 0.93.0 - '@rolldown/pluginutils': 1.0.0-beta.41 - ansis: 4.2.0 + '@oxc-project/types': 0.95.0 + '@rolldown/pluginutils': 1.0.0-beta.44 optionalDependencies: - '@rolldown/binding-android-arm64': 1.0.0-beta.41 - '@rolldown/binding-darwin-arm64': 1.0.0-beta.41 - '@rolldown/binding-darwin-x64': 1.0.0-beta.41 - '@rolldown/binding-freebsd-x64': 1.0.0-beta.41 - '@rolldown/binding-linux-arm-gnueabihf': 1.0.0-beta.41 - '@rolldown/binding-linux-arm64-gnu': 1.0.0-beta.41 - '@rolldown/binding-linux-arm64-musl': 1.0.0-beta.41 - '@rolldown/binding-linux-x64-gnu': 1.0.0-beta.41 - '@rolldown/binding-linux-x64-musl': 1.0.0-beta.41 - '@rolldown/binding-openharmony-arm64': 1.0.0-beta.41 - '@rolldown/binding-wasm32-wasi': 1.0.0-beta.41 - '@rolldown/binding-win32-arm64-msvc': 1.0.0-beta.41 - '@rolldown/binding-win32-ia32-msvc': 1.0.0-beta.41 - '@rolldown/binding-win32-x64-msvc': 1.0.0-beta.41 + '@rolldown/binding-android-arm64': 1.0.0-beta.44 + '@rolldown/binding-darwin-arm64': 1.0.0-beta.44 + '@rolldown/binding-darwin-x64': 1.0.0-beta.44 + '@rolldown/binding-freebsd-x64': 1.0.0-beta.44 + '@rolldown/binding-linux-arm-gnueabihf': 1.0.0-beta.44 + '@rolldown/binding-linux-arm64-gnu': 1.0.0-beta.44 + '@rolldown/binding-linux-arm64-musl': 1.0.0-beta.44 + '@rolldown/binding-linux-x64-gnu': 1.0.0-beta.44 + '@rolldown/binding-linux-x64-musl': 1.0.0-beta.44 + '@rolldown/binding-openharmony-arm64': 1.0.0-beta.44 + '@rolldown/binding-wasm32-wasi': 1.0.0-beta.44 + '@rolldown/binding-win32-arm64-msvc': 1.0.0-beta.44 + '@rolldown/binding-win32-ia32-msvc': 1.0.0-beta.44 + '@rolldown/binding-win32-x64-msvc': 1.0.0-beta.44 rollup@4.46.2: dependencies: @@ -4072,6 +4094,23 @@ snapshots: magic-string: 0.30.19 zimmerframe: 1.1.2 + svelte@https://pkg.pr.new/sveltejs/svelte@1377c40: + dependencies: + '@ampproject/remapping': 2.3.0 + '@jridgewell/sourcemap-codec': 1.5.5 + '@sveltejs/acorn-typescript': 1.0.5(acorn@8.15.0) + '@types/estree': 1.0.8 + acorn: 8.15.0 + aria-query: 5.3.2 + axobject-query: 4.1.0 + clsx: 2.1.1 + esm-env: 1.2.2 + esrap: 2.1.0 + is-reference: 3.0.3 + locate-character: 3.0.0 + magic-string: 0.30.19 + zimmerframe: 1.1.2 + synckit@0.11.8: dependencies: '@pkgr/core': 0.2.7 @@ -4144,8 +4183,8 @@ snapshots: diff: 8.0.2 empathic: 2.0.0 hookable: 5.5.3 - rolldown: 1.0.0-beta.41 - rolldown-plugin-dts: 0.16.9(rolldown@1.0.0-beta.41)(typescript@5.8.3) + rolldown: 1.0.0-beta.44 + rolldown-plugin-dts: 0.16.9(rolldown@1.0.0-beta.44)(typescript@5.8.3) semver: 7.7.2 tinyexec: 1.0.1 tinyglobby: 0.2.15