resuml 1.5.0 → 1.5.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/package.json +1 -1
- package/scripts/bundle-themes.js +95 -9
package/package.json
CHANGED
package/scripts/bundle-themes.js
CHANGED
|
@@ -15,10 +15,10 @@
|
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
17
|
import { build } from 'esbuild';
|
|
18
|
-
import { resolve, dirname } from 'path';
|
|
18
|
+
import { resolve, dirname, join } from 'path';
|
|
19
19
|
import { fileURLToPath } from 'url';
|
|
20
20
|
import { execSync } from 'child_process';
|
|
21
|
-
import { mkdirSync, writeFileSync, existsSync, readFileSync } from 'fs';
|
|
21
|
+
import { mkdirSync, writeFileSync, existsSync, readFileSync, readdirSync } from 'fs';
|
|
22
22
|
|
|
23
23
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
24
24
|
const THEMES_DIR = resolve(__dirname, '../docs/themes');
|
|
@@ -81,7 +81,90 @@ async function discoverThemes() {
|
|
|
81
81
|
return themes;
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
-
|
|
84
|
+
/** Recursively collect text files from a theme directory for embedding in the fs shim. */
|
|
85
|
+
function collectThemeFiles(themeDir) {
|
|
86
|
+
const files = {};
|
|
87
|
+
const dirs = {};
|
|
88
|
+
|
|
89
|
+
function walk(dir, relPrefix = '') {
|
|
90
|
+
let entries;
|
|
91
|
+
try { entries = readdirSync(dir, { withFileTypes: true }); }
|
|
92
|
+
catch { return; }
|
|
93
|
+
|
|
94
|
+
const childNames = [];
|
|
95
|
+
for (const entry of entries) {
|
|
96
|
+
if (entry.name === 'node_modules' || entry.name.startsWith('.')) continue;
|
|
97
|
+
childNames.push(entry.name);
|
|
98
|
+
const full = join(dir, entry.name);
|
|
99
|
+
const rel = relPrefix ? `${relPrefix}/${entry.name}` : entry.name;
|
|
100
|
+
|
|
101
|
+
if (entry.isDirectory()) {
|
|
102
|
+
walk(full, rel);
|
|
103
|
+
} else {
|
|
104
|
+
const ext = (entry.name.split('.').pop() || '').toLowerCase();
|
|
105
|
+
if (['css', 'hbs', 'html', 'json', 'txt', 'handlebars', 'mustache'].includes(ext)) {
|
|
106
|
+
try { files[rel] = readFileSync(full, 'utf-8'); }
|
|
107
|
+
catch { /* skip unreadable */ }
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
dirs[relPrefix || '.'] = childNames;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
walk(themeDir);
|
|
115
|
+
return { files, dirs };
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/** Generate an fs shim that embeds the theme's files so readFileSync/readdirSync work at runtime. */
|
|
119
|
+
function generateThemeFsShim(themeFiles) {
|
|
120
|
+
const { files, dirs } = themeFiles;
|
|
121
|
+
return `
|
|
122
|
+
const __files = ${JSON.stringify(files)};
|
|
123
|
+
const __dirs = ${JSON.stringify(dirs)};
|
|
124
|
+
|
|
125
|
+
function matchFile(path) {
|
|
126
|
+
const clean = path.replace(/\\/+/g, '/').replace(/^\\/+/, '');
|
|
127
|
+
if (__files[clean] !== undefined) return __files[clean];
|
|
128
|
+
for (const key of Object.keys(__files)) {
|
|
129
|
+
if (clean.endsWith('/' + key) || clean.endsWith(key)) return __files[key];
|
|
130
|
+
}
|
|
131
|
+
return undefined;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function matchDir(path) {
|
|
135
|
+
const clean = path.replace(/\\/+/g, '/').replace(/^\\/+/, '');
|
|
136
|
+
if (__dirs[clean] !== undefined) return __dirs[clean];
|
|
137
|
+
for (const key of Object.keys(__dirs)) {
|
|
138
|
+
if (clean.endsWith('/' + key) || clean.endsWith(key)) return __dirs[key];
|
|
139
|
+
}
|
|
140
|
+
return undefined;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
export const readFileSync = (path, encoding) => {
|
|
144
|
+
const r = matchFile(path);
|
|
145
|
+
return r !== undefined ? r : '';
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
export const readdirSync = (path) => {
|
|
149
|
+
const r = matchDir(path);
|
|
150
|
+
return r !== undefined ? r : [];
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
export const existsSync = (path) => {
|
|
154
|
+
return matchFile(path) !== undefined || matchDir(path) !== undefined;
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
export default { readFileSync, readdirSync, existsSync };
|
|
158
|
+
`;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
async function bundleTheme(shortName, packageName, shimsDir) {
|
|
162
|
+
// Generate a theme-specific fs shim with embedded file contents so that
|
|
163
|
+
// readFileSync / readdirSync return real CSS, templates, and partials at runtime.
|
|
164
|
+
const themeDir = resolve(__dirname, `../node_modules/${packageName}`);
|
|
165
|
+
const themeFiles = collectThemeFiles(themeDir);
|
|
166
|
+
writeFileSync(resolve(shimsDir, 'fs.js'), generateThemeFsShim(themeFiles));
|
|
167
|
+
|
|
85
168
|
const entryContent = `
|
|
86
169
|
import * as themeNs from '${packageName}';
|
|
87
170
|
const _t = themeNs.default ?? themeNs;
|
|
@@ -100,6 +183,13 @@ async function bundleTheme(shortName, packageName) {
|
|
|
100
183
|
format: 'esm',
|
|
101
184
|
target: 'es2022',
|
|
102
185
|
platform: 'browser',
|
|
186
|
+
// Use 'require' condition so packages like underscore/lodash resolve to their
|
|
187
|
+
// CJS/UMD builds (which export a callable function) instead of their ESM builds
|
|
188
|
+
// (which export a namespace object that breaks _(collection) call syntax).
|
|
189
|
+
conditions: ['browser', 'require', 'default'],
|
|
190
|
+
// Prefer the CJS 'main' field over the ESM 'module' field for packages
|
|
191
|
+
// that don't use the exports map (older packages).
|
|
192
|
+
mainFields: ['browser', 'main'],
|
|
103
193
|
outfile: resolve(THEMES_DIR, `${shortName}.js`),
|
|
104
194
|
define: {
|
|
105
195
|
'process.env.NODE_ENV': '"production"',
|
|
@@ -150,11 +240,7 @@ async function main() {
|
|
|
150
240
|
export const extname = (p) => { const m = p.match(/\\.[^.]+$/); return m ? m[0] : ''; };
|
|
151
241
|
export default { join, resolve, dirname, basename, extname };
|
|
152
242
|
`);
|
|
153
|
-
|
|
154
|
-
export const readFileSync = () => '';
|
|
155
|
-
export const existsSync = () => false;
|
|
156
|
-
export default { readFileSync, existsSync };
|
|
157
|
-
`);
|
|
243
|
+
// fs shim is generated per-theme in bundleTheme() with embedded file contents
|
|
158
244
|
writeFileSync(resolve(shimsDir, 'url.js'), `
|
|
159
245
|
export const URL = globalThis.URL;
|
|
160
246
|
export const URLSearchParams = globalThis.URLSearchParams;
|
|
@@ -229,7 +315,7 @@ async function main() {
|
|
|
229
315
|
} catch {}
|
|
230
316
|
|
|
231
317
|
// Bundle it
|
|
232
|
-
const success = await bundleTheme(theme.name, theme.packageName);
|
|
318
|
+
const success = await bundleTheme(theme.name, theme.packageName, shimsDir);
|
|
233
319
|
|
|
234
320
|
if (success) {
|
|
235
321
|
const outFile = resolve(THEMES_DIR, `${theme.name}.js`);
|