Extension ID: cdx.presentation
Version: 0.1
Status: Draft
Maturity: Draft
The Presentation Extension provides advanced layout and styling capabilities beyond the core specification:
- Advanced page layout (columns, grids)
- Print-specific features (bleeds, crop marks)
- Master pages and templates
- Advanced typography
Presentation data is stored in the presentation/ directory as one reactive presentation file per type — presentation/paginated.json, presentation/continuous.json, and/or presentation/responsive.json (Presentation Layers, core specification section 4.1) — plus optional precise presentation/layouts/*.json. Each reactive file is a single object conforming to presentation.schema.json and declared in manifest.presentation[] with its {type, path, hash} (Manifest section 4.7).
This extension's concepts are top-level sections of that one presentation object, not separate files: styles under styles/typography/colors, master pages and templates under masterPages/masterRules/pageTemplate, and the table of contents under tableOfContents (with listOfFigures/listOfTables/index). A document does not ship styles.json, layout.json, or toc.json; those concepts live inside the reactive presentation file the manifest already declares.
{
"extensions": [
{
"id": "cdx.presentation",
"version": "0.1",
"required": false
}
]
}{
"layout": {
"type": "columns",
"columns": 2,
"gap": "0.25in",
"balance": true
}
}| Field | Type | Description |
|---|---|---|
columns |
integer | Number of columns (1-12) |
gap |
string | Gap between columns |
balance |
boolean | Balance column heights |
rule |
object | Column rule (separator line) |
{
"layout": {
"type": "grid",
"columns": 12,
"rows": "auto",
"gap": "16px",
"areas": [
{ "name": "header", "column": "1 / 13", "row": "1" },
{ "name": "sidebar", "column": "1 / 4", "row": "2" },
{ "name": "content", "column": "4 / 13", "row": "2" }
]
}
}Define multiple regions for text to flow through:
{
"flowRegions": [
{
"id": "main-flow",
"regions": [
{ "page": 1, "area": "content" },
{ "page": 2, "area": "full" },
{ "page": 3, "area": "content" }
]
}
]
}For professional printing:
{
"print": {
"bleed": {
"top": "0.125in",
"right": "0.125in",
"bottom": "0.125in",
"left": "0.125in"
},
"trim": {
"width": "8.5in",
"height": "11in"
},
"cropMarks": true,
"registrationMarks": true,
"colorBars": false
}
}A color definition is discriminated by type. An rgb or cmyk color carries a value (a hex string for rgb, comma-separated components for cmyk); a spot color carries a name and a fallback hex color for non-spot rendering.
{
"colors": {
"brand-blue": {
"type": "spot",
"name": "PANTONE 286 C",
"fallback": "#0033a0"
},
"body-text": {
"type": "rgb",
"value": "#1a1a1a"
},
"rich-black": {
"type": "cmyk",
"value": "0,0,0,1"
}
}
}{
"styles": {
"blackText": {
"color": "#000000",
"overprint": true
}
}
}{
"print": {
"standard": "PDF/X-4",
"outputIntent": {
"profile": "sRGB IEC61966-2.1",
"condition": "sRGB"
}
}
}The standard field selects the print/archival output intent. Supported values: PDF/X-1a, PDF/X-3, PDF/X-4, PDF/A-1, PDF/A-2, and PDF/A-3.
Master pages define reusable page templates:
{
"masterPages": {
"default": {
"margins": { "top": "1in", "right": "1in", "bottom": "1in", "left": "1in" },
"header": { "height": "0.5in" },
"footer": { "height": "0.5in" }
},
"chapter-start": {
"basedOn": "default",
"margins": { "top": "2in" },
"header": null
},
"full-bleed": {
"margins": { "top": "0", "right": "0", "bottom": "0", "left": "0" }
}
}
}Apply master pages to specific pages:
{
"pages": [
{ "number": 1, "master": "chapter-start" },
{ "number": 2, "master": "default" },
{ "number": 3, "master": "full-bleed" }
]
}{
"masterRules": [
{ "match": { "first": true }, "master": "chapter-start" },
{ "match": { "contains": "full-bleed-image" }, "master": "full-bleed" },
{ "match": { "default": true }, "master": "default" }
]
}{
"styles": {
"body": {
"fontFamily": "Source Serif Pro",
"fontFeatureSettings": {
"liga": true,
"kern": true,
"onum": true,
"smcp": false
}
}
}
}Common features:
liga- Standard ligatureskern- Kerningonum- Oldstyle numeralslnum- Lining numeralssmcp- Small capsswsh- Swashfrac- Fractions
{
"styles": {
"heading": {
"fontFamily": "Roboto Flex",
"fontVariationSettings": {
"wght": 700,
"wdth": 100,
"slnt": 0
}
}
}
}{
"typography": {
"hyphenation": {
"enabled": true,
"language": "en-US",
"minWordLength": 6,
"minBefore": 3,
"minAfter": 2,
"maxConsecutive": 2
}
}
}{
"typography": {
"widows": 2,
"orphans": 2,
"avoidBreakInside": ["blockquote", "table"]
}
}{
"styles": {
"chapter-first-para": {
"dropCap": {
"lines": 3,
"fontFamily": "inherit",
"fontWeight": "bold",
"marginRight": "0.1em"
}
}
}
}{
"typography": {
"baselineGrid": {
"enabled": true,
"lineHeight": "14pt",
"offset": "0pt"
}
}
}Line numbering in margins is common for legal briefs, manuscripts, and code review documents.
{
"typography": {
"lineNumbering": {
"enabled": true,
"start": 1,
"interval": 1,
"side": "left",
"restart": "page"
}
}
}| Field | Type | Required | Description |
|---|---|---|---|
enabled |
boolean | Yes | Whether line numbering is active |
start |
integer | No | Starting line number (default: 1) |
interval |
integer | No | Number every N lines (default: 1, every 5 is common) |
side |
string | No | Which margin: "left" (default) or "right" |
restart |
string | No | When to restart numbering (see below) |
style |
object | No | Number styling (see below) |
| Value | Description |
|---|---|
page |
Restart numbering on each page |
section |
Restart at section boundaries |
none |
Continuous numbering throughout document |
{
"typography": {
"lineNumbering": {
"enabled": true,
"interval": 5,
"side": "left",
"restart": "page",
"style": {
"fontSize": "8pt",
"color": "#666666",
"fontFamily": "monospace",
"marginRight": "0.5em"
}
}
}
}For documents where only certain blocks should be numbered (e.g., code blocks only):
{
"typography": {
"lineNumbering": {
"enabled": true,
"scope": ["codeBlock", "blockquote"]
}
}
}When scope is specified, only the listed block types receive line numbers. If omitted, all content is numbered.
Note: The
figureandfigcaptionblock types are now part of the core specification (see Content Blocks, Sections 4.20-4.21). This extension provides additional float positioning and advanced numbering capabilities.
{
"type": "image",
"src": "assets/images/figure1.avif",
"alt": "Figure 1",
"float": {
"position": "top",
"span": "column",
"clearance": "1em"
}
}Position options: top, bottom, inline, page-top, page-bottom
Span options: column, page, spread
The core figure block supports basic numbering ("auto", "none", or explicit number). This extension adds chapter-based numbering via the numberingConfig field:
The numberingConfig field provides extended numbering configuration beyond the core numbering field. The core numbering field (string or integer) controls basic numbering mode, while numberingConfig provides presentation-specific formatting options (style, a format template such as "Figure #", and chapter, a boolean enabling chapter-based numbering).
{
"type": "figure",
"children": [
{ "type": "image", "src": "assets/images/architecture.avif", "alt": "System architecture" },
{
"type": "figcaption",
"children": [{ "type": "text", "value": "Figure 1: System architecture" }]
}
],
"numberingConfig": {
"style": "Figure #",
"chapter": true
}
}The presentation:reference block's target field uses Content Anchor URI syntax (see core Anchors and References specification). The # prefix identifies internal document references. The block uses the presentation: namespace prefix as required by the core content blocks spec (section 5) for extension block types:
Renderer safety. The
targetfield is constrained to safe schemes (Renderer Safety section 2.1); fragment and relative references remain permitted, but dangerous schemes such asjavascript:are rejected.
{
"type": "text",
"value": "See ",
"marks": []
},
{
"type": "presentation:reference",
"target": "#fig-architecture",
"format": "Figure #"
}{
"tableOfContents": {
"title": "Contents",
"levels": [1, 2, 3],
"styles": {
"toc1": { "fontWeight": "bold", "marginTop": "1em" },
"toc2": { "marginLeft": "1em" },
"toc3": { "marginLeft": "2em", "fontSize": "0.9em" }
},
"pageNumbers": true,
"leaders": "dots"
}
}The leaders style is one of none, dots, dashes, or underline.
{
"listOfFigures": {
"title": "List of Figures",
"style": "toc2"
},
"listOfTables": {
"title": "List of Tables",
"style": "toc2"
}
}Index entries are carried by the presentation:index mark, which uses the presentation: namespace prefix as required by the core content blocks spec (section 5) for extension mark types.
In content:
{
"type": "text",
"value": "algorithm",
"marks": [
{ "type": "presentation:index", "term": "algorithm", "subterm": "sorting" }
]
}{
"index": {
"title": "Index",
"columns": 2,
"style": {
"mainEntry": { "fontWeight": "bold" },
"subEntry": { "marginLeft": "1em" }
}
}
}The presentation extension defines a self-contained presentation:footnote mark that carries its footnote content directly in a content array, for documents that use the presentation extension without the semantic extension.
Cross-Extension Note: When both the presentation and semantic extensions are active, the semantic extension provides the canonical footnote model — the bare footnote mark with separate semantic:footnote blocks for footnote content. The bare footnote mark and the presentation:footnote mark are distinct marks; a document SHOULD use a single footnote model. Presentation footnote styling (section 10.2) applies to whichever model is in use.
In content:
{
"type": "text",
"value": "important claim",
"marks": [
{
"type": "presentation:footnote",
"id": "fn1",
"content": [
{ "type": "text", "value": "Source: Annual Report 2024" }
]
}
]
}The footnote position is one of page-bottom, column-bottom, or section-end. The numbering style is one of 1, a, A, i, I, or * (symbolic/asterisk).
{
"footnotes": {
"numbering": "1",
"position": "page-bottom",
"separator": {
"width": "2in",
"style": "solid",
"margin": "0.5em"
},
"style": {
"fontSize": "0.85em",
"lineHeight": 1.4
}
}
}The endnote numbering style is one of 1, a, A, i, or I. Unlike footnotes (section 10.2), endnotes do not offer the symbolic * style, since a long endnote list would exhaust the symbol sequence.
{
"endnotes": {
"title": "Notes",
"numbering": "1",
"perChapter": false
}
}{
"pageTemplate": {
"header": {
"content": {
"left": { "variable": "chapter-title" },
"right": { "variable": "section-title" }
}
},
"footer": {
"content": {
"center": { "text": "Page {pageNumber} of {pageCount}" }
}
}
}
}| Variable | Description |
|---|---|
{pageNumber} |
Current page number |
{pageCount} |
Total pages |
{chapter-title} |
Current chapter title |
{section-title} |
Current section title |
{date} |
Current date |
{title} |
Document title |
{author} |
Document author |
{
"pageTemplate": {
"odd": {
"header": { "content": { "right": { "variable": "section-title" } } }
},
"even": {
"header": { "content": { "left": { "variable": "chapter-title" } } }
}
}
}{
"version": "0.1",
"type": "paginated",
"defaults": {
"pageSize": { "width": "6in", "height": "9in" },
"margins": { "top": "0.75in", "outside": "0.75in", "bottom": "0.875in", "inside": "1in" }
},
"masterPages": {
"chapter": {
"margins": { "top": "2in" },
"footer": { "content": { "center": { "text": "{pageNumber}" } } }
},
"body": {
"header": {
"content": { "outside": { "variable": "section-title" } }
},
"footer": {
"content": { "outside": { "text": "{pageNumber}" } }
}
}
},
"typography": {
"hyphenation": { "enabled": true, "language": "en-US" },
"widows": 2,
"orphans": 2
},
"styles": {
"body": { "fontFamily": "Georgia, serif", "fontSize": "11pt", "lineHeight": 1.4 }
}
}