@dogsbay/format-dita 0.2.0-beta.123 → 0.2.0-beta.125

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -27,7 +27,7 @@ dogsbay import-dita docs/ -o content --report topics.md
27
27
  ```
28
28
 
29
29
  Tasks become native `:::steps`, notes become callouts, CALS and
30
- simpletables become tables, `<xref href="x.dita">` becomes `[…](x.md)`,
30
+ simpletables (and a reference topic's `<properties>`) become tables, `<xref href="x.dita">` becomes `[…](x.md)`,
31
31
  and `keyref` links become `key:` links. Nested or sibling topics in
32
32
  multi-topic files are emitted inline as anchored sections.
33
33
 
@@ -38,6 +38,23 @@ emit `{% include %}` so one canonical copy of reused text survives. Use
38
38
  `dogsbay import-dita --no-conref-includes` to keep conrefs on the ledger
39
39
  instead.
40
40
 
41
+ **Lines.** Every conversion note carries `line`, the source line of the
42
+ element that raised it (or of the block being converted), so a host can point
43
+ at it. `{ sourceLines: true }` also puts each block's line on `meta.line`, which
44
+ `@dogsbay/render-html` writes as `data-line` when asked (`dataLines: true`).
45
+
46
+ **Specializations in raw source:** a file as authored has no `@class`, so
47
+ an element is known only by its name, and a specialization the converter
48
+ does not know by name (a `<troubleshooting>` topic, a hazard statement's
49
+ items) loses its markup. `{ classDefaults: true }` fills in each missing
50
+ `@class` from the DITA 1.3 DTD defaults first (612 elements, the table
51
+ `DITA_CLASS_DEFAULTS`, generated by `scripts/generate-class-defaults.mjs`
52
+ from DITA-OT's `.mod` files), as parsing against the DTDs would; the
53
+ element then converts as what it specializes. An existing `@class` is kept;
54
+ a name the DTDs do not declare (custom or DITA 2.0) stays unclassed, with
55
+ one note per topic. It is off by default for now because it changes the
56
+ output for such elements.
57
+
41
58
  Everything that cannot map cleanly lands in the conversion ledger instead
42
59
  of disappearing: filter attributes, table spans, semantic-inline downgrades,
43
60
  `conkeyref`, conref ranges/pushes, whole-topic conrefs, unresolved targets,
package/dist/blocks.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { inlineToDogsbayMd } from "@dogsbay/format-dogsbay-md/browser";
2
- import { convertInline, elementName, idAnchor, publishImage, trimInline, textOf, inlineSafeSnippet, conrefLedgerDetail, } from "./inline.js";
2
+ import { convertInline, elementName, isKnownInline, idAnchor, publishImage, trimInline, textOf, inlineSafeSnippet, conrefLedgerDetail, } from "./inline.js";
3
3
  import { publishHref, publishLabel, publishLanguage, publishString } from "./types.js";
4
4
  import { anchorId } from "./anchors.js";
5
5
  import { DB_QUALIFIERS, outputTokens, youtubeId } from "./qualifiers.js";
@@ -52,6 +52,13 @@ const withProvenance = (node, el) => {
52
52
  }
53
53
  return node;
54
54
  };
55
+ /** A list item or step: its source line (ParseOptions.sourceLines), as convertBlock gives a block. */
56
+ const atLine = (node, el, ctx) => {
57
+ const line = ctx.lineOf?.(el);
58
+ if (line !== undefined && node.meta?.line === undefined)
59
+ node.meta = { ...node.meta, line };
60
+ return node;
61
+ };
55
62
  const noteFilterAttrs = (el, ctx) => {
56
63
  for (const attr of ["audience", "platform", "product", "props", "otherprops", "rev"]) {
57
64
  if (el.attribs?.[attr]) {
@@ -77,8 +84,29 @@ const isBlockChild = (el, ctx) => {
77
84
  const name = blockName(el, ctx);
78
85
  if (ctx.publish && name === "image")
79
86
  return el.attribs?.placement === "break";
80
- return BLOCK_ELEMENTS.has(name);
87
+ return BLOCK_ELEMENTS.has(name) || (isUnknownElement(el, ctx) && holdsBlocks(el, ctx));
81
88
  };
89
+ /**
90
+ * An element the converter knows by neither a block nor an inline name (a
91
+ * custom specialization). Both resolutions count: with @class, a
92
+ * specialization of <fn> or <ph> resolves to an inline name, not a block one.
93
+ */
94
+ const isUnknownElement = (el, ctx) => !isKnownBlock(elementName(el, ctx, isKnownBlock)) && !isKnownInline(elementName(el, ctx, isKnownInline));
95
+ /**
96
+ * Whether an unknown element holds block content (a <p>, a list), directly or
97
+ * through other unknown wrappers. Such an element is a block wrapper: read as
98
+ * inline, its paragraphs and lists were flattened into one run of text, with
99
+ * an "unrecognized inline element" note for each of them. An image does not
100
+ * count: it sits in a sentence as often as not (an icon in a UI label).
101
+ */
102
+ const holdsBlocks = (el, ctx) => el.children.some((c) => {
103
+ if (!isElement(c))
104
+ return false;
105
+ const name = blockName(c, ctx);
106
+ if (name === "image")
107
+ return false;
108
+ return BLOCK_ELEMENTS.has(name) || TRANSPARENT_CONTAINERS.has(name) || (isUnknownElement(c, ctx) && holdsBlocks(c, ctx));
109
+ });
82
110
  const paragraphFrom = (nodes, ctx) => {
83
111
  const inline = trimInline(convertInline(nodes, ctx));
84
112
  if (inline.length === 0)
@@ -210,12 +238,18 @@ const definingItemNode = (el, ctx, type) => {
210
238
  ctx.note("@conref", `<${el.name.toLowerCase()} id="${el.attribs.id}"> is reused elsewhere via "${snippet.file}" but its content is multi-line — replace it with the include manually to keep one copy`);
211
239
  return null;
212
240
  };
241
+ /**
242
+ * Whether an element is a `tag` by name or, with @class, by what it
243
+ * specializes: a hazard statement's <typeofhazard> is an <li>. Matching the
244
+ * name alone dropped such items, and their text, without a note.
245
+ */
246
+ const isPart = (el, ctx, tag) => isElement(el) && elementName(el, ctx, (n) => n === tag) === tag;
213
247
  const convertListItems = (el, ctx, itemTag) => el.children
214
- .filter((c) => isElement(c) && c.name.toLowerCase() === itemTag)
248
+ .filter((c) => isPart(c, ctx, itemTag))
215
249
  .map((li) => {
216
250
  const viaConref = itemConref(li, ctx, "list-item") ?? definingItemNode(li, ctx, "list-item");
217
251
  if (viaConref)
218
- return withProvenance(viaConref, li);
252
+ return atLine(withProvenance(viaConref, li), li, ctx);
219
253
  const { inline: content, children: blocks } = mixedContent(li, { ...ctx, constrained: true });
220
254
  const { inline, children } = withItemAnchor(content, blocks, [li.attribs?.id], ctx);
221
255
  const item = { type: "list-item" };
@@ -223,7 +257,7 @@ const convertListItems = (el, ctx, itemTag) => el.children
223
257
  item.inline = inline;
224
258
  if (children.length > 0)
225
259
  item.children = children;
226
- return withProvenance(item, li);
260
+ return atLine(withProvenance(item, li), li, ctx);
227
261
  });
228
262
  /** Components an `@outputclass` `db-*` token selects, per element. */
229
263
  const DB_COMPONENTS = {
@@ -529,7 +563,7 @@ const inlineLabel = (inline) => (inline ?? [])
529
563
  const dlComponentEntries = (el, ctx, component, keepEmpty = false, anchorsOut) => {
530
564
  const out = [];
531
565
  let pending = [];
532
- const entries = el.children.filter((c) => isElement(c) && c.name.toLowerCase() === "dlentry");
566
+ const entries = el.children.filter((c) => isPart(c, ctx, "dlentry"));
533
567
  for (const entry of entries) {
534
568
  const items = convertDefList({ ...el, children: [entry] }, ctx).children ?? [];
535
569
  const terms = items.filter((n) => n.type === "dt");
@@ -637,7 +671,7 @@ const dlToCards = (el, ctx, anchors) => {
637
671
  const convertDefList = (el, ctx, tags = { entry: "dlentry", term: "dt", def: "dd" }) => {
638
672
  const children = [];
639
673
  for (const entry of el.children.filter(isElement)) {
640
- if (entry.name.toLowerCase() !== tags.entry)
674
+ if (!isPart(entry, ctx, tags.entry))
641
675
  continue;
642
676
  // Entry-level conref (<dlentry conref>): a term/definition pair can't
643
677
  // splice as an include — ledger it so the loss is never silent
@@ -647,8 +681,7 @@ const convertDefList = (el, ctx, tags = { entry: "dlentry", term: "dt", def: "dd
647
681
  }
648
682
  let entryAnchored = false;
649
683
  for (const part of entry.children.filter(isElement)) {
650
- const name = part.name.toLowerCase();
651
- if (name === tags.term) {
684
+ if (isPart(part, ctx, tags.term)) {
652
685
  // Term-level conref (<dt conref>/<pt conref>): single-line
653
686
  // include or ledger — never a silent empty term
654
687
  const viaConref = constrainedConrefInline(part, ctx);
@@ -659,7 +692,7 @@ const convertDefList = (el, ctx, tags = { entry: "dlentry", term: "dt", def: "dd
659
692
  });
660
693
  entryAnchored = true;
661
694
  }
662
- else if (name === tags.def) {
695
+ else if (isPart(part, ctx, tags.def)) {
663
696
  const viaConref = constrainedConrefInline(part, ctx);
664
697
  if (viaConref) {
665
698
  children.push({ type: "dd", inline: viaConref });
@@ -719,12 +752,23 @@ const TABLE_PARTS = new Set([
719
752
  const hasClassToken = (el, token) => ` ${el.attribs?.class ?? ""} `.includes(` ${token} `);
720
753
  const elementChildren = (el) => el.children.filter(isElement);
721
754
  const PROPERTY_KINDS = ["proptype", "propvalue", "propdesc"];
755
+ /**
756
+ * Whether an element is the reference domain's `local` (`properties`, `property`, …):
757
+ * by @class when DITA-OT has filled it in, else by name, as authored source has none.
758
+ */
759
+ const isReference = (el, local) => hasClassToken(el, `reference/${local}`) || el.name.toLowerCase() === local;
722
760
  /** A properties table cell's column: `proptype`, or with suffix "hd" a header cell (`proptypehd`). */
723
- const propertyKind = (cell, suffix = "") => PROPERTY_KINDS.find((k) => hasClassToken(cell, `reference/${k}${suffix}`));
761
+ const propertyKind = (cell, suffix = "") => PROPERTY_KINDS.find((k) => isReference(cell, `${k}${suffix}`));
762
+ /**
763
+ * A properties table's cells. Exactly the cells `propertyKind` recognizes (a
764
+ * published cell's @class names its kind before the stentry it specializes),
765
+ * so a row's converted cells and its cell elements line up index for index.
766
+ */
767
+ const PROPERTY_CELLS = new Set([...PROPERTY_KINDS, ...PROPERTY_KINDS.map((k) => `${k}hd`)]);
724
768
  /** A properties table's columns in use, its properties that have cells, and its header row. */
725
769
  const propertiesColumns = (el) => {
726
- const header = elementChildren(el).find((c) => hasClassToken(c, "reference/prophead"));
727
- const propertyRows = elementChildren(el).filter((c) => hasClassToken(c, "reference/property") && elementChildren(c).some((cell) => !!propertyKind(cell)));
770
+ const header = elementChildren(el).find((c) => isReference(c, "prophead"));
771
+ const propertyRows = elementChildren(el).filter((c) => isReference(c, "property") && elementChildren(c).some((cell) => !!propertyKind(cell)));
728
772
  const used = PROPERTY_KINDS.filter((k) => propertyRows.some((r) => elementChildren(r).some((c) => propertyKind(c) === k)) ||
729
773
  (header ? elementChildren(header).some((c) => propertyKind(c, "hd") === k) : false));
730
774
  return { used, propertyRows, ...(header ? { header } : {}) };
@@ -829,15 +873,24 @@ const convertTable = (el, ctx) => {
829
873
  }
830
874
  };
831
875
  walk(el);
832
- // Publishing: a properties table's columns are the type, value and description columns
876
+ // A properties table's columns are the type, value and description columns
833
877
  // its header or any property uses (DITA-OT's hasType, hasValue, hasDesc); each row
834
878
  // aligns its cells to them, a property with no cells is dropped, and a header cell
835
- // missing for a column in use is DITA-OT's generated label ("Type", "Value", "Description")
836
- if (ctx.publish && hasClassToken(el, "reference/properties")) {
879
+ // missing for a column in use is DITA-OT's generated label ("Type", "Value",
880
+ // "Description"; localized when publishing). Authored source has no @class, so
881
+ // the parts are matched by name too (the walk above sees no sthead/strow then).
882
+ if (isReference(el, "properties")) {
837
883
  const { used, propertyRows, header } = propertiesColumns(el);
884
+ // A property with no cells has no row; one that reuses a row by conref is noted, not lost
885
+ for (const row of elementChildren(el)) {
886
+ if (isReference(row, "property") && !propertyRows.includes(row) && (row.attribs?.conref || row.attribs?.conkeyref)) {
887
+ const ref = row.attribs.conref ?? row.attribs.conkeyref;
888
+ ctx.note(row.attribs.conref ? "@conref" : "@conkeyref", `<property> pulls content from "${ref}" — ${conrefLedgerDetail(row.attribs, undefined, ctx.conref !== undefined)}`);
889
+ }
890
+ }
838
891
  rows.length = 0;
839
892
  for (const row of propertyRows) {
840
- const converted = convertRow(row, SIMPLE_CELLS);
893
+ const converted = convertRow(row, PROPERTY_CELLS);
841
894
  const cellEls = elementChildren(row).filter((c) => !!propertyKind(c));
842
895
  rows.push({
843
896
  type: "tr",
@@ -847,13 +900,10 @@ const convertTable = (el, ctx) => {
847
900
  }),
848
901
  });
849
902
  }
850
- const lang = publishLanguage(el, ctx.publish);
851
- const label = {
852
- proptype: publishString(ctx.publish, lang, "Type"),
853
- propvalue: publishString(ctx.publish, lang, "Value"),
854
- propdesc: publishString(ctx.publish, lang, "Description"),
855
- };
856
- const authored = header ? convertRow(header, SIMPLE_CELLS, true) : undefined;
903
+ const lang = ctx.publish ? publishLanguage(el, ctx.publish) : undefined;
904
+ const word = (w) => (ctx.publish ? publishString(ctx.publish, lang, w) : w);
905
+ const label = { proptype: word("Type"), propvalue: word("Value"), propdesc: word("Description") };
906
+ const authored = header ? convertRow(header, PROPERTY_CELLS, true) : undefined;
857
907
  const headerCells = header ? elementChildren(header).filter((c) => !!propertyKind(c, "hd")) : [];
858
908
  headRows.length = 0;
859
909
  headRows.push({
@@ -940,11 +990,11 @@ export const convertStepContent = (stepEl, ctx) => {
940
990
  const convertSteps = (el, ctx, type) => {
941
991
  const stepTag = type === "steps" ? "step" : "substep";
942
992
  const children = el.children
943
- .filter((c) => isElement(c) && c.name.toLowerCase() === stepTag)
993
+ .filter((c) => isPart(c, ctx, stepTag))
944
994
  .map((stepEl) => {
945
995
  const viaConref = itemConref(stepEl, ctx, "step") ?? definingItemNode(stepEl, ctx, "step");
946
996
  if (viaConref)
947
- return withProvenance(viaConref, stepEl);
997
+ return atLine(withProvenance(viaConref, stepEl), stepEl, ctx);
948
998
  const { inline: content, children: blocks } = convertStepContent(stepEl, { ...ctx, constrained: true });
949
999
  // Publishing: DITA-OT labels optional and required steps
950
1000
  const importance = stepEl.attribs?.importance;
@@ -960,7 +1010,7 @@ const convertSteps = (el, ctx, type) => {
960
1010
  step.inline = inline;
961
1011
  if (children.length > 0)
962
1012
  step.children = children;
963
- return withProvenance(step, stepEl);
1013
+ return atLine(withProvenance(step, stepEl), stepEl, ctx);
964
1014
  });
965
1015
  return { type, children };
966
1016
  };
@@ -1012,7 +1062,7 @@ const publishTaskLabel = (name, ctx, el) => ctx.publish?.taskLabels && TASK_LABE
1012
1062
  /** Block-level DITA elements (used to split mixed content). */
1013
1063
  const BLOCK_ELEMENTS = new Set([
1014
1064
  "p", "shortdesc", "note", "codeblock", "pre", "screen", "msgblock", "ul", "ol", "sl", "dl", "parml", "table", "simpletable",
1015
- "fig", "image", "section", "example", "steps", "steps-unordered", "substeps", "lq", "object",
1065
+ "properties", "fig", "image", "section", "example", "steps", "steps-unordered", "substeps", "lq", "object",
1016
1066
  "prereq", "context", "result", "postreq", "tasktroubleshooting", "choices", "choicetable", "syntaxdiagram",
1017
1067
  ]);
1018
1068
  const SYNTAX_GROUPS = new Set(["groupseq", "groupchoice", "groupcomp"]);
@@ -1119,6 +1169,27 @@ const ANCHORED_ELSEWHERE = new Set(["title", "related-links", "prolog", "data",
1119
1169
  * DITA-OT's pages. (Headings carry their own id.)
1120
1170
  */
1121
1171
  export function convertBlock(el, ctx) {
1172
+ // A note raised while converting this element takes its line
1173
+ const outer = ctx.position?.el;
1174
+ if (ctx.position)
1175
+ ctx.position.el = el;
1176
+ try {
1177
+ const out = convertBlockThemed(el, ctx);
1178
+ // Source lines: each node this element became starts at its line
1179
+ // (nested blocks came through here first and keep their own)
1180
+ const line = ctx.lineOf?.(el);
1181
+ if (line !== undefined)
1182
+ for (const node of out)
1183
+ if (node.meta?.line === undefined)
1184
+ node.meta = { ...node.meta, line };
1185
+ return out;
1186
+ }
1187
+ finally {
1188
+ if (ctx.position)
1189
+ ctx.position.el = outer;
1190
+ }
1191
+ }
1192
+ function convertBlockThemed(el, ctx) {
1122
1193
  const out = convertBlockAnchored(el, ctx);
1123
1194
  // A scoped theme wraps the element's whole output, its anchor included
1124
1195
  const theme = /(^|\s)db-theme-/i.test(el.attribs?.outputclass ?? "") ? themeOf(el, ctx) : undefined;
@@ -1364,7 +1435,7 @@ function convertBlockContent(el, ctx) {
1364
1435
  // as <li>: referencing items include or ledger, defining items
1365
1436
  // hand their text to the snippet)
1366
1437
  const items = el.children
1367
- .filter((c) => isElement(c) && c.name.toLowerCase() === "sli")
1438
+ .filter((c) => isPart(c, ctx, "sli"))
1368
1439
  .map((sli) => {
1369
1440
  const viaConref = itemConref(sli, ctx, "list-item") ?? definingItemNode(sli, ctx, "list-item");
1370
1441
  if (viaConref)
@@ -1400,9 +1471,17 @@ function convertBlockContent(el, ctx) {
1400
1471
  return [withProvenance(convertDefList(el, ctx, { entry: "plentry", term: "pt", def: "pd" }), el)];
1401
1472
  case "table":
1402
1473
  case "simpletable":
1403
- // Publishing: DITA-OT drops a properties table none of whose properties has a cell
1404
- if (ctx.publish && hasClassToken(el, "reference/properties") && propertiesColumns(el).propertyRows.length === 0)
1474
+ case "properties":
1475
+ // A properties table none of whose properties has a cell has no columns: DITA-OT drops it
1476
+ if (isReference(el, "properties") && propertiesColumns(el).propertyRows.length === 0) {
1477
+ if (!ctx.publish) {
1478
+ for (const row of elementChildren(el).filter((r) => r.attribs?.conref || r.attribs?.conkeyref)) {
1479
+ const ref = row.attribs.conref ?? row.attribs.conkeyref;
1480
+ ctx.note(row.attribs.conref ? "@conref" : "@conkeyref", `<${row.name.toLowerCase()}> pulls content from "${ref}" — ${conrefLedgerDetail(row.attribs, undefined, ctx.conref !== undefined)}`);
1481
+ }
1482
+ }
1405
1483
  return [];
1484
+ }
1406
1485
  return [withProvenance(convertTable(el, ctx), el)];
1407
1486
  case "syntaxdiagram":
1408
1487
  if (ctx.publish)
@@ -0,0 +1,15 @@
1
+ import type { AnyNode, Element } from "domhandler";
2
+ /** An element's DITA 1.3 default @class (`inMap`: inside a map document), or undefined for a name the DTDs do not declare. */
3
+ export declare const classDefault: (name: string, inMap?: boolean) => string | undefined;
4
+ /**
5
+ * Fill in the @class a DTD would have defaulted, on every element that has
6
+ * none, as parsing against the DTDs (or DITA-OT preprocessing) does. An
7
+ * existing @class is kept. Returns the element names the DITA 1.3 DTDs do not
8
+ * declare (custom specializations, DITA 2.0), in document order, each once;
9
+ * those stay unclassed. Not reported: the `<dita>` wrapper of a composite
10
+ * topic, which has no @class by design, and foreign vocabularies (a
11
+ * namespace prefix, or an undeclared name inside a `<foreign>`
12
+ * specialization: MathML, SVG), which are not DITA elements and are left
13
+ * untouched. A DITA element inside one (`<mathmlref>`, `<svgref>`) is classed.
14
+ */
15
+ export declare function applyClassDefaults(nodes: AnyNode[], firstOf?: Map<string, Element>): string[];
@@ -0,0 +1,42 @@
1
+ import { isTag } from "domhandler";
2
+ import { DITA_CLASS_DEFAULTS, DITA_MAP_CLASS_DEFAULTS } from "./class-defaults.js";
3
+ const own = (table, name) => Object.prototype.hasOwnProperty.call(table, name) ? table[name] : undefined;
4
+ /** An element's DITA 1.3 default @class (`inMap`: inside a map document), or undefined for a name the DTDs do not declare. */
5
+ export const classDefault = (name, inMap = false) => (inMap ? own(DITA_MAP_CLASS_DEFAULTS, name) : undefined) ?? own(DITA_CLASS_DEFAULTS, name);
6
+ /**
7
+ * Fill in the @class a DTD would have defaulted, on every element that has
8
+ * none, as parsing against the DTDs (or DITA-OT preprocessing) does. An
9
+ * existing @class is kept. Returns the element names the DITA 1.3 DTDs do not
10
+ * declare (custom specializations, DITA 2.0), in document order, each once;
11
+ * those stay unclassed. Not reported: the `<dita>` wrapper of a composite
12
+ * topic, which has no @class by design, and foreign vocabularies (a
13
+ * namespace prefix, or an undeclared name inside a `<foreign>`
14
+ * specialization: MathML, SVG), which are not DITA elements and are left
15
+ * untouched. A DITA element inside one (`<mathmlref>`, `<svgref>`) is classed.
16
+ */
17
+ export function applyClassDefaults(nodes, firstOf) {
18
+ const root = nodes.find(isTag);
19
+ const inMap = !!root && (["map", "bookmap", "subjectScheme"].includes(root.name) || ` ${root.attribs?.class ?? ""} `.includes(" map/map "));
20
+ const unknown = new Set();
21
+ const visit = (el, inForeign) => {
22
+ if (el.name.includes(":"))
23
+ return;
24
+ if (!el.attribs?.class?.trim()) {
25
+ const value = classDefault(el.name, inMap);
26
+ if (value)
27
+ el.attribs = { ...el.attribs, class: value };
28
+ else if (el.name !== "dita" && !inForeign && !unknown.has(el.name)) {
29
+ unknown.add(el.name);
30
+ firstOf?.set(el.name, el);
31
+ }
32
+ }
33
+ const foreign = inForeign || ` ${el.attribs?.class ?? ""} `.includes(" topic/foreign ");
34
+ for (const child of el.children)
35
+ if (isTag(child))
36
+ visit(child, foreign);
37
+ };
38
+ for (const node of nodes)
39
+ if (isTag(node))
40
+ visit(node, false);
41
+ return [...unknown];
42
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Each DITA 1.3 element's default @class, as its DTD declares it. GENERATED by
3
+ * scripts/generate-class-defaults.mjs from the .mod files under dita-ot-4.3.5's
4
+ * plugins/org.oasis-open.dita.v1_3/dtd/ (612 elements); do not edit.
5
+ */
6
+ export declare const DITA_CLASS_DEFAULTS: Readonly<Record<string, string>>;
7
+ /** Elements whose class differs inside a map (map.mod declares them too). */
8
+ export declare const DITA_MAP_CLASS_DEFAULTS: Readonly<Record<string, string>>;