data-dw-* Attributes
This page is the authoritative specification of the data-dw-* attribute system used by docwow's HTML output.
Every element in a docwow HTML document carries two things:
- CSS classes — control visual appearance in the browser
data-dw-*attributes — carry Word metadata needed for lossless round-trip back to DOCX
If you are building a browser-based editor on top of docwow, you must preserve all data-dw-* attributes on every element. Stripping them will cause information loss when converting back to DOCX.
Document container
<div class="dw-document"
data-dw-page-width="595.28"
data-dw-page-height="841.89"
data-dw-margin-top="72.0"
data-dw-margin-right="72.0"
data-dw-margin-bottom="72.0"
data-dw-margin-left="72.0">
All dimension values are in points (pt).
| Attribute | Type | Description |
|---|---|---|
data-dw-page-width |
float (pt) | Page width |
data-dw-page-height |
float (pt) | Page height |
data-dw-margin-top |
float (pt) | Top margin |
data-dw-margin-right |
float (pt) | Right margin |
data-dw-margin-bottom |
float (pt) | Bottom margin |
data-dw-margin-left |
float (pt) | Left margin |
Paragraphs (<p class="dw-p">)
<p class="dw-p dw-style-Normal"
data-dw-style="Normal"
data-dw-align="justify"
data-dw-indent-left="36.0"
data-dw-indent-right="0.0"
data-dw-indent-first-line="18.0"
data-dw-space-before="12.0"
data-dw-space-after="6.0"
data-dw-line-spacing="14.0"
data-dw-page-break-before="true"
data-dw-keep-together="true"
data-dw-keep-with-next="true">
Paragraph attributes
| Attribute | Type | Description |
|---|---|---|
data-dw-style |
string | Named Word style ID (e.g. Normal, Heading1) |
data-dw-align |
string | left | center | right | justify |
data-dw-indent-left |
float (pt) | Left indent |
data-dw-indent-right |
float (pt) | Right indent |
data-dw-indent-first-line |
float (pt) | First-line indent. Negative value = hanging indent |
data-dw-space-before |
float (pt) | Space before paragraph |
data-dw-space-after |
float (pt) | Space after paragraph |
data-dw-line-spacing |
float (pt) | Exact line spacing. Absent = auto |
data-dw-page-break-before |
"true" |
Forces a page break before this paragraph |
data-dw-keep-together |
"true" |
Keep all lines of paragraph on same page |
data-dw-keep-with-next |
"true" |
Keep this paragraph on same page as the next |
data-dw-shading |
hex RGB string | Paragraph background shading color (e.g. 4472C4). Absent = no shading |
data-dw-tab-stops |
string | Comma-separated tab stops: pos:align or pos:align:leader (e.g. 36pt:left,144pt:right:dot). Absent = no custom stops |
data-dw-borders |
string | Pipe-separated paragraph borders: side:style:width_pt:color (e.g. top:single:0.5:FF0000\|bottom:single:0.5:). Absent = no borders |
List paragraph attributes
When a paragraph belongs to a list, it gains two additional attributes:
| Attribute | Type | Description |
|---|---|---|
data-dw-num-id |
string | Numbering definition ID (matches data-dw-num-id on the <ul>/<ol>) |
data-dw-level |
integer | List nesting level, 0-based |
Section break attributes
Section breaks render as <div class="dw-section-break"> elements (always display:none):
| Attribute | Type | Description |
|---|---|---|
data-dw-break-type |
string | nextPage | evenPage | oddPage | continuous |
data-dw-page-width |
float (pt) | Page width of the section |
data-dw-page-height |
float (pt) | Page height of the section |
data-dw-margin-top |
float (pt) | Top margin |
data-dw-margin-bottom |
float (pt) | Bottom margin |
data-dw-margin-left |
float (pt) | Left margin |
data-dw-margin-right |
float (pt) | Right margin |
Cross-reference attributes
Cross-references render as <a class="dw-xref"> elements:
| Attribute | Type | Description |
|---|---|---|
data-dw-xref |
string | Target bookmark name (matches a data-dw-bookmark anchor elsewhere in the document) |
Runs (<span class="dw-r">)
<span class="dw-r dw-cstyle-Strong"
data-dw-bold="true"
data-dw-italic="true"
data-dw-underline="true"
data-dw-strike="true"
data-dw-font="Arial"
data-dw-size="14.0"
data-dw-color="FF0000"
data-dw-highlight="yellow"
data-dw-valign="superscript"
data-dw-char-style="Strong">
text content
</span>
| Attribute | Type | Description |
|---|---|---|
data-dw-bold |
"true" |
Bold |
data-dw-italic |
"true" |
Italic |
data-dw-underline |
"true" |
Underline |
data-dw-strike |
"true" |
Strikethrough |
data-dw-small-caps |
"true" |
Small caps (lowercase letters rendered as smaller uppercase) |
data-dw-all-caps |
"true" |
All caps (all letters rendered as uppercase) |
data-dw-vanish |
"true" |
Hidden text (w:vanish); rendered as display:none in HTML |
data-dw-font |
string | Font family name |
data-dw-size |
float (pt) | Font size |
data-dw-color |
string | Font color as 6-digit hex, no # (e.g. FF0000) |
data-dw-highlight |
string | Highlight color name (e.g. yellow, cyan, red) |
data-dw-valign |
string | superscript | subscript |
data-dw-char-style |
string | Named Word character style ID (e.g. Strong, Emphasis). Absent = no character style |
When a character style is applied, the span also gains a CSS class dw-cstyle-{id} (e.g. dw-cstyle-Strong) for CSS-based styling.
Boolean attributes (data-dw-bold, etc.) are only present when true; their absence means false.
Newlines within a run are represented as literal \n characters in the text content (preserved by white-space: pre-wrap in CSS).
Tables (<table class="dw-table">)
<table class="dw-table"
data-dw-style="TableGrid"
data-dw-width="360.0"
data-dw-col-widths="120.0,120.0,120.0">
| Attribute | Type | Description |
|---|---|---|
data-dw-style |
string | Word table style ID |
data-dw-width |
float (pt) | Total table width |
data-dw-col-widths |
comma-separated floats (pt) | Width of each column, in order |
Table cells (<td class="dw-td">)
| Attribute | Type | Description |
|---|---|---|
colspan |
integer | HTML standard colspan (column span) |
data-dw-width |
float (pt) | Cell width |
data-dw-v-merge-start |
"true" |
This cell starts a vertical merge group |
data-dw-v-merge-continue |
"true" |
This cell continues a vertical merge (is a continuation row) |
data-dw-shading |
hex RGB string | Cell background shading color (e.g. ED7D31). Absent = no shading |
Note
Vertically merged cells use the standard HTML rowspan attribute for visual rendering,
but data-dw-v-merge-start / data-dw-v-merge-continue are also written so the
round-trip reconstructs Word's <w:vMerge> elements exactly.
Lists (<ul> / <ol>)
<ul class="dw-list"
data-dw-num-id="1"
data-dw-num-fmt="bullet">
<ol class="dw-list"
data-dw-num-id="2"
data-dw-num-fmt="decimal">
| Attribute | Type | Description |
|---|---|---|
data-dw-num-id |
string | Numbering definition ID — links list paragraphs to this list |
data-dw-num-fmt |
string | bullet | decimal | lowerLetter | upperLetter | lowerRoman | upperRoman |
Nested lists are represented as nested <ul>/<ol> elements inside <li> elements, matching the HTML spec. Each nesting level inherits the data-dw-num-id of its parent list.
Inline images (<img class="dw-img">)
<img class="dw-img"
src="data:image/png;base64,iVBOR..."
data-dw-width="72.0"
data-dw-height="36.0"
data-dw-content-type="image/png"
alt="Chart 1">
| Attribute | Type | Description |
|---|---|---|
src |
data URI | Image bytes encoded as base64 (data:<content-type>;base64,<data>) |
data-dw-width |
float (pt) | Rendered width in points |
data-dw-height |
float (pt) | Rendered height in points |
data-dw-content-type |
string | MIME type (e.g. image/png, image/jpeg) |
alt |
string | Alt text from Word's image description |
Headers and footers (<header> / <footer>)
<header class="dw-header dw-header-default" data-dw-header-type="default">
<p class="dw-p">...</p>
</header>
<footer class="dw-footer dw-footer-default" data-dw-footer-type="default">
<p class="dw-p dw-page-only">...</p>
</footer>
| Attribute | Type | Description |
|---|---|---|
data-dw-header-type |
string | default | first | even — which slot this header occupies |
data-dw-footer-type |
string | default | first | even — which slot this footer occupies |
The data-dw-title-pg attribute on the document div signals that a different first-page header/footer is active:
| Attribute | Type | Description |
|---|---|---|
data-dw-title-pg |
"true" |
Document uses a distinct first-page header/footer |
Floating images (<figure class="dw-float-img">)
Floating images are rendered as <figure> elements (or <span> for wrap="none" to stay inside the paragraph's stacking context). The inner <img> carries the base64 data URI; all positioning metadata is on the outer element.
<figure class="dw-float-img"
style="float:left;margin:0 8pt 4pt 0;z-index:1;"
data-dw-float-wrap="square"
data-dw-float-h-anchor="column"
data-dw-float-v-anchor="paragraph"
data-dw-float-pos-h="72pt"
data-dw-float-pos-v="36pt"
data-dw-float-behind="false"
data-dw-rid="rId5"
data-dw-width="144pt"
data-dw-height="72pt">
<img src="data:image/png;base64,iVBOR..."
alt="Company logo"
style="width:144pt;height:72pt;display:block">
</figure>
| Attribute | Type | Description |
|---|---|---|
data-dw-float-wrap |
string | Text wrapping type: square | tight | topAndBottom | through | none |
data-dw-float-h-anchor |
string | Horizontal reference frame: margin | page | column | character |
data-dw-float-v-anchor |
string | Vertical reference frame: margin | page | paragraph | line |
data-dw-float-pos-h |
CSS string (e.g. 72pt) |
Horizontal offset from the h-anchor origin |
data-dw-float-pos-v |
CSS string (e.g. 36pt) |
Vertical offset from the v-anchor origin |
data-dw-float-behind |
"true" / "false" |
Whether the image floats behind body text |
data-dw-rid |
string | Original OOXML relationship ID — used on round-trip to preserve the relationship |
data-dw-width |
CSS string (e.g. 144pt) |
Rendered width |
data-dw-height |
CSS string (e.g. 72pt) |
Rendered height |
The image content type is derived from the base64 data URI (data:<content-type>;base64,...). The HTML parser reads this to reconstruct the binary image data.
Page number fields (<span class="dw-field">)
<span class="dw-field" data-dw-field="PAGE">1</span>
<span class="dw-field" data-dw-field="NUMPAGES">1</span>
<span class="dw-field" data-dw-field="DATE">2025-01-01</span>
| Attribute | Value | Description |
|---|---|---|
data-dw-field |
PAGE |
Current page number (static placeholder 1 in HTML) |
data-dw-field |
NUMPAGES |
Total page count (static placeholder 1 in HTML) |
data-dw-field |
SECTIONPAGES |
Pages in the current section (static placeholder 1 in HTML) |
data-dw-field |
DATE |
Document date (rendered as a static string in HTML) |
data-dw-field |
TIME |
Document time (rendered as a static string in HTML) |
data-dw-field |
AUTHOR |
Document author (rendered as a static string in HTML) |
data-dw-field |
TITLE |
Document title (rendered as a static string in HTML) |
data-dw-field |
FILENAME |
File name (rendered as a static string in HTML) |
The HTML parser reads data-dw-field to reconstruct the PageNumberField model on round-trip — the displayed text content is ignored.
Page breaks (<div class="dw-page-break">)
| Attribute | Type | Description |
|---|---|---|
data-dw-page |
integer | The page number that begins after this break |
Always display:none. Preserved for round-trip only.
Footnote and endnote references (<a class="dw-footnote-ref">)
| Attribute | Type | Description |
|---|---|---|
class |
string | dw-footnote-ref for footnotes, dw-endnote-ref for endnotes |
href |
string | Anchor link to the note body (#fn-N for footnotes, #en-N for endnotes) |
data-dw-note-type |
string | footnote | endnote |
data-dw-note-id |
integer (as string) | The note ID (matches the body section entry) |
Footnote and endnote sections (<section>)
<section class="dw-footnotes" data-dw-note-section="footnotes">
<div class="dw-fn" id="fn-1" data-dw-note-id="1" data-dw-note-type="footnote">
<span class="dw-fn-marker">[1]</span>
<div class="dw-fn-body">
<p class="dw-p">Footnote content.</p>
</div>
</div>
</section>
<section class="dw-endnotes" data-dw-note-section="endnotes">
<div class="dw-en" id="en-1" data-dw-note-id="1" data-dw-note-type="endnote">
<span class="dw-en-marker">[1]</span>
<div class="dw-fn-body">
<p class="dw-p">Endnote content.</p>
</div>
</div>
</section>
| Element / Attribute | Description |
|---|---|
<section class="dw-footnotes"> |
Container for all footnote bodies |
<section class="dw-endnotes"> |
Container for all endnote bodies |
data-dw-note-section |
footnotes | endnotes |
<div class="dw-fn"> / <div class="dw-en"> |
Individual note body container |
id |
fn-N (footnotes) or en-N (endnotes) — anchored from body references |
data-dw-note-id |
Integer note ID as string |
data-dw-note-type |
footnote | endnote |
<span class="dw-fn-marker"> / <span class="dw-en-marker"> |
Visual marker (e.g. [1]) |
<div class="dw-fn-body"> |
Container for note paragraph content |
Bookmark anchors (<a class="dw-bookmark">)
A zero-width anchor that marks the position of a Word w:bookmarkStart element.
| Attribute | Type | Description |
|---|---|---|
id |
string | The bookmark name — used as the fragment target for #name links |
class |
string | Always dw-bookmark |
data-dw-bookmark |
string | The bookmark name (same as id; used by the HTML parser to reconstruct the model) |
The element is always empty (no text content). Anchor hyperlinks pointing to #name resolve to the bookmark with the matching id.
Table of Contents (<nav class="dw-toc">)
<nav class="dw-toc"
data-dw-toc="true"
data-dw-toc-title="Contents">
<p class="dw-toc-title">Contents</p>
<ul class="dw-toc-list">
<li class="dw-toc-entry dw-toc-level-1" data-dw-toc-level="1">
<a class="dw-toc-link" href="#_Toc123456789">Introduction</a>
</li>
<li class="dw-toc-entry dw-toc-level-2" data-dw-toc-level="2">
<span class="dw-toc-text">Background</span>
</li>
</ul>
</nav>
Represents a Word w:sdt structured document tag that contains a table of contents.
| Element / Attribute | Description |
|---|---|
<nav class="dw-toc"> |
Container for the whole TOC block |
data-dw-toc |
Always "true" — marks the element as a TOC for the HTML parser |
data-dw-toc-title |
The TOC heading text — used to reconstruct the model on round-trip |
<p class="dw-toc-title"> |
Visible heading paragraph — omitted when the title is empty |
<ul class="dw-toc-list"> |
Ordered list of TOC entries |
<li class="dw-toc-entry dw-toc-level-N"> |
One TOC entry; N is 1–9 |
data-dw-toc-level |
Integer level of this entry (1–9) |
<a class="dw-toc-link" href="…"> |
Clickable link to the heading anchor (when a URL is available) |
<span class="dw-toc-text"> |
Non-linked entry text (when no anchor URL is available) |
Track changes (<ins class="dw-ins"> / <del class="dw-del">)
Insertions use <ins> and deletions use <del>. Both carry the same set of data-dw-* attributes. A hover popup with Accept/Reject buttons is injected by the renderer as a child <span class="dw-tc-popup"> — this span is ignored by the HTML parser on round-trip.
<ins class="dw-ins"
data-dw-author="Alice"
data-dw-date="2025-07-10T09:00:00Z"
data-dw-change-id="1">
<span class="dw-tc-popup">...</span>
<span class="dw-r">inserted text</span>
</ins>
<del class="dw-del"
data-dw-author="Alice"
data-dw-date="2025-07-10T09:00:00Z"
data-dw-change-id="2">
<span class="dw-tc-popup">...</span>
<span class="dw-r">deleted text</span>
</del>
| Attribute | Type | Description |
|---|---|---|
data-dw-author |
string | Reviewer display name |
data-dw-date |
string | ISO-8601 datetime of the change |
data-dw-change-id |
integer (as string) | OOXML w:id for the change |
The inner <span class="dw-tc-popup"> is a purely visual element (contains author, date, and Accept/Reject buttons). It is ignored by the HTML parser. The <span class="dw-r"> children are the only children the parser reads to reconstruct run content.
Accepting or rejecting in the browser removes the <ins>/<del> wrapper. A subsequent HTML→DOCX round-trip will see the remaining <span class="dw-r"> elements as plain text runs — the accepted/rejected state is preserved.
Comment references (<a class="dw-comment-ref">)
Each inline comment reference renders as a superscript [N] anchor. When the document has comment bodies available, the renderer embeds a CSS-only hover popup directly inside the <a> element — no JavaScript required.
<a href="#comment-1"
class="dw-comment-ref"
data-dw-comment-id="1">
[1]
<span class="dw-comment-popup">
<span class="dw-comment-popup-author">
Alice
<span class="dw-comment-popup-date">· 2024-01-15T10:00:00Z</span>
</span>
<span class="dw-comment-popup-text">This is a great example!</span>
</span>
</a>
The popup spans are purely visual and are ignored by the HTML parser on round-trip — they carry no data-dw-* attributes. The data-dw-comment-id on the <a> is the only attribute the parser reads.
| Attribute / Element | Type | Notes |
|---|---|---|
class="dw-comment-ref" |
string | Marks the inline reference; used by the HTML parser |
data-dw-comment-id |
integer | Comment ID; used to reconstruct CommentRef on round-trip |
href |
string | Anchor pointing to #comment-{id} in the hidden comments section |
dw-comment-popup |
— | CSS hover popup container; hidden by default, shown on :hover |
dw-comment-popup-author |
— | Author name and optional date |
dw-comment-popup-date |
— | Omitted when date is empty |
dw-comment-popup-text |
— | Plain text of the comment body |
Comment sections (<section class="dw-comments">)
The comment section is present in every HTML document that has comments, but it is visually hidden (display: none). It exists solely to preserve the full comment metadata for the HTML → DOCX round-trip; the HTML parser reads it to reconstruct Comment objects.
<section class="dw-comments" data-dw-note-section="comments">
<div class="dw-comment"
id="comment-1"
data-dw-comment-id="1"
data-dw-comment-author="Alice"
data-dw-comment-date="2024-01-15T10:00:00Z"
data-dw-comment-initials="A">
<span class="dw-comment-marker">[1]</span>
<div class="dw-comment-body">
<p class="dw-p">…</p>
</div>
</div>
</section>
| Element / Attribute | Description |
|---|---|
<section class="dw-comments"> |
Hidden container for all comment bodies (display:none) |
data-dw-note-section |
Always "comments" — marks the section for the HTML parser |
<div class="dw-comment"> |
One comment body |
id |
comment-{id} — anchor target for the in-text reference |
data-dw-comment-id |
Integer comment ID — used to reconstruct the model on round-trip |
data-dw-comment-author |
Author display name |
data-dw-comment-date |
ISO-8601 datetime string, or empty string |
data-dw-comment-initials |
Author initials, or empty string |
<span class="dw-comment-marker"> |
[N] marker at the start of the comment |
<div class="dw-comment-body"> |
Contains one or more <p class="dw-p"> paragraphs |
Attribute presence rules
- Omitted = default. Attributes are only written when their value differs from the Word default (e.g.
data-dw-alignis omitted for left-aligned paragraphs). - Boolean flags (
data-dw-bold,data-dw-page-break-before, etc.) are present only whentrue. - Numeric values use the Python
reprof afloat(e.g."36.0","595.28").