@dogsbay/format-fluidtopics-rest 0.2.0-beta.92

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.
Files changed (54) hide show
  1. package/README.md +87 -0
  2. package/dist/assets.d.ts +13 -0
  3. package/dist/assets.d.ts.map +1 -0
  4. package/dist/assets.js +53 -0
  5. package/dist/assets.js.map +1 -0
  6. package/dist/cli.d.ts +9 -0
  7. package/dist/cli.d.ts.map +1 -0
  8. package/dist/cli.js +28 -0
  9. package/dist/cli.js.map +1 -0
  10. package/dist/frontmatter.d.ts +15 -0
  11. package/dist/frontmatter.d.ts.map +1 -0
  12. package/dist/frontmatter.js +24 -0
  13. package/dist/frontmatter.js.map +1 -0
  14. package/dist/headings.d.ts +13 -0
  15. package/dist/headings.d.ts.map +1 -0
  16. package/dist/headings.js +76 -0
  17. package/dist/headings.js.map +1 -0
  18. package/dist/html-to-tree.d.ts +11 -0
  19. package/dist/html-to-tree.d.ts.map +1 -0
  20. package/dist/html-to-tree.js +285 -0
  21. package/dist/html-to-tree.js.map +1 -0
  22. package/dist/importer.d.ts +44 -0
  23. package/dist/importer.d.ts.map +1 -0
  24. package/dist/importer.js +196 -0
  25. package/dist/importer.js.map +1 -0
  26. package/dist/index.d.ts +26 -0
  27. package/dist/index.d.ts.map +1 -0
  28. package/dist/index.js +9 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/inline-html.d.ts +52 -0
  31. package/dist/inline-html.d.ts.map +1 -0
  32. package/dist/inline-html.js +157 -0
  33. package/dist/inline-html.js.map +1 -0
  34. package/dist/khub.d.ts +59 -0
  35. package/dist/khub.d.ts.map +1 -0
  36. package/dist/khub.js +93 -0
  37. package/dist/khub.js.map +1 -0
  38. package/dist/links.d.ts +13 -0
  39. package/dist/links.d.ts.map +1 -0
  40. package/dist/links.js +55 -0
  41. package/dist/links.js.map +1 -0
  42. package/dist/nav.d.ts +7 -0
  43. package/dist/nav.d.ts.map +1 -0
  44. package/dist/nav.js +15 -0
  45. package/dist/nav.js.map +1 -0
  46. package/dist/single-page.d.ts +47 -0
  47. package/dist/single-page.d.ts.map +1 -0
  48. package/dist/single-page.js +77 -0
  49. package/dist/single-page.js.map +1 -0
  50. package/dist/tree.d.ts +2 -0
  51. package/dist/tree.d.ts.map +1 -0
  52. package/dist/tree.js +2 -0
  53. package/dist/tree.js.map +1 -0
  54. package/package.json +50 -0
@@ -0,0 +1,285 @@
1
+ /**
2
+ * Convert a DITA-OT **HTML5** topic (as served by FT's khub `…/content`
3
+ * endpoint) into Dogsbay TreeNode[].
4
+ *
5
+ * DITA-OT's HTML5 transtype preserves the DITA element vocabulary in `class`
6
+ * names, so the conversion is deterministic:
7
+ * div.body.conbody|taskbody|refbody → topic type (concept/task/reference)
8
+ * p.shortdesc / p.p / p → paragraph
9
+ * section.section + h2.sectiontitle → flattened to heading + content
10
+ * table.table (CALS) → table/thead/tbody/tr/th/td
11
+ * ul/ol/li, dl/dt/dd, pre/codeblock, note → lists / deflists / code / callout
12
+ * span.ph etc. → inline (see inline-html.ts)
13
+ * FT chrome (zDocs*, ai-summary, toggle/summary/tooltip, css-…) is stripped.
14
+ */
15
+ import { load } from "cheerio";
16
+ import { inlineFromChildren, textContent } from "./inline-html.js";
17
+ const CHROME_CLASS = /\b(zDocs[\w-]*|ai-summary[\w-]*|summarize[\w-]*|summary-[\w-]*|toggle-[\w-]*|tooltip[\w-]*|disclaimer[\w-]*|sparkle[\w-]*|info-icon|info-tooltip[\w-]*|table--title-label|spacer)\b/;
18
+ const SKIP_TAGS = new Set(["script", "style", "svg", "button", "nav", "head", "noscript"]);
19
+ /** Block-level tags — a list item containing any of these is walked as blocks. */
20
+ const BLOCK_TAGS = new Set([
21
+ "p", "ul", "ol", "dl", "table", "pre", "div", "section", "figure", "fig", "blockquote",
22
+ "h1", "h2", "h3", "h4", "h5", "h6", "note",
23
+ ]);
24
+ export function htmlToTree(html, opts = {}) {
25
+ const $ = load(html);
26
+ const title = $("h1.topictitle1").first().text().trim() || $("h1").first().text().trim() || undefined;
27
+ const bodyEl = ($("div.body").get(0) ?? $("article").get(0) ?? $("main").get(0) ?? $("body").get(0));
28
+ const topicType = bodyTypeFrom(bodyEl);
29
+ const tree = bodyEl ? walkBlocks(bodyEl.children ?? [], opts) : [];
30
+ return { tree, title, topicType };
31
+ }
32
+ function bodyTypeFrom(el) {
33
+ const cls = el?.attribs?.class ?? "";
34
+ if (/\bconbody\b/.test(cls))
35
+ return "concept";
36
+ if (/\btaskbody\b/.test(cls))
37
+ return "task";
38
+ if (/\b(refbody|reference)\b/.test(cls))
39
+ return "reference";
40
+ if (/\bglossbody\b/.test(cls))
41
+ return "glossentry";
42
+ return "topic";
43
+ }
44
+ function isChrome(n) {
45
+ const name = (n.name ?? "").toLowerCase();
46
+ if (SKIP_TAGS.has(name))
47
+ return true;
48
+ const cls = n.attribs?.class ?? "";
49
+ if (name === "details" && /ai-summary/.test(cls))
50
+ return true;
51
+ if (CHROME_CLASS.test(cls))
52
+ return true;
53
+ return false;
54
+ }
55
+ /** An element is "inline" if it isn't a block tag or a heading. */
56
+ function isInline(name) {
57
+ return !BLOCK_TAGS.has(name) && !/^h[1-6]$/.test(name);
58
+ }
59
+ function walkBlocks(nodes, opts) {
60
+ const out = [];
61
+ // Accumulate consecutive inline-level children (text, spans, xref spans,
62
+ // <a>, <img>, emphasis…) and flush them as ONE paragraph via the inline
63
+ // walker — so a mixed-content block (e.g. an <li> with "Updated the <xref>
64
+ // section:" followed by a nested <ul>) keeps its prose together and its
65
+ // xref spans resolve to links, instead of fragmenting into one-word paragraphs.
66
+ let buf = [];
67
+ const flush = () => {
68
+ if (buf.length === 0)
69
+ return;
70
+ const inline = inlineFromChildren(buf, opts);
71
+ buf = [];
72
+ if (inline.length)
73
+ out.push(paragraph(inline));
74
+ };
75
+ for (const n of nodes) {
76
+ if (n.type === "text") {
77
+ buf.push(n);
78
+ continue;
79
+ }
80
+ if (n.type !== "tag")
81
+ continue;
82
+ if (isChrome(n))
83
+ continue;
84
+ const name = (n.name ?? "").toLowerCase();
85
+ const cls = n.attribs?.class ?? "";
86
+ // Inline element (incl. <img>, xref spans) → accumulate into the run.
87
+ if (isInline(name)) {
88
+ buf.push(n);
89
+ continue;
90
+ }
91
+ // Block element → flush the pending inline run, then handle the block.
92
+ flush();
93
+ const hm = /^h([1-6])$/.exec(name);
94
+ if (hm) {
95
+ out.push({
96
+ type: "heading",
97
+ props: { level: Number(hm[1]) },
98
+ children: [{ type: "prose", inline: inlineFromChildren(n.children, opts) }],
99
+ });
100
+ continue;
101
+ }
102
+ switch (name) {
103
+ case "p": {
104
+ const inline = inlineFromChildren(n.children, opts);
105
+ if (inline.length)
106
+ out.push(paragraph(inline));
107
+ break;
108
+ }
109
+ case "section":
110
+ case "div": {
111
+ if (/\bnote\b/.test(cls)) {
112
+ out.push({
113
+ type: "callout",
114
+ props: { variant: noteVariant(cls) },
115
+ children: walkBlocks(n.children ?? [], opts),
116
+ });
117
+ }
118
+ else {
119
+ // section.section, div.p wrapper, fig wrapper, generic div → unwrap
120
+ out.push(...walkBlocks(n.children ?? [], opts));
121
+ }
122
+ break;
123
+ }
124
+ case "ul":
125
+ case "ol": {
126
+ const items = (n.children ?? [])
127
+ .filter((c) => c.type === "tag" && (c.name ?? "").toLowerCase() === "li")
128
+ .map((li) => {
129
+ // Inline-only <li> → one tight prose item; <li> with block children
130
+ // (e.g. a nested list) → walk as blocks (inline runs coalesce there too).
131
+ const hasBlock = (li.children ?? []).some((c) => c.type === "tag" && BLOCK_TAGS.has((c.name ?? "").toLowerCase()));
132
+ const children = hasBlock
133
+ ? walkBlocks(li.children ?? [], opts)
134
+ : [{ type: "prose", inline: inlineFromChildren(li.children, opts) }];
135
+ return { type: "list-item", children };
136
+ });
137
+ out.push({ type: name === "ol" ? "ordered-list" : "unordered-list", children: items });
138
+ break;
139
+ }
140
+ case "dl": {
141
+ const children = [];
142
+ for (const c of n.children ?? []) {
143
+ const cn = (c.name ?? "").toLowerCase();
144
+ // Canonical dt shape is inline-on-the-node (matches the parser +
145
+ // renderDeflist, which reads dt.inline); dd carries block children.
146
+ if (cn === "dt")
147
+ children.push({ type: "dt", inline: inlineFromChildren(c.children, opts) });
148
+ else if (cn === "dd")
149
+ children.push({ type: "dd", children: walkBlocks(c.children ?? [], opts) });
150
+ }
151
+ out.push({ type: "deflist", children });
152
+ break;
153
+ }
154
+ case "pre": {
155
+ out.push({ type: "code", props: { code: rawText(n), lang: langFrom(cls) } });
156
+ break;
157
+ }
158
+ case "table": {
159
+ out.push(convertTable(n, opts));
160
+ break;
161
+ }
162
+ case "figure":
163
+ case "fig":
164
+ default:
165
+ out.push(...walkBlocks(n.children ?? [], opts));
166
+ }
167
+ }
168
+ flush();
169
+ return out;
170
+ }
171
+ function convertTable(t, opts) {
172
+ const caption = findFirst(t, "caption");
173
+ const children = [];
174
+ const section = (name) => {
175
+ const sec = findFirst(t, name);
176
+ if (!sec)
177
+ return null;
178
+ const rows = childrenNamed(sec, "tr").map((tr) => ({
179
+ type: "tr",
180
+ children: childrenNamed(tr, name === "thead" ? "th" : "td", true).map((cell) => {
181
+ const node = {
182
+ type: name === "thead" ? "th" : "td",
183
+ // Cells can hold block content (lists, multiple paragraphs) — walk as
184
+ // blocks when present so structure survives; else a single prose run.
185
+ children: cellChildren(cell, opts),
186
+ };
187
+ // Carry CALS spans (DITA-OT emits them as HTML colspan/rowspan) so the
188
+ // serializer can emit a spanning HTML table — otherwise every cell
189
+ // below a row-spanned cell shifts into the wrong column.
190
+ const spans = cellSpans(cell);
191
+ if (spans)
192
+ node.props = spans;
193
+ return node;
194
+ }),
195
+ }));
196
+ return rows.length ? { type: name, children: rows } : null;
197
+ };
198
+ const thead = section("thead");
199
+ const tbody = section("tbody");
200
+ if (thead)
201
+ children.push(thead);
202
+ if (tbody)
203
+ children.push(tbody);
204
+ const node = { type: "table", children };
205
+ if (caption) {
206
+ const cap = textContent(caption);
207
+ if (cap)
208
+ node.props = { caption: cap };
209
+ }
210
+ return node;
211
+ }
212
+ // ── helpers ─────────────────────────────────────────────
213
+ /** Read a cell's colspan/rowspan into TreeNode props (only when > 1). */
214
+ function cellSpans(cell) {
215
+ const cs = parseInt(cell.attribs?.colspan ?? "", 10);
216
+ const rs = parseInt(cell.attribs?.rowspan ?? "", 10);
217
+ const props = {};
218
+ if (Number.isFinite(cs) && cs > 1)
219
+ props.colspan = cs;
220
+ if (Number.isFinite(rs) && rs > 1)
221
+ props.rowspan = rs;
222
+ return Object.keys(props).length ? props : undefined;
223
+ }
224
+ /** Cell content: block-walk when it has block children (lists, paragraphs), else inline. */
225
+ function cellChildren(cell, opts) {
226
+ const hasBlock = (cell.children ?? []).some((c) => c.type === "tag" && BLOCK_TAGS.has((c.name ?? "").toLowerCase()));
227
+ return hasBlock
228
+ ? walkBlocks(cell.children ?? [], opts)
229
+ : [{ type: "prose", inline: inlineFromChildren(cell.children, opts) }];
230
+ }
231
+ function paragraph(inline) {
232
+ return { type: "paragraph", children: [{ type: "prose", inline }] };
233
+ }
234
+ function noteVariant(cls) {
235
+ const m = /\bnote_(\w+)\b/.exec(cls) || /\b(warning|caution|danger|tip|important|note)\b/.exec(cls);
236
+ return m ? (m[1] === "note" ? "note" : m[1]) : "note";
237
+ }
238
+ function langFrom(cls) {
239
+ const m = /\blanguage-([\w+-]+)\b/.exec(cls);
240
+ return m ? m[1] : undefined;
241
+ }
242
+ /** Raw text (no whitespace collapse) — for code blocks. */
243
+ function rawText(n) {
244
+ let s = "";
245
+ const rec = (nodes) => {
246
+ for (const c of nodes) {
247
+ if (c.type === "text")
248
+ s += c.data ?? "";
249
+ else if (c.children)
250
+ rec(c.children);
251
+ }
252
+ };
253
+ rec(n.children ?? []);
254
+ return s.replace(/^\n+|\s+$/g, "");
255
+ }
256
+ /** First descendant element with the given tag name. */
257
+ function findFirst(n, name) {
258
+ for (const c of n.children ?? []) {
259
+ if (c.type === "tag") {
260
+ if ((c.name ?? "").toLowerCase() === name)
261
+ return c;
262
+ const deep = findFirst(c, name);
263
+ if (deep)
264
+ return deep;
265
+ }
266
+ }
267
+ return undefined;
268
+ }
269
+ /** Direct (or near) child elements with the given tag name. `deep` searches descendants. */
270
+ function childrenNamed(n, name, deep = false) {
271
+ const out = [];
272
+ const scan = (nodes) => {
273
+ for (const c of nodes) {
274
+ if (c.type !== "tag")
275
+ continue;
276
+ if ((c.name ?? "").toLowerCase() === name)
277
+ out.push(c);
278
+ else if (deep && c.children)
279
+ scan(c.children);
280
+ }
281
+ };
282
+ scan(n.children ?? []);
283
+ return out;
284
+ }
285
+ //# sourceMappingURL=html-to-tree.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"html-to-tree.js","sourceRoot":"","sources":["../src/html-to-tree.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Fluid Topics REST importer.
3
+ *
4
+ * Harvests a live FT portal via the khub API and reverse-engineers each topic's
5
+ * DITA-OT HTML5 into Dogsbay TreeNode[] — producing ExportPage[] + NavItem[].
6
+ * Works on any *public* FT portal (ServiceNow, Johnson Controls /bas, FT's own
7
+ * docs); gated portals throw KhubAuthError.
8
+ */
9
+ import type { ExportPage, NavItem } from "@dogsbay/types";
10
+ import { KhubClient } from "./khub.js";
11
+ export interface RestImportOptions {
12
+ /** Portal root or `…/api/khub` URL (ignored if `client` is given). */
13
+ portalBase?: string;
14
+ /** Inject a client (tests). */
15
+ client?: KhubClient;
16
+ /** Limit to these map ids; else import every map the portal lists. */
17
+ maps?: string[];
18
+ /** Filter listed maps by case-insensitive title substring. */
19
+ titleFilter?: string;
20
+ lang?: string;
21
+ hrefPrefix?: string;
22
+ throttleMs?: number;
23
+ fetchImpl?: typeof fetch;
24
+ taxonomyNames?: readonly string[];
25
+ onProgress?: (msg: string) => void;
26
+ /**
27
+ * Roll each map into ONE page (whole book) instead of one page per topic.
28
+ * TOC nodes become nested headings; internal xrefs become in-page anchors.
29
+ */
30
+ singlePage?: boolean;
31
+ }
32
+ export interface RestImportResult {
33
+ pages: ExportPage[];
34
+ nav: NavItem[];
35
+ unresolved: Record<string, string[]>;
36
+ mapsProcessed: number;
37
+ /** Extracted `data:` images, as content-relative paths + bytes to write. */
38
+ assets: {
39
+ path: string;
40
+ data: Buffer;
41
+ }[];
42
+ }
43
+ export declare function importFluidTopicsRest(opts: RestImportOptions): Promise<RestImportResult>;
44
+ //# sourceMappingURL=importer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"importer.d.ts","sourceRoot":"","sources":["../src/importer.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAE1D,OAAO,EAAE,UAAU,EAA0C,MAAM,WAAW,CAAC;AAU/E,MAAM,WAAW,iBAAiB;IAChC,sEAAsE;IACtE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,+BAA+B;IAC/B,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,sEAAsE;IACtE,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,8DAA8D;IAC9D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,aAAa,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,GAAG,EAAE,OAAO,EAAE,CAAC;IACf,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACrC,aAAa,EAAE,MAAM,CAAC;IACtB,4EAA4E;IAC5E,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC1C;AAED,wBAAsB,qBAAqB,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAsL9F"}
@@ -0,0 +1,196 @@
1
+ import { parseMeta } from "@dogsbay/types";
2
+ import { KhubClient, KhubAuthError, tocTopics } from "./khub.js";
3
+ import { htmlToTree } from "./html-to-tree.js";
4
+ import { resolveHref, slugFromPrettyUrl, routeFromSlug } from "./links.js";
5
+ import { buildFrontmatter } from "./frontmatter.js";
6
+ import { tocToNav } from "./nav.js";
7
+ import { extractHeadings } from "./headings.js";
8
+ import { parseDataUri, assetPath } from "./assets.js";
9
+ import { buildBookAnchors, bookHeading, shiftHeadings, bookSlugFrom, bookNavItem } from "./single-page.js";
10
+ export async function importFluidTopicsRest(opts) {
11
+ const client = opts.client ??
12
+ new KhubClient(opts.portalBase ?? "", { fetchImpl: opts.fetchImpl, throttleMs: opts.throttleMs });
13
+ const hrefPrefix = opts.hrefPrefix ?? "/docs";
14
+ const log = opts.onProgress ?? (() => { });
15
+ // Map inventory (titles + metadata). Tolerate a portal that 401s the list.
16
+ const listed = await client.listMaps(opts.lang).catch((e) => {
17
+ if (e instanceof KhubAuthError)
18
+ throw e;
19
+ return [];
20
+ });
21
+ const idToMap = new Map(listed.map((m) => [m.id, m]));
22
+ let ids = opts.maps?.length ? opts.maps : listed.map((m) => m.id);
23
+ if (!opts.maps?.length && opts.titleFilter) {
24
+ const needle = opts.titleFilter.toLowerCase();
25
+ ids = listed.filter((m) => (m.title ?? "").toLowerCase().includes(needle)).map((m) => m.id);
26
+ }
27
+ // For requested ids not present in the listing, fetch metadata directly.
28
+ for (const id of ids) {
29
+ if (!idToMap.has(id)) {
30
+ const m = (await client.getMap(id));
31
+ idToMap.set(id, { id, title: m.title ?? id, metadata: m.metadata });
32
+ }
33
+ }
34
+ // Pre-pass: fetch every selected map's TOC once, and build a tocId → slug
35
+ // index so internal xrefs (hrefless <a data-tocid data-mapid>) can resolve.
36
+ // In single-page mode we additionally pre-compute each book's route + per-node
37
+ // anchors, so xrefs (which may point forward) resolve to `<book>#<anchor>`.
38
+ const tocs = new Map();
39
+ const tocIdToSlug = new Map();
40
+ const bookAnchors = new Map();
41
+ const bookRoutes = new Map();
42
+ const anchorIndex = new Map(); // key: tocId and `${mapId}:${tocId}`
43
+ for (const id of ids) {
44
+ const toc = await client.getToc(id);
45
+ tocs.set(id, toc);
46
+ const walk = (ns) => {
47
+ for (const n of ns) {
48
+ if (n.tocId && n.prettyUrl) {
49
+ const slug = slugFromPrettyUrl(n.prettyUrl);
50
+ if (slug) {
51
+ tocIdToSlug.set(`${id}:${n.tocId}`, slug);
52
+ if (!tocIdToSlug.has(n.tocId))
53
+ tocIdToSlug.set(n.tocId, slug);
54
+ }
55
+ }
56
+ if (n.children?.length)
57
+ walk(n.children);
58
+ }
59
+ };
60
+ walk(toc);
61
+ if (opts.singlePage) {
62
+ const anchors = buildBookAnchors(toc);
63
+ bookAnchors.set(id, anchors);
64
+ const topicSlugs = tocTopics(toc).map((t) => slugFromPrettyUrl(t.prettyUrl)).filter(Boolean);
65
+ const route = routeFromSlug(bookSlugFrom(topicSlugs, idToMap.get(id)?.title ?? id), hrefPrefix);
66
+ bookRoutes.set(id, route);
67
+ for (const [tocId, anchor] of anchors.byTocId) {
68
+ anchorIndex.set(`${id}:${tocId}`, { anchor, route });
69
+ if (!anchorIndex.has(tocId))
70
+ anchorIndex.set(tocId, { anchor, route });
71
+ }
72
+ }
73
+ }
74
+ const resolveTocId = (tocId, mapId) => {
75
+ if (opts.singlePage) {
76
+ const hit = (mapId ? anchorIndex.get(`${mapId}:${tocId}`) : undefined) ?? anchorIndex.get(tocId);
77
+ return hit ? `${hit.route}#${hit.anchor}` : undefined;
78
+ }
79
+ const slug = (mapId ? tocIdToSlug.get(`${mapId}:${tocId}`) : undefined) ?? tocIdToSlug.get(tocId);
80
+ return slug !== undefined ? routeFromSlug(slug, hrefPrefix) : undefined;
81
+ };
82
+ // Extract inline `data:` images to real `_assets` files (deduped by path).
83
+ const assetBytes = new Map();
84
+ const onImage = (img) => {
85
+ if (!img.src.startsWith("data:"))
86
+ return img.src;
87
+ const parsed = parseDataUri(img.src);
88
+ if (!parsed)
89
+ return img.src;
90
+ const path = assetPath(img.resourceId, img.displayName, parsed);
91
+ if (!assetBytes.has(path))
92
+ assetBytes.set(path, parsed.data);
93
+ return `/${path}`;
94
+ };
95
+ const pages = [];
96
+ const nav = [];
97
+ const unresolved = {};
98
+ const seen = new Set();
99
+ let mapsProcessed = 0;
100
+ for (const id of ids) {
101
+ const mapInfo = idToMap.get(id);
102
+ const toc = tocs.get(id);
103
+ const topics = tocTopics(toc);
104
+ log(`map ${mapInfo?.title ?? id}: ${topics.length} topics`);
105
+ // ── single-page (whole book) ───────────────────────────
106
+ if (opts.singlePage) {
107
+ const { ordered } = bookAnchors.get(id);
108
+ const route = bookRoutes.get(id);
109
+ const bookSlug = route.startsWith(hrefPrefix) ? route.slice(hrefPrefix.length).replace(/^\//, "") : route.replace(/^\//, "");
110
+ const combined = [];
111
+ const local = [];
112
+ for (const entry of ordered) {
113
+ const t = entry.node;
114
+ combined.push(bookHeading(entry.level, t.title || labelFromSlug(entry.anchor), entry.anchor));
115
+ if (!t.contentId)
116
+ continue;
117
+ let html;
118
+ try {
119
+ html = await client.getTopicContent(id, t.contentId);
120
+ }
121
+ catch (e) {
122
+ if (e instanceof KhubAuthError)
123
+ throw e;
124
+ log(` ! skip ${entry.anchor}: ${e.message}`);
125
+ continue;
126
+ }
127
+ const fromSlug = slugFromPrettyUrl(t.prettyUrl) || bookSlug;
128
+ const { tree } = htmlToTree(html, {
129
+ resolveHref: (h) => {
130
+ const r = resolveHref(h, fromSlug, hrefPrefix);
131
+ if (!r.resolved && h)
132
+ local.push(h);
133
+ return r.href;
134
+ },
135
+ resolveTocId,
136
+ onImage,
137
+ });
138
+ shiftHeadings(tree, entry.level - 1);
139
+ combined.push(...tree);
140
+ }
141
+ const title = mapInfo?.title ?? id;
142
+ const frontmatter = buildFrontmatter({ title, topicType: "topic", mapMeta: mapInfo?.metadata });
143
+ const headings = extractHeadings(combined);
144
+ const meta = parseMeta(frontmatter, { slug: bookSlug, taxonomyNames: opts.taxonomyNames });
145
+ pages.push({ slug: bookSlug, title, tree: combined, headings, frontmatter, meta });
146
+ if (local.length)
147
+ unresolved[bookSlug] = local;
148
+ nav.push(bookNavItem(title, route));
149
+ mapsProcessed++;
150
+ continue;
151
+ }
152
+ // ── per-topic (default) ────────────────────────────────
153
+ for (const t of topics) {
154
+ const slug = slugFromPrettyUrl(t.prettyUrl) || `topic/${(t.contentId ?? "").toLowerCase()}`;
155
+ if (seen.has(slug))
156
+ continue;
157
+ seen.add(slug);
158
+ let html;
159
+ try {
160
+ html = await client.getTopicContent(id, t.contentId);
161
+ }
162
+ catch (e) {
163
+ if (e instanceof KhubAuthError)
164
+ throw e; // gated portal — abort
165
+ log(` ! skip ${slug}: ${e.message}`);
166
+ continue;
167
+ }
168
+ const local = [];
169
+ const { tree, title, topicType } = htmlToTree(html, {
170
+ resolveHref: (h) => {
171
+ const r = resolveHref(h, slug, hrefPrefix);
172
+ if (!r.resolved && h)
173
+ local.push(h);
174
+ return r.href;
175
+ },
176
+ resolveTocId,
177
+ onImage,
178
+ });
179
+ const finalTitle = title || t.title || labelFromSlug(slug);
180
+ const frontmatter = buildFrontmatter({ title: finalTitle, topicType, mapMeta: mapInfo?.metadata });
181
+ const headings = extractHeadings(tree);
182
+ const meta = parseMeta(frontmatter, { slug, taxonomyNames: opts.taxonomyNames });
183
+ pages.push({ slug, title: finalTitle, tree, headings, frontmatter, meta });
184
+ if (local.length)
185
+ unresolved[slug] = local;
186
+ }
187
+ nav.push({ label: mapInfo?.title ?? id, children: tocToNav(toc, hrefPrefix) });
188
+ mapsProcessed++;
189
+ }
190
+ const assets = [...assetBytes].map(([path, data]) => ({ path, data }));
191
+ return { pages, nav, unresolved, mapsProcessed, assets };
192
+ }
193
+ function labelFromSlug(slug) {
194
+ return (slug.split("/").pop() ?? slug).replace(/[-_]/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
195
+ }
196
+ //# sourceMappingURL=importer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"importer.js","sourceRoot":"","sources":["../src/importer.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,SAAS,EAAgB,MAAM,WAAW,CAAC;AAC/E,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3E,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AACpC,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,aAAa,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAkC3G,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,IAAuB;IACjE,MAAM,MAAM,GACV,IAAI,CAAC,MAAM;QACX,IAAI,UAAU,CAAC,IAAI,CAAC,UAAU,IAAI,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC;IACpG,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,IAAI,OAAO,CAAC;IAC9C,MAAM,GAAG,GAAG,IAAI,CAAC,UAAU,IAAI,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IAE1C,2EAA2E;IAC3E,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE;QAC1D,IAAI,CAAC,YAAY,aAAa;YAAE,MAAM,CAAC,CAAC;QACxC,OAAO,EAAe,CAAC;IACzB,CAAC,CAAC,CAAC;IACH,MAAM,OAAO,GAAG,IAAI,GAAG,CAAkB,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAEvE,IAAI,GAAG,GAAG,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAClE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;QAC3C,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,CAAC,WAAW,EAAE,CAAC;QAC9C,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAC9F,CAAC;IACD,yEAAyE;IACzE,KAAK,MAAM,EAAE,IAAI,GAAG,EAAE,CAAC;QACrB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;YACrB,MAAM,CAAC,GAAG,CAAC,MAAM,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAuB,CAAC;YAC1D,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,KAAK,EAAG,CAAwB,CAAC,KAAK,IAAI,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;QAC9F,CAAC;IACH,CAAC;IAED,0EAA0E;IAC1E,4EAA4E;IAC5E,+EAA+E;IAC/E,4EAA4E;IAC5E,MAAM,IAAI,GAAG,IAAI,GAAG,EAAqD,CAAC;IAC1E,MAAM,WAAW,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC9C,MAAM,WAAW,GAAG,IAAI,GAAG,EAA+C,CAAC;IAC3E,MAAM,UAAU,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC7C,MAAM,WAAW,GAAG,IAAI,GAAG,EAA6C,CAAC,CAAC,qCAAqC;IAC/G,KAAK,MAAM,EAAE,IAAI,GAAG,EAAE,CAAC;QACrB,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACpC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;QAClB,MAAM,IAAI,GAAG,CAAC,EAAc,EAAE,EAAE;YAC9B,KAAK,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC;gBACnB,IAAI,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,SAAS,EAAE,CAAC;oBAC3B,MAAM,IAAI,GAAG,iBAAiB,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;oBAC5C,IAAI,IAAI,EAAE,CAAC;wBACT,WAAW,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,IAAI,CAAC,CAAC;wBAC1C,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC;4BAAE,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;oBAChE,CAAC;gBACH,CAAC;gBACD,IAAI,CAAC,CAAC,QAAQ,EAAE,MAAM;oBAAE,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;YAC3C,CAAC;QACH,CAAC,CAAC;QACF,IAAI,CAAC,GAAG,CAAC,CAAC;QAEV,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACpB,MAAM,OAAO,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC;YACtC,WAAW,CAAC,GAAG,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;YAC7B,MAAM,UAAU,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YAC7F,MAAM,KAAK,GAAG,aAAa,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,KAAK,IAAI,EAAE,CAAC,EAAE,UAAU,CAAC,CAAC;YAChG,UAAU,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;YAC1B,KAAK,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;gBAC9C,WAAW,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;gBACrD,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC;oBAAE,WAAW,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;YACzE,CAAC;QACH,CAAC;IACH,CAAC;IACD,MAAM,YAAY,GAAG,CAAC,KAAa,EAAE,KAAc,EAAsB,EAAE;QACzE,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACpB,MAAM,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,KAAK,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YACjG,OAAO,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;QACxD,CAAC;QACD,MAAM,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,KAAK,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAClG,OAAO,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,aAAa,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC1E,CAAC,CAAC;IAEF,2EAA2E;IAC3E,MAAM,UAAU,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC7C,MAAM,OAAO,GAAG,CAAC,GAA+D,EAAU,EAAE;QAC1F,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC;YAAE,OAAO,GAAG,CAAC,GAAG,CAAC;QACjD,MAAM,MAAM,GAAG,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACrC,IAAI,CAAC,MAAM;YAAE,OAAO,GAAG,CAAC,GAAG,CAAC;QAC5B,MAAM,IAAI,GAAG,SAAS,CAAC,GAAG,CAAC,UAAU,EAAE,GAAG,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;QAChE,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,UAAU,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;QAC7D,OAAO,IAAI,IAAI,EAAE,CAAC;IACpB,CAAC,CAAC;IAEF,MAAM,KAAK,GAAiB,EAAE,CAAC;IAC/B,MAAM,GAAG,GAAc,EAAE,CAAC;IAC1B,MAAM,UAAU,GAA6B,EAAE,CAAC;IAChD,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,IAAI,aAAa,GAAG,CAAC,CAAC;IAEtB,KAAK,MAAM,EAAE,IAAI,GAAG,EAAE,CAAC;QACrB,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAE,CAAC;QAC1B,MAAM,MAAM,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;QAC9B,GAAG,CAAC,OAAO,OAAO,EAAE,KAAK,IAAI,EAAE,KAAK,MAAM,CAAC,MAAM,SAAS,CAAC,CAAC;QAE5D,0DAA0D;QAC1D,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACpB,MAAM,EAAE,OAAO,EAAE,GAAG,WAAW,CAAC,GAAG,CAAC,EAAE,CAAE,CAAC;YACzC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,CAAC,EAAE,CAAE,CAAC;YAClC,MAAM,QAAQ,GAAG,KAAK,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YAC7H,MAAM,QAAQ,GAAe,EAAE,CAAC;YAChC,MAAM,KAAK,GAAa,EAAE,CAAC;YAC3B,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;gBAC5B,MAAM,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC;gBACrB,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,IAAI,aAAa,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;gBAC9F,IAAI,CAAC,CAAC,CAAC,SAAS;oBAAE,SAAS;gBAC3B,IAAI,IAAY,CAAC;gBACjB,IAAI,CAAC;oBACH,IAAI,GAAG,MAAM,MAAM,CAAC,eAAe,CAAC,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC;gBACvD,CAAC;gBAAC,OAAO,CAAC,EAAE,CAAC;oBACX,IAAI,CAAC,YAAY,aAAa;wBAAE,MAAM,CAAC,CAAC;oBACxC,GAAG,CAAC,YAAY,KAAK,CAAC,MAAM,KAAM,CAAW,CAAC,OAAO,EAAE,CAAC,CAAC;oBACzD,SAAS;gBACX,CAAC;gBACD,MAAM,QAAQ,GAAG,iBAAiB,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,QAAQ,CAAC;gBAC5D,MAAM,EAAE,IAAI,EAAE,GAAG,UAAU,CAAC,IAAI,EAAE;oBAChC,WAAW,EAAE,CAAC,CAAC,EAAE,EAAE;wBACjB,MAAM,CAAC,GAAG,WAAW,CAAC,CAAC,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC;wBAC/C,IAAI,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC;4BAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;wBACpC,OAAO,CAAC,CAAC,IAAI,CAAC;oBAChB,CAAC;oBACD,YAAY;oBACZ,OAAO;iBACR,CAAC,CAAC;gBACH,aAAa,CAAC,IAAI,EAAE,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;gBACrC,QAAQ,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;YACzB,CAAC;YAED,MAAM,KAAK,GAAG,OAAO,EAAE,KAAK,IAAI,EAAE,CAAC;YACnC,MAAM,WAAW,GAAG,gBAAgB,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,CAAC;YAChG,MAAM,QAAQ,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;YAC3C,MAAM,IAAI,GAAG,SAAS,CAAC,WAAW,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,aAAa,EAAE,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC;YAC3F,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC;YACnF,IAAI,KAAK,CAAC,MAAM;gBAAE,UAAU,CAAC,QAAQ,CAAC,GAAG,KAAK,CAAC;YAC/C,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;YACpC,aAAa,EAAE,CAAC;YAChB,SAAS;QACX,CAAC;QAED,0DAA0D;QAC1D,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;YACvB,MAAM,IAAI,GAAG,iBAAiB,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,SAAS,CAAC,CAAC,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC;YAC5F,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;gBAAE,SAAS;YAC7B,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAEf,IAAI,IAAY,CAAC;YACjB,IAAI,CAAC;gBACH,IAAI,GAAG,MAAM,MAAM,CAAC,eAAe,CAAC,EAAE,EAAE,CAAC,CAAC,SAAU,CAAC,CAAC;YACxD,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,IAAI,CAAC,YAAY,aAAa;oBAAE,MAAM,CAAC,CAAC,CAAC,uBAAuB;gBAChE,GAAG,CAAC,YAAY,IAAI,KAAM,CAAW,CAAC,OAAO,EAAE,CAAC,CAAC;gBACjD,SAAS;YACX,CAAC;YAED,MAAM,KAAK,GAAa,EAAE,CAAC;YAC3B,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,UAAU,CAAC,IAAI,EAAE;gBAClD,WAAW,EAAE,CAAC,CAAC,EAAE,EAAE;oBACjB,MAAM,CAAC,GAAG,WAAW,CAAC,CAAC,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;oBAC3C,IAAI,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC;wBAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;oBACpC,OAAO,CAAC,CAAC,IAAI,CAAC;gBAChB,CAAC;gBACD,YAAY;gBACZ,OAAO;aACR,CAAC,CAAC;YAEH,MAAM,UAAU,GAAG,KAAK,IAAI,CAAC,CAAC,KAAK,IAAI,aAAa,CAAC,IAAI,CAAC,CAAC;YAC3D,MAAM,WAAW,GAAG,gBAAgB,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,CAAC;YACnG,MAAM,QAAQ,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;YACvC,MAAM,IAAI,GAAG,SAAS,CAAC,WAAW,EAAE,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC;YAEjF,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC;YAC3E,IAAI,KAAK,CAAC,MAAM;gBAAE,UAAU,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC;QAC7C,CAAC;QAED,GAAG,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,IAAI,EAAE,EAAE,QAAQ,EAAE,QAAQ,CAAC,GAAG,EAAE,UAAU,CAAC,EAAE,CAAC,CAAC;QAC/E,aAAa,EAAE,CAAC;IAClB,CAAC;IAED,MAAM,MAAM,GAAG,CAAC,GAAG,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IACvE,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,EAAE,CAAC;AAC3D,CAAC;AAED,SAAS,aAAa,CAAC,IAAY;IACjC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;AACxG,CAAC"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * @dogsbay/format-fluidtopics-rest
3
+ *
4
+ * Importer for a *live* Fluid Topics portal via the public khub REST API. It
5
+ * reverse-engineers each topic's DITA-OT HTML5 (where the DITA element
6
+ * vocabulary survives in `class` names) into the universal TreeNode model —
7
+ * producing ExportPage[] + NavItem[] for any public FT portal (ServiceNow,
8
+ * Johnson Controls, FT's own docs).
9
+ *
10
+ * The sibling `@dogsbay/format-fluidtopics-markdown` does the same job from a
11
+ * Git Markdown export (Option A); this is Option B (live REST / Option B of the
12
+ * A→B→C migration plan).
13
+ */
14
+ export type { TreeNode, ExportPage, NavItem, Heading } from "@dogsbay/types";
15
+ export { htmlToTree } from "./html-to-tree.js";
16
+ export type { HtmlToTreeResult } from "./html-to-tree.js";
17
+ export { KhubClient, KhubAuthError, normalizeKhubBase, tocTopics } from "./khub.js";
18
+ export type { KhubMap, KhubTocNode, KhubClientOptions } from "./khub.js";
19
+ export { importFluidTopicsRest } from "./importer.js";
20
+ export type { RestImportOptions, RestImportResult } from "./importer.js";
21
+ export { slugFromPrettyUrl, routeFromSlug, resolveHref } from "./links.js";
22
+ export { buildFrontmatter } from "./frontmatter.js";
23
+ export { tocToNav } from "./nav.js";
24
+ export { extractHeadings } from "./headings.js";
25
+ export { inlineFromChildren } from "./inline-html.js";
26
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,YAAY,EAAE,QAAQ,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAE7E,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,YAAY,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAE1D,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACpF,YAAY,EAAE,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAEzE,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AACtD,YAAY,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEzE,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC3E,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AACpC,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,9 @@
1
+ export { htmlToTree } from "./html-to-tree.js";
2
+ export { KhubClient, KhubAuthError, normalizeKhubBase, tocTopics } from "./khub.js";
3
+ export { importFluidTopicsRest } from "./importer.js";
4
+ export { slugFromPrettyUrl, routeFromSlug, resolveHref } from "./links.js";
5
+ export { buildFrontmatter } from "./frontmatter.js";
6
+ export { tocToNav } from "./nav.js";
7
+ export { extractHeadings } from "./headings.js";
8
+ export { inlineFromChildren } from "./inline-html.js";
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAeA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAG/C,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAGpF,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAGtD,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC3E,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AACpC,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC"}