[{"data":1,"prerenderedAt":927},["ShallowReactive",2],{"lit-docx-doc:\u002Fguide\u002Fhtml":3},{"id":4,"title":5,"body":6,"description":912,"extension":913,"keywords":914,"locale":920,"meta":921,"navigation":105,"order":326,"path":922,"section":923,"seo":924,"stem":925,"__hash__":926},"docs\u002Fguide\u002Fhtml.zh-CN.md","渲染为 HTML",{"type":7,"value":8,"toc":903},"minimark",[9,23,48,53,59,168,204,207,210,228,238,241,263,466,501,505,709,721,724,756,759,793,825,828,835,884,891,894,899],[10,11,12,16,17,22],"p",{},[13,14,15],"code",{},"@quirekit\u002Flit-docx-html"," 把 DOCX 渲染成随屏幕宽度重排的 HTML，适合在网页或 App 中展示由 Word 编写的内容，\n例如用户协议、隐私政策和公告。它不分页，也不还原页面尺寸、字体和段落间距；",[18,19,21],"a",{"href":20},"\u002F","快速开始","中示例的“预览”就由它渲染。",[24,25,30],"pre",{"className":26,"code":27,"language":28,"meta":29,"style":29},"language-bash shiki shiki-themes github-light github-light github-dark","pnpm add @quirekit\u002Flit-docx-html\n","bash","",[13,31,32],{"__ignoreMap":29},[33,34,37,41,45],"span",{"class":35,"line":36},"line",1,[33,38,40],{"class":39},"sgQzM","pnpm",[33,42,44],{"class":43},"s-HEn"," add",[33,46,47],{"class":43}," @quirekit\u002Flit-docx-html\n",[49,50,52],"h2",{"id":51},"转换为-html","转换为 HTML",[10,54,55,58],{},[13,56,57],{},"docxToHtml"," 在浏览器和 Node 中都可运行。在构建时转换，页面直接输出静态 HTML，浏览器不必加载解析器：",[24,60,64],{"className":61,"code":62,"language":63,"meta":29,"style":29},"language-ts shiki shiki-themes github-light github-light github-dark","import { readFile } from \"node:fs\u002Fpromises\";\nimport { docxToHtml } from \"@quirekit\u002Flit-docx-html\";\n\nconst { html, outline, emphasis } = await docxToHtml(new Uint8Array(await readFile(\"agreement.docx\")));\n","ts",[13,65,66,85,100,107],{"__ignoreMap":29},[33,67,68,72,76,79,82],{"class":35,"line":36},[33,69,71],{"class":70},"sDD9d","import",[33,73,75],{"class":74},"sVPnS"," { readFile } ",[33,77,78],{"class":70},"from",[33,80,81],{"class":43}," \"node:fs\u002Fpromises\"",[33,83,84],{"class":74},";\n",[33,86,88,90,93,95,98],{"class":35,"line":87},2,[33,89,71],{"class":70},[33,91,92],{"class":74}," { docxToHtml } ",[33,94,78],{"class":70},[33,96,97],{"class":43}," \"@quirekit\u002Flit-docx-html\"",[33,99,84],{"class":74},[33,101,103],{"class":35,"line":102},3,[33,104,106],{"emptyLinePlaceholder":105},true,"\n",[33,108,110,113,116,120,123,126,128,131,134,137,140,143,146,149,152,154,157,160,162,165],{"class":35,"line":109},4,[33,111,112],{"class":70},"const",[33,114,115],{"class":74}," { ",[33,117,119],{"class":118},"sUNQB","html",[33,121,122],{"class":74},", ",[33,124,125],{"class":118},"outline",[33,127,122],{"class":74},[33,129,130],{"class":118},"emphasis",[33,132,133],{"class":74}," } ",[33,135,136],{"class":70},"=",[33,138,139],{"class":70}," await",[33,141,142],{"class":39}," docxToHtml",[33,144,145],{"class":74},"(",[33,147,148],{"class":70},"new",[33,150,151],{"class":39}," Uint8Array",[33,153,145],{"class":74},[33,155,156],{"class":70},"await",[33,158,159],{"class":39}," readFile",[33,161,145],{"class":74},[33,163,164],{"class":43},"\"agreement.docx\"",[33,166,167],{"class":74},")));\n",[169,170,171,188,193,198],"ul",{},[172,173,174,176,177,180,181,180,184,187],"li",{},[13,175,119],{},"：正文的 HTML 片段。文字与属性都已转义；链接只保留 ",[13,178,179],{},"http","、",[13,182,183],{},"https",[13,185,186],{},"mailto"," 与页内锚点，图片只保留内嵌的位图。",[172,189,190,192],{},[13,191,125],{},"：标题与条款，含锚点、层级、编号文字（如“第一条”“1.1”）和正文，可用来生成目录。",[172,194,195,197],{},[13,196,130],{},"：加粗或下划线的文字及其所在条款的锚点。协议通常用这种格式标出需要特别提示的条款，可以汇总展示。",[172,199,200,203],{},[13,201,202],{},"title","：文档标题，取条款开始前第一行居中的文字或第一个标题。",[49,205,206],{"id":206},"条款编号",[10,208,209],{},"Word 自动编号的段落会在渲染时加上编号文字。很多协议的编号是直接输入的文字，例如“第三条”“一、”“（一）”“4.1”“（1）”“①”，\n这些也会被识别为条款，进入目录并获得锚点，文字本身保持原样。",[169,211,212,215,218],{},[172,213,214],{},"层级按各种编号写法在文档中第一次出现的先后决定：先出现“一、”再出现“第一条”时，条在章之下；反之亦然。\nWord 编号与手工编号一起参与排序。",[172,216,217],{},"某种写法在全文只出现一次时（如“1.5 倍行距”）不当作条款；表格内的段落不当作条款。",[172,219,220,223,224,227],{},[13,221,222],{},"outlineDepth"," 控制目录列到第几级，默认 2；",[13,225,226],{},"typedClauses: false"," 关闭手工编号识别。",[10,229,230,231,234,235,237],{},"加粗或下划线只有在去掉条款号与 ",[13,232,233],{},"{{…}}"," 占位符后仍有至少 8 个文字时才计入 ",[13,236,130],{},"，加粗的条款号和下划线填空不会混入重点条款。",[49,239,240],{"id":240},"自定义渲染",[10,242,243,246,247,250,251,254,255,258,259,262],{},[13,244,245],{},"renderers"," 按节点类型、",[13,248,249],{},"markRenderers"," 按标记类型替换默认渲染。渲染函数返回 ",[13,252,253],{},"{ tag, attrs, children }","\n与文字组成的树；返回 ",[13,256,257],{},"null"," 省略该节点，返回 ",[13,260,261],{},"undefined"," 使用默认渲染：",[24,264,266],{"className":61,"code":265,"language":63,"meta":29,"style":29},"const { html } = await docxToHtml(bytes, {\n  renderers: {\n    \u002F\u002F 编号条款渲染成带编号徽标的 section\n    paragraph: (node, context) => context.number\n      ? { tag: \"section\", attrs: { class: \"clause\", id: context.anchor },\n          children: [{ tag: \"b\", children: [context.number] }, ...context.children()] }\n      : undefined,\n    \u002F\u002F 不展示表格\n    table: () => null,\n  },\n  markRenderers: {\n    \u002F\u002F 加粗文字统一标成重点\n    bold: (_mark, content) => ({ tag: \"mark\", attrs: { class: \"key-term\" }, children: content }),\n  },\n});\n",[13,267,268,287,292,298,324,345,369,381,387,403,409,415,421,455,460],{"__ignoreMap":29},[33,269,270,272,274,276,278,280,282,284],{"class":35,"line":36},[33,271,112],{"class":70},[33,273,115],{"class":74},[33,275,119],{"class":118},[33,277,133],{"class":74},[33,279,136],{"class":70},[33,281,139],{"class":70},[33,283,142],{"class":39},[33,285,286],{"class":74},"(bytes, {\n",[33,288,289],{"class":35,"line":87},[33,290,291],{"class":74},"  renderers: {\n",[33,293,294],{"class":35,"line":102},[33,295,297],{"class":296},"sqmzS","    \u002F\u002F 编号条款渲染成带编号徽标的 section\n",[33,299,300,303,306,310,312,315,318,321],{"class":35,"line":109},[33,301,302],{"class":39},"    paragraph",[33,304,305],{"class":74},": (",[33,307,309],{"class":308},"sde8i","node",[33,311,122],{"class":74},[33,313,314],{"class":308},"context",[33,316,317],{"class":74},") ",[33,319,320],{"class":70},"=>",[33,322,323],{"class":74}," context.number\n",[33,325,327,330,333,336,339,342],{"class":35,"line":326},5,[33,328,329],{"class":70},"      ?",[33,331,332],{"class":74}," { tag: ",[33,334,335],{"class":43},"\"section\"",[33,337,338],{"class":74},", attrs: { class: ",[33,340,341],{"class":43},"\"clause\"",[33,343,344],{"class":74},", id: context.anchor },\n",[33,346,348,351,354,357,360,363,366],{"class":35,"line":347},6,[33,349,350],{"class":74},"          children: [{ tag: ",[33,352,353],{"class":43},"\"b\"",[33,355,356],{"class":74},", children: [context.number] }, ",[33,358,359],{"class":70},"...",[33,361,362],{"class":74},"context.",[33,364,365],{"class":39},"children",[33,367,368],{"class":74},"()] }\n",[33,370,372,375,378],{"class":35,"line":371},7,[33,373,374],{"class":70},"      :",[33,376,377],{"class":118}," undefined",[33,379,380],{"class":74},",\n",[33,382,384],{"class":35,"line":383},8,[33,385,386],{"class":296},"    \u002F\u002F 不展示表格\n",[33,388,390,393,396,398,401],{"class":35,"line":389},9,[33,391,392],{"class":39},"    table",[33,394,395],{"class":74},": () ",[33,397,320],{"class":70},[33,399,400],{"class":118}," null",[33,402,380],{"class":74},[33,404,406],{"class":35,"line":405},10,[33,407,408],{"class":74},"  },\n",[33,410,412],{"class":35,"line":411},11,[33,413,414],{"class":74},"  markRenderers: {\n",[33,416,418],{"class":35,"line":417},12,[33,419,420],{"class":296},"    \u002F\u002F 加粗文字统一标成重点\n",[33,422,424,427,429,432,434,437,439,441,444,447,449,452],{"class":35,"line":423},13,[33,425,426],{"class":39},"    bold",[33,428,305],{"class":74},[33,430,431],{"class":308},"_mark",[33,433,122],{"class":74},[33,435,436],{"class":308},"content",[33,438,317],{"class":74},[33,440,320],{"class":70},[33,442,443],{"class":74}," ({ tag: ",[33,445,446],{"class":43},"\"mark\"",[33,448,338],{"class":74},[33,450,451],{"class":43},"\"key-term\"",[33,453,454],{"class":74}," }, children: content }),\n",[33,456,458],{"class":35,"line":457},14,[33,459,408],{"class":74},[33,461,463],{"class":35,"line":462},15,[33,464,465],{"class":74},"});\n",[10,467,468,469,472,473,476,477,180,480,483,484,488,489,492,493,496,497,500],{},"渲染上下文提供 ",[13,470,471],{},"children()","（已渲染的子节点）、",[13,474,475],{},"fallback()","（默认渲染结果）、",[13,478,479],{},"number",[13,481,482],{},"anchor"," 与祖先节点。\n节点类型与属性见 ",[18,485,487],{"href":486},"\u002Fguide\u002Flitast","LitAST 节点模型","。已解析的 LitAST 可以直接交给 ",[13,490,491],{},"renderLitDocx","，再用 ",[13,494,495],{},"toHtml","\n序列化；解析时请使用 ",[13,498,499],{},"numberingMode: \"flat-numbered-paragraphs\"","，编号文字才能按 Word 的规则计算。",[49,502,504],{"id":503},"在-vue-中使用","在 Vue 中使用",[24,506,510],{"className":507,"code":508,"language":509,"meta":29,"style":29},"language-vue shiki shiki-themes github-light github-light github-dark","\u003Cscript setup lang=\"ts\">\nimport { ref } from \"vue\";\nimport { LitDocxView } from \"@quirekit\u002Flit-docx-html\u002Fvue\";\n\ndefineProps\u003C{ bytes: Uint8Array }>();\nconst agreed = ref(false);\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003CLitDocxView :source=\"bytes\" @rendered=\"result => console.log(result.outline)\" @read-end=\"agreed = true\" \u002F>\n\u003C\u002Ftemplate>\n","vue",[13,511,512,535,549,563,567,586,607,616,620,629,701],{"__ignoreMap":29},[33,513,514,517,521,524,527,529,532],{"class":35,"line":36},[33,515,516],{"class":74},"\u003C",[33,518,520],{"class":519},"su0ou","script",[33,522,523],{"class":39}," setup",[33,525,526],{"class":39}," lang",[33,528,136],{"class":74},[33,530,531],{"class":43},"\"ts\"",[33,533,534],{"class":74},">\n",[33,536,537,539,542,544,547],{"class":35,"line":87},[33,538,71],{"class":70},[33,540,541],{"class":74}," { ref } ",[33,543,78],{"class":70},[33,545,546],{"class":43}," \"vue\"",[33,548,84],{"class":74},[33,550,551,553,556,558,561],{"class":35,"line":102},[33,552,71],{"class":70},[33,554,555],{"class":74}," { LitDocxView } ",[33,557,78],{"class":70},[33,559,560],{"class":43}," \"@quirekit\u002Flit-docx-html\u002Fvue\"",[33,562,84],{"class":74},[33,564,565],{"class":35,"line":109},[33,566,106],{"emptyLinePlaceholder":105},[33,568,569,572,575,578,581,583],{"class":35,"line":326},[33,570,571],{"class":39},"defineProps",[33,573,574],{"class":74},"\u003C{ ",[33,576,577],{"class":308},"bytes",[33,579,580],{"class":70},":",[33,582,151],{"class":39},[33,584,585],{"class":74}," }>();\n",[33,587,588,590,593,596,599,601,604],{"class":35,"line":347},[33,589,112],{"class":70},[33,591,592],{"class":118}," agreed",[33,594,595],{"class":70}," =",[33,597,598],{"class":39}," ref",[33,600,145],{"class":74},[33,602,603],{"class":118},"false",[33,605,606],{"class":74},");\n",[33,608,609,612,614],{"class":35,"line":371},[33,610,611],{"class":74},"\u003C\u002F",[33,613,520],{"class":519},[33,615,534],{"class":74},[33,617,618],{"class":35,"line":383},[33,619,106],{"emptyLinePlaceholder":105},[33,621,622,624,627],{"class":35,"line":389},[33,623,516],{"class":74},[33,625,626],{"class":519},"template",[33,628,534],{"class":74},[33,630,631,634,637,640,643,645,648,650,652,655,658,660,662,665,668,671,674,677,679,681,684,686,688,691,693,696,698],{"class":35,"line":405},[33,632,633],{"class":74},"  \u003C",[33,635,636],{"class":519},"LitDocxView",[33,638,639],{"class":74}," :",[33,641,642],{"class":39},"source",[33,644,136],{"class":74},[33,646,647],{"class":43},"\"",[33,649,577],{"class":74},[33,651,647],{"class":43},[33,653,654],{"class":74}," @",[33,656,657],{"class":39},"rendered",[33,659,136],{"class":74},[33,661,647],{"class":43},[33,663,664],{"class":308},"result",[33,666,667],{"class":70}," =>",[33,669,670],{"class":74}," console.",[33,672,673],{"class":39},"log",[33,675,676],{"class":74},"(result.outline)",[33,678,647],{"class":43},[33,680,654],{"class":74},[33,682,683],{"class":39},"read-end",[33,685,136],{"class":74},[33,687,647],{"class":43},[33,689,690],{"class":74},"agreed ",[33,692,136],{"class":70},[33,694,695],{"class":118}," true",[33,697,647],{"class":43},[33,699,700],{"class":74}," \u002F>\n",[33,702,703,705,707],{"class":35,"line":411},[33,704,611],{"class":74},[33,706,626],{"class":519},[33,708,534],{"class":74},[10,710,711,713,714,717,718,720],{},[13,712,642],{}," 接受 DOCX 字节或 LitAST；",[13,715,716],{},"options"," 传入与上面相同的自定义渲染。",[13,719,683],{}," 在文档末尾第一次进入视口时触发，\n可用于“阅读完毕后才能勾选同意”。",[49,722,723],{"id":723},"主题与静态页面",[10,725,726,727,730,731,734,735,180,738,741,742,745,746,749,750,752,753,755],{},"包内的 ",[13,728,729],{},"@quirekit\u002Flit-docx-html\u002Fstyles.css"," 是默认主题：作用于 ",[13,732,733],{},".lit-docx"," 容器，颜色与字体都是 CSS 变量（如\n",[13,736,737],{},"--lit-docx-accent",[13,739,740],{},"--lit-docx-font","），跟随系统深色模式，也可用 ",[13,743,744],{},"data-theme=\"light\""," 或 ",[13,747,748],{},"\"dark\""," 固定。\n",[13,751,636],{}," 的根元素就是 ",[13,754,733],{},"。",[10,757,758],{},"构建时可以直接用命令生成完整页面：",[24,760,762],{"className":26,"code":761,"language":28,"meta":29,"style":29},"npx lit-docx-html agreement.docx -o agreement.html --toc --key-terms --outline agreement.json\n",[13,763,764],{"__ignoreMap":29},[33,765,766,769,772,775,778,781,784,787,790],{"class":35,"line":36},[33,767,768],{"class":39},"npx",[33,770,771],{"class":43}," lit-docx-html",[33,773,774],{"class":43}," agreement.docx",[33,776,777],{"class":118}," -o",[33,779,780],{"class":43}," agreement.html",[33,782,783],{"class":118}," --toc",[33,785,786],{"class":118}," --key-terms",[33,788,789],{"class":118}," --outline",[33,791,792],{"class":43}," agreement.json\n",[10,794,795,798,799,802,803,806,807,810,811,814,815,180,818,180,821,824],{},[13,796,797],{},"--toc"," 加入目录，",[13,800,801],{},"--key-terms"," 加入重点条款，",[13,804,805],{},"--fragment"," 只输出正文片段，",[13,808,809],{},"--lang en"," 切换英文界面文字，\n",[13,812,813],{},"--outline"," 另存目录与重点条款的 JSON。在代码中可用 ",[13,816,817],{},"renderHtmlPage",[13,819,820],{},"renderToc",[13,822,823],{},"renderKeyTerms"," 组合同样的页面。",[49,826,827],{"id":827},"对比两个版本",[10,829,830,831,834],{},"协议更新后通常要告知用户改了什么。",[13,832,833],{},"compareDocx"," 按段落、标题和表格行对比两个版本，返回新增、删除与修改，并标出所在条款：",[24,836,838],{"className":61,"code":837,"language":63,"meta":29,"style":29},"import { compareDocx } from \"@quirekit\u002Flit-docx-html\";\n\nconst changes = await compareDocx(oldBytes, newBytes);\n\u002F\u002F [{ kind: \"added\", clause: { number: \"第二条\", text: \"个人信息\" }, after: \"…\" },\n\u002F\u002F  { kind: \"modified\", clause: { number: \"第三条\", text: \"服务内容\" }, before: \"…按年收取。\", after: \"…按月收取。\" }]\n",[13,839,840,853,857,874,879],{"__ignoreMap":29},[33,841,842,844,847,849,851],{"class":35,"line":36},[33,843,71],{"class":70},[33,845,846],{"class":74}," { compareDocx } ",[33,848,78],{"class":70},[33,850,97],{"class":43},[33,852,84],{"class":74},[33,854,855],{"class":35,"line":87},[33,856,106],{"emptyLinePlaceholder":105},[33,858,859,861,864,866,868,871],{"class":35,"line":102},[33,860,112],{"class":70},[33,862,863],{"class":118}," changes",[33,865,595],{"class":70},[33,867,139],{"class":70},[33,869,870],{"class":39}," compareDocx",[33,872,873],{"class":74},"(oldBytes, newBytes);\n",[33,875,876],{"class":35,"line":109},[33,877,878],{"class":296},"\u002F\u002F [{ kind: \"added\", clause: { number: \"第二条\", text: \"个人信息\" }, after: \"…\" },\n",[33,880,881],{"class":35,"line":326},[33,882,883],{"class":296},"\u002F\u002F  { kind: \"modified\", clause: { number: \"第三条\", text: \"服务内容\" }, before: \"…按年收取。\", after: \"…按月收取。\" }]\n",[10,885,886,887,890],{},"匹配时忽略手工输入的条款号，中间插入一条后，后面整体顺延的“第五条”“第六条”不会被当成修改。相邻的删除与新增\n文字相似度达到 ",[13,888,889],{},"similarity","（默认 0.4）时合并为一处修改。删除项标注旧版本中的条款，其余标注新版本中的条款。",[49,892,893],{"id":893},"许可",[10,895,896,898],{},[13,897,15],{}," 与 lit-docx 一样是 QuireKit 商业组件，适用相同的授权条款。",[900,901,902],"style",{},"html pre.shiki code .sgQzM, html code.shiki .sgQzM{--shiki-default:#6F42C1;--shiki-light:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .s-HEn, html code.shiki .s-HEn{--shiki-default:#032F62;--shiki-light:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sDD9d, html code.shiki .sDD9d{--shiki-default:#D73A49;--shiki-light:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVPnS, html code.shiki .sVPnS{--shiki-default:#24292E;--shiki-light:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sUNQB, html code.shiki .sUNQB{--shiki-default:#005CC5;--shiki-light:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sqmzS, html code.shiki .sqmzS{--shiki-default:#6A737D;--shiki-light:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sde8i, html code.shiki .sde8i{--shiki-default:#E36209;--shiki-light:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .su0ou, html code.shiki .su0ou{--shiki-default:#22863A;--shiki-light:#22863A;--shiki-dark:#85E89D}",{"title":29,"searchDepth":87,"depth":87,"links":904},[905,906,907,908,909,910,911],{"id":51,"depth":87,"text":52},{"id":206,"depth":87,"text":206},{"id":240,"depth":87,"text":240},{"id":503,"depth":87,"text":504},{"id":723,"depth":87,"text":723},{"id":827,"depth":87,"text":827},{"id":893,"depth":87,"text":893},"用 lit-docx-html 把 DOCX 渲染成随屏幕重排的语义 HTML，自定义任意节点的渲染，并取得目录与加粗、下划线的提示文字。","md",[915,916,917,240,918,919],"HTML","渲染","用户协议","目录","lit-docx-html","zh-CN",{},"\u002Fguide\u002Fhtml","指南",{"title":5,"description":912},"guide\u002Fhtml.zh-CN","i-ye8NA4n0WtrvqN3gQIjIjcQ04pbP4OuoE2dEPiSgg",1793045344143]