resuml 1.5.1 → 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 +88 -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;
|
|
@@ -157,11 +240,7 @@ async function main() {
|
|
|
157
240
|
export const extname = (p) => { const m = p.match(/\\.[^.]+$/); return m ? m[0] : ''; };
|
|
158
241
|
export default { join, resolve, dirname, basename, extname };
|
|
159
242
|
`);
|
|
160
|
-
|
|
161
|
-
export const readFileSync = () => '';
|
|
162
|
-
export const existsSync = () => false;
|
|
163
|
-
export default { readFileSync, existsSync };
|
|
164
|
-
`);
|
|
243
|
+
// fs shim is generated per-theme in bundleTheme() with embedded file contents
|
|
165
244
|
writeFileSync(resolve(shimsDir, 'url.js'), `
|
|
166
245
|
export const URL = globalThis.URL;
|
|
167
246
|
export const URLSearchParams = globalThis.URLSearchParams;
|
|
@@ -236,7 +315,7 @@ async function main() {
|
|
|
236
315
|
} catch {}
|
|
237
316
|
|
|
238
317
|
// Bundle it
|
|
239
|
-
const success = await bundleTheme(theme.name, theme.packageName);
|
|
318
|
+
const success = await bundleTheme(theme.name, theme.packageName, shimsDir);
|
|
240
319
|
|
|
241
320
|
if (success) {
|
|
242
321
|
const outFile = resolve(THEMES_DIR, `${theme.name}.js`);
|