@dogsbay/format-dita 0.2.0-beta.122 → 0.2.0-beta.124
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 +19 -1
- package/dist/anchors.d.ts +0 -1
- package/dist/anchors.js +0 -1
- package/dist/blocks.d.ts +2 -1
- package/dist/blocks.js +289 -37
- package/dist/class-defaults-apply.d.ts +15 -0
- package/dist/class-defaults-apply.js +40 -0
- package/dist/class-defaults.d.ts +8 -0
- package/dist/class-defaults.js +625 -0
- package/dist/conref.d.ts +0 -1
- package/dist/conref.js +1 -2
- package/dist/index.d.ts +4 -1
- package/dist/index.js +5 -1
- package/dist/inline.d.ts +2 -9
- package/dist/inline.js +50 -8
- package/dist/markdown.d.ts +0 -1
- package/dist/markdown.js +1 -2
- package/dist/parse.d.ts +0 -1
- package/dist/parse.js +24 -4
- package/dist/publish-support.d.ts +0 -1
- package/dist/publish-support.js +0 -1
- package/dist/qualifiers.d.ts +25 -0
- package/dist/qualifiers.js +40 -0
- package/dist/types.d.ts +10 -1
- package/dist/types.js +0 -1
- package/dist/well-formed.d.ts +14 -0
- package/dist/well-formed.js +110 -0
- package/package.json +5 -4
- package/dist/anchors.d.ts.map +0 -1
- package/dist/anchors.js.map +0 -1
- package/dist/blocks.d.ts.map +0 -1
- package/dist/blocks.js.map +0 -1
- package/dist/conref.d.ts.map +0 -1
- package/dist/conref.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/inline.d.ts.map +0 -1
- package/dist/inline.js.map +0 -1
- package/dist/markdown.d.ts.map +0 -1
- package/dist/markdown.js.map +0 -1
- package/dist/parse.d.ts.map +0 -1
- package/dist/parse.js.map +0 -1
- package/dist/publish-support.d.ts.map +0 -1
- package/dist/publish-support.js.map +0 -1
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js.map +0 -1
package/README.md
CHANGED
|
@@ -3,6 +3,12 @@
|
|
|
3
3
|
Convert DITA topic XML to Dogsbay's TreeNode model — and, composed with
|
|
4
4
|
`@dogsbay/format-dogsbay-md`, straight to markdown.
|
|
5
5
|
|
|
6
|
+
**Browser-safe:** the package imports no Node built-ins, so it bundles for a
|
|
7
|
+
browser or a Worker (a test bundles it with esbuild for `platform: "browser"`).
|
|
8
|
+
Malformed XML is reported, not repaired silently: the parser would close an
|
|
9
|
+
unclosed element for you, so a `<xml>` note gives the first problem and its
|
|
10
|
+
line (`checkWellFormed` is exported too).
|
|
11
|
+
|
|
6
12
|
```ts
|
|
7
13
|
import { ditaTopicToDogsbayMd } from "@dogsbay/format-dita";
|
|
8
14
|
|
|
@@ -21,7 +27,7 @@ dogsbay import-dita docs/ -o content --report topics.md
|
|
|
21
27
|
```
|
|
22
28
|
|
|
23
29
|
Tasks become native `:::steps`, notes become callouts, CALS and
|
|
24
|
-
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)`,
|
|
25
31
|
and `keyref` links become `key:` links. Nested or sibling topics in
|
|
26
32
|
multi-topic files are emitted inline as anchored sections.
|
|
27
33
|
|
|
@@ -32,6 +38,18 @@ emit `{% include %}` so one canonical copy of reused text survives. Use
|
|
|
32
38
|
`dogsbay import-dita --no-conref-includes` to keep conrefs on the ledger
|
|
33
39
|
instead.
|
|
34
40
|
|
|
41
|
+
**Specializations in raw source:** a file as authored has no `@class`, so
|
|
42
|
+
an element is known only by its name, and a specialization the converter
|
|
43
|
+
does not know by name (a `<troubleshooting>` topic, a hazard statement's
|
|
44
|
+
items) loses its markup. `{ classDefaults: true }` fills in each missing
|
|
45
|
+
`@class` from the DITA 1.3 DTD defaults first (612 elements, the table
|
|
46
|
+
`DITA_CLASS_DEFAULTS`, generated by `scripts/generate-class-defaults.mjs`
|
|
47
|
+
from DITA-OT's `.mod` files), as parsing against the DTDs would; the
|
|
48
|
+
element then converts as what it specializes. An existing `@class` is kept;
|
|
49
|
+
a name the DTDs do not declare (custom or DITA 2.0) stays unclassed, with
|
|
50
|
+
one note per topic. It is off by default for now because it changes the
|
|
51
|
+
output for such elements.
|
|
52
|
+
|
|
35
53
|
Everything that cannot map cleanly lands in the conversion ledger instead
|
|
36
54
|
of disappearing: filter attributes, table spans, semantic-inline downgrades,
|
|
37
55
|
`conkeyref`, conref ranges/pushes, whole-topic conrefs, unresolved targets,
|
package/dist/anchors.d.ts
CHANGED
package/dist/anchors.js
CHANGED
|
@@ -32,4 +32,3 @@ export const renamedElementIds = (nodes) => {
|
|
|
32
32
|
};
|
|
33
33
|
/** The anchor for an element id in a topic: the id, or `topicid__elementid` when an earlier topic has it. */
|
|
34
34
|
export const anchorId = (ctx, id) => (ctx.topicId !== undefined && ctx.anchorIds?.get(`${ctx.topicId}/${id}`)) || id;
|
|
35
|
-
//# sourceMappingURL=anchors.js.map
|
package/dist/blocks.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ import type { Element, AnyNode } from "domhandler";
|
|
|
11
11
|
import type { TreeNode } from "@dogsbay/types";
|
|
12
12
|
import { type InlineContext } from "./inline.js";
|
|
13
13
|
import { type ConrefSiteContext, type ConrefSnippetRef } from "./types.js";
|
|
14
|
+
import { DB_QUALIFIERS } from "./qualifiers.js";
|
|
14
15
|
export interface BlockContext extends InlineContext {
|
|
15
16
|
/** Current heading depth for <section>/<example> titles. */
|
|
16
17
|
headingLevel: number;
|
|
@@ -31,6 +32,7 @@ export interface BlockContext extends InlineContext {
|
|
|
31
32
|
* from the snippet's baked-in base level.
|
|
32
33
|
*/
|
|
33
34
|
export declare const includeDirective: (snippet: ConrefSnippetRef, site: ConrefSiteContext, headingLevel: number) => string;
|
|
35
|
+
export { DB_QUALIFIERS };
|
|
34
36
|
/**
|
|
35
37
|
* One <step>/<substep>'s content: <cmd> as the leading inline run, the
|
|
36
38
|
* rest as block children. Shared by convertSteps (constrained context)
|
|
@@ -61,4 +63,3 @@ export declare function convertBlock(el: Element, ctx: BlockContext): TreeNode[]
|
|
|
61
63
|
export declare function convertChildren(el: Element, ctx: BlockContext,
|
|
62
64
|
/** Element names, or particular child nodes, to leave out */
|
|
63
65
|
skip?: Set<string | AnyNode>): TreeNode[];
|
|
64
|
-
//# sourceMappingURL=blocks.d.ts.map
|
package/dist/blocks.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { inlineToDogsbayMd } from "@dogsbay/format-dogsbay-md";
|
|
1
|
+
import { inlineToDogsbayMd } from "@dogsbay/format-dogsbay-md/browser";
|
|
2
2
|
import { convertInline, elementName, 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
|
+
import { DB_QUALIFIERS, outputTokens, youtubeId } from "./qualifiers.js";
|
|
5
6
|
const isElement = (node) => node.type === "tag";
|
|
6
7
|
const isNonEmptyText = (node) => node.type === "text" && node.data.trim().length > 0;
|
|
7
8
|
/** DITA note @type → callout type in the dogsbay-md vocabulary. */
|
|
@@ -209,8 +210,14 @@ const definingItemNode = (el, ctx, type) => {
|
|
|
209
210
|
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`);
|
|
210
211
|
return null;
|
|
211
212
|
};
|
|
213
|
+
/**
|
|
214
|
+
* Whether an element is a `tag` by name or, with @class, by what it
|
|
215
|
+
* specializes: a hazard statement's <typeofhazard> is an <li>. Matching the
|
|
216
|
+
* name alone dropped such items, and their text, without a note.
|
|
217
|
+
*/
|
|
218
|
+
const isPart = (el, ctx, tag) => isElement(el) && elementName(el, ctx, (n) => n === tag) === tag;
|
|
212
219
|
const convertListItems = (el, ctx, itemTag) => el.children
|
|
213
|
-
.filter((c) =>
|
|
220
|
+
.filter((c) => isPart(c, ctx, itemTag))
|
|
214
221
|
.map((li) => {
|
|
215
222
|
const viaConref = itemConref(li, ctx, "list-item") ?? definingItemNode(li, ctx, "list-item");
|
|
216
223
|
if (viaConref)
|
|
@@ -230,9 +237,13 @@ const DB_COMPONENTS = {
|
|
|
230
237
|
section: ["db-details"],
|
|
231
238
|
// A section cannot nest, and cannot hold one: these can, so a details or
|
|
232
239
|
// sheet goes inside a section (or another div) through them
|
|
233
|
-
div: ["db-details"],
|
|
234
|
-
sectiondiv: ["db-details"],
|
|
235
|
-
bodydiv: ["db-details"],
|
|
240
|
+
div: ["db-details", "db-grid"],
|
|
241
|
+
sectiondiv: ["db-details", "db-grid"],
|
|
242
|
+
bodydiv: ["db-details", "db-grid"],
|
|
243
|
+
ul: ["db-files"],
|
|
244
|
+
ol: ["db-steps"],
|
|
245
|
+
// Alone in a <p>: a block component (xrefComponent)
|
|
246
|
+
xref: ["db-link-card", "db-button", "db-video"],
|
|
236
247
|
};
|
|
237
248
|
/** Elements without a <title>: a `db-details` one takes it from a leading `<p outputclass="db-title">`. */
|
|
238
249
|
const UNTITLED_DETAILS = new Set(["div", "sectiondiv", "bodydiv"]);
|
|
@@ -248,7 +259,9 @@ const toDetails = (el, ctx, classes, title, skip, titleId) => {
|
|
|
248
259
|
const ownId = el.attribs?.id ?? titleId;
|
|
249
260
|
if (ownId)
|
|
250
261
|
props.id = anchorId(ctx, ownId);
|
|
251
|
-
const
|
|
262
|
+
const q = qualify("db-details", classes, ctx);
|
|
263
|
+
Object.assign(props, q.props);
|
|
264
|
+
const tokens = (q.classes ?? "").split(" ").filter(Boolean);
|
|
252
265
|
if (tokens.includes("drawer"))
|
|
253
266
|
ctx.note("@outputclass", `"drawer" on db-details is now "sheet" — converted as a sheet`);
|
|
254
267
|
if (tokens.includes("sheet") || tokens.includes("drawer"))
|
|
@@ -267,6 +280,99 @@ const toDetails = (el, ctx, classes, title, skip, titleId) => {
|
|
|
267
280
|
ctx.note("@outputclass", `db-details "${props.title}" has no content`);
|
|
268
281
|
return withProvenance({ type: "details", props, children }, el);
|
|
269
282
|
};
|
|
283
|
+
/**
|
|
284
|
+
* `<div outputclass="db-grid cols-3">`: each child `<div>` is a cell (its
|
|
285
|
+
* `span-N` token spans columns); any other child block is a cell of its own.
|
|
286
|
+
* DITA-OT shows the cells one after another.
|
|
287
|
+
*/
|
|
288
|
+
const toGrid = (el, ctx, classes) => {
|
|
289
|
+
const q = qualify("db-grid", classes, ctx);
|
|
290
|
+
const props = { ...q.props, ...(q.classes ? { class: q.classes } : {}) };
|
|
291
|
+
if (el.attribs?.id)
|
|
292
|
+
props.id = anchorId(ctx, el.attribs.id);
|
|
293
|
+
const cells = [];
|
|
294
|
+
for (const child of el.children) {
|
|
295
|
+
if (!isElement(child)) {
|
|
296
|
+
if (isNonEmptyText(child))
|
|
297
|
+
cells.push({ type: "grid-item", children: [{ type: "paragraph", inline: convertInline([child], ctx) }] });
|
|
298
|
+
continue;
|
|
299
|
+
}
|
|
300
|
+
if (blockName(child, ctx) === "div") {
|
|
301
|
+
const cellProps = {};
|
|
302
|
+
const rest = [];
|
|
303
|
+
for (const t of outputTokens(child.attribs?.outputclass)) {
|
|
304
|
+
const span = /^span-(\d+)$/.exec(t);
|
|
305
|
+
if (span && DB_QUALIFIERS.gridColumns.includes(Number(span[1])))
|
|
306
|
+
cellProps.span = Number(span[1]);
|
|
307
|
+
else if (/^[a-z0-9][a-z0-9-]*$/.test(t) && !t.startsWith("db-"))
|
|
308
|
+
rest.push(t);
|
|
309
|
+
else
|
|
310
|
+
ctx.note("@outputclass", `"${t}" on a db-grid cell ignored: a cell takes span-2 to span-6`);
|
|
311
|
+
}
|
|
312
|
+
if (rest.length)
|
|
313
|
+
cellProps.class = rest.join(" ");
|
|
314
|
+
if (child.attribs?.id)
|
|
315
|
+
cellProps.id = anchorId(ctx, child.attribs.id);
|
|
316
|
+
cells.push(withProvenance({ type: "grid-item", ...(Object.keys(cellProps).length ? { props: cellProps } : {}), children: convertChildren(child, ctx) }, child));
|
|
317
|
+
}
|
|
318
|
+
else {
|
|
319
|
+
const blocks = convertBlock(child, ctx);
|
|
320
|
+
if (blocks.length)
|
|
321
|
+
cells.push({ type: "grid-item", children: blocks });
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
if (!cells.length)
|
|
325
|
+
ctx.note("@outputclass", `db-grid has no cells`);
|
|
326
|
+
return withProvenance({ type: "grid", props, children: cells }, el);
|
|
327
|
+
};
|
|
328
|
+
/**
|
|
329
|
+
* A `<p>` holding only an `<xref outputclass="db-link-card|db-button|db-video">`
|
|
330
|
+
* (and whitespace): the block component. The href resolves exactly as the
|
|
331
|
+
* xref's would (rename, fragment, key, publish paths), because the link is
|
|
332
|
+
* converted first and read back. Undefined when the paragraph is anything
|
|
333
|
+
* else; an xref component beside other text stays a link, with a note.
|
|
334
|
+
*/
|
|
335
|
+
const xrefComponent = (p, ctx) => {
|
|
336
|
+
const kids = p.children.filter((c) => isElement(c) || isNonEmptyText(c));
|
|
337
|
+
const xrefs = p.children.filter((c) => isElement(c) && c.name.toLowerCase() === "xref" && /(^|\s)db-/.test(c.attribs?.outputclass ?? ""));
|
|
338
|
+
if (!xrefs.length)
|
|
339
|
+
return undefined;
|
|
340
|
+
if (kids.length !== 1) {
|
|
341
|
+
ctx.note("@outputclass", `an <xref> component must be alone in its <p> — kept as a link`);
|
|
342
|
+
return undefined;
|
|
343
|
+
}
|
|
344
|
+
const x = xrefs[0];
|
|
345
|
+
const component = dbComponent(x, ctx);
|
|
346
|
+
if (!component)
|
|
347
|
+
return undefined;
|
|
348
|
+
if (ctx.inTableCell) {
|
|
349
|
+
// A cell holds inline content only: the component would lose its link
|
|
350
|
+
ctx.note("@outputclass", `${component.name} inside a table cell — kept as a link`);
|
|
351
|
+
return undefined;
|
|
352
|
+
}
|
|
353
|
+
const link = convertInline([x], ctx).find((n) => n.type === "link");
|
|
354
|
+
if (!link?.href) {
|
|
355
|
+
ctx.note("@outputclass", `${component.name} without a resolvable href — kept as text`);
|
|
356
|
+
return undefined;
|
|
357
|
+
}
|
|
358
|
+
const title = inlineLabel(link.children);
|
|
359
|
+
const q = qualify(component.name, component.classes, ctx);
|
|
360
|
+
const props = { ...q.props, ...(q.classes ? { class: q.classes } : {}) };
|
|
361
|
+
if (component.name === "db-link-card") {
|
|
362
|
+
const desc = x.children.find((c) => isElement(c) && c.name.toLowerCase() === "desc");
|
|
363
|
+
const description = desc ? inlineLabel(convertInline(desc.children, ctx)) : "";
|
|
364
|
+
return withProvenance({ type: "link-card", props: { ...props, title: title || link.href, href: link.href, ...(description ? { description } : {}) } }, x);
|
|
365
|
+
}
|
|
366
|
+
if (component.name === "db-button") {
|
|
367
|
+
return withProvenance({ type: "link-button", props: { ...props, href: link.href }, children: [{ type: "paragraph", inline: link.children }] }, x);
|
|
368
|
+
}
|
|
369
|
+
const id = youtubeId(link.href);
|
|
370
|
+
if (!id) {
|
|
371
|
+
ctx.note("@outputclass", `db-video "${link.href}" is not a YouTube URL — kept as a link`);
|
|
372
|
+
return undefined;
|
|
373
|
+
}
|
|
374
|
+
return withProvenance({ type: "youtube", props: { ...props, id, ...(title && title !== link.href ? { title } : {}) } }, x);
|
|
375
|
+
};
|
|
270
376
|
/**
|
|
271
377
|
* The component an element's `@outputclass` selects: its first `db-*` token,
|
|
272
378
|
* and the remaining tokens as classes. `db-` makes the token ours: other
|
|
@@ -277,7 +383,8 @@ const toDetails = (el, ctx, classes, title, skip, titleId) => {
|
|
|
277
383
|
* as plain DITA.
|
|
278
384
|
*/
|
|
279
385
|
const dbComponent = (el, ctx) => {
|
|
280
|
-
|
|
386
|
+
// `db-theme-*` is a scope, not a component (themeOf): never picked or kept as a class
|
|
387
|
+
const tokens = outputTokens(el.attribs?.outputclass);
|
|
281
388
|
const at = tokens.findIndex((t) => t.startsWith("db-"));
|
|
282
389
|
if (at < 0)
|
|
283
390
|
return undefined;
|
|
@@ -298,6 +405,83 @@ const dbComponent = (el, ctx) => {
|
|
|
298
405
|
ctx.note("@outputclass", `class ${dropped.map((t) => `"${t}"`).join(", ")} on ${name} dropped: classes are lowercase letters, digits and hyphens`);
|
|
299
406
|
return { name, ...(safe.length ? { classes: safe.join(" ") } : {}) };
|
|
300
407
|
};
|
|
408
|
+
export { DB_QUALIFIERS };
|
|
409
|
+
/**
|
|
410
|
+
* A component's qualifier tokens as props: `pills`/`underline` on db-tabs
|
|
411
|
+
* (`variant`), `tone-*` on db-cards (`tone`) and db-details (its colour,
|
|
412
|
+
* `variant`). Props, not classes: a sanitized single page strips classes, and
|
|
413
|
+
* every renderer and exporter can implement or declare a prop. Anything else
|
|
414
|
+
* stays a free class; a `tone-` token outside the tones is noted.
|
|
415
|
+
*/
|
|
416
|
+
const qualify = (component, classes, ctx) => {
|
|
417
|
+
const props = {};
|
|
418
|
+
const rest = [];
|
|
419
|
+
for (const t of (classes ?? "").split(" ").filter(Boolean)) {
|
|
420
|
+
if (component === "db-tabs" && DB_QUALIFIERS.tabVariants.includes(t)) {
|
|
421
|
+
props.variant = t;
|
|
422
|
+
continue;
|
|
423
|
+
}
|
|
424
|
+
if (component === "db-button" && DB_QUALIFIERS.buttonVariants.includes(t)) {
|
|
425
|
+
if (t !== "primary")
|
|
426
|
+
props.variant = t;
|
|
427
|
+
continue;
|
|
428
|
+
}
|
|
429
|
+
const cols = /^cols-(\d+)$/.exec(t);
|
|
430
|
+
if (component === "db-grid" && cols) {
|
|
431
|
+
if (DB_QUALIFIERS.gridColumns.includes(Number(cols[1])))
|
|
432
|
+
props.cols = Number(cols[1]);
|
|
433
|
+
else
|
|
434
|
+
ctx.note("@outputclass", `"${t}": db-grid takes cols-1 to cols-6 — ignored`);
|
|
435
|
+
continue;
|
|
436
|
+
}
|
|
437
|
+
const tone = /^tone-(.+)$/.exec(t);
|
|
438
|
+
if (tone && (component === "db-cards" || component === "db-details")) {
|
|
439
|
+
if (DB_QUALIFIERS.tones.includes(tone[1]))
|
|
440
|
+
props[component === "db-details" ? "variant" : "tone"] = tone[1];
|
|
441
|
+
else
|
|
442
|
+
ctx.note("@outputclass", `"${t}" is not a tone (${DB_QUALIFIERS.tones.join(", ")}) — ignored`);
|
|
443
|
+
continue;
|
|
444
|
+
}
|
|
445
|
+
if (tone) {
|
|
446
|
+
ctx.note("@outputclass", `"${t}": ${component} takes no tone (db-cards and db-details do) — ignored`);
|
|
447
|
+
continue;
|
|
448
|
+
}
|
|
449
|
+
rest.push(t);
|
|
450
|
+
}
|
|
451
|
+
return { props, ...(rest.length ? { classes: rest.join(" ") } : {}) };
|
|
452
|
+
};
|
|
453
|
+
/** Elements a scoped theme (`db-theme-<name>`) applies to: containers of blocks. */
|
|
454
|
+
// section and its task/reference specialisations, plus the generic containers
|
|
455
|
+
const THEMED = new Set(["section", "sectiondiv", "div", "bodydiv", "example", "context", "prereq", "result", "postreq", "refsyn"]);
|
|
456
|
+
/**
|
|
457
|
+
* The scoped theme an element asks for (`outputclass="db-theme-dark"`),
|
|
458
|
+
* independent of its component token. Noted when it is unknown, on an element
|
|
459
|
+
* that is not a block container, or inside a table cell.
|
|
460
|
+
*/
|
|
461
|
+
const themeOf = (el, ctx) => {
|
|
462
|
+
const tokens = (el.attribs?.outputclass ?? "").split(/\s+/).filter((t) => /^db-theme-/i.test(t));
|
|
463
|
+
const token = tokens[0];
|
|
464
|
+
if (!token)
|
|
465
|
+
return undefined;
|
|
466
|
+
if (tokens.length > 1)
|
|
467
|
+
ctx.note("@outputclass", `${tokens.slice(1).map((t) => `"${t}"`).join(", ")} ignored: one theme per element`);
|
|
468
|
+
const name = token.slice("db-theme-".length).toLowerCase();
|
|
469
|
+
// By @class in publish mode, so a specialised section is still a section
|
|
470
|
+
const element = blockName(el, ctx).toLowerCase();
|
|
471
|
+
if (!THEMED.has(element)) {
|
|
472
|
+
ctx.note("@outputclass", `"${token}" applies to section, sectiondiv, div, bodydiv and example — not <${element}>`);
|
|
473
|
+
return undefined;
|
|
474
|
+
}
|
|
475
|
+
if (!DB_QUALIFIERS.themes.includes(name)) {
|
|
476
|
+
ctx.note("@outputclass", `"${token}" is not a theme (${DB_QUALIFIERS.themes.join(", ")}) — content kept, unthemed`);
|
|
477
|
+
return undefined;
|
|
478
|
+
}
|
|
479
|
+
if (ctx.inTableCell) {
|
|
480
|
+
ctx.note("@outputclass", `"${token}" inside a table cell — content kept, unthemed`);
|
|
481
|
+
return undefined;
|
|
482
|
+
}
|
|
483
|
+
return name;
|
|
484
|
+
};
|
|
301
485
|
/** An `id` anchor the converter wrote (`<a id="x"></a>`), as opposed to other inline HTML. */
|
|
302
486
|
const isIdAnchor = (n) => n.type === "html-inline" && /^<a id="[^"]*"><\/a>$/.test(n.html);
|
|
303
487
|
const decodeEntities = (s) => s.replace(/&(#x[0-9a-f]+|#\d+|amp|lt|gt|quot|apos);/gi, (m, e) => {
|
|
@@ -351,7 +535,7 @@ const inlineLabel = (inline) => (inline ?? [])
|
|
|
351
535
|
const dlComponentEntries = (el, ctx, component, keepEmpty = false, anchorsOut) => {
|
|
352
536
|
const out = [];
|
|
353
537
|
let pending = [];
|
|
354
|
-
const entries = el.children.filter((c) =>
|
|
538
|
+
const entries = el.children.filter((c) => isPart(c, ctx, "dlentry"));
|
|
355
539
|
for (const entry of entries) {
|
|
356
540
|
const items = convertDefList({ ...el, children: [entry] }, ctx).children ?? [];
|
|
357
541
|
const terms = items.filter((n) => n.type === "dt");
|
|
@@ -459,7 +643,7 @@ const dlToCards = (el, ctx, anchors) => {
|
|
|
459
643
|
const convertDefList = (el, ctx, tags = { entry: "dlentry", term: "dt", def: "dd" }) => {
|
|
460
644
|
const children = [];
|
|
461
645
|
for (const entry of el.children.filter(isElement)) {
|
|
462
|
-
if (entry
|
|
646
|
+
if (!isPart(entry, ctx, tags.entry))
|
|
463
647
|
continue;
|
|
464
648
|
// Entry-level conref (<dlentry conref>): a term/definition pair can't
|
|
465
649
|
// splice as an include — ledger it so the loss is never silent
|
|
@@ -469,8 +653,7 @@ const convertDefList = (el, ctx, tags = { entry: "dlentry", term: "dt", def: "dd
|
|
|
469
653
|
}
|
|
470
654
|
let entryAnchored = false;
|
|
471
655
|
for (const part of entry.children.filter(isElement)) {
|
|
472
|
-
|
|
473
|
-
if (name === tags.term) {
|
|
656
|
+
if (isPart(part, ctx, tags.term)) {
|
|
474
657
|
// Term-level conref (<dt conref>/<pt conref>): single-line
|
|
475
658
|
// include or ledger — never a silent empty term
|
|
476
659
|
const viaConref = constrainedConrefInline(part, ctx);
|
|
@@ -481,7 +664,7 @@ const convertDefList = (el, ctx, tags = { entry: "dlentry", term: "dt", def: "dd
|
|
|
481
664
|
});
|
|
482
665
|
entryAnchored = true;
|
|
483
666
|
}
|
|
484
|
-
else if (
|
|
667
|
+
else if (isPart(part, ctx, tags.def)) {
|
|
485
668
|
const viaConref = constrainedConrefInline(part, ctx);
|
|
486
669
|
if (viaConref) {
|
|
487
670
|
children.push({ type: "dd", inline: viaConref });
|
|
@@ -541,12 +724,23 @@ const TABLE_PARTS = new Set([
|
|
|
541
724
|
const hasClassToken = (el, token) => ` ${el.attribs?.class ?? ""} `.includes(` ${token} `);
|
|
542
725
|
const elementChildren = (el) => el.children.filter(isElement);
|
|
543
726
|
const PROPERTY_KINDS = ["proptype", "propvalue", "propdesc"];
|
|
727
|
+
/**
|
|
728
|
+
* Whether an element is the reference domain's `local` (`properties`, `property`, …):
|
|
729
|
+
* by @class when DITA-OT has filled it in, else by name, as authored source has none.
|
|
730
|
+
*/
|
|
731
|
+
const isReference = (el, local) => hasClassToken(el, `reference/${local}`) || el.name.toLowerCase() === local;
|
|
544
732
|
/** A properties table cell's column: `proptype`, or with suffix "hd" a header cell (`proptypehd`). */
|
|
545
|
-
const propertyKind = (cell, suffix = "") => PROPERTY_KINDS.find((k) =>
|
|
733
|
+
const propertyKind = (cell, suffix = "") => PROPERTY_KINDS.find((k) => isReference(cell, `${k}${suffix}`));
|
|
734
|
+
/**
|
|
735
|
+
* A properties table's cells. Exactly the cells `propertyKind` recognizes (a
|
|
736
|
+
* published cell's @class names its kind before the stentry it specializes),
|
|
737
|
+
* so a row's converted cells and its cell elements line up index for index.
|
|
738
|
+
*/
|
|
739
|
+
const PROPERTY_CELLS = new Set([...PROPERTY_KINDS, ...PROPERTY_KINDS.map((k) => `${k}hd`)]);
|
|
546
740
|
/** A properties table's columns in use, its properties that have cells, and its header row. */
|
|
547
741
|
const propertiesColumns = (el) => {
|
|
548
|
-
const header = elementChildren(el).find((c) =>
|
|
549
|
-
const propertyRows = elementChildren(el).filter((c) =>
|
|
742
|
+
const header = elementChildren(el).find((c) => isReference(c, "prophead"));
|
|
743
|
+
const propertyRows = elementChildren(el).filter((c) => isReference(c, "property") && elementChildren(c).some((cell) => !!propertyKind(cell)));
|
|
550
744
|
const used = PROPERTY_KINDS.filter((k) => propertyRows.some((r) => elementChildren(r).some((c) => propertyKind(c) === k)) ||
|
|
551
745
|
(header ? elementChildren(header).some((c) => propertyKind(c, "hd") === k) : false));
|
|
552
746
|
return { used, propertyRows, ...(header ? { header } : {}) };
|
|
@@ -651,15 +845,24 @@ const convertTable = (el, ctx) => {
|
|
|
651
845
|
}
|
|
652
846
|
};
|
|
653
847
|
walk(el);
|
|
654
|
-
//
|
|
848
|
+
// A properties table's columns are the type, value and description columns
|
|
655
849
|
// its header or any property uses (DITA-OT's hasType, hasValue, hasDesc); each row
|
|
656
850
|
// aligns its cells to them, a property with no cells is dropped, and a header cell
|
|
657
|
-
// missing for a column in use is DITA-OT's generated label ("Type", "Value",
|
|
658
|
-
|
|
851
|
+
// missing for a column in use is DITA-OT's generated label ("Type", "Value",
|
|
852
|
+
// "Description"; localized when publishing). Authored source has no @class, so
|
|
853
|
+
// the parts are matched by name too (the walk above sees no sthead/strow then).
|
|
854
|
+
if (isReference(el, "properties")) {
|
|
659
855
|
const { used, propertyRows, header } = propertiesColumns(el);
|
|
856
|
+
// A property with no cells has no row; one that reuses a row by conref is noted, not lost
|
|
857
|
+
for (const row of elementChildren(el)) {
|
|
858
|
+
if (isReference(row, "property") && !propertyRows.includes(row) && (row.attribs?.conref || row.attribs?.conkeyref)) {
|
|
859
|
+
const ref = row.attribs.conref ?? row.attribs.conkeyref;
|
|
860
|
+
ctx.note(row.attribs.conref ? "@conref" : "@conkeyref", `<property> pulls content from "${ref}" — ${conrefLedgerDetail(row.attribs, undefined, ctx.conref !== undefined)}`);
|
|
861
|
+
}
|
|
862
|
+
}
|
|
660
863
|
rows.length = 0;
|
|
661
864
|
for (const row of propertyRows) {
|
|
662
|
-
const converted = convertRow(row,
|
|
865
|
+
const converted = convertRow(row, PROPERTY_CELLS);
|
|
663
866
|
const cellEls = elementChildren(row).filter((c) => !!propertyKind(c));
|
|
664
867
|
rows.push({
|
|
665
868
|
type: "tr",
|
|
@@ -669,13 +872,10 @@ const convertTable = (el, ctx) => {
|
|
|
669
872
|
}),
|
|
670
873
|
});
|
|
671
874
|
}
|
|
672
|
-
const lang = publishLanguage(el, ctx.publish);
|
|
673
|
-
const
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
propdesc: publishString(ctx.publish, lang, "Description"),
|
|
677
|
-
};
|
|
678
|
-
const authored = header ? convertRow(header, SIMPLE_CELLS, true) : undefined;
|
|
875
|
+
const lang = ctx.publish ? publishLanguage(el, ctx.publish) : undefined;
|
|
876
|
+
const word = (w) => (ctx.publish ? publishString(ctx.publish, lang, w) : w);
|
|
877
|
+
const label = { proptype: word("Type"), propvalue: word("Value"), propdesc: word("Description") };
|
|
878
|
+
const authored = header ? convertRow(header, PROPERTY_CELLS, true) : undefined;
|
|
679
879
|
const headerCells = header ? elementChildren(header).filter((c) => !!propertyKind(c, "hd")) : [];
|
|
680
880
|
headRows.length = 0;
|
|
681
881
|
headRows.push({
|
|
@@ -762,7 +962,7 @@ export const convertStepContent = (stepEl, ctx) => {
|
|
|
762
962
|
const convertSteps = (el, ctx, type) => {
|
|
763
963
|
const stepTag = type === "steps" ? "step" : "substep";
|
|
764
964
|
const children = el.children
|
|
765
|
-
.filter((c) =>
|
|
965
|
+
.filter((c) => isPart(c, ctx, stepTag))
|
|
766
966
|
.map((stepEl) => {
|
|
767
967
|
const viaConref = itemConref(stepEl, ctx, "step") ?? definingItemNode(stepEl, ctx, "step");
|
|
768
968
|
if (viaConref)
|
|
@@ -834,7 +1034,7 @@ const publishTaskLabel = (name, ctx, el) => ctx.publish?.taskLabels && TASK_LABE
|
|
|
834
1034
|
/** Block-level DITA elements (used to split mixed content). */
|
|
835
1035
|
const BLOCK_ELEMENTS = new Set([
|
|
836
1036
|
"p", "shortdesc", "note", "codeblock", "pre", "screen", "msgblock", "ul", "ol", "sl", "dl", "parml", "table", "simpletable",
|
|
837
|
-
"fig", "image", "section", "example", "steps", "steps-unordered", "substeps", "lq", "object",
|
|
1037
|
+
"properties", "fig", "image", "section", "example", "steps", "steps-unordered", "substeps", "lq", "object",
|
|
838
1038
|
"prereq", "context", "result", "postreq", "tasktroubleshooting", "choices", "choicetable", "syntaxdiagram",
|
|
839
1039
|
]);
|
|
840
1040
|
const SYNTAX_GROUPS = new Set(["groupseq", "groupchoice", "groupcomp"]);
|
|
@@ -941,6 +1141,17 @@ const ANCHORED_ELSEWHERE = new Set(["title", "related-links", "prolog", "data",
|
|
|
941
1141
|
* DITA-OT's pages. (Headings carry their own id.)
|
|
942
1142
|
*/
|
|
943
1143
|
export function convertBlock(el, ctx) {
|
|
1144
|
+
const out = convertBlockAnchored(el, ctx);
|
|
1145
|
+
// A scoped theme wraps the element's whole output, its anchor included
|
|
1146
|
+
const theme = /(^|\s)db-theme-/i.test(el.attribs?.outputclass ?? "") ? themeOf(el, ctx) : undefined;
|
|
1147
|
+
if (!theme || !out.length)
|
|
1148
|
+
return out;
|
|
1149
|
+
// The element's own id anchor stays outside the band: inside, it would be
|
|
1150
|
+
// the band's first child and take the first-child margin trim meant for content
|
|
1151
|
+
const lead = out[0].type === "html" && /^<a id="[^"]*"><\/a>$/.test(out[0].html ?? "") ? [out[0]] : [];
|
|
1152
|
+
return [...lead, { type: "theme", props: { name: theme }, children: out.slice(lead.length) }];
|
|
1153
|
+
}
|
|
1154
|
+
function convertBlockAnchored(el, ctx) {
|
|
944
1155
|
const out = convertBlockContent(el, ctx);
|
|
945
1156
|
const id = el.attribs?.id;
|
|
946
1157
|
if (!ctx.publish || !id || ANCHORED_ELSEWHERE.has(blockName(el, ctx)))
|
|
@@ -1068,6 +1279,12 @@ function convertBlockContent(el, ctx) {
|
|
|
1068
1279
|
ctx.note("@outputclass", `db-details on <${name}> has no leading <p outputclass="db-title"> with text — titled "Details"`);
|
|
1069
1280
|
return [toDetails(el, ctx, component.classes, title, new Set(titleP ? [titleP] : []), titleP?.attribs?.id)];
|
|
1070
1281
|
}
|
|
1282
|
+
else if (component?.name === "db-grid" && ctx.inTableCell) {
|
|
1283
|
+
ctx.note("@outputclass", `db-grid inside a table cell — kept as its content`);
|
|
1284
|
+
}
|
|
1285
|
+
else if (component?.name === "db-grid") {
|
|
1286
|
+
return [toGrid(el, ctx, component.classes)];
|
|
1287
|
+
}
|
|
1071
1288
|
}
|
|
1072
1289
|
if (TRANSPARENT_CONTAINERS.has(name)) {
|
|
1073
1290
|
// Publishing: a topic body starts with the topic's "Prerequisites" links, when it has any
|
|
@@ -1083,6 +1300,13 @@ function convertBlockContent(el, ctx) {
|
|
|
1083
1300
|
switch (name) {
|
|
1084
1301
|
case "p":
|
|
1085
1302
|
case "shortdesc": {
|
|
1303
|
+
// A link card, button or video: an xref component alone in its paragraph
|
|
1304
|
+
const xc = name === "p" ? xrefComponent(el, ctx) : undefined;
|
|
1305
|
+
if (xc) {
|
|
1306
|
+
// Publishing: the xref's own id (a link target) as an anchor before the component
|
|
1307
|
+
const anchors = anchorNodes([el.children.find((c) => isElement(c) && c.name.toLowerCase() === "xref")?.attribs?.id], ctx);
|
|
1308
|
+
return anchors.length ? [{ type: "paragraph", inline: anchors }, xc] : [xc];
|
|
1309
|
+
}
|
|
1086
1310
|
// DITA allows blocks (ul, note, pre, …) inside <p>: leading inline
|
|
1087
1311
|
// becomes the paragraph, block children follow as siblings
|
|
1088
1312
|
const { inline, children } = mixedContent(el, ctx);
|
|
@@ -1134,16 +1358,35 @@ function convertBlockContent(el, ctx) {
|
|
|
1134
1358
|
};
|
|
1135
1359
|
return [withProvenance(node, el)];
|
|
1136
1360
|
}
|
|
1137
|
-
case "ul":
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1361
|
+
case "ul": {
|
|
1362
|
+
const list = withProvenance({ type: "unordered-list", children: convertListItems(el, ctx, "li") }, el);
|
|
1363
|
+
// A file tree: folders are items with a nested list, or end in "/"
|
|
1364
|
+
if (dbComponent(el, ctx)?.name === "db-files") {
|
|
1365
|
+
if (!ctx.inTableCell)
|
|
1366
|
+
return [{ type: "files", children: [list] }];
|
|
1367
|
+
ctx.note("@outputclass", `db-files inside a table cell — kept as a list`);
|
|
1368
|
+
}
|
|
1369
|
+
return [list];
|
|
1370
|
+
}
|
|
1371
|
+
case "ol": {
|
|
1372
|
+
const items = convertListItems(el, ctx, "li");
|
|
1373
|
+
// Steps outside a task: each item a numbered, connected step
|
|
1374
|
+
if (dbComponent(el, ctx)?.name === "db-steps") {
|
|
1375
|
+
if (!ctx.inTableCell) {
|
|
1376
|
+
// An item stays itself (its id, its provenance) as a step
|
|
1377
|
+
const steps = items.map((it) => ({ ...it, type: "step" }));
|
|
1378
|
+
return [withProvenance({ type: "steps", children: steps }, el)];
|
|
1379
|
+
}
|
|
1380
|
+
ctx.note("@outputclass", `db-steps inside a table cell — kept as a numbered list`);
|
|
1381
|
+
}
|
|
1382
|
+
return [withProvenance({ type: "ordered-list", children: items }, el)];
|
|
1383
|
+
}
|
|
1141
1384
|
case "sl": {
|
|
1142
1385
|
// Simple list → unordered list of <sli> items (same conref hooks
|
|
1143
1386
|
// as <li>: referencing items include or ledger, defining items
|
|
1144
1387
|
// hand their text to the snippet)
|
|
1145
1388
|
const items = el.children
|
|
1146
|
-
.filter((c) =>
|
|
1389
|
+
.filter((c) => isPart(c, ctx, "sli"))
|
|
1147
1390
|
.map((sli) => {
|
|
1148
1391
|
const viaConref = itemConref(sli, ctx, "list-item") ?? definingItemNode(sli, ctx, "list-item");
|
|
1149
1392
|
if (viaConref)
|
|
@@ -1165,7 +1408,9 @@ function convertBlockContent(el, ctx) {
|
|
|
1165
1408
|
}[component.name];
|
|
1166
1409
|
const children = build(el, ctx);
|
|
1167
1410
|
if (children) {
|
|
1168
|
-
const
|
|
1411
|
+
const q = qualify(component.name, component.classes, ctx);
|
|
1412
|
+
const props = { ...q.props, ...(q.classes ? { class: q.classes } : {}) };
|
|
1413
|
+
const group = withProvenance({ type, ...(Object.keys(props).length ? { props } : {}), children }, el);
|
|
1169
1414
|
return anchors.length ? [{ type: "paragraph", inline: anchors }, group] : [group];
|
|
1170
1415
|
}
|
|
1171
1416
|
ctx.note("@outputclass", `${component.name} on a <dl> with no usable entry — kept as a definition list`);
|
|
@@ -1177,9 +1422,17 @@ function convertBlockContent(el, ctx) {
|
|
|
1177
1422
|
return [withProvenance(convertDefList(el, ctx, { entry: "plentry", term: "pt", def: "pd" }), el)];
|
|
1178
1423
|
case "table":
|
|
1179
1424
|
case "simpletable":
|
|
1180
|
-
|
|
1181
|
-
|
|
1425
|
+
case "properties":
|
|
1426
|
+
// A properties table none of whose properties has a cell has no columns: DITA-OT drops it
|
|
1427
|
+
if (isReference(el, "properties") && propertiesColumns(el).propertyRows.length === 0) {
|
|
1428
|
+
if (!ctx.publish) {
|
|
1429
|
+
for (const row of elementChildren(el).filter((r) => r.attribs?.conref || r.attribs?.conkeyref)) {
|
|
1430
|
+
const ref = row.attribs.conref ?? row.attribs.conkeyref;
|
|
1431
|
+
ctx.note(row.attribs.conref ? "@conref" : "@conkeyref", `<${row.name.toLowerCase()}> pulls content from "${ref}" — ${conrefLedgerDetail(row.attribs, undefined, ctx.conref !== undefined)}`);
|
|
1432
|
+
}
|
|
1433
|
+
}
|
|
1182
1434
|
return [];
|
|
1435
|
+
}
|
|
1183
1436
|
return [withProvenance(convertTable(el, ctx), el)];
|
|
1184
1437
|
case "syntaxdiagram":
|
|
1185
1438
|
if (ctx.publish)
|
|
@@ -1414,4 +1667,3 @@ skip = new Set()) {
|
|
|
1414
1667
|
flushInline();
|
|
1415
1668
|
return out;
|
|
1416
1669
|
}
|
|
1417
|
-
//# sourceMappingURL=blocks.js.map
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { AnyNode } 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[]): string[];
|
|
@@ -0,0 +1,40 @@
|
|
|
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) {
|
|
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)
|
|
29
|
+
unknown.add(el.name);
|
|
30
|
+
}
|
|
31
|
+
const foreign = inForeign || ` ${el.attribs?.class ?? ""} `.includes(" topic/foreign ");
|
|
32
|
+
for (const child of el.children)
|
|
33
|
+
if (isTag(child))
|
|
34
|
+
visit(child, foreign);
|
|
35
|
+
};
|
|
36
|
+
for (const node of nodes)
|
|
37
|
+
if (isTag(node))
|
|
38
|
+
visit(node, false);
|
|
39
|
+
return [...unknown];
|
|
40
|
+
}
|
|
@@ -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>>;
|