UNPKG

dtsc

Version:

Generate bundled TypeScript declaration files

153 lines 5.83 kB
import { EOL } from 'os'; export async function bundle(options) { const { files, source, exclude = [] } = options; const moduleRE = `["'](${files.join('|')})(\\.[jt]s)?["']`; const internalImport = new RegExp('import\\(' + moduleRE + '\\)\\.', 'g'); const internalExport = new RegExp('^ {4}export .+ from ' + moduleRE + ';$'); const internalInject = new RegExp('^declare module ' + moduleRE + ' {$'); const importMap = {}; const namespaceMap = {}; let prolog = '', cap; let current, temporary; let identifier, isExportDefault; const platforms = {}; const output = source.split(/\r?\n/g).filter((line) => { // Step 1: collect informations if (isExportDefault) { if (line === ' }') isExportDefault = false; return false; } else if (temporary) { if (line === '}') return temporary = null; temporary.push(line); } else if ((cap = /^declare module ["'](.+)["'] \{( \})?$/.exec(line))) { // ^1 // ignore empty module declarations if (cap[2]) return temporary = null; if (exclude.includes(cap[1])) return temporary = null; current = cap[1]; const segments = current.split(/\//g); const lastName = segments.pop(); if (['node', 'browser'].includes(lastName) && segments.length) { temporary = (platforms[segments.join('/')] ||= {})[lastName] = []; } else { return true; } } else if ((cap = /^ {4}import ["'](.+)["'];$/.exec(line))) { // ^1 // import module directly if (!files.includes(cap[1])) prolog += line.trimStart() + EOL; } else if ((cap = /^ {4}import (type )?\* as (.+) from ["'](.+)["'];$/.exec(line))) { // ^1 ^2 ^3 // import as namespace if (files.includes(cap[3])) { // mark internal module as namespace namespaceMap[cap[3]] = cap[2]; } else if (!prolog.includes(line.trimStart())) { // preserve external module imports once prolog += line.trimStart() + EOL; } } else if ((cap = /^ {4}import (type )?(\S*)(?:, *)?(?:\{(.*)\})? from ["'](.+)["'];$/.exec(line))) { // ^1 ^2 ^3 ^4 // ignore internal imports if (files.includes(cap[4])) return; // handle aliases from external imports const map = importMap[cap[4]] ||= {}; cap[2] && Object.defineProperty(map, 'default', { value: cap[2] }); cap[3] && cap[3].split(',').map((part) => { part = part.trim(); if (part.startsWith('type ')) { part = part.slice(5); } if (part.includes(' as ')) { const [left, right] = part.split(' as '); map[left.trimEnd()] = right.trimStart(); } else { map[part] = part; } }); } else if (line.startsWith('///')) { prolog += line + EOL; } else if (line.startsWith('#!')) { return false; } else if (line.startsWith(' export default ')) { if (current === 'index') return true; if (line.endsWith('{')) isExportDefault = true; return false; } else { return line.trim() !== 'export {};'; } }).map((line) => { // Step 2: flatten module declarations if ((cap = /^declare module ["'](.+)["'] \{$/.exec(line))) { if ((identifier = namespaceMap[cap[1]])) { return `declare namespace ${identifier} {`; } else { return ''; } } else if (line === '}') { return identifier ? '}' : ''; } else if (!internalExport.exec(line)) { if (!identifier) line = line.slice(4); return line .replace(internalImport, '') .replace(/import\("index"\)/g, "import('.')") .replace(/^(module|class|namespace|const|global|function|interface) /, (_) => `declare ${_}`); } else { return ''; } }).map((line) => { if ((cap = internalInject.exec(line))) { identifier = '@internal'; return ''; } else if (line === '}') { return identifier ? identifier = '' : '}'; } else { if (identifier) line = line.slice(4); return line.replace(/^((class|namespace|interface) .+ \{)$/, (_) => `export ${_}`); } }).filter(line => line).join(EOL); Object.entries(importMap).forEach(([name, map]) => { const output = []; const entries = Object.entries(map); if (map.default) output.push(map.default); if (entries.length) { output.push('{ ' + entries.map(([left, right]) => { if (left === right) return left; return `${left} as ${right}`; }).join(', ') + ' }'); } prolog += `import ${output.join(', ')} from '${name}';${EOL}`; }); return prolog + output + EOL; } //# sourceMappingURL=bundle.js.map