juice-email-cli 2.3.14 → 2.3.15
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/src/init.js +8 -4
- package/src/snippet.js +25 -33
package/package.json
CHANGED
package/src/init.js
CHANGED
|
@@ -5,7 +5,7 @@ const path = require('path');
|
|
|
5
5
|
const chalk = require('chalk');
|
|
6
6
|
const {
|
|
7
7
|
resolveEdmDir, loadMeta, findBrands, findTemplateVersions,
|
|
8
|
-
findSeriesDirs, findSnippetVariants, findConfigs,
|
|
8
|
+
findSeriesDirs, filterSeries, findSnippetVariants, findConfigs,
|
|
9
9
|
promptOutputName,
|
|
10
10
|
} = require('./snippet');
|
|
11
11
|
|
|
@@ -92,6 +92,7 @@ async function selectWithNav(message, choices, showBack) {
|
|
|
92
92
|
async function interactiveInit(edmDir, cwd) {
|
|
93
93
|
let step = 'brand';
|
|
94
94
|
let brand = null, version = null, series = null, variant = null;
|
|
95
|
+
let hadVariantStep = false; // track if variant step was actually shown
|
|
95
96
|
|
|
96
97
|
while (true) {
|
|
97
98
|
if (step === 'brand') {
|
|
@@ -122,7 +123,9 @@ async function interactiveInit(edmDir, cwd) {
|
|
|
122
123
|
}
|
|
123
124
|
|
|
124
125
|
if (step === 'series') {
|
|
125
|
-
|
|
126
|
+
let allSeries = findSeriesDirs(brand.path);
|
|
127
|
+
// Apply template version series filtering (allow/block in _meta.yaml)
|
|
128
|
+
allSeries = filterSeries(allSeries, version.meta);
|
|
126
129
|
if (allSeries.length === 0) {
|
|
127
130
|
series = null;
|
|
128
131
|
step = 'copy';
|
|
@@ -150,6 +153,7 @@ async function interactiveInit(edmDir, cwd) {
|
|
|
150
153
|
step = 'copy';
|
|
151
154
|
continue;
|
|
152
155
|
}
|
|
156
|
+
hadVariantStep = true;
|
|
153
157
|
const choices = variants.map(v => ({
|
|
154
158
|
name: formatName(v.meta, v.name) + (v.meta.description ? ' — ' + chalk.dim(v.meta.description) : ''),
|
|
155
159
|
value: v,
|
|
@@ -218,7 +222,7 @@ async function interactiveInit(edmDir, cwd) {
|
|
|
218
222
|
mainChoices,
|
|
219
223
|
true
|
|
220
224
|
);
|
|
221
|
-
if (action === 'back') { step =
|
|
225
|
+
if (action === 'back') { step = hadVariantStep ? 'variant' : (series ? 'series' : 'version'); break; }
|
|
222
226
|
if (action === 'exit') { console.log(chalk.gray('已退出。\n')); return; }
|
|
223
227
|
if (action === 'edit') {
|
|
224
228
|
const { checkbox } = await import('@inquirer/prompts');
|
|
@@ -234,7 +238,7 @@ async function interactiveInit(edmDir, cwd) {
|
|
|
234
238
|
// fall through to confirmation below
|
|
235
239
|
} else if (selected.length === 0) {
|
|
236
240
|
console.log(chalk.gray('未选择任何内容。\n'));
|
|
237
|
-
step =
|
|
241
|
+
step = hadVariantStep ? 'variant' : (series ? 'series' : 'version');
|
|
238
242
|
break;
|
|
239
243
|
}
|
|
240
244
|
|
package/src/snippet.js
CHANGED
|
@@ -204,24 +204,6 @@ function findConfigs(variantDir, sourceLabel) {
|
|
|
204
204
|
* Collect configs from multiple directories, deduplicating by path.
|
|
205
205
|
* Returns { name, path, isOptimal, source }[].
|
|
206
206
|
*/
|
|
207
|
-
function collectConfigs(dirs) {
|
|
208
|
-
const seen = new Set();
|
|
209
|
-
const result = [];
|
|
210
|
-
for (const { dir, label, markOptimal } of dirs) {
|
|
211
|
-
if (!fs.existsSync(dir)) continue;
|
|
212
|
-
const configs = findConfigs(dir, label);
|
|
213
|
-
for (const c of configs) {
|
|
214
|
-
if (seen.has(c.path)) continue;
|
|
215
|
-
seen.add(c.path);
|
|
216
|
-
if (markOptimal && c.name === 'juice.yaml') {
|
|
217
|
-
c.isOptimal = true;
|
|
218
|
-
}
|
|
219
|
-
result.push(c);
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
return result;
|
|
223
|
-
}
|
|
224
|
-
|
|
225
207
|
function findFiles(dir, regex) {
|
|
226
208
|
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
227
209
|
return entries
|
|
@@ -425,11 +407,11 @@ async function assembleSnippet({ snippetPath, templatePath, config, cwd, outputB
|
|
|
425
407
|
const outPaths = resolveSnippetOutputPaths(outputBaseName, cwd);
|
|
426
408
|
const variables = Object.assign({}, config.variables || {});
|
|
427
409
|
|
|
428
|
-
// 1. 未渲染的片段插入模板 → .raw.html
|
|
410
|
+
// 1. 未渲染的片段插入模板 → .raw.html
|
|
429
411
|
const rawMarkup = insertIntoContent(templateHtml, snippetRaw);
|
|
430
412
|
fs.writeFileSync(outPaths.raw, rawMarkup, 'utf8');
|
|
431
413
|
|
|
432
|
-
// 2. Mustache
|
|
414
|
+
// 2. Mustache 渲染 → .html
|
|
433
415
|
const originalEscape = Mustache.escape;
|
|
434
416
|
let renderedHtml;
|
|
435
417
|
try {
|
|
@@ -442,34 +424,45 @@ async function assembleSnippet({ snippetPath, templatePath, config, cwd, outputB
|
|
|
442
424
|
}
|
|
443
425
|
fs.writeFileSync(outPaths.normal, renderedHtml, 'utf8');
|
|
444
426
|
|
|
445
|
-
// 3.
|
|
427
|
+
// 3. Juice CSS 内联 → .output.html
|
|
446
428
|
const templateDir = path.dirname(templatePath);
|
|
447
429
|
const extraCss = collectExtraCss(templateDir, config);
|
|
448
430
|
const juiceOpts = Object.assign({}, config.juice || {});
|
|
449
431
|
delete juiceOpts.extraCssFiles;
|
|
450
|
-
|
|
432
|
+
let processed;
|
|
433
|
+
try {
|
|
434
|
+
processed = juice(renderedHtml, { ...juiceOpts, extraCss });
|
|
435
|
+
} catch (err) {
|
|
436
|
+
throw new Error(`CSS 内联失败:${err.message}`);
|
|
437
|
+
}
|
|
451
438
|
fs.writeFileSync(outPaths.output, processed, 'utf8');
|
|
452
439
|
|
|
453
440
|
// 4. 压缩 → .minified.html
|
|
454
|
-
|
|
441
|
+
let minified;
|
|
442
|
+
try {
|
|
443
|
+
minified = await minifyHtml(processed, config.minify);
|
|
444
|
+
} catch (err) {
|
|
445
|
+
throw new Error(`压缩失败:${err.message}`);
|
|
446
|
+
}
|
|
455
447
|
fs.writeFileSync(outPaths.minified, minified, 'utf8');
|
|
456
448
|
|
|
457
449
|
// 5. 报告
|
|
450
|
+
const rel = (p) => './' + path.relative(cwd, p);
|
|
458
451
|
const layers = config._layers || [];
|
|
459
|
-
const layerLines = layers
|
|
460
|
-
.map((l) => ` ${chalk.gray('·')} ${l.label}`)
|
|
461
|
-
|
|
452
|
+
const layerLines = layers.length > 0
|
|
453
|
+
? layers.map((l) => ` ${chalk.gray('·')} ${l.label}`).join('\n') + '\n'
|
|
454
|
+
: '';
|
|
462
455
|
|
|
463
456
|
console.log(
|
|
464
457
|
chalk.green('\n✔ 片段组装完成') + '\n' +
|
|
465
458
|
` ${chalk.bold('片段:')} ${chalk.cyan(snippetPath)}\n` +
|
|
466
459
|
` ${chalk.bold('模板:')} ${chalk.cyan(templatePath)}\n` +
|
|
467
|
-
` ${chalk.bold('配置层(低→高):')}\n${layerLines}
|
|
460
|
+
` ${chalk.bold('配置层(低→高):')}\n${layerLines}` +
|
|
468
461
|
` ${chalk.bold('输出:')}\n` +
|
|
469
|
-
` ${chalk.green('·')} 原始组装 ${chalk.cyan(outPaths.raw)}
|
|
470
|
-
` ${chalk.green('·')} 已渲染 ${chalk.cyan(outPaths.normal)} ${chalk.gray(
|
|
471
|
-
` ${chalk.green('·')} 内联后 ${chalk.cyan(outPaths.output)} ${chalk.gray(
|
|
472
|
-
` ${chalk.green('·')} 压缩版 ${chalk.cyan(outPaths.minified)} ${chalk.gray(
|
|
462
|
+
` ${chalk.green('·')} 原始组装 ${chalk.cyan(rel(outPaths.raw))} ${chalk.gray(fmtSize(rawMarkup))}\n` +
|
|
463
|
+
` ${chalk.green('·')} 已渲染 ${chalk.cyan(rel(outPaths.normal))} ${chalk.gray(fmtSize(renderedHtml))}\n` +
|
|
464
|
+
` ${chalk.green('·')} 内联后 ${chalk.cyan(rel(outPaths.output))} ${chalk.gray(fmtSize(processed))}\n` +
|
|
465
|
+
` ${chalk.green('·')} 压缩版 ${chalk.cyan(rel(outPaths.minified))} ${chalk.gray(fmtSize(minified) + ',节省 ' + savings(processed, minified))}`
|
|
473
466
|
);
|
|
474
467
|
|
|
475
468
|
return outPaths;
|
|
@@ -715,7 +708,7 @@ async function promptConfirm(summary) {
|
|
|
715
708
|
console.log(` 片段变体: ${chalk.green(summary.variantName)} ${chalk.gray(`(${summary.variant})`)}`);
|
|
716
709
|
console.log(` 配置 YAML: ${chalk.green(summary.configFile)}`);
|
|
717
710
|
console.log(chalk.gray('───────────────────────────────────────────'));
|
|
718
|
-
console.log(` 输出目录: ${chalk.cyan(
|
|
711
|
+
console.log(` 输出目录: ${chalk.cyan('./')}`);
|
|
719
712
|
console.log(` 输出文件名: ${chalk.green(summary.outputBaseName)}`);
|
|
720
713
|
console.log(` 输出文件:`);
|
|
721
714
|
console.log(` ${chalk.green('·')} ${path.basename(outPaths.raw)} ${chalk.gray('(未渲染,无 CSS 内联)')}`);
|
|
@@ -969,7 +962,6 @@ module.exports = {
|
|
|
969
962
|
findHtmlFiles,
|
|
970
963
|
findYamlFiles,
|
|
971
964
|
findLocalConfig,
|
|
972
|
-
collectConfigs,
|
|
973
965
|
getBrand,
|
|
974
966
|
filterSeries,
|
|
975
967
|
// config
|