juice-email-cli 2.4.6 → 2.4.7
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/edm/elabscience/series/activity/_meta.yaml +2 -0
- package/edm/elabscience/series/activity/default/_meta.yaml +2 -0
- package/edm/elabscience/series/activity/default/juice.yaml +34 -0
- package/edm/elabscience/series/activity/default/snippet.html +9 -0
- package/package.json +2 -2
- package/src/index.js +80 -1
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# juice.yaml - 用户配置文件示例
|
|
2
|
+
#
|
|
3
|
+
# 放置位置(优先级从低到高):
|
|
4
|
+
# ~/juice.yaml ← 用户主目录,对所有项目生效
|
|
5
|
+
# <模板文件目录>/juice.yaml ← 仅对当前项目生效(推荐)
|
|
6
|
+
# juice -c <此文件> ← 命令行指定
|
|
7
|
+
#
|
|
8
|
+
# 所有配置项均与 CLI 内置默认值深度合并,未填写的字段自动使用内置值。
|
|
9
|
+
# 完整默认配置见:<CLI安装目录>/defaults/juice.yaml
|
|
10
|
+
|
|
11
|
+
# ─── 模板变量(Mustache 语法)────────────────────────────────────────────────
|
|
12
|
+
variables:
|
|
13
|
+
banner:
|
|
14
|
+
pc: https://files.elabscience.cn/assets/images/article/202604221646/pc.webp
|
|
15
|
+
mobile: https://files.elabscience.cn/assets/images/article/202604221646/mobile.webp
|
|
16
|
+
|
|
17
|
+
information:
|
|
18
|
+
image: https://elabcomfile.oss-us-west-1.aliyuncs.com/edm/202605211020/CD38-NAD.webp
|
|
19
|
+
content: "This study identifies the CD38-NAD<sup>+</sup> axis as an immunometabolic checkpoint in ITP. Anti-CD38 antibodies deplete NAD<sup>+</sup>, driving M1 macrophages and FcγRI upregulation, which increases platelet phagocytosis. Restoring NAD<sup>+</sup> via CD38 inhibition or NMN reprograms macrophages to a resting state and blocks platelet destruction without affecting humoral immunity. In 25 refractory ITP patients, low-dose NMN (450 mg bid × 2 weeks) was well tolerated: 20% achieved platelets ≥50×10<sup>9</sup>/L, and 52% maintained response at week 8, with stable immunoglobulin levels. Thus, targeting CD38-NAD<sup>+</sup> metabolism offers a non-antibody-depleting therapeutic strategy."
|
|
20
|
+
link: https://www.procellsystem.com/resources/publications
|
|
21
|
+
buttonText: View More Publications
|
|
22
|
+
summary: Human plasma and mouse cell supernatant iNOS level were measured using Elabscience<sup>®</sup> Human/Mouse NOS2/iNOS(Nitric Oxide Synthase 2, Inducible) ELISA Kit, respectively.
|
|
23
|
+
|
|
24
|
+
# ── 产品列表 ────────────────────────────────────────────────────────────────
|
|
25
|
+
# 使用 {{#productLists}}...{{/productLists}} 循环遍历
|
|
26
|
+
# {{#productLists}}{{name}}{{catNo}}{{/productLists}}
|
|
27
|
+
productLists:
|
|
28
|
+
- name: Human NOS2/iNOS(Nitric Oxide Synthase 2, Inducible) ELISA Kit
|
|
29
|
+
catNo: E-EL-H0753
|
|
30
|
+
link: https://www.elabscience.com/p/human-nos2-inos-nitric-oxide-synthase-2-inducible-elisa-kit--e-el-h0753
|
|
31
|
+
|
|
32
|
+
- name: Mouse NOS2/iNOS(Nitric Oxide Synthase 2, Inducible) ELISA Kit
|
|
33
|
+
catNo: E-EL-M0696
|
|
34
|
+
link: https://www.elabscience.com/p/mouse-nos2-inos-nitric-oxide-synthase-2-inducible-elisa-kit--e-el-m0696
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
{{#banner}}
|
|
2
|
+
<div>
|
|
3
|
+
<img class="{{#banner.mobile}}d-none d-md-block{{/banner.mobile}}{{^banner.mobile}}d-block{{/banner.mobile}} img-fluid m-auto border-0" src="{{banner.pc}}" />
|
|
4
|
+
|
|
5
|
+
{{#banner.mobile}}
|
|
6
|
+
<img class="d-block d-md-none img-fluid m-auto border-0" src="{{banner.mobile}}" />
|
|
7
|
+
{{/banner.mobile}}
|
|
8
|
+
</div>
|
|
9
|
+
{{/banner}}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "juice-email-cli",
|
|
3
|
-
"version": "2.4.
|
|
3
|
+
"version": "2.4.7",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "CLI tool to generate email-client-compatible HTML with juice (CSS inlining) + Mustache templating + minification",
|
|
6
6
|
"main": "src/index.js",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"url": "https://github.com/GuoSirius/juice-cli/issues"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@inquirer/prompts": "^8.
|
|
40
|
+
"@inquirer/prompts": "^8.5.0",
|
|
41
41
|
"chalk": "^5.6.2",
|
|
42
42
|
"commander": "^14.0.3",
|
|
43
43
|
"html-minifier-terser": "^7.2.0",
|
package/src/index.js
CHANGED
|
@@ -65,6 +65,71 @@ export function findConfigs(configPath, inputFile) {
|
|
|
65
65
|
return { highPriorityPath, homePath: resolveHomeConfig() };
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
+
// ─── 列出目录下所有配置文件 ─────────────────────────────────────────────────────
|
|
69
|
+
|
|
70
|
+
function findYamlConfigFiles(dir) {
|
|
71
|
+
if (!fs.existsSync(dir)) return [];
|
|
72
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
73
|
+
return entries
|
|
74
|
+
.filter(e => e.isFile() && /\.ya?ml$/i.test(e.name) && e.name !== '_meta.yaml' && e.name !== '_meta.yml')
|
|
75
|
+
.map(e => ({ name: e.name, path: path.join(dir, e.name) }));
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
async function resolveProjectConfig(inputFile) {
|
|
79
|
+
const inputDir = path.dirname(path.resolve(inputFile));
|
|
80
|
+
const yamlFiles = findYamlConfigFiles(inputDir);
|
|
81
|
+
|
|
82
|
+
if (yamlFiles.length === 0) return null;
|
|
83
|
+
|
|
84
|
+
if (yamlFiles.length === 1) {
|
|
85
|
+
const name = yamlFiles[0].name;
|
|
86
|
+
if (name === 'juice.yaml' || name === 'juice.yml') {
|
|
87
|
+
return yamlFiles[0].path;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const { select, input } = await import('@inquirer/prompts');
|
|
92
|
+
|
|
93
|
+
const choices = yamlFiles.map(f => {
|
|
94
|
+
const isOptimal = f.name === 'juice.yaml';
|
|
95
|
+
if (isOptimal) {
|
|
96
|
+
return {
|
|
97
|
+
name: `${chalk.green('●')} ${f.name} ${chalk.green('(最优配对)')}`,
|
|
98
|
+
value: { type: 'file', path: f.path },
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
return {
|
|
102
|
+
name: ` ${f.name}`,
|
|
103
|
+
value: { type: 'file', path: f.path },
|
|
104
|
+
};
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
const defaultIdx = yamlFiles.findIndex(f => f.name === 'juice.yaml');
|
|
108
|
+
|
|
109
|
+
choices.push(
|
|
110
|
+
{ name: ' [自定义] 输入其他路径...', value: { type: 'custom' } },
|
|
111
|
+
{ name: ' [跳过] 不使用项目配置', value: { type: 'skip' } },
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
const result = await select({
|
|
115
|
+
message: '请选择配置文件:',
|
|
116
|
+
choices,
|
|
117
|
+
default: defaultIdx >= 0 ? defaultIdx : 0,
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
if (result.type === 'custom') {
|
|
121
|
+
const customPath = await input({ message: '请输入配置文件路径:' });
|
|
122
|
+
const resolved = path.resolve(customPath);
|
|
123
|
+
if (!fs.existsSync(resolved)) {
|
|
124
|
+
throw new Error(`指定的配置文件不存在:${resolved}`);
|
|
125
|
+
}
|
|
126
|
+
return resolved;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (result.type === 'skip') return null;
|
|
130
|
+
return result.path;
|
|
131
|
+
}
|
|
132
|
+
|
|
68
133
|
// ─── 配置文件加载 ─────────────────────────────────────────────────────────────
|
|
69
134
|
|
|
70
135
|
export function loadYaml(filePath) {
|
|
@@ -207,7 +272,21 @@ export async function run({ file, config: configPath }) {
|
|
|
207
272
|
process.exit(1);
|
|
208
273
|
}
|
|
209
274
|
|
|
210
|
-
|
|
275
|
+
let highPriorityPath = null;
|
|
276
|
+
|
|
277
|
+
if (configPath) {
|
|
278
|
+
const resolved = path.resolve(configPath);
|
|
279
|
+
if (!fs.existsSync(resolved)) {
|
|
280
|
+
throw new Error(`指定的配置文件不存在:${resolved}`);
|
|
281
|
+
}
|
|
282
|
+
highPriorityPath = resolved;
|
|
283
|
+
} else {
|
|
284
|
+
spinner.stop();
|
|
285
|
+
highPriorityPath = await resolveProjectConfig(inputFile);
|
|
286
|
+
spinner.start();
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
const homePath = resolveHomeConfig();
|
|
211
290
|
const { config, layers } = buildConfig(highPriorityPath, homePath);
|
|
212
291
|
const encoding = (config.output && config.output.encoding) || 'utf8';
|
|
213
292
|
|