svelte-preprocess
Version:
A Svelte preprocessor wrapper with baked-in support for commonly used preprocessors
137 lines (136 loc) • 6.28 kB
JavaScript
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.transformer = exports.loadTsconfig = void 0;
const path_1 = require("path");
const typescript_1 = __importDefault(require("typescript"));
const errors_1 = require("../modules/errors");
/**
* Map of valid tsconfigs (no errors). Key is the path.
*/
const tsconfigMap = new Map();
function createFormatDiagnosticsHost(cwd) {
return {
getCanonicalFileName: (fileName) => fileName.replace('.injected.ts', ''),
getCurrentDirectory: () => cwd,
getNewLine: () => typescript_1.default.sys.newLine,
};
}
function formatDiagnostics(diagnostics, basePath) {
if (Array.isArray(diagnostics)) {
return typescript_1.default.formatDiagnosticsWithColorAndContext(diagnostics, createFormatDiagnosticsHost(basePath));
}
return typescript_1.default.formatDiagnostic(diagnostics, createFormatDiagnosticsHost(basePath));
}
let warned_verbatim = false;
function getCompilerOptions({ filename, options, basePath, }) {
var _a;
const inputOptions = (_a = options.compilerOptions) !== null && _a !== void 0 ? _a : {};
const { errors, options: convertedCompilerOptions } = options.tsconfigFile !== false || options.tsconfigDirectory
? loadTsconfig(inputOptions, filename, options)
: typescript_1.default.convertCompilerOptionsFromJson(inputOptions, basePath);
if (errors.length) {
throw new Error(formatDiagnostics(errors, basePath));
}
const compilerOptions = {
target: typescript_1.default.ScriptTarget.ES2015,
...convertedCompilerOptions,
// force module(resolution) to esnext and a compatible moduleResolution. Reason:
// transpileModule treats NodeNext as CommonJS because it doesn't read the package.json.
// Also see https://github.com/microsoft/TypeScript/issues/53022 (the filename workaround doesn't work).
module: typescript_1.default.ModuleKind.ESNext,
moduleResolution: typescript_1.default.ModuleResolutionKind.Node10,
allowNonTsExtensions: true,
// Clear outDir since it causes source map issues when the files aren't actually written to disk.
outDir: undefined,
};
if (!warned_verbatim && !compilerOptions.verbatimModuleSyntax) {
warned_verbatim = true;
console.warn('The TypeScript option verbatimModuleSyntax is now required when using Svelte files with lang="ts". Please add it to your tsconfig.json.');
}
if (compilerOptions.target === typescript_1.default.ScriptTarget.ES3 ||
compilerOptions.target === typescript_1.default.ScriptTarget.ES5) {
throw new Error(`Svelte only supports es6+ syntax. Set your 'compilerOptions.target' to 'es6' or higher.`);
}
return compilerOptions;
}
function transpileTs({ code, fileName, basePath, options, compilerOptions, transformers, }) {
const { outputText: transpiledCode, sourceMapText, diagnostics, } = typescript_1.default.transpileModule(code, {
fileName,
compilerOptions,
reportDiagnostics: options.reportDiagnostics !== false,
transformers,
});
if (diagnostics && diagnostics.length > 0) {
// could this be handled elsewhere?
const hasError = diagnostics.some((d) => d.category === typescript_1.default.DiagnosticCategory.Error);
if (hasError) {
const formattedDiagnostics = formatDiagnostics(diagnostics, basePath);
console.log(formattedDiagnostics);
(0, errors_1.throwTypescriptError)();
}
}
return { transpiledCode, sourceMapText, diagnostics };
}
function loadTsconfig(compilerOptionsJSON, filename, tsOptions) {
if (typeof tsOptions.tsconfigFile === 'boolean') {
return { errors: [], options: compilerOptionsJSON };
}
let basePath = process.cwd();
const fileDirectory = (tsOptions.tsconfigDirectory ||
(0, path_1.dirname)(filename));
let tsconfigFile = tsOptions.tsconfigFile ||
typescript_1.default.findConfigFile(fileDirectory, typescript_1.default.sys.fileExists);
if (!tsconfigFile) {
return { errors: [], options: compilerOptionsJSON };
}
tsconfigFile = (0, path_1.isAbsolute)(tsconfigFile)
? tsconfigFile
: (0, path_1.join)(basePath, tsconfigFile);
basePath = (0, path_1.dirname)(tsconfigFile);
if (tsconfigMap.has(tsconfigFile)) {
return {
errors: [],
options: tsconfigMap.get(tsconfigFile),
};
}
const { error, config } = typescript_1.default.readConfigFile(tsconfigFile, typescript_1.default.sys.readFile);
if (error) {
throw new Error(formatDiagnostics(error, basePath));
}
// Do this so TS will not search for initial files which might take a while
config.include = [];
let { errors, options } = typescript_1.default.parseJsonConfigFileContent(config, typescript_1.default.sys, basePath, compilerOptionsJSON, tsconfigFile);
// Filter out "no files found error"
errors = errors.filter((d) => d.code !== 18003);
if (errors.length === 0) {
tsconfigMap.set(tsconfigFile, options);
}
return { errors, options };
}
exports.loadTsconfig = loadTsconfig;
let warned_mixed = false;
const transformer = async ({ content, filename = 'input.svelte', options = {}, }) => {
const basePath = process.cwd();
filename = (0, path_1.isAbsolute)(filename) ? filename : (0, path_1.resolve)(basePath, filename);
const compilerOptions = getCompilerOptions({ filename, options, basePath });
if ('handleMixedImports' in options && !warned_mixed) {
warned_mixed = true;
console.warn('The svelte-preprocess TypeScript option handleMixedImports was removed. Use the verbatimModuleSyntax TypeScript option instead.');
}
const { transpiledCode, sourceMapText, diagnostics } = transpileTs({
code: content,
fileName: filename,
basePath,
options,
compilerOptions,
});
return {
code: transpiledCode,
map: sourceMapText,
diagnostics,
};
};
exports.transformer = transformer;
;