WordprocessingML structural elements — runs, hyperlinks, paragraphs, tables, sections, SDTs.
Module docxStructure | Source packages/front/office/ooxml/src/docx/structure.js | Deps xml, docxProperties, docxDrawing, ooxmlMath | Worker-safe yes
Every structural element has a parse<Name> / render<Name> pair that round-trips its XML. Unknown children of a container land in _extras. The model is uniform: every node carries a type and a children (or body / cells / rows).
Resolve
const s = runtime.resolve('docxStructure');
// Returns: { parseRun, renderRun,
// parseHyperlink, renderHyperlink,
// parseParagraph, renderParagraph,
// parseTable, renderTable,
// parseRow, renderRow,
// parseCell, renderCell,
// parseSection, renderSection,
// parseSdt, renderSdt,
// parseSdtProperties, renderSdtProperties,
// parseBody, renderBodyChildren }
API
| Method | Signature | Returns |
|---|---|---|
parseRun / renderRun |
(<w:r>) / (run) |
Run with typed rPr + children. |
parseHyperlink / renderHyperlink |
symmetric | <w:hyperlink>. |
parseParagraph / renderParagraph |
<w:p> |
Full paragraph. |
parseTable / renderTable |
<w:tbl> |
Table with a typed tblPr and rows. |
parseRow / renderRow |
<w:tr> |
Row with cells. |
parseCell / renderCell |
<w:tc> |
Cell with children. |
parseSection / renderSection |
<w:sectPr> |
Section properties. |
parseSdt / renderSdt |
<w:sdt> |
Structured Document Tag (templating). |
parseSdtProperties / renderSdtProperties |
<w:sdtPr> |
SDT properties. |
parseBody |
(<w:body>) => {body, sectPr, extras} |
Decomposed body. |
renderBodyChildren |
(doc) => element[] |
<w:body> children (with sectPr last). |
Model
document := { type:'document', body:[paragraph|table|blockSdt|oMathPara],
sectPr?, _extras? }
paragraph := { type:'paragraph', pPr?, children:[run|hyperlink|sdt],
_extras? }
run := { type:'run', rPr?, children:[textRun|breakRun|tabRun|drawing|…] }
textRun := { type:'text', value: string }
breakRun := { type:'break', kind?: 'page'|'column'|'line' }
tabRun := { type:'tab' }
delText := { type:'delText', value: string } // inside <w:del>
commentReference := { type:'commentReference', id }
footnoteReference / endnoteReference / softHyphen / noBreakHyphen — same shape
hyperlink := { type:'hyperlink', rId?, anchor?, target?, external?, children:[run] }
// target / external: set by docx.read when the rId resolves in
// the node's part, consumed by docx.write (see docx.md § Notes)
table := { type:'table',
tblPr?: TableProperties, // <w:tblPr>: style, width, borders, cellMargins
// (see docxProperties; other tblPr
// children live in tblPr._extras)
_extras?: [xmlNode], // <w:tblGrid> (and anything else), verbatim
rows:[{ type:'row',
cells:[{ type:'cell',
children:[paragraph|table] }] }] }
sdt := { type:'sdt', properties?: SdtProperties,
children:[run|hyperlink|sdt] } // inline, in a paragraph
blockSdt := { type:'blockSdt', properties?: SdtProperties,
children:[paragraph|table|blockSdt] } // block, in the body
SdtProperties := { alias?, tag?, id?: number, showingPlcHdr?: true,
dataBinding?: { xpath?, prefixMappings?, storeItemID? },
kind?: 'text'|'richText'|'picture'|'dropDownList'|'comboBox'
|'date'|'checkbox'|'repeatingSection'|'repeatingSectionItem',
sectionTitle?: string, // repeatingSection only
doNotAllowInsertDeleteSection?: true, // repeatingSection only
_kindNode?: xmlNode, // dropDownList / comboBox / date / checkbox, verbatim
_extras?: [xmlNode] } // any other <w:sdtPr> child, verbatim
Examples
Build a rich paragraph
const s = runtime.resolve('docxStructure');
const para = {
type: 'paragraph',
pPr: { align: 'center' },
children: [
{ type: 'run', rPr: { bold: true },
children: [{ type: 'text', value: 'Title' }] },
{ type: 'run', children: [{ type: 'break', kind: 'line' }] },
{ type: 'run', children: [{ type: 'text', value: 'subtitle' }] }
]
};
s.renderParagraph(para);
Parse a body
const root = xml.parse('<w:body>…</w:body>');
const { body, sectPr, extras } = s.parseBody(root);
// body: Array<paragraph|table|…>, sectPr: SectionProperties|undefined
Notes
<w:ins>/<w:del>(tracked changes) are parsed but their children are flattened into the parent run;delTextstays distinct fromtextso the two are never merged by accident.commentReference/footnoteReference/endnoteReferencecarry only anid; the content lives in the linked part.- Tables:
<w:tblPr>is typed astable.tblPr(style,width,borders) and rendered first, then_extras(so a preserved<w:tblGrid>still precedes the rows), then the rows. A table with notblPrrenders no<w:tblPr>(byte-identical to before).<w:tblGrid>and each row's<w:trPr>are NOT typed here: they stay verbatim in_extras(table._extras/row._extras); cell borders (<w:tcBorders>) stay in the cell'stcPr._extras. The opt-inwmlTablePropertiespromotes those. oMathParanodes are delegated toooxmlMath.- Drawings are delegated to
docxDrawing. - SDTs (Structured Document Tags) type the
alias,tag,id,showingPlcHdranddataBindingchildren of<w:sdtPr>plus thekindelement; anything else (<w:placeholder>,<w:rPr>,<w:lock>, …) stays verbatim inproperties._extras— see templating. - Repeating sections are a Word 2012 extension ([MS-DOCX] §2.5.1.10, §2.5.1.11, §2.5.3.8), not ECMA-376 elements.
parseSdtPropertiesreads<w15:repeatingSection>askind: 'repeatingSection', its<w15:sectionTitle w:val>child assectionTitleand its<w15:doNotAllowInsertDeleteSection>child (on/off: an absentw:val,1,trueoronmean on) asdoNotAllowInsertDeleteSection: true;<w15:repeatingSectionItem/>reads askind: 'repeatingSectionItem'. The legacy main-namespace form (<w:repeatingSection w:sectionTitle="…"/>,<w:repeatingSectionItem/>) is still read.renderSdtPropertieswrites thew15elements only, title before the lock; declaring thew15namespace on the part root is the caller's job (docx.writedoes it forword/document.xml).
See also
- docx — top-level orchestrator.
- docx-properties — delegated formatting.
- math — inline and block math.