[READ-ONLY] Mirror of https://github.com/danielroe/rollup-plugin-pure. Annotate functions as pure for Rollup
0

Configure Feed

Select the types of activity you want to include in your feed.

feat: support regex function names (#349)

+43 -13
+1 -1
README.md
··· 37 37 export default defineConfig({ 38 38 plugins: [ 39 39 PluginPure({ 40 - functions: ['defineComponent'], 40 + functions: ['defineComponent', /^define(Page|Meta)$/], 41 41 include: [/(?<!im)pure\.js$/], 42 42 // exclude: [], 43 43 // sourcemap: true,
+10 -1
playground/src/impure.js
··· 1 1 function defineComponent(options) { 2 - console.log('THIS_SHOULD_REMAIN_IMPURE') 2 + console.log('THIS_SHOULD_REMAIN_COMPONENT') 3 + return options 4 + } 5 + 6 + function definePage(options) { 7 + console.log('THIS_SHOULD_REMAIN_PAGE') 3 8 return options 4 9 } 5 10 ··· 10 15 11 16 export const comp = defineComponent({ 12 17 someComponent: true, 18 + }) 19 + 20 + export const page = definePage({ 21 + name: 'Example', 13 22 }) 14 23 15 24 export const config = $createConfig({
+16 -2
playground/src/pure.js
··· 1 1 function defineComponent(options) { 2 - console.log('THIS_SHOULD_BE_REMOVED_PURE') 2 + console.log('THIS_SHOULD_BE_REMOVED_COMPONENT') 3 + return options 4 + } 5 + 6 + function definePage(options) { 7 + console.log('THIS_SHOULD_BE_REMOVED_PAGE') 3 8 return options 4 9 } 5 10 ··· 20 25 someComponent: true, 21 26 }) 22 27 28 + // Normal exports should be annotated 29 + export const page = definePage({ 30 + name: 'Example', 31 + }) 32 + 23 33 export const config = $createConfig({ 24 34 someConfig: true, 25 35 }) ··· 29 39 }) 30 40 31 41 // Already annotated call - should not be double annotated 32 - export const alreadyAnnotated = /* @__PURE__ */ defineComponent({ 42 + export const compAnnotated = /* @__PURE__ */ defineComponent({ 33 43 someComponent: true, 34 44 }) 45 + export const pageAnnotated = /* @__PURE__ */ definePage({ 46 + name: 'Example', 47 + }) 35 48 export const hashStyleAnnotated = /* #__PURE__ */ $createConfig({ 36 49 someConfig: true, 37 50 }) 38 51 39 52 // ensures regex isn't over-eager 40 53 defineComponent($createConfig()) 54 + definePage($createConfig()) 41 55 42 56 export const foo = 'hello'
+1 -1
playground/vite.config.mjs
··· 4 4 export default defineConfig({ 5 5 plugins: [ 6 6 PluginPure({ 7 - functions: ['defineComponent', '$createConfig', 'hashStyleFunction'], 7 + functions: [/^define(Component|Page)$/, '$createConfig', 'hashStyleFunction'], 8 8 include: [/(?<!im)pure\.js$/], 9 9 }), 10 10 ],
+11 -6
src/index.ts
··· 7 7 8 8 export interface PureAnnotationsOptions { 9 9 sourcemap?: boolean 10 - functions: string[] 10 + functions: (string | RegExp)[] 11 11 include?: FilterPattern 12 12 exclude?: FilterPattern 13 13 } 14 14 15 15 const withLocations = <T>(node: T) => node as T & { start: number, end: number } 16 16 export function PluginPure(options: PureAnnotationsOptions): Plugin { 17 - const functionSet = new Set(options.functions) 18 17 const filter = createFilter(options.include, options.exclude) 19 18 20 19 return { ··· 26 25 return 27 26 } 28 27 29 - // quick check if any of the functions are in the code 30 - if (!options.functions.some(func => code.includes(func))) { 28 + // quick check for early return 29 + if (options.functions.every(func => typeof func === 'string' && !code.includes(func))) { 31 30 return 32 31 } 33 32 ··· 49 48 if ( 50 49 node.type === 'FunctionDeclaration' 51 50 && node.id 52 - && functionSet.has(node.id.name) 51 + && isMatched(node.id.name, options.functions) 53 52 ) { 54 53 for (const _comment of ast.comments || []) { 55 54 const comment = withLocations(_comment) ··· 64 63 if ( 65 64 node.type === 'CallExpression' 66 65 && node.callee.type === 'Identifier' 67 - && functionSet.has(node.callee.name) 66 + && isMatched(node.callee.name, options.functions) 68 67 ) { 69 68 for (const _comment of ast.comments || /* v8-ignore */ []) { 70 69 const comment = withLocations(_comment) ··· 87 86 }, 88 87 } 89 88 } 89 + 90 + function isMatched(name: string, patterns: (string | RegExp)[]) { 91 + return patterns.some(pattern => 92 + typeof pattern === 'string' ? name === pattern : pattern.test(name), 93 + ) 94 + }
+4 -2
test/e2e.spec.ts
··· 16 16 const code = await readFile(join(assetsDir, filename), 'utf-8') 17 17 18 18 // Verify that string literals from impure.js should be present in the bundle 19 - expect(code).toContain('THIS_SHOULD_REMAIN_IMPURE') 19 + expect(code).toContain('THIS_SHOULD_REMAIN_COMPONENT') 20 + expect(code).toContain('THIS_SHOULD_REMAIN_PAGE') 20 21 expect(code).toContain('THIS_SHOULD_REMAIN_CONFIG') 21 22 22 23 // Verify that string literals from pure.js should not be present in the bundle 23 - expect(code).not.toContain('THIS_SHOULD_BE_REMOVED_PURE') 24 + expect(code).not.toContain('THIS_SHOULD_BE_REMOVED_COMPONENT') 25 + expect(code).not.toContain('THIS_SHOULD_BE_REMOVED_PAGE') 24 26 expect(code).not.toContain('THIS_SHOULD_BE_REMOVED_CONFIG') 25 27 expect(code).not.toContain('THIS_SHOULD_BE_REMOVED_HASH_STYLE') 26 28