@v1hz/md2docx 2.2.0 → 2.4.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/README.md +102 -55
- package/config/config.json +5 -0
- package/config/config.schema.json +26 -0
- package/config/lua/limit-image-size.lua +93 -0
- package/config/style-config.json +20 -0
- package/config/style-config.schema.json +68 -0
- package/config/{style.json → style-raw.json} +14 -14
- package/dist/index.js +445 -75
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -103482,7 +103482,7 @@ Actual: ` + parser.attribValue);
|
|
|
103482
103482
|
var options;
|
|
103483
103483
|
var pureJsParser = true;
|
|
103484
103484
|
var currentElement;
|
|
103485
|
-
function
|
|
103485
|
+
function validateOptions2(userOptions) {
|
|
103486
103486
|
options = helper.copyOptions(userOptions);
|
|
103487
103487
|
helper.ensureFlagExists("ignoreDeclaration", options);
|
|
103488
103488
|
helper.ensureFlagExists("ignoreInstruction", options);
|
|
@@ -103730,7 +103730,7 @@ Actual: ` + parser.attribValue);
|
|
|
103730
103730
|
var parser = pureJsParser ? sax.parser(true, {}) : parser = new expat.Parser("UTF-8");
|
|
103731
103731
|
var result = {};
|
|
103732
103732
|
currentElement = result;
|
|
103733
|
-
options =
|
|
103733
|
+
options = validateOptions2(userOptions);
|
|
103734
103734
|
if (pureJsParser) {
|
|
103735
103735
|
parser.opt = { strictEntities: true };
|
|
103736
103736
|
parser.onopentag = onStartElement;
|
|
@@ -103764,13 +103764,13 @@ Actual: ` + parser.attribValue);
|
|
|
103764
103764
|
require_xml2json = /* @__PURE__ */ __commonJSMin((exports, module) => {
|
|
103765
103765
|
var helper = require_options_helper();
|
|
103766
103766
|
var xml2js = require_xml2js();
|
|
103767
|
-
function
|
|
103767
|
+
function validateOptions2(userOptions) {
|
|
103768
103768
|
var options = helper.copyOptions(userOptions);
|
|
103769
103769
|
helper.ensureSpacesExists(options);
|
|
103770
103770
|
return options;
|
|
103771
103771
|
}
|
|
103772
103772
|
module.exports = function(xml, userOptions) {
|
|
103773
|
-
var options =
|
|
103773
|
+
var options = validateOptions2(userOptions), js = xml2js(xml, options), json, parentKey = "compact" in options && options.compact ? "_parent" : "parent";
|
|
103774
103774
|
if ("addParent" in options && options.addParent)
|
|
103775
103775
|
json = JSON.stringify(js, function(k, v) {
|
|
103776
103776
|
return k === parentKey ? "_" : v;
|
|
@@ -103784,7 +103784,7 @@ Actual: ` + parser.attribValue);
|
|
|
103784
103784
|
var helper = require_options_helper();
|
|
103785
103785
|
var isArray = require_array_helper().isArray;
|
|
103786
103786
|
var currentElement, currentElementName;
|
|
103787
|
-
function
|
|
103787
|
+
function validateOptions2(userOptions) {
|
|
103788
103788
|
var options = helper.copyOptions(userOptions);
|
|
103789
103789
|
helper.ensureFlagExists("ignoreDeclaration", options);
|
|
103790
103790
|
helper.ensureFlagExists("ignoreInstruction", options);
|
|
@@ -104064,7 +104064,7 @@ Actual: ` + parser.attribValue);
|
|
|
104064
104064
|
return xml.join("");
|
|
104065
104065
|
}
|
|
104066
104066
|
module.exports = function(js, options) {
|
|
104067
|
-
options =
|
|
104067
|
+
options = validateOptions2(options);
|
|
104068
104068
|
var xml = [];
|
|
104069
104069
|
currentElement = js;
|
|
104070
104070
|
currentElementName = "_root_";
|
|
@@ -128401,7 +128401,7 @@ import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
|
128401
128401
|
// package.json
|
|
128402
128402
|
var package_default = {
|
|
128403
128403
|
name: "@v1hz/md2docx",
|
|
128404
|
-
version: "2.
|
|
128404
|
+
version: "2.4.0",
|
|
128405
128405
|
description: "基于 pandoc 的 Markdown 转 Word 工具,自动格式化 Markdown,支持自定义样式,AI 友好,用户友好。",
|
|
128406
128406
|
keywords: [
|
|
128407
128407
|
"converter",
|
|
@@ -128471,8 +128471,8 @@ var package_default = {
|
|
|
128471
128471
|
// src/cli.ts
|
|
128472
128472
|
function createProgram(version, actions) {
|
|
128473
128473
|
const program2 = new Command;
|
|
128474
|
-
program2.name("md2docx").description("将 Markdown 转换为 Word 文档").version(version, "-v, --version", "显示版本号").helpOption("-h, --help", "显示帮助").helpCommand(false).showHelpAfterError("使用 --help 查看帮助").showSuggestionAfterError().enablePositionalOptions().argument("[markdown]", "Markdown 文件(仅无其他转换选项时)").option("-f, --file <path>", "Markdown 文件").option("-c, --config <path>", "自定义配置文件").option("-
|
|
128475
|
-
const hasAdditionalOptions = options.config !== undefined || options.
|
|
128474
|
+
program2.name("md2docx").description("将 Markdown 转换为 Word 文档").version(version, "-v, --version", "显示版本号").helpOption("-h, --help", "显示帮助").helpCommand(false).showHelpAfterError("使用 --help 查看帮助").showSuggestionAfterError().enablePositionalOptions().argument("[markdown]", "Markdown 文件(仅无其他转换选项时)").option("-f, --file <path>", "Markdown 文件").option("-c, --config <path>", "自定义配置文件").option("--style-raw <path>", "自定义底层 Word 样式").option("--style-config <path>", "自定义语义化样式配置").option("-o, --output <path>", "输出 DOCX 文件").action(async function(markdown, options) {
|
|
128475
|
+
const hasAdditionalOptions = options.config !== undefined || options.styleRaw !== undefined || options.styleConfig !== undefined || options.output !== undefined;
|
|
128476
128476
|
if (markdown !== undefined) {
|
|
128477
128477
|
if (options.file !== undefined || hasAdditionalOptions) {
|
|
128478
128478
|
this.error("位置参数不能与转换选项同时使用;使用选项时请通过 -f, --file 指定 Markdown 文件");
|
|
@@ -128493,11 +128493,13 @@ function createProgram(version, actions) {
|
|
|
128493
128493
|
this.help({ error: true });
|
|
128494
128494
|
});
|
|
128495
128495
|
exportCommand.exitOverride();
|
|
128496
|
-
const exportConfigCommand = exportCommand.command("config").description("导出默认配置").helpOption("-h, --help", "显示帮助").option("-o, --output <path>", "输出 JSON 文件,默认 ./config.json").
|
|
128496
|
+
const exportConfigCommand = exportCommand.command("config").description("导出默认配置").helpOption("-h, --help", "显示帮助").option("-o, --output <path>", "输出 JSON 文件,默认 ./config.json").action(actions.exportConfig);
|
|
128497
128497
|
exportConfigCommand.exitOverride();
|
|
128498
|
-
const
|
|
128499
|
-
|
|
128500
|
-
const
|
|
128498
|
+
const exportStyleRawCommand = exportCommand.command("style-raw").description("导出默认底层 Word 样式,或从 DOCX 提取底层样式").helpOption("-h, --help", "显示帮助").option("-f, --file <path>", "用于提取底层样式的 DOCX 文件").option("-o, --output <path>", "输出 JSON 文件").action(actions.exportStyleRaw);
|
|
128499
|
+
exportStyleRawCommand.exitOverride();
|
|
128500
|
+
const exportStyleConfigCommand = exportCommand.command("style-config").description("导出默认语义化样式配置").helpOption("-h, --help", "显示帮助").option("-o, --output <path>", "输出 JSON 文件,默认 ./style-config.json").action(actions.exportStyleConfig);
|
|
128501
|
+
exportStyleConfigCommand.exitOverride();
|
|
128502
|
+
const formatCommand = program2.command("format").description("预处理并格式化 Markdown").helpOption("-h, --help", "显示帮助").requiredOption("-f, --file <path>", "Markdown 文件").option("-c, --config <path>", "自定义配置文件").option("-o, --output <path>", "输出 Markdown 文件").action(actions.format);
|
|
128501
128503
|
formatCommand.exitOverride();
|
|
128502
128504
|
const cleanCommand = program2.command("clean").description("清除 ~/.md2docx 中的预处理文件和样式缓存").helpOption("-h, --help", "显示帮助").action(async () => {
|
|
128503
128505
|
await actions.clean();
|
|
@@ -128595,6 +128597,10 @@ function validateConfig(value, path2) {
|
|
|
128595
128597
|
if (!Number.isInteger(mermaid.density) || mermaid.density < 72) {
|
|
128596
128598
|
invalidConfig(path2, "renderMermaid.density", "必须是不小于 72 的整数");
|
|
128597
128599
|
}
|
|
128600
|
+
const imageSize = expectRecord(root.imageSize, path2, "imageSize");
|
|
128601
|
+
expectBoolean(imageSize.enabled, path2, "imageSize.enabled");
|
|
128602
|
+
expectPositiveNumber(imageSize.maxWidthCm, path2, "imageSize.maxWidthCm");
|
|
128603
|
+
expectPositiveNumber(imageSize.maxHeightCm, path2, "imageSize.maxHeightCm");
|
|
128598
128604
|
validateEnabled(root.removeThematicBreaks, path2, "removeThematicBreaks");
|
|
128599
128605
|
const title = expectRecord(root.detectTitle, path2, "detectTitle");
|
|
128600
128606
|
expectBoolean(title.enabled, path2, "detectTitle.enabled");
|
|
@@ -128629,6 +128635,12 @@ function expectString(value, path2, field) {
|
|
|
128629
128635
|
invalidConfig(path2, field, "必须是字符串");
|
|
128630
128636
|
return value;
|
|
128631
128637
|
}
|
|
128638
|
+
function expectPositiveNumber(value, path2, field) {
|
|
128639
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
|
|
128640
|
+
invalidConfig(path2, field, "必须是大于 0 的有限数字");
|
|
128641
|
+
}
|
|
128642
|
+
return value;
|
|
128643
|
+
}
|
|
128632
128644
|
function invalidConfig(path2, field, reason) {
|
|
128633
128645
|
throw new Error(`配置文件无效:${path2}
|
|
128634
128646
|
位置:${field}
|
|
@@ -128652,11 +128664,7 @@ function resolveOutputPath(path2, defaultName, extensions, label) {
|
|
|
128652
128664
|
assertExtension(resolved, extensions, label);
|
|
128653
128665
|
return resolved;
|
|
128654
128666
|
}
|
|
128655
|
-
function prepareOutput(path2
|
|
128656
|
-
if (existsSync2(path2) && !force) {
|
|
128657
|
-
throw new Error(`输出文件已存在:${path2}
|
|
128658
|
-
使用 --force 覆盖现有文件`);
|
|
128659
|
-
}
|
|
128667
|
+
function prepareOutput(path2) {
|
|
128660
128668
|
mkdirSync(dirname2(path2), { recursive: true });
|
|
128661
128669
|
}
|
|
128662
128670
|
function assertExtension(path2, extensions, label) {
|
|
@@ -146108,6 +146116,11 @@ var config_default = `{
|
|
|
146108
146116
|
"theme": "tokyo-night-light",
|
|
146109
146117
|
"density": 200
|
|
146110
146118
|
},
|
|
146119
|
+
"imageSize": {
|
|
146120
|
+
"enabled": true,
|
|
146121
|
+
"maxWidthCm": 12,
|
|
146122
|
+
"maxHeightCm": 12
|
|
146123
|
+
},
|
|
146111
146124
|
"detectTitle": {
|
|
146112
146125
|
"enabled": true,
|
|
146113
146126
|
"strategy": "first-h1"
|
|
@@ -146118,6 +146131,102 @@ var config_default = `{
|
|
|
146118
146131
|
}
|
|
146119
146132
|
`;
|
|
146120
146133
|
|
|
146134
|
+
// config/lua/limit-image-size.lua
|
|
146135
|
+
var limit_image_size_default = `local max_width_cm
|
|
146136
|
+
local max_height_cm
|
|
146137
|
+
local size_cache = {}
|
|
146138
|
+
local warned = {}
|
|
146139
|
+
|
|
146140
|
+
local function warn_once(source, message)
|
|
146141
|
+
if warned[source] then
|
|
146142
|
+
return
|
|
146143
|
+
end
|
|
146144
|
+
warned[source] = true
|
|
146145
|
+
local text = "无法限制图片尺寸 " .. source .. ":" .. message
|
|
146146
|
+
if pandoc.log and pandoc.log.warn then
|
|
146147
|
+
pandoc.log.warn(text)
|
|
146148
|
+
else
|
|
146149
|
+
io.stderr:write("[WARNING] " .. text .. "\\n")
|
|
146150
|
+
end
|
|
146151
|
+
end
|
|
146152
|
+
|
|
146153
|
+
local function metadata_number(meta, key)
|
|
146154
|
+
local value = meta[key]
|
|
146155
|
+
if value == nil then
|
|
146156
|
+
return nil
|
|
146157
|
+
end
|
|
146158
|
+
return tonumber(pandoc.utils.stringify(value))
|
|
146159
|
+
end
|
|
146160
|
+
|
|
146161
|
+
local function read_config(meta)
|
|
146162
|
+
max_width_cm = metadata_number(meta, "md2docx-image-max-width-cm")
|
|
146163
|
+
max_height_cm = metadata_number(meta, "md2docx-image-max-height-cm")
|
|
146164
|
+
end
|
|
146165
|
+
|
|
146166
|
+
local function image_size(source)
|
|
146167
|
+
local cached = size_cache[source]
|
|
146168
|
+
if cached ~= nil then
|
|
146169
|
+
return cached or nil
|
|
146170
|
+
end
|
|
146171
|
+
if pandoc.image == nil or pandoc.image.size == nil then
|
|
146172
|
+
warn_once(source, "当前 Pandoc 不支持 pandoc.image.size,请升级到 3.1.13 或更高版本")
|
|
146173
|
+
size_cache[source] = false
|
|
146174
|
+
return nil
|
|
146175
|
+
end
|
|
146176
|
+
|
|
146177
|
+
local fetched, _, contents = pcall(pandoc.mediabag.fetch, source)
|
|
146178
|
+
if not fetched or contents == nil then
|
|
146179
|
+
warn_once(source, fetched and "未读取到图片内容" or tostring(_))
|
|
146180
|
+
size_cache[source] = false
|
|
146181
|
+
return nil
|
|
146182
|
+
end
|
|
146183
|
+
|
|
146184
|
+
local measured, size = pcall(pandoc.image.size, contents, PANDOC_WRITER_OPTIONS)
|
|
146185
|
+
if not measured then
|
|
146186
|
+
warn_once(source, tostring(size))
|
|
146187
|
+
size_cache[source] = false
|
|
146188
|
+
return nil
|
|
146189
|
+
end
|
|
146190
|
+
|
|
146191
|
+
size_cache[source] = size
|
|
146192
|
+
return size
|
|
146193
|
+
end
|
|
146194
|
+
|
|
146195
|
+
local function limit_image(image)
|
|
146196
|
+
if max_width_cm == nil or max_height_cm == nil then
|
|
146197
|
+
return nil
|
|
146198
|
+
end
|
|
146199
|
+
if image.attributes.width ~= nil or image.attributes.height ~= nil then
|
|
146200
|
+
return nil
|
|
146201
|
+
end
|
|
146202
|
+
|
|
146203
|
+
local size = image_size(image.src)
|
|
146204
|
+
if size == nil then
|
|
146205
|
+
return nil
|
|
146206
|
+
end
|
|
146207
|
+
|
|
146208
|
+
local fallback_dpi = PANDOC_WRITER_OPTIONS.dpi or 96
|
|
146209
|
+
local horizontal_dpi = size.dpi_horz > 0 and size.dpi_horz or fallback_dpi
|
|
146210
|
+
local vertical_dpi = size.dpi_vert > 0 and size.dpi_vert or fallback_dpi
|
|
146211
|
+
local width_cm = size.width / horizontal_dpi * 2.54
|
|
146212
|
+
local height_cm = size.height / vertical_dpi * 2.54
|
|
146213
|
+
local scale = math.min(1, max_width_cm / width_cm, max_height_cm / height_cm)
|
|
146214
|
+
|
|
146215
|
+
if scale >= 1 then
|
|
146216
|
+
return nil
|
|
146217
|
+
end
|
|
146218
|
+
|
|
146219
|
+
image.attributes.width = string.format("%.4fcm", width_cm * scale)
|
|
146220
|
+
image.attributes.height = string.format("%.4fcm", height_cm * scale)
|
|
146221
|
+
return image
|
|
146222
|
+
end
|
|
146223
|
+
|
|
146224
|
+
return {
|
|
146225
|
+
{ Meta = read_config },
|
|
146226
|
+
{ Image = limit_image },
|
|
146227
|
+
}
|
|
146228
|
+
`;
|
|
146229
|
+
|
|
146121
146230
|
// config/lua/add-inline-code.lua
|
|
146122
146231
|
var add_inline_code_default = `-- Author: Achuan-2
|
|
146123
146232
|
function Code(el)
|
|
@@ -146126,8 +146235,8 @@ function Code(el)
|
|
|
146126
146235
|
end
|
|
146127
146236
|
return { Code = Code }`;
|
|
146128
146237
|
|
|
146129
|
-
// config/style.json
|
|
146130
|
-
var
|
|
146238
|
+
// config/style-raw.json
|
|
146239
|
+
var style_raw_default = `{
|
|
146131
146240
|
"default": {
|
|
146132
146241
|
"document": {
|
|
146133
146242
|
"run": {
|
|
@@ -146688,7 +146797,7 @@ var style_default = `{
|
|
|
146688
146797
|
"eastAsia": "zh-CN"
|
|
146689
146798
|
},
|
|
146690
146799
|
"shading": {
|
|
146691
|
-
"
|
|
146800
|
+
"type": "pct5",
|
|
146692
146801
|
"color": "auto",
|
|
146693
146802
|
"fill": "auto"
|
|
146694
146803
|
}
|
|
@@ -146700,40 +146809,40 @@ var style_default = `{
|
|
|
146700
146809
|
},
|
|
146701
146810
|
"wordWrap": false,
|
|
146702
146811
|
"shading": {
|
|
146703
|
-
"
|
|
146812
|
+
"type": "clear",
|
|
146704
146813
|
"color": "F3F4F4",
|
|
146705
146814
|
"fill": "FFFFFF",
|
|
146706
146815
|
"themeFill": "background1"
|
|
146707
146816
|
},
|
|
146708
146817
|
"border": {
|
|
146709
146818
|
"top": {
|
|
146710
|
-
"
|
|
146819
|
+
"style": "single",
|
|
146711
146820
|
"color": "BFBFBF",
|
|
146712
|
-
"
|
|
146821
|
+
"size": 8,
|
|
146713
146822
|
"space": 10,
|
|
146714
146823
|
"themeColor": "background1",
|
|
146715
146824
|
"themeShade": "BF"
|
|
146716
146825
|
},
|
|
146717
146826
|
"left": {
|
|
146718
|
-
"
|
|
146827
|
+
"style": "single",
|
|
146719
146828
|
"color": "BFBFBF",
|
|
146720
|
-
"
|
|
146829
|
+
"size": 8,
|
|
146721
146830
|
"space": 10,
|
|
146722
146831
|
"themeColor": "background1",
|
|
146723
146832
|
"themeShade": "BF"
|
|
146724
146833
|
},
|
|
146725
146834
|
"bottom": {
|
|
146726
|
-
"
|
|
146835
|
+
"style": "single",
|
|
146727
146836
|
"color": "BFBFBF",
|
|
146728
|
-
"
|
|
146837
|
+
"size": 8,
|
|
146729
146838
|
"space": 10,
|
|
146730
146839
|
"themeColor": "background1",
|
|
146731
146840
|
"themeShade": "BF"
|
|
146732
146841
|
},
|
|
146733
146842
|
"right": {
|
|
146734
|
-
"
|
|
146843
|
+
"style": "single",
|
|
146735
146844
|
"color": "BFBFBF",
|
|
146736
|
-
"
|
|
146845
|
+
"size": 8,
|
|
146737
146846
|
"space": 10,
|
|
146738
146847
|
"themeColor": "background1",
|
|
146739
146848
|
"themeShade": "BF"
|
|
@@ -146879,7 +146988,7 @@ var style_default = `{
|
|
|
146879
146988
|
"eastAsia": "zh-CN"
|
|
146880
146989
|
},
|
|
146881
146990
|
"shading": {
|
|
146882
|
-
"
|
|
146991
|
+
"type": "clear",
|
|
146883
146992
|
"color": "F3F4F4",
|
|
146884
146993
|
"fill": "FFFFFF",
|
|
146885
146994
|
"themeFill": "background1"
|
|
@@ -146973,16 +147082,16 @@ var style_default = `{
|
|
|
146973
147082
|
"eastAsia": "zh-CN"
|
|
146974
147083
|
},
|
|
146975
147084
|
"shading": {
|
|
146976
|
-
"
|
|
147085
|
+
"type": "clear",
|
|
146977
147086
|
"color": "F3F4F4",
|
|
146978
147087
|
"fill": "F2F2F2",
|
|
146979
147088
|
"themeFill": "background1",
|
|
146980
147089
|
"themeFillShade": "F2"
|
|
146981
147090
|
},
|
|
146982
147091
|
"border": {
|
|
146983
|
-
"
|
|
147092
|
+
"style": "none",
|
|
146984
147093
|
"color": "auto",
|
|
146985
|
-
"
|
|
147094
|
+
"size": 0,
|
|
146986
147095
|
"space": 0
|
|
146987
147096
|
}
|
|
146988
147097
|
}
|
|
@@ -147084,9 +147193,33 @@ var style_default = `{
|
|
|
147084
147193
|
}
|
|
147085
147194
|
`;
|
|
147086
147195
|
|
|
147196
|
+
// config/style-config.json
|
|
147197
|
+
var style_config_default = `{
|
|
147198
|
+
"$schema": "https://raw.githubusercontent.com/WXY-V1hZ/md2docx/main/config/style-config.schema.json",
|
|
147199
|
+
"schemaVersion": 1,
|
|
147200
|
+
"options": {
|
|
147201
|
+
"body": {
|
|
147202
|
+
"firstLineIndent": true
|
|
147203
|
+
},
|
|
147204
|
+
"headings": {
|
|
147205
|
+
"1": {
|
|
147206
|
+
"startOnNewPage": false
|
|
147207
|
+
}
|
|
147208
|
+
},
|
|
147209
|
+
"inlineCode": {
|
|
147210
|
+
"background": true
|
|
147211
|
+
},
|
|
147212
|
+
"codeBlock": {
|
|
147213
|
+
"border": true
|
|
147214
|
+
}
|
|
147215
|
+
}
|
|
147216
|
+
}
|
|
147217
|
+
`;
|
|
147218
|
+
|
|
147087
147219
|
// src/resources.ts
|
|
147088
147220
|
var DEFAULT_CONFIG_TEXT = config_default;
|
|
147089
|
-
var
|
|
147221
|
+
var DEFAULT_STYLE_CONFIG_TEXT = style_config_default;
|
|
147222
|
+
var DEFAULT_STYLE_RAW_TEXT = style_raw_default;
|
|
147090
147223
|
function materializeResource(name2, content3) {
|
|
147091
147224
|
const directory = join4(TMP_DIR, "resources");
|
|
147092
147225
|
const path3 = join4(directory, name2);
|
|
@@ -147099,21 +147232,238 @@ function materializeResource(name2, content3) {
|
|
|
147099
147232
|
function materializeDefaultConfig() {
|
|
147100
147233
|
return materializeResource("config.json", DEFAULT_CONFIG_TEXT);
|
|
147101
147234
|
}
|
|
147102
|
-
function
|
|
147103
|
-
return materializeResource("style.json",
|
|
147235
|
+
function materializeDefaultStyleRaw() {
|
|
147236
|
+
return materializeResource("style-raw.json", DEFAULT_STYLE_RAW_TEXT);
|
|
147237
|
+
}
|
|
147238
|
+
function materializeDefaultStyleConfig() {
|
|
147239
|
+
return materializeResource("style-config.json", DEFAULT_STYLE_CONFIG_TEXT);
|
|
147104
147240
|
}
|
|
147105
|
-
function
|
|
147241
|
+
function materializeInlineCodeFilter() {
|
|
147106
147242
|
return materializeResource("add-inline-code.lua", add_inline_code_default);
|
|
147107
147243
|
}
|
|
147244
|
+
function materializeImageSizeFilter() {
|
|
147245
|
+
return materializeResource("limit-image-size.lua", limit_image_size_default);
|
|
147246
|
+
}
|
|
147247
|
+
|
|
147248
|
+
// src/style/compiler.ts
|
|
147249
|
+
import { readFileSync as readFileSync2 } from "node:fs";
|
|
147250
|
+
|
|
147251
|
+
// src/style/config.ts
|
|
147252
|
+
function validateStyleConfig(value2, path3) {
|
|
147253
|
+
const root2 = expectRecord2(value2, path3, "样式配置");
|
|
147254
|
+
rejectUnknown(root2, ["$schema", "schemaVersion", "options"], path3, "样式配置");
|
|
147255
|
+
if (root2.$schema !== undefined)
|
|
147256
|
+
expectString2(root2.$schema, path3, "$schema");
|
|
147257
|
+
if (root2.schemaVersion !== 1)
|
|
147258
|
+
invalidStyleConfig(path3, "schemaVersion", "目前只支持版本 1");
|
|
147259
|
+
if (root2.options !== undefined)
|
|
147260
|
+
validateOptions(root2.options, path3);
|
|
147261
|
+
return root2;
|
|
147262
|
+
}
|
|
147263
|
+
function validateOptions(value2, path3) {
|
|
147264
|
+
const options = expectRecord2(value2, path3, "options");
|
|
147265
|
+
rejectUnknown(options, ["body", "headings", "inlineCode", "codeBlock"], path3, "options");
|
|
147266
|
+
if (options.body !== undefined) {
|
|
147267
|
+
const body = expectRecord2(options.body, path3, "options.body");
|
|
147268
|
+
rejectUnknown(body, ["firstLineIndent"], path3, "options.body");
|
|
147269
|
+
if (body.firstLineIndent !== undefined) {
|
|
147270
|
+
expectBoolean2(body.firstLineIndent, path3, "options.body.firstLineIndent");
|
|
147271
|
+
}
|
|
147272
|
+
}
|
|
147273
|
+
if (options.headings !== undefined) {
|
|
147274
|
+
const headings = expectRecord2(options.headings, path3, "options.headings");
|
|
147275
|
+
rejectUnknown(headings, ["1"], path3, "options.headings");
|
|
147276
|
+
if (headings["1"] !== undefined) {
|
|
147277
|
+
const heading1 = expectRecord2(headings["1"], path3, 'options.headings["1"]');
|
|
147278
|
+
rejectUnknown(heading1, ["startOnNewPage"], path3, 'options.headings["1"]');
|
|
147279
|
+
if (heading1.startOnNewPage !== undefined) {
|
|
147280
|
+
expectBoolean2(heading1.startOnNewPage, path3, 'options.headings["1"].startOnNewPage');
|
|
147281
|
+
}
|
|
147282
|
+
}
|
|
147283
|
+
}
|
|
147284
|
+
if (options.inlineCode !== undefined) {
|
|
147285
|
+
const inlineCode2 = expectRecord2(options.inlineCode, path3, "options.inlineCode");
|
|
147286
|
+
rejectUnknown(inlineCode2, ["background"], path3, "options.inlineCode");
|
|
147287
|
+
if (inlineCode2.background !== undefined) {
|
|
147288
|
+
expectBoolean2(inlineCode2.background, path3, "options.inlineCode.background");
|
|
147289
|
+
}
|
|
147290
|
+
}
|
|
147291
|
+
if (options.codeBlock !== undefined) {
|
|
147292
|
+
const codeBlock = expectRecord2(options.codeBlock, path3, "options.codeBlock");
|
|
147293
|
+
rejectUnknown(codeBlock, ["border"], path3, "options.codeBlock");
|
|
147294
|
+
if (codeBlock.border !== undefined) {
|
|
147295
|
+
expectBoolean2(codeBlock.border, path3, "options.codeBlock.border");
|
|
147296
|
+
}
|
|
147297
|
+
}
|
|
147298
|
+
}
|
|
147299
|
+
function rejectUnknown(value2, allowed, path3, field) {
|
|
147300
|
+
const unknown2 = Object.keys(value2).find((key) => !allowed.includes(key));
|
|
147301
|
+
if (unknown2 !== undefined)
|
|
147302
|
+
invalidStyleConfig(path3, `${field}.${unknown2}`, "不是支持的配置项");
|
|
147303
|
+
}
|
|
147304
|
+
function expectRecord2(value2, path3, field) {
|
|
147305
|
+
if (!isRecord(value2))
|
|
147306
|
+
invalidStyleConfig(path3, field, "必须是对象");
|
|
147307
|
+
return value2;
|
|
147308
|
+
}
|
|
147309
|
+
function isRecord(value2) {
|
|
147310
|
+
return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
|
|
147311
|
+
}
|
|
147312
|
+
function expectBoolean2(value2, path3, field) {
|
|
147313
|
+
if (typeof value2 !== "boolean")
|
|
147314
|
+
invalidStyleConfig(path3, field, "必须是 boolean");
|
|
147315
|
+
}
|
|
147316
|
+
function expectString2(value2, path3, field) {
|
|
147317
|
+
if (typeof value2 !== "string")
|
|
147318
|
+
invalidStyleConfig(path3, field, "必须是字符串");
|
|
147319
|
+
}
|
|
147320
|
+
function invalidStyleConfig(path3, field, reason) {
|
|
147321
|
+
throw new Error(`样式配置无效:${path3}
|
|
147322
|
+
位置:${field}
|
|
147323
|
+
原因:${reason}`);
|
|
147324
|
+
}
|
|
147325
|
+
|
|
147326
|
+
// src/style/compiler.ts
|
|
147327
|
+
function resolveEffectiveStyles(sources, defaults) {
|
|
147328
|
+
const rawPath = sources.styleRawPath ?? defaults?.styleRawPath ?? materializeDefaultStyleRaw();
|
|
147329
|
+
const rawStyle = loadStyleRaw(rawPath);
|
|
147330
|
+
if (sources.styleConfigPath) {
|
|
147331
|
+
return compileStyleConfig(rawStyle, loadStyleConfig(sources.styleConfigPath));
|
|
147332
|
+
}
|
|
147333
|
+
if (sources.styleRawPath)
|
|
147334
|
+
return rawStyle;
|
|
147335
|
+
const defaultConfigPath = defaults?.styleConfigPath ?? materializeDefaultStyleConfig();
|
|
147336
|
+
return compileStyleConfig(rawStyle, loadStyleConfig(defaultConfigPath));
|
|
147337
|
+
}
|
|
147338
|
+
function loadStyleRaw(path3) {
|
|
147339
|
+
const source = parseJson(readFileSync2(path3, "utf-8"), path3, "底层样式文件");
|
|
147340
|
+
if (!isRecord2(source))
|
|
147341
|
+
throw new Error(`底层样式文件必须是 JSON 对象:${path3}`);
|
|
147342
|
+
if (looksLikeStyleConfig(source)) {
|
|
147343
|
+
throw new Error(`底层样式文件无效:${path3}
|
|
147344
|
+
当前文件看起来是语义化样式配置,请改用 --style-config`);
|
|
147345
|
+
}
|
|
147346
|
+
if (!looksLikeRawStyle(source)) {
|
|
147347
|
+
throw new Error(`底层样式文件无效:${path3}
|
|
147348
|
+
缺少 Word 样式定义`);
|
|
147349
|
+
}
|
|
147350
|
+
return source;
|
|
147351
|
+
}
|
|
147352
|
+
function loadStyleConfig(path3) {
|
|
147353
|
+
const source = parseJson(readFileSync2(path3, "utf-8"), path3, "语义化样式配置");
|
|
147354
|
+
if (isRecord2(source) && looksLikeRawStyle(source)) {
|
|
147355
|
+
throw new Error(`语义化样式配置无效:${path3}
|
|
147356
|
+
当前文件看起来是底层样式,请改用 --style-raw`);
|
|
147357
|
+
}
|
|
147358
|
+
return validateStyleConfig(source, path3);
|
|
147359
|
+
}
|
|
147360
|
+
function compileStyleConfig(rawStyle, config) {
|
|
147361
|
+
const styles = structuredClone(rawStyle);
|
|
147362
|
+
const options = config.options;
|
|
147363
|
+
if (!options)
|
|
147364
|
+
return styles;
|
|
147365
|
+
const firstLineIndent = options.body?.firstLineIndent;
|
|
147366
|
+
if (firstLineIndent !== undefined)
|
|
147367
|
+
applyBodyFirstLineIndent(styles, firstLineIndent);
|
|
147368
|
+
const startOnNewPage = options.headings?.["1"]?.startOnNewPage;
|
|
147369
|
+
if (startOnNewPage !== undefined)
|
|
147370
|
+
applyHeading1PageBreak(styles, startOnNewPage);
|
|
147371
|
+
const inlineCodeBackground = options.inlineCode?.background;
|
|
147372
|
+
if (inlineCodeBackground !== undefined) {
|
|
147373
|
+
applyInlineCodeBackground(styles, inlineCodeBackground);
|
|
147374
|
+
}
|
|
147375
|
+
const codeBlockBorder = options.codeBlock?.border;
|
|
147376
|
+
if (codeBlockBorder !== undefined)
|
|
147377
|
+
applyCodeBlockBorder(styles, codeBlockBorder);
|
|
147378
|
+
return styles;
|
|
147379
|
+
}
|
|
147380
|
+
function applyBodyFirstLineIndent(styles, enabled) {
|
|
147381
|
+
const firstParagraph = findStyle(styles, "paragraphStyles", "First Paragraph");
|
|
147382
|
+
const bodyText = findStyle(styles, "paragraphStyles", "Body Text");
|
|
147383
|
+
for (const style of [firstParagraph, bodyText]) {
|
|
147384
|
+
const paragraph2 = ensureObject(style, "paragraph");
|
|
147385
|
+
paragraph2.indent = {
|
|
147386
|
+
...optionalObject(paragraph2.indent),
|
|
147387
|
+
firstLine: enabled ? 200 : 0,
|
|
147388
|
+
firstLineChars: enabled ? 200 : 0
|
|
147389
|
+
};
|
|
147390
|
+
}
|
|
147391
|
+
}
|
|
147392
|
+
function applyHeading1PageBreak(styles, enabled) {
|
|
147393
|
+
const heading1 = findStyle(styles, "paragraphStyles", "heading 1");
|
|
147394
|
+
ensureObject(heading1, "paragraph").pageBreakBefore = enabled;
|
|
147395
|
+
}
|
|
147396
|
+
function applyInlineCodeBackground(styles, enabled) {
|
|
147397
|
+
const inlineCode2 = findStyle(styles, "characterStyles", "Inline Code");
|
|
147398
|
+
ensureObject(inlineCode2, "run").shading = {
|
|
147399
|
+
type: "clear",
|
|
147400
|
+
color: enabled ? "F3F4F4" : "auto",
|
|
147401
|
+
fill: enabled ? "F2F2F2" : "auto"
|
|
147402
|
+
};
|
|
147403
|
+
}
|
|
147404
|
+
function applyCodeBlockBorder(styles, enabled) {
|
|
147405
|
+
const sourceCode = findStyle(styles, "paragraphStyles", "Source Code");
|
|
147406
|
+
const border = () => ({
|
|
147407
|
+
style: enabled ? "single" : "none",
|
|
147408
|
+
color: enabled ? "BFBFBF" : "auto",
|
|
147409
|
+
size: enabled ? 8 : 0,
|
|
147410
|
+
space: enabled ? 10 : 0
|
|
147411
|
+
});
|
|
147412
|
+
ensureObject(sourceCode, "paragraph").border = {
|
|
147413
|
+
top: border(),
|
|
147414
|
+
left: border(),
|
|
147415
|
+
bottom: border(),
|
|
147416
|
+
right: border()
|
|
147417
|
+
};
|
|
147418
|
+
}
|
|
147419
|
+
function findStyle(styles, collectionName, name2) {
|
|
147420
|
+
const collection = styles[collectionName];
|
|
147421
|
+
if (!Array.isArray(collection)) {
|
|
147422
|
+
throw new Error(`底层样式缺少 ${collectionName},无法应用语义化样式配置`);
|
|
147423
|
+
}
|
|
147424
|
+
const normalizedName = name2.toLowerCase();
|
|
147425
|
+
const style = collection.find((entry) => isRecord2(entry) && typeof entry.name === "string" && entry.name.toLowerCase() === normalizedName);
|
|
147426
|
+
if (!style)
|
|
147427
|
+
throw new Error(`底层样式缺少“${name2}”,无法应用语义化样式配置`);
|
|
147428
|
+
return style;
|
|
147429
|
+
}
|
|
147430
|
+
function ensureObject(parent, key) {
|
|
147431
|
+
const current = parent[key];
|
|
147432
|
+
if (isRecord2(current))
|
|
147433
|
+
return current;
|
|
147434
|
+
const created = {};
|
|
147435
|
+
parent[key] = created;
|
|
147436
|
+
return created;
|
|
147437
|
+
}
|
|
147438
|
+
function optionalObject(value2) {
|
|
147439
|
+
return isRecord2(value2) ? value2 : {};
|
|
147440
|
+
}
|
|
147441
|
+
function parseJson(text5, path3, kind) {
|
|
147442
|
+
try {
|
|
147443
|
+
return JSON.parse(text5);
|
|
147444
|
+
} catch (error) {
|
|
147445
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
147446
|
+
throw new Error(`${kind}不是有效的 JSON:${path3}
|
|
147447
|
+
${message}`);
|
|
147448
|
+
}
|
|
147449
|
+
}
|
|
147450
|
+
function looksLikeStyleConfig(value2) {
|
|
147451
|
+
return "schemaVersion" in value2 || "options" in value2 || "preset" in value2;
|
|
147452
|
+
}
|
|
147453
|
+
function looksLikeRawStyle(value2) {
|
|
147454
|
+
return ["default", "paragraphStyles", "characterStyles", "tableStyles", "tableStylesXml"].some((key) => (key in value2));
|
|
147455
|
+
}
|
|
147456
|
+
function isRecord2(value2) {
|
|
147457
|
+
return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
|
|
147458
|
+
}
|
|
147108
147459
|
|
|
147109
147460
|
// src/style/generate.ts
|
|
147110
|
-
import { existsSync as existsSync5, mkdirSync as mkdirSync4
|
|
147461
|
+
import { existsSync as existsSync5, mkdirSync as mkdirSync4 } from "node:fs";
|
|
147111
147462
|
import { writeFile } from "node:fs/promises";
|
|
147112
147463
|
import { createHash as createHash2 } from "node:crypto";
|
|
147113
147464
|
import { dirname as dirname4 } from "path";
|
|
147114
|
-
async function
|
|
147465
|
+
async function generateTemplateDocxFromStyles(raw, outputPath) {
|
|
147115
147466
|
const { Document: Document2, Packer: Packer3 } = await Promise.resolve().then(() => (init_dist(), exports_dist));
|
|
147116
|
-
const raw = JSON.parse(readFileSync2(styleJsonPath, "utf-8"));
|
|
147117
147467
|
const tableStylesXml = raw.tableStylesXml;
|
|
147118
147468
|
const { tableStylesXml: _, ...styles } = raw;
|
|
147119
147469
|
const doc = new Document2({
|
|
@@ -147138,14 +147488,16 @@ async function generateTemplateDocx(styleJsonPath, outputPath) {
|
|
|
147138
147488
|
await writeFile(outputPath, buf);
|
|
147139
147489
|
}
|
|
147140
147490
|
var generatePromises = new Map;
|
|
147141
|
-
|
|
147142
|
-
|
|
147143
|
-
|
|
147491
|
+
function styleCacheHash(rawStyle) {
|
|
147492
|
+
return createHash2("sha256").update(JSON.stringify(rawStyle)).digest("hex").slice(0, 16);
|
|
147493
|
+
}
|
|
147494
|
+
async function ensureTemplateDocx(rawStyle) {
|
|
147495
|
+
const hash = styleCacheHash(rawStyle);
|
|
147144
147496
|
const outputPath = styleTemplateDocx(hash);
|
|
147145
147497
|
if (!existsSync5(outputPath)) {
|
|
147146
147498
|
let promise = generatePromises.get(outputPath);
|
|
147147
147499
|
if (!promise) {
|
|
147148
|
-
promise =
|
|
147500
|
+
promise = generateTemplateDocxFromStyles(rawStyle, outputPath).catch((error) => {
|
|
147149
147501
|
generatePromises.delete(outputPath);
|
|
147150
147502
|
throw error;
|
|
147151
147503
|
});
|
|
@@ -147162,25 +147514,29 @@ async function convertMarkdown(options) {
|
|
|
147162
147514
|
throw new Error("缺少必填参数:--file");
|
|
147163
147515
|
const input = resolveInputPath(options.file, [".md", ".markdown"], "Markdown 文件");
|
|
147164
147516
|
const configPath = options.config ? resolveInputPath(options.config, [".json"], "配置文件") : materializeDefaultConfig();
|
|
147165
|
-
const
|
|
147517
|
+
const styleRawPath = options.styleRaw ? resolveInputPath(options.styleRaw, [".json"], "底层样式文件") : undefined;
|
|
147518
|
+
const styleConfigPath = options.styleConfig ? resolveInputPath(options.styleConfig, [".json"], "语义化样式配置") : undefined;
|
|
147166
147519
|
const baseName = parse4(input).name;
|
|
147167
147520
|
const output = resolveOutputPath(options.output, `${baseName}.docx`, [".docx"], "DOCX 输出文件");
|
|
147168
|
-
prepareOutput(output
|
|
147521
|
+
prepareOutput(output);
|
|
147169
147522
|
const config = await loadConfig(configPath);
|
|
147170
147523
|
const outDir = preprocessDir(input);
|
|
147171
147524
|
mkdirSync5(outDir, { recursive: true });
|
|
147172
147525
|
const formatted = await preprocess2(input, config, outDir);
|
|
147173
147526
|
const markdownOutput = formattedMdPath(input);
|
|
147174
147527
|
writeFileSync3(markdownOutput, formatted, "utf-8");
|
|
147175
|
-
const
|
|
147176
|
-
const
|
|
147528
|
+
const effectiveStyles = resolveEffectiveStyles({ styleRawPath, styleConfigPath });
|
|
147529
|
+
const templatePath = await ensureTemplateDocx(effectiveStyles);
|
|
147530
|
+
const inlineCodeFilter = materializeInlineCodeFilter();
|
|
147531
|
+
const imageSizeArgs = config.imageSize.enabled ? buildImageSizePandocArgs(config.imageSize, materializeImageSizeFilter()) : [];
|
|
147177
147532
|
const pandocArgs = [
|
|
147178
147533
|
markdownOutput,
|
|
147179
147534
|
"-o",
|
|
147180
147535
|
output,
|
|
147181
147536
|
...buildPandocResourcePathArgs(input),
|
|
147182
147537
|
`--reference-doc=${templatePath}`,
|
|
147183
|
-
...existsSync6(
|
|
147538
|
+
...existsSync6(inlineCodeFilter) ? [`--lua-filter=${inlineCodeFilter}`] : [],
|
|
147539
|
+
...imageSizeArgs
|
|
147184
147540
|
];
|
|
147185
147541
|
const { exitCode, stderr } = await runProcess("pandoc", pandocArgs);
|
|
147186
147542
|
if (exitCode !== 0) {
|
|
@@ -147188,6 +147544,15 @@ async function convertMarkdown(options) {
|
|
|
147188
147544
|
}
|
|
147189
147545
|
console.log(`已生成:${output}`);
|
|
147190
147546
|
}
|
|
147547
|
+
function buildImageSizePandocArgs(config, filterPath) {
|
|
147548
|
+
if (!config.enabled)
|
|
147549
|
+
return [];
|
|
147550
|
+
return [
|
|
147551
|
+
`--metadata=md2docx-image-max-width-cm:${config.maxWidthCm}`,
|
|
147552
|
+
`--metadata=md2docx-image-max-height-cm:${config.maxHeightCm}`,
|
|
147553
|
+
`--lua-filter=${filterPath}`
|
|
147554
|
+
];
|
|
147555
|
+
}
|
|
147191
147556
|
function buildPandocResourcePathArgs(inputPath, workingDirectory = process.cwd()) {
|
|
147192
147557
|
const workingDir = resolve5(workingDirectory);
|
|
147193
147558
|
const sourceDir = dirname5(resolve5(inputPath));
|
|
@@ -147299,31 +147664,31 @@ function mapShd(shd) {
|
|
|
147299
147664
|
if (!shd)
|
|
147300
147665
|
return;
|
|
147301
147666
|
const sh = {};
|
|
147302
|
-
for (const a of [
|
|
147303
|
-
"val",
|
|
147304
|
-
"color",
|
|
147305
|
-
"fill",
|
|
147306
|
-
"themeColor",
|
|
147307
|
-
"themeTint",
|
|
147308
|
-
"themeFill",
|
|
147309
|
-
"themeFillShade",
|
|
147310
|
-
"themeShade"
|
|
147311
|
-
]) {
|
|
147667
|
+
for (const a of ["color", "fill"]) {
|
|
147312
147668
|
const v = wAttr(shd, a);
|
|
147313
147669
|
if (v !== null)
|
|
147314
147670
|
sh[a] = v;
|
|
147315
147671
|
}
|
|
147672
|
+
const type = wAttr(shd, "val");
|
|
147673
|
+
if (type !== null)
|
|
147674
|
+
sh.type = type;
|
|
147316
147675
|
return Object.keys(sh).length > 0 ? sh : undefined;
|
|
147317
147676
|
}
|
|
147318
147677
|
function mapBorder(bdr) {
|
|
147319
147678
|
if (!bdr)
|
|
147320
147679
|
return;
|
|
147321
147680
|
const b = {};
|
|
147322
|
-
for (const a of ["
|
|
147681
|
+
for (const a of ["color", "space"]) {
|
|
147323
147682
|
const v = wAttr(bdr, a);
|
|
147324
147683
|
if (v !== null)
|
|
147325
147684
|
b[a] = /^\d+$/.test(v) ? Number(v) : v;
|
|
147326
147685
|
}
|
|
147686
|
+
const style = wAttr(bdr, "val");
|
|
147687
|
+
if (style !== null)
|
|
147688
|
+
b.style = style;
|
|
147689
|
+
const size = wAttr(bdr, "sz");
|
|
147690
|
+
if (size !== null)
|
|
147691
|
+
b.size = /^\d+$/.test(size) ? Number(size) : size;
|
|
147327
147692
|
return Object.keys(b).length > 0 ? b : undefined;
|
|
147328
147693
|
}
|
|
147329
147694
|
function mapRunProps(rPr) {
|
|
@@ -147831,23 +148196,32 @@ function extractStylesFromDocx(docxPath) {
|
|
|
147831
148196
|
// src/commands/export.ts
|
|
147832
148197
|
async function exportConfig(options) {
|
|
147833
148198
|
const output = resolveOutputPath(options.output, "config.json", [".json"], "配置输出文件");
|
|
147834
|
-
prepareOutput(output
|
|
148199
|
+
prepareOutput(output);
|
|
147835
148200
|
writeFileSync4(output, DEFAULT_CONFIG_TEXT, "utf-8");
|
|
147836
148201
|
console.log(`已导出配置:${output}`);
|
|
147837
148202
|
}
|
|
147838
|
-
async function
|
|
148203
|
+
async function exportStyleRaw(options) {
|
|
147839
148204
|
const source = options.file ? resolveInputPath(options.file, [".docx"], "DOCX 文件") : undefined;
|
|
147840
|
-
const defaultName =
|
|
147841
|
-
const output = resolveOutputPath(options.output, defaultName, [".json"], "
|
|
147842
|
-
prepareOutput(output
|
|
148205
|
+
const defaultName = defaultStyleRawOutputName(source);
|
|
148206
|
+
const output = resolveOutputPath(options.output, defaultName, [".json"], "底层样式输出文件");
|
|
148207
|
+
prepareOutput(output);
|
|
147843
148208
|
if (source) {
|
|
147844
148209
|
const styles = extractStylesFromDocx(source);
|
|
147845
148210
|
writeFileSync4(output, `${JSON.stringify(styles, null, 2)}
|
|
147846
148211
|
`, "utf-8");
|
|
147847
148212
|
} else {
|
|
147848
|
-
writeFileSync4(output,
|
|
148213
|
+
writeFileSync4(output, DEFAULT_STYLE_RAW_TEXT, "utf-8");
|
|
147849
148214
|
}
|
|
147850
|
-
console.log(
|
|
148215
|
+
console.log(`已导出底层样式:${output}`);
|
|
148216
|
+
}
|
|
148217
|
+
function defaultStyleRawOutputName(source) {
|
|
148218
|
+
return source ? `${parse5(source).name}_style-raw.json` : "style-raw.json";
|
|
148219
|
+
}
|
|
148220
|
+
async function exportStyleConfig(options) {
|
|
148221
|
+
const output = resolveOutputPath(options.output, "style-config.json", [".json"], "语义化样式配置输出文件");
|
|
148222
|
+
prepareOutput(output);
|
|
148223
|
+
writeFileSync4(output, DEFAULT_STYLE_CONFIG_TEXT, "utf-8");
|
|
148224
|
+
console.log(`已导出语义化样式配置:${output}`);
|
|
147851
148225
|
}
|
|
147852
148226
|
|
|
147853
148227
|
// src/commands/format.ts
|
|
@@ -147858,17 +148232,12 @@ async function formatMarkdown(options) {
|
|
|
147858
148232
|
const configPath = options.config ? resolveInputPath(options.config, [".json"], "配置文件") : materializeDefaultConfig();
|
|
147859
148233
|
const defaultName = `${parse6(input).name}_formatted.md`;
|
|
147860
148234
|
const output = resolveOutputPath(options.output, defaultName, [".md", ".markdown"], "Markdown 输出文件");
|
|
147861
|
-
|
|
147862
|
-
prepareOutput(output, force);
|
|
148235
|
+
prepareOutput(output);
|
|
147863
148236
|
const config = await loadConfig(configPath);
|
|
147864
148237
|
const outputName = parse6(output).name;
|
|
147865
148238
|
const assetsName = `${outputName}_assets`;
|
|
147866
148239
|
const assetsDir = resolve6(dirname6(output), assetsName);
|
|
147867
148240
|
if (config.renderMermaid.enabled && existsSync7(assetsDir)) {
|
|
147868
|
-
if (!force) {
|
|
147869
|
-
throw new Error(`资源目录已存在:${assetsDir}
|
|
147870
|
-
使用 --force 覆盖现有目录`);
|
|
147871
|
-
}
|
|
147872
148241
|
const parent = resolve6(dirname6(output));
|
|
147873
148242
|
if (dirname6(assetsDir) !== parent)
|
|
147874
148243
|
throw new Error(`拒绝清理非输出目录:${assetsDir}`);
|
|
@@ -147885,7 +148254,8 @@ async function run(args) {
|
|
|
147885
148254
|
convert: convertMarkdown,
|
|
147886
148255
|
format: formatMarkdown,
|
|
147887
148256
|
exportConfig,
|
|
147888
|
-
|
|
148257
|
+
exportStyleRaw,
|
|
148258
|
+
exportStyleConfig,
|
|
147889
148259
|
clean: cleanIntermediateFiles
|
|
147890
148260
|
});
|
|
147891
148261
|
program2.exitOverride();
|