@keload/node-red-dxp 1.6.0 → 1.7.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/dist/builder/index.cjs +738 -0
- package/dist/builder/index.cjs.map +1 -0
- package/dist/builder/index.js +705 -0
- package/dist/builder/index.js.map +1 -0
- package/dist/cli/index.cjs +91 -125
- package/dist/cli/index.cjs.map +1 -1
- package/package.json +6 -3
|
@@ -0,0 +1,738 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var fs = require('fs');
|
|
4
|
+
var path2 = require('path');
|
|
5
|
+
var cosmiconfig = require('cosmiconfig');
|
|
6
|
+
var fastGlob = require('fast-glob');
|
|
7
|
+
var radash = require('radash');
|
|
8
|
+
var fsPromise = require('fs/promises');
|
|
9
|
+
var esbuild = require('esbuild');
|
|
10
|
+
var htmlMinifierTerser = require('html-minifier-terser');
|
|
11
|
+
var purgeCss = require('@fullhuman/postcss-purgecss');
|
|
12
|
+
var autoprefixer = require('autoprefixer');
|
|
13
|
+
var cssnano = require('cssnano');
|
|
14
|
+
var postcss = require('postcss');
|
|
15
|
+
var sass = require('sass');
|
|
16
|
+
var tailwindcss = require('tailwindcss');
|
|
17
|
+
|
|
18
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
19
|
+
|
|
20
|
+
function _interopNamespace(e) {
|
|
21
|
+
if (e && e.__esModule) return e;
|
|
22
|
+
var n = Object.create(null);
|
|
23
|
+
if (e) {
|
|
24
|
+
Object.keys(e).forEach(function (k) {
|
|
25
|
+
if (k !== 'default') {
|
|
26
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
27
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
28
|
+
enumerable: true,
|
|
29
|
+
get: function () { return e[k]; }
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
n.default = e;
|
|
35
|
+
return Object.freeze(n);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
var fs__default = /*#__PURE__*/_interopDefault(fs);
|
|
39
|
+
var path2__default = /*#__PURE__*/_interopDefault(path2);
|
|
40
|
+
var fsPromise__default = /*#__PURE__*/_interopDefault(fsPromise);
|
|
41
|
+
var esbuild__default = /*#__PURE__*/_interopDefault(esbuild);
|
|
42
|
+
var purgeCss__default = /*#__PURE__*/_interopDefault(purgeCss);
|
|
43
|
+
var autoprefixer__default = /*#__PURE__*/_interopDefault(autoprefixer);
|
|
44
|
+
var cssnano__default = /*#__PURE__*/_interopDefault(cssnano);
|
|
45
|
+
var postcss__default = /*#__PURE__*/_interopDefault(postcss);
|
|
46
|
+
var sass__namespace = /*#__PURE__*/_interopNamespace(sass);
|
|
47
|
+
var tailwindcss__default = /*#__PURE__*/_interopDefault(tailwindcss);
|
|
48
|
+
|
|
49
|
+
var __defProp = Object.defineProperty;
|
|
50
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
51
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
52
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
53
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
54
|
+
var __spreadValues = (a, b) => {
|
|
55
|
+
for (var prop in b || (b = {}))
|
|
56
|
+
if (__hasOwnProp.call(b, prop))
|
|
57
|
+
__defNormalProp(a, prop, b[prop]);
|
|
58
|
+
if (__getOwnPropSymbols)
|
|
59
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
60
|
+
if (__propIsEnum.call(b, prop))
|
|
61
|
+
__defNormalProp(a, prop, b[prop]);
|
|
62
|
+
}
|
|
63
|
+
return a;
|
|
64
|
+
};
|
|
65
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
66
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
67
|
+
}) : x)(function(x) {
|
|
68
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
69
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
70
|
+
});
|
|
71
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
72
|
+
var __async = (__this, __arguments, generator) => {
|
|
73
|
+
return new Promise((resolve, reject) => {
|
|
74
|
+
var fulfilled = (value) => {
|
|
75
|
+
try {
|
|
76
|
+
step(generator.next(value));
|
|
77
|
+
} catch (e) {
|
|
78
|
+
reject(e);
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
var rejected = (value) => {
|
|
82
|
+
try {
|
|
83
|
+
step(generator.throw(value));
|
|
84
|
+
} catch (e) {
|
|
85
|
+
reject(e);
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
|
|
89
|
+
step((generator = generator.apply(__this, __arguments)).next());
|
|
90
|
+
});
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
// node_modules/.pnpm/is-what@5.0.2/node_modules/is-what/dist/getType.js
|
|
94
|
+
function getType(payload) {
|
|
95
|
+
return Object.prototype.toString.call(payload).slice(8, -1);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// node_modules/.pnpm/is-what@5.0.2/node_modules/is-what/dist/isPlainObject.js
|
|
99
|
+
function isPlainObject(payload) {
|
|
100
|
+
if (getType(payload) !== "Object")
|
|
101
|
+
return false;
|
|
102
|
+
const prototype = Object.getPrototypeOf(payload);
|
|
103
|
+
return !!prototype && prototype.constructor === Object && prototype === Object.prototype;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// node_modules/.pnpm/is-what@5.0.2/node_modules/is-what/dist/isSymbol.js
|
|
107
|
+
function isSymbol(payload) {
|
|
108
|
+
return getType(payload) === "Symbol";
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// node_modules/.pnpm/merge-anything@6.0.2/node_modules/merge-anything/dist/merge.js
|
|
112
|
+
function assignProp(carry, key, newVal, originalObject) {
|
|
113
|
+
const propType = {}.propertyIsEnumerable.call(originalObject, key) ? "enumerable" : "nonenumerable";
|
|
114
|
+
if (propType === "enumerable")
|
|
115
|
+
carry[key] = newVal;
|
|
116
|
+
if (propType === "nonenumerable") {
|
|
117
|
+
Object.defineProperty(carry, key, {
|
|
118
|
+
value: newVal,
|
|
119
|
+
enumerable: false,
|
|
120
|
+
writable: true,
|
|
121
|
+
configurable: true
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
function mergeRecursively(origin, newComer, compareFn) {
|
|
126
|
+
if (!isPlainObject(newComer))
|
|
127
|
+
return newComer;
|
|
128
|
+
let newObject = {};
|
|
129
|
+
if (isPlainObject(origin)) {
|
|
130
|
+
const props2 = Object.getOwnPropertyNames(origin);
|
|
131
|
+
const symbols2 = Object.getOwnPropertySymbols(origin);
|
|
132
|
+
newObject = [...props2, ...symbols2].reduce((carry, key) => {
|
|
133
|
+
const targetVal = origin[key];
|
|
134
|
+
if (!isSymbol(key) && !Object.getOwnPropertyNames(newComer).includes(key) || isSymbol(key) && !Object.getOwnPropertySymbols(newComer).includes(key)) {
|
|
135
|
+
assignProp(carry, key, targetVal, origin);
|
|
136
|
+
}
|
|
137
|
+
return carry;
|
|
138
|
+
}, {});
|
|
139
|
+
}
|
|
140
|
+
const props = Object.getOwnPropertyNames(newComer);
|
|
141
|
+
const symbols = Object.getOwnPropertySymbols(newComer);
|
|
142
|
+
const result = [...props, ...symbols].reduce((carry, key) => {
|
|
143
|
+
let newVal = newComer[key];
|
|
144
|
+
const targetVal = isPlainObject(origin) ? origin[key] : void 0;
|
|
145
|
+
if (targetVal !== void 0 && isPlainObject(newVal)) {
|
|
146
|
+
newVal = mergeRecursively(targetVal, newVal);
|
|
147
|
+
}
|
|
148
|
+
const propToAssign = newVal;
|
|
149
|
+
assignProp(carry, key, propToAssign, newComer);
|
|
150
|
+
return carry;
|
|
151
|
+
}, newObject);
|
|
152
|
+
return result;
|
|
153
|
+
}
|
|
154
|
+
function merge(object, ...otherObjects) {
|
|
155
|
+
return otherObjects.reduce((result, newComer) => {
|
|
156
|
+
return mergeRecursively(result, newComer);
|
|
157
|
+
}, object);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// src/default-config.ts
|
|
161
|
+
var defaultConfig = {
|
|
162
|
+
libCacheDir: ".node-red-dx",
|
|
163
|
+
srcDir: "src",
|
|
164
|
+
nodesDirName: "nodes",
|
|
165
|
+
nodes: {
|
|
166
|
+
controllerName: "controller",
|
|
167
|
+
localesDirName: "locales",
|
|
168
|
+
editor: {
|
|
169
|
+
dirName: "editor",
|
|
170
|
+
htmlName: "index",
|
|
171
|
+
tsName: "index"
|
|
172
|
+
}
|
|
173
|
+
},
|
|
174
|
+
builder: {
|
|
175
|
+
outputDir: "dist"
|
|
176
|
+
},
|
|
177
|
+
watcher: {
|
|
178
|
+
nodeRed: {
|
|
179
|
+
enabled: true,
|
|
180
|
+
path: "~/.node-red",
|
|
181
|
+
url: "http://localhost:1880"
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
// src/current-context.ts
|
|
187
|
+
var CONFIG_FILE_NAME = "node-red-dx";
|
|
188
|
+
var cleanPkgName = (pkgName) => pkgName.replace("@", "").replace("/", "-");
|
|
189
|
+
function getConfig() {
|
|
190
|
+
const explorerSync = cosmiconfig.cosmiconfigSync(CONFIG_FILE_NAME);
|
|
191
|
+
try {
|
|
192
|
+
const result = explorerSync.search();
|
|
193
|
+
return merge(defaultConfig, result ? result.config : {});
|
|
194
|
+
} catch (error) {
|
|
195
|
+
console.error("Error while loading configuration", error);
|
|
196
|
+
throw error;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
var currentConfig = getConfig();
|
|
200
|
+
var currentDir = process.cwd();
|
|
201
|
+
var jsonPackage = JSON.parse(fs.readFileSync(`${currentDir}/package.json`, "utf-8"));
|
|
202
|
+
var pathSrcDir = `${currentDir}/${currentConfig.srcDir}`;
|
|
203
|
+
var additionalResourcesDir = `${currentDir}/resources`;
|
|
204
|
+
var pathSrcNodesDir = `${pathSrcDir}/${currentConfig.nodesDirName}`;
|
|
205
|
+
var pathLibCacheDir = `${currentDir}/${currentConfig.libCacheDir}`;
|
|
206
|
+
var currentPackagedDistPath = `${path2__default.default.resolve(__dirname, "..")}`;
|
|
207
|
+
var packageNameSlug = cleanPkgName(jsonPackage.name);
|
|
208
|
+
function listNodeFolders(rawNodes = []) {
|
|
209
|
+
return rawNodes.map((entry) => {
|
|
210
|
+
const fullPath = entry.path;
|
|
211
|
+
const fullEditorPath = `${fullPath}/${currentConfig.nodes.editor.dirName}`;
|
|
212
|
+
const relativePath = fullPath.replace(currentDir, "").slice(1);
|
|
213
|
+
const relativeEditorPath = `${relativePath}/${currentConfig.nodes.editor.dirName}`;
|
|
214
|
+
const scssFiles = fastGlob.globSync(`${fullEditorPath}/**/*.scss`);
|
|
215
|
+
const mdxFiles = fastGlob.globSync(`${fullPath}/doc.mdx`);
|
|
216
|
+
const mdFiles = fastGlob.globSync(`${fullPath}/doc.md`);
|
|
217
|
+
const dashName = radash.dash(entry.name);
|
|
218
|
+
return {
|
|
219
|
+
fullEditorPath,
|
|
220
|
+
fullPath,
|
|
221
|
+
name: entry.name,
|
|
222
|
+
pascalName: radash.pascal(entry.name),
|
|
223
|
+
dashName,
|
|
224
|
+
relativeEditorPath,
|
|
225
|
+
relativePath,
|
|
226
|
+
resolvedLocalesPaths: fastGlob.globSync(`${fullPath}/${currentConfig.nodes.localesDirName}/*.json`),
|
|
227
|
+
nodeIdentifier: `${packageNameSlug}-${dashName}`,
|
|
228
|
+
fullControllerPath: `${fullPath}/controller.ts`,
|
|
229
|
+
editor: {
|
|
230
|
+
tsPath: `${fullEditorPath}/${currentConfig.nodes.editor.tsName}.ts`,
|
|
231
|
+
htmlPath: `${fullEditorPath}/${currentConfig.nodes.editor.htmlName}.html`,
|
|
232
|
+
scssFiles
|
|
233
|
+
},
|
|
234
|
+
doc: {
|
|
235
|
+
mdxFiles,
|
|
236
|
+
mdFiles
|
|
237
|
+
}
|
|
238
|
+
};
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
function getCurrentContext() {
|
|
242
|
+
const resolvedNodesPaths = fastGlob.globSync(`${pathSrcNodesDir}/**/*`, { onlyDirectories: true, deep: 1, objectMode: true });
|
|
243
|
+
const listNodesFull = listNodeFolders(resolvedNodesPaths);
|
|
244
|
+
const listNodesFullNames = listNodesFull.map((node) => node.name);
|
|
245
|
+
return {
|
|
246
|
+
currentDir,
|
|
247
|
+
pathSrcDir,
|
|
248
|
+
pathSrcNodesDir,
|
|
249
|
+
additionalResourcesDir,
|
|
250
|
+
pathDist: `${currentDir}/${currentConfig.builder.outputDir}`,
|
|
251
|
+
currentPackagedDistPath,
|
|
252
|
+
cacheDirFiles: {
|
|
253
|
+
controllerIndex: `${pathLibCacheDir}/controller-index.ts`,
|
|
254
|
+
editorIndex: `${pathLibCacheDir}/editor-index.ts`
|
|
255
|
+
},
|
|
256
|
+
pathLibCacheDir,
|
|
257
|
+
packageName: jsonPackage.name,
|
|
258
|
+
packageNameSlug,
|
|
259
|
+
config: currentConfig,
|
|
260
|
+
resolvedSrcPathsScss: fastGlob.globSync(`${pathSrcDir}/**/*.scss`, { ignore: [`${pathSrcNodesDir}/**/*.scss`] }),
|
|
261
|
+
resolvedNodesPaths: resolvedNodesPaths.map((entry) => entry.path),
|
|
262
|
+
resolvedSrcLocalesPaths: fastGlob.globSync(`${pathSrcDir}/locales/*.json`),
|
|
263
|
+
listNodesFull,
|
|
264
|
+
listNodesFullNames
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
var currentContext = getCurrentContext();
|
|
268
|
+
var distributionPackagePath = `${path2__default.default.resolve(__dirname, "..")}`;
|
|
269
|
+
function createFolderIfNotExists(folderPath) {
|
|
270
|
+
if (!fs__default.default.existsSync(folderPath)) {
|
|
271
|
+
fs__default.default.mkdirSync(folderPath, { recursive: true });
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
function writeFile(path3, content) {
|
|
275
|
+
return __async(this, null, function* () {
|
|
276
|
+
try {
|
|
277
|
+
yield fsPromise__default.default.writeFile(path3, content);
|
|
278
|
+
} catch (error) {
|
|
279
|
+
console.error("Error writing controller index:", error);
|
|
280
|
+
}
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
function cleanPaths(paths) {
|
|
284
|
+
return __async(this, null, function* () {
|
|
285
|
+
for (const dirPath of paths) {
|
|
286
|
+
try {
|
|
287
|
+
const resolvedPath = path2__default.default.resolve(dirPath);
|
|
288
|
+
const stats = yield fsPromise__default.default.stat(resolvedPath).catch(() => null);
|
|
289
|
+
if (stats == null ? void 0 : stats.isDirectory()) {
|
|
290
|
+
yield fsPromise__default.default.rm(resolvedPath, { recursive: true, force: true });
|
|
291
|
+
}
|
|
292
|
+
} catch (error) {
|
|
293
|
+
console.error(`Error cleaning path (${dirPath}): ${error}`);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
var addCredentialsExportPlugin = {
|
|
299
|
+
name: "add-credentials-export",
|
|
300
|
+
setup(build) {
|
|
301
|
+
build.onLoad({ filter: /controller\.ts$/ }, (args) => __async(this, null, function* () {
|
|
302
|
+
const source = yield fsPromise__default.default.readFile(args.path, "utf8");
|
|
303
|
+
const hasCredentialsExport = /export\s+const\s+credentials\s*=/.test(source);
|
|
304
|
+
if (!hasCredentialsExport) {
|
|
305
|
+
return {
|
|
306
|
+
contents: `${source}
|
|
307
|
+
export const credentials = {};`,
|
|
308
|
+
loader: "ts"
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
return { contents: source, loader: "ts" };
|
|
312
|
+
}));
|
|
313
|
+
}
|
|
314
|
+
};
|
|
315
|
+
|
|
316
|
+
// src/builder/controller/BuilderController.class.ts
|
|
317
|
+
var BuilderController = class {
|
|
318
|
+
constructor(params) {
|
|
319
|
+
__publicField(this, "params");
|
|
320
|
+
this.params = __spreadValues({ minify: false }, params);
|
|
321
|
+
}
|
|
322
|
+
getControllerIndexContent() {
|
|
323
|
+
return __async(this, null, function* () {
|
|
324
|
+
return `
|
|
325
|
+
import type { NodeAPI } from 'node-red';
|
|
326
|
+
${currentContext.listNodesFull.map((node) => `import ${node.pascalName}, {credentials as cred${node.pascalName}} from '${node.fullControllerPath}';`).join("\n")}
|
|
327
|
+
|
|
328
|
+
|
|
329
|
+
export default async (RED: NodeAPI): Promise<void> => {
|
|
330
|
+
global.RED = RED;
|
|
331
|
+
|
|
332
|
+
${currentContext.listNodesFull.map(
|
|
333
|
+
(node) => `// @ts-ignore
|
|
334
|
+
global.RED.nodes.registerType('${node.name}', ${node.pascalName}, {
|
|
335
|
+
credentials: cred${node.pascalName}
|
|
336
|
+
});`
|
|
337
|
+
).join("\n")}
|
|
338
|
+
};
|
|
339
|
+
`.trim();
|
|
340
|
+
});
|
|
341
|
+
}
|
|
342
|
+
buildScript() {
|
|
343
|
+
return esbuild__default.default.build({
|
|
344
|
+
entryPoints: [currentContext.cacheDirFiles.controllerIndex],
|
|
345
|
+
outfile: `${currentContext.pathDist}/index.js`,
|
|
346
|
+
bundle: true,
|
|
347
|
+
minify: this.params.minify,
|
|
348
|
+
minifyWhitespace: this.params.minify,
|
|
349
|
+
minifyIdentifiers: this.params.minify,
|
|
350
|
+
minifySyntax: this.params.minify,
|
|
351
|
+
platform: "node",
|
|
352
|
+
format: "cjs",
|
|
353
|
+
target: "es2018",
|
|
354
|
+
loader: { ".ts": "ts" },
|
|
355
|
+
packages: "external",
|
|
356
|
+
plugins: [addCredentialsExportPlugin]
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
getControllerTask() {
|
|
360
|
+
return __async(this, null, function* () {
|
|
361
|
+
return this.getControllerIndexContent().then((content) => {
|
|
362
|
+
writeFile(`${currentContext.cacheDirFiles.controllerIndex}`, content).then(() => {
|
|
363
|
+
this.buildScript();
|
|
364
|
+
});
|
|
365
|
+
});
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
};
|
|
369
|
+
var BuildDoc = class {
|
|
370
|
+
// TODO need to refactor
|
|
371
|
+
getAllDocContent() {
|
|
372
|
+
const result = [];
|
|
373
|
+
for (const node of currentContext.listNodesFull) {
|
|
374
|
+
const fileMd = node.doc.mdFiles[0];
|
|
375
|
+
if (fileMd) {
|
|
376
|
+
const htmlMd = fs__default.default.readFileSync(node.doc.mdFiles[0], "utf-8");
|
|
377
|
+
const inner = `
|
|
378
|
+
<script type="text/markdown" data-help-name="${node.name}">
|
|
379
|
+
${htmlMd}
|
|
380
|
+
</script>
|
|
381
|
+
`;
|
|
382
|
+
result.push(inner);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
return result.length ? result.join("\n") : "";
|
|
386
|
+
}
|
|
387
|
+
};
|
|
388
|
+
function cleanSpaces(str) {
|
|
389
|
+
return str.trim().replace(/\n\s+/g, "");
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
// src/builder/editor/i18n.ts
|
|
393
|
+
function updateI18nAttributes(nodeName = "", htmlContent = "") {
|
|
394
|
+
if (!nodeName || !htmlContent) {
|
|
395
|
+
return htmlContent;
|
|
396
|
+
}
|
|
397
|
+
return htmlContent.replace(/data-i18n="([^"]+)"/g, (match, i18nValue) => {
|
|
398
|
+
const updatedValue = i18nValue.replace(/(\[.*?\])?(node-red:[^;]+|[^;]+)/g, (_, prefix, key) => {
|
|
399
|
+
let res = key;
|
|
400
|
+
if (!key.startsWith("node-red:")) {
|
|
401
|
+
res = `${nodeName}.${key}`;
|
|
402
|
+
}
|
|
403
|
+
return (prefix || "") + res;
|
|
404
|
+
});
|
|
405
|
+
return `data-i18n="${updatedValue}"`;
|
|
406
|
+
});
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
// src/builder/editor/html.ts
|
|
410
|
+
function minifyHtml(content) {
|
|
411
|
+
return __async(this, null, function* () {
|
|
412
|
+
return htmlMinifierTerser.minify(content, {
|
|
413
|
+
collapseWhitespace: true,
|
|
414
|
+
removeComments: true,
|
|
415
|
+
removeRedundantAttributes: false,
|
|
416
|
+
useShortDoctype: true,
|
|
417
|
+
removeEmptyAttributes: false,
|
|
418
|
+
minifyCSS: false,
|
|
419
|
+
minifyJS: false
|
|
420
|
+
});
|
|
421
|
+
});
|
|
422
|
+
}
|
|
423
|
+
function wrapHtml(nodeName, html) {
|
|
424
|
+
return `
|
|
425
|
+
<script type="text/html" data-template-name="${nodeName}">
|
|
426
|
+
${html}
|
|
427
|
+
</script>
|
|
428
|
+
`;
|
|
429
|
+
}
|
|
430
|
+
function processNodeHtml(node, packageNameSlug2, minify2 = false) {
|
|
431
|
+
return __async(this, null, function* () {
|
|
432
|
+
const htmlContent = fs.readFileSync(node.editor.htmlPath, "utf8");
|
|
433
|
+
const htmlContentWithAdditionalDiv = `
|
|
434
|
+
<div class="${packageNameSlug2}">
|
|
435
|
+
<div class="${node.nodeIdentifier}">${htmlContent}</div>
|
|
436
|
+
</div>
|
|
437
|
+
`;
|
|
438
|
+
let html = minify2 ? yield minifyHtml(htmlContentWithAdditionalDiv) : htmlContentWithAdditionalDiv;
|
|
439
|
+
html = updateI18nAttributes(node.name, html);
|
|
440
|
+
const wrappedHtml = wrapHtml(node.name, html);
|
|
441
|
+
return {
|
|
442
|
+
nodeName: node.name,
|
|
443
|
+
nodeIdentifier: node.nodeIdentifier,
|
|
444
|
+
html,
|
|
445
|
+
wrappedHtml
|
|
446
|
+
};
|
|
447
|
+
});
|
|
448
|
+
}
|
|
449
|
+
function getNodesHtml(params) {
|
|
450
|
+
return __async(this, null, function* () {
|
|
451
|
+
const { nodes, minify: minify2 = false } = params;
|
|
452
|
+
const res = yield Promise.all(nodes.map((node) => processNodeHtml(node, params.packageNameSlug, minify2)));
|
|
453
|
+
const allHtml = res.map((node) => node.html).join("").trim();
|
|
454
|
+
return {
|
|
455
|
+
html: allHtml,
|
|
456
|
+
allWrappedHtml: res.map((node) => minify2 ? cleanSpaces(node.wrappedHtml) : node.wrappedHtml).join("").trim()
|
|
457
|
+
};
|
|
458
|
+
});
|
|
459
|
+
}
|
|
460
|
+
function processCSS(cssString, htmlString) {
|
|
461
|
+
return __async(this, null, function* () {
|
|
462
|
+
const result = yield postcss__default.default([
|
|
463
|
+
purgeCss__default.default({
|
|
464
|
+
content: [{ raw: htmlString, extension: "html" }]
|
|
465
|
+
// Analyse directe du HTML
|
|
466
|
+
}),
|
|
467
|
+
autoprefixer__default.default,
|
|
468
|
+
cssnano__default.default({ preset: "default" })
|
|
469
|
+
]).process(cssString, { from: void 0 });
|
|
470
|
+
return result.css;
|
|
471
|
+
});
|
|
472
|
+
}
|
|
473
|
+
function compileScss(filePath) {
|
|
474
|
+
const result = sass__namespace.compile(filePath, { style: "expanded" });
|
|
475
|
+
return result.css;
|
|
476
|
+
}
|
|
477
|
+
function buildStyles(files) {
|
|
478
|
+
const styles = {};
|
|
479
|
+
for (let i = 0; i < files.length; i++) {
|
|
480
|
+
const filePath = files[i];
|
|
481
|
+
styles[filePath] = compileScss(filePath);
|
|
482
|
+
}
|
|
483
|
+
return styles;
|
|
484
|
+
}
|
|
485
|
+
function getNodesStyles(nodes) {
|
|
486
|
+
const hasStyles = nodes.some((node) => node.editor.scssFiles.length);
|
|
487
|
+
if (!hasStyles) {
|
|
488
|
+
return [];
|
|
489
|
+
}
|
|
490
|
+
return nodes.filter((node) => node.editor.scssFiles.length).map((node) => {
|
|
491
|
+
const nodeStyles = buildStyles(node.editor.scssFiles);
|
|
492
|
+
const mergedCompiledStyles = Object.values(nodeStyles).join("");
|
|
493
|
+
return {
|
|
494
|
+
name: node.name,
|
|
495
|
+
mergedCompiledStyles,
|
|
496
|
+
scssFinal: `
|
|
497
|
+
#${node.nodeIdentifier}{
|
|
498
|
+
${mergedCompiledStyles}
|
|
499
|
+
}`
|
|
500
|
+
};
|
|
501
|
+
});
|
|
502
|
+
}
|
|
503
|
+
function generateCSSFromHTMLWithTailwind(_0) {
|
|
504
|
+
return __async(this, arguments, function* (htmlString, tailwindConfig = {}) {
|
|
505
|
+
const defaultConfig2 = {
|
|
506
|
+
content: [{ raw: htmlString }],
|
|
507
|
+
theme: {}
|
|
508
|
+
};
|
|
509
|
+
const finalConfig = __spreadValues(__spreadValues({}, defaultConfig2), tailwindConfig);
|
|
510
|
+
const tailwindScssFilePath = fastGlob.globSync(
|
|
511
|
+
`${distributionPackagePath}/${currentContext.config.nodes.editor.dirName}/assets/tailwind.scss`
|
|
512
|
+
)[0];
|
|
513
|
+
const scssString = tailwindScssFilePath.length ? fs__default.default.readFileSync(tailwindScssFilePath, "utf8") : "";
|
|
514
|
+
const result = yield postcss__default.default([tailwindcss__default.default(finalConfig), __require("autoprefixer")]).process(scssString, {
|
|
515
|
+
from: void 0
|
|
516
|
+
});
|
|
517
|
+
return result.css;
|
|
518
|
+
});
|
|
519
|
+
}
|
|
520
|
+
function getSrcStyles() {
|
|
521
|
+
const srcStyles = currentContext.resolvedSrcPathsScss;
|
|
522
|
+
const srcStylesCompiled = buildStyles([...srcStyles]);
|
|
523
|
+
return Object.values(srcStylesCompiled).join("");
|
|
524
|
+
}
|
|
525
|
+
function getAllCompiledStyles(params) {
|
|
526
|
+
return __async(this, null, function* () {
|
|
527
|
+
const { rawHtml, minify: minify2 = false, nodes } = params || {};
|
|
528
|
+
const srcStyles = getSrcStyles();
|
|
529
|
+
const nodesStyles = getNodesStyles(nodes);
|
|
530
|
+
const twCss = yield generateCSSFromHTMLWithTailwind(rawHtml);
|
|
531
|
+
const getSrcWrapper = (content) => `.${currentContext.packageNameSlug}{${content}}`;
|
|
532
|
+
const allNodesStyles = nodesStyles.map((node) => node.scssFinal).join("\n");
|
|
533
|
+
const result = getSrcWrapper(`${twCss}${srcStyles}${allNodesStyles}`);
|
|
534
|
+
return minify2 ? processCSS(result, rawHtml) : result;
|
|
535
|
+
});
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
// src/builder/editor/BuilderEditor.class.ts
|
|
539
|
+
var BuilderEditor = class {
|
|
540
|
+
constructor(params) {
|
|
541
|
+
__publicField(this, "params");
|
|
542
|
+
this.params = __spreadValues({ minify: false }, params);
|
|
543
|
+
}
|
|
544
|
+
getEditorIndexContent() {
|
|
545
|
+
return __async(this, null, function* () {
|
|
546
|
+
return `
|
|
547
|
+
import type { NodeAPI } from 'node-red';
|
|
548
|
+
${currentContext.listNodesFull.map((node) => `import ${node.pascalName} from '${node.editor.tsPath}';`).join("\n")}
|
|
549
|
+
|
|
550
|
+
declare const RED: NodeAPI;
|
|
551
|
+
|
|
552
|
+
${currentContext.listNodesFull.map((node) => `// @ts-ignore
|
|
553
|
+
window.RED.nodes.registerType('${node.name}', ${node.pascalName});`).join("\n")}
|
|
554
|
+
`.trim();
|
|
555
|
+
});
|
|
556
|
+
}
|
|
557
|
+
getBuiltScript() {
|
|
558
|
+
return __async(this, null, function* () {
|
|
559
|
+
const result = yield esbuild__default.default.build({
|
|
560
|
+
entryPoints: [currentContext.cacheDirFiles.editorIndex],
|
|
561
|
+
bundle: true,
|
|
562
|
+
platform: "browser",
|
|
563
|
+
format: "iife",
|
|
564
|
+
target: "es6",
|
|
565
|
+
sourcemap: false,
|
|
566
|
+
minify: this.params.minify,
|
|
567
|
+
minifyWhitespace: this.params.minify,
|
|
568
|
+
minifySyntax: this.params.minify,
|
|
569
|
+
minifyIdentifiers: this.params.minify,
|
|
570
|
+
legalComments: "none",
|
|
571
|
+
inject: [`${currentContext.currentPackagedDistPath}/editor/global-solid.ts`],
|
|
572
|
+
write: false,
|
|
573
|
+
loader: { ".ts": "ts" }
|
|
574
|
+
});
|
|
575
|
+
if (result.outputFiles && result.outputFiles.length > 0) {
|
|
576
|
+
return result.outputFiles[0].text;
|
|
577
|
+
}
|
|
578
|
+
return "";
|
|
579
|
+
});
|
|
580
|
+
}
|
|
581
|
+
prepareEditorIndex() {
|
|
582
|
+
return __async(this, null, function* () {
|
|
583
|
+
const js = yield this.getBuiltScript();
|
|
584
|
+
const html = yield getNodesHtml({
|
|
585
|
+
minify: this.params.minify,
|
|
586
|
+
nodes: currentContext.listNodesFull,
|
|
587
|
+
packageNameSlug: currentContext.packageNameSlug
|
|
588
|
+
});
|
|
589
|
+
const css = yield getAllCompiledStyles({
|
|
590
|
+
rawHtml: html.html,
|
|
591
|
+
minify: this.params.minify,
|
|
592
|
+
nodes: currentContext.listNodesFull
|
|
593
|
+
});
|
|
594
|
+
const builderDoc = new BuildDoc();
|
|
595
|
+
const docs = builderDoc.getAllDocContent();
|
|
596
|
+
const wrappedJs = `<script type="application/javascript">${js.trim()}</script>`;
|
|
597
|
+
const wrappedCss = `<style>${css}</style>`;
|
|
598
|
+
return `
|
|
599
|
+
${html.allWrappedHtml}
|
|
600
|
+
${wrappedCss}
|
|
601
|
+
${wrappedJs}
|
|
602
|
+
${docs}`.trim();
|
|
603
|
+
});
|
|
604
|
+
}
|
|
605
|
+
getEditorTask() {
|
|
606
|
+
return __async(this, null, function* () {
|
|
607
|
+
return this.getEditorIndexContent().then((content) => {
|
|
608
|
+
writeFile(`${currentContext.cacheDirFiles.editorIndex}`, content).then(() => {
|
|
609
|
+
this.prepareEditorIndex().then((contentFinalIndexHtml) => __async(this, null, function* () {
|
|
610
|
+
yield writeFile(
|
|
611
|
+
`${currentContext.pathDist}/${currentContext.config.nodes.editor.htmlName}.html`,
|
|
612
|
+
contentFinalIndexHtml
|
|
613
|
+
);
|
|
614
|
+
}));
|
|
615
|
+
});
|
|
616
|
+
});
|
|
617
|
+
});
|
|
618
|
+
}
|
|
619
|
+
};
|
|
620
|
+
function getWithContent(path3) {
|
|
621
|
+
return __async(this, null, function* () {
|
|
622
|
+
const codeLang = path3.split("/").pop().split(".").shift();
|
|
623
|
+
const content = yield fsPromise__default.default.readFile(path3, "utf-8");
|
|
624
|
+
return {
|
|
625
|
+
codeLang,
|
|
626
|
+
content
|
|
627
|
+
};
|
|
628
|
+
});
|
|
629
|
+
}
|
|
630
|
+
function getGlobalLocales() {
|
|
631
|
+
return __async(this, null, function* () {
|
|
632
|
+
const nodesList = currentContext.listNodesFullNames;
|
|
633
|
+
const srcLocales = currentContext.resolvedSrcLocalesPaths;
|
|
634
|
+
const srcLocalesWithContent = yield Promise.all(srcLocales.map(getWithContent));
|
|
635
|
+
const grouped = {};
|
|
636
|
+
nodesList.forEach((nodeName) => {
|
|
637
|
+
for (const { codeLang, content } of srcLocalesWithContent) {
|
|
638
|
+
if (!grouped[codeLang]) {
|
|
639
|
+
grouped[codeLang] = [];
|
|
640
|
+
}
|
|
641
|
+
grouped[codeLang].push(`"${nodeName}":${content}`);
|
|
642
|
+
}
|
|
643
|
+
});
|
|
644
|
+
let allContent = "";
|
|
645
|
+
for (const [lang, locales] of Object.entries(grouped)) {
|
|
646
|
+
const content = locales.map((innerContent) => innerContent).join(",").slice(0, -1);
|
|
647
|
+
allContent += `"${lang}":{${content}},`;
|
|
648
|
+
}
|
|
649
|
+
return `{${allContent.slice(0, -1)}}`;
|
|
650
|
+
});
|
|
651
|
+
}
|
|
652
|
+
function processNode(path3) {
|
|
653
|
+
return __async(this, null, function* () {
|
|
654
|
+
const cleanPath = path3.replace(`${currentContext.pathSrcNodesDir}${path2.sep}`, "");
|
|
655
|
+
const [nodeName, , fileName] = cleanPath.split(path2.sep);
|
|
656
|
+
const [codeLang] = fileName.split(".");
|
|
657
|
+
const content = yield fsPromise__default.default.readFile(path3, "utf-8");
|
|
658
|
+
return {
|
|
659
|
+
nodeName,
|
|
660
|
+
codeLang,
|
|
661
|
+
path: path3,
|
|
662
|
+
content
|
|
663
|
+
};
|
|
664
|
+
});
|
|
665
|
+
}
|
|
666
|
+
function getScopedNodesLocales() {
|
|
667
|
+
return __async(this, null, function* () {
|
|
668
|
+
const toto = fastGlob.globSync(`${currentContext.pathSrcNodesDir}/**/locales/*.json`);
|
|
669
|
+
const res = yield Promise.all(toto.map(processNode));
|
|
670
|
+
const grouped = {};
|
|
671
|
+
res.forEach(({ nodeName, codeLang, content }) => {
|
|
672
|
+
if (!grouped[codeLang]) {
|
|
673
|
+
grouped[codeLang] = [];
|
|
674
|
+
}
|
|
675
|
+
grouped[codeLang].push(`"${nodeName}":${content}`);
|
|
676
|
+
});
|
|
677
|
+
let allContent = "";
|
|
678
|
+
for (const [lang, locales] of Object.entries(grouped)) {
|
|
679
|
+
const content = locales.map((innerContent) => innerContent).join(",").slice(0, -1);
|
|
680
|
+
allContent += `"${lang}":{${content}},`;
|
|
681
|
+
}
|
|
682
|
+
return `{${allContent.slice(0, -1)}}`;
|
|
683
|
+
});
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
// src/builder/locales/getLocales.ts
|
|
687
|
+
function writeAllLocales() {
|
|
688
|
+
return __async(this, null, function* () {
|
|
689
|
+
const [globalLocales, scopedLocales] = yield Promise.all([getGlobalLocales(), getScopedNodesLocales()]);
|
|
690
|
+
const res = merge(JSON.parse(globalLocales), JSON.parse(scopedLocales));
|
|
691
|
+
const toResolveCreateDirs = [];
|
|
692
|
+
const toResolve = [];
|
|
693
|
+
for (const [folderName, locales] of Object.entries(res)) {
|
|
694
|
+
toResolveCreateDirs.push(createFolderIfNotExists(`${currentContext.pathDist}/locales/${folderName}`));
|
|
695
|
+
toResolve.push(writeFile(`${currentContext.pathDist}/locales/${folderName}/index.json`, JSON.stringify(locales)));
|
|
696
|
+
}
|
|
697
|
+
yield Promise.all(toResolveCreateDirs);
|
|
698
|
+
yield Promise.all(toResolve);
|
|
699
|
+
});
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
// src/builder/Builder.class.ts
|
|
703
|
+
var Builder = class {
|
|
704
|
+
constructor(params) {
|
|
705
|
+
__publicField(this, "params");
|
|
706
|
+
__publicField(this, "builderController");
|
|
707
|
+
__publicField(this, "builderEditor");
|
|
708
|
+
this.params = __spreadValues({ minify: false }, params);
|
|
709
|
+
this.builderController = new BuilderController({
|
|
710
|
+
minify: this.params.minify
|
|
711
|
+
});
|
|
712
|
+
this.builderEditor = new BuilderEditor({
|
|
713
|
+
minify: this.params.minify
|
|
714
|
+
});
|
|
715
|
+
}
|
|
716
|
+
prepare() {
|
|
717
|
+
createFolderIfNotExists(currentContext.pathLibCacheDir);
|
|
718
|
+
const runs = [
|
|
719
|
+
cleanPaths([currentContext.pathDist]),
|
|
720
|
+
writeFile(`${currentContext.pathLibCacheDir}/config.json`, JSON.stringify(currentContext.config, null, 2))
|
|
721
|
+
];
|
|
722
|
+
return Promise.all(runs);
|
|
723
|
+
}
|
|
724
|
+
buildAll() {
|
|
725
|
+
return __async(this, null, function* () {
|
|
726
|
+
yield this.prepare();
|
|
727
|
+
return Promise.all([
|
|
728
|
+
this.builderController.getControllerTask(),
|
|
729
|
+
this.builderEditor.getEditorTask(),
|
|
730
|
+
writeAllLocales()
|
|
731
|
+
]);
|
|
732
|
+
});
|
|
733
|
+
}
|
|
734
|
+
};
|
|
735
|
+
|
|
736
|
+
exports.Builder = Builder;
|
|
737
|
+
//# sourceMappingURL=index.cjs.map
|
|
738
|
+
//# sourceMappingURL=index.cjs.map
|