rollup-plugin-keywords 1.2.1 → 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 +6 -4
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +8 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -4
- package/dist/index.d.ts +7 -4
- package/dist/index.js +8 -6
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -10,9 +10,10 @@ import _traverse from "@babel/traverse";
|
|
|
10
10
|
import { globby } from "globby";
|
|
11
11
|
var VIRTUAL_MODULE_ID = "virtual:keywords";
|
|
12
12
|
var RESOLVED_VIRTUAL_MODULE_ID = `\0${VIRTUAL_MODULE_ID}`;
|
|
13
|
-
var
|
|
13
|
+
var resolveOptions = (options) => {
|
|
14
14
|
return {
|
|
15
|
-
additionalModulesToScan: options
|
|
15
|
+
additionalModulesToScan: options?.additionalModulesToScan || [],
|
|
16
|
+
isDev: options?.isDev
|
|
16
17
|
};
|
|
17
18
|
};
|
|
18
19
|
var createPrefixedLogger = (logger, pluginName, usePrefix = true) => {
|
|
@@ -101,7 +102,8 @@ ${exportDeclaration}
|
|
|
101
102
|
await writeFile(path.join(pluginRoot, filename), `${content.trim()}
|
|
102
103
|
`);
|
|
103
104
|
};
|
|
104
|
-
var collectKeywordsFromFiles = async (root, logger, ignoredDirs = [], options
|
|
105
|
+
var collectKeywordsFromFiles = async (root, logger, ignoredDirs = [], options) => {
|
|
106
|
+
const resolvedOptions = resolveOptions(options);
|
|
105
107
|
const collectedKeywords = /* @__PURE__ */ new Set();
|
|
106
108
|
logger.info("Scanning project files for keywords...");
|
|
107
109
|
const files = await globby("**/*.{js,ts,jsx,tsx}", {
|
|
@@ -119,7 +121,7 @@ var collectKeywordsFromFiles = async (root, logger, ignoredDirs = [], options =
|
|
|
119
121
|
const code = await readFile(file, "utf-8");
|
|
120
122
|
const keywords = extractKeywords(
|
|
121
123
|
code,
|
|
122
|
-
|
|
124
|
+
resolvedOptions.additionalModulesToScan
|
|
123
125
|
);
|
|
124
126
|
for (const key of keywords) {
|
|
125
127
|
collectedKeywords.add(key);
|
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 const buildOptions = (\n options: Partial<KeywordsPluginOptions> = {},\n): KeywordsPluginOptions => {\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 = buildOptions(),\n): Promise<Set<string>> => {\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 options.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":"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","names":["path","path"]}
|
package/dist/index.cjs
CHANGED
|
@@ -43,9 +43,10 @@ var import_traverse = __toESM(require("@babel/traverse"), 1);
|
|
|
43
43
|
var import_globby = require("globby");
|
|
44
44
|
var VIRTUAL_MODULE_ID = "virtual:keywords";
|
|
45
45
|
var RESOLVED_VIRTUAL_MODULE_ID = `\0${VIRTUAL_MODULE_ID}`;
|
|
46
|
-
var
|
|
46
|
+
var resolveOptions = (options) => {
|
|
47
47
|
return {
|
|
48
|
-
additionalModulesToScan: options
|
|
48
|
+
additionalModulesToScan: options?.additionalModulesToScan || [],
|
|
49
|
+
isDev: options?.isDev
|
|
49
50
|
};
|
|
50
51
|
};
|
|
51
52
|
var createPrefixedLogger = (logger, pluginName, usePrefix = true) => {
|
|
@@ -134,7 +135,8 @@ ${exportDeclaration}
|
|
|
134
135
|
await (0, import_promises.writeFile)(import_path.default.join(pluginRoot, filename), `${content.trim()}
|
|
135
136
|
`);
|
|
136
137
|
};
|
|
137
|
-
var collectKeywordsFromFiles = async (root, logger, ignoredDirs = [], options
|
|
138
|
+
var collectKeywordsFromFiles = async (root, logger, ignoredDirs = [], options) => {
|
|
139
|
+
const resolvedOptions = resolveOptions(options);
|
|
138
140
|
const collectedKeywords = /* @__PURE__ */ new Set();
|
|
139
141
|
logger.info("Scanning project files for keywords...");
|
|
140
142
|
const files = await (0, import_globby.globby)("**/*.{js,ts,jsx,tsx}", {
|
|
@@ -152,7 +154,7 @@ var collectKeywordsFromFiles = async (root, logger, ignoredDirs = [], options =
|
|
|
152
154
|
const code = await (0, import_promises.readFile)(file, "utf-8");
|
|
153
155
|
const keywords = extractKeywords(
|
|
154
156
|
code,
|
|
155
|
-
|
|
157
|
+
resolvedOptions.additionalModulesToScan
|
|
156
158
|
);
|
|
157
159
|
for (const key of keywords) {
|
|
158
160
|
collectedKeywords.add(key);
|
|
@@ -197,11 +199,11 @@ var PLUGIN_NAME = "rollup-plugin-keywords";
|
|
|
197
199
|
|
|
198
200
|
// src/index.ts
|
|
199
201
|
var keywordsPlugin = (options) => {
|
|
200
|
-
const pluginOptions =
|
|
202
|
+
const pluginOptions = resolveOptions(options);
|
|
201
203
|
let collectedKeywords;
|
|
202
204
|
let logger;
|
|
203
205
|
const root = process.cwd();
|
|
204
|
-
const isDev = process.env.NODE_ENV === "development";
|
|
206
|
+
const isDev = pluginOptions.isDev ?? process.env.NODE_ENV === "development";
|
|
205
207
|
return {
|
|
206
208
|
name: PLUGIN_NAME,
|
|
207
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 buildOptions,\n collectKeywordsAndGenerateTypes,\n createPrefixedLogger,\n generateModuleCode,\n RESOLVED_VIRTUAL_MODULE_ID,\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 = (\n options?: Partial<KeywordsPluginOptions>,\n): Plugin => {\n const pluginOptions = buildOptions(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 const buildOptions = (\n options: Partial<KeywordsPluginOptions> = {},\n): KeywordsPluginOptions => {\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 = buildOptions(),\n): Promise<Set<string>> => {\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 options.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":"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","names":["_traverse","path"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
import { KeywordsPluginOptions } from 'minifiable-keywords';
|
|
2
|
-
export { KeywordsPluginOptions } from 'minifiable-keywords';
|
|
3
1
|
import { Plugin } from 'rollup';
|
|
4
2
|
|
|
5
|
-
|
|
3
|
+
interface KeywordsPluginOptions {
|
|
4
|
+
additionalModulesToScan?: string[];
|
|
5
|
+
isDev?: boolean;
|
|
6
|
+
}
|
|
6
7
|
|
|
7
|
-
|
|
8
|
+
declare const keywordsPlugin: (options?: KeywordsPluginOptions) => Plugin;
|
|
9
|
+
|
|
10
|
+
export { type KeywordsPluginOptions, keywordsPlugin as default, keywordsPlugin };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
import { KeywordsPluginOptions } from 'minifiable-keywords';
|
|
2
|
-
export { KeywordsPluginOptions } from 'minifiable-keywords';
|
|
3
1
|
import { Plugin } from 'rollup';
|
|
4
2
|
|
|
5
|
-
|
|
3
|
+
interface KeywordsPluginOptions {
|
|
4
|
+
additionalModulesToScan?: string[];
|
|
5
|
+
isDev?: boolean;
|
|
6
|
+
}
|
|
6
7
|
|
|
7
|
-
|
|
8
|
+
declare const keywordsPlugin: (options?: KeywordsPluginOptions) => Plugin;
|
|
9
|
+
|
|
10
|
+
export { type KeywordsPluginOptions, keywordsPlugin as default, keywordsPlugin };
|
package/dist/index.js
CHANGED
|
@@ -6,9 +6,10 @@ import _traverse from "@babel/traverse";
|
|
|
6
6
|
import { globby } from "globby";
|
|
7
7
|
var VIRTUAL_MODULE_ID = "virtual:keywords";
|
|
8
8
|
var RESOLVED_VIRTUAL_MODULE_ID = `\0${VIRTUAL_MODULE_ID}`;
|
|
9
|
-
var
|
|
9
|
+
var resolveOptions = (options) => {
|
|
10
10
|
return {
|
|
11
|
-
additionalModulesToScan: options
|
|
11
|
+
additionalModulesToScan: options?.additionalModulesToScan || [],
|
|
12
|
+
isDev: options?.isDev
|
|
12
13
|
};
|
|
13
14
|
};
|
|
14
15
|
var createPrefixedLogger = (logger, pluginName, usePrefix = true) => {
|
|
@@ -97,7 +98,8 @@ ${exportDeclaration}
|
|
|
97
98
|
await writeFile(path.join(pluginRoot, filename), `${content.trim()}
|
|
98
99
|
`);
|
|
99
100
|
};
|
|
100
|
-
var collectKeywordsFromFiles = async (root, logger, ignoredDirs = [], options
|
|
101
|
+
var collectKeywordsFromFiles = async (root, logger, ignoredDirs = [], options) => {
|
|
102
|
+
const resolvedOptions = resolveOptions(options);
|
|
101
103
|
const collectedKeywords = /* @__PURE__ */ new Set();
|
|
102
104
|
logger.info("Scanning project files for keywords...");
|
|
103
105
|
const files = await globby("**/*.{js,ts,jsx,tsx}", {
|
|
@@ -115,7 +117,7 @@ var collectKeywordsFromFiles = async (root, logger, ignoredDirs = [], options =
|
|
|
115
117
|
const code = await readFile(file, "utf-8");
|
|
116
118
|
const keywords = extractKeywords(
|
|
117
119
|
code,
|
|
118
|
-
|
|
120
|
+
resolvedOptions.additionalModulesToScan
|
|
119
121
|
);
|
|
120
122
|
for (const key of keywords) {
|
|
121
123
|
collectedKeywords.add(key);
|
|
@@ -160,11 +162,11 @@ var PLUGIN_NAME = "rollup-plugin-keywords";
|
|
|
160
162
|
|
|
161
163
|
// src/index.ts
|
|
162
164
|
var keywordsPlugin = (options) => {
|
|
163
|
-
const pluginOptions =
|
|
165
|
+
const pluginOptions = resolveOptions(options);
|
|
164
166
|
let collectedKeywords;
|
|
165
167
|
let logger;
|
|
166
168
|
const root = process.cwd();
|
|
167
|
-
const isDev = process.env.NODE_ENV === "development";
|
|
169
|
+
const isDev = pluginOptions.isDev ?? process.env.NODE_ENV === "development";
|
|
168
170
|
return {
|
|
169
171
|
name: PLUGIN_NAME,
|
|
170
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 const buildOptions = (\n options: Partial<KeywordsPluginOptions> = {},\n): KeywordsPluginOptions => {\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 = buildOptions(),\n): Promise<Set<string>> => {\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 options.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 buildOptions,\n collectKeywordsAndGenerateTypes,\n createPrefixedLogger,\n generateModuleCode,\n RESOLVED_VIRTUAL_MODULE_ID,\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 = (\n options?: Partial<KeywordsPluginOptions>,\n): Plugin => {\n const pluginOptions = buildOptions(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":"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","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"
|