vike 0.4.249-commit-4ef7732 → 0.4.249-commit-b3b9c55

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.
@@ -1,22 +1,50 @@
1
1
  export { pluginReplaceConstantsNonRunnableDev };
2
- import { isRunnableDevEnvironment, isDevCheck } from '../../utils.js';
2
+ // We cannot use [`define`](https://vite.dev/config/shared-options.html#define) because we don't have access to `this.environment` and therefore we cannot call `isRunnableDevEnvironment(this.environment)` inside a configEnvironment() hook.
3
+ import { isRunnableDevEnvironment, isDevCheck, assert } from '../../utils.js';
3
4
  import { getMagicString } from '../../shared/getMagicString.js';
4
- // - We cannot use [`define`](https://vite.dev/config/shared-options.html#define) because we don't have access to `this.environment` and therefore we cannot call `isRunnableDevEnvironment(this.environment)` inside a configEnvironment() hook.
5
- // - We cannot use [`filter.id`](https://rolldown.rs/plugins/hook-filters) because Vite's optimizeDeps bundles packages (e.g. `vike` or `telefunc`) into node_modules/.vite/deps_ssr/chunk-WBC5FHD7.js
6
5
  const IS_NON_RUNNABLE_DEV = 'globalThis.__VIKE__IS_NON_RUNNABLE_DEV';
7
6
  const DYNAMIC_IMPORT = '__VIKE__DYNAMIC_IMPORT';
7
+ // === Rolldown filter
8
+ const filterRolldown1 = {
9
+ code: {
10
+ include: IS_NON_RUNNABLE_DEV,
11
+ },
12
+ };
13
+ const filterFunction1 = (code) => {
14
+ return code.includes(IS_NON_RUNNABLE_DEV);
15
+ };
16
+ const filterRolldown2 = {
17
+ code: {
18
+ include: DYNAMIC_IMPORT,
19
+ },
20
+ };
21
+ const filterFunction2 = (code) => {
22
+ return code.includes(DYNAMIC_IMPORT);
23
+ };
24
+ // We cannot use [`filter.id`](https://rolldown.rs/plugins/hook-filters) because Vite's optimizeDeps bundles packages (e.g. `vike` or `telefunc`) into node_modules/.vite/deps_ssr/chunk-WBC5FHD7.js
25
+ //
26
+ // Therefore, we cannot do this:
27
+ // ```js
28
+ // const distFileIsNonRunnableDev = requireResolveDistFile('dist/utils/isNonRunnableDevProcess.js')
29
+ // const distFileGlobalContext = requireResolveDistFile('dist/server/runtime/globalContext.js')
30
+ // const filterRolldown = {
31
+ // id: {
32
+ // include: [distFileIsNonRunnableDev, distFileGlobalContext].map(
33
+ // (filePath) => new RegExp(`^${escapeRegex(filePath)}($|${escapeRegex('?')}.*)`),
34
+ // ),
35
+ // },
36
+ // }
37
+ // ```
38
+ // ===
8
39
  function pluginReplaceConstantsNonRunnableDev() {
9
40
  return [
10
41
  {
11
42
  name: 'vike:pluginReplaceConstantsNonRunnableDev:IS_NON_RUNNABLE_DEV',
12
43
  apply: (_, configEnv) => isDevCheck(configEnv),
13
44
  transform: {
14
- filter: {
15
- code: {
16
- include: IS_NON_RUNNABLE_DEV,
17
- },
18
- },
45
+ filter: filterRolldown1,
19
46
  handler(code, id) {
47
+ assert(filterFunction1(code));
20
48
  if (isRunnableDevEnvironment(this.environment))
21
49
  return;
22
50
  const { magicString, getMagicStringResult } = getMagicString(code, id);
@@ -29,12 +57,9 @@ function pluginReplaceConstantsNonRunnableDev() {
29
57
  name: 'vike:pluginReplaceConstantsNonRunnableDev:DYNAMIC_IMPORT',
30
58
  apply: (_, configEnv) => isDevCheck(configEnv),
31
59
  transform: {
32
- filter: {
33
- code: {
34
- include: DYNAMIC_IMPORT,
35
- },
36
- },
60
+ filter: filterRolldown2,
37
61
  handler(code, id) {
62
+ assert(filterFunction2(code));
38
63
  if (isRunnableDevEnvironment(this.environment))
39
64
  return;
40
65
  const { magicString, getMagicStringResult } = getMagicString(code, id);
@@ -1,5 +1,5 @@
1
1
  export { pluginAssertFileEnv };
2
- import { assert, assertUsage, assertWarning, capitalizeFirstLetter, isFilePathAbsolute, joinEnglish, rollupSourceMapRemove, } from '../utils.js';
2
+ import { applyDev, assert, assertUsage, assertWarning, capitalizeFirstLetter, isFilePathAbsolute, joinEnglish, rollupSourceMapRemove, } from '../utils.js';
3
3
  import { extractAssetsRE } from './pluginExtractAssets.js';
4
4
  import { extractExportNamesRE } from './pluginExtractExportNames.js';
5
5
  import pc from '@brillout/picocolors';
@@ -10,6 +10,7 @@ import { isV1Design } from '../shared/resolveVikeConfigInternal.js';
10
10
  import { isViteServerSide, isViteServerSide_extraSafe } from '../shared/isViteServerSide.js';
11
11
  import { suffixesAssertFileEnv } from '../../../shared-server-node/getFileSuffixes.js';
12
12
  const envS = suffixesAssertFileEnv;
13
+ // === Rolldown filter
13
14
  const skipNodeModules = '/node_modules/'; // Only assert `.server.js`, `.client.js` and `.ssr.js` for user files
14
15
  const filterRolldown = {
15
16
  id: {
@@ -22,18 +23,19 @@ const filterFunction = (id) => {
22
23
  return false;
23
24
  return envS.some((suffix) => id.includes(getSuffix(suffix)));
24
25
  };
26
+ // ===
25
27
  function pluginAssertFileEnv() {
26
28
  let config;
27
29
  let viteDevServer;
28
30
  return [
29
31
  {
30
- name: 'vike:pluginAssertFileEnv',
32
+ name: 'vike:pluginAssertFileEnv:dev',
33
+ // In build, we use generateBundle() instead of the load() hook. Using load() works for dynamic imports in dev thanks to Vite's lazy transpiling, but it doesn't work in build because Rollup transpiles any dynamically imported module even if it's never actually imported.
34
+ apply: applyDev,
31
35
  load: {
32
36
  filter: filterRolldown,
33
37
  handler(id, options) {
34
- // In build, we use generateBundle() instead of the load() hook. Using load() works for dynamic imports in dev thanks to Vite's lazy transpiling, but it doesn't work in build because Rollup transpiles any dynamically imported module even if it's never actually imported.
35
- if (!viteDevServer)
36
- return;
38
+ assert(viteDevServer);
37
39
  if (!isV1Design())
38
40
  return;
39
41
  if (skip(id, config.root))
@@ -53,14 +55,26 @@ function pluginAssertFileEnv() {
53
55
  true);
54
56
  },
55
57
  },
58
+ configureServer: {
59
+ handler(viteDevServer_) {
60
+ viteDevServer = viteDevServer_;
61
+ },
62
+ },
63
+ configResolved: {
64
+ handler(config_) {
65
+ config = config_;
66
+ },
67
+ },
68
+ },
69
+ {
70
+ name: 'vike:pluginAssertFileEnv:build',
71
+ // In dev, only using load() is enough as it also works for dynamic imports (see sibling comment).
72
+ apply: 'build',
56
73
  // In production, we have to use transform() to replace modules with a runtime error because generateBundle() doesn't work for dynamic imports. In production, dynamic imports can only be verified at runtime.
57
74
  transform: {
58
75
  filter: filterRolldown,
59
76
  async handler(code, id, options) {
60
77
  id = normalizeId(id);
61
- // In dev, only using load() is enough as it also works for dynamic imports (see sibling comment).
62
- if (viteDevServer)
63
- return;
64
78
  if (skip(id, config.root))
65
79
  return;
66
80
  const isServerSide = isViteServerSide_extraSafe(config, this.environment, options);
@@ -101,11 +115,6 @@ function pluginAssertFileEnv() {
101
115
  config = config_;
102
116
  },
103
117
  },
104
- configureServer: {
105
- handler(viteDevServer_) {
106
- viteDevServer = viteDevServer_;
107
- },
108
- },
109
118
  },
110
119
  ];
111
120
  function assertFileEnv(moduleId, isServerSide, importers, onlyWarn) {
@@ -23,12 +23,14 @@ const rawRE = /(\?|&)raw(?:&|$)/;
23
23
  const urlRE = /(\?|&)url(?:&|$)/;
24
24
  const EMPTY_MODULE_ID = 'virtual:vike:empty-module';
25
25
  const debug = createDebug('vike:pluginExtractAssets');
26
+ // === Rolldown filter
26
27
  const filterRolldown = {
27
28
  id: {
28
29
  include: extractAssetsRE,
29
30
  },
30
31
  };
31
32
  const filterFunction = (id) => extractAssetsRE.test(id);
33
+ // ===
32
34
  function pluginExtractAssets() {
33
35
  let config;
34
36
  let vikeConfig;
@@ -8,12 +8,14 @@ import { isViteServerSide_extraSafe } from '../shared/isViteServerSide.js';
8
8
  const extractExportNamesRE = /(\?|&)extractExportNames(?:&|$)/;
9
9
  const debug = createDebug('vike:pluginExtractExportNames');
10
10
  const globalObject = getGlobalObject('plugins/pluginExtractExportNames.ts', {});
11
+ // === Rolldown filter
11
12
  const filterRolldown = {
12
13
  id: {
13
14
  include: extractExportNamesRE,
14
15
  },
15
16
  };
16
17
  const filterFunction = (id) => extractExportNamesRE.test(id);
18
+ // ===
17
19
  function pluginExtractExportNames() {
18
20
  let isDev = false;
19
21
  let config;
@@ -14,6 +14,7 @@ const PUBLIC_ENV_ALLOWLIST = [
14
14
  // - Make import.meta.env work inside +config.js
15
15
  // - For it to work, we'll probably need the user to define the settings (e.g. `envDir`) for loadEnv() inside vike.config.js instead of vite.config.js
16
16
  // - Or stop using Vite's `mode` implementation and have Vike implement its own `mode` feature? (So that the only dependencies are `$ vike build --mode staging` and `$ MODE=staging vike build`.)
17
+ // === Rolldown filter
17
18
  const skipNodeModules = '/node_modules/';
18
19
  const skipIrrelevant = 'import.meta.env.';
19
20
  const filterRolldown = {
@@ -31,6 +32,7 @@ const filterFunction = (id, code) => {
31
32
  return false;
32
33
  return true;
33
34
  };
35
+ // ===
34
36
  function pluginReplaceConstantsEnvVars() {
35
37
  let envVarsAll;
36
38
  let envPrefix;
@@ -2,16 +2,18 @@ export { pluginReplaceConstantsGlobalThis };
2
2
  export { VIRTUAL_FILE_ID_constantsGlobalThis };
3
3
  import { assert, isDebug, addVirtualFileIdPrefix, escapeRegex } from '../utils.js';
4
4
  import { isViteServerSide_applyToEnvironment, isViteServerSide_configEnvironment, isViteServerSide_extraSafe, } from '../shared/isViteServerSide.js';
5
+ const VIRTUAL_FILE_ID_constantsGlobalThis = 'virtual:vike:server:constantsGlobalThis';
5
6
  const isDebugVal = isDebug();
6
7
  globalThis.__VIKE__IS_CLIENT = false;
7
8
  globalThis.__VIKE__IS_DEBUG = isDebugVal;
8
- const VIRTUAL_FILE_ID_constantsGlobalThis = 'virtual:vike:server:constantsGlobalThis';
9
+ // === Rolldown filter
9
10
  const filterRolldown = {
10
11
  id: {
11
12
  include: new RegExp(escapeRegex(VIRTUAL_FILE_ID_constantsGlobalThis)),
12
13
  },
13
14
  };
14
15
  const filterFunction = (id) => id === VIRTUAL_FILE_ID_constantsGlobalThis || id === addVirtualFileIdPrefix(VIRTUAL_FILE_ID_constantsGlobalThis);
16
+ // ===
15
17
  function pluginReplaceConstantsGlobalThis() {
16
18
  let config;
17
19
  let isDev;
@@ -11,7 +11,7 @@ const constantsIsClientSide = [
11
11
  ];
12
12
  // - See https://vike.dev/pageContext#narrowing-down
13
13
  // - We cannot use [`define`](https://vite.dev/config/shared-options.html#define) because of https://github.com/rolldown/rolldown/issues/4300
14
- // filterRolldown
14
+ // === Rolldown filter
15
15
  const skipNodeModules = '/node_modules/';
16
16
  const skipIrrelevant = 'Context.isClientSide';
17
17
  assert(constantsIsClientSide.every((constant) => constant.endsWith(skipIrrelevant)));
@@ -30,6 +30,7 @@ const filterFunction = (id, code) => {
30
30
  return false;
31
31
  return true;
32
32
  };
33
+ // ===
33
34
  function pluginReplaceConstantsPageContext() {
34
35
  let config;
35
36
  return [
@@ -90,10 +90,12 @@ type RemoveTarget = {
90
90
  * }
91
91
  */
92
92
  type StaticReplace = {
93
- /** Type of transformation - currently only 'call' is supported, but can be extended in the future */
94
- type?: 'call';
95
93
  /** Environment filter: 'client' = client only, 'server' = everything except client */
96
- env?: 'server' | 'client';
94
+ env: 'server' | 'client';
95
+ /** Rolldown filter — MUST be narrowing as much as possible, otherwise you'll get significant performance degradation */
96
+ filter: string;
97
+ /** Type of transformation - currently only 'call' is supported, but can be extended in the future */
98
+ type: 'call';
97
99
  /** Match criteria */
98
100
  match: {
99
101
  /**
@@ -2,7 +2,7 @@ export { applyStaticReplace };
2
2
  import { transformAsync } from '@babel/core';
3
3
  import * as t from '@babel/types';
4
4
  import { parseImportString } from '../../shared/importString.js';
5
- import assert from 'node:assert';
5
+ import { assert } from '../../utils.js';
6
6
  // ============================================================================
7
7
  // Main transformer
8
8
  // ============================================================================
@@ -11,9 +11,11 @@ async function applyStaticReplace(code, staticReplaceList, id, env) {
11
11
  const SKIPPED = undefined;
12
12
  const NO_CHANGE = null;
13
13
  const staticReplaceListFiltered = staticReplaceList.filter((staticReplace) => {
14
- if (!staticReplace.env)
15
- return true;
16
- return staticReplace.env === env;
14
+ if (staticReplace.env && staticReplace.env !== env)
15
+ return false;
16
+ if (!code.includes(staticReplace.filter))
17
+ return false;
18
+ return true;
17
19
  });
18
20
  if (staticReplaceListFiltered.length === 0) {
19
21
  return SKIPPED;
@@ -58,6 +60,15 @@ function valueToAst(value) {
58
60
  return t.numericLiteral(value);
59
61
  if (typeof value === 'boolean')
60
62
  return t.booleanLiteral(value);
63
+ if (Array.isArray(value)) {
64
+ return t.arrayExpression(value.map(valueToAst));
65
+ }
66
+ if (typeof value === 'object') {
67
+ const properties = Object.entries(value).map(([key, val]) => {
68
+ return t.objectProperty(t.identifier(key), valueToAst(val));
69
+ });
70
+ return t.objectExpression(properties);
71
+ }
61
72
  return t.callExpression(t.memberExpression(t.identifier('JSON'), t.identifier('parse')), [
62
73
  t.stringLiteral(JSON.stringify(value)),
63
74
  ]);
@@ -1,8 +1,7 @@
1
1
  export { pluginStaticReplace };
2
- import { assert, createDebug } from '../utils.js';
2
+ import { assert, assertUsage, createDebug } from '../utils.js';
3
3
  import { isViteServerSide_extraSafe } from '../shared/isViteServerSide.js';
4
4
  import { applyStaticReplace } from './pluginStaticReplace/applyStaticReplace.js';
5
- import { buildFilterRolldown } from './pluginStaticReplace/buildFilterRolldown.js';
6
5
  const debug = createDebug('vike:staticReplace');
7
6
  function pluginStaticReplace(vikeConfig) {
8
7
  let config;
@@ -10,9 +9,9 @@ function pluginStaticReplace(vikeConfig) {
10
9
  const staticReplaceList = getStaticReplaceList(vikeConfig);
11
10
  if (staticReplaceList.length === 0)
12
11
  return [];
13
- // filterRolldown
12
+ // === Rolldown filter
14
13
  const skipNodeModules = '/node_modules/';
15
- const include = buildFilterRolldown(staticReplaceList);
14
+ const include = getFilterRolldown(staticReplaceList);
16
15
  assert(include);
17
16
  const filterRolldown = {
18
17
  id: {
@@ -25,10 +24,11 @@ function pluginStaticReplace(vikeConfig) {
25
24
  const filterFunction = (id, code) => {
26
25
  if (id.includes(skipNodeModules))
27
26
  return false;
28
- if (!include.test(code))
27
+ if (!include.some((s) => code.includes(s)))
29
28
  return false;
30
29
  return true;
31
30
  };
31
+ // ===
32
32
  return [
33
33
  {
34
34
  name: 'vike:pluginStaticReplace',
@@ -79,3 +79,10 @@ function getStaticReplaceList(vikeConfig) {
79
79
  }
80
80
  return staticReplaceList;
81
81
  }
82
+ function getFilterRolldown(staticReplaceList) {
83
+ return staticReplaceList.map((staticReplace) => {
84
+ const { filter } = staticReplace;
85
+ assertUsage(filter, '+staticReplace entry is missing rolldown filter');
86
+ return filter;
87
+ });
88
+ }
@@ -12,12 +12,14 @@ import { updateUserFiles } from '../../../server/runtime/globalContext.js';
12
12
  import { isPlusFile } from '../shared/resolveVikeConfigInternal/crawlPlusFilePaths.js';
13
13
  import { isTemporaryBuildFile } from '../shared/resolveVikeConfigInternal/transpileAndExecuteFile.js';
14
14
  import { debugFileChange, getVikeConfigError } from '../../../shared-server-node/getVikeConfigError.js';
15
+ // === Rolldown filter
15
16
  const filterRolldown = {
16
17
  id: {
17
18
  include: new RegExp(`^(${escapeRegex(virtualFileIdPrefix1)}|${escapeRegex(virtualFileIdPrefix2)})`),
18
19
  },
19
20
  };
20
21
  const filterFunction = (id) => isVirtualFileId(id);
22
+ // ===
21
23
  function pluginVirtualFiles() {
22
24
  let config;
23
25
  return [
@@ -1,7 +1,8 @@
1
1
  export { parseImportString };
2
2
  export { isImportString };
3
3
  export { serializeImportString };
4
- import { assert } from '../utils.js';
4
+ import pc from '@brillout/picocolors';
5
+ import { assert, assertWarning } from '../utils.js';
5
6
  const IMPORT = 'import';
6
7
  const SEP = ':';
7
8
  /**
@@ -17,14 +18,12 @@ const SEP = ':';
17
18
  * // => { importPath: './Layout', exportName: 'default' }
18
19
  */
19
20
  function parseImportString(importString, { legacy = false } = {}) {
20
- if (!isImportString(importString))
21
+ if (!importString.startsWith(`${IMPORT}${SEP}`))
21
22
  return null;
22
23
  const parts = importString.split(SEP);
23
24
  assert(parts[0] === IMPORT);
24
25
  if (legacy && parts.length === 2) {
25
- /* TODO
26
- assertWarning(false, 'To-Do', { onlyOnce: true, showStackTrace: true })
27
- */
26
+ assertWarning(false, `Replace ${pc.cyan(importString)} with ${pc.cyan(importString)}${pc.cyan(':default')} (import strings must include the export name)`, { onlyOnce: true });
28
27
  const exportName = 'default';
29
28
  const importPath = parts[1];
30
29
  assert(importPath);
@@ -47,7 +46,7 @@ function parseImportString(importString, { legacy = false } = {}) {
47
46
  * // => false
48
47
  */
49
48
  function isImportString(str) {
50
- return str.startsWith(`${IMPORT}${SEP}`);
49
+ return !!parseImportString(str, { legacy: true });
51
50
  }
52
51
  /**
53
52
  * Serialize import string from importPath and export name.
@@ -1 +1 @@
1
- export declare const PROJECT_VERSION: "0.4.249-commit-4ef7732";
1
+ export declare const PROJECT_VERSION: "0.4.249-commit-b3b9c55";
@@ -1,2 +1,2 @@
1
1
  // Automatically updated by @brillout/release-me
2
- export const PROJECT_VERSION = '0.4.249-commit-4ef7732';
2
+ export const PROJECT_VERSION = '0.4.249-commit-b3b9c55';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vike",
3
- "version": "0.4.249-commit-4ef7732",
3
+ "version": "0.4.249-commit-b3b9c55",
4
4
  "repository": "https://github.com/vikejs/vike",
5
5
  "exports": {
6
6
  "./server": {
@@ -119,6 +119,7 @@
119
119
  },
120
120
  "dependencies": {
121
121
  "@babel/core": "^7.28.5",
122
+ "@babel/types": "^7.28.5",
122
123
  "@brillout/import": "^0.2.6",
123
124
  "@brillout/json-serializer": "^0.5.21",
124
125
  "@brillout/picocolors": "^1.0.30",
@@ -244,7 +245,6 @@
244
245
  "./universal-middleware.js"
245
246
  ],
246
247
  "devDependencies": {
247
- "@babel/types": "^7.28.5",
248
248
  "@brillout/release-me": "^0.4.12",
249
249
  "@types/babel__core": "^7.20.5",
250
250
  "@types/estree": "^1.0.5",
@@ -1,9 +0,0 @@
1
- export { buildFilterRolldown };
2
- import type { StaticReplace } from './applyStaticReplace.js';
3
- /**
4
- * Build a filterRolldown from staticReplaceList by extracting all import strings.
5
- * For a single entry, ALL import strings must be present (AND logic),
6
- * except for call.match.function array which is OR logic.
7
- * Between staticReplace entries it's OR logic.
8
- */
9
- declare function buildFilterRolldown(staticReplaceList: StaticReplace[]): RegExp | null;
@@ -1,100 +0,0 @@
1
- export { buildFilterRolldown };
2
- import { escapeRegex } from '../../utils.js';
3
- import { parseImportString } from '../../shared/importString.js';
4
- /**
5
- * Build a filterRolldown from staticReplaceList by extracting all import strings.
6
- * For a single entry, ALL import strings must be present (AND logic),
7
- * except for call.match.function array which is OR logic.
8
- * Between staticReplace entries it's OR logic.
9
- */
10
- function buildFilterRolldown(staticReplaceList) {
11
- const rulePatterns = [];
12
- // Process each entry separately
13
- for (const staticReplaceEntry of staticReplaceList) {
14
- const importStrings = new Set();
15
- const functionImportStrings = new Set();
16
- // Extract function import strings separately
17
- extractImportStrings(staticReplaceEntry.match.function, functionImportStrings);
18
- // Extract arg import strings
19
- if (staticReplaceEntry.match.args) {
20
- for (const condition of Object.values(staticReplaceEntry.match.args)) {
21
- extractImportStringsFromCondition(condition, importStrings);
22
- }
23
- }
24
- // Build pattern for this staticReplaceEntry
25
- const ruleParts = [];
26
- // For function imports: if array, use OR; otherwise use AND
27
- if (functionImportStrings.size > 0) {
28
- const functionPatterns = [];
29
- for (const importStr of functionImportStrings) {
30
- const parts = parseImportString(importStr);
31
- if (parts) {
32
- // Each function import should match both importPath and export name
33
- functionPatterns.push(`(?=.*${escapeRegex(parts.importPath)})(?=.*${escapeRegex(parts.exportName)})`);
34
- }
35
- }
36
- // If multiple functions, they are alternatives (OR)
37
- if (functionPatterns.length > 0) {
38
- if (functionPatterns.length === 1) {
39
- ruleParts.push(functionPatterns[0]);
40
- }
41
- else {
42
- // Multiple function patterns: file must match at least one
43
- ruleParts.push(`(?:${functionPatterns.join('|')})`);
44
- }
45
- }
46
- }
47
- // For arg imports: all must be present (AND)
48
- for (const importStr of importStrings) {
49
- const parts = parseImportString(importStr);
50
- if (parts) {
51
- // Each arg import should match both importPath and export name
52
- ruleParts.push(`(?=.*${escapeRegex(parts.importPath)})(?=.*${escapeRegex(parts.exportName)})`);
53
- }
54
- }
55
- // Combine all parts for this rule with AND logic
56
- if (ruleParts.length > 0) {
57
- // All parts must match for this rule
58
- rulePatterns.push(ruleParts.join(''));
59
- }
60
- }
61
- if (rulePatterns.length === 0)
62
- return null;
63
- // Create a regex that matches if any rule pattern matches (OR between staticReplace entries)
64
- return new RegExp(rulePatterns.join('|'), 's');
65
- }
66
- /**
67
- * Extract import strings from function patterns
68
- */
69
- function extractImportStrings(functions, result) {
70
- const arr = Array.isArray(functions) ? functions : [functions];
71
- for (const fn of arr) {
72
- if (parseImportString(fn)) {
73
- result.add(fn);
74
- }
75
- }
76
- }
77
- /**
78
- * Extract import strings from argument conditions
79
- */
80
- function extractImportStringsFromCondition(condition, result) {
81
- if (typeof condition === 'string') {
82
- if (parseImportString(condition)) {
83
- result.add(condition);
84
- }
85
- }
86
- else if (condition && typeof condition === 'object') {
87
- // Handle call condition
88
- if ('call' in condition && typeof condition.call === 'string') {
89
- if (parseImportString(condition.call)) {
90
- result.add(condition.call);
91
- }
92
- // Recursively check nested args
93
- if (condition.args) {
94
- for (const nestedCondition of Object.values(condition.args)) {
95
- extractImportStringsFromCondition(nestedCondition, result);
96
- }
97
- }
98
- }
99
- }
100
- }