rollup-plugin-keywords 1.2.2 → 1.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +2 -1
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +3 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -12,7 +12,8 @@ var VIRTUAL_MODULE_ID = "virtual:keywords";
|
|
|
12
12
|
var RESOLVED_VIRTUAL_MODULE_ID = `\0${VIRTUAL_MODULE_ID}`;
|
|
13
13
|
var resolveOptions = (options) => {
|
|
14
14
|
return {
|
|
15
|
-
additionalModulesToScan: options?.additionalModulesToScan || []
|
|
15
|
+
additionalModulesToScan: options?.additionalModulesToScan || [],
|
|
16
|
+
isDev: options?.isDev
|
|
16
17
|
};
|
|
17
18
|
};
|
|
18
19
|
var createPrefixedLogger = (logger, pluginName, usePrefix = true) => {
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli.ts","../../minifiable-keywords/src/index.ts","../src/shared.ts"],"sourcesContent":["import path from 'node:path';\nimport { parseArgs } from 'node:util';\nimport {\n collectKeywordsAndGenerateTypes,\n createPrefixedLogger,\n} from 'minifiable-keywords';\nimport { loadConfigFile } from 'rollup/loadConfigFile';\nimport { PLUGIN_NAME } from './shared';\n\nconst main = async () => {\n const root = process.cwd();\n const logger = createPrefixedLogger(console, PLUGIN_NAME);\n\n const { values } = parseArgs({\n options: {\n config: {\n type: 'string',\n short: 'c',\n },\n configPlugin: {\n type: 'string',\n },\n },\n strict: false,\n });\n\n const configPath = path.resolve(\n root,\n typeof values.config === 'string' ? values.config : 'rollup.config.js',\n );\n\n const commandOptions: Record<string, any> = {};\n if (typeof values.configPlugin === 'string') {\n commandOptions.configPlugin = values.configPlugin;\n }\n\n let pluginOptions;\n let options;\n let warnings;\n\n try {\n const loaded = await loadConfigFile(configPath, commandOptions);\n options = loaded.options;\n warnings = loaded.warnings;\n warnings.flush();\n } catch (error: any) {\n logger.error(`Error loading Rollup configuration: ${error.message}`);\n process.exit(1);\n }\n\n for (const option of options) {\n if (!option.plugins) continue;\n\n const keywordsPlugin = option.plugins.find(\n (plugin: any) => plugin && plugin.name === PLUGIN_NAME,\n );\n\n if (keywordsPlugin) {\n pluginOptions = (keywordsPlugin as any).api?.options;\n break;\n }\n }\n\n if (!pluginOptions) {\n logger.error('Keywords plugin not found in Rollup configuration.');\n process.exit(1);\n }\n\n try {\n await collectKeywordsAndGenerateTypes(root, logger, [], pluginOptions);\n } catch (error: any) {\n logger.error(\n `Failed to collect keywords and generate types: ${error.message}`,\n );\n process.exit(1);\n }\n};\n\nawait main();\n","import { mkdir, readFile, writeFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport { parse } from '@babel/parser';\nimport _traverse, { type Node } from '@babel/traverse';\nimport { globby } from 'globby';\n\nexport const VIRTUAL_MODULE_ID = 'virtual:keywords';\nexport const RESOLVED_VIRTUAL_MODULE_ID = `\\0${VIRTUAL_MODULE_ID}`;\n\nexport interface KeywordsPluginOptions {\n additionalModulesToScan?: string[];\n}\n\nexport type ResolvedKeywordsPluginOptions = Required<KeywordsPluginOptions>;\n\nexport const resolveOptions = (\n options?: KeywordsPluginOptions,\n): ResolvedKeywordsPluginOptions => {\n return {\n additionalModulesToScan: options?.additionalModulesToScan || [],\n };\n};\n\nexport interface Logger {\n info: (message: string) => void;\n warn: (message: string) => void;\n error: (message: string) => void;\n}\n\nexport interface PrefixedLogger extends Logger {\n pluginName: string;\n}\n\nexport const createPrefixedLogger = (\n logger: Logger,\n pluginName: string,\n usePrefix: boolean = true,\n): PrefixedLogger => {\n const prefix = usePrefix ? `[${pluginName}] ` : '';\n const prefixed = (message: string) => `${prefix}${message}`;\n return {\n pluginName,\n info: (message: string) => logger.info(prefixed(message)),\n warn: (message: string) => logger.warn(prefixed(message)),\n error: (message: string) => logger.error(prefixed(message)),\n };\n};\n\n// ref: https://github.com/babel/babel/discussions/13093\nconst traverse =\n typeof _traverse === 'function'\n ? _traverse\n : ((_traverse as any).default as typeof _traverse);\n\nexport const extractKeywords = (\n code: string,\n additionalModulesToScan: string[] = [],\n): Set<string> => {\n const keywords = new Set<string>();\n\n // Fast-path: Skip parsing if no relevant imports are present in the code.\n const containsTargetModule =\n code.includes(VIRTUAL_MODULE_ID) ||\n additionalModulesToScan.some((moduleName) => code.includes(moduleName));\n\n if (!containsTargetModule) {\n return keywords;\n }\n\n let ast: Node;\n try {\n ast = parse(code, {\n sourceType: 'module',\n plugins: ['typescript', 'jsx'],\n errorRecovery: true,\n });\n } catch (e) {\n return keywords;\n }\n\n const keywordNamespaces = new Set<string>();\n\n traverse(ast, {\n enter(nodePath) {\n const node = nodePath.node;\n\n if (node.type === 'ImportDeclaration') {\n const isTargetModule =\n node.source.value === VIRTUAL_MODULE_ID ||\n additionalModulesToScan.includes(node.source.value);\n\n if (isTargetModule) {\n for (const specifier of node.specifiers) {\n if (specifier.type === 'ImportNamespaceSpecifier') {\n keywordNamespaces.add(specifier.local.name);\n }\n\n if (specifier.type === 'ImportDefaultSpecifier') {\n keywords.add('default');\n }\n\n if (specifier.type === 'ImportSpecifier') {\n if (specifier.imported.type === 'Identifier') {\n keywords.add(specifier.imported.name);\n }\n }\n }\n }\n }\n },\n });\n\n if (keywordNamespaces.size === 0) {\n return keywords;\n }\n\n traverse(ast, {\n enter(nodePath) {\n const node = nodePath.node;\n\n if (\n node.type === 'MemberExpression' &&\n !node.computed && // Exclude computed properties like K['xyz']\n node.object.type === 'Identifier' &&\n keywordNamespaces.has(node.object.name) &&\n node.property.type === 'Identifier'\n ) {\n keywords.add(node.property.name);\n }\n\n if (\n node.type === 'TSQualifiedName' &&\n node.left.type === 'Identifier' &&\n keywordNamespaces.has(node.left.name) &&\n node.right.type === 'Identifier'\n ) {\n keywords.add(node.right.name);\n }\n },\n });\n\n return keywords;\n};\n\nconst keywordConstPrefix = '_';\nconst createExportDeclaration = (keywords: Set<string>): string[] => {\n const aliases = [...keywords].map(\n (key) => ` ${keywordConstPrefix}${key} as ${key},`,\n );\n return [`export {`, ...aliases, `};`];\n};\n\nexport const generateTypesFile = async (\n collectedKeywords: Set<string>,\n root: string,\n dirname: string = '.keywords',\n filename: string = 'index.d.ts',\n): Promise<void> => {\n const keywordDeclarations = [...collectedKeywords]\n .map((key) => `declare const ${keywordConstPrefix}${key}: unique symbol;`)\n .join('\\n');\n const exportDeclaration =\n createExportDeclaration(collectedKeywords).join('\\n');\n const content = `${keywordDeclarations}\\n${exportDeclaration}\\n`;\n const pluginRoot = path.join(root, dirname);\n await mkdir(pluginRoot, { recursive: true });\n await writeFile(path.join(pluginRoot, filename), `${content.trim()}\\n`);\n};\n\nexport const collectKeywordsFromFiles = async (\n root: string,\n logger: PrefixedLogger,\n ignoredDirs: string[] = [],\n options?: KeywordsPluginOptions,\n): Promise<Set<string>> => {\n const resolvedOptions = resolveOptions(options);\n const collectedKeywords = new Set<string>();\n\n logger.info('Scanning project files for keywords...');\n\n const files = await globby('**/*.{js,ts,jsx,tsx}', {\n cwd: root,\n absolute: true,\n ignore: ['**/node_modules/**', ...ignoredDirs.map((dir) => `${dir}/**`)],\n gitignore: true,\n });\n\n const concurrency = 100;\n for (let i = 0; i < files.length; i += concurrency) {\n const chunk = files.slice(i, i + concurrency);\n await Promise.all(\n chunk.map(async (file) => {\n try {\n const code = await readFile(file, 'utf-8');\n const keywords = extractKeywords(\n code,\n resolvedOptions.additionalModulesToScan,\n );\n for (const key of keywords) {\n collectedKeywords.add(key);\n }\n } catch (error: any) {\n logger.warn(`Failed to process file ${file}: ${error.message}`);\n }\n }),\n );\n }\n\n logger.info(\n `Scan complete. Found ${collectedKeywords.size} unique keywords.`,\n );\n\n return collectedKeywords;\n};\n\nexport const collectKeywordsAndGenerateTypes = async (\n root: string,\n logger: PrefixedLogger,\n ignoredDirs?: string[],\n options?: KeywordsPluginOptions,\n): Promise<Set<string>> => {\n const collectedKeywords = await collectKeywordsFromFiles(\n root,\n logger,\n ignoredDirs,\n options,\n );\n await generateTypesFile(collectedKeywords, root);\n return collectedKeywords;\n};\n\nexport const generateModuleCode = (\n collectedKeywords: Set<string>,\n isDev: boolean,\n): string => {\n const symbolConstructorName = '__SYMBOL__';\n const symbolDeclaration = `const ${symbolConstructorName} = Symbol;`;\n const keywordDeclarations = [...collectedKeywords]\n .map(\n (key) =>\n `const ${keywordConstPrefix}${key} = /* @__PURE__ */ ${symbolConstructorName}(${isDev ? `'${key}'` : ''});`,\n )\n .join('\\n');\n const exportDeclaration =\n createExportDeclaration(collectedKeywords).join('\\n');\n return `${symbolDeclaration}\\n${keywordDeclarations}\\n${exportDeclaration}\\n`;\n};\n\nexport const splitQuery = (id: string) => id.split('?');\n","export const PLUGIN_NAME = 'rollup-plugin-keywords';\n"],"mappings":"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","names":["path","path"]}
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts","../../minifiable-keywords/src/index.ts","../src/shared.ts"],"sourcesContent":["import path from 'node:path';\nimport { parseArgs } from 'node:util';\nimport {\n collectKeywordsAndGenerateTypes,\n createPrefixedLogger,\n} from 'minifiable-keywords';\nimport { loadConfigFile } from 'rollup/loadConfigFile';\nimport { PLUGIN_NAME } from './shared';\n\nconst main = async () => {\n const root = process.cwd();\n const logger = createPrefixedLogger(console, PLUGIN_NAME);\n\n const { values } = parseArgs({\n options: {\n config: {\n type: 'string',\n short: 'c',\n },\n configPlugin: {\n type: 'string',\n },\n },\n strict: false,\n });\n\n const configPath = path.resolve(\n root,\n typeof values.config === 'string' ? values.config : 'rollup.config.js',\n );\n\n const commandOptions: Record<string, any> = {};\n if (typeof values.configPlugin === 'string') {\n commandOptions.configPlugin = values.configPlugin;\n }\n\n let pluginOptions;\n let options;\n let warnings;\n\n try {\n const loaded = await loadConfigFile(configPath, commandOptions);\n options = loaded.options;\n warnings = loaded.warnings;\n warnings.flush();\n } catch (error: any) {\n logger.error(`Error loading Rollup configuration: ${error.message}`);\n process.exit(1);\n }\n\n for (const option of options) {\n if (!option.plugins) continue;\n\n const keywordsPlugin = option.plugins.find(\n (plugin: any) => plugin && plugin.name === PLUGIN_NAME,\n );\n\n if (keywordsPlugin) {\n pluginOptions = (keywordsPlugin as any).api?.options;\n break;\n }\n }\n\n if (!pluginOptions) {\n logger.error('Keywords plugin not found in Rollup configuration.');\n process.exit(1);\n }\n\n try {\n await collectKeywordsAndGenerateTypes(root, logger, [], pluginOptions);\n } catch (error: any) {\n logger.error(\n `Failed to collect keywords and generate types: ${error.message}`,\n );\n process.exit(1);\n }\n};\n\nawait main();\n","import { mkdir, readFile, writeFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport { parse } from '@babel/parser';\nimport _traverse, { type Node } from '@babel/traverse';\nimport { globby } from 'globby';\n\nexport const VIRTUAL_MODULE_ID = 'virtual:keywords';\nexport const RESOLVED_VIRTUAL_MODULE_ID = `\\0${VIRTUAL_MODULE_ID}`;\n\nexport interface KeywordsPluginOptions {\n additionalModulesToScan?: string[];\n isDev?: boolean;\n}\n\nexport type ResolvedKeywordsPluginOptions = Required<\n Omit<KeywordsPluginOptions, 'isDev'>\n> & { isDev?: boolean };\n\nexport const resolveOptions = (\n options?: KeywordsPluginOptions,\n): ResolvedKeywordsPluginOptions => {\n return {\n additionalModulesToScan: options?.additionalModulesToScan || [],\n isDev: options?.isDev,\n };\n};\n\nexport interface Logger {\n info: (message: string) => void;\n warn: (message: string) => void;\n error: (message: string) => void;\n}\n\nexport interface PrefixedLogger extends Logger {\n pluginName: string;\n}\n\nexport const createPrefixedLogger = (\n logger: Logger,\n pluginName: string,\n usePrefix: boolean = true,\n): PrefixedLogger => {\n const prefix = usePrefix ? `[${pluginName}] ` : '';\n const prefixed = (message: string) => `${prefix}${message}`;\n return {\n pluginName,\n info: (message: string) => logger.info(prefixed(message)),\n warn: (message: string) => logger.warn(prefixed(message)),\n error: (message: string) => logger.error(prefixed(message)),\n };\n};\n\n// ref: https://github.com/babel/babel/discussions/13093\nconst traverse =\n typeof _traverse === 'function'\n ? _traverse\n : ((_traverse as any).default as typeof _traverse);\n\nexport const extractKeywords = (\n code: string,\n additionalModulesToScan: string[] = [],\n): Set<string> => {\n const keywords = new Set<string>();\n\n // Fast-path: Skip parsing if no relevant imports are present in the code.\n const containsTargetModule =\n code.includes(VIRTUAL_MODULE_ID) ||\n additionalModulesToScan.some((moduleName) => code.includes(moduleName));\n\n if (!containsTargetModule) {\n return keywords;\n }\n\n let ast: Node;\n try {\n ast = parse(code, {\n sourceType: 'module',\n plugins: ['typescript', 'jsx'],\n errorRecovery: true,\n });\n } catch (e) {\n return keywords;\n }\n\n const keywordNamespaces = new Set<string>();\n\n traverse(ast, {\n enter(nodePath) {\n const node = nodePath.node;\n\n if (node.type === 'ImportDeclaration') {\n const isTargetModule =\n node.source.value === VIRTUAL_MODULE_ID ||\n additionalModulesToScan.includes(node.source.value);\n\n if (isTargetModule) {\n for (const specifier of node.specifiers) {\n if (specifier.type === 'ImportNamespaceSpecifier') {\n keywordNamespaces.add(specifier.local.name);\n }\n\n if (specifier.type === 'ImportDefaultSpecifier') {\n keywords.add('default');\n }\n\n if (specifier.type === 'ImportSpecifier') {\n if (specifier.imported.type === 'Identifier') {\n keywords.add(specifier.imported.name);\n }\n }\n }\n }\n }\n },\n });\n\n if (keywordNamespaces.size === 0) {\n return keywords;\n }\n\n traverse(ast, {\n enter(nodePath) {\n const node = nodePath.node;\n\n if (\n node.type === 'MemberExpression' &&\n !node.computed && // Exclude computed properties like K['xyz']\n node.object.type === 'Identifier' &&\n keywordNamespaces.has(node.object.name) &&\n node.property.type === 'Identifier'\n ) {\n keywords.add(node.property.name);\n }\n\n if (\n node.type === 'TSQualifiedName' &&\n node.left.type === 'Identifier' &&\n keywordNamespaces.has(node.left.name) &&\n node.right.type === 'Identifier'\n ) {\n keywords.add(node.right.name);\n }\n },\n });\n\n return keywords;\n};\n\nconst keywordConstPrefix = '_';\nconst createExportDeclaration = (keywords: Set<string>): string[] => {\n const aliases = [...keywords].map(\n (key) => ` ${keywordConstPrefix}${key} as ${key},`,\n );\n return [`export {`, ...aliases, `};`];\n};\n\nexport const generateTypesFile = async (\n collectedKeywords: Set<string>,\n root: string,\n dirname: string = '.keywords',\n filename: string = 'index.d.ts',\n): Promise<void> => {\n const keywordDeclarations = [...collectedKeywords]\n .map((key) => `declare const ${keywordConstPrefix}${key}: unique symbol;`)\n .join('\\n');\n const exportDeclaration =\n createExportDeclaration(collectedKeywords).join('\\n');\n const content = `${keywordDeclarations}\\n${exportDeclaration}\\n`;\n const pluginRoot = path.join(root, dirname);\n await mkdir(pluginRoot, { recursive: true });\n await writeFile(path.join(pluginRoot, filename), `${content.trim()}\\n`);\n};\n\nexport const collectKeywordsFromFiles = async (\n root: string,\n logger: PrefixedLogger,\n ignoredDirs: string[] = [],\n options?: KeywordsPluginOptions,\n): Promise<Set<string>> => {\n const resolvedOptions = resolveOptions(options);\n const collectedKeywords = new Set<string>();\n\n logger.info('Scanning project files for keywords...');\n\n const files = await globby('**/*.{js,ts,jsx,tsx}', {\n cwd: root,\n absolute: true,\n ignore: ['**/node_modules/**', ...ignoredDirs.map((dir) => `${dir}/**`)],\n gitignore: true,\n });\n\n const concurrency = 100;\n for (let i = 0; i < files.length; i += concurrency) {\n const chunk = files.slice(i, i + concurrency);\n await Promise.all(\n chunk.map(async (file) => {\n try {\n const code = await readFile(file, 'utf-8');\n const keywords = extractKeywords(\n code,\n resolvedOptions.additionalModulesToScan,\n );\n for (const key of keywords) {\n collectedKeywords.add(key);\n }\n } catch (error: any) {\n logger.warn(`Failed to process file ${file}: ${error.message}`);\n }\n }),\n );\n }\n\n logger.info(\n `Scan complete. Found ${collectedKeywords.size} unique keywords.`,\n );\n\n return collectedKeywords;\n};\n\nexport const collectKeywordsAndGenerateTypes = async (\n root: string,\n logger: PrefixedLogger,\n ignoredDirs?: string[],\n options?: KeywordsPluginOptions,\n): Promise<Set<string>> => {\n const collectedKeywords = await collectKeywordsFromFiles(\n root,\n logger,\n ignoredDirs,\n options,\n );\n await generateTypesFile(collectedKeywords, root);\n return collectedKeywords;\n};\n\nexport const generateModuleCode = (\n collectedKeywords: Set<string>,\n isDev: boolean,\n): string => {\n const symbolConstructorName = '__SYMBOL__';\n const symbolDeclaration = `const ${symbolConstructorName} = Symbol;`;\n const keywordDeclarations = [...collectedKeywords]\n .map(\n (key) =>\n `const ${keywordConstPrefix}${key} = /* @__PURE__ */ ${symbolConstructorName}(${isDev ? `'${key}'` : ''});`,\n )\n .join('\\n');\n const exportDeclaration =\n createExportDeclaration(collectedKeywords).join('\\n');\n return `${symbolDeclaration}\\n${keywordDeclarations}\\n${exportDeclaration}\\n`;\n};\n\nexport const splitQuery = (id: string) => id.split('?');\n","export const PLUGIN_NAME = 'rollup-plugin-keywords';\n"],"mappings":";AAAA,OAAOA,WAAU;AACjB,SAAS,iBAAiB;;;ACD1B,SAAS,OAAO,UAAU,iBAAiB;AAC3C,OAAO,UAAU;AACjB,SAAS,aAAa;AACtB,OAAO,eAA8B;AACrC,SAAS,cAAc;AAEhB,IAAM,oBAAoB;AAC1B,IAAM,6BAA6B,KAAK,iBAAiB;AAWzD,IAAM,iBAAiB,CAC5B,YACkC;AAClC,SAAO;IACL,yBAAyB,SAAS,2BAA2B,CAAC;IAC9D,OAAO,SAAS;EAClB;AACF;AAYO,IAAM,uBAAuB,CAClC,QACA,YACA,YAAqB,SACF;AACnB,QAAM,SAAS,YAAY,IAAI,UAAU,OAAO;AAChD,QAAM,WAAW,CAAC,YAAoB,GAAG,MAAM,GAAG,OAAO;AACzD,SAAO;IACL;IACA,MAAM,CAAC,YAAoB,OAAO,KAAK,SAAS,OAAO,CAAC;IACxD,MAAM,CAAC,YAAoB,OAAO,KAAK,SAAS,OAAO,CAAC;IACxD,OAAO,CAAC,YAAoB,OAAO,MAAM,SAAS,OAAO,CAAC;EAC5D;AACF;AAGA,IAAM,WACJ,OAAO,cAAc,aACjB,YACE,UAAkB;AAEnB,IAAM,kBAAkB,CAC7B,MACA,0BAAoC,CAAC,MACrB;AAChB,QAAM,WAAW,oBAAI,IAAY;AAGjC,QAAM,uBACJ,KAAK,SAAS,iBAAiB,KAC/B,wBAAwB,KAAK,CAAC,eAAe,KAAK,SAAS,UAAU,CAAC;AAExE,MAAI,CAAC,sBAAsB;AACzB,WAAO;EACT;AAEA,MAAI;AACJ,MAAI;AACF,UAAM,MAAM,MAAM;MAChB,YAAY;MACZ,SAAS,CAAC,cAAc,KAAK;MAC7B,eAAe;IACjB,CAAC;EACH,SAAS,GAAG;AACV,WAAO;EACT;AAEA,QAAM,oBAAoB,oBAAI,IAAY;AAE1C,WAAS,KAAK;IACZ,MAAM,UAAU;AACd,YAAM,OAAO,SAAS;AAEtB,UAAI,KAAK,SAAS,qBAAqB;AACrC,cAAM,iBACJ,KAAK,OAAO,UAAU,qBACtB,wBAAwB,SAAS,KAAK,OAAO,KAAK;AAEpD,YAAI,gBAAgB;AAClB,qBAAW,aAAa,KAAK,YAAY;AACvC,gBAAI,UAAU,SAAS,4BAA4B;AACjD,gCAAkB,IAAI,UAAU,MAAM,IAAI;YAC5C;AAEA,gBAAI,UAAU,SAAS,0BAA0B;AAC/C,uBAAS,IAAI,SAAS;YACxB;AAEA,gBAAI,UAAU,SAAS,mBAAmB;AACxC,kBAAI,UAAU,SAAS,SAAS,cAAc;AAC5C,yBAAS,IAAI,UAAU,SAAS,IAAI;cACtC;YACF;UACF;QACF;MACF;IACF;EACF,CAAC;AAED,MAAI,kBAAkB,SAAS,GAAG;AAChC,WAAO;EACT;AAEA,WAAS,KAAK;IACZ,MAAM,UAAU;AACd,YAAM,OAAO,SAAS;AAEtB,UACE,KAAK,SAAS,sBACd,CAAC,KAAK;MACN,KAAK,OAAO,SAAS,gBACrB,kBAAkB,IAAI,KAAK,OAAO,IAAI,KACtC,KAAK,SAAS,SAAS,cACvB;AACA,iBAAS,IAAI,KAAK,SAAS,IAAI;MACjC;AAEA,UACE,KAAK,SAAS,qBACd,KAAK,KAAK,SAAS,gBACnB,kBAAkB,IAAI,KAAK,KAAK,IAAI,KACpC,KAAK,MAAM,SAAS,cACpB;AACA,iBAAS,IAAI,KAAK,MAAM,IAAI;MAC9B;IACF;EACF,CAAC;AAED,SAAO;AACT;AAEA,IAAM,qBAAqB;AAC3B,IAAM,0BAA0B,CAAC,aAAoC;AACnE,QAAM,UAAU,CAAC,GAAG,QAAQ,EAAE;IAC5B,CAAC,QAAQ,KAAK,kBAAkB,GAAG,GAAG,OAAO,GAAG;EAClD;AACA,SAAO,CAAC,YAAY,GAAG,SAAS,IAAI;AACtC;AAEO,IAAM,oBAAoB,OAC/B,mBACA,MACA,UAAkB,aAClB,WAAmB,iBACD;AAClB,QAAM,sBAAsB,CAAC,GAAG,iBAAiB,EAC9C,IAAI,CAAC,QAAQ,iBAAiB,kBAAkB,GAAG,GAAG,kBAAkB,EACxE,KAAK,IAAI;AACZ,QAAM,oBACJ,wBAAwB,iBAAiB,EAAE,KAAK,IAAI;AACtD,QAAM,UAAU,GAAG,mBAAmB;EAAK,iBAAiB;;AAC5D,QAAM,aAAa,KAAK,KAAK,MAAM,OAAO;AAC1C,QAAM,MAAM,YAAY,EAAE,WAAW,KAAK,CAAC;AAC3C,QAAM,UAAU,KAAK,KAAK,YAAY,QAAQ,GAAG,GAAG,QAAQ,KAAK,CAAC;CAAI;AACxE;AAEO,IAAM,2BAA2B,OACtC,MACA,QACA,cAAwB,CAAC,GACzB,YACyB;AACzB,QAAM,kBAAkB,eAAe,OAAO;AAC9C,QAAM,oBAAoB,oBAAI,IAAY;AAE1C,SAAO,KAAK,wCAAwC;AAEpD,QAAM,QAAQ,MAAM,OAAO,wBAAwB;IACjD,KAAK;IACL,UAAU;IACV,QAAQ,CAAC,sBAAsB,GAAG,YAAY,IAAI,CAAC,QAAQ,GAAG,GAAG,KAAK,CAAC;IACvE,WAAW;EACb,CAAC;AAED,QAAM,cAAc;AACpB,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK,aAAa;AAClD,UAAM,QAAQ,MAAM,MAAM,GAAG,IAAI,WAAW;AAC5C,UAAM,QAAQ;MACZ,MAAM,IAAI,OAAO,SAAS;AACxB,YAAI;AACF,gBAAM,OAAO,MAAM,SAAS,MAAM,OAAO;AACzC,gBAAM,WAAW;YACf;YACA,gBAAgB;UAClB;AACA,qBAAW,OAAO,UAAU;AAC1B,8BAAkB,IAAI,GAAG;UAC3B;QACF,SAAS,OAAY;AACnB,iBAAO,KAAK,0BAA0B,IAAI,KAAK,MAAM,OAAO,EAAE;QAChE;MACF,CAAC;IACH;EACF;AAEA,SAAO;IACL,wBAAwB,kBAAkB,IAAI;EAChD;AAEA,SAAO;AACT;AAEO,IAAM,kCAAkC,OAC7C,MACA,QACA,aACA,YACyB;AACzB,QAAM,oBAAoB,MAAM;IAC9B;IACA;IACA;IACA;EACF;AACA,QAAM,kBAAkB,mBAAmB,IAAI;AAC/C,SAAO;AACT;;;ADnOA,SAAS,sBAAsB;;;AENxB,IAAM,cAAc;;;AFS3B,IAAM,OAAO,YAAY;AACvB,QAAM,OAAO,QAAQ,IAAI;AACzB,QAAM,SAAS,qBAAqB,SAAS,WAAW;AAExD,QAAM,EAAE,OAAO,IAAI,UAAU;AAAA,IAC3B,SAAS;AAAA,MACP,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,OAAO;AAAA,MACT;AAAA,MACA,cAAc;AAAA,QACZ,MAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,QAAQ;AAAA,EACV,CAAC;AAED,QAAM,aAAaC,MAAK;AAAA,IACtB;AAAA,IACA,OAAO,OAAO,WAAW,WAAW,OAAO,SAAS;AAAA,EACtD;AAEA,QAAM,iBAAsC,CAAC;AAC7C,MAAI,OAAO,OAAO,iBAAiB,UAAU;AAC3C,mBAAe,eAAe,OAAO;AAAA,EACvC;AAEA,MAAI;AACJ,MAAI;AACJ,MAAI;AAEJ,MAAI;AACF,UAAM,SAAS,MAAM,eAAe,YAAY,cAAc;AAC9D,cAAU,OAAO;AACjB,eAAW,OAAO;AAClB,aAAS,MAAM;AAAA,EACjB,SAAS,OAAY;AACnB,WAAO,MAAM,uCAAuC,MAAM,OAAO,EAAE;AACnE,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,aAAW,UAAU,SAAS;AAC5B,QAAI,CAAC,OAAO,QAAS;AAErB,UAAM,iBAAiB,OAAO,QAAQ;AAAA,MACpC,CAAC,WAAgB,UAAU,OAAO,SAAS;AAAA,IAC7C;AAEA,QAAI,gBAAgB;AAClB,sBAAiB,eAAuB,KAAK;AAC7C;AAAA,IACF;AAAA,EACF;AAEA,MAAI,CAAC,eAAe;AAClB,WAAO,MAAM,oDAAoD;AACjE,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,MAAI;AACF,UAAM,gCAAgC,MAAM,QAAQ,CAAC,GAAG,aAAa;AAAA,EACvE,SAAS,OAAY;AACnB,WAAO;AAAA,MACL,kDAAkD,MAAM,OAAO;AAAA,IACjE;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;AAEA,MAAM,KAAK;","names":["path","path"]}
|
package/dist/index.cjs
CHANGED
|
@@ -45,7 +45,8 @@ var VIRTUAL_MODULE_ID = "virtual:keywords";
|
|
|
45
45
|
var RESOLVED_VIRTUAL_MODULE_ID = `\0${VIRTUAL_MODULE_ID}`;
|
|
46
46
|
var resolveOptions = (options) => {
|
|
47
47
|
return {
|
|
48
|
-
additionalModulesToScan: options?.additionalModulesToScan || []
|
|
48
|
+
additionalModulesToScan: options?.additionalModulesToScan || [],
|
|
49
|
+
isDev: options?.isDev
|
|
49
50
|
};
|
|
50
51
|
};
|
|
51
52
|
var createPrefixedLogger = (logger, pluginName, usePrefix = true) => {
|
|
@@ -202,7 +203,7 @@ var keywordsPlugin = (options) => {
|
|
|
202
203
|
let collectedKeywords;
|
|
203
204
|
let logger;
|
|
204
205
|
const root = process.cwd();
|
|
205
|
-
const isDev = process.env.NODE_ENV === "development";
|
|
206
|
+
const isDev = pluginOptions.isDev ?? process.env.NODE_ENV === "development";
|
|
206
207
|
return {
|
|
207
208
|
name: PLUGIN_NAME,
|
|
208
209
|
api: {
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../../minifiable-keywords/src/index.ts","../src/shared.ts"],"sourcesContent":["import {\n collectKeywordsAndGenerateTypes,\n createPrefixedLogger,\n generateModuleCode,\n RESOLVED_VIRTUAL_MODULE_ID,\n resolveOptions,\n splitQuery,\n VIRTUAL_MODULE_ID,\n type KeywordsPluginOptions,\n type PrefixedLogger,\n} from 'minifiable-keywords';\nimport type { Plugin } from 'rollup';\nimport { PLUGIN_NAME } from './shared';\n\nexport type { KeywordsPluginOptions } from 'minifiable-keywords';\n\nexport const keywordsPlugin = (options?: KeywordsPluginOptions): Plugin => {\n const pluginOptions = resolveOptions(options);\n let collectedKeywords: Set<string>;\n let logger: PrefixedLogger;\n const root = process.cwd();\n const isDev = process.env.NODE_ENV === 'development';\n\n return {\n name: PLUGIN_NAME,\n api: {\n options: pluginOptions,\n },\n\n async buildStart() {\n const pluginThis = this;\n logger = createPrefixedLogger(\n {\n info: pluginThis.info,\n warn: pluginThis.warn,\n error: pluginThis.error,\n },\n PLUGIN_NAME,\n false,\n );\n collectedKeywords = await collectKeywordsAndGenerateTypes(\n root,\n logger,\n [],\n pluginOptions,\n );\n },\n\n resolveId(source, importer) {\n if (!importer) {\n return;\n }\n const [validSource] = splitQuery(source);\n if (validSource === VIRTUAL_MODULE_ID) {\n return RESOLVED_VIRTUAL_MODULE_ID;\n }\n },\n\n load(id) {\n const [validId] = splitQuery(id);\n if (validId === RESOLVED_VIRTUAL_MODULE_ID) {\n return generateModuleCode(collectedKeywords, isDev);\n }\n },\n };\n};\n\nexport default keywordsPlugin;\n","import { mkdir, readFile, writeFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport { parse } from '@babel/parser';\nimport _traverse, { type Node } from '@babel/traverse';\nimport { globby } from 'globby';\n\nexport const VIRTUAL_MODULE_ID = 'virtual:keywords';\nexport const RESOLVED_VIRTUAL_MODULE_ID = `\\0${VIRTUAL_MODULE_ID}`;\n\nexport interface KeywordsPluginOptions {\n additionalModulesToScan?: string[];\n}\n\nexport type ResolvedKeywordsPluginOptions = Required<KeywordsPluginOptions>;\n\nexport const resolveOptions = (\n options?: KeywordsPluginOptions,\n): ResolvedKeywordsPluginOptions => {\n return {\n additionalModulesToScan: options?.additionalModulesToScan || [],\n };\n};\n\nexport interface Logger {\n info: (message: string) => void;\n warn: (message: string) => void;\n error: (message: string) => void;\n}\n\nexport interface PrefixedLogger extends Logger {\n pluginName: string;\n}\n\nexport const createPrefixedLogger = (\n logger: Logger,\n pluginName: string,\n usePrefix: boolean = true,\n): PrefixedLogger => {\n const prefix = usePrefix ? `[${pluginName}] ` : '';\n const prefixed = (message: string) => `${prefix}${message}`;\n return {\n pluginName,\n info: (message: string) => logger.info(prefixed(message)),\n warn: (message: string) => logger.warn(prefixed(message)),\n error: (message: string) => logger.error(prefixed(message)),\n };\n};\n\n// ref: https://github.com/babel/babel/discussions/13093\nconst traverse =\n typeof _traverse === 'function'\n ? _traverse\n : ((_traverse as any).default as typeof _traverse);\n\nexport const extractKeywords = (\n code: string,\n additionalModulesToScan: string[] = [],\n): Set<string> => {\n const keywords = new Set<string>();\n\n // Fast-path: Skip parsing if no relevant imports are present in the code.\n const containsTargetModule =\n code.includes(VIRTUAL_MODULE_ID) ||\n additionalModulesToScan.some((moduleName) => code.includes(moduleName));\n\n if (!containsTargetModule) {\n return keywords;\n }\n\n let ast: Node;\n try {\n ast = parse(code, {\n sourceType: 'module',\n plugins: ['typescript', 'jsx'],\n errorRecovery: true,\n });\n } catch (e) {\n return keywords;\n }\n\n const keywordNamespaces = new Set<string>();\n\n traverse(ast, {\n enter(nodePath) {\n const node = nodePath.node;\n\n if (node.type === 'ImportDeclaration') {\n const isTargetModule =\n node.source.value === VIRTUAL_MODULE_ID ||\n additionalModulesToScan.includes(node.source.value);\n\n if (isTargetModule) {\n for (const specifier of node.specifiers) {\n if (specifier.type === 'ImportNamespaceSpecifier') {\n keywordNamespaces.add(specifier.local.name);\n }\n\n if (specifier.type === 'ImportDefaultSpecifier') {\n keywords.add('default');\n }\n\n if (specifier.type === 'ImportSpecifier') {\n if (specifier.imported.type === 'Identifier') {\n keywords.add(specifier.imported.name);\n }\n }\n }\n }\n }\n },\n });\n\n if (keywordNamespaces.size === 0) {\n return keywords;\n }\n\n traverse(ast, {\n enter(nodePath) {\n const node = nodePath.node;\n\n if (\n node.type === 'MemberExpression' &&\n !node.computed && // Exclude computed properties like K['xyz']\n node.object.type === 'Identifier' &&\n keywordNamespaces.has(node.object.name) &&\n node.property.type === 'Identifier'\n ) {\n keywords.add(node.property.name);\n }\n\n if (\n node.type === 'TSQualifiedName' &&\n node.left.type === 'Identifier' &&\n keywordNamespaces.has(node.left.name) &&\n node.right.type === 'Identifier'\n ) {\n keywords.add(node.right.name);\n }\n },\n });\n\n return keywords;\n};\n\nconst keywordConstPrefix = '_';\nconst createExportDeclaration = (keywords: Set<string>): string[] => {\n const aliases = [...keywords].map(\n (key) => ` ${keywordConstPrefix}${key} as ${key},`,\n );\n return [`export {`, ...aliases, `};`];\n};\n\nexport const generateTypesFile = async (\n collectedKeywords: Set<string>,\n root: string,\n dirname: string = '.keywords',\n filename: string = 'index.d.ts',\n): Promise<void> => {\n const keywordDeclarations = [...collectedKeywords]\n .map((key) => `declare const ${keywordConstPrefix}${key}: unique symbol;`)\n .join('\\n');\n const exportDeclaration =\n createExportDeclaration(collectedKeywords).join('\\n');\n const content = `${keywordDeclarations}\\n${exportDeclaration}\\n`;\n const pluginRoot = path.join(root, dirname);\n await mkdir(pluginRoot, { recursive: true });\n await writeFile(path.join(pluginRoot, filename), `${content.trim()}\\n`);\n};\n\nexport const collectKeywordsFromFiles = async (\n root: string,\n logger: PrefixedLogger,\n ignoredDirs: string[] = [],\n options?: KeywordsPluginOptions,\n): Promise<Set<string>> => {\n const resolvedOptions = resolveOptions(options);\n const collectedKeywords = new Set<string>();\n\n logger.info('Scanning project files for keywords...');\n\n const files = await globby('**/*.{js,ts,jsx,tsx}', {\n cwd: root,\n absolute: true,\n ignore: ['**/node_modules/**', ...ignoredDirs.map((dir) => `${dir}/**`)],\n gitignore: true,\n });\n\n const concurrency = 100;\n for (let i = 0; i < files.length; i += concurrency) {\n const chunk = files.slice(i, i + concurrency);\n await Promise.all(\n chunk.map(async (file) => {\n try {\n const code = await readFile(file, 'utf-8');\n const keywords = extractKeywords(\n code,\n resolvedOptions.additionalModulesToScan,\n );\n for (const key of keywords) {\n collectedKeywords.add(key);\n }\n } catch (error: any) {\n logger.warn(`Failed to process file ${file}: ${error.message}`);\n }\n }),\n );\n }\n\n logger.info(\n `Scan complete. Found ${collectedKeywords.size} unique keywords.`,\n );\n\n return collectedKeywords;\n};\n\nexport const collectKeywordsAndGenerateTypes = async (\n root: string,\n logger: PrefixedLogger,\n ignoredDirs?: string[],\n options?: KeywordsPluginOptions,\n): Promise<Set<string>> => {\n const collectedKeywords = await collectKeywordsFromFiles(\n root,\n logger,\n ignoredDirs,\n options,\n );\n await generateTypesFile(collectedKeywords, root);\n return collectedKeywords;\n};\n\nexport const generateModuleCode = (\n collectedKeywords: Set<string>,\n isDev: boolean,\n): string => {\n const symbolConstructorName = '__SYMBOL__';\n const symbolDeclaration = `const ${symbolConstructorName} = Symbol;`;\n const keywordDeclarations = [...collectedKeywords]\n .map(\n (key) =>\n `const ${keywordConstPrefix}${key} = /* @__PURE__ */ ${symbolConstructorName}(${isDev ? `'${key}'` : ''});`,\n )\n .join('\\n');\n const exportDeclaration =\n createExportDeclaration(collectedKeywords).join('\\n');\n return `${symbolDeclaration}\\n${keywordDeclarations}\\n${exportDeclaration}\\n`;\n};\n\nexport const splitQuery = (id: string) => id.split('?');\n","export const PLUGIN_NAME = 'rollup-plugin-keywords';\n"],"mappings":"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","names":["_traverse","path"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../../minifiable-keywords/src/index.ts","../src/shared.ts"],"sourcesContent":["import {\n collectKeywordsAndGenerateTypes,\n createPrefixedLogger,\n generateModuleCode,\n RESOLVED_VIRTUAL_MODULE_ID,\n resolveOptions,\n splitQuery,\n VIRTUAL_MODULE_ID,\n type KeywordsPluginOptions,\n type PrefixedLogger,\n} from 'minifiable-keywords';\nimport type { Plugin } from 'rollup';\nimport { PLUGIN_NAME } from './shared';\n\nexport type { KeywordsPluginOptions } from 'minifiable-keywords';\n\nexport const keywordsPlugin = (options?: KeywordsPluginOptions): Plugin => {\n const pluginOptions = resolveOptions(options);\n let collectedKeywords: Set<string>;\n let logger: PrefixedLogger;\n const root = process.cwd();\n const isDev = pluginOptions.isDev ?? process.env.NODE_ENV === 'development';\n\n return {\n name: PLUGIN_NAME,\n api: {\n options: pluginOptions,\n },\n\n async buildStart() {\n const pluginThis = this;\n logger = createPrefixedLogger(\n {\n info: pluginThis.info,\n warn: pluginThis.warn,\n error: pluginThis.error,\n },\n PLUGIN_NAME,\n false,\n );\n collectedKeywords = await collectKeywordsAndGenerateTypes(\n root,\n logger,\n [],\n pluginOptions,\n );\n },\n\n resolveId(source, importer) {\n if (!importer) {\n return;\n }\n const [validSource] = splitQuery(source);\n if (validSource === VIRTUAL_MODULE_ID) {\n return RESOLVED_VIRTUAL_MODULE_ID;\n }\n },\n\n load(id) {\n const [validId] = splitQuery(id);\n if (validId === RESOLVED_VIRTUAL_MODULE_ID) {\n return generateModuleCode(collectedKeywords, isDev);\n }\n },\n };\n};\n\nexport default keywordsPlugin;\n","import { mkdir, readFile, writeFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport { parse } from '@babel/parser';\nimport _traverse, { type Node } from '@babel/traverse';\nimport { globby } from 'globby';\n\nexport const VIRTUAL_MODULE_ID = 'virtual:keywords';\nexport const RESOLVED_VIRTUAL_MODULE_ID = `\\0${VIRTUAL_MODULE_ID}`;\n\nexport interface KeywordsPluginOptions {\n additionalModulesToScan?: string[];\n isDev?: boolean;\n}\n\nexport type ResolvedKeywordsPluginOptions = Required<\n Omit<KeywordsPluginOptions, 'isDev'>\n> & { isDev?: boolean };\n\nexport const resolveOptions = (\n options?: KeywordsPluginOptions,\n): ResolvedKeywordsPluginOptions => {\n return {\n additionalModulesToScan: options?.additionalModulesToScan || [],\n isDev: options?.isDev,\n };\n};\n\nexport interface Logger {\n info: (message: string) => void;\n warn: (message: string) => void;\n error: (message: string) => void;\n}\n\nexport interface PrefixedLogger extends Logger {\n pluginName: string;\n}\n\nexport const createPrefixedLogger = (\n logger: Logger,\n pluginName: string,\n usePrefix: boolean = true,\n): PrefixedLogger => {\n const prefix = usePrefix ? `[${pluginName}] ` : '';\n const prefixed = (message: string) => `${prefix}${message}`;\n return {\n pluginName,\n info: (message: string) => logger.info(prefixed(message)),\n warn: (message: string) => logger.warn(prefixed(message)),\n error: (message: string) => logger.error(prefixed(message)),\n };\n};\n\n// ref: https://github.com/babel/babel/discussions/13093\nconst traverse =\n typeof _traverse === 'function'\n ? _traverse\n : ((_traverse as any).default as typeof _traverse);\n\nexport const extractKeywords = (\n code: string,\n additionalModulesToScan: string[] = [],\n): Set<string> => {\n const keywords = new Set<string>();\n\n // Fast-path: Skip parsing if no relevant imports are present in the code.\n const containsTargetModule =\n code.includes(VIRTUAL_MODULE_ID) ||\n additionalModulesToScan.some((moduleName) => code.includes(moduleName));\n\n if (!containsTargetModule) {\n return keywords;\n }\n\n let ast: Node;\n try {\n ast = parse(code, {\n sourceType: 'module',\n plugins: ['typescript', 'jsx'],\n errorRecovery: true,\n });\n } catch (e) {\n return keywords;\n }\n\n const keywordNamespaces = new Set<string>();\n\n traverse(ast, {\n enter(nodePath) {\n const node = nodePath.node;\n\n if (node.type === 'ImportDeclaration') {\n const isTargetModule =\n node.source.value === VIRTUAL_MODULE_ID ||\n additionalModulesToScan.includes(node.source.value);\n\n if (isTargetModule) {\n for (const specifier of node.specifiers) {\n if (specifier.type === 'ImportNamespaceSpecifier') {\n keywordNamespaces.add(specifier.local.name);\n }\n\n if (specifier.type === 'ImportDefaultSpecifier') {\n keywords.add('default');\n }\n\n if (specifier.type === 'ImportSpecifier') {\n if (specifier.imported.type === 'Identifier') {\n keywords.add(specifier.imported.name);\n }\n }\n }\n }\n }\n },\n });\n\n if (keywordNamespaces.size === 0) {\n return keywords;\n }\n\n traverse(ast, {\n enter(nodePath) {\n const node = nodePath.node;\n\n if (\n node.type === 'MemberExpression' &&\n !node.computed && // Exclude computed properties like K['xyz']\n node.object.type === 'Identifier' &&\n keywordNamespaces.has(node.object.name) &&\n node.property.type === 'Identifier'\n ) {\n keywords.add(node.property.name);\n }\n\n if (\n node.type === 'TSQualifiedName' &&\n node.left.type === 'Identifier' &&\n keywordNamespaces.has(node.left.name) &&\n node.right.type === 'Identifier'\n ) {\n keywords.add(node.right.name);\n }\n },\n });\n\n return keywords;\n};\n\nconst keywordConstPrefix = '_';\nconst createExportDeclaration = (keywords: Set<string>): string[] => {\n const aliases = [...keywords].map(\n (key) => ` ${keywordConstPrefix}${key} as ${key},`,\n );\n return [`export {`, ...aliases, `};`];\n};\n\nexport const generateTypesFile = async (\n collectedKeywords: Set<string>,\n root: string,\n dirname: string = '.keywords',\n filename: string = 'index.d.ts',\n): Promise<void> => {\n const keywordDeclarations = [...collectedKeywords]\n .map((key) => `declare const ${keywordConstPrefix}${key}: unique symbol;`)\n .join('\\n');\n const exportDeclaration =\n createExportDeclaration(collectedKeywords).join('\\n');\n const content = `${keywordDeclarations}\\n${exportDeclaration}\\n`;\n const pluginRoot = path.join(root, dirname);\n await mkdir(pluginRoot, { recursive: true });\n await writeFile(path.join(pluginRoot, filename), `${content.trim()}\\n`);\n};\n\nexport const collectKeywordsFromFiles = async (\n root: string,\n logger: PrefixedLogger,\n ignoredDirs: string[] = [],\n options?: KeywordsPluginOptions,\n): Promise<Set<string>> => {\n const resolvedOptions = resolveOptions(options);\n const collectedKeywords = new Set<string>();\n\n logger.info('Scanning project files for keywords...');\n\n const files = await globby('**/*.{js,ts,jsx,tsx}', {\n cwd: root,\n absolute: true,\n ignore: ['**/node_modules/**', ...ignoredDirs.map((dir) => `${dir}/**`)],\n gitignore: true,\n });\n\n const concurrency = 100;\n for (let i = 0; i < files.length; i += concurrency) {\n const chunk = files.slice(i, i + concurrency);\n await Promise.all(\n chunk.map(async (file) => {\n try {\n const code = await readFile(file, 'utf-8');\n const keywords = extractKeywords(\n code,\n resolvedOptions.additionalModulesToScan,\n );\n for (const key of keywords) {\n collectedKeywords.add(key);\n }\n } catch (error: any) {\n logger.warn(`Failed to process file ${file}: ${error.message}`);\n }\n }),\n );\n }\n\n logger.info(\n `Scan complete. Found ${collectedKeywords.size} unique keywords.`,\n );\n\n return collectedKeywords;\n};\n\nexport const collectKeywordsAndGenerateTypes = async (\n root: string,\n logger: PrefixedLogger,\n ignoredDirs?: string[],\n options?: KeywordsPluginOptions,\n): Promise<Set<string>> => {\n const collectedKeywords = await collectKeywordsFromFiles(\n root,\n logger,\n ignoredDirs,\n options,\n );\n await generateTypesFile(collectedKeywords, root);\n return collectedKeywords;\n};\n\nexport const generateModuleCode = (\n collectedKeywords: Set<string>,\n isDev: boolean,\n): string => {\n const symbolConstructorName = '__SYMBOL__';\n const symbolDeclaration = `const ${symbolConstructorName} = Symbol;`;\n const keywordDeclarations = [...collectedKeywords]\n .map(\n (key) =>\n `const ${keywordConstPrefix}${key} = /* @__PURE__ */ ${symbolConstructorName}(${isDev ? `'${key}'` : ''});`,\n )\n .join('\\n');\n const exportDeclaration =\n createExportDeclaration(collectedKeywords).join('\\n');\n return `${symbolDeclaration}\\n${keywordDeclarations}\\n${exportDeclaration}\\n`;\n};\n\nexport const splitQuery = (id: string) => id.split('?');\n","export const PLUGIN_NAME = 'rollup-plugin-keywords';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,sBAA2C;AAC3C,kBAAiB;AACjB,oBAAsB;AACtB,sBAAqC;AACrC,oBAAuB;AAEhB,IAAM,oBAAoB;AAC1B,IAAM,6BAA6B,KAAK,iBAAiB;AAWzD,IAAM,iBAAiB,CAC5B,YACkC;AAClC,SAAO;IACL,yBAAyB,SAAS,2BAA2B,CAAC;IAC9D,OAAO,SAAS;EAClB;AACF;AAYO,IAAM,uBAAuB,CAClC,QACA,YACA,YAAqB,SACF;AACnB,QAAM,SAAS,YAAY,IAAI,UAAU,OAAO;AAChD,QAAM,WAAW,CAAC,YAAoB,GAAG,MAAM,GAAG,OAAO;AACzD,SAAO;IACL;IACA,MAAM,CAAC,YAAoB,OAAO,KAAK,SAAS,OAAO,CAAC;IACxD,MAAM,CAAC,YAAoB,OAAO,KAAK,SAAS,OAAO,CAAC;IACxD,OAAO,CAAC,YAAoB,OAAO,MAAM,SAAS,OAAO,CAAC;EAC5D;AACF;AAGA,IAAM,WACJ,OAAO,gBAAAA,YAAc,aACjB,gBAAAA,UACE,gBAAAA,QAAkB;AAEnB,IAAM,kBAAkB,CAC7B,MACA,0BAAoC,CAAC,MACrB;AAChB,QAAM,WAAW,oBAAI,IAAY;AAGjC,QAAM,uBACJ,KAAK,SAAS,iBAAiB,KAC/B,wBAAwB,KAAK,CAAC,eAAe,KAAK,SAAS,UAAU,CAAC;AAExE,MAAI,CAAC,sBAAsB;AACzB,WAAO;EACT;AAEA,MAAI;AACJ,MAAI;AACF,cAAM,qBAAM,MAAM;MAChB,YAAY;MACZ,SAAS,CAAC,cAAc,KAAK;MAC7B,eAAe;IACjB,CAAC;EACH,SAAS,GAAG;AACV,WAAO;EACT;AAEA,QAAM,oBAAoB,oBAAI,IAAY;AAE1C,WAAS,KAAK;IACZ,MAAM,UAAU;AACd,YAAM,OAAO,SAAS;AAEtB,UAAI,KAAK,SAAS,qBAAqB;AACrC,cAAM,iBACJ,KAAK,OAAO,UAAU,qBACtB,wBAAwB,SAAS,KAAK,OAAO,KAAK;AAEpD,YAAI,gBAAgB;AAClB,qBAAW,aAAa,KAAK,YAAY;AACvC,gBAAI,UAAU,SAAS,4BAA4B;AACjD,gCAAkB,IAAI,UAAU,MAAM,IAAI;YAC5C;AAEA,gBAAI,UAAU,SAAS,0BAA0B;AAC/C,uBAAS,IAAI,SAAS;YACxB;AAEA,gBAAI,UAAU,SAAS,mBAAmB;AACxC,kBAAI,UAAU,SAAS,SAAS,cAAc;AAC5C,yBAAS,IAAI,UAAU,SAAS,IAAI;cACtC;YACF;UACF;QACF;MACF;IACF;EACF,CAAC;AAED,MAAI,kBAAkB,SAAS,GAAG;AAChC,WAAO;EACT;AAEA,WAAS,KAAK;IACZ,MAAM,UAAU;AACd,YAAM,OAAO,SAAS;AAEtB,UACE,KAAK,SAAS,sBACd,CAAC,KAAK;MACN,KAAK,OAAO,SAAS,gBACrB,kBAAkB,IAAI,KAAK,OAAO,IAAI,KACtC,KAAK,SAAS,SAAS,cACvB;AACA,iBAAS,IAAI,KAAK,SAAS,IAAI;MACjC;AAEA,UACE,KAAK,SAAS,qBACd,KAAK,KAAK,SAAS,gBACnB,kBAAkB,IAAI,KAAK,KAAK,IAAI,KACpC,KAAK,MAAM,SAAS,cACpB;AACA,iBAAS,IAAI,KAAK,MAAM,IAAI;MAC9B;IACF;EACF,CAAC;AAED,SAAO;AACT;AAEA,IAAM,qBAAqB;AAC3B,IAAM,0BAA0B,CAAC,aAAoC;AACnE,QAAM,UAAU,CAAC,GAAG,QAAQ,EAAE;IAC5B,CAAC,QAAQ,KAAK,kBAAkB,GAAG,GAAG,OAAO,GAAG;EAClD;AACA,SAAO,CAAC,YAAY,GAAG,SAAS,IAAI;AACtC;AAEO,IAAM,oBAAoB,OAC/B,mBACA,MACA,UAAkB,aAClB,WAAmB,iBACD;AAClB,QAAM,sBAAsB,CAAC,GAAG,iBAAiB,EAC9C,IAAI,CAAC,QAAQ,iBAAiB,kBAAkB,GAAG,GAAG,kBAAkB,EACxE,KAAK,IAAI;AACZ,QAAM,oBACJ,wBAAwB,iBAAiB,EAAE,KAAK,IAAI;AACtD,QAAM,UAAU,GAAG,mBAAmB;EAAK,iBAAiB;;AAC5D,QAAM,aAAa,YAAAC,QAAK,KAAK,MAAM,OAAO;AAC1C,YAAM,uBAAM,YAAY,EAAE,WAAW,KAAK,CAAC;AAC3C,YAAM,2BAAU,YAAAA,QAAK,KAAK,YAAY,QAAQ,GAAG,GAAG,QAAQ,KAAK,CAAC;CAAI;AACxE;AAEO,IAAM,2BAA2B,OACtC,MACA,QACA,cAAwB,CAAC,GACzB,YACyB;AACzB,QAAM,kBAAkB,eAAe,OAAO;AAC9C,QAAM,oBAAoB,oBAAI,IAAY;AAE1C,SAAO,KAAK,wCAAwC;AAEpD,QAAM,QAAQ,UAAM,sBAAO,wBAAwB;IACjD,KAAK;IACL,UAAU;IACV,QAAQ,CAAC,sBAAsB,GAAG,YAAY,IAAI,CAAC,QAAQ,GAAG,GAAG,KAAK,CAAC;IACvE,WAAW;EACb,CAAC;AAED,QAAM,cAAc;AACpB,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK,aAAa;AAClD,UAAM,QAAQ,MAAM,MAAM,GAAG,IAAI,WAAW;AAC5C,UAAM,QAAQ;MACZ,MAAM,IAAI,OAAO,SAAS;AACxB,YAAI;AACF,gBAAM,OAAO,UAAM,0BAAS,MAAM,OAAO;AACzC,gBAAM,WAAW;YACf;YACA,gBAAgB;UAClB;AACA,qBAAW,OAAO,UAAU;AAC1B,8BAAkB,IAAI,GAAG;UAC3B;QACF,SAAS,OAAY;AACnB,iBAAO,KAAK,0BAA0B,IAAI,KAAK,MAAM,OAAO,EAAE;QAChE;MACF,CAAC;IACH;EACF;AAEA,SAAO;IACL,wBAAwB,kBAAkB,IAAI;EAChD;AAEA,SAAO;AACT;AAEO,IAAM,kCAAkC,OAC7C,MACA,QACA,aACA,YACyB;AACzB,QAAM,oBAAoB,MAAM;IAC9B;IACA;IACA;IACA;EACF;AACA,QAAM,kBAAkB,mBAAmB,IAAI;AAC/C,SAAO;AACT;AAEO,IAAM,qBAAqB,CAChC,mBACA,UACW;AACX,QAAM,wBAAwB;AAC9B,QAAM,oBAAoB,SAAS,qBAAqB;AACxD,QAAM,sBAAsB,CAAC,GAAG,iBAAiB,EAC9C;IACC,CAAC,QACC,SAAS,kBAAkB,GAAG,GAAG,sBAAsB,qBAAqB,IAAI,QAAQ,IAAI,GAAG,MAAM,EAAE;EAC3G,EACC,KAAK,IAAI;AACZ,QAAM,oBACJ,wBAAwB,iBAAiB,EAAE,KAAK,IAAI;AACtD,SAAO,GAAG,iBAAiB;EAAK,mBAAmB;EAAK,iBAAiB;;AAC3E;AAEO,IAAM,aAAa,CAAC,OAAe,GAAG,MAAM,GAAG;;;AC5P/C,IAAM,cAAc;;;AFgBpB,IAAM,iBAAiB,CAAC,YAA4C;AACzE,QAAM,gBAAgB,eAAe,OAAO;AAC5C,MAAI;AACJ,MAAI;AACJ,QAAM,OAAO,QAAQ,IAAI;AACzB,QAAM,QAAQ,cAAc,SAAS,QAAQ,IAAI,aAAa;AAE9D,SAAO;AAAA,IACL,MAAM;AAAA,IACN,KAAK;AAAA,MACH,SAAS;AAAA,IACX;AAAA,IAEA,MAAM,aAAa;AACjB,YAAM,aAAa;AACnB,eAAS;AAAA,QACP;AAAA,UACE,MAAM,WAAW;AAAA,UACjB,MAAM,WAAW;AAAA,UACjB,OAAO,WAAW;AAAA,QACpB;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA,0BAAoB,MAAM;AAAA,QACxB;AAAA,QACA;AAAA,QACA,CAAC;AAAA,QACD;AAAA,MACF;AAAA,IACF;AAAA,IAEA,UAAU,QAAQ,UAAU;AAC1B,UAAI,CAAC,UAAU;AACb;AAAA,MACF;AACA,YAAM,CAAC,WAAW,IAAI,WAAW,MAAM;AACvC,UAAI,gBAAgB,mBAAmB;AACrC,eAAO;AAAA,MACT;AAAA,IACF;AAAA,IAEA,KAAK,IAAI;AACP,YAAM,CAAC,OAAO,IAAI,WAAW,EAAE;AAC/B,UAAI,YAAY,4BAA4B;AAC1C,eAAO,mBAAmB,mBAAmB,KAAK;AAAA,MACpD;AAAA,IACF;AAAA,EACF;AACF;AAEA,IAAO,gBAAQ;","names":["_traverse","path"]}
|
package/dist/index.d.cts
CHANGED
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -8,7 +8,8 @@ var VIRTUAL_MODULE_ID = "virtual:keywords";
|
|
|
8
8
|
var RESOLVED_VIRTUAL_MODULE_ID = `\0${VIRTUAL_MODULE_ID}`;
|
|
9
9
|
var resolveOptions = (options) => {
|
|
10
10
|
return {
|
|
11
|
-
additionalModulesToScan: options?.additionalModulesToScan || []
|
|
11
|
+
additionalModulesToScan: options?.additionalModulesToScan || [],
|
|
12
|
+
isDev: options?.isDev
|
|
12
13
|
};
|
|
13
14
|
};
|
|
14
15
|
var createPrefixedLogger = (logger, pluginName, usePrefix = true) => {
|
|
@@ -165,7 +166,7 @@ var keywordsPlugin = (options) => {
|
|
|
165
166
|
let collectedKeywords;
|
|
166
167
|
let logger;
|
|
167
168
|
const root = process.cwd();
|
|
168
|
-
const isDev = process.env.NODE_ENV === "development";
|
|
169
|
+
const isDev = pluginOptions.isDev ?? process.env.NODE_ENV === "development";
|
|
169
170
|
return {
|
|
170
171
|
name: PLUGIN_NAME,
|
|
171
172
|
api: {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../minifiable-keywords/src/index.ts","../src/shared.ts","../src/index.ts"],"sourcesContent":["import { mkdir, readFile, writeFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport { parse } from '@babel/parser';\nimport _traverse, { type Node } from '@babel/traverse';\nimport { globby } from 'globby';\n\nexport const VIRTUAL_MODULE_ID = 'virtual:keywords';\nexport const RESOLVED_VIRTUAL_MODULE_ID = `\\0${VIRTUAL_MODULE_ID}`;\n\nexport interface KeywordsPluginOptions {\n additionalModulesToScan?: string[];\n}\n\nexport type ResolvedKeywordsPluginOptions = Required<KeywordsPluginOptions>;\n\nexport const resolveOptions = (\n options?: KeywordsPluginOptions,\n): ResolvedKeywordsPluginOptions => {\n return {\n additionalModulesToScan: options?.additionalModulesToScan || [],\n };\n};\n\nexport interface Logger {\n info: (message: string) => void;\n warn: (message: string) => void;\n error: (message: string) => void;\n}\n\nexport interface PrefixedLogger extends Logger {\n pluginName: string;\n}\n\nexport const createPrefixedLogger = (\n logger: Logger,\n pluginName: string,\n usePrefix: boolean = true,\n): PrefixedLogger => {\n const prefix = usePrefix ? `[${pluginName}] ` : '';\n const prefixed = (message: string) => `${prefix}${message}`;\n return {\n pluginName,\n info: (message: string) => logger.info(prefixed(message)),\n warn: (message: string) => logger.warn(prefixed(message)),\n error: (message: string) => logger.error(prefixed(message)),\n };\n};\n\n// ref: https://github.com/babel/babel/discussions/13093\nconst traverse =\n typeof _traverse === 'function'\n ? _traverse\n : ((_traverse as any).default as typeof _traverse);\n\nexport const extractKeywords = (\n code: string,\n additionalModulesToScan: string[] = [],\n): Set<string> => {\n const keywords = new Set<string>();\n\n // Fast-path: Skip parsing if no relevant imports are present in the code.\n const containsTargetModule =\n code.includes(VIRTUAL_MODULE_ID) ||\n additionalModulesToScan.some((moduleName) => code.includes(moduleName));\n\n if (!containsTargetModule) {\n return keywords;\n }\n\n let ast: Node;\n try {\n ast = parse(code, {\n sourceType: 'module',\n plugins: ['typescript', 'jsx'],\n errorRecovery: true,\n });\n } catch (e) {\n return keywords;\n }\n\n const keywordNamespaces = new Set<string>();\n\n traverse(ast, {\n enter(nodePath) {\n const node = nodePath.node;\n\n if (node.type === 'ImportDeclaration') {\n const isTargetModule =\n node.source.value === VIRTUAL_MODULE_ID ||\n additionalModulesToScan.includes(node.source.value);\n\n if (isTargetModule) {\n for (const specifier of node.specifiers) {\n if (specifier.type === 'ImportNamespaceSpecifier') {\n keywordNamespaces.add(specifier.local.name);\n }\n\n if (specifier.type === 'ImportDefaultSpecifier') {\n keywords.add('default');\n }\n\n if (specifier.type === 'ImportSpecifier') {\n if (specifier.imported.type === 'Identifier') {\n keywords.add(specifier.imported.name);\n }\n }\n }\n }\n }\n },\n });\n\n if (keywordNamespaces.size === 0) {\n return keywords;\n }\n\n traverse(ast, {\n enter(nodePath) {\n const node = nodePath.node;\n\n if (\n node.type === 'MemberExpression' &&\n !node.computed && // Exclude computed properties like K['xyz']\n node.object.type === 'Identifier' &&\n keywordNamespaces.has(node.object.name) &&\n node.property.type === 'Identifier'\n ) {\n keywords.add(node.property.name);\n }\n\n if (\n node.type === 'TSQualifiedName' &&\n node.left.type === 'Identifier' &&\n keywordNamespaces.has(node.left.name) &&\n node.right.type === 'Identifier'\n ) {\n keywords.add(node.right.name);\n }\n },\n });\n\n return keywords;\n};\n\nconst keywordConstPrefix = '_';\nconst createExportDeclaration = (keywords: Set<string>): string[] => {\n const aliases = [...keywords].map(\n (key) => ` ${keywordConstPrefix}${key} as ${key},`,\n );\n return [`export {`, ...aliases, `};`];\n};\n\nexport const generateTypesFile = async (\n collectedKeywords: Set<string>,\n root: string,\n dirname: string = '.keywords',\n filename: string = 'index.d.ts',\n): Promise<void> => {\n const keywordDeclarations = [...collectedKeywords]\n .map((key) => `declare const ${keywordConstPrefix}${key}: unique symbol;`)\n .join('\\n');\n const exportDeclaration =\n createExportDeclaration(collectedKeywords).join('\\n');\n const content = `${keywordDeclarations}\\n${exportDeclaration}\\n`;\n const pluginRoot = path.join(root, dirname);\n await mkdir(pluginRoot, { recursive: true });\n await writeFile(path.join(pluginRoot, filename), `${content.trim()}\\n`);\n};\n\nexport const collectKeywordsFromFiles = async (\n root: string,\n logger: PrefixedLogger,\n ignoredDirs: string[] = [],\n options?: KeywordsPluginOptions,\n): Promise<Set<string>> => {\n const resolvedOptions = resolveOptions(options);\n const collectedKeywords = new Set<string>();\n\n logger.info('Scanning project files for keywords...');\n\n const files = await globby('**/*.{js,ts,jsx,tsx}', {\n cwd: root,\n absolute: true,\n ignore: ['**/node_modules/**', ...ignoredDirs.map((dir) => `${dir}/**`)],\n gitignore: true,\n });\n\n const concurrency = 100;\n for (let i = 0; i < files.length; i += concurrency) {\n const chunk = files.slice(i, i + concurrency);\n await Promise.all(\n chunk.map(async (file) => {\n try {\n const code = await readFile(file, 'utf-8');\n const keywords = extractKeywords(\n code,\n resolvedOptions.additionalModulesToScan,\n );\n for (const key of keywords) {\n collectedKeywords.add(key);\n }\n } catch (error: any) {\n logger.warn(`Failed to process file ${file}: ${error.message}`);\n }\n }),\n );\n }\n\n logger.info(\n `Scan complete. Found ${collectedKeywords.size} unique keywords.`,\n );\n\n return collectedKeywords;\n};\n\nexport const collectKeywordsAndGenerateTypes = async (\n root: string,\n logger: PrefixedLogger,\n ignoredDirs?: string[],\n options?: KeywordsPluginOptions,\n): Promise<Set<string>> => {\n const collectedKeywords = await collectKeywordsFromFiles(\n root,\n logger,\n ignoredDirs,\n options,\n );\n await generateTypesFile(collectedKeywords, root);\n return collectedKeywords;\n};\n\nexport const generateModuleCode = (\n collectedKeywords: Set<string>,\n isDev: boolean,\n): string => {\n const symbolConstructorName = '__SYMBOL__';\n const symbolDeclaration = `const ${symbolConstructorName} = Symbol;`;\n const keywordDeclarations = [...collectedKeywords]\n .map(\n (key) =>\n `const ${keywordConstPrefix}${key} = /* @__PURE__ */ ${symbolConstructorName}(${isDev ? `'${key}'` : ''});`,\n )\n .join('\\n');\n const exportDeclaration =\n createExportDeclaration(collectedKeywords).join('\\n');\n return `${symbolDeclaration}\\n${keywordDeclarations}\\n${exportDeclaration}\\n`;\n};\n\nexport const splitQuery = (id: string) => id.split('?');\n","export const PLUGIN_NAME = 'rollup-plugin-keywords';\n","import {\n collectKeywordsAndGenerateTypes,\n createPrefixedLogger,\n generateModuleCode,\n RESOLVED_VIRTUAL_MODULE_ID,\n resolveOptions,\n splitQuery,\n VIRTUAL_MODULE_ID,\n type KeywordsPluginOptions,\n type PrefixedLogger,\n} from 'minifiable-keywords';\nimport type { Plugin } from 'rollup';\nimport { PLUGIN_NAME } from './shared';\n\nexport type { KeywordsPluginOptions } from 'minifiable-keywords';\n\nexport const keywordsPlugin = (options?: KeywordsPluginOptions): Plugin => {\n const pluginOptions = resolveOptions(options);\n let collectedKeywords: Set<string>;\n let logger: PrefixedLogger;\n const root = process.cwd();\n const isDev = process.env.NODE_ENV === 'development';\n\n return {\n name: PLUGIN_NAME,\n api: {\n options: pluginOptions,\n },\n\n async buildStart() {\n const pluginThis = this;\n logger = createPrefixedLogger(\n {\n info: pluginThis.info,\n warn: pluginThis.warn,\n error: pluginThis.error,\n },\n PLUGIN_NAME,\n false,\n );\n collectedKeywords = await collectKeywordsAndGenerateTypes(\n root,\n logger,\n [],\n pluginOptions,\n );\n },\n\n resolveId(source, importer) {\n if (!importer) {\n return;\n }\n const [validSource] = splitQuery(source);\n if (validSource === VIRTUAL_MODULE_ID) {\n return RESOLVED_VIRTUAL_MODULE_ID;\n }\n },\n\n load(id) {\n const [validId] = splitQuery(id);\n if (validId === RESOLVED_VIRTUAL_MODULE_ID) {\n return generateModuleCode(collectedKeywords, isDev);\n }\n },\n };\n};\n\nexport default keywordsPlugin;\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../minifiable-keywords/src/index.ts","../src/shared.ts","../src/index.ts"],"sourcesContent":["import { mkdir, readFile, writeFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport { parse } from '@babel/parser';\nimport _traverse, { type Node } from '@babel/traverse';\nimport { globby } from 'globby';\n\nexport const VIRTUAL_MODULE_ID = 'virtual:keywords';\nexport const RESOLVED_VIRTUAL_MODULE_ID = `\\0${VIRTUAL_MODULE_ID}`;\n\nexport interface KeywordsPluginOptions {\n additionalModulesToScan?: string[];\n isDev?: boolean;\n}\n\nexport type ResolvedKeywordsPluginOptions = Required<\n Omit<KeywordsPluginOptions, 'isDev'>\n> & { isDev?: boolean };\n\nexport const resolveOptions = (\n options?: KeywordsPluginOptions,\n): ResolvedKeywordsPluginOptions => {\n return {\n additionalModulesToScan: options?.additionalModulesToScan || [],\n isDev: options?.isDev,\n };\n};\n\nexport interface Logger {\n info: (message: string) => void;\n warn: (message: string) => void;\n error: (message: string) => void;\n}\n\nexport interface PrefixedLogger extends Logger {\n pluginName: string;\n}\n\nexport const createPrefixedLogger = (\n logger: Logger,\n pluginName: string,\n usePrefix: boolean = true,\n): PrefixedLogger => {\n const prefix = usePrefix ? `[${pluginName}] ` : '';\n const prefixed = (message: string) => `${prefix}${message}`;\n return {\n pluginName,\n info: (message: string) => logger.info(prefixed(message)),\n warn: (message: string) => logger.warn(prefixed(message)),\n error: (message: string) => logger.error(prefixed(message)),\n };\n};\n\n// ref: https://github.com/babel/babel/discussions/13093\nconst traverse =\n typeof _traverse === 'function'\n ? _traverse\n : ((_traverse as any).default as typeof _traverse);\n\nexport const extractKeywords = (\n code: string,\n additionalModulesToScan: string[] = [],\n): Set<string> => {\n const keywords = new Set<string>();\n\n // Fast-path: Skip parsing if no relevant imports are present in the code.\n const containsTargetModule =\n code.includes(VIRTUAL_MODULE_ID) ||\n additionalModulesToScan.some((moduleName) => code.includes(moduleName));\n\n if (!containsTargetModule) {\n return keywords;\n }\n\n let ast: Node;\n try {\n ast = parse(code, {\n sourceType: 'module',\n plugins: ['typescript', 'jsx'],\n errorRecovery: true,\n });\n } catch (e) {\n return keywords;\n }\n\n const keywordNamespaces = new Set<string>();\n\n traverse(ast, {\n enter(nodePath) {\n const node = nodePath.node;\n\n if (node.type === 'ImportDeclaration') {\n const isTargetModule =\n node.source.value === VIRTUAL_MODULE_ID ||\n additionalModulesToScan.includes(node.source.value);\n\n if (isTargetModule) {\n for (const specifier of node.specifiers) {\n if (specifier.type === 'ImportNamespaceSpecifier') {\n keywordNamespaces.add(specifier.local.name);\n }\n\n if (specifier.type === 'ImportDefaultSpecifier') {\n keywords.add('default');\n }\n\n if (specifier.type === 'ImportSpecifier') {\n if (specifier.imported.type === 'Identifier') {\n keywords.add(specifier.imported.name);\n }\n }\n }\n }\n }\n },\n });\n\n if (keywordNamespaces.size === 0) {\n return keywords;\n }\n\n traverse(ast, {\n enter(nodePath) {\n const node = nodePath.node;\n\n if (\n node.type === 'MemberExpression' &&\n !node.computed && // Exclude computed properties like K['xyz']\n node.object.type === 'Identifier' &&\n keywordNamespaces.has(node.object.name) &&\n node.property.type === 'Identifier'\n ) {\n keywords.add(node.property.name);\n }\n\n if (\n node.type === 'TSQualifiedName' &&\n node.left.type === 'Identifier' &&\n keywordNamespaces.has(node.left.name) &&\n node.right.type === 'Identifier'\n ) {\n keywords.add(node.right.name);\n }\n },\n });\n\n return keywords;\n};\n\nconst keywordConstPrefix = '_';\nconst createExportDeclaration = (keywords: Set<string>): string[] => {\n const aliases = [...keywords].map(\n (key) => ` ${keywordConstPrefix}${key} as ${key},`,\n );\n return [`export {`, ...aliases, `};`];\n};\n\nexport const generateTypesFile = async (\n collectedKeywords: Set<string>,\n root: string,\n dirname: string = '.keywords',\n filename: string = 'index.d.ts',\n): Promise<void> => {\n const keywordDeclarations = [...collectedKeywords]\n .map((key) => `declare const ${keywordConstPrefix}${key}: unique symbol;`)\n .join('\\n');\n const exportDeclaration =\n createExportDeclaration(collectedKeywords).join('\\n');\n const content = `${keywordDeclarations}\\n${exportDeclaration}\\n`;\n const pluginRoot = path.join(root, dirname);\n await mkdir(pluginRoot, { recursive: true });\n await writeFile(path.join(pluginRoot, filename), `${content.trim()}\\n`);\n};\n\nexport const collectKeywordsFromFiles = async (\n root: string,\n logger: PrefixedLogger,\n ignoredDirs: string[] = [],\n options?: KeywordsPluginOptions,\n): Promise<Set<string>> => {\n const resolvedOptions = resolveOptions(options);\n const collectedKeywords = new Set<string>();\n\n logger.info('Scanning project files for keywords...');\n\n const files = await globby('**/*.{js,ts,jsx,tsx}', {\n cwd: root,\n absolute: true,\n ignore: ['**/node_modules/**', ...ignoredDirs.map((dir) => `${dir}/**`)],\n gitignore: true,\n });\n\n const concurrency = 100;\n for (let i = 0; i < files.length; i += concurrency) {\n const chunk = files.slice(i, i + concurrency);\n await Promise.all(\n chunk.map(async (file) => {\n try {\n const code = await readFile(file, 'utf-8');\n const keywords = extractKeywords(\n code,\n resolvedOptions.additionalModulesToScan,\n );\n for (const key of keywords) {\n collectedKeywords.add(key);\n }\n } catch (error: any) {\n logger.warn(`Failed to process file ${file}: ${error.message}`);\n }\n }),\n );\n }\n\n logger.info(\n `Scan complete. Found ${collectedKeywords.size} unique keywords.`,\n );\n\n return collectedKeywords;\n};\n\nexport const collectKeywordsAndGenerateTypes = async (\n root: string,\n logger: PrefixedLogger,\n ignoredDirs?: string[],\n options?: KeywordsPluginOptions,\n): Promise<Set<string>> => {\n const collectedKeywords = await collectKeywordsFromFiles(\n root,\n logger,\n ignoredDirs,\n options,\n );\n await generateTypesFile(collectedKeywords, root);\n return collectedKeywords;\n};\n\nexport const generateModuleCode = (\n collectedKeywords: Set<string>,\n isDev: boolean,\n): string => {\n const symbolConstructorName = '__SYMBOL__';\n const symbolDeclaration = `const ${symbolConstructorName} = Symbol;`;\n const keywordDeclarations = [...collectedKeywords]\n .map(\n (key) =>\n `const ${keywordConstPrefix}${key} = /* @__PURE__ */ ${symbolConstructorName}(${isDev ? `'${key}'` : ''});`,\n )\n .join('\\n');\n const exportDeclaration =\n createExportDeclaration(collectedKeywords).join('\\n');\n return `${symbolDeclaration}\\n${keywordDeclarations}\\n${exportDeclaration}\\n`;\n};\n\nexport const splitQuery = (id: string) => id.split('?');\n","export const PLUGIN_NAME = 'rollup-plugin-keywords';\n","import {\n collectKeywordsAndGenerateTypes,\n createPrefixedLogger,\n generateModuleCode,\n RESOLVED_VIRTUAL_MODULE_ID,\n resolveOptions,\n splitQuery,\n VIRTUAL_MODULE_ID,\n type KeywordsPluginOptions,\n type PrefixedLogger,\n} from 'minifiable-keywords';\nimport type { Plugin } from 'rollup';\nimport { PLUGIN_NAME } from './shared';\n\nexport type { KeywordsPluginOptions } from 'minifiable-keywords';\n\nexport const keywordsPlugin = (options?: KeywordsPluginOptions): Plugin => {\n const pluginOptions = resolveOptions(options);\n let collectedKeywords: Set<string>;\n let logger: PrefixedLogger;\n const root = process.cwd();\n const isDev = pluginOptions.isDev ?? process.env.NODE_ENV === 'development';\n\n return {\n name: PLUGIN_NAME,\n api: {\n options: pluginOptions,\n },\n\n async buildStart() {\n const pluginThis = this;\n logger = createPrefixedLogger(\n {\n info: pluginThis.info,\n warn: pluginThis.warn,\n error: pluginThis.error,\n },\n PLUGIN_NAME,\n false,\n );\n collectedKeywords = await collectKeywordsAndGenerateTypes(\n root,\n logger,\n [],\n pluginOptions,\n );\n },\n\n resolveId(source, importer) {\n if (!importer) {\n return;\n }\n const [validSource] = splitQuery(source);\n if (validSource === VIRTUAL_MODULE_ID) {\n return RESOLVED_VIRTUAL_MODULE_ID;\n }\n },\n\n load(id) {\n const [validId] = splitQuery(id);\n if (validId === RESOLVED_VIRTUAL_MODULE_ID) {\n return generateModuleCode(collectedKeywords, isDev);\n }\n },\n };\n};\n\nexport default keywordsPlugin;\n"],"mappings":";AAAA,SAAS,OAAO,UAAU,iBAAiB;AAC3C,OAAO,UAAU;AACjB,SAAS,aAAa;AACtB,OAAO,eAA8B;AACrC,SAAS,cAAc;AAEhB,IAAM,oBAAoB;AAC1B,IAAM,6BAA6B,KAAK,iBAAiB;AAWzD,IAAM,iBAAiB,CAC5B,YACkC;AAClC,SAAO;IACL,yBAAyB,SAAS,2BAA2B,CAAC;IAC9D,OAAO,SAAS;EAClB;AACF;AAYO,IAAM,uBAAuB,CAClC,QACA,YACA,YAAqB,SACF;AACnB,QAAM,SAAS,YAAY,IAAI,UAAU,OAAO;AAChD,QAAM,WAAW,CAAC,YAAoB,GAAG,MAAM,GAAG,OAAO;AACzD,SAAO;IACL;IACA,MAAM,CAAC,YAAoB,OAAO,KAAK,SAAS,OAAO,CAAC;IACxD,MAAM,CAAC,YAAoB,OAAO,KAAK,SAAS,OAAO,CAAC;IACxD,OAAO,CAAC,YAAoB,OAAO,MAAM,SAAS,OAAO,CAAC;EAC5D;AACF;AAGA,IAAM,WACJ,OAAO,cAAc,aACjB,YACE,UAAkB;AAEnB,IAAM,kBAAkB,CAC7B,MACA,0BAAoC,CAAC,MACrB;AAChB,QAAM,WAAW,oBAAI,IAAY;AAGjC,QAAM,uBACJ,KAAK,SAAS,iBAAiB,KAC/B,wBAAwB,KAAK,CAAC,eAAe,KAAK,SAAS,UAAU,CAAC;AAExE,MAAI,CAAC,sBAAsB;AACzB,WAAO;EACT;AAEA,MAAI;AACJ,MAAI;AACF,UAAM,MAAM,MAAM;MAChB,YAAY;MACZ,SAAS,CAAC,cAAc,KAAK;MAC7B,eAAe;IACjB,CAAC;EACH,SAAS,GAAG;AACV,WAAO;EACT;AAEA,QAAM,oBAAoB,oBAAI,IAAY;AAE1C,WAAS,KAAK;IACZ,MAAM,UAAU;AACd,YAAM,OAAO,SAAS;AAEtB,UAAI,KAAK,SAAS,qBAAqB;AACrC,cAAM,iBACJ,KAAK,OAAO,UAAU,qBACtB,wBAAwB,SAAS,KAAK,OAAO,KAAK;AAEpD,YAAI,gBAAgB;AAClB,qBAAW,aAAa,KAAK,YAAY;AACvC,gBAAI,UAAU,SAAS,4BAA4B;AACjD,gCAAkB,IAAI,UAAU,MAAM,IAAI;YAC5C;AAEA,gBAAI,UAAU,SAAS,0BAA0B;AAC/C,uBAAS,IAAI,SAAS;YACxB;AAEA,gBAAI,UAAU,SAAS,mBAAmB;AACxC,kBAAI,UAAU,SAAS,SAAS,cAAc;AAC5C,yBAAS,IAAI,UAAU,SAAS,IAAI;cACtC;YACF;UACF;QACF;MACF;IACF;EACF,CAAC;AAED,MAAI,kBAAkB,SAAS,GAAG;AAChC,WAAO;EACT;AAEA,WAAS,KAAK;IACZ,MAAM,UAAU;AACd,YAAM,OAAO,SAAS;AAEtB,UACE,KAAK,SAAS,sBACd,CAAC,KAAK;MACN,KAAK,OAAO,SAAS,gBACrB,kBAAkB,IAAI,KAAK,OAAO,IAAI,KACtC,KAAK,SAAS,SAAS,cACvB;AACA,iBAAS,IAAI,KAAK,SAAS,IAAI;MACjC;AAEA,UACE,KAAK,SAAS,qBACd,KAAK,KAAK,SAAS,gBACnB,kBAAkB,IAAI,KAAK,KAAK,IAAI,KACpC,KAAK,MAAM,SAAS,cACpB;AACA,iBAAS,IAAI,KAAK,MAAM,IAAI;MAC9B;IACF;EACF,CAAC;AAED,SAAO;AACT;AAEA,IAAM,qBAAqB;AAC3B,IAAM,0BAA0B,CAAC,aAAoC;AACnE,QAAM,UAAU,CAAC,GAAG,QAAQ,EAAE;IAC5B,CAAC,QAAQ,KAAK,kBAAkB,GAAG,GAAG,OAAO,GAAG;EAClD;AACA,SAAO,CAAC,YAAY,GAAG,SAAS,IAAI;AACtC;AAEO,IAAM,oBAAoB,OAC/B,mBACA,MACA,UAAkB,aAClB,WAAmB,iBACD;AAClB,QAAM,sBAAsB,CAAC,GAAG,iBAAiB,EAC9C,IAAI,CAAC,QAAQ,iBAAiB,kBAAkB,GAAG,GAAG,kBAAkB,EACxE,KAAK,IAAI;AACZ,QAAM,oBACJ,wBAAwB,iBAAiB,EAAE,KAAK,IAAI;AACtD,QAAM,UAAU,GAAG,mBAAmB;EAAK,iBAAiB;;AAC5D,QAAM,aAAa,KAAK,KAAK,MAAM,OAAO;AAC1C,QAAM,MAAM,YAAY,EAAE,WAAW,KAAK,CAAC;AAC3C,QAAM,UAAU,KAAK,KAAK,YAAY,QAAQ,GAAG,GAAG,QAAQ,KAAK,CAAC;CAAI;AACxE;AAEO,IAAM,2BAA2B,OACtC,MACA,QACA,cAAwB,CAAC,GACzB,YACyB;AACzB,QAAM,kBAAkB,eAAe,OAAO;AAC9C,QAAM,oBAAoB,oBAAI,IAAY;AAE1C,SAAO,KAAK,wCAAwC;AAEpD,QAAM,QAAQ,MAAM,OAAO,wBAAwB;IACjD,KAAK;IACL,UAAU;IACV,QAAQ,CAAC,sBAAsB,GAAG,YAAY,IAAI,CAAC,QAAQ,GAAG,GAAG,KAAK,CAAC;IACvE,WAAW;EACb,CAAC;AAED,QAAM,cAAc;AACpB,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK,aAAa;AAClD,UAAM,QAAQ,MAAM,MAAM,GAAG,IAAI,WAAW;AAC5C,UAAM,QAAQ;MACZ,MAAM,IAAI,OAAO,SAAS;AACxB,YAAI;AACF,gBAAM,OAAO,MAAM,SAAS,MAAM,OAAO;AACzC,gBAAM,WAAW;YACf;YACA,gBAAgB;UAClB;AACA,qBAAW,OAAO,UAAU;AAC1B,8BAAkB,IAAI,GAAG;UAC3B;QACF,SAAS,OAAY;AACnB,iBAAO,KAAK,0BAA0B,IAAI,KAAK,MAAM,OAAO,EAAE;QAChE;MACF,CAAC;IACH;EACF;AAEA,SAAO;IACL,wBAAwB,kBAAkB,IAAI;EAChD;AAEA,SAAO;AACT;AAEO,IAAM,kCAAkC,OAC7C,MACA,QACA,aACA,YACyB;AACzB,QAAM,oBAAoB,MAAM;IAC9B;IACA;IACA;IACA;EACF;AACA,QAAM,kBAAkB,mBAAmB,IAAI;AAC/C,SAAO;AACT;AAEO,IAAM,qBAAqB,CAChC,mBACA,UACW;AACX,QAAM,wBAAwB;AAC9B,QAAM,oBAAoB,SAAS,qBAAqB;AACxD,QAAM,sBAAsB,CAAC,GAAG,iBAAiB,EAC9C;IACC,CAAC,QACC,SAAS,kBAAkB,GAAG,GAAG,sBAAsB,qBAAqB,IAAI,QAAQ,IAAI,GAAG,MAAM,EAAE;EAC3G,EACC,KAAK,IAAI;AACZ,QAAM,oBACJ,wBAAwB,iBAAiB,EAAE,KAAK,IAAI;AACtD,SAAO,GAAG,iBAAiB;EAAK,mBAAmB;EAAK,iBAAiB;;AAC3E;AAEO,IAAM,aAAa,CAAC,OAAe,GAAG,MAAM,GAAG;;;AC5P/C,IAAM,cAAc;;;ACgBpB,IAAM,iBAAiB,CAAC,YAA4C;AACzE,QAAM,gBAAgB,eAAe,OAAO;AAC5C,MAAI;AACJ,MAAI;AACJ,QAAM,OAAO,QAAQ,IAAI;AACzB,QAAM,QAAQ,cAAc,SAAS,QAAQ,IAAI,aAAa;AAE9D,SAAO;AAAA,IACL,MAAM;AAAA,IACN,KAAK;AAAA,MACH,SAAS;AAAA,IACX;AAAA,IAEA,MAAM,aAAa;AACjB,YAAM,aAAa;AACnB,eAAS;AAAA,QACP;AAAA,UACE,MAAM,WAAW;AAAA,UACjB,MAAM,WAAW;AAAA,UACjB,OAAO,WAAW;AAAA,QACpB;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA,0BAAoB,MAAM;AAAA,QACxB;AAAA,QACA;AAAA,QACA,CAAC;AAAA,QACD;AAAA,MACF;AAAA,IACF;AAAA,IAEA,UAAU,QAAQ,UAAU;AAC1B,UAAI,CAAC,UAAU;AACb;AAAA,MACF;AACA,YAAM,CAAC,WAAW,IAAI,WAAW,MAAM;AACvC,UAAI,gBAAgB,mBAAmB;AACrC,eAAO;AAAA,MACT;AAAA,IACF;AAAA,IAEA,KAAK,IAAI;AACP,YAAM,CAAC,OAAO,IAAI,WAAW,EAAE;AAC/B,UAAI,YAAY,4BAA4B;AAC1C,eAAO,mBAAmB,mBAAmB,KAAK;AAAA,MACpD;AAAA,IACF;AAAA,EACF;AACF;AAEA,IAAO,gBAAQ;","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rollup-plugin-keywords",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.3",
|
|
4
4
|
"description": "A Rollup plugin that provides minifiable Symbols (keywords) to use in place of string literals for aggressive minification/obfuscation.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"rollup",
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"rimraf": "^6.0.1",
|
|
47
47
|
"tsup": "^8.5.0",
|
|
48
48
|
"vitest": "^4.0.0",
|
|
49
|
-
"minifiable-keywords": "1.2.
|
|
49
|
+
"minifiable-keywords": "1.2.3"
|
|
50
50
|
},
|
|
51
51
|
"peerDependencies": {
|
|
52
52
|
"rollup": "^3.0.0 || ^4.0.0"
|