Insert HTML and Markdown
Convert, inspect, and apply bounded HTML or Markdown content to an open DOCX.
The Document API accepts HTML and Markdown as structured input. You can inspect the canonical fragment first, or pass the source directly to insert() or replace().
HTML and Markdown are not Word package fragments. SuperDoc preserves the supported structure listed below, normalizes representation details, and reports anything it drops or downgrades.
Convert before applying
Use htmlToFragment() or markdownToFragment() when your application needs to inspect diagnostics or reuse the canonical fragment:
import { SuperDoc } from 'superdoc';
import 'superdoc/style.css';
const superdoc = new SuperDoc({
selector: '#editor',
document: '/contract.docx',
onReady: async ({ superdoc }) => {
const doc = superdoc.activeEditor?.doc;
if (!doc) throw new Error('The active document is unavailable.');
const converted = await doc.htmlToFragment({
html: '<h2>Scope</h2><p><strong>Review</strong> this clause.</p>',
});
const fatal = converted.diagnostics.find((diagnostic) => diagnostic.severity === 'error');
if (fatal) throw new Error(`HTML conversion failed: ${fatal.message}`);
const insertInput = {
type: 'html',
value: '<h2>Scope</h2><p><strong>Review</strong> this clause.</p>',
} as const;
const checked = await doc.capabilities.check({
operation: 'insert',
input: insertInput,
options: { changeMode: 'tracked' },
});
if (checked.operation !== 'insert') {
throw new Error(`Unexpected support-check operation: ${checked.operation}`);
}
if (!checked.supported || !checked.guard) {
throw new Error(`Rich insert is not supported: ${checked.failure?.message ?? checked.outcome}`);
}
const insertReceipt = await doc.insert(insertInput, {
changeMode: 'tracked',
supportCheck: checked.guard,
});
if (!insertReceipt.success) {
throw new Error(`Rich insert failed: ${insertReceipt.failure?.message ?? 'unknown failure'}`);
}
const match = await doc.query.match({
select: { type: 'text', pattern: 'Existing clause' },
require: 'exactlyOne',
});
const clause = match.items[0];
if (!clause || clause.matchKind !== 'text') throw new Error('The clause was not found.');
const replaceReceipt = await doc.replace(
{
target: clause.target,
type: 'markdown',
value: '**Replacement clause** with a [reference](https://example.com/policy).',
},
{
changeMode: 'tracked',
expectedRevision: match.evaluatedRevision,
},
);
if (!replaceReceipt.success) {
throw new Error(`Rich replace failed: ${replaceReceipt.failure?.message ?? 'unknown failure'}`);
}
console.log(checked.outcome, insertReceipt.outcome, replaceReceipt.conversion);
},
});
window.addEventListener('beforeunload', () => {
superdoc.destroy();
});
Each result contains:
fragment: the canonical structured content.lossy:truewhen conversion normalized, downgraded, or dropped source content.diagnostics: ordered, source-located conversion findings.
A warning-bearing result can still be applied. An error means there is no safe rich fragment to apply. Check diagnostic severity and disposition instead of treating every lossy result as a failure.
Check an exact workflow before applying
Use doc.capabilities() for a cheap synchronous snapshot of general operation availability. Use
doc.capabilities.check() when the answer must account for exact HTML or Markdown, the current target, the requested
change mode, and the current document revision. A check does not mutate package bytes, history, tracked changes, or the
public revision.
A supported write that would change the document returns a guard. Pass it to the unchanged rich insert() or
replace() request. The write fails closed when the source, format, target, placement, story, nesting policy, mode,
analysis result, or document revision no longer matches. The guard digest detects accidental reuse; it is not a
security signature.
The common outcome is preserved, preserved-with-warnings, simplified, rejected, no-op, invalid-target, or
outdated. Read the complete conversion diagnostics and final mutation receipt before choosing application-specific
fallback behavior.
Insert or replace raw source
Pass value with type: 'html' or type: 'markdown' to convert and apply in one call. Rich insert supports a selection, a block with before or after, a ref, or no target for append. Rich replace accepts a selection, paragraph or heading block, whole table block, ref, or the explicit { kind: 'story', storyType: 'body' } target.
The body target replaces all main-body blocks in one direct mutation while retaining the destination DOCX package and terminal section properties. It does not replace the DOCX file. Tracked mode is supported for selection and block workflows, but tracked whole-body replacement returns CAPABILITY_UNSUPPORTED.
Use dryRun: true to resolve and preflight without creating IDs, history, or document changes. Pair a mutation with expectedRevision when it depends on an earlier read.
Successful raw-source receipts include the final outcome and a conversion report. They may also include created entity identities, source-path effects, affected stories, text-range shifts, and a transaction ID. Check success before using any success-only field.
Supported inbound constructs
| Source construct | Result |
|---|---|
| Paragraphs, headings, bold, italic, underline, strike, hard breaks | Preserved as canonical blocks and runs |
| Ordered and unordered lists, including bounded nesting and ordered starts | Preserved with canonical list levels |
| Tables with a complete leading header row and column spans | Preserved; explicit widths and broad table styling are not |
Safe http, https, and mailto links | Preserved as external hyperlinks |
| Horizontal rules | Preserved as durable horizontal-rule blocks |
| Safe bounded color, font, spacing, indentation, cell shading, and padding | Normalized to typed canonical properties |
| Code, block quotes, task markers, and unsupported inline forms | Downgraded or dropped with diagnostics |
| Scripts, event handlers, unsafe URLs, raw images, nested tables, row spans, malformed or over-limit input | Sanitized with warnings when safe structure remains; otherwise rejected |
The limits are deliberate. Arbitrary CSS, embedded active content, and full DOCX package fidelity are outside the HTML/Markdown contract.
Projection and persistence
Direct changes are immediately part of the document. This inbound API creates review markup that can be accepted or
rejected through the tracked-changes API. Detailed outbound HTML and Markdown reads can then project redline, final,
or original views. Save and reopen the DOCX before treating a mutation workflow as complete.
Standalone outbound conversion of an SDFragment to HTML or Markdown is not part of this inbound API. Document reads
have a separate HTML and Markdown projection contract, including compact string
getters and detailed reads with review, fidelity, and provenance metadata.
For target discovery, start with query content. For failure handling, see receipts and errors. The generated HTML conversion reference, insert reference, and replace reference list the complete shapes.