npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@dogsbay/format-fluidtopics-rest

v0.2.0-beta.92

Published

Fluid Topics REST (khub) importer for Dogsbay — reverse-engineers a live FT portal's DITA-OT HTML5 into TreeNode[] / ExportPage[]

Readme

@dogsbay/format-fluidtopics-rest

Importer for a live Fluid Topics portal via the public khub REST API (Option B of the FT→Dogsbay migration). It reverse-engineers each topic's DITA-OT HTML5 — where the DITA element vocabulary survives in class names (conbody/taskbody/refbody, shortdesc, section, CALS tables, span.ph, …) — into Dogsbay's universal TreeNode model, producing ExportPage[] + NavItem[].

Works on any public FT portal. Gated portals (RBAC) throw KhubAuthError.

The sibling @dogsbay/format-fluidtopics-markdown does the same job from a Git Markdown export (Option A).

Usage

import { importFluidTopicsRest } from "@dogsbay/format-fluidtopics-rest";

const { pages, nav } = await importFluidTopicsRest({
  portalBase: "https://www.servicenow.com/docs", // or .../bas, docs.fluidtopics.com
  titleFilter: "Customer Relationship Management", // or maps: ["<mapId>"]
  hrefPrefix: "/docs",
});

Or the low-level converter / client:

import { htmlToTree, KhubClient } from "@dogsbay/format-fluidtopics-rest";
const { tree, title, topicType } = htmlToTree(htmlString); // topicType: concept|task|reference|topic

CLI: dogsbay migrate-fluidtopics-rest <portal-url> [--map <id>] [--title-filter <s>] [--single-page] [-o <dir>].

Single-page (whole-book) mode

Pass --single-page / singlePage: true to roll each map into one page (the whole book) instead of one page per topic — for readers who prefer a single long page over "bitty" topics, and to match FT portals that serve a book as one page. TOC nodes become nested headings (level = TOC depth), internal xrefs become in-page anchors, and the page lands at the book's common path prefix (e.g. …/metasys-ui-and-jct-technical-bulletin/16.0).

What it does

  • khub harvestmapsmaps/{id}/tocmaps/{id}/topics/{cid}/content; path-scoped bases (…/bas/api/khub); polite throttling; 401/403 → KhubAuthError.
  • HTML5 → TreeNode — topic type from the body class; DITA sections flattened to headings; CALS tables → structured table nodes; span.ph/keyword/uicontrol unwrapped, codeph → inline code; FT chrome (zDocs*, ai-summary, sentence, css-…, toggle/summary/tooltip) stripped.
  • Frontmattertopic_typetype, plus lang/version from the map metadata.
  • Nav — from each map's TOC (the authoritative DITA map), with route slugs derived from prettyUrl.

Rendering fidelity

Tuned against the live FT portals; each item is regression-tested. Full story in docs-dev/fluidtopics-rest-importer.md.

  • Internal xrefs — FT renders them as hrefless <span data-tocid data-mapid> (resolved by its client at runtime, zero hrefs in the static HTML). The importer builds a tocId → slug index from the selected maps' TOCs and resolves them to real routes, falling back to plain text (not a dead link) when out of set.
  • Figures / inline images — block <img> survive; base64 data: images are extracted to real content/_assets/… files (filename from FT metadata).
  • Lists & inline runs — consecutive inline content is coalesced into one paragraph, so xrefs inside list items resolve and prose doesn't fragment.
  • Tables — CALS → structured tables; cells with block content (lists, paragraphs) are preserved (HTML tables per the Dogsbay-MD convention).
  • Definition lists<dl>/<dt>/<dd> → a real deflist (dt.inline term + dd block children), not literal : text.

Verified (live, 2026-06)

ServiceNow www.servicenow.com/docs (CRM, 24 topics), Johnson Controls docs.johnsoncontrols.com/bas (Metasys bulletin, 55), Fluid Topics docs.fluidtopics.com (13). Notably, REST succeeds on ServiceNow's CRM publication where the Markdown export (Option A) failed (its index.md TOC was stale: 1/24 targets existed) — the live khub TOC+content is authoritative.

Known gaps

  • Nav-card landing grids come through as a generic table (Option A special-cases them into :::cards) — a nav-card-detection pass is future work.
  • Cross-map xrefs resolve only when the target map is in the import set (single---map runs leave them as text).
  • External image URLs are kept as-is (not downloaded); only inline data: images are localized to _assets.
  • conref/keyref/profiling were already resolved/flattened upstream by FT's DITA-OT run (not recoverable, and not needed for delivery).