UNPKG

@best-shot/sfc-split-plugin

Version:

141 lines (126 loc) 3.76 kB
import { createHash } from 'node:crypto'; import { join, relative, resolve } from 'node:path'; import { fileURLToPath } from 'node:url'; import { toJSONString } from '@into-mini/sfc-transformer/utils.mjs'; import slash from 'slash'; function createShortHash(input) { return createHash('sha256').update(input).digest('hex').slice(0, 8); } function reach(path) { return fileURLToPath(import.meta.resolve(path)); } function handleImport({ toThis, addSmartEntry, componentRoot, context, rootContext, maps, callback, }) { if (Object.keys(maps).length > 0) { for (const [name, path] of Object.entries(maps)) { if (path.endsWith('.vue') && !path.startsWith('plugin://')) { try { const absolutePath = slash( path.startsWith('.') ? resolve(context, path) : reach(path), ); const relativePath = slash(relative(rootContext, absolutePath)); const hack = relativePath.startsWith('..'); const entryName = hack ? [ componentRoot, absolutePath .split('/') .slice(-2) .join('/') .replace(/\.vue$/, ''), createShortHash(slash(absolutePath)), ].join('/') : relativePath.replace(/\.vue$/, ''); const placer = toThis(entryName); callback({ name, placer, }); const entryPath = relativePath.startsWith('..') ? absolutePath : `./${relativePath}`; this.addDependency(resolve(absolutePath)); this.addMissingDependency(resolve(absolutePath)); addSmartEntry({ name: entryName, path: entryPath, }); } catch (error) { console.error(error); } } } } } export default function loader(source, map, meta) { this.cacheable(); const callback = this.async(); const { componentRoot } = this.getOptions(); const { entryName: thisEntryName } = this; const resourcePath = slash(this.resourcePath); const { paths, config, script } = this.processSfcFile({ source, resourcePath, }); const { rootContext, context } = this; for (const path of paths) { const filePath = join(rootContext, path); this.addDependency(filePath); this.addMissingDependency(filePath); } function toThis(entryName) { return slash(relative(`/${thisEntryName}/..`, `/${entryName}`)); } const addSmartEntry = (io) => { this.addSmartEntry(io); }; if (config?.usingComponents) { handleImport.bind(this)({ toThis, addSmartEntry, componentRoot, context, rootContext, maps: config.usingComponents, callback({ name, placer }) { config.usingComponents[name] = placer; if (placer.includes(componentRoot)) { config.componentPlaceholder ??= {}; config.componentPlaceholder[name] = 'view'; } }, }); } if (config?.componentGenerics) { handleImport.bind(this)({ toThis, addSmartEntry, componentRoot, context, rootContext, maps: Object.fromEntries( Object.entries(config.componentGenerics) .filter(([_, item]) => item?.default) .map(([key, item]) => [key, item.default]), ), callback({ name, placer }) { config.componentGenerics[name].default = placer; }, }); } const file = [ ...paths .map((path) => relative(`${resourcePath}/..`, path)) .map((path) => `import "./${path}";`), script, ].join('\n'); this.emitFile(`${thisEntryName}.json`, toJSONString(config)); callback(null, file, map, meta); }