14 KiB
Footnotes and endnotes
Footnotes, endnotes and their document options. Implemented in
src/model/story.rs (text), src/model/prefs.rs (options) and
src/idml/story.rs, designmap.rs, resources.rs (writing).
| Class | Object | IDML element |
|---|---|---|
| 0x24F | Footnote | Footnote (story text) |
| 0x2801 | Endnote story | Story with IsEndnoteStory="true" |
| 0x2805 | Endnote | Endnote (story text) |
| 0x2804 | Endnote range | EndnoteRange (endnote story text) |
Counts are over the little-endian corpus without the privately held
samples, unless they name the trustworthy pairs (measurement.md).
Footnotes
Reference. A footnote reference is a U+0004 character in story or
table cell text. The owned-items strand (run kind 0x209, objects.md)
lists an object of class 0x24F, the footnote, at that position. 14,026
footnotes in 391 files, InDesign 5 to 21, are all at a U+0004: 14,002 in
story text and 24 in table cell text. In the pairs, the 819 Footnote
elements of the IDML are in place of exactly these characters; the count
per story matches in 47 of 47 stories.
Text. The footnote's text is in the same story text, after the
story's own text, as table cell text is (tables.md). The text-owner
strand (run kind 0x2A4) gives it the footnote UID as owner and 1 as the
cell field. In all 14,026 footnotes the text is one stretch, its cell
field is 1, and it ends with U+000D. 14,001 footnote texts contain one
U+0004, the footnote number, which IDML writes as <?ACE 4?>; the other
25 have none. 261 footnote texts contain an anchored object (U+FFFC) and
1 contains a table.
IDML. IDML writes a Footnote element, without Self or attributes,
in place of the reference character, inside the CharacterStyleRange of
that position. The Footnote holds ParagraphStyleRange elements built
from the footnote text, like a table cell; the final U+000D is not
written. Evidence: the footnote texts of a story in the INDD equal the
IDML footnote texts of that story in 819 of 819 footnotes (47 stories, 46
pairs), compared as multisets with U+0004, U+0018, U+FEFF and U+FFFC left
out; the sequence of paragraph styles matches in 498 of 499 footnotes of
the trustworthy pairs. Inside footnotes IDML has hyperlink sources (182
in a character range, 315 in a paragraph range), page references (33)
and cross-reference sources (25); the converter places sources in
footnotes by the rules of hyperlinks.md.
A U+0004 without a footnote or endnote object stays <?ACE 4?>, as in
IDML: footnote numbers inside footnote and endnote text, and one pasted
number in a 17.4 pair.
With this, 8 more stories of the trustworthy pairs have identical text, and their text ranges are compared.
Footnote options (preferences chunk 0x2820)
Chunk 0x2820 of the preferences object (class 0x2202) holds the
document's FootnoteOption. It is 231 bytes in InDesign 7 to 11 and 233
bytes from 12 on, longer when the strings are longer, and missing in 90
of the 733 pairs collected. 643 files have the chunk and a
FootnoteOption in their IDML, 442 of them trustworthy pairs; every
attribute decoded below matches in 442 of 442 trustworthy pairs. Over
all 643 files there are 4 mismatches, all in stale pairs
(EnableStraddling in 3 files from 12.0, and a RuleColor).
| Offset | Type | IDML |
|---|---|---|
| 0 | u32 character style UID | FootnoteMarkerStyle |
| 4 | u32 paragraph style UID | FootnoteTextStyle |
| 8 | u32 code | FootnoteNumberingStyle: 0xCA07 Arabic (641), 0xCA0A Symbols (1), 0xCA58 Asterisks (1) |
| 12 | u32 | StartAt |
| 16 | u16 | RestartNumbering: 0 DontRestart (641), 1 PageRestart (2) |
| 18, 22 | u16, u16 | MarkerPositioning: (1, 0) SuperscriptMarker (635), (0, 0) NormalMarker (4), (0, 1) RubyMarker (4) |
| 20 | u16 | 0 in all |
| 24 | f64 | SpaceBetween |
| 32 | f64 | Spacer |
| 40 | u16 | EosPlacement (1 true): 21 files true, 1,364 false, all matching (corpus of 2026-10) |
| 42 | u16 | ShowPrefixSuffix: 0 NoPrefixSuffix (640), 1 PrefixSuffixReference (1), 3 PrefixSuffixBoth (2) |
| 44 | string | Prefix |
| string | Suffix |
|
| string | SeparatorText (tab, U+3000, U+2002, U+2003 and . seen) |
A string here is a u32 length in UTF-16 units followed by text segments
(objects.md), not the in-object string form.
The tail follows the separator: 172 bytes in files from InDesign 7 to 11, 174 bytes from 12 on. Offsets are from the start of the tail.
| Offset | Type | IDML |
|---|---|---|
| 0 | u16 | NoSplitting |
| 4 | f64 | FootnoteMinimumFirstBaselineOffset: 19.84 in one file, 0 in the 1,384 others with a known tail, all matching (corpus of 2026-10) |
| 12 | u16, 174-byte tail only | EnableStraddling (317 of 317 trustworthy pairs) |
| R | rule block, 78 bytes | Rule… |
| R + 78 | the same block | ContinuingRule… |
R is 18 for a 174-byte tail and 16 for a 172-byte tail. Each block:
| Block offset | Type | IDML (Rule or ContinuingRule prefix) |
|---|---|---|
| 0 | u16 | …On |
| 2 | u32 code, then u32 0 | …Type, as the stroke types of page items and cells: 0x5A29 StrokeStyle/$ID/Solid, 0x5A39 …/Canned Dotted, 0xB007 …/ThickThick |
| 10 | u32 swatch UID | …Color |
| 14 | f64 | …LineWeight |
| 22 | f64 | …Tint |
| 30 | u16 | 0 in all |
| 32 | u32 swatch UID | …GapColor |
| 36 | f64 | …GapTint |
| 44 | 2 bytes | 0 in all; the two overprint flags are false in all, so they cannot be told apart |
| 46 | f64 | …LeftIndent |
| 54 | f64 | …Width |
| 62 | f64 | …Offset |
| 70 | 8 bytes | 0 in all |
A tail of another length is not read: the converter keeps the observed
values for the rules and warns. Codes not listed are left out.
FootnoteFirstBaselineOffset and the overprint flags have one value in
every sample and come from the generated value file (idml-values.md).
Without the chunk (90 files) the IDML has the defaults of the value
file, FootnoteTextStyle="ParagraphStyle/$ID/NormalParagraphStyle",
SeparatorText tab, and EnableStraddling="true" from DOM 12 (67 of 67).
In the corpus of 2026-10 the 75 files without the chunk (51 trustworthy)
also have, each in 75 of 75: StartAt="1", Prefix="", Suffix="",
FootnoteMarkerStyle="CharacterStyle/$ID/[No character style]",
SeparatorText tab, SpaceBetween="0", Spacer="0",
FootnoteMinimumFirstBaselineOffset="0", EosPlacement="false",
NoSplitting="false"; for the rule and the continuing rule …On
true, …LineWeight 1, …Tint and …GapTint 100, …LeftIndent 0,
…Width 72 (rule) and 288 (continuing rule), …Offset 0, …Type
StrokeStyle/$ID/Solid, …Color Color/Black, …GapColor
Swatch/None; and the properties FootnoteNumberingStyle Arabic,
RestartNumbering DontRestart, ShowPrefixSuffix NoPrefixSuffix
and MarkerPositioning SuperscriptMarker. The value files lost most of
these when the corpus grew, because files with the chunk vary; the
converter writes them for files without the chunk.
The 75 files without the chunk all have a last session with language
code 0x0100 or 0x0103 (objects.md, save history), so whether a
Japanese edition writes another separator without the chunk, as it does
for endnotes (endnote options, below), is not shown.
In the trustworthy pairs every FootnoteOption value is reproduced
(489 of 489 pairs for each attribute).
Text frame footnote options
TextFrameFootnoteOptionsObject is a child of TextFrame in IDML from
DOM 12, with EnableOverrides, SpanFootnotesAcross,
MinimumSpacingOption and SpaceBetweenFootnotes: the frame's
FootnotesEnableOverrides, FootnotesSpanAcrossColumns,
FootnotesMinimumSpacing and FootnotesSpaceBetween.
IDML writes it on a frame of DOM 12 or later when one of these holds:
- the frame's applied object style lacks category 0xADCA (footnotes) in
its category list (chunk 0x1B92E;
objects.md, text frame preferences); - the frame's footnote values (span, minimum spacing, space between) differ from the style's;
- the frame has no object style object.
This is the rule TextFramePreference follows for its Footnotes…
attributes, applied from DOM 12 although TextFramePreference has no
footnote values before 13.1. The frame's values are in chunk 0x22608 of
its multi-column frame (objects.md, text frame preferences): u16 at 2
the span (1 = true), f64 at 4 and 12 the spacings. Without the chunk they
are false, 12 and 6. The style's values are those of its text frame
settings (chunk 0x1B924: u16 at 144, f64 at 146 and 154), or of the
style it is based on, or false, 12 and 6.
Evidence: measured on 16,900 text frames of DOM 12 or later in 606
trustworthy pairs before 2026-10 (every frame with the category off or
without a style has the element, 6,011 of 6,011; every frame with the
category on and equal values has none, 10,888 of 10,888; the one frame
with the category on and other values has it). Over the 1,251
trustworthy pairs after 2026-10, the converter's elements by this rule
are 20,096 of the 20,096 reference elements on the frames it writes, with
all four values, and no element that the reference lacks; the other 255
are on frames it does not write. Three
elements of the output have an EnableOverrides that the reference
element lacks (not explained).
EnableOverrides is false in every element. Chunk 0x22608 has a u16 0
at offset 0 in every sample; it is probably that flag, which no sample
shows set. The converter writes false. The element follows
TextFramePreference and the frame's BaselineFrameGridOption.
Endnotes
Endnote story. Document chunk 0x22618 is a u32, the UID of the
endnote story, class 0x2801 (12 of 12 files with endnotes). The story is
listed in document chunk 0x222 with the other stories and has the same
strands as a class 0x201 story. IDML lists it in StoryList in that
order and writes it as a Story with IsEndnoteStory="true". One per
file; 729 endnotes in 12 files (InDesign 16.2, 17.2, 20.0 and 21.2).
Reference. An endnote reference is a U+0004 in story text. The
owned-items strand lists an object of class 0x2805 at that position (729
of 729). IDML writes, in place of the character,
<Endnote Self="u<0x2805 UID>" EndnoteTextRange="u<0x2804 UID>"/>.
Endnote objects. Class 0x2805, chunk 0x22616: u32 UID of its range (class 0x2804). Class 0x2804, chunk 0x2261A: u32 UID of its endnote. The two point at each other in 729 of 729.
Range position. The endnote story's strand of class 0xCA1C holds a
range tree (hyperlinks.md, position in the text) whose node sources
are the 0x2804 objects: 729 nodes for 729 endnotes. The same tree also
holds 15 hyperlink text sources (class 0x13502). The range text starts
with U+FEFF U+0004 (710 of 729), ends with U+FEFF (729 of 729) and holds a
paragraph return in 13 of 729. IDML writes
<EndnoteRange Self="u<0x2804 UID>" SourceEndnote="u<0x2805 UID>">
around the range, both U+FEFF included in Content: inside one
CharacterStyleRange when the range lies in one (2 ranges in a 21.2
pair), or as a child of the ParagraphStyleRange around several (1
range in a 17.2 file with a DOM 14 IDML). How IDML writes a range across
paragraphs is not shown. The converter writes ranges within one
character range and leaves out the wrapper of others, with a warning.
Endnote text frame. A text frame whose story is the endnote story is
written as EndnoteTextFrame, with the attributes and children of a
TextFrame (1 frame, compared attribute by attribute).
Schema. The 21.5 schema rejects InDesign's own endnote markup:
Endnote is allowed only directly in Story, Cell and similar
places, not in CharacterStyleRange, and EndnoteRange is defined
without content. Jing reports both on the reference IDML. The converter
writes the markup as InDesign does; measurement.md describes the
validation exception.
Endnote options (preferences chunk 0x2261E)
Fields in order:
- string
EndnoteTitle - u32
EndnoteTitleStyle(paragraph style UID) - u32 numbering code (0xCA07
Arabic, the only value) - u32
StartEndnoteNumberAt - u32 restart (0
Continuous, the only value) - u32
EndnoteMarkerPositioning: 1SuperscriptMarker, 3RubyMarker - u32
EndnoteMarkerStyle(character style UID) - u32
EndnoteTextStyle(paragraph style UID) - string
EndnoteSeparatorText - u32 (1 in all)
- u32 (1 in all)
- string (empty in all)
- string (empty in all)
- u32 (0 in all)
Strings are as in chunk 0x2820. 359 files have the chunk and an
EndnoteOption in their IDML (240 trustworthy): all values match in all
359, and the parse ends at the end of the chunk. Fields 10 to 14 never
vary (ScopeValue EndnoteDocumentScope, FrameCreateOption
NewPage, EndnotePrefix, EndnoteSuffix, ShowEndnotePrefixSuffix
NoPrefixSuffix), so which is which is not proven; their values come
from the value file.
Without the chunk (149 files with DOM 13 or later) the marker and
text styles are the defaults, which the converter writes. The title is
the exporting InDesign's localized default (Endnotes 108, Notes de fin 18, Eindnoten 12, 4 others in the 654 pairs before 2026-10), and
the separator and marker position follow its language. The converter
writes the separator U+3000 when the last session of the save history
has language code 0x0101, and tab otherwise (140 of 141 pairs before
2026-10; objects.md, save history). Over all pairs of the corpus of
2026-10 without the chunk this gives 258 of 273 separators (211 of 226
trustworthy). Of the 15 others, 13 have code 0x0101 and tab, and their
IDML has the values of a Roman edition in the preferences too
(LightBlue baseline grid, Violet column guides; preferences.md,
values of the exporting edition): they were exported by another
installation. One Japanese document of code 0x0101 has tab and one
Korean document of code 0x0100 has U+3000; no stored value separates
them. The title and the marker position
follow the saving edition that the XMP black name shows (objects.md,
saving edition): RubyMarker for a Japanese edition only, so Korean
editions, which also have code 0x0101, get SuperscriptMarker. Over the
trustworthy pairs of the corpus after 2026-10 this gives 917 of 918
titles and 916 of 918 marker positions (692 and 876 before); without a
black name the marker follows the code.
IsEndnoteStory
IsEndnoteStory is on every Story and XmlStory from DOM 13: 0 of
2,467 stories and 0 of 39 XML stories in DOM 12 IDML, 3,094 of 3,094 and
173 of 173 in DOM 13.0–14.0.