@lowdefy/build 4.7.0 → 4.7.1
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/build/buildImports/buildIconImports.js +1 -31
- package/dist/build/buildImports/iconPackages.js +49 -0
- package/dist/build/buildRefs/makeRefDefinition.js +4 -2
- package/dist/build/buildRefs/walker.js +21 -13
- package/dist/build/jit/buildPageJit.js +29 -1
- package/dist/build/jit/detectMissingIcons.js +36 -0
- package/dist/build/jit/extractIconData.js +54 -0
- package/dist/build/jit/shallowBuild.js +4 -0
- package/dist/build/jit/updateIconImportsJit.js +45 -0
- package/dist/build/jit/writeIconsDynamic.js +20 -0
- package/dist/defaultTypesMap.js +347 -338
- package/package.json +42 -42
|
@@ -12,36 +12,7 @@
|
|
|
12
12
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
13
|
See the License for the specific language governing permissions and
|
|
14
14
|
limitations under the License.
|
|
15
|
-
*/
|
|
16
|
-
'react-icons/ai': /"(Ai[A-Z0-9]\w*)"/gm,
|
|
17
|
-
'react-icons/bi': /"(Bi[A-Z0-9]\w*)"/gm,
|
|
18
|
-
'react-icons/bs': /"(Bs[A-Z0-9]\w*)"/gm,
|
|
19
|
-
'react-icons/cg': /"(Cg[A-Z0-9]\w*)"/gm,
|
|
20
|
-
'react-icons/ci': /"(Ci[A-Z0-9]\w*)"/gm,
|
|
21
|
-
'react-icons/di': /"(Di[A-Z0-9]\w*)"/gm,
|
|
22
|
-
'react-icons/fa': /"(Fa[A-Z0-9]\w*)"/gm,
|
|
23
|
-
'react-icons/fc': /"(Fc[A-Z0-9]\w*)"/gm,
|
|
24
|
-
'react-icons/fi': /"(Fi[A-Z0-9]\w*)"/gm,
|
|
25
|
-
'react-icons/gi': /"(Gi[A-Z0-9]\w*)"/gm,
|
|
26
|
-
'react-icons/go': /"(Go[A-Z0-9]\w*)"/gm,
|
|
27
|
-
'react-icons/gr': /"(Gr[A-Z0-9]\w*)"/gm,
|
|
28
|
-
'react-icons/hi': /"(Hi[A-Z0-9]\w*)"/gm,
|
|
29
|
-
'react-icons/im': /"(Im[A-Z0-9]\w*)"/gm,
|
|
30
|
-
'react-icons/io': /"(IoIos[A-Z0-9]\w*)"/gm,
|
|
31
|
-
'react-icons/io5': /"(Io[A-Z0-9]\w*)"/gm,
|
|
32
|
-
'react-icons/lu': /"(Lu[A-Z0-9]\w*)"/gm,
|
|
33
|
-
'react-icons/md': /"(Md[A-Z0-9]\w*)"/gm,
|
|
34
|
-
'react-icons/pi': /"(Pi[A-Z0-9]\w*)"/gm,
|
|
35
|
-
'react-icons/ri': /"(Ri[A-Z0-9]\w*)"/gm,
|
|
36
|
-
'react-icons/rx': /"(Rx[A-Z0-9]\w*)"/gm,
|
|
37
|
-
'react-icons/si': /"(Si[A-Z0-9]\w*)"/gm,
|
|
38
|
-
'react-icons/sl': /"(Sl[A-Z0-9]\w*)"/gm,
|
|
39
|
-
'react-icons/tb': /"(Tb[A-Z0-9]\w*)"/gm,
|
|
40
|
-
'react-icons/tfi': /"(Tfi[A-Z0-9]\w*)"/gm,
|
|
41
|
-
'react-icons/ti': /"(Ti[A-Z0-9]\w*)"/gm,
|
|
42
|
-
'react-icons/vsc': /"(Vsc[A-Z0-9]\w*)"/gm,
|
|
43
|
-
'react-icons/wi': /"(Wi[A-Z0-9]\w*)"/gm
|
|
44
|
-
};
|
|
15
|
+
*/ import iconPackages from './iconPackages.js';
|
|
45
16
|
function getConfigIcons({ components, icons, regex }) {
|
|
46
17
|
[
|
|
47
18
|
...JSON.stringify(components.global || {}).matchAll(regex)
|
|
@@ -65,7 +36,6 @@ function getBlockDefaultIcons({ blocks, context, icons, regex }) {
|
|
|
65
36
|
function buildIconImports({ blocks, components, context, defaults = {} }) {
|
|
66
37
|
const iconImports = [];
|
|
67
38
|
Object.entries(iconPackages).forEach(([iconPackage, regex])=>{
|
|
68
|
-
defaults;
|
|
69
39
|
const icons = new Set(defaults[iconPackage]);
|
|
70
40
|
getConfigIcons({
|
|
71
41
|
components,
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2020-2026 Lowdefy, Inc
|
|
3
|
+
|
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
you may not use this file except in compliance with the License.
|
|
6
|
+
You may obtain a copy of the License at
|
|
7
|
+
|
|
8
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
|
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
See the License for the specific language governing permissions and
|
|
14
|
+
limitations under the License.
|
|
15
|
+
*/ // Icon name regex patterns keyed by react-icons package.
|
|
16
|
+
// Note: 'react-icons/io' and 'react-icons/io5' overlap — IoIos* icons match
|
|
17
|
+
// both packages. This is intentional and matches the existing buildIconImports
|
|
18
|
+
// behavior where both packages receive the IoIos* icons.
|
|
19
|
+
const iconPackages = {
|
|
20
|
+
'react-icons/ai': /"(Ai[A-Z0-9]\w*)"/gm,
|
|
21
|
+
'react-icons/bi': /"(Bi[A-Z0-9]\w*)"/gm,
|
|
22
|
+
'react-icons/bs': /"(Bs[A-Z0-9]\w*)"/gm,
|
|
23
|
+
'react-icons/cg': /"(Cg[A-Z0-9]\w*)"/gm,
|
|
24
|
+
'react-icons/ci': /"(Ci[A-Z0-9]\w*)"/gm,
|
|
25
|
+
'react-icons/di': /"(Di[A-Z0-9]\w*)"/gm,
|
|
26
|
+
'react-icons/fa': /"(Fa[A-Z0-9]\w*)"/gm,
|
|
27
|
+
'react-icons/fc': /"(Fc[A-Z0-9]\w*)"/gm,
|
|
28
|
+
'react-icons/fi': /"(Fi[A-Z0-9]\w*)"/gm,
|
|
29
|
+
'react-icons/gi': /"(Gi[A-Z0-9]\w*)"/gm,
|
|
30
|
+
'react-icons/go': /"(Go[A-Z0-9]\w*)"/gm,
|
|
31
|
+
'react-icons/gr': /"(Gr[A-Z0-9]\w*)"/gm,
|
|
32
|
+
'react-icons/hi': /"(Hi[A-Z0-9]\w*)"/gm,
|
|
33
|
+
'react-icons/im': /"(Im[A-Z0-9]\w*)"/gm,
|
|
34
|
+
'react-icons/io': /"(IoIos[A-Z0-9]\w*)"/gm,
|
|
35
|
+
'react-icons/io5': /"(Io[A-Z0-9]\w*)"/gm,
|
|
36
|
+
'react-icons/lu': /"(Lu[A-Z0-9]\w*)"/gm,
|
|
37
|
+
'react-icons/md': /"(Md[A-Z0-9]\w*)"/gm,
|
|
38
|
+
'react-icons/pi': /"(Pi[A-Z0-9]\w*)"/gm,
|
|
39
|
+
'react-icons/ri': /"(Ri[A-Z0-9]\w*)"/gm,
|
|
40
|
+
'react-icons/rx': /"(Rx[A-Z0-9]\w*)"/gm,
|
|
41
|
+
'react-icons/si': /"(Si[A-Z0-9]\w*)"/gm,
|
|
42
|
+
'react-icons/sl': /"(Sl[A-Z0-9]\w*)"/gm,
|
|
43
|
+
'react-icons/tb': /"(Tb[A-Z0-9]\w*)"/gm,
|
|
44
|
+
'react-icons/tfi': /"(Tfi[A-Z0-9]\w*)"/gm,
|
|
45
|
+
'react-icons/ti': /"(Ti[A-Z0-9]\w*)"/gm,
|
|
46
|
+
'react-icons/vsc': /"(Vsc[A-Z0-9]\w*)"/gm,
|
|
47
|
+
'react-icons/wi': /"(Wi[A-Z0-9]\w*)"/gm
|
|
48
|
+
};
|
|
49
|
+
export default iconPackages;
|
|
@@ -15,8 +15,10 @@
|
|
|
15
15
|
*/ import { get } from '@lowdefy/helpers';
|
|
16
16
|
import getRefPath from './getRefPath.js';
|
|
17
17
|
import makeId from '../../utils/makeId.js';
|
|
18
|
-
function makeRefDefinition(refDefinition, parent, refMap, lineNumber) {
|
|
19
|
-
|
|
18
|
+
function makeRefDefinition(refDefinition, parent, refMap, lineNumber, walkerPath) {
|
|
19
|
+
// Use walker tree path when available for deterministic IDs under parallel
|
|
20
|
+
// resolution. Falls back to counter for root ref and JIT-created refs.
|
|
21
|
+
const id = walkerPath != null ? walkerPath : makeId.next();
|
|
20
22
|
const refDef = {
|
|
21
23
|
parent,
|
|
22
24
|
lineNumber
|
|
@@ -208,7 +208,7 @@ function resolveVar(node, ctx) {
|
|
|
208
208
|
async function resolveRef(node, ctx) {
|
|
209
209
|
// 1. Create ref definition
|
|
210
210
|
const lineNumber = node['~l'];
|
|
211
|
-
const refDef = makeRefDefinition(node._ref, ctx.refId, ctx.refMap, lineNumber);
|
|
211
|
+
const refDef = makeRefDefinition(node._ref, ctx.refId, ctx.refMap, lineNumber, ctx.path);
|
|
212
212
|
// 2. Store unresolved vars before resolution mutates them, and clone so
|
|
213
213
|
// resolution operates on a copy (preserving original.vars for resolver refs).
|
|
214
214
|
const varKeys = Object.keys(refDef.vars);
|
|
@@ -220,11 +220,11 @@ async function resolveRef(node, ctx) {
|
|
|
220
220
|
if (type.isObject(refDef.path)) {
|
|
221
221
|
refDef.path = await resolve(cloneForResolve(refDef.path), ctx);
|
|
222
222
|
}
|
|
223
|
-
|
|
223
|
+
await Promise.all(varKeys.map(async (varKey)=>{
|
|
224
224
|
if (type.isObject(refDef.vars[varKey]) || type.isArray(refDef.vars[varKey])) {
|
|
225
225
|
refDef.vars[varKey] = await resolve(refDef.vars[varKey], ctx);
|
|
226
226
|
}
|
|
227
|
-
}
|
|
227
|
+
}));
|
|
228
228
|
if (type.isObject(refDef.key)) {
|
|
229
229
|
refDef.key = await resolve(cloneForResolve(refDef.key), ctx);
|
|
230
230
|
}
|
|
@@ -307,28 +307,36 @@ async function resolve(node, ctx) {
|
|
|
307
307
|
// 4. Object with _var — resolve, then re-walk the result so any
|
|
308
308
|
// _ref or _build.* operators inside the default value get processed.
|
|
309
309
|
if (type.isObject(node) && !type.isUndefined(node._var)) {
|
|
310
|
-
|
|
311
|
-
|
|
310
|
+
try {
|
|
311
|
+
const varResult = resolveVar(node, ctx);
|
|
312
|
+
return await resolve(varResult, ctx);
|
|
313
|
+
} catch (error) {
|
|
314
|
+
if (error instanceof ConfigError) {
|
|
315
|
+
ctx.collectError(error);
|
|
316
|
+
return null;
|
|
317
|
+
}
|
|
318
|
+
throw error;
|
|
319
|
+
}
|
|
312
320
|
}
|
|
313
|
-
// 5. Array — walk children in
|
|
321
|
+
// 5. Array — walk children in parallel
|
|
314
322
|
if (type.isArray(node)) {
|
|
315
|
-
|
|
316
|
-
node[i] = await resolve(
|
|
317
|
-
}
|
|
323
|
+
await Promise.all(node.map(async (item, i)=>{
|
|
324
|
+
node[i] = await resolve(item, ctx.child(String(i)));
|
|
325
|
+
}));
|
|
318
326
|
return node;
|
|
319
327
|
}
|
|
320
|
-
// 6. Object — walk children in
|
|
328
|
+
// 6. Object — walk children in parallel
|
|
321
329
|
const keys = Object.keys(node);
|
|
322
|
-
|
|
330
|
+
await Promise.all(keys.map(async (key)=>{
|
|
323
331
|
if (ctx.shouldStop) {
|
|
324
332
|
const childPath = ctx.path ? `${ctx.path}.${key}` : key;
|
|
325
333
|
if (ctx.shouldStop(childPath, ctx.refId)) {
|
|
326
334
|
delete node[key];
|
|
327
|
-
|
|
335
|
+
return;
|
|
328
336
|
}
|
|
329
337
|
}
|
|
330
338
|
node[key] = await resolve(node[key], ctx.child(key));
|
|
331
|
-
}
|
|
339
|
+
}));
|
|
332
340
|
// Check if this is a _build.* operator
|
|
333
341
|
if (isBuildOperator(node)) {
|
|
334
342
|
const result = evaluateBuildOperator(node, ctx);
|
|
@@ -33,7 +33,9 @@ import makeRefDefinition from '../buildRefs/makeRefDefinition.js';
|
|
|
33
33
|
import { resolve, WalkContext, cloneForResolve, tagRefDeep } from '../buildRefs/walker.js';
|
|
34
34
|
import validateOperatorsDynamic from '../validateOperatorsDynamic.js';
|
|
35
35
|
import writeMaps from '../writeMaps.js';
|
|
36
|
+
import detectMissingIcons from './detectMissingIcons.js';
|
|
36
37
|
import detectMissingPluginPackages from './detectMissingPluginPackages.js';
|
|
38
|
+
import updateIconImportsJit from './updateIconImportsJit.js';
|
|
37
39
|
import updateServerPackageJsonJit from './updateServerPackageJsonJit.js';
|
|
38
40
|
import validatePageTypes from './validatePageTypes.js';
|
|
39
41
|
import writePageJit from './writePageJit.js';
|
|
@@ -43,6 +45,20 @@ validateOperatorsDynamic({
|
|
|
43
45
|
const dynamicIdentifiers = collectDynamicIdentifiers({
|
|
44
46
|
operators
|
|
45
47
|
});
|
|
48
|
+
async function updateDynamicIcons({ page, context }) {
|
|
49
|
+
if (!context.iconImports) return;
|
|
50
|
+
const missingIcons = detectMissingIcons({
|
|
51
|
+
page,
|
|
52
|
+
iconImports: context.iconImports
|
|
53
|
+
});
|
|
54
|
+
if (missingIcons.length > 0) {
|
|
55
|
+
await updateIconImportsJit({
|
|
56
|
+
newIcons: missingIcons,
|
|
57
|
+
iconImports: context.iconImports,
|
|
58
|
+
context
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
}
|
|
46
62
|
async function buildPageJit({ pageId, pageRegistry, context, directories, logger }) {
|
|
47
63
|
// Use provided context or create a minimal one for JIT builds
|
|
48
64
|
const buildContext = context ?? createContext({
|
|
@@ -68,7 +84,12 @@ async function buildPageJit({ pageId, pageRegistry, context, directories, logger
|
|
|
68
84
|
const pagePath = path.join(buildContext.directories.build, 'pages', pageId, `${pageId}.json`);
|
|
69
85
|
try {
|
|
70
86
|
const content = await fs.promises.readFile(pagePath, 'utf8');
|
|
71
|
-
|
|
87
|
+
const page = serializer.deserialize(JSON.parse(content));
|
|
88
|
+
await updateDynamicIcons({
|
|
89
|
+
page,
|
|
90
|
+
context: buildContext
|
|
91
|
+
});
|
|
92
|
+
return page;
|
|
72
93
|
} catch (err) {
|
|
73
94
|
if (err.code !== 'ENOENT') throw err;
|
|
74
95
|
}
|
|
@@ -200,6 +221,13 @@ async function buildPageJit({ pageId, pageRegistry, context, directories, logger
|
|
|
200
221
|
]
|
|
201
222
|
};
|
|
202
223
|
}
|
|
224
|
+
// Detect icons in the JIT-resolved page that weren't discovered during skeleton build.
|
|
225
|
+
// Placed after detectMissingPluginPackages so we skip this when packages are being
|
|
226
|
+
// installed (the server restarts and icons will be discovered on the next build).
|
|
227
|
+
await updateDynamicIcons({
|
|
228
|
+
page: processed,
|
|
229
|
+
context: buildContext
|
|
230
|
+
});
|
|
203
231
|
// Validate link, state, payload, and server-state references
|
|
204
232
|
const pageIds = Object.keys(pageRegistry);
|
|
205
233
|
validateLinkReferences({
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2020-2026 Lowdefy, Inc
|
|
3
|
+
|
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
you may not use this file except in compliance with the License.
|
|
6
|
+
You may obtain a copy of the License at
|
|
7
|
+
|
|
8
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
|
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
See the License for the specific language governing permissions and
|
|
14
|
+
limitations under the License.
|
|
15
|
+
*/ import iconPackages from '../buildImports/iconPackages.js';
|
|
16
|
+
function detectMissingIcons({ page, iconImports }) {
|
|
17
|
+
const pageJson = JSON.stringify(page);
|
|
18
|
+
const newIcons = [];
|
|
19
|
+
for (const [iconPackage, regex] of Object.entries(iconPackages)){
|
|
20
|
+
const existing = iconImports.find((entry)=>entry.package === iconPackage);
|
|
21
|
+
const existingSet = new Set(existing?.icons ?? []);
|
|
22
|
+
const seen = new Set();
|
|
23
|
+
for (const match of pageJson.matchAll(regex)){
|
|
24
|
+
const iconName = match[1];
|
|
25
|
+
if (!existingSet.has(iconName) && !seen.has(iconName)) {
|
|
26
|
+
seen.add(iconName);
|
|
27
|
+
newIcons.push({
|
|
28
|
+
icon: iconName,
|
|
29
|
+
package: iconPackage
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return newIcons;
|
|
35
|
+
}
|
|
36
|
+
export default detectMissingIcons;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2020-2026 Lowdefy, Inc
|
|
3
|
+
|
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
you may not use this file except in compliance with the License.
|
|
6
|
+
You may obtain a copy of the License at
|
|
7
|
+
|
|
8
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
|
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
See the License for the specific language governing permissions and
|
|
14
|
+
limitations under the License.
|
|
15
|
+
*/ import { createRequire } from 'module';
|
|
16
|
+
import path from 'path';
|
|
17
|
+
// Matches the JSON data argument inside GenIcon({...})(props) in react-icons source.
|
|
18
|
+
// react-icons icons are generated functions of the form:
|
|
19
|
+
// function IconName(props) { return GenIcon({...})(props); }
|
|
20
|
+
// Tolerates optional whitespace around GenIcon call and props argument.
|
|
21
|
+
const genIconDataRegex = /GenIcon\s*\(([\s\S]*?)\)\s*\(\s*props\s*\)/;
|
|
22
|
+
function extractIconData({ icons, directories, logger }) {
|
|
23
|
+
const serverRequire = createRequire(path.join(directories.server, 'package.json'));
|
|
24
|
+
const iconDataMap = {};
|
|
25
|
+
const moduleCache = {};
|
|
26
|
+
for (const { icon, package: pkg } of icons){
|
|
27
|
+
if (!moduleCache[pkg]) {
|
|
28
|
+
try {
|
|
29
|
+
moduleCache[pkg] = serverRequire(pkg);
|
|
30
|
+
} catch {
|
|
31
|
+
if (logger) {
|
|
32
|
+
logger.warn(`Could not load icon package "${pkg}" for dynamic icon extraction.`);
|
|
33
|
+
}
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
const iconFn = moduleCache[pkg][icon];
|
|
38
|
+
if (!iconFn) continue;
|
|
39
|
+
const match = iconFn.toString().match(genIconDataRegex);
|
|
40
|
+
if (match) {
|
|
41
|
+
try {
|
|
42
|
+
iconDataMap[icon] = JSON.parse(match[1]);
|
|
43
|
+
} catch {
|
|
44
|
+
if (logger) {
|
|
45
|
+
logger.warn(`Could not parse icon data for "${icon}" from "${pkg}".`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
} else if (logger) {
|
|
49
|
+
logger.warn(`Could not extract icon data for "${icon}" from "${pkg}". The icon will show as a fallback.`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return iconDataMap;
|
|
53
|
+
}
|
|
54
|
+
export default extractIconData;
|
|
@@ -209,6 +209,10 @@ async function shallowBuild(options) {
|
|
|
209
209
|
components,
|
|
210
210
|
context
|
|
211
211
|
});
|
|
212
|
+
// Persist icon imports snapshot for JIT icon detection.
|
|
213
|
+
// When buildPageJit resolves a page, it compares discovered icons against
|
|
214
|
+
// this snapshot and regenerates plugins/icons.js if new icons are found.
|
|
215
|
+
await context.writeBuildArtifact('iconImports.json', JSON.stringify(components.imports.icons));
|
|
212
216
|
await writePageRegistry({
|
|
213
217
|
pageRegistry,
|
|
214
218
|
context
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2020-2026 Lowdefy, Inc
|
|
3
|
+
|
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
you may not use this file except in compliance with the License.
|
|
6
|
+
You may obtain a copy of the License at
|
|
7
|
+
|
|
8
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
|
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
See the License for the specific language governing permissions and
|
|
14
|
+
limitations under the License.
|
|
15
|
+
*/ import extractIconData from './extractIconData.js';
|
|
16
|
+
import writeIconsDynamic from './writeIconsDynamic.js';
|
|
17
|
+
async function updateIconImportsJit({ newIcons, iconImports, context }) {
|
|
18
|
+
for (const { icon, package: pkg } of newIcons){
|
|
19
|
+
let entry = iconImports.find((e)=>e.package === pkg);
|
|
20
|
+
if (!entry) {
|
|
21
|
+
entry = {
|
|
22
|
+
icons: [],
|
|
23
|
+
package: pkg
|
|
24
|
+
};
|
|
25
|
+
iconImports.push(entry);
|
|
26
|
+
}
|
|
27
|
+
// Guard against concurrent JIT builds adding the same icon
|
|
28
|
+
if (!entry.icons.includes(icon)) {
|
|
29
|
+
entry.icons.push(icon);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
await context.writeBuildArtifact('iconImports.json', JSON.stringify(iconImports));
|
|
33
|
+
// Extract SVG tree data from react-icons and write a self-contained JS module
|
|
34
|
+
// that the client can fetch at runtime without a Next.js rebuild.
|
|
35
|
+
const newIconData = extractIconData({
|
|
36
|
+
icons: newIcons,
|
|
37
|
+
directories: context.directories,
|
|
38
|
+
logger: context.logger
|
|
39
|
+
});
|
|
40
|
+
await writeIconsDynamic({
|
|
41
|
+
newIconData,
|
|
42
|
+
context
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
export default updateIconImportsJit;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2020-2026 Lowdefy, Inc
|
|
3
|
+
|
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
you may not use this file except in compliance with the License.
|
|
6
|
+
You may obtain a copy of the License at
|
|
7
|
+
|
|
8
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
|
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
See the License for the specific language governing permissions and
|
|
14
|
+
limitations under the License.
|
|
15
|
+
*/ async function writeIconsDynamic({ newIconData, context }) {
|
|
16
|
+
Object.assign(context.dynamicIconData, newIconData);
|
|
17
|
+
const content = `export default ${JSON.stringify(context.dynamicIconData)};\n`;
|
|
18
|
+
await context.writeBuildArtifact('plugins/iconsDynamic.js', content);
|
|
19
|
+
}
|
|
20
|
+
export default writeIconsDynamic;
|