mirror of
https://github.com/Sevichecc/Urara-Blog.git
synced 2025-05-03 13:19:29 +08:00
273 lines
6.9 KiB
Text
273 lines
6.9 KiB
Text
import fs__default from 'fs';
|
|
import path__default from 'path';
|
|
import { $ } from './index.js';
|
|
import { m as mkdirp, p as posixify } from './filesystem.js';
|
|
|
|
/** @type {Map<string, string>} */
|
|
const previous_contents = new Map();
|
|
|
|
/**
|
|
* @param {string} file
|
|
* @param {string} code
|
|
*/
|
|
function write_if_changed(file, code) {
|
|
if (code !== previous_contents.get(file)) {
|
|
write(file, code);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param {string} file
|
|
* @param {string} code
|
|
*/
|
|
function write(file, code) {
|
|
previous_contents.set(file, code);
|
|
mkdirp(path__default.dirname(file));
|
|
fs__default.writeFileSync(file, code);
|
|
}
|
|
|
|
/** @param {string} str */
|
|
function trim(str) {
|
|
const indentation = /** @type {RegExpExecArray} */ (/\n?(\s*)/.exec(str))[1];
|
|
const pattern = new RegExp(`^${indentation}`, 'gm');
|
|
return str.replace(pattern, '').trim();
|
|
}
|
|
|
|
const reserved = new Set([
|
|
'do',
|
|
'if',
|
|
'in',
|
|
'for',
|
|
'let',
|
|
'new',
|
|
'try',
|
|
'var',
|
|
'case',
|
|
'else',
|
|
'enum',
|
|
'eval',
|
|
'null',
|
|
'this',
|
|
'true',
|
|
'void',
|
|
'with',
|
|
'await',
|
|
'break',
|
|
'catch',
|
|
'class',
|
|
'const',
|
|
'false',
|
|
'super',
|
|
'throw',
|
|
'while',
|
|
'yield',
|
|
'delete',
|
|
'export',
|
|
'import',
|
|
'public',
|
|
'return',
|
|
'static',
|
|
'switch',
|
|
'typeof',
|
|
'default',
|
|
'extends',
|
|
'finally',
|
|
'package',
|
|
'private',
|
|
'continue',
|
|
'debugger',
|
|
'function',
|
|
'arguments',
|
|
'interface',
|
|
'protected',
|
|
'implements',
|
|
'instanceof'
|
|
]);
|
|
|
|
const valid_identifier = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;
|
|
|
|
/**
|
|
* @param {string} cwd
|
|
* @param {string} file
|
|
*/
|
|
function maybe_file(cwd, file) {
|
|
const resolved = path__default.resolve(cwd, file);
|
|
if (fs__default.existsSync(resolved)) {
|
|
return resolved;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param {string} file
|
|
*/
|
|
function project_relative(file) {
|
|
return posixify(path__default.relative('.', file));
|
|
}
|
|
|
|
/**
|
|
* @param {string} file
|
|
*/
|
|
function remove_trailing_slashstar(file) {
|
|
if (file.endsWith('/*')) {
|
|
return file.slice(0, -2);
|
|
} else {
|
|
return file;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Writes the tsconfig that the user's tsconfig inherits from.
|
|
* @param {import('types').ValidatedKitConfig} config
|
|
*/
|
|
function write_tsconfig(config, cwd = process.cwd()) {
|
|
const out = path__default.join(config.outDir, 'tsconfig.json');
|
|
const user_file = maybe_file(cwd, 'tsconfig.json') || maybe_file(cwd, 'jsconfig.json');
|
|
|
|
if (user_file) validate(config, cwd, out, user_file);
|
|
|
|
/** @param {string} file */
|
|
const config_relative = (file) => posixify(path__default.relative(config.outDir, file));
|
|
|
|
const include = ['ambient.d.ts'];
|
|
for (const dir of [config.files.routes, config.files.lib]) {
|
|
const relative = project_relative(path__default.dirname(dir));
|
|
include.push(config_relative(`${relative}/**/*.js`));
|
|
include.push(config_relative(`${relative}/**/*.ts`));
|
|
include.push(config_relative(`${relative}/**/*.svelte`));
|
|
}
|
|
|
|
write_if_changed(
|
|
out,
|
|
JSON.stringify(
|
|
{
|
|
compilerOptions: {
|
|
// generated options
|
|
baseUrl: config_relative('.'),
|
|
paths: get_tsconfig_paths(config),
|
|
rootDirs: [config_relative('.'), './types'],
|
|
|
|
// essential options
|
|
// svelte-preprocess cannot figure out whether you have a value or a type, so tell TypeScript
|
|
// to enforce using \`import type\` instead of \`import\` for Types.
|
|
importsNotUsedAsValues: 'error',
|
|
// Vite compiles modules one at a time
|
|
isolatedModules: true,
|
|
// TypeScript doesn't know about import usages in the template because it only sees the
|
|
// script of a Svelte file. Therefore preserve all value imports. Requires TS 4.5 or higher.
|
|
preserveValueImports: true,
|
|
|
|
// This is required for svelte-kit package to work as expected
|
|
// Can be overwritten
|
|
lib: ['esnext', 'DOM', 'DOM.Iterable'],
|
|
moduleResolution: 'node',
|
|
module: 'esnext',
|
|
target: 'esnext'
|
|
},
|
|
include,
|
|
exclude: [config_relative('node_modules/**'), './[!ambient.d.ts]**']
|
|
},
|
|
null,
|
|
'\t'
|
|
)
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @param {import('types').ValidatedKitConfig} config
|
|
* @param {string} cwd
|
|
* @param {string} out
|
|
* @param {string} user_file
|
|
*/
|
|
function validate(config, cwd, out, user_file) {
|
|
// we have to eval the file, since it's not parseable as JSON (contains comments)
|
|
const user_tsconfig_json = fs__default.readFileSync(user_file, 'utf-8');
|
|
const user_tsconfig = (0, eval)(`(${user_tsconfig_json})`);
|
|
|
|
// we need to check that the user's tsconfig extends the framework config
|
|
const extend = user_tsconfig.extends;
|
|
const extends_framework_config = extend && path__default.resolve(cwd, extend) === out;
|
|
|
|
const kind = path__default.basename(user_file);
|
|
|
|
if (extends_framework_config) {
|
|
const { paths: user_paths } = user_tsconfig.compilerOptions || {};
|
|
|
|
if (user_paths && fs__default.existsSync(config.files.lib)) {
|
|
/** @type {string[]} */
|
|
const lib = user_paths['$lib'] || [];
|
|
/** @type {string[]} */
|
|
const lib_ = user_paths['$lib/*'] || [];
|
|
|
|
const missing_lib_paths =
|
|
!lib.some((relative) => path__default.resolve(cwd, relative) === config.files.lib) ||
|
|
!lib_.some((relative) => path__default.resolve(cwd, relative) === path__default.join(config.files.lib, '/*'));
|
|
|
|
if (missing_lib_paths) {
|
|
console.warn(
|
|
$
|
|
.bold()
|
|
.yellow(`Your compilerOptions.paths in ${kind} should include the following:`)
|
|
);
|
|
const relative = posixify(path__default.relative('.', config.files.lib));
|
|
console.warn(`{\n "$lib":["${relative}"],\n "$lib/*":["${relative}/*"]\n}`);
|
|
}
|
|
}
|
|
} else {
|
|
let relative = posixify(path__default.relative('.', out));
|
|
if (!relative.startsWith('./')) relative = './' + relative;
|
|
|
|
console.warn(
|
|
$.bold().yellow(`Your ${kind} should extend the configuration generated by SvelteKit:`)
|
|
);
|
|
console.warn(`{\n "extends": "${relative}"\n}`);
|
|
}
|
|
}
|
|
|
|
// <something><optional /*>
|
|
const alias_regex = /^(.+?)(\/\*)?$/;
|
|
// <path><optional /* or .fileending>
|
|
const value_regex = /^(.*?)((\/\*)|(\.\w+))?$/;
|
|
|
|
/**
|
|
* Generates tsconfig path aliases from kit's aliases.
|
|
* Related to vite alias creation.
|
|
*
|
|
* @param {import('types').ValidatedKitConfig} config
|
|
*/
|
|
function get_tsconfig_paths(config) {
|
|
const alias = {
|
|
...config.alias
|
|
};
|
|
if (fs__default.existsSync(project_relative(config.files.lib))) {
|
|
alias['$lib'] = project_relative(config.files.lib);
|
|
}
|
|
|
|
/** @type {Record<string, string[]>} */
|
|
const paths = {};
|
|
|
|
for (const [key, value] of Object.entries(alias)) {
|
|
const key_match = alias_regex.exec(key);
|
|
if (!key_match) throw new Error(`Invalid alias key: ${key}`);
|
|
|
|
const value_match = value_regex.exec(value);
|
|
if (!value_match) throw new Error(`Invalid alias value: ${value}`);
|
|
|
|
const rel_path = project_relative(remove_trailing_slashstar(value));
|
|
const slashstar = key_match[2];
|
|
|
|
if (slashstar) {
|
|
paths[key] = [rel_path + '/*'];
|
|
} else {
|
|
paths[key] = [rel_path];
|
|
const fileending = value_match[4];
|
|
|
|
if (!fileending && !(key + '/*' in alias)) {
|
|
paths[key + '/*'] = [rel_path + '/*'];
|
|
}
|
|
}
|
|
}
|
|
|
|
return paths;
|
|
}
|
|
|
|
export { write as a, write_tsconfig as b, reserved as r, trim as t, valid_identifier as v, write_if_changed as w };
|