@navita/core 0.0.0 → 0.0.2
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/createRenderer.d.ts +21 -11
- package/createRenderer.js +45 -315
- package/createRenderer.mjs +45 -298
- package/evaluateAndProcess.d.ts +32 -10
- package/evaluateAndProcess.js +254 -49
- package/evaluateAndProcess.mjs +259 -37
- package/index.d.ts +1 -22
- package/index.js +0 -53
- package/index.mjs +0 -47
- package/package.json +18 -11
package/evaluateAndProcess.js
CHANGED
|
@@ -1,66 +1,271 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var path = require('node:path');
|
|
4
|
+
var swc = require('@navita/swc');
|
|
4
5
|
var vm = require('node:vm');
|
|
6
|
+
var fs = require('node:fs');
|
|
7
|
+
var enhancedResolve = require('enhanced-resolve');
|
|
8
|
+
var engine = require('@navita/engine');
|
|
9
|
+
var adapter = require('@navita/adapter');
|
|
5
10
|
|
|
6
|
-
function
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
12
|
-
Object.defineProperty(n, k, d.get ? d : {
|
|
13
|
-
enumerable: true,
|
|
14
|
-
get: function () { return e[k]; }
|
|
15
|
-
});
|
|
16
|
-
}
|
|
11
|
+
function createMagicProxy() {
|
|
12
|
+
// Todo: at some point, the magic proxy should notify the user
|
|
13
|
+
// that they are using a browser API in a node environment
|
|
14
|
+
return new Proxy({}, {
|
|
15
|
+
get: ()=>createMagicProxy()
|
|
17
16
|
});
|
|
18
|
-
}
|
|
19
|
-
n.default = e;
|
|
20
|
-
return Object.freeze(n);
|
|
21
17
|
}
|
|
22
18
|
|
|
23
|
-
|
|
19
|
+
const context = vm.createContext({
|
|
20
|
+
global
|
|
21
|
+
});
|
|
22
|
+
const vmGlobalsRecord = new vm.Script(`
|
|
23
|
+
Object
|
|
24
|
+
.getOwnPropertyNames(globalThis)
|
|
25
|
+
.reduce((acc, name) => ({
|
|
26
|
+
...acc,
|
|
27
|
+
[name]: globalThis[name],
|
|
28
|
+
}), {});
|
|
29
|
+
`).runInContext(context);
|
|
30
|
+
const vmGlobalsNonEnumerableRecord = {};
|
|
31
|
+
Object.getOwnPropertyNames(global).forEach((name)=>{
|
|
32
|
+
// The second condition here is to prevent jest's Symbol polyfill from being added.
|
|
33
|
+
// https://github.com/jestjs/jest/blob/25a8785584c9d54a05887001ee7f498d489a5441/packages/jest-util/src/installCommonGlobals.ts#L49
|
|
34
|
+
if (!vmGlobalsRecord[name] && global[name] !== globalThis.Symbol) {
|
|
35
|
+
vmGlobalsNonEnumerableRecord[name] = global[name];
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
function createCompiledFunction(source, define) {
|
|
39
|
+
// This looks a bit weird, but it's much quicker to do it this way than to
|
|
40
|
+
// run vm.runInContext. There's a bit more information in this issue:
|
|
41
|
+
// https://github.com/nodejs/node/issues/31658
|
|
42
|
+
const sandbox = {
|
|
43
|
+
define,
|
|
44
|
+
...vmGlobalsRecord,
|
|
45
|
+
...vmGlobalsNonEnumerableRecord,
|
|
46
|
+
window: createMagicProxy(),
|
|
47
|
+
document: createMagicProxy(),
|
|
48
|
+
navigator: createMagicProxy(),
|
|
49
|
+
console
|
|
50
|
+
};
|
|
51
|
+
const params = Object.keys(sandbox);
|
|
52
|
+
const implementations = Object.values(sandbox);
|
|
53
|
+
const compiledFunction = vm.compileFunction(source, params, {
|
|
54
|
+
parsingContext: context
|
|
55
|
+
});
|
|
56
|
+
return ()=>compiledFunction(...implementations);
|
|
57
|
+
}
|
|
24
58
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
59
|
+
const { ResolverFactory , CachedInputFileSystem } = enhancedResolve;
|
|
60
|
+
const resolver = ResolverFactory.createResolver({
|
|
61
|
+
fileSystem: new CachedInputFileSystem(fs, 4000),
|
|
62
|
+
extensions: [
|
|
63
|
+
".js",
|
|
64
|
+
".cjs",
|
|
65
|
+
".mjs"
|
|
66
|
+
],
|
|
67
|
+
conditionNames: [
|
|
68
|
+
"import",
|
|
69
|
+
"require"
|
|
70
|
+
]
|
|
71
|
+
});
|
|
72
|
+
const requireResolveLike = (request, paths = [])=>Promise.any(paths.map((path)=>new Promise((resolve, reject)=>{
|
|
73
|
+
resolver.resolve({}, path, request, {}, (err, result)=>{
|
|
74
|
+
if (err || !result) {
|
|
75
|
+
return reject(err);
|
|
76
|
+
}
|
|
77
|
+
resolve(result);
|
|
78
|
+
});
|
|
79
|
+
})));
|
|
80
|
+
const importWithRequireResolution = async (request, startPath = __dirname)=>{
|
|
81
|
+
return import(await requireResolveLike(request, [
|
|
82
|
+
startPath
|
|
83
|
+
]) || request);
|
|
84
|
+
};
|
|
85
|
+
function createDefineFunction({ filePath , resolver , isExternal , resolverCache , nodeModuleCache , setAdapter }, resolveDependency) {
|
|
86
|
+
const filepathDirectory = path.dirname(filePath);
|
|
87
|
+
return async function define(dependencies, factoryFn) {
|
|
88
|
+
const exports = {};
|
|
89
|
+
const dependencyMap = {
|
|
90
|
+
require: importWithRequireResolution,
|
|
91
|
+
exports
|
|
92
|
+
};
|
|
93
|
+
const resolvedDependencies = await Promise.all(dependencies.filter((dependency)=>!(dependency in dependencyMap)).map((dependency)=>{
|
|
94
|
+
if (!resolverCache[filepathDirectory]) {
|
|
95
|
+
resolverCache[filepathDirectory] = {};
|
|
96
|
+
}
|
|
97
|
+
if (resolverCache[filepathDirectory][dependency]) {
|
|
98
|
+
return resolverCache[filepathDirectory][dependency];
|
|
99
|
+
}
|
|
100
|
+
const resolved = resolver(filePath, dependency).catch(()=>undefined).then((resolvedDependency)=>{
|
|
101
|
+
if (!resolvedDependency) {
|
|
102
|
+
return requireResolveLike(dependency, [
|
|
103
|
+
filepathDirectory,
|
|
37
104
|
__dirname
|
|
38
|
-
]
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
105
|
+
]).catch(()=>{
|
|
106
|
+
throw new Error(`Failed to resolve dependency "${dependency}" in ${filePath}`);
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
return resolvedDependency;
|
|
110
|
+
});
|
|
111
|
+
resolverCache[filepathDirectory][dependency] = resolved;
|
|
112
|
+
return resolved;
|
|
113
|
+
})).catch((error)=>{
|
|
114
|
+
throw error;
|
|
115
|
+
});
|
|
116
|
+
for (const dependency of resolvedDependencies){
|
|
117
|
+
if (nodeModuleCache[dependency]) {
|
|
118
|
+
dependencyMap[dependency] = nodeModuleCache[dependency];
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Ignore everything that's not:
|
|
123
|
+
* .js, .ts, .jsx, .tsx, .mts, .mjs, .cjs, .cts
|
|
124
|
+
*/ if (/\.(?![mc]?[tj]sx?$)[^.]+$/.test(dependency)) {
|
|
125
|
+
dependencyMap[dependency] = {};
|
|
126
|
+
continue;
|
|
42
127
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
128
|
+
if (isExternal(dependency)) {
|
|
129
|
+
const module = importWithRequireResolution(dependency, filepathDirectory);
|
|
130
|
+
if (!nodeModuleCache[dependency]) {
|
|
131
|
+
nodeModuleCache[dependency] = module;
|
|
132
|
+
}
|
|
133
|
+
dependencyMap[dependency] = nodeModuleCache[dependency];
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
dependencyMap[dependency] = resolveDependency(dependency);
|
|
137
|
+
}
|
|
138
|
+
const dependencyValues = await Promise.all(Object.values(dependencyMap));
|
|
139
|
+
// The adapter needs to be set before factoryFn is called.
|
|
140
|
+
setAdapter();
|
|
141
|
+
factoryFn(...dependencyValues);
|
|
142
|
+
return {
|
|
143
|
+
dependencies: resolvedDependencies.filter((x)=>!isExternal(x)),
|
|
144
|
+
exports
|
|
145
|
+
};
|
|
47
146
|
};
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function formatResults(results = []) {
|
|
150
|
+
const result = results.map((item)=>{
|
|
151
|
+
if (item instanceof engine.Static) {
|
|
152
|
+
return '';
|
|
153
|
+
}
|
|
154
|
+
return JSON.stringify(item);
|
|
52
155
|
});
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
|
|
156
|
+
return `const $$evaluatedValues = [${result.join(',')}];`;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
function setAdapter({ engine: engine$1 , collectResults , }) {
|
|
160
|
+
adapter.setAdapter({
|
|
161
|
+
generateIdentifier: (value)=>engine$1.generateIdentifier(value),
|
|
162
|
+
addStaticCss: (selector, css)=>engine$1.addStatic(selector, css),
|
|
163
|
+
addCss: (css)=>engine$1.addStyle(css),
|
|
164
|
+
addKeyframe: (keyframe)=>engine$1.addKeyframes(keyframe),
|
|
165
|
+
addFontFace: (fontFace)=>{
|
|
166
|
+
const hasFontFamily = (Array.isArray(fontFace) ? fontFace : [
|
|
167
|
+
fontFace
|
|
168
|
+
]).some((fontFace)=>'fontFamily' in fontFace);
|
|
169
|
+
if (hasFontFamily) {
|
|
170
|
+
throw new Error('This function creates and returns a font-family name, so the "fontFamily" property should not be provided.');
|
|
171
|
+
}
|
|
172
|
+
return engine$1.addFontFace(fontFace);
|
|
173
|
+
},
|
|
174
|
+
collectResult ({ index , filePath , identifier , result: resultFactory , line , column , }) {
|
|
175
|
+
if (index === 0) {
|
|
176
|
+
if (collectResults) {
|
|
177
|
+
collectResults[filePath] = [];
|
|
178
|
+
}
|
|
179
|
+
engine$1.clearUsedIds(filePath);
|
|
180
|
+
}
|
|
181
|
+
engine$1.setFilePath(filePath);
|
|
182
|
+
let result = resultFactory();
|
|
183
|
+
engine$1.setFilePath(undefined);
|
|
184
|
+
if (result instanceof engine.ClassList) {
|
|
185
|
+
const extraClass = engine$1.addSourceMapReference({
|
|
186
|
+
index,
|
|
187
|
+
identifier,
|
|
188
|
+
classList: result,
|
|
189
|
+
filePath,
|
|
190
|
+
line,
|
|
191
|
+
column
|
|
192
|
+
});
|
|
193
|
+
if (extraClass) {
|
|
194
|
+
result = new engine.ClassList([
|
|
195
|
+
result.toString(),
|
|
196
|
+
extraClass
|
|
197
|
+
].join(' '));
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
if (collectResults) {
|
|
201
|
+
collectResults[filePath][index] = result;
|
|
202
|
+
}
|
|
203
|
+
return result;
|
|
204
|
+
}
|
|
56
205
|
});
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
const rootDir = path.resolve(__dirname, "../../");
|
|
209
|
+
const isExternal = (dependency)=>dependency.startsWith(rootDir) || dependency.includes('node_modules');
|
|
210
|
+
const defaultNodeModuleCache = {};
|
|
211
|
+
const defaultResolverCache = {};
|
|
212
|
+
const defaultModuleCache = new Map();
|
|
213
|
+
const collectedResults = {};
|
|
214
|
+
async function evaluateAndProcess({ type , filePath , source , engine , resolver , readFile , importMap , nodeModuleCache =defaultNodeModuleCache , resolverCache =defaultResolverCache , moduleCache =defaultModuleCache }) {
|
|
215
|
+
const cacheKey = `${filePath}:${type}`;
|
|
216
|
+
const compiledFn = await (async ()=>{
|
|
217
|
+
if (moduleCache.has(cacheKey)) {
|
|
218
|
+
const cache = moduleCache.get(cacheKey);
|
|
219
|
+
if (cache.source === source) {
|
|
220
|
+
return cache.compiledFn;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
const newSource = await swc.extraction(source, {
|
|
224
|
+
filename: filePath,
|
|
225
|
+
entryPoint: type === 'entryPoint',
|
|
226
|
+
importMap
|
|
227
|
+
});
|
|
228
|
+
const define = createDefineFunction({
|
|
229
|
+
filePath,
|
|
230
|
+
resolver,
|
|
231
|
+
isExternal,
|
|
232
|
+
resolverCache,
|
|
233
|
+
nodeModuleCache,
|
|
234
|
+
setAdapter: ()=>setAdapter({
|
|
235
|
+
engine,
|
|
236
|
+
collectResults: collectedResults
|
|
237
|
+
})
|
|
238
|
+
}, (dependency)=>readFile(dependency).then((source)=>evaluateAndProcess({
|
|
239
|
+
type: 'dependency',
|
|
240
|
+
source: source.toString(),
|
|
241
|
+
filePath: dependency,
|
|
242
|
+
engine,
|
|
243
|
+
resolver,
|
|
244
|
+
readFile,
|
|
245
|
+
importMap,
|
|
246
|
+
nodeModuleCache,
|
|
247
|
+
resolverCache,
|
|
248
|
+
moduleCache
|
|
249
|
+
})).then(({ result })=>result));
|
|
250
|
+
const compiledFn = createCompiledFunction(`return ${newSource}`, define);
|
|
251
|
+
moduleCache.set(cacheKey, {
|
|
252
|
+
source,
|
|
253
|
+
compiledFn
|
|
254
|
+
});
|
|
255
|
+
return compiledFn;
|
|
256
|
+
})();
|
|
257
|
+
return compiledFn().then(({ dependencies , exports })=>{
|
|
258
|
+
if (type === 'entryPoint') {
|
|
259
|
+
return {
|
|
260
|
+
result: formatResults(collectedResults[filePath]),
|
|
261
|
+
dependencies
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
return {
|
|
265
|
+
result: exports,
|
|
266
|
+
dependencies
|
|
267
|
+
};
|
|
61
268
|
});
|
|
62
|
-
script.runInContext(vm__namespace.createContext(context));
|
|
63
|
-
renderer.setFilePath(undefined);
|
|
64
269
|
}
|
|
65
270
|
|
|
66
271
|
exports.evaluateAndProcess = evaluateAndProcess;
|
package/evaluateAndProcess.mjs
CHANGED
|
@@ -2,50 +2,272 @@ import { fileURLToPath as fileURLToPath$1 } from 'url';
|
|
|
2
2
|
const __filename = fileURLToPath$1(import.meta.url);
|
|
3
3
|
import { dirname as dirname$1 } from 'path';
|
|
4
4
|
const __dirname = dirname$1(__filename);
|
|
5
|
-
import
|
|
6
|
-
|
|
7
|
-
import
|
|
8
|
-
import
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import { extraction } from '@navita/swc';
|
|
7
|
+
import vm from 'node:vm';
|
|
8
|
+
import fs from 'node:fs';
|
|
9
|
+
import enhancedResolve from 'enhanced-resolve';
|
|
10
|
+
import { Static, ClassList } from '@navita/engine';
|
|
11
|
+
import { setAdapter as setAdapter$1 } from '@navita/adapter';
|
|
9
12
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
13
|
+
function createMagicProxy() {
|
|
14
|
+
// Todo: at some point, the magic proxy should notify the user
|
|
15
|
+
// that they are using a browser API in a node environment
|
|
16
|
+
return new Proxy({}, {
|
|
17
|
+
get: ()=>createMagicProxy()
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const context = vm.createContext({
|
|
22
|
+
global
|
|
23
|
+
});
|
|
24
|
+
const vmGlobalsRecord = new vm.Script(`
|
|
25
|
+
Object
|
|
26
|
+
.getOwnPropertyNames(globalThis)
|
|
27
|
+
.reduce((acc, name) => ({
|
|
28
|
+
...acc,
|
|
29
|
+
[name]: globalThis[name],
|
|
30
|
+
}), {});
|
|
31
|
+
`).runInContext(context);
|
|
32
|
+
const vmGlobalsNonEnumerableRecord = {};
|
|
33
|
+
Object.getOwnPropertyNames(global).forEach((name)=>{
|
|
34
|
+
// The second condition here is to prevent jest's Symbol polyfill from being added.
|
|
35
|
+
// https://github.com/jestjs/jest/blob/25a8785584c9d54a05887001ee7f498d489a5441/packages/jest-util/src/installCommonGlobals.ts#L49
|
|
36
|
+
if (!vmGlobalsRecord[name] && global[name] !== globalThis.Symbol) {
|
|
37
|
+
vmGlobalsNonEnumerableRecord[name] = global[name];
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
function createCompiledFunction(source, define) {
|
|
41
|
+
// This looks a bit weird, but it's much quicker to do it this way than to
|
|
42
|
+
// run vm.runInContext. There's a bit more information in this issue:
|
|
43
|
+
// https://github.com/nodejs/node/issues/31658
|
|
44
|
+
const sandbox = {
|
|
45
|
+
define,
|
|
46
|
+
...vmGlobalsRecord,
|
|
47
|
+
...vmGlobalsNonEnumerableRecord,
|
|
48
|
+
window: createMagicProxy(),
|
|
49
|
+
document: createMagicProxy(),
|
|
50
|
+
navigator: createMagicProxy(),
|
|
51
|
+
console
|
|
52
|
+
};
|
|
53
|
+
const params = Object.keys(sandbox);
|
|
54
|
+
const implementations = Object.values(sandbox);
|
|
55
|
+
const compiledFunction = vm.compileFunction(source, params, {
|
|
56
|
+
parsingContext: context
|
|
57
|
+
});
|
|
58
|
+
return ()=>compiledFunction(...implementations);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const { ResolverFactory , CachedInputFileSystem } = enhancedResolve;
|
|
62
|
+
const resolver = ResolverFactory.createResolver({
|
|
63
|
+
fileSystem: new CachedInputFileSystem(fs, 4000),
|
|
64
|
+
extensions: [
|
|
65
|
+
".js",
|
|
66
|
+
".cjs",
|
|
67
|
+
".mjs"
|
|
68
|
+
],
|
|
69
|
+
conditionNames: [
|
|
70
|
+
"import",
|
|
71
|
+
"require"
|
|
72
|
+
]
|
|
73
|
+
});
|
|
74
|
+
const requireResolveLike = (request, paths = [])=>Promise.any(paths.map((path)=>new Promise((resolve, reject)=>{
|
|
75
|
+
resolver.resolve({}, path, request, {}, (err, result)=>{
|
|
76
|
+
if (err || !result) {
|
|
77
|
+
return reject(err);
|
|
78
|
+
}
|
|
79
|
+
resolve(result);
|
|
80
|
+
});
|
|
81
|
+
})));
|
|
82
|
+
const importWithRequireResolution = async (request, startPath = __dirname)=>{
|
|
83
|
+
return import(await requireResolveLike(request, [
|
|
84
|
+
startPath
|
|
85
|
+
]) || request);
|
|
86
|
+
};
|
|
87
|
+
function createDefineFunction({ filePath , resolver , isExternal , resolverCache , nodeModuleCache , setAdapter }, resolveDependency) {
|
|
88
|
+
const filepathDirectory = path.dirname(filePath);
|
|
89
|
+
return async function define(dependencies, factoryFn) {
|
|
90
|
+
const exports = {};
|
|
91
|
+
const dependencyMap = {
|
|
92
|
+
require: importWithRequireResolution,
|
|
93
|
+
exports
|
|
94
|
+
};
|
|
95
|
+
const resolvedDependencies = await Promise.all(dependencies.filter((dependency)=>!(dependency in dependencyMap)).map((dependency)=>{
|
|
96
|
+
if (!resolverCache[filepathDirectory]) {
|
|
97
|
+
resolverCache[filepathDirectory] = {};
|
|
98
|
+
}
|
|
99
|
+
if (resolverCache[filepathDirectory][dependency]) {
|
|
100
|
+
return resolverCache[filepathDirectory][dependency];
|
|
101
|
+
}
|
|
102
|
+
const resolved = resolver(filePath, dependency).catch(()=>undefined).then((resolvedDependency)=>{
|
|
103
|
+
if (!resolvedDependency) {
|
|
104
|
+
return requireResolveLike(dependency, [
|
|
105
|
+
filepathDirectory,
|
|
22
106
|
__dirname
|
|
23
|
-
]
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
107
|
+
]).catch(()=>{
|
|
108
|
+
throw new Error(`Failed to resolve dependency "${dependency}" in ${filePath}`);
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
return resolvedDependency;
|
|
112
|
+
});
|
|
113
|
+
resolverCache[filepathDirectory][dependency] = resolved;
|
|
114
|
+
return resolved;
|
|
115
|
+
})).catch((error)=>{
|
|
116
|
+
throw error;
|
|
117
|
+
});
|
|
118
|
+
for (const dependency of resolvedDependencies){
|
|
119
|
+
if (nodeModuleCache[dependency]) {
|
|
120
|
+
dependencyMap[dependency] = nodeModuleCache[dependency];
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Ignore everything that's not:
|
|
125
|
+
* .js, .ts, .jsx, .tsx, .mts, .mjs, .cjs, .cts
|
|
126
|
+
*/ if (/\.(?![mc]?[tj]sx?$)[^.]+$/.test(dependency)) {
|
|
127
|
+
dependencyMap[dependency] = {};
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
if (isExternal(dependency)) {
|
|
131
|
+
const module = importWithRequireResolution(dependency, filepathDirectory);
|
|
132
|
+
if (!nodeModuleCache[dependency]) {
|
|
133
|
+
nodeModuleCache[dependency] = module;
|
|
134
|
+
}
|
|
135
|
+
dependencyMap[dependency] = nodeModuleCache[dependency];
|
|
136
|
+
continue;
|
|
27
137
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
138
|
+
dependencyMap[dependency] = resolveDependency(dependency);
|
|
139
|
+
}
|
|
140
|
+
const dependencyValues = await Promise.all(Object.values(dependencyMap));
|
|
141
|
+
// The adapter needs to be set before factoryFn is called.
|
|
142
|
+
setAdapter();
|
|
143
|
+
factoryFn(...dependencyValues);
|
|
144
|
+
return {
|
|
145
|
+
dependencies: resolvedDependencies.filter((x)=>!isExternal(x)),
|
|
146
|
+
exports
|
|
147
|
+
};
|
|
32
148
|
};
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function formatResults(results = []) {
|
|
152
|
+
const result = results.map((item)=>{
|
|
153
|
+
if (item instanceof Static) {
|
|
154
|
+
return '';
|
|
155
|
+
}
|
|
156
|
+
return JSON.stringify(item);
|
|
37
157
|
});
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
158
|
+
return `const $$evaluatedValues = [${result.join(',')}];`;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function setAdapter({ engine , collectResults , }) {
|
|
162
|
+
setAdapter$1({
|
|
163
|
+
generateIdentifier: (value)=>engine.generateIdentifier(value),
|
|
164
|
+
addStaticCss: (selector, css)=>engine.addStatic(selector, css),
|
|
165
|
+
addCss: (css)=>engine.addStyle(css),
|
|
166
|
+
addKeyframe: (keyframe)=>engine.addKeyframes(keyframe),
|
|
167
|
+
addFontFace: (fontFace)=>{
|
|
168
|
+
const hasFontFamily = (Array.isArray(fontFace) ? fontFace : [
|
|
169
|
+
fontFace
|
|
170
|
+
]).some((fontFace)=>'fontFamily' in fontFace);
|
|
171
|
+
if (hasFontFamily) {
|
|
172
|
+
throw new Error('This function creates and returns a font-family name, so the "fontFamily" property should not be provided.');
|
|
173
|
+
}
|
|
174
|
+
return engine.addFontFace(fontFace);
|
|
175
|
+
},
|
|
176
|
+
collectResult ({ index , filePath , identifier , result: resultFactory , line , column , }) {
|
|
177
|
+
if (index === 0) {
|
|
178
|
+
if (collectResults) {
|
|
179
|
+
collectResults[filePath] = [];
|
|
180
|
+
}
|
|
181
|
+
engine.clearUsedIds(filePath);
|
|
182
|
+
}
|
|
183
|
+
engine.setFilePath(filePath);
|
|
184
|
+
let result = resultFactory();
|
|
185
|
+
engine.setFilePath(undefined);
|
|
186
|
+
if (result instanceof ClassList) {
|
|
187
|
+
const extraClass = engine.addSourceMapReference({
|
|
188
|
+
index,
|
|
189
|
+
identifier,
|
|
190
|
+
classList: result,
|
|
191
|
+
filePath,
|
|
192
|
+
line,
|
|
193
|
+
column
|
|
194
|
+
});
|
|
195
|
+
if (extraClass) {
|
|
196
|
+
result = new ClassList([
|
|
197
|
+
result.toString(),
|
|
198
|
+
extraClass
|
|
199
|
+
].join(' '));
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
if (collectResults) {
|
|
203
|
+
collectResults[filePath][index] = result;
|
|
204
|
+
}
|
|
205
|
+
return result;
|
|
206
|
+
}
|
|
41
207
|
});
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
const rootDir = path.resolve(__dirname, "../../");
|
|
211
|
+
const isExternal = (dependency)=>dependency.startsWith(rootDir) || dependency.includes('node_modules');
|
|
212
|
+
const defaultNodeModuleCache = {};
|
|
213
|
+
const defaultResolverCache = {};
|
|
214
|
+
const defaultModuleCache = new Map();
|
|
215
|
+
const collectedResults = {};
|
|
216
|
+
async function evaluateAndProcess({ type , filePath , source , engine , resolver , readFile , importMap , nodeModuleCache =defaultNodeModuleCache , resolverCache =defaultResolverCache , moduleCache =defaultModuleCache }) {
|
|
217
|
+
const cacheKey = `${filePath}:${type}`;
|
|
218
|
+
const compiledFn = await (async ()=>{
|
|
219
|
+
if (moduleCache.has(cacheKey)) {
|
|
220
|
+
const cache = moduleCache.get(cacheKey);
|
|
221
|
+
if (cache.source === source) {
|
|
222
|
+
return cache.compiledFn;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
const newSource = await extraction(source, {
|
|
226
|
+
filename: filePath,
|
|
227
|
+
entryPoint: type === 'entryPoint',
|
|
228
|
+
importMap
|
|
229
|
+
});
|
|
230
|
+
const define = createDefineFunction({
|
|
231
|
+
filePath,
|
|
232
|
+
resolver,
|
|
233
|
+
isExternal,
|
|
234
|
+
resolverCache,
|
|
235
|
+
nodeModuleCache,
|
|
236
|
+
setAdapter: ()=>setAdapter({
|
|
237
|
+
engine,
|
|
238
|
+
collectResults: collectedResults
|
|
239
|
+
})
|
|
240
|
+
}, (dependency)=>readFile(dependency).then((source)=>evaluateAndProcess({
|
|
241
|
+
type: 'dependency',
|
|
242
|
+
source: source.toString(),
|
|
243
|
+
filePath: dependency,
|
|
244
|
+
engine,
|
|
245
|
+
resolver,
|
|
246
|
+
readFile,
|
|
247
|
+
importMap,
|
|
248
|
+
nodeModuleCache,
|
|
249
|
+
resolverCache,
|
|
250
|
+
moduleCache
|
|
251
|
+
})).then(({ result })=>result));
|
|
252
|
+
const compiledFn = createCompiledFunction(`return ${newSource}`, define);
|
|
253
|
+
moduleCache.set(cacheKey, {
|
|
254
|
+
source,
|
|
255
|
+
compiledFn
|
|
256
|
+
});
|
|
257
|
+
return compiledFn;
|
|
258
|
+
})();
|
|
259
|
+
return compiledFn().then(({ dependencies , exports })=>{
|
|
260
|
+
if (type === 'entryPoint') {
|
|
261
|
+
return {
|
|
262
|
+
result: formatResults(collectedResults[filePath]),
|
|
263
|
+
dependencies
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
return {
|
|
267
|
+
result: exports,
|
|
268
|
+
dependencies
|
|
269
|
+
};
|
|
46
270
|
});
|
|
47
|
-
script.runInContext(vm.createContext(context));
|
|
48
|
-
renderer.setFilePath(undefined);
|
|
49
271
|
}
|
|
50
272
|
|
|
51
273
|
export { evaluateAndProcess };
|
package/index.d.ts
CHANGED
|
@@ -1,23 +1,2 @@
|
|
|
1
|
-
import { StyleRule, GlobalStyleRule, CSSKeyframes } from '@navita/types';
|
|
2
|
-
import { Renderer } from './createRenderer.js';
|
|
3
|
-
import 'fela';
|
|
4
1
|
|
|
5
|
-
|
|
6
|
-
generateIdentifier: typeof generateIdentifier;
|
|
7
|
-
setCss: typeof setCss;
|
|
8
|
-
setStaticCss: typeof setStaticCss;
|
|
9
|
-
setKeyFrame: typeof setKeyFrame;
|
|
10
|
-
collectResult?: typeof collectResult;
|
|
11
|
-
};
|
|
12
|
-
declare const setAdapter: (renderer: Renderer) => void;
|
|
13
|
-
declare function generateIdentifier(value: unknown): string;
|
|
14
|
-
declare function setCss(css: StyleRule): string;
|
|
15
|
-
declare function setStaticCss(selector: string, css: GlobalStyleRule): void;
|
|
16
|
-
declare function setKeyFrame(keyframe: CSSKeyframes): string;
|
|
17
|
-
declare function collectResult<T>(input: {
|
|
18
|
-
filePath: string;
|
|
19
|
-
index: number;
|
|
20
|
-
result: () => T;
|
|
21
|
-
}): T;
|
|
22
|
-
|
|
23
|
-
export { Adapter, collectResult, generateIdentifier, setAdapter, setCss, setKeyFrame, setStaticCss };
|
|
2
|
+
export { }
|