@sveltejs/package
Version:
The fastest way to build Svelte packages
139 lines (121 loc) • 4.28 kB
JavaScript
import * as fs from 'node:fs';
import * as path from 'node:path';
import { VERSION } from 'svelte/compiler';
import { posixify, mkdirp, walk } from './filesystem.js';
const is_svelte_5_plus = Number(VERSION.split('.')[0]) >= 5;
/**
* Resolves aliases
*
* @param {string} input
* @param {string} file Relative to the input
* @param {string} content
* @param {Record<string, string>} aliases
* @returns {string}
*/
export function resolve_aliases(input, file, content, aliases) {
/**
* @param {string} match
* @param {string} quote
* @param {string} import_path
*/
const replace_import_path = (match, quote, import_path) => {
for (const [alias, value] of Object.entries(aliases)) {
if (
import_path !== alias &&
!import_path.startsWith(alias + (alias.endsWith('/') ? '' : '/'))
) {
continue;
}
const full_path = path.join(input, file);
const full_import_path = path.join(value, import_path.slice(alias.length));
let resolved = posixify(path.relative(path.dirname(full_path), full_import_path));
resolved = resolved.startsWith('.') ? resolved : './' + resolved;
return match.replace(quote + import_path + quote, quote + resolved + quote);
}
return match;
};
// import/export (type) (xxx | xxx,) { ... } from ...
content = content.replace(
/\b(?:import|export)(?:\s+type)?(?:(?:\s+\p{L}[\p{L}0-9]*\s+)|(?:(?:\s+\p{L}[\p{L}0-9]*\s*,\s*)?\s*\{[^}]*\}\s*))from\s*(['"])([^'";]+)\1/gmu,
(match, quote, import_path) => replace_import_path(match, quote, import_path)
);
// import/export (type) * as xxx from ...
content = content.replace(
/\b(?:import|export)(?:\s+type)?\s*\*\s*as\s+\p{L}[\p{L}0-9]*\s+from\s*(['"])([^'";]+)\1/gmu,
(match, quote, import_path) => replace_import_path(match, quote, import_path)
);
// export (type) * from ...
content = content.replace(
/\b(?:export)(?:\s+type)?\s*\*\s*from\s*(['"])([^'";]+)\1/gmu,
(match, quote, import_path) => replace_import_path(match, quote, import_path)
);
// import(...)
content = content.replace(
/\bimport\s*\(\s*(['"])([^'";]+)\1\s*\)/g,
(match, quote, import_path) => replace_import_path(match, quote, import_path)
);
// import '...'
content = content.replace(/\bimport\s+(['"])([^'";]+)\1/g, (match, quote, import_path) =>
replace_import_path(match, quote, import_path)
);
return content;
}
/**
* Strip out lang="X" or type="text/X" tags. Doing it here is only a temporary solution.
* See https://github.com/sveltejs/kit/issues/2450 for ideas for places where it's handled better.
*
* @param {string} content
*/
export function strip_lang_tags(content) {
return content
.replace(
/(<!--[^]*?-->)|(<script[^>]*?)\s(?:type|lang)=(["'])(.*?)\3/g,
// Things like application/ld+json should be kept as-is. Preprocessed languages are "ts" etc.
// Svelte 5 deals with TypeScript natively, and in the template, too, therefore keep it in.
// Not removing it would mean Svelte parses without its TS plugin and then runs into errors.
(match, comment, tag_open, _, type) =>
type?.startsWith('application/') || (is_svelte_5_plus && type === 'ts')
? match
: (comment ?? '') + (tag_open ?? '')
)
.replace(/(<!--[^]*?-->)|(<style[^>]*?)\s(?:type|lang)=(["']).*?\3/g, '$1$2');
}
/**
* @param {string} file
* @param {Parameters<typeof fs.writeFileSync>[1]} contents
*/
export function write(file, contents) {
mkdirp(path.dirname(file));
fs.writeFileSync(file, contents);
}
/**
* @param {string} input
* @param {string[]} extensions
* @returns {import('./types.js').File[]}
*/
export function scan(input, extensions) {
return walk(input).map((file) => analyze(file, extensions));
}
/**
* @param {string} file
* @param {string[]} extensions
* @returns {import('./types.js').File}
*/
export function analyze(file, extensions) {
const name = posixify(file);
const svelte_extension = extensions.find((ext) => name.endsWith(ext));
const base = svelte_extension ? name : name.slice(0, -path.extname(name).length);
const dest = svelte_extension
? name.slice(0, -svelte_extension.length) + '.svelte'
: name.endsWith('.d.ts')
? name
: name.endsWith('.ts')
? name.slice(0, -3) + '.js'
: name;
return {
name,
dest,
base,
is_svelte: !!svelte_extension
};
}