From d77082bcfea1b1c220d06aae7f88395b2a6d93a0 Mon Sep 17 00:00:00 2001 From: Stanislav Khromov Date: Mon, 15 Jun 2026 01:01:26 +0200 Subject: [PATCH] feat: add customNamespaces option to exempt namespaced attributes from type validation Frameworks built on top of Svelte attach custom namespaced attributes (e.g. ) which previously caused "Type 'true' is not assignable to type 'never'" errors. Adds a configurable, opt-in customNamespaces option: - svelte2tsx: new customNamespaces?: string[] option, honored in both the element (addAttribute) and component (addProp) branches via the existing __sveltets_2_empty wrapper so value expressions stay type-checked. - svelte-check (CLI) and language server (editor) both read it from svelte.config.js, keeping CLI and editor in lockstep. Includes svelte2tsx fixtures, language-server diagnostics tests, README docs, and a changeset. --- .changeset/custom-namespaces.md | 18 ++++++++++ .../src/lib/documents/configLoader.ts | 6 ++++ .../plugins/typescript/DocumentSnapshot.ts | 3 +- .../custom-namespaces-disabled/Counter.svelte | 5 +++ .../expectedv2.json | 10 ++++++ .../custom-namespaces-disabled/input.svelte | 7 ++++ .../Counter.svelte | 5 +++ .../expectedv2.json | 10 ++++++ .../input.svelte | 7 ++++ .../svelte.config.js | 3 ++ .../fixtures/custom-namespaces/Counter.svelte | 5 +++ .../custom-namespaces/expectedv2.json | 1 + .../fixtures/custom-namespaces/input.svelte | 13 +++++++ .../custom-namespaces/svelte.config.js | 3 ++ packages/svelte-check/README.md | 32 +++++++++++++++++ packages/svelte-check/src/incremental.ts | 36 ++++++++++++++----- packages/svelte2tsx/index.d.ts | 9 +++++ .../svelte2tsx/src/htmlxtojsx_v2/index.ts | 5 ++- .../src/htmlxtojsx_v2/nodes/Attribute.ts | 35 +++++++++++++++++- packages/svelte2tsx/src/svelte2tsx/index.ts | 16 ++++++++- packages/svelte2tsx/test/helpers.ts | 4 ++- .../custom-namespaces-disabled/expectedv2.ts | 22 ++++++++++++ .../custom-namespaces-disabled/input.svelte | 14 ++++++++ .../samples/custom-namespaces/config.json | 3 ++ .../samples/custom-namespaces/expectedv2.ts | 23 ++++++++++++ .../samples/custom-namespaces/input.svelte | 14 ++++++++ 26 files changed, 295 insertions(+), 14 deletions(-) create mode 100644 .changeset/custom-namespaces.md create mode 100644 packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/custom-namespaces-disabled/Counter.svelte create mode 100644 packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/custom-namespaces-disabled/expectedv2.json create mode 100644 packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/custom-namespaces-disabled/input.svelte create mode 100644 packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/custom-namespaces-value-checked/Counter.svelte create mode 100644 packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/custom-namespaces-value-checked/expectedv2.json create mode 100644 packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/custom-namespaces-value-checked/input.svelte create mode 100644 packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/custom-namespaces-value-checked/svelte.config.js create mode 100644 packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/custom-namespaces/Counter.svelte create mode 100644 packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/custom-namespaces/expectedv2.json create mode 100644 packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/custom-namespaces/input.svelte create mode 100644 packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/custom-namespaces/svelte.config.js create mode 100644 packages/svelte2tsx/test/svelte2tsx/samples/custom-namespaces-disabled/expectedv2.ts create mode 100644 packages/svelte2tsx/test/svelte2tsx/samples/custom-namespaces-disabled/input.svelte create mode 100644 packages/svelte2tsx/test/svelte2tsx/samples/custom-namespaces/config.json create mode 100644 packages/svelte2tsx/test/svelte2tsx/samples/custom-namespaces/expectedv2.ts create mode 100644 packages/svelte2tsx/test/svelte2tsx/samples/custom-namespaces/input.svelte diff --git a/.changeset/custom-namespaces.md b/.changeset/custom-namespaces.md new file mode 100644 index 000000000..8b17a5091 --- /dev/null +++ b/.changeset/custom-namespaces.md @@ -0,0 +1,18 @@ +--- +'svelte2tsx': minor +'svelte-check': minor +'svelte-language-server': minor +--- + +feat: add `customNamespaces` option to exempt custom namespaced attributes from prop/attribute type validation + +Frameworks built on top of Svelte sometimes attach custom namespaced attributes to elements and components (e.g. ``). These previously caused a `Type 'true' is not assignable to type 'never'` error. You can now list the namespaces to treat as opaque framework metadata via `customNamespaces` in `svelte.config.js`: + +```js +// svelte.config.js +export default { + customNamespaces: ['mochi'] +}; +``` + +An entry `'mochi'` matches an attribute named exactly `mochi` or any attribute starting with `mochi:`. Value expressions inside matched attributes are still type-checked. The option is honored by both `svelte-check` (CLI) and the language server (editor). `svelte2tsx` exposes the underlying `customNamespaces?: string[]` option directly. diff --git a/packages/language-server/src/lib/documents/configLoader.ts b/packages/language-server/src/lib/documents/configLoader.ts index 2678ed0a1..237c18ce9 100644 --- a/packages/language-server/src/lib/documents/configLoader.ts +++ b/packages/language-server/src/lib/documents/configLoader.ts @@ -30,6 +30,12 @@ export interface SvelteConfig { isFallbackConfig?: boolean; configSource?: 'svelte' | 'vite'; kit?: any; + /** + * Attribute namespaces (e.g. `'mochi'`) that frameworks built on top of Svelte attach to + * elements and components as opaque metadata. Matching attributes (`mochi` or `mochi:*`) + * are exempt from prop/attribute type validation. See svelte2tsx' `customNamespaces` option. + */ + customNamespaces?: string[]; } type LoadConfigFromDirectoryFn = typeof loadConfigFromDirectory; diff --git a/packages/language-server/src/plugins/typescript/DocumentSnapshot.ts b/packages/language-server/src/plugins/typescript/DocumentSnapshot.ts index 0cd520bf4..031cd22a0 100644 --- a/packages/language-server/src/plugins/typescript/DocumentSnapshot.ts +++ b/packages/language-server/src/plugins/typescript/DocumentSnapshot.ts @@ -255,7 +255,8 @@ function preprocessSvelteFile(document: Document, options: SvelteSnapshotOptions }) : document.config?.compilerOptions?.customElement), emitJsDoc: options.emitJsDoc, - rewriteExternalImports: options.rewriteExternalImports + rewriteExternalImports: options.rewriteExternalImports, + customNamespaces: document.config?.customNamespaces }); text = tsx.code; tsxMap = tsx.map as EncodedSourceMap; diff --git a/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/custom-namespaces-disabled/Counter.svelte b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/custom-namespaces-disabled/Counter.svelte new file mode 100644 index 000000000..ff7dee16e --- /dev/null +++ b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/custom-namespaces-disabled/Counter.svelte @@ -0,0 +1,5 @@ + + + diff --git a/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/custom-namespaces-disabled/expectedv2.json b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/custom-namespaces-disabled/expectedv2.json new file mode 100644 index 000000000..634459031 --- /dev/null +++ b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/custom-namespaces-disabled/expectedv2.json @@ -0,0 +1,10 @@ +[ + { + "range": { "start": { "line": 6, "character": 9 }, "end": { "line": 6, "character": 22 } }, + "severity": 1, + "source": "ts", + "message": "Type 'true' is not assignable to type 'never'.", + "code": 2322, + "tags": [] + } +] diff --git a/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/custom-namespaces-disabled/input.svelte b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/custom-namespaces-disabled/input.svelte new file mode 100644 index 000000000..f53f2e246 --- /dev/null +++ b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/custom-namespaces-disabled/input.svelte @@ -0,0 +1,7 @@ + + + + diff --git a/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/custom-namespaces-value-checked/Counter.svelte b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/custom-namespaces-value-checked/Counter.svelte new file mode 100644 index 000000000..ff7dee16e --- /dev/null +++ b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/custom-namespaces-value-checked/Counter.svelte @@ -0,0 +1,5 @@ + + + diff --git a/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/custom-namespaces-value-checked/expectedv2.json b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/custom-namespaces-value-checked/expectedv2.json new file mode 100644 index 000000000..596d35c3e --- /dev/null +++ b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/custom-namespaces-value-checked/expectedv2.json @@ -0,0 +1,10 @@ +[ + { + "range": { "start": { "line": 6, "character": 22 }, "end": { "line": 6, "character": 29 } }, + "severity": 1, + "source": "ts", + "message": "Cannot find name 'typoVar'.", + "code": 2304, + "tags": [] + } +] diff --git a/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/custom-namespaces-value-checked/input.svelte b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/custom-namespaces-value-checked/input.svelte new file mode 100644 index 000000000..ec5a5f4c5 --- /dev/null +++ b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/custom-namespaces-value-checked/input.svelte @@ -0,0 +1,7 @@ + + + + diff --git a/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/custom-namespaces-value-checked/svelte.config.js b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/custom-namespaces-value-checked/svelte.config.js new file mode 100644 index 000000000..dbf6fb002 --- /dev/null +++ b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/custom-namespaces-value-checked/svelte.config.js @@ -0,0 +1,3 @@ +module.exports = { + customNamespaces: ['mochi'] +}; diff --git a/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/custom-namespaces/Counter.svelte b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/custom-namespaces/Counter.svelte new file mode 100644 index 000000000..ff7dee16e --- /dev/null +++ b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/custom-namespaces/Counter.svelte @@ -0,0 +1,5 @@ + + + diff --git a/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/custom-namespaces/expectedv2.json b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/custom-namespaces/expectedv2.json new file mode 100644 index 000000000..fe51488c7 --- /dev/null +++ b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/custom-namespaces/expectedv2.json @@ -0,0 +1 @@ +[] diff --git a/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/custom-namespaces/input.svelte b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/custom-namespaces/input.svelte new file mode 100644 index 000000000..22f32213c --- /dev/null +++ b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/custom-namespaces/input.svelte @@ -0,0 +1,13 @@ + + + + + + +
x
+
+
diff --git a/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/custom-namespaces/svelte.config.js b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/custom-namespaces/svelte.config.js new file mode 100644 index 000000000..dbf6fb002 --- /dev/null +++ b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/custom-namespaces/svelte.config.js @@ -0,0 +1,3 @@ +module.exports = { + customNamespaces: ['mochi'] +}; diff --git a/packages/svelte-check/README.md b/packages/svelte-check/README.md index a05eff83b..2a1813ce4 100644 --- a/packages/svelte-check/README.md +++ b/packages/svelte-check/README.md @@ -66,6 +66,38 @@ Usage: | `--incremental` | Opts into TypeScript's incremental build cache, which speeds up subsequent runs. Saved within `.svelte-kit` or if not available within `.svelte-check`. This might result in slightly different type check outcomes, and certain patterns are not supported. Specifically, anything that is not in the root dir of your tsconfig.json and is a Svelte file will not be properly loaded and type-checked. | | `--tsgo` | Use TypeScript's Go implementation. Needs to have `@typescript/native-preview` installed. Subject to the same limitations as `--incremental` | +### Custom attribute namespaces + +Frameworks built on top of Svelte sometimes attach custom namespaced attributes to elements and +components to carry framework-level metadata, e.g. ``. At runtime Svelte +passes these through, but at type-check time `svelte-check` reports +`Type 'true' is not assignable to type 'never'` because the component/element has no such prop. + +To exempt one or more namespaces from prop/attribute validation, list them under +`customNamespaces` in your `svelte.config.js`: + +```js +// svelte.config.js +export default { + preprocess: [ + /* ... */ + ], + // Attributes named exactly `mochi` or starting with `mochi:` are treated as opaque metadata. + customNamespaces: ['mochi'] +}; +``` + +This option is read from the same `svelte.config.js` by both the CLI and the editor (the Svelte +language server / VS Code extension), so the editor experience matches `svelte-check`. Matching +attributes are still emitted such that any value expression is type-checked +(`mochi:defer={someVar}` still errors if `someVar` is undefined), but the attribute name itself is +no longer validated against the component's props. + +Note that the Svelte compiler also emits an `attribute_illegal_colon` warning for namespaced +attributes. `customNamespaces` only addresses the TypeScript prop/attribute error; to silence the +compiler warning as well, combine it with +`--compiler-warnings "attribute_illegal_colon:ignore"`. Frameworks typically need both. + ### FAQ #### Why is there no option to only check specific files (for example only staged files)? diff --git a/packages/svelte-check/src/incremental.ts b/packages/svelte-check/src/incremental.ts index aec4c83b7..8fcb85be9 100644 --- a/packages/svelte-check/src/incremental.ts +++ b/packages/svelte-check/src/incremental.ts @@ -107,21 +107,38 @@ function kitFilesSettingsFromConfig(config: any): InternalHelpers.KitFilesSettin } /** - * Loads the svelte.config.js file and extracts SvelteKit file path settings. + * Reads the `customNamespaces` option from a loaded Svelte config, normalizing it to a + * string array (or undefined when absent/invalid). + */ +function customNamespacesFromConfig(config: any): string[] | undefined { + const namespaces = config?.customNamespaces; + if (!Array.isArray(namespaces)) { + return undefined; + } + return namespaces.filter((ns): ns is string => typeof ns === 'string'); +} + +/** + * Loads the svelte.config.js file and extracts the settings svelte2tsx needs: + * SvelteKit file path settings and the `customNamespaces` option. * Falls back to default paths when no Svelte config can be loaded. * * @param workspacePath - Root directory of the project - * @returns KitFilesSettings with paths for params, hooks files + * @returns Kit file path settings and custom namespaces */ -async function loadKitFilesSettings( - workspacePath: string -): Promise { +async function loadSvelteConfigSettings(workspacePath: string): Promise<{ + kitFilesSettings: InternalHelpers.KitFilesSettings; + customNamespaces: string[] | undefined; +}> { const result = await loadConfig(workspacePath, { traverse: false }); if (!result || !('config' in result)) { - return defaultKitFilesSettings; + return { kitFilesSettings: defaultKitFilesSettings, customNamespaces: undefined }; } - return kitFilesSettingsFromConfig(result.config.kit); + return { + kitFilesSettings: kitFilesSettingsFromConfig(result.config.kit), + customNamespaces: customNamespacesFromConfig(result.config) + }; } /** @@ -146,7 +163,7 @@ export async function emitSvelteFiles( const manifest = incremental ? loadManifest(manifestPath, workspacePath) : { version: MANIFEST_VERSION, entries: {} as Record }; - const kitFilesSettings = await loadKitFilesSettings(workspacePath); + const { kitFilesSettings, customNamespaces } = await loadSvelteConfigSettings(workspacePath); const isJsOrTsFile = (filePath: string) => filePath.endsWith('.ts') || filePath.endsWith('.js'); const allRelevantFiles = await findFiles( workspacePath, @@ -232,7 +249,8 @@ export async function emitSvelteFiles( rewriteExternalImports: { workspacePath, generatedPath: outPath - } + }, + customNamespaces }); fs.writeFileSync(outPath, tsx.code, 'utf-8'); diff --git a/packages/svelte2tsx/index.d.ts b/packages/svelte2tsx/index.d.ts index 271e210f2..e3acb5c1f 100644 --- a/packages/svelte2tsx/index.d.ts +++ b/packages/svelte2tsx/index.d.ts @@ -95,6 +95,15 @@ export function svelte2tsx( * from the generated file location. */ rewriteExternalImports?: InternalHelpers.RewriteExternalImportsConfig; + /** + * Attribute namespaces that should be treated as opaque framework metadata rather than + * typed props/attributes. An entry `'mochi'` matches an attribute named exactly `mochi` + * or any attribute starting with `mochi:`. Matching attributes are emitted so their + * value expressions are still type-checked, but the attribute name itself is exempt from + * prop/attribute validation. A trailing `:` in an entry is ignored, so both `'mochi'` + * and `'mochi:'` work. + */ + customNamespaces?: string[]; } ): SvelteCompiledToTsx diff --git a/packages/svelte2tsx/src/htmlxtojsx_v2/index.ts b/packages/svelte2tsx/src/htmlxtojsx_v2/index.ts index f15d624d9..b7f74f34a 100644 --- a/packages/svelte2tsx/src/htmlxtojsx_v2/index.ts +++ b/packages/svelte2tsx/src/htmlxtojsx_v2/index.ts @@ -103,6 +103,7 @@ export function convertHtmlxToJsx( emitJsDoc?: boolean; isTsFile?: boolean; rewriteExternalImports?: RewriteExternalImportsOptions; + customNamespaces?: string[]; } = { svelte5Plus: false } ): TemplateProcessResult { options.typingsNamespace = options.typingsNamespace || 'svelteHTML'; @@ -498,7 +499,8 @@ export function convertHtmlxToJsx( parent, preserveAttributeCase, options.svelte5Plus, - element + element, + options.customNamespaces ); break; case 'Spread': @@ -675,6 +677,7 @@ export function htmlx2jsx( preserveAttributeCase: boolean; typingsNamespace: string; svelte5Plus: boolean; + customNamespaces?: string[]; } ) { const { htmlxAst, tags } = parseHtmlx(htmlx, parse, { ...options }); diff --git a/packages/svelte2tsx/src/htmlxtojsx_v2/nodes/Attribute.ts b/packages/svelte2tsx/src/htmlxtojsx_v2/nodes/Attribute.ts index bda3288c1..70b710f6a 100644 --- a/packages/svelte2tsx/src/htmlxtojsx_v2/nodes/Attribute.ts +++ b/packages/svelte2tsx/src/htmlxtojsx_v2/nodes/Attribute.ts @@ -44,6 +44,20 @@ const numberOnlyAttributes = new Set([ 'tabindex' ]); +/** + * Returns whether the given attribute name belongs to one of the configured + * custom namespaces. A namespace entry `'mochi'` matches an attribute named + * exactly `mochi` or any attribute starting with `mochi:`. + * + * Entries are expected to be normalized (no trailing `:`) by the caller. + */ +function matchesCustomNamespace(name: string, customNamespaces: string[] | undefined): boolean { + if (!customNamespaces?.length) { + return false; + } + return customNamespaces.some((ns) => name === ns || name.startsWith(ns + ':')); +} + /** * Handle various kinds of attributes and make them conform to being valid in context of a object definition * - {x} ---> x @@ -57,7 +71,8 @@ export function handleAttribute( parent: BaseNode, preserveCase: boolean, svelte5Plus: boolean, - element: Element | InlineComponent + element: Element | InlineComponent, + customNamespaces?: string[] ): void { if ( parent.name === '!DOCTYPE' || @@ -91,6 +106,15 @@ export function handleAttribute( value = ['__sveltets_2_any()']; } value.push('})'); + } else if (matchesCustomNamespace(attr.name, customNamespaces)) { + // Attributes in a configured custom namespace are opaque framework + // metadata, not typed attributes. Wrap them so the attribute name is + // exempt from validation while any value expression stays type-checked. + name.unshift('...__sveltets_2_empty({'); + if (!value) { + value = ['__sveltets_2_any()']; + } + value.push('})'); } element.addAttribute(name, value); } @@ -103,6 +127,15 @@ export function handleAttribute( value = ['""']; } value.push('})'); + } else if (matchesCustomNamespace(attr.name, customNamespaces)) { + // Attributes in a configured custom namespace are opaque framework + // metadata, not typed props. Wrap them so the attribute name is + // exempt from validation while any value expression stays type-checked. + name.unshift('...__sveltets_2_empty({'); + if (!value) { + value = ['__sveltets_2_any()']; + } + value.push('})'); } element.addProp(name, value); }; diff --git a/packages/svelte2tsx/src/svelte2tsx/index.ts b/packages/svelte2tsx/src/svelte2tsx/index.ts index fb0ee2c03..f26d62565 100644 --- a/packages/svelte2tsx/src/svelte2tsx/index.ts +++ b/packages/svelte2tsx/src/svelte2tsx/index.ts @@ -26,6 +26,7 @@ function processSvelteTemplate( emitJsDoc?: boolean; isTsFile?: boolean; rewriteExternalImports?: RewriteExternalImportsOptions; + customNamespaces?: string[]; } ): TemplateProcessResult { const { htmlxAst, tags } = parseHtmlx(str.original, parse, options); @@ -55,10 +56,22 @@ export function svelte2tsx( workspacePath: string; generatedPath: string; }; + /** + * Attribute namespaces that should be treated as opaque framework metadata rather than + * typed props/attributes. An entry `'mochi'` matches an attribute named exactly `mochi` + * or any attribute starting with `mochi:`. Matching attributes are emitted so their + * value expressions are still type-checked, but the attribute name itself is exempt from + * prop/attribute validation. + */ + customNamespaces?: string[]; } = { parse } ) { options.mode = options.mode || 'ts'; options.version = options.version || VERSION; + // Normalize custom namespaces by stripping a trailing `:` so both `'mochi'` and `'mochi:'` work. + const customNamespaces = options.customNamespaces + ?.map((ns) => (ns.endsWith(':') ? ns.slice(0, -1) : ns)) + .filter((ns) => ns.length > 0); const str = new MagicString(svelte); @@ -93,7 +106,8 @@ export function svelte2tsx( } = processSvelteTemplate(str, options.parse || parse, { ...options, svelte5Plus, - rewriteExternalImports: rewriteExternalImportsOptions + rewriteExternalImports: rewriteExternalImportsOptions, + customNamespaces }); /* Rearrange the script tags so that module is first, and instance second followed finally by the template diff --git a/packages/svelte2tsx/test/helpers.ts b/packages/svelte2tsx/test/helpers.ts index 44f161342..3ea216044 100644 --- a/packages/svelte2tsx/test/helpers.ts +++ b/packages/svelte2tsx/test/helpers.ts @@ -372,6 +372,7 @@ type BaseConfig = { emitOnTemplateError?: boolean; filename?: string; rewriteExternalImports?: Svelte2TsxConfig['rewriteExternalImports']; + customNamespaces?: string[]; }; type Svelte2TsxConfig = Required[1]>; @@ -386,7 +387,8 @@ export function get_svelte2tsx_config(base: BaseConfig, sampleName: string): Sve accessors: sampleName.startsWith('accessors-config'), emitJsDoc: sampleName.startsWith('jsdoc-'), version: VERSION, - rewriteExternalImports: base.rewriteExternalImports + rewriteExternalImports: base.rewriteExternalImports, + customNamespaces: base.customNamespaces }; } diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/custom-namespaces-disabled/expectedv2.ts b/packages/svelte2tsx/test/svelte2tsx/samples/custom-namespaces-disabled/expectedv2.ts new file mode 100644 index 000000000..1595fc308 --- /dev/null +++ b/packages/svelte2tsx/test/svelte2tsx/samples/custom-namespaces-disabled/expectedv2.ts @@ -0,0 +1,22 @@ +/// +; +import Counter from './Counter.svelte'; +function $$render() { + + + let count = 5; +; +async () => { + + + { const $$_retnuoC0C = __sveltets_2_ensureComponent(Counter); new $$_retnuoC0C({ target: __sveltets_2_any(), props: {"mochi:hydrate":true,}});} + { const $$_retnuoC0C = __sveltets_2_ensureComponent(Counter); new $$_retnuoC0C({ target: __sveltets_2_any(), props: { "mochi:defer":count,}});} + { const $$_retnuoC0C = __sveltets_2_ensureComponent(Counter); new $$_retnuoC0C({ target: __sveltets_2_any(), props: {"mochi":true,}});} + + { svelteHTML.createElement("div", {"mochi:foo":true,}); } + { svelteHTML.createElement("div", { "mochi:bar":count,}); } + { svelteHTML.createElement("div", {"mochi":true,}); }}; +return { props: /** @type {Record} */ ({}), slots: {}, events: {} }} + +export default class Input__SvelteComponent_ extends __sveltets_2_createSvelte2TsxComponent(__sveltets_2_partial(__sveltets_2_with_any_event($$render()))) { +} \ No newline at end of file diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/custom-namespaces-disabled/input.svelte b/packages/svelte2tsx/test/svelte2tsx/samples/custom-namespaces-disabled/input.svelte new file mode 100644 index 000000000..714bbab6d --- /dev/null +++ b/packages/svelte2tsx/test/svelte2tsx/samples/custom-namespaces-disabled/input.svelte @@ -0,0 +1,14 @@ + + + + + + + +
x
+
+
diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/custom-namespaces/config.json b/packages/svelte2tsx/test/svelte2tsx/samples/custom-namespaces/config.json new file mode 100644 index 000000000..3ffdf0e52 --- /dev/null +++ b/packages/svelte2tsx/test/svelte2tsx/samples/custom-namespaces/config.json @@ -0,0 +1,3 @@ +{ + "customNamespaces": ["mochi"] +} diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/custom-namespaces/expectedv2.ts b/packages/svelte2tsx/test/svelte2tsx/samples/custom-namespaces/expectedv2.ts new file mode 100644 index 000000000..65fa53abc --- /dev/null +++ b/packages/svelte2tsx/test/svelte2tsx/samples/custom-namespaces/expectedv2.ts @@ -0,0 +1,23 @@ +/// +; +import Counter from './Counter.svelte'; +function $$render() { + + + let count = 5; +; +async () => { + + + { const $$_retnuoC0C = __sveltets_2_ensureComponent(Counter); new $$_retnuoC0C({ target: __sveltets_2_any(), props: {...__sveltets_2_empty({"mochi:hydrate":true}),}});} + { const $$_retnuoC0C = __sveltets_2_ensureComponent(Counter); new $$_retnuoC0C({ target: __sveltets_2_any(), props: { ...__sveltets_2_empty({"mochi:defer":count}),}});} + { const $$_retnuoC0C = __sveltets_2_ensureComponent(Counter); new $$_retnuoC0C({ target: __sveltets_2_any(), props: {...__sveltets_2_empty({"mochi":true}),}});} + + + { svelteHTML.createElement("div", {...__sveltets_2_empty({"mochi:foo":true}),}); } + { svelteHTML.createElement("div", { ...__sveltets_2_empty({"mochi:bar":count}),}); } + { svelteHTML.createElement("div", {...__sveltets_2_empty({"mochi":true}),}); }}; +return { props: /** @type {Record} */ ({}), slots: {}, events: {} }} + +export default class Input__SvelteComponent_ extends __sveltets_2_createSvelte2TsxComponent(__sveltets_2_partial(__sveltets_2_with_any_event($$render()))) { +} \ No newline at end of file diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/custom-namespaces/input.svelte b/packages/svelte2tsx/test/svelte2tsx/samples/custom-namespaces/input.svelte new file mode 100644 index 000000000..558758731 --- /dev/null +++ b/packages/svelte2tsx/test/svelte2tsx/samples/custom-namespaces/input.svelte @@ -0,0 +1,14 @@ + + + + + + + + +
x
+
+