[{"data":1,"prerenderedAt":970},["ShallowReactive",2],{"lit-docx-doc:\u002Fen\u002Fguide\u002Fhtml":3},{"id":4,"title":5,"body":6,"description":955,"extension":956,"keywords":957,"locale":963,"meta":964,"navigation":105,"order":366,"path":965,"section":966,"seo":967,"stem":968,"__hash__":969},"docs\u002Fguide\u002Fhtml.en.md","Rendering to HTML",{"type":7,"value":8,"toc":946},"minimark",[9,23,48,53,59,168,207,211,238,267,277,281,303,506,541,545,749,761,765,796,799,833,866,870,877,926,933,937,942],[10,11,12,16,17,22],"p",{},[13,14,15],"code",{},"@quirekit\u002Flit-docx-html"," renders DOCX as HTML that reflows to the screen width. It suits Word-authored content shown\non websites or in apps, such as user agreements, privacy policies and announcements. It does not paginate or\nreproduce page size, fonts or paragraph spacing; the Preview of the ",[18,19,21],"a",{"href":20},"\u002Fen","Quick start"," example is rendered by it.",[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},"convert-to-html","Convert to HTML",[10,54,55,58],{},[13,56,57],{},"docxToHtml"," runs in browsers and in Node. Converting at build time lets pages ship static HTML without loading\nthe parser in the browser:",[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,187,196,201],"ul",{},[172,173,174,176,177,122,180,122,183,186],"li",{},[13,175,119],{},": the body as an HTML fragment. Text and attributes are escaped; links keep only ",[13,178,179],{},"http",[13,181,182],{},"https",[13,184,185],{},"mailto","\nand in-page anchors, and images keep only embedded raster data.",[172,188,189,191,192,195],{},[13,190,125],{},": headings and clauses with anchor, level, number text (such as ",[13,193,194],{},"1.1",") and text, for a table of contents.",[172,197,198,200],{},[13,199,130],{},": bold or underlined passages with the anchor of their clause. Agreements usually mark terms that need\nspecial attention this way, so they can be listed together.",[172,202,203,206],{},[13,204,205],{},"title",": the document title, taken from the first centered line before any clause or the first heading.",[49,208,210],{"id":209},"clause-numbers","Clause numbers",[10,212,213,214,122,217,122,220,122,223,122,226,229,230,233,234,237],{},"Paragraphs numbered by Word get their number text when rendered. Many agreements type the numbers instead, such as\n",[13,215,216],{},"第三条",[13,218,219],{},"一、",[13,221,222],{},"（一）",[13,224,225],{},"4.1",[13,227,228],{},"(1)"," or ",[13,231,232],{},"①",", or ",[13,235,236],{},"Section 2","; these are recognized as clauses too, enter the outline\nand get anchors, while the text stays as written.",[169,239,240,250,257],{},[172,241,242,243,245,246,249],{},"Levels follow the order in which each numbering style first appears: when ",[13,244,219],{}," comes before ",[13,247,248],{},"第一条",", articles nest\nunder sections, and the other way round. Word numbering and typed numbers are ranked together.",[172,251,252,253,256],{},"A style used only once in the document (such as ",[13,254,255],{},"1.5 times spacing",") is not a clause, and paragraphs inside tables never are.",[172,258,259,262,263,266],{},[13,260,261],{},"outlineDepth"," sets how many levels the outline lists, 2 by default; ",[13,264,265],{},"typedClauses: false"," turns typed numbers off.",[10,268,269,270,272,273,276],{},"Bold or underlined text counts toward ",[13,271,130],{}," only when at least 8 letters remain after removing the clause number\nand ",[13,274,275],{},"{{…}}"," placeholders, so bold clause numbers and underlined blanks do not enter the key terms.",[49,278,280],{"id":279},"custom-rendering","Custom rendering",[10,282,283,286,287,290,291,294,295,298,299,302],{},[13,284,285],{},"renderers"," replaces the default rendering by node type and ",[13,288,289],{},"markRenderers"," by mark type. A renderer returns a tree\nof ",[13,292,293],{},"{ tag, attrs, children }"," and strings; ",[13,296,297],{},"null"," omits the node and ",[13,300,301],{},"undefined"," uses the default:",[24,304,306],{"className":61,"code":305,"language":63,"meta":29,"style":29},"const { html } = await docxToHtml(bytes, {\n  renderers: {\n    \u002F\u002F Numbered clauses become sections with a number badge\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 Hide tables\n    table: () => null,\n  },\n  markRenderers: {\n    \u002F\u002F Mark all bold text as key terms\n    bold: (_mark, content) => ({ tag: \"mark\", attrs: { class: \"key-term\" }, children: content }),\n  },\n});\n",[13,307,308,327,332,338,364,385,409,421,427,443,449,455,461,495,500],{"__ignoreMap":29},[33,309,310,312,314,316,318,320,322,324],{"class":35,"line":36},[33,311,112],{"class":70},[33,313,115],{"class":74},[33,315,119],{"class":118},[33,317,133],{"class":74},[33,319,136],{"class":70},[33,321,139],{"class":70},[33,323,142],{"class":39},[33,325,326],{"class":74},"(bytes, {\n",[33,328,329],{"class":35,"line":87},[33,330,331],{"class":74},"  renderers: {\n",[33,333,334],{"class":35,"line":102},[33,335,337],{"class":336},"sqmzS","    \u002F\u002F Numbered clauses become sections with a number badge\n",[33,339,340,343,346,350,352,355,358,361],{"class":35,"line":109},[33,341,342],{"class":39},"    paragraph",[33,344,345],{"class":74},": (",[33,347,349],{"class":348},"sde8i","node",[33,351,122],{"class":74},[33,353,354],{"class":348},"context",[33,356,357],{"class":74},") ",[33,359,360],{"class":70},"=>",[33,362,363],{"class":74}," context.number\n",[33,365,367,370,373,376,379,382],{"class":35,"line":366},5,[33,368,369],{"class":70},"      ?",[33,371,372],{"class":74}," { tag: ",[33,374,375],{"class":43},"\"section\"",[33,377,378],{"class":74},", attrs: { class: ",[33,380,381],{"class":43},"\"clause\"",[33,383,384],{"class":74},", id: context.anchor },\n",[33,386,388,391,394,397,400,403,406],{"class":35,"line":387},6,[33,389,390],{"class":74},"          children: [{ tag: ",[33,392,393],{"class":43},"\"b\"",[33,395,396],{"class":74},", children: [context.number] }, ",[33,398,399],{"class":70},"...",[33,401,402],{"class":74},"context.",[33,404,405],{"class":39},"children",[33,407,408],{"class":74},"()] }\n",[33,410,412,415,418],{"class":35,"line":411},7,[33,413,414],{"class":70},"      :",[33,416,417],{"class":118}," undefined",[33,419,420],{"class":74},",\n",[33,422,424],{"class":35,"line":423},8,[33,425,426],{"class":336},"    \u002F\u002F Hide tables\n",[33,428,430,433,436,438,441],{"class":35,"line":429},9,[33,431,432],{"class":39},"    table",[33,434,435],{"class":74},": () ",[33,437,360],{"class":70},[33,439,440],{"class":118}," null",[33,442,420],{"class":74},[33,444,446],{"class":35,"line":445},10,[33,447,448],{"class":74},"  },\n",[33,450,452],{"class":35,"line":451},11,[33,453,454],{"class":74},"  markRenderers: {\n",[33,456,458],{"class":35,"line":457},12,[33,459,460],{"class":336},"    \u002F\u002F Mark all bold text as key terms\n",[33,462,464,467,469,472,474,477,479,481,484,487,489,492],{"class":35,"line":463},13,[33,465,466],{"class":39},"    bold",[33,468,345],{"class":74},[33,470,471],{"class":348},"_mark",[33,473,122],{"class":74},[33,475,476],{"class":348},"content",[33,478,357],{"class":74},[33,480,360],{"class":70},[33,482,483],{"class":74}," ({ tag: ",[33,485,486],{"class":43},"\"mark\"",[33,488,378],{"class":74},[33,490,491],{"class":43},"\"key-term\"",[33,493,494],{"class":74}," }, children: content }),\n",[33,496,498],{"class":35,"line":497},14,[33,499,448],{"class":74},[33,501,503],{"class":35,"line":502},15,[33,504,505],{"class":74},"});\n",[10,507,508,509,512,513,516,517,122,520,523,524,528,529,532,533,536,537,540],{},"The context provides ",[13,510,511],{},"children()"," (rendered children), ",[13,514,515],{},"fallback()"," (the default rendering), ",[13,518,519],{},"number",[13,521,522],{},"anchor"," and the\nancestors. See the ",[18,525,527],{"href":526},"\u002Fen\u002Fguide\u002Flitast","LitAST node model"," for node types and attributes. Parsed LitAST can go straight\nto ",[13,530,531],{},"renderLitDocx"," and be serialized with ",[13,534,535],{},"toHtml","; parse with ",[13,538,539],{},"numberingMode: \"flat-numbered-paragraphs\""," so number\ntext follows Word's rules.",[49,542,544],{"id":543},"in-vue","In Vue",[24,546,550],{"className":547,"code":548,"language":549,"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,551,552,575,589,603,607,626,647,656,660,669,741],{"__ignoreMap":29},[33,553,554,557,561,564,567,569,572],{"class":35,"line":36},[33,555,556],{"class":74},"\u003C",[33,558,560],{"class":559},"su0ou","script",[33,562,563],{"class":39}," setup",[33,565,566],{"class":39}," lang",[33,568,136],{"class":74},[33,570,571],{"class":43},"\"ts\"",[33,573,574],{"class":74},">\n",[33,576,577,579,582,584,587],{"class":35,"line":87},[33,578,71],{"class":70},[33,580,581],{"class":74}," { ref } ",[33,583,78],{"class":70},[33,585,586],{"class":43}," \"vue\"",[33,588,84],{"class":74},[33,590,591,593,596,598,601],{"class":35,"line":102},[33,592,71],{"class":70},[33,594,595],{"class":74}," { LitDocxView } ",[33,597,78],{"class":70},[33,599,600],{"class":43}," \"@quirekit\u002Flit-docx-html\u002Fvue\"",[33,602,84],{"class":74},[33,604,605],{"class":35,"line":109},[33,606,106],{"emptyLinePlaceholder":105},[33,608,609,612,615,618,621,623],{"class":35,"line":366},[33,610,611],{"class":39},"defineProps",[33,613,614],{"class":74},"\u003C{ ",[33,616,617],{"class":348},"bytes",[33,619,620],{"class":70},":",[33,622,151],{"class":39},[33,624,625],{"class":74}," }>();\n",[33,627,628,630,633,636,639,641,644],{"class":35,"line":387},[33,629,112],{"class":70},[33,631,632],{"class":118}," agreed",[33,634,635],{"class":70}," =",[33,637,638],{"class":39}," ref",[33,640,145],{"class":74},[33,642,643],{"class":118},"false",[33,645,646],{"class":74},");\n",[33,648,649,652,654],{"class":35,"line":411},[33,650,651],{"class":74},"\u003C\u002F",[33,653,560],{"class":559},[33,655,574],{"class":74},[33,657,658],{"class":35,"line":423},[33,659,106],{"emptyLinePlaceholder":105},[33,661,662,664,667],{"class":35,"line":429},[33,663,556],{"class":74},[33,665,666],{"class":559},"template",[33,668,574],{"class":74},[33,670,671,674,677,680,683,685,688,690,692,695,698,700,702,705,708,711,714,717,719,721,724,726,728,731,733,736,738],{"class":35,"line":445},[33,672,673],{"class":74},"  \u003C",[33,675,676],{"class":559},"LitDocxView",[33,678,679],{"class":74}," :",[33,681,682],{"class":39},"source",[33,684,136],{"class":74},[33,686,687],{"class":43},"\"",[33,689,617],{"class":74},[33,691,687],{"class":43},[33,693,694],{"class":74}," @",[33,696,697],{"class":39},"rendered",[33,699,136],{"class":74},[33,701,687],{"class":43},[33,703,704],{"class":348},"result",[33,706,707],{"class":70}," =>",[33,709,710],{"class":74}," console.",[33,712,713],{"class":39},"log",[33,715,716],{"class":74},"(result.outline)",[33,718,687],{"class":43},[33,720,694],{"class":74},[33,722,723],{"class":39},"read-end",[33,725,136],{"class":74},[33,727,687],{"class":43},[33,729,730],{"class":74},"agreed ",[33,732,136],{"class":70},[33,734,735],{"class":118}," true",[33,737,687],{"class":43},[33,739,740],{"class":74}," \u002F>\n",[33,742,743,745,747],{"class":35,"line":451},[33,744,651],{"class":74},[33,746,666],{"class":559},[33,748,574],{"class":74},[10,750,751,753,754,757,758,760],{},[13,752,682],{}," accepts DOCX bytes or LitAST, and ",[13,755,756],{},"options"," takes the custom renderers above. ",[13,759,723],{}," fires the first time\nthe end of the document enters the viewport, for “agree after reading” checkboxes.",[49,762,764],{"id":763},"theme-and-static-pages","Theme and static pages",[10,766,767,770,771,774,775,778,779,782,783,229,786,789,790,792,793,795],{},[13,768,769],{},"@quirekit\u002Flit-docx-html\u002Fstyles.css"," is the default theme. It applies to the ",[13,772,773],{},".lit-docx"," container, exposes colors and\nfonts as CSS variables (such as ",[13,776,777],{},"--lit-docx-accent"," and ",[13,780,781],{},"--lit-docx-font","), follows the system dark mode and can be\nfixed with ",[13,784,785],{},"data-theme=\"light\"",[13,787,788],{},"\"dark\"",". The root element of ",[13,791,676],{}," is ",[13,794,773],{},".",[10,797,798],{},"At build time a command generates a complete page:",[24,800,802],{"className":26,"code":801,"language":28,"meta":29,"style":29},"npx lit-docx-html agreement.docx -o agreement.html --toc --key-terms --outline agreement.json\n",[13,803,804],{"__ignoreMap":29},[33,805,806,809,812,815,818,821,824,827,830],{"class":35,"line":36},[33,807,808],{"class":39},"npx",[33,810,811],{"class":43}," lit-docx-html",[33,813,814],{"class":43}," agreement.docx",[33,816,817],{"class":118}," -o",[33,819,820],{"class":43}," agreement.html",[33,822,823],{"class":118}," --toc",[33,825,826],{"class":118}," --key-terms",[33,828,829],{"class":118}," --outline",[33,831,832],{"class":43}," agreement.json\n",[10,834,835,838,839,842,843,846,847,850,851,854,855,122,858,861,862,865],{},[13,836,837],{},"--toc"," adds the table of contents, ",[13,840,841],{},"--key-terms"," the key terms, ",[13,844,845],{},"--fragment"," outputs only the body, ",[13,848,849],{},"--lang en"," switches\nthe interface text, and ",[13,852,853],{},"--outline"," saves the outline and key terms as JSON. In code, ",[13,856,857],{},"renderHtmlPage",[13,859,860],{},"renderToc"," and\n",[13,863,864],{},"renderKeyTerms"," compose the same page.",[49,867,869],{"id":868},"compare-two-versions","Compare two versions",[10,871,872,873,876],{},"After an agreement changes, users usually need to know what changed. ",[13,874,875],{},"compareDocx"," compares paragraphs, headings and\ntable rows of two versions and returns additions, removals and modifications with their clause:",[24,878,880],{"className":61,"code":879,"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: \"Section 2\", text: \"Personal data\" }, after: \"…\" },\n\u002F\u002F  { kind: \"modified\", clause: { number: \"Section 3\", text: \"Services\" }, before: \"…billed yearly.\", after: \"…billed monthly.\" }]\n",[13,881,882,895,899,916,921],{"__ignoreMap":29},[33,883,884,886,889,891,893],{"class":35,"line":36},[33,885,71],{"class":70},[33,887,888],{"class":74}," { compareDocx } ",[33,890,78],{"class":70},[33,892,97],{"class":43},[33,894,84],{"class":74},[33,896,897],{"class":35,"line":87},[33,898,106],{"emptyLinePlaceholder":105},[33,900,901,903,906,908,910,913],{"class":35,"line":102},[33,902,112],{"class":70},[33,904,905],{"class":118}," changes",[33,907,635],{"class":70},[33,909,139],{"class":70},[33,911,912],{"class":39}," compareDocx",[33,914,915],{"class":74},"(oldBytes, newBytes);\n",[33,917,918],{"class":35,"line":109},[33,919,920],{"class":336},"\u002F\u002F [{ kind: \"added\", clause: { number: \"Section 2\", text: \"Personal data\" }, after: \"…\" },\n",[33,922,923],{"class":35,"line":366},[33,924,925],{"class":336},"\u002F\u002F  { kind: \"modified\", clause: { number: \"Section 3\", text: \"Services\" }, before: \"…billed yearly.\", after: \"…billed monthly.\" }]\n",[10,927,928,929,932],{},"Typed clause numbers are ignored when matching, so inserting a clause does not mark every renumbered clause after it\nas modified. Adjacent removed and added text whose similarity reaches ",[13,930,931],{},"similarity"," (0.4 by default) becomes one\nmodification. Removals carry the clause of the old version; other changes carry the clause of the new version.",[49,934,936],{"id":935},"license","License",[10,938,939,941],{},[13,940,15],{}," is a QuireKit commercial component under the same license terms as lit-docx.",[943,944,945],"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":947},[948,949,950,951,952,953,954],{"id":51,"depth":87,"text":52},{"id":209,"depth":87,"text":210},{"id":279,"depth":87,"text":280},{"id":543,"depth":87,"text":544},{"id":763,"depth":87,"text":764},{"id":868,"depth":87,"text":869},{"id":935,"depth":87,"text":936},"Render DOCX to reflowing semantic HTML with lit-docx-html, replace the rendering of any node, and get an outline and the bold or underlined passages.","md",[958,959,960,961,125,962],"HTML","rendering","user agreement","custom rendering","lit-docx-html","en",{},"\u002Fen\u002Fguide\u002Fhtml","Guides",{"title":5,"description":955},"guide\u002Fhtml.en","36EgrbR5rxOTkSXlGLxsZ_dLXXIslBYdKZezBx4ieV0",1793045343968]