mirror of https://github.com/sveltejs/svelte
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
174 lines
5.8 KiB
174 lines
5.8 KiB
/** @import { LegacyRoot } from './types/legacy-nodes.js' */
|
|
/** @import { CompileOptions, CompileResult, ValidatedCompileOptions, ModuleCompileOptions } from '#compiler' */
|
|
/** @import { AST } from './public.js' */
|
|
import { walk as zimmerframe_walk } from 'zimmerframe';
|
|
import { convert } from './legacy.js';
|
|
import { parse as _parse } from './phases/1-parse/index.js';
|
|
import { remove_typescript_nodes } from './phases/1-parse/remove_typescript_nodes.js';
|
|
import { analyze_component, analyze_module } from './phases/2-analyze/index.js';
|
|
import { transform_component, transform_module } from './phases/3-transform/index.js';
|
|
import { validate_component_options, validate_module_options } from './validate-options.js';
|
|
import * as state from './state.js';
|
|
export { default as preprocess } from './preprocess/index.js';
|
|
|
|
/**
|
|
* `compile` converts your `.svelte` source code into a JavaScript module that exports a component
|
|
*
|
|
* @param {string} source The component source code
|
|
* @param {CompileOptions} options The compiler options
|
|
* @returns {CompileResult}
|
|
*/
|
|
export function compile(source, options) {
|
|
source = remove_bom(source);
|
|
state.reset({ warning: options.warningFilter, filename: options.filename });
|
|
const validated = validate_component_options(options, '');
|
|
|
|
let parsed = _parse(source);
|
|
|
|
const { customElement: customElementOptions, ...parsed_options } = parsed.options || {};
|
|
|
|
/** @type {ValidatedCompileOptions} */
|
|
const combined_options = {
|
|
...validated,
|
|
...parsed_options,
|
|
customElementOptions
|
|
};
|
|
|
|
if (parsed.metadata.ts) {
|
|
parsed = {
|
|
...parsed,
|
|
fragment: parsed.fragment && remove_typescript_nodes(parsed.fragment),
|
|
instance: parsed.instance && remove_typescript_nodes(parsed.instance),
|
|
module: parsed.module && remove_typescript_nodes(parsed.module)
|
|
};
|
|
if (combined_options.customElementOptions?.extend) {
|
|
combined_options.customElementOptions.extend = remove_typescript_nodes(
|
|
combined_options.customElementOptions?.extend
|
|
);
|
|
}
|
|
}
|
|
|
|
const analysis = analyze_component(parsed, source, combined_options);
|
|
const result = transform_component(analysis, source, combined_options);
|
|
result.ast = to_public_ast(source, parsed, options.modernAst);
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* `compileModule` takes your JavaScript source code containing runes, and turns it into a JavaScript module.
|
|
*
|
|
* @param {string} source The component source code
|
|
* @param {ModuleCompileOptions} options
|
|
* @returns {CompileResult}
|
|
*/
|
|
export function compileModule(source, options) {
|
|
source = remove_bom(source);
|
|
state.reset({ warning: options.warningFilter, filename: options.filename });
|
|
const validated = validate_module_options(options, '');
|
|
|
|
const analysis = analyze_module(source, validated);
|
|
return transform_module(analysis, source, validated);
|
|
}
|
|
|
|
/**
|
|
* The parse function parses a component, returning only its abstract syntax tree.
|
|
*
|
|
* The `modern` option (`false` by default in Svelte 5) makes the parser return a modern AST instead of the legacy AST.
|
|
* `modern` will become `true` by default in Svelte 6, and the option will be removed in Svelte 7.
|
|
*
|
|
* @overload
|
|
* @param {string} source
|
|
* @param {{ filename?: string; modern: true; loose?: boolean }} options
|
|
* @returns {AST.Root}
|
|
*/
|
|
|
|
/**
|
|
* The parse function parses a component, returning only its abstract syntax tree.
|
|
*
|
|
* The `modern` option (`false` by default in Svelte 5) makes the parser return a modern AST instead of the legacy AST.
|
|
* `modern` will become `true` by default in Svelte 6, and the option will be removed in Svelte 7.
|
|
*
|
|
* @overload
|
|
* @param {string} source
|
|
* @param {{ filename?: string; modern?: false; loose?: boolean }} [options]
|
|
* @returns {Record<string, any>}
|
|
*/
|
|
|
|
// TODO 6.0 remove unused `filename`
|
|
/**
|
|
* The parse function parses a component, returning only its abstract syntax tree.
|
|
*
|
|
* The `modern` option (`false` by default in Svelte 5) makes the parser return a modern AST instead of the legacy AST.
|
|
* `modern` will become `true` by default in Svelte 6, and the option will be removed in Svelte 7.
|
|
*
|
|
* The `loose` option, available since 5.13.0, tries to always return an AST even if the input will not successfully compile.
|
|
*
|
|
* The `filename` option is unused and will be removed in Svelte 6.0.
|
|
*
|
|
* @param {string} source
|
|
* @param {{ filename?: string; rootDir?: string; modern?: boolean; loose?: boolean }} [options]
|
|
* @returns {AST.Root | LegacyRoot}
|
|
*/
|
|
export function parse(source, { modern, loose } = {}) {
|
|
source = remove_bom(source);
|
|
state.reset({ warning: () => false, filename: undefined });
|
|
|
|
const ast = _parse(source, loose);
|
|
return to_public_ast(source, ast, modern);
|
|
}
|
|
|
|
/**
|
|
* @param {string} source
|
|
* @param {AST.Root} ast
|
|
* @param {boolean | undefined} modern
|
|
*/
|
|
function to_public_ast(source, ast, modern) {
|
|
if (modern) {
|
|
const clean = (/** @type {any} */ node) => {
|
|
delete node.metadata;
|
|
};
|
|
|
|
ast.options?.attributes.forEach((attribute) => {
|
|
clean(attribute);
|
|
clean(attribute.value);
|
|
if (Array.isArray(attribute.value)) {
|
|
attribute.value.forEach(clean);
|
|
}
|
|
});
|
|
|
|
// remove things that we don't want to treat as public API
|
|
return zimmerframe_walk(ast, null, {
|
|
_(node, { next }) {
|
|
clean(node);
|
|
next();
|
|
}
|
|
});
|
|
}
|
|
|
|
return convert(source, ast);
|
|
}
|
|
|
|
/**
|
|
* Remove the byte order mark from a string if it's present since it would mess with our template generation logic
|
|
* @param {string} source
|
|
*/
|
|
function remove_bom(source) {
|
|
if (source.charCodeAt(0) === 0xfeff) {
|
|
return source.slice(1);
|
|
}
|
|
return source;
|
|
}
|
|
|
|
/**
|
|
* @deprecated Replace this with `import { walk } from 'estree-walker'`
|
|
* @returns {never}
|
|
*/
|
|
export function walk() {
|
|
throw new Error(
|
|
`'svelte/compiler' no longer exports a \`walk\` utility — please import it directly from 'estree-walker' instead`
|
|
);
|
|
}
|
|
|
|
export { VERSION } from '../version.js';
|
|
export { migrate } from './migrate/index.js';
|