@emulsify/core 4.2.1 → 4.3.0
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/.storybook/main-vite.js +91 -36
- package/README.md +185 -56
- package/config/a11y.config.js +2 -1
- package/config/vite/entries.js +4 -4
- package/config/vite/plugins/{copy-src-assets.js → assets/copy-src-assets.js} +1 -1
- package/config/vite/plugins/{copy-twig-files.js → assets/copy-twig-files.js} +1 -1
- package/config/vite/plugins/{css-asset-relativizer.js → assets/css-asset-relativizer.js} +9 -0
- package/config/vite/plugins/{mirror-components.js → assets/mirror-components.js} +2 -28
- package/config/vite/plugins/{source-file-index.js → assets/source-file-index.js} +1 -1
- package/config/vite/plugins/{svg-sprite.js → assets/svg-sprite.js} +2 -2
- package/config/vite/plugins/index.js +23 -14
- package/config/vite/plugins/reporter/asset-resolver.js +541 -0
- package/config/vite/plugins/reporter/build-errors.js +284 -0
- package/config/vite/plugins/reporter/diagnostics.js +366 -0
- package/config/vite/plugins/reporter/format.js +199 -0
- package/config/vite/plugins/reporter/index.js +308 -0
- package/config/vite/plugins/reporter/render.js +758 -0
- package/config/vite/plugins/reporter/sass-logger.js +237 -0
- package/config/vite/plugins/reporter/vite-logger.js +188 -0
- package/config/vite/plugins/reporter/watch-mode.js +40 -0
- package/config/vite/plugins/{twig-extension-installers.js → twig/extension-installers.js} +1 -1
- package/config/vite/{twig-extensions.js → plugins/twig/extensions.js} +2 -2
- package/config/vite/plugins/{twig-module.js → twig/twig-module.js} +197 -85
- package/config/vite/plugins/{virtual-twig-asset-sources.js → twig/virtual-twig-asset-sources.js} +37 -136
- package/config/vite/plugins/{virtual-twig-globs.js → twig/virtual-twig-globs.js} +3 -32
- package/config/vite/plugins/{vituum-patch.js → twig/vituum-patch.js} +3 -3
- package/config/vite/plugins.js +1 -1
- package/config/vite/project-config.js +1 -1
- package/config/vite/project-structure.js +1 -1
- package/config/vite/utils/lru.js +77 -0
- package/config/vite/utils/package-version.js +42 -0
- package/config/vite/utils/paths.js +1 -9
- package/config/vite/utils/react-singleton.js +1 -1
- package/config/vite/vite.config.js +51 -5
- package/package.json +93 -58
- package/scripts/a11y.js +115 -23
- package/scripts/audit/checks/core-imports.js +78 -0
- package/scripts/audit/checks/css-asset-references.js +99 -0
- package/scripts/audit/checks/drupal-assumptions.js +48 -0
- package/scripts/audit/checks/files-outside-roots.js +53 -0
- package/scripts/audit/checks/generated-package-scripts.js +113 -0
- package/scripts/audit/checks/legacy-twig-stories.js +33 -0
- package/scripts/audit/checks/package-overrides.js +91 -0
- package/scripts/audit/checks/project-config.js +71 -0
- package/scripts/audit/checks/story-discovery.js +35 -0
- package/scripts/audit/checks/twig-references.js +69 -0
- package/scripts/audit/checks/twig-volume.js +54 -0
- package/scripts/audit/checks/webpack-patterns.js +86 -0
- package/scripts/audit/index.js +177 -0
- package/scripts/audit/lib/css.js +165 -0
- package/scripts/audit/lib/files.js +168 -0
- package/scripts/audit/lib/findings.js +31 -0
- package/scripts/audit/lib/package-json.js +65 -0
- package/scripts/audit/lib/twig.js +227 -0
- package/scripts/audit/report.js +273 -0
- package/scripts/audit-twig-stories.js +115 -78
- package/scripts/audit.js +150 -1632
- package/scripts/check-node-version.js +136 -10
- package/scripts/inspect-components.js +456 -0
- package/scripts/lib/cli.js +179 -0
- package/scripts/lib/fs.js +31 -0
- package/scripts/lib/proc.js +78 -0
- package/scripts/lib/text.js +14 -0
- package/scripts/loadYaml.js +2 -2
- package/src/extensions/shared/attributes.js +3 -3
- package/src/extensions/shared/lists.js +2 -6
- package/src/extensions/shared/root-relative.js +38 -0
- package/src/storybook/index.js +4 -0
- package/src/storybook/render-twig.js +1 -1
- package/src/storybook/render-web-component.js +459 -0
- package/src/storybook/twig/asset-source-runtime.js +193 -0
- package/src/storybook/twig/{source-extensions.js → constants.js} +3 -1
- package/src/storybook/twig/reference-paths.js +2 -13
- package/src/storybook/twig/setup.js +12 -2
- package/src/storybook/twig/source-function.js +5 -2
- package/config/vite/utils/unique.js +0 -36
- package/src/storybook/twig/include.js +0 -28
- package/src/storybook/twig/source-events.js +0 -5
|
@@ -10,22 +10,24 @@
|
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
import fs from 'fs';
|
|
13
|
+
import { readFile, stat } from 'fs/promises';
|
|
13
14
|
import { basename, dirname, isAbsolute, relative, resolve } from 'path';
|
|
14
15
|
import Twig from 'twig';
|
|
15
16
|
|
|
16
17
|
import {
|
|
17
18
|
getTwigFunctionMap,
|
|
18
19
|
registerTwigExtensions,
|
|
19
|
-
} from '
|
|
20
|
-
import { toRootRelativePath } from '
|
|
21
|
-
import { resolveProjectStructure } from '
|
|
20
|
+
} from '../../../../src/extensions/twig/index.js';
|
|
21
|
+
import { toRootRelativePath } from '../../../../src/storybook/twig/reference-paths.js';
|
|
22
|
+
import { resolveProjectStructure } from '../../project-structure.js';
|
|
22
23
|
import {
|
|
23
|
-
registerConfiguredTwigExtensions,
|
|
24
24
|
shouldRegisterDrupalTwigFilters,
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
import {
|
|
28
|
-
import {
|
|
25
|
+
installProjectTwigExtensions,
|
|
26
|
+
} from './extensions.js';
|
|
27
|
+
import { firstExistingPath, safeExists } from '../../utils/fs-safe.js';
|
|
28
|
+
import { createLruCache } from '../../utils/lru.js';
|
|
29
|
+
import { toPosixPath } from '../../utils/paths.js';
|
|
30
|
+
import { unique } from '../../../../src/extensions/shared/lists.js';
|
|
29
31
|
|
|
30
32
|
/** Twig token types that can reference another template file. */
|
|
31
33
|
const templateReferenceTokenTypes = [
|
|
@@ -38,6 +40,10 @@ const templateReferenceTokenTypes = [
|
|
|
38
40
|
|
|
39
41
|
const includeFunctionName = 'include';
|
|
40
42
|
const sourceFunctionName = 'source';
|
|
43
|
+
const VIRTUAL_TWIG_DEPENDENCY_PREFIX = 'virtual:emulsify-twig-dep:';
|
|
44
|
+
const RESOLVED_VIRTUAL_TWIG_DEPENDENCY_PREFIX = `\0${VIRTUAL_TWIG_DEPENDENCY_PREFIX}`;
|
|
45
|
+
const maxCompiledTemplateCacheEntries = 2000;
|
|
46
|
+
const maxResolutionCacheEntries = 5000;
|
|
41
47
|
const expressionTokenTypes = {
|
|
42
48
|
arrayEnd: 'Twig.expression.type.array.end',
|
|
43
49
|
arrayStart: 'Twig.expression.type.array.start',
|
|
@@ -63,16 +69,16 @@ const expressionClosingTokenTypes = new Set([
|
|
|
63
69
|
/**
|
|
64
70
|
* Cache compiled Twig templates by absolute path for the life of one build.
|
|
65
71
|
*
|
|
66
|
-
* @type {
|
|
72
|
+
* @type {ReturnType<typeof createLruCache>}
|
|
67
73
|
*/
|
|
68
|
-
const compileCache =
|
|
74
|
+
const compileCache = createLruCache(maxCompiledTemplateCacheEntries);
|
|
69
75
|
|
|
70
76
|
/**
|
|
71
77
|
* Cache resolved Twig include paths by source directory, reference, and roots.
|
|
72
78
|
*
|
|
73
|
-
* @type {
|
|
79
|
+
* @type {ReturnType<typeof createLruCache>}
|
|
74
80
|
*/
|
|
75
|
-
const resolutionCache =
|
|
81
|
+
const resolutionCache = createLruCache(maxResolutionCacheEntries);
|
|
76
82
|
|
|
77
83
|
/**
|
|
78
84
|
* Cache recursively discovered component grouping directories by root.
|
|
@@ -121,6 +127,13 @@ const canMemoizeByEnv = (env) => env && typeof env === 'object';
|
|
|
121
127
|
* @returns {boolean} TRUE when the request is a renderable Twig module.
|
|
122
128
|
*/
|
|
123
129
|
const isTwigModuleRequest = (id) => {
|
|
130
|
+
if (
|
|
131
|
+
id.startsWith(VIRTUAL_TWIG_DEPENDENCY_PREFIX) ||
|
|
132
|
+
id.startsWith(RESOLVED_VIRTUAL_TWIG_DEPENDENCY_PREFIX)
|
|
133
|
+
) {
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
136
|
+
|
|
124
137
|
const [filePath, query = ''] = id.split('?');
|
|
125
138
|
if (!filePath.endsWith('.twig')) return false;
|
|
126
139
|
return !query || query === 'twig' || !/(^|&)(raw|url)\b/.test(query);
|
|
@@ -134,6 +147,24 @@ const isTwigModuleRequest = (id) => {
|
|
|
134
147
|
*/
|
|
135
148
|
const stripRequestQuery = (id) => id.split('?')[0];
|
|
136
149
|
|
|
150
|
+
const encodeVirtualTwigDependencyId = (filePath) =>
|
|
151
|
+
`${VIRTUAL_TWIG_DEPENDENCY_PREFIX}${encodeURIComponent(resolve(filePath))}`;
|
|
152
|
+
|
|
153
|
+
const resolvedVirtualTwigDependencyId = (filePath) =>
|
|
154
|
+
`${RESOLVED_VIRTUAL_TWIG_DEPENDENCY_PREFIX}${encodeURIComponent(
|
|
155
|
+
resolve(filePath),
|
|
156
|
+
)}`;
|
|
157
|
+
|
|
158
|
+
const decodeVirtualTwigDependencyId = (id) => {
|
|
159
|
+
const normalizedId = id.startsWith('\0') ? id.slice(1) : id;
|
|
160
|
+
|
|
161
|
+
return normalizedId.startsWith(VIRTUAL_TWIG_DEPENDENCY_PREFIX)
|
|
162
|
+
? decodeURIComponent(
|
|
163
|
+
normalizedId.slice(VIRTUAL_TWIG_DEPENDENCY_PREFIX.length),
|
|
164
|
+
)
|
|
165
|
+
: '';
|
|
166
|
+
};
|
|
167
|
+
|
|
137
168
|
/**
|
|
138
169
|
* Extract the first argument from a Twig function token parameter list.
|
|
139
170
|
*
|
|
@@ -445,6 +476,21 @@ const templateIdForPath = (filePath, options) => {
|
|
|
445
476
|
const makeTemplateInstantiationCode = (templateId, params) =>
|
|
446
477
|
`Twig.twig(${JSON.stringify({ ...params, id: templateId })})`;
|
|
447
478
|
|
|
479
|
+
const makeTemplateInstantiationFromParamsCode = (
|
|
480
|
+
templateIdExpression,
|
|
481
|
+
paramsExpression,
|
|
482
|
+
) => `Twig.twig({ ...${paramsExpression}, id: ${templateIdExpression} })`;
|
|
483
|
+
|
|
484
|
+
const generateTwigDependencyModule = async (filePath, options) => {
|
|
485
|
+
const compiled = await compileTwigTemplate(filePath, options, compileCache);
|
|
486
|
+
|
|
487
|
+
return [
|
|
488
|
+
`export const templateId = ${JSON.stringify(compiled.templateId)};`,
|
|
489
|
+
`export const templateParams = ${JSON.stringify(compiled.templateParams)};`,
|
|
490
|
+
'',
|
|
491
|
+
].join('\n');
|
|
492
|
+
};
|
|
493
|
+
|
|
448
494
|
/**
|
|
449
495
|
* Rewrite static include/import/embed references to module-local template IDs.
|
|
450
496
|
*
|
|
@@ -779,12 +825,12 @@ const invalidateKnownResolutionCacheEntries = (filePath) => {
|
|
|
779
825
|
* @param {string} filePath - Absolute template file path.
|
|
780
826
|
* @param {ReturnType<typeof makeTwigPluginOptions>} options - Twig plugin options.
|
|
781
827
|
* @param {typeof compileCache} [cache=compileCache] - Shared compile cache.
|
|
782
|
-
* @returns {{ code: string, includes: string[], sourceReferences: string[] }} Compiled template code and references.
|
|
828
|
+
* @returns {Promise<{ code: string, includes: string[], sourceReferences: string[] }>} Compiled template code and references.
|
|
783
829
|
*/
|
|
784
|
-
const compileTwigTemplate = (filePath, options, cache = compileCache) => {
|
|
830
|
+
const compileTwigTemplate = async (filePath, options, cache = compileCache) => {
|
|
785
831
|
const absoluteFilePath = resolve(filePath);
|
|
786
832
|
knownTwigFiles.add(absoluteFilePath);
|
|
787
|
-
const { mtimeMs } =
|
|
833
|
+
const { mtimeMs } = await stat(absoluteFilePath);
|
|
788
834
|
const cached = cache.get(absoluteFilePath);
|
|
789
835
|
if (cached?.mtimeMs === mtimeMs) {
|
|
790
836
|
return cached.compiled;
|
|
@@ -792,9 +838,9 @@ const compileTwigTemplate = (filePath, options, cache = compileCache) => {
|
|
|
792
838
|
|
|
793
839
|
const compilerTwig = Twig.factory();
|
|
794
840
|
registerTwigExtensions(compilerTwig);
|
|
795
|
-
|
|
841
|
+
installProjectTwigExtensions(compilerTwig, options);
|
|
796
842
|
|
|
797
|
-
const source =
|
|
843
|
+
const source = await readFile(absoluteFilePath, 'utf8');
|
|
798
844
|
const compileOptions = {
|
|
799
845
|
allowInlineIncludes: true,
|
|
800
846
|
namespaces: options.namespaces,
|
|
@@ -1042,7 +1088,27 @@ export function emulsifyTwigModulePlugin(options) {
|
|
|
1042
1088
|
knownTwigFiles.clear();
|
|
1043
1089
|
transformedTwigModules.clear();
|
|
1044
1090
|
},
|
|
1045
|
-
|
|
1091
|
+
resolveId(id) {
|
|
1092
|
+
if (id.startsWith(VIRTUAL_TWIG_DEPENDENCY_PREFIX)) {
|
|
1093
|
+
return `\0${id}`;
|
|
1094
|
+
}
|
|
1095
|
+
|
|
1096
|
+
return null;
|
|
1097
|
+
},
|
|
1098
|
+
async load(id) {
|
|
1099
|
+
if (!id.startsWith(RESOLVED_VIRTUAL_TWIG_DEPENDENCY_PREFIX)) {
|
|
1100
|
+
return null;
|
|
1101
|
+
}
|
|
1102
|
+
|
|
1103
|
+
const dependencyPath = decodeVirtualTwigDependencyId(id);
|
|
1104
|
+
if (!dependencyPath) {
|
|
1105
|
+
return null;
|
|
1106
|
+
}
|
|
1107
|
+
|
|
1108
|
+
this.addWatchFile(dependencyPath);
|
|
1109
|
+
return generateTwigDependencyModule(dependencyPath, options);
|
|
1110
|
+
},
|
|
1111
|
+
async transform(...args) {
|
|
1046
1112
|
const [, id] = args;
|
|
1047
1113
|
if (!isTwigModuleRequest(id)) {
|
|
1048
1114
|
return null;
|
|
@@ -1051,10 +1117,11 @@ export function emulsifyTwigModulePlugin(options) {
|
|
|
1051
1117
|
const filePath = stripRequestQuery(id);
|
|
1052
1118
|
const sourceFilePath = resolve(filePath);
|
|
1053
1119
|
transformedTwigModules.add(sourceFilePath);
|
|
1054
|
-
/** @type {Map<string, ReturnType<typeof compileTwigTemplate
|
|
1120
|
+
/** @type {Map<string, Awaited<ReturnType<typeof compileTwigTemplate>>>} */
|
|
1055
1121
|
const compiledDependencyTemplates = new Map();
|
|
1056
1122
|
/** @type {Map<string, Set<string>>} */
|
|
1057
1123
|
const compiledDependencyReferences = new Map();
|
|
1124
|
+
const queuedDependencyTemplates = new Set();
|
|
1058
1125
|
clearDependencyImporter(sourceFilePath);
|
|
1059
1126
|
|
|
1060
1127
|
/**
|
|
@@ -1089,13 +1156,15 @@ export function emulsifyTwigModulePlugin(options) {
|
|
|
1089
1156
|
* @param {string[]} templateReferences - Raw references found in tokens.
|
|
1090
1157
|
* @param {string} fromFilePath - Absolute importer path.
|
|
1091
1158
|
* @param {typeof compileCache} cache - Shared compile cache.
|
|
1092
|
-
* @returns {void}
|
|
1159
|
+
* @returns {Promise<void>}
|
|
1093
1160
|
*/
|
|
1094
|
-
const compileDependencyTemplates = (
|
|
1161
|
+
const compileDependencyTemplates = async (
|
|
1095
1162
|
templateReferences,
|
|
1096
1163
|
fromFilePath,
|
|
1097
1164
|
cache,
|
|
1098
1165
|
) => {
|
|
1166
|
+
const dependencyRecords = [];
|
|
1167
|
+
|
|
1099
1168
|
for (const templatePath of templateReferences) {
|
|
1100
1169
|
const dependencyPath = resolveTwigTemplate(
|
|
1101
1170
|
templatePath,
|
|
@@ -1106,22 +1175,38 @@ export function emulsifyTwigModulePlugin(options) {
|
|
|
1106
1175
|
const absoluteDependencyPath = resolve(dependencyPath);
|
|
1107
1176
|
addCompiledDependencyReference(absoluteDependencyPath, templatePath);
|
|
1108
1177
|
if (absoluteDependencyPath === sourceFilePath) continue;
|
|
1178
|
+
if (
|
|
1179
|
+
compiledDependencyTemplates.has(absoluteDependencyPath) ||
|
|
1180
|
+
queuedDependencyTemplates.has(absoluteDependencyPath)
|
|
1181
|
+
) {
|
|
1182
|
+
continue;
|
|
1183
|
+
}
|
|
1109
1184
|
|
|
1110
|
-
|
|
1111
|
-
absoluteDependencyPath,
|
|
1112
|
-
);
|
|
1113
|
-
if (dependencyTemplate) continue;
|
|
1185
|
+
queuedDependencyTemplates.add(absoluteDependencyPath);
|
|
1114
1186
|
|
|
1115
1187
|
addDependencyImporter(absoluteDependencyPath, sourceFilePath);
|
|
1116
1188
|
this.addWatchFile(absoluteDependencyPath);
|
|
1117
1189
|
|
|
1118
|
-
|
|
1190
|
+
dependencyRecords.push({ absoluteDependencyPath });
|
|
1191
|
+
}
|
|
1192
|
+
|
|
1193
|
+
const compiledDependencyRecords = await Promise.all(
|
|
1194
|
+
dependencyRecords.map(async ({ absoluteDependencyPath }) => ({
|
|
1119
1195
|
absoluteDependencyPath,
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1196
|
+
compiled: await compileTwigTemplate(
|
|
1197
|
+
absoluteDependencyPath,
|
|
1198
|
+
options,
|
|
1199
|
+
cache,
|
|
1200
|
+
),
|
|
1201
|
+
})),
|
|
1202
|
+
);
|
|
1203
|
+
|
|
1204
|
+
for (const {
|
|
1205
|
+
absoluteDependencyPath,
|
|
1206
|
+
compiled,
|
|
1207
|
+
} of compiledDependencyRecords) {
|
|
1123
1208
|
compiledDependencyTemplates.set(absoluteDependencyPath, compiled);
|
|
1124
|
-
compileDependencyTemplates(
|
|
1209
|
+
await compileDependencyTemplates(
|
|
1125
1210
|
compiled.includes,
|
|
1126
1211
|
absoluteDependencyPath,
|
|
1127
1212
|
cache,
|
|
@@ -1133,51 +1218,56 @@ export function emulsifyTwigModulePlugin(options) {
|
|
|
1133
1218
|
* Emit raw Twig source registrations for static source() references.
|
|
1134
1219
|
*
|
|
1135
1220
|
* @param {string} fromFilePath - Absolute file that contains the reference.
|
|
1136
|
-
* @param {ReturnType<typeof compileTwigTemplate
|
|
1137
|
-
* @returns {string[]} Generated source map registration statements.
|
|
1221
|
+
* @param {Awaited<ReturnType<typeof compileTwigTemplate>>} compiledTemplate - Compiled template metadata.
|
|
1222
|
+
* @returns {Promise<string[]>} Generated source map registration statements.
|
|
1138
1223
|
*/
|
|
1139
|
-
const makeSourceTemplateRegistrations = (
|
|
1224
|
+
const makeSourceTemplateRegistrations = async (
|
|
1140
1225
|
fromFilePath,
|
|
1141
1226
|
compiledTemplate,
|
|
1142
|
-
) =>
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1227
|
+
) => {
|
|
1228
|
+
const registrations = await Promise.all(
|
|
1229
|
+
(compiledTemplate.sourceReferences || []).map(async (reference) => {
|
|
1230
|
+
if (
|
|
1231
|
+
reference.startsWith('@assets/') ||
|
|
1232
|
+
reference.startsWith('assets/')
|
|
1233
|
+
) {
|
|
1234
|
+
return [];
|
|
1235
|
+
}
|
|
1150
1236
|
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1237
|
+
const sourcePath = resolveTwigTemplate(
|
|
1238
|
+
reference,
|
|
1239
|
+
dirname(fromFilePath),
|
|
1240
|
+
options,
|
|
1241
|
+
);
|
|
1242
|
+
if (!sourcePath) return [];
|
|
1243
|
+
|
|
1244
|
+
const absoluteSourcePath = resolve(sourcePath);
|
|
1245
|
+
addDependencyImporter(absoluteSourcePath, sourceFilePath);
|
|
1246
|
+
this.addWatchFile(absoluteSourcePath);
|
|
1247
|
+
const sourceText = await readFile(absoluteSourcePath, 'utf8');
|
|
1248
|
+
|
|
1249
|
+
return unique([
|
|
1250
|
+
reference,
|
|
1251
|
+
templateIdForPath(absoluteSourcePath, options),
|
|
1252
|
+
]).map(
|
|
1253
|
+
(key) =>
|
|
1254
|
+
`__emulsifySourceTemplates.set(${JSON.stringify(
|
|
1255
|
+
key,
|
|
1256
|
+
)}, ${JSON.stringify(sourceText)});`,
|
|
1257
|
+
);
|
|
1258
|
+
}),
|
|
1259
|
+
);
|
|
1260
|
+
|
|
1261
|
+
return registrations.flat();
|
|
1262
|
+
};
|
|
1173
1263
|
|
|
1174
1264
|
try {
|
|
1175
|
-
const compiled = compileTwigTemplate(
|
|
1265
|
+
const compiled = await compileTwigTemplate(
|
|
1176
1266
|
sourceFilePath,
|
|
1177
1267
|
options,
|
|
1178
1268
|
compileCache,
|
|
1179
1269
|
);
|
|
1180
|
-
compileDependencyTemplates(
|
|
1270
|
+
await compileDependencyTemplates(
|
|
1181
1271
|
compiled.includes,
|
|
1182
1272
|
sourceFilePath,
|
|
1183
1273
|
compileCache,
|
|
@@ -1190,29 +1280,40 @@ export function emulsifyTwigModulePlugin(options) {
|
|
|
1190
1280
|
.map(([dependencyPath, compiledDependency], index) => ({
|
|
1191
1281
|
dependencyPath,
|
|
1192
1282
|
compiledDependency,
|
|
1193
|
-
|
|
1283
|
+
idVariableName: `__emulsifyDependencyTemplateId${index}`,
|
|
1284
|
+
paramsVariableName: `__emulsifyDependencyTemplateParams${index}`,
|
|
1285
|
+
templateVariableName: `__emulsifyDependency${index}`,
|
|
1286
|
+
virtualModuleId: encodeVirtualTwigDependencyId(dependencyPath),
|
|
1194
1287
|
}));
|
|
1288
|
+
const dependencyTemplateImports = dependencyTemplateRecords
|
|
1289
|
+
.map(
|
|
1290
|
+
({ idVariableName, paramsVariableName, virtualModuleId }) =>
|
|
1291
|
+
`import { templateId as ${idVariableName}, templateParams as ${paramsVariableName} } from ${JSON.stringify(
|
|
1292
|
+
virtualModuleId,
|
|
1293
|
+
)};`,
|
|
1294
|
+
)
|
|
1295
|
+
.join('\n');
|
|
1195
1296
|
const dependencyTemplateCode = dependencyTemplateRecords
|
|
1196
1297
|
.map(
|
|
1197
|
-
({
|
|
1198
|
-
const ${
|
|
1199
|
-
|
|
1200
|
-
|
|
1298
|
+
({ idVariableName, paramsVariableName, templateVariableName }) => `
|
|
1299
|
+
const ${templateVariableName} = ${makeTemplateInstantiationFromParamsCode(
|
|
1300
|
+
idVariableName,
|
|
1301
|
+
paramsVariableName,
|
|
1201
1302
|
)};
|
|
1202
|
-
${
|
|
1303
|
+
${templateVariableName}.method = 'emulsify';
|
|
1203
1304
|
`,
|
|
1204
1305
|
)
|
|
1205
1306
|
.join('\n');
|
|
1206
1307
|
const includeTemplateRegistrations = [
|
|
1207
1308
|
...dependencyTemplateRecords.flatMap(
|
|
1208
|
-
({ dependencyPath,
|
|
1309
|
+
({ dependencyPath, templateVariableName }) =>
|
|
1209
1310
|
Array.from(
|
|
1210
1311
|
compiledDependencyReferences.get(dependencyPath) || [],
|
|
1211
1312
|
).map(
|
|
1212
1313
|
(reference) =>
|
|
1213
1314
|
`__emulsifyIncludeTemplates.set(${JSON.stringify(
|
|
1214
1315
|
reference,
|
|
1215
|
-
)}, (context = {}) => ${
|
|
1316
|
+
)}, (context = {}) => ${templateVariableName}.render(context));`,
|
|
1216
1317
|
),
|
|
1217
1318
|
),
|
|
1218
1319
|
...Array.from(
|
|
@@ -1224,29 +1325,34 @@ export function emulsifyTwigModulePlugin(options) {
|
|
|
1224
1325
|
)}, (context = {}) => __emulsifyTemplate.render(context));`,
|
|
1225
1326
|
),
|
|
1226
1327
|
].join('\n');
|
|
1227
|
-
const sourceTemplateRegistrations =
|
|
1228
|
-
|
|
1229
|
-
(
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1328
|
+
const sourceTemplateRegistrations = (
|
|
1329
|
+
await Promise.all([
|
|
1330
|
+
...dependencyTemplateRecords.map(
|
|
1331
|
+
({ dependencyPath, compiledDependency }) =>
|
|
1332
|
+
makeSourceTemplateRegistrations(
|
|
1333
|
+
dependencyPath,
|
|
1334
|
+
compiledDependency,
|
|
1335
|
+
),
|
|
1336
|
+
),
|
|
1337
|
+
makeSourceTemplateRegistrations(sourceFilePath, compiled),
|
|
1338
|
+
])
|
|
1339
|
+
)
|
|
1340
|
+
.flat()
|
|
1341
|
+
.join('\n');
|
|
1237
1342
|
const renderErrorPrefix = JSON.stringify(
|
|
1238
1343
|
`An error occurred whilst rendering ${toPosixPath(filePath)}: `,
|
|
1239
1344
|
);
|
|
1240
1345
|
const moduleCode = `
|
|
1346
|
+
${dependencyTemplateImports}
|
|
1241
1347
|
import { factory } from 'twig';
|
|
1242
1348
|
import { registerTwigExtensions } from '@emulsify/core/extensions/twig';
|
|
1243
|
-
|
|
1349
|
+
import { installProjectTwigExtensions } from 'virtual:emulsify-twig-extension-installers';
|
|
1244
1350
|
import { createTwigIncludeFunction } from '@emulsify/core/storybook/twig/include-function';
|
|
1245
1351
|
import { createTwigSourceFunction } from '@emulsify/core/storybook/twig/source-function';
|
|
1246
1352
|
|
|
1247
1353
|
const Twig = factory();
|
|
1248
1354
|
registerTwigExtensions(Twig);
|
|
1249
|
-
|
|
1355
|
+
installProjectTwigExtensions(Twig);
|
|
1250
1356
|
Twig.extend((TwigCore) => {
|
|
1251
1357
|
TwigCore.Templates.registerLoader(
|
|
1252
1358
|
'emulsify',
|
|
@@ -1329,6 +1435,7 @@ export function emulsifyTwigModulePlugin(options) {
|
|
|
1329
1435
|
|
|
1330
1436
|
const fileExists = safeExists(filePath);
|
|
1331
1437
|
const knownFile = knownTwigFiles.has(filePath);
|
|
1438
|
+
const dependencyModuleId = resolvedVirtualTwigDependencyId(filePath);
|
|
1332
1439
|
const importers = dependencyImporters.get(filePath);
|
|
1333
1440
|
const projectRoot = options.projectDir || options.root;
|
|
1334
1441
|
const projectPathChanged =
|
|
@@ -1388,6 +1495,11 @@ export function emulsifyTwigModulePlugin(options) {
|
|
|
1388
1495
|
}
|
|
1389
1496
|
|
|
1390
1497
|
const modules = new Set(moduleGraph.getModulesByFile(filePath) || []);
|
|
1498
|
+
const dependencyModule = moduleGraph.getModuleById?.(dependencyModuleId);
|
|
1499
|
+
if (dependencyModule) {
|
|
1500
|
+
moduleGraph.invalidateModule?.(dependencyModule);
|
|
1501
|
+
modules.add(dependencyModule);
|
|
1502
|
+
}
|
|
1391
1503
|
for (const importer of affectedImporters) {
|
|
1392
1504
|
compileCache.delete(importer);
|
|
1393
1505
|
|