@mintlify/cli 4.0.1762 → 4.0.1764

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 (49) hide show
  1. package/README.md +18 -0
  2. package/__test__/agent-setup-config.test.ts +314 -0
  3. package/__test__/agent-setup.test.ts +207 -0
  4. package/__test__/migrate.test.ts +186 -0
  5. package/__test__/validateRules.test.ts +36 -0
  6. package/bin/agent-setup-config.js +141 -0
  7. package/bin/agent-setup.js +146 -0
  8. package/bin/cli.js +65 -0
  9. package/bin/migrate.js +54 -0
  10. package/bin/tsconfig.build.tsbuildinfo +1 -1
  11. package/bin/validate/files.js +16 -4
  12. package/bin/validate/mdx.js +1 -1
  13. package/bin/welcome.js +1 -0
  14. package/migrate/index.md +56 -0
  15. package/migrate/sources/confluence.md +120 -0
  16. package/migrate/sources/docsify.md +128 -0
  17. package/migrate/sources/document360.md +117 -0
  18. package/migrate/sources/docus.md +136 -0
  19. package/migrate/sources/docusaurus.md +143 -0
  20. package/migrate/sources/fern.md +130 -0
  21. package/migrate/sources/fumadocs.md +141 -0
  22. package/migrate/sources/gitbook.md +120 -0
  23. package/migrate/sources/github-wiki.md +90 -0
  24. package/migrate/sources/jekyll.md +104 -0
  25. package/migrate/sources/mdbook.md +98 -0
  26. package/migrate/sources/mkdocs.md +113 -0
  27. package/migrate/sources/nextra.md +144 -0
  28. package/migrate/sources/notion.md +99 -0
  29. package/migrate/sources/nuxt.md +113 -0
  30. package/migrate/sources/pdf.md +99 -0
  31. package/migrate/sources/readme.md +118 -0
  32. package/migrate/sources/redocly.md +114 -0
  33. package/migrate/sources/starlight.md +136 -0
  34. package/migrate/sources/vitepress.md +143 -0
  35. package/migrate/sources/vuepress.md +153 -0
  36. package/migrate/topics/api.md +76 -0
  37. package/migrate/topics/changelog.md +47 -0
  38. package/migrate/topics/conversion.md +194 -0
  39. package/migrate/topics/discovery.md +93 -0
  40. package/migrate/topics/navigation.md +82 -0
  41. package/migrate/topics/verify.md +58 -0
  42. package/package.json +12 -10
  43. package/src/agent-setup-config.ts +144 -0
  44. package/src/agent-setup.ts +165 -0
  45. package/src/cli.tsx +91 -0
  46. package/src/migrate.ts +76 -0
  47. package/src/validate/files.ts +23 -3
  48. package/src/validate/mdx.ts +1 -1
  49. package/src/welcome.ts +1 -0
@@ -20,7 +20,7 @@ var __rest = (this && this.__rest) || function (s, e) {
20
20
  };
21
21
  import { getAST, getFileCategory, parseFrontmatter, replaceVariables } from '@mintlify/common';
22
22
  import { categorizeMdxFiles, getErrorPosition, getMintIgnore, listContentFiles, } from '@mintlify/prebuild';
23
- import { applyEdits, collectAnchorLinks, parseContent, relocate, selectEdits, unmapEdit, } from './mdx.js';
23
+ import { applyEdits, collectAnchorLinks, parseContent, relocate, selectEdits, toOffset, unmapEdit, } from './mdx.js';
24
24
  import { PARSE_ERROR } from './rules/parseError.js';
25
25
  const CHECKED_CATEGORIES = new Set(['page', 'snippet', 'snippet-v2']);
26
26
  export const readSiteFiles = (baseDir) => __awaiter(void 0, void 0, void 0, function* () {
@@ -44,12 +44,24 @@ const readFrontmatter = (content) => {
44
44
  }
45
45
  };
46
46
  const REASON_POSITION = /\s*\(\d+:\d+(?:-\d+:\d+)?\)$/;
47
- export const toParseError = (error) => {
47
+ const TAG_NAME_RULES = new Set(['unexpected-character', 'unexpected-eof']);
48
+ const ESCAPE_HINT = "; if this < isn't a tag, escape it as \\<";
49
+ const isStrayLessThan = (error, content, position) => {
50
+ const { source, ruleId } = (error !== null && error !== void 0 ? error : {});
51
+ return (source === 'micromark-extension-mdx-jsx' &&
52
+ typeof ruleId === 'string' &&
53
+ TAG_NAME_RULES.has(ruleId) &&
54
+ (position === null || position === void 0 ? void 0 : position.line) != null &&
55
+ position.column != null &&
56
+ content[toOffset(content, position.line, position.column) - 1] === '<');
57
+ };
58
+ export const toParseError = (error, content = '') => {
48
59
  const reason = error === null || error === void 0 ? void 0 : error.reason;
49
60
  const fallback = error instanceof Error ? error.message : 'could not parse this file';
50
61
  const text = typeof reason === 'string' ? reason : fallback;
51
62
  const position = error && typeof error === 'object' ? getErrorPosition(error) : null;
52
- return Object.assign(Object.assign(Object.assign({}, ((position === null || position === void 0 ? void 0 : position.line) != null && { line: position.line })), ((position === null || position === void 0 ? void 0 : position.column) != null && { column: position.column })), { message: text.replace(REASON_POSITION, '') });
63
+ const hint = isStrayLessThan(error, content, position) ? ESCAPE_HINT : '';
64
+ return Object.assign(Object.assign(Object.assign({}, ((position === null || position === void 0 ? void 0 : position.line) != null && { line: position.line })), ((position === null || position === void 0 ? void 0 : position.column) != null && { column: position.column })), { message: text.replace(REASON_POSITION, '') + hint });
53
65
  };
54
66
  const parseErrorDiagnostic = (file, error) => (Object.assign(Object.assign({}, error), { rule: PARSE_ERROR.id, group: PARSE_ERROR.group, severity: PARSE_ERROR.severity, file, message: `${error.message} (other checks were skipped for this file)` }));
55
67
  const tryParseContent = (content) => {
@@ -69,7 +81,7 @@ export const parseFile = (file, content, baseDir, extras = {}) => {
69
81
  return { context: Object.assign(Object.assign({}, context), { tree: getAST(content, file) }), approximate: true };
70
82
  }
71
83
  catch (error) {
72
- return { error: toParseError(error) };
84
+ return { error: toParseError(error, content) };
73
85
  }
74
86
  };
75
87
  const EMPTY_TREE = { type: 'root', children: [] };
@@ -153,7 +153,7 @@ export const selectEdits = (edits) => {
153
153
  return selected;
154
154
  };
155
155
  export const applyEdits = (content, edits) => selectEdits(edits).reduce((result, edit) => result.slice(0, edit.start) + edit.text + result.slice(edit.end), content);
156
- const toOffset = (content, line, column = 1) => {
156
+ export const toOffset = (content, line, column = 1) => {
157
157
  let offset = 0;
158
158
  for (let current = 1; current < line; current++) {
159
159
  const next = content.indexOf('\n', offset);
package/bin/welcome.js CHANGED
@@ -44,6 +44,7 @@ const GROUPS = [
44
44
  {
45
45
  title: 'CLI',
46
46
  commands: [
47
+ { name: 'agent setup', description: 'Install Mintlify skills and configure Admin MCP' },
47
48
  { name: 'config', description: 'Manage CLI configuration' },
48
49
  { name: 'update', description: 'Update to the latest version' },
49
50
  ],
@@ -0,0 +1,56 @@
1
+ # Migrate a docs site to Mintlify
2
+
3
+ Follow these instructions to move an existing documentation site into a Mintlify project in the current directory. The goal is reading parity: every page, every section and every URL from the source arrives in Mintlify, converted to MDX and wired into `docs.json`.
4
+
5
+ Read the Mintlify docs index at https://mintlify.com/docs/llms.txt before you start, and use it to look up the `docs.json` schema and components as you go.
6
+
7
+ ## Get the source
8
+
9
+ Work out what the user is migrating from and how you can reach it: the repo, an export, or the live site, in that order of preference. If the user has not said and it is not obvious from the current directory, ask them before doing anything else. Never modify the source; write the Mintlify project to a separate directory. Details: `mint migrate --topic discovery`.
10
+
11
+ If the platform has a source guide, print it with `mint migrate --from <name>` (the list is at the end of this page). Detection signals and platform specifics for each route are in its guide.
12
+
13
+ ## Workflow
14
+
15
+ 1. **Inventory.** Build a complete list of source pages before converting anything. Record each one in `migration-manifest.json` (see `mint migrate --topic discovery`).
16
+ 2. **Mirror**, live-site route only. Download the raw source for every page into `mirror/`, one file per page. A repo or export is already the source. Convert from files, never from memory.
17
+ 3. **Convert.** Turn every page into `.mdx` with source-backed frontmatter, Mintlify components and root-absolute links (`--topic conversion`). Past about 50 pages, write a transformer script and re-run it after every rule fix instead of hand-editing output.
18
+ 4. **docs.json.** Build navigation from the source's own navigation data, add redirects for every URL that moves, and carry over only the chrome the source actually shows (`--topic navigation`).
19
+ 5. **API reference**, only if the source has one (`--topic api`).
20
+ 6. **Changelog**, only if the source has one (`--topic changelog`).
21
+ 7. **Verify.** Run `mint validate` and `mint broken-links`, run the content sweeps, and reconcile the manifest (`--topic verify`).
22
+ 8. **Report** to the user (below).
23
+
24
+ ## Rules
25
+
26
+ - **Keep every page.** Nothing in the inventory is skipped silently. Each page ends as `done`, `excluded` (with a reason, such as a sitemap entry that 404s everywhere) or `blocked` (with a reason and a next step).
27
+ - **Never invent content.** Every word on every page comes from the source. Do not summarize, rewrite, pad or add introductions.
28
+ - **Never invent frontmatter.** `title`, `sidebarTitle`, `description` and `icon` all render visibly. Copy them from the source or leave them out.
29
+ - **Mirror the source navigation.** Same tabs, groups, order, labels and nesting depth. Do not reorganize unless the user asks.
30
+ - **Preserve URLs.** Keep source paths where possible. Every URL that changes gets a redirect (`mint migrate --topic navigation`, Redirects).
31
+ - **Use Mintlify components** where the source has a real equivalent (callouts, steps, tabs, cards, accordions, code groups, API fields). Leave ambiguous structure as plain markdown. Catalog: https://www.mintlify.com/docs/components/index.md
32
+ - **Download assets.** Images and files live in the repo, not hotlinked from the old site.
33
+ - **Never fix a finding by deleting content.** If a page will not parse, fix the conversion.
34
+ - **Report what you could not carry over.** Anything dropped, approximated or blocked goes in the final report.
35
+
36
+ ## Done means
37
+
38
+ - `mint validate` passes with no errors.
39
+ - `mint broken-links` reports nothing.
40
+ - Every manifest row is `done`, `excluded` or `blocked` (discovered = done + excluded + blocked), and every `blocked` row is in the report.
41
+ - Every `.mdx` file is in `docs.json` navigation and every navigation entry has a file.
42
+ - Every source URL resolves on the new site, directly or through a redirect.
43
+
44
+ Reference: https://www.mintlify.com/docs/cli/commands.md
45
+
46
+ ## Report
47
+
48
+ Finish with a short report to the user:
49
+
50
+ - Counts of manifest rows: discovered, done, excluded, blocked.
51
+ - Every excluded or blocked page with its reason.
52
+ - Everything dropped or approximated: custom components with no equivalent, interactive widgets, embeds, search or analytics config, versioning, localization, theme details. A custom-designed homepage or landing page (hero, bespoke layout) is converted as content and reported, not rebuilt with custom code.
53
+ - Redirects added.
54
+ - Anything that needs the user's input, such as an export for gated content or a decision about versions.
55
+
56
+ Delete `mirror/` and any transformer scripts only if the user asks; keep `migration-manifest.json` until they have reviewed the report.
@@ -0,0 +1,120 @@
1
+ # Confluence
2
+
3
+ Confluence Cloud and Data Center spaces. Content is usually behind login, so the customer exports the space and you work on the export locally. The old site stays on Confluence, so you produce a route table instead of redirects.
4
+
5
+ ## Detect
6
+
7
+ - Cloud URLs: `https://<site>.atlassian.net/wiki/spaces/<KEY>/pages/<pageId>/<Title>`; short links `/wiki/x/<code>`.
8
+ - Data Center URLs: `/display/<KEY>/<Page+Title>`, `/pages/viewpage.action?pageId=<id>`, short links `/x/<code>`.
9
+ - An XML export ZIP contains `entities.xml`; an HTML export ZIP contains `index.html` and an `attachments/` folder.
10
+ - Page bodies contain `<ac:structured-macro ac:name="...">` (storage format) or Confluence panel classes (HTML export).
11
+
12
+ ## Get the source
13
+
14
+ Mintlify's guide for this platform: https://www.mintlify.com/docs/help-center/migrate-from-confluence.md
15
+
16
+ ### From the repo
17
+
18
+ None; use an export.
19
+
20
+ ### From an export
21
+
22
+ One export per space. Formats and menus: https://support.atlassian.com/confluence-cloud/docs/export-content-to-word-pdf-html-and-xml/ (Cloud) and https://confluence.atlassian.com/doc/export-content-to-word-pdf-html-and-xml-139475.html (Data Center).
23
+
24
+ | Export | Who can run it | What you get |
25
+ | -------- | ------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------- |
26
+ | XML | Cloud: space admin. Data Center: Export Space permission (Back up) | `entities.xml` with every page's storage-format body, parent and position, plus attachments. Preferred. |
27
+ | HTML | Same as XML | Rendered HTML per page, `index.html` with the space tree, attachments in per-page-id folders. Flatter: macros are already rendered. |
28
+ | PDF/Word | Any viewer | Do not use; follow `mint migrate --from pdf` only if nothing else is available. |
29
+
30
+ The HTML export omits blog posts and comments; ask whether blogs are in scope. Comments are not migrated.
31
+
32
+ **XML export.** Parse `entities.xml` as XML; never regex it. It is an object dump: `Page` objects (title, `parent`, `position`, `space`), `BodyContent` objects (the storage-format body, linked to its page), and `Attachment` objects (file name, owning page). It also holds historical versions, drafts and trashed pages: keep only the current version of each page (older versions are listed under the current page's `historicalVersions`). Object model notes: https://confluence.atlassian.com/confkb/use-space-site-xml-export-entities-xml-to-find-confluence-objects-1283686755.html
33
+
34
+ **HTML export.** Read the space tree from `index.html` and each page's breadcrumbs. Per-page file names and wrapper markup vary by version; inspect a few files and inventory every distinct `class` before writing the transformer.
35
+
36
+ Split the export into one storage-format (XML export) or HTML (HTML export) file per page, named by page id.
37
+
38
+ ### From the live site
39
+
40
+ Not covered yet. Use an export.
41
+
42
+ ## Config → docs.json
43
+
44
+ A space has almost no site chrome to carry over.
45
+
46
+ | Confluence | docs.json |
47
+ | ----------------------------------------- | ------------------------------------------------------------------ |
48
+ | Space name | `name` |
49
+ | Space logo | `logo` (ask the customer for a light/dark logo) |
50
+ | Space key | none; used only in the route table |
51
+ | Several spaces migrated together | `navigation.tabs` or `navigation.products`, one per space |
52
+ | Space home page | first page of the first group |
53
+ | Labels | drop and report (or `keywords` if the customer wants search terms) |
54
+ | Page restrictions, space permissions | drop and report |
55
+ | Space theme, look and feel | drop and report |
56
+ | Blog posts, comments, likes, page history | drop and report |
57
+
58
+ ## Navigation
59
+
60
+ Build the tree from page `parent` and `position` (XML) or from `index.html` (HTML). Order siblings by `position`; where it is empty, take the order from the rendered page tree.
61
+
62
+ - The space home page is the root; its children become top-level groups or pages.
63
+ - A page with children becomes a nested group whose first page is the parent page itself.
64
+ - Keep titles verbatim as labels. Confluence trees are often deep; keep the depth and tell the customer if it exceeds what reads well, rather than flattening.
65
+ - Pages whose only content is a `children` macro become the group's first page with that list rendered as links.
66
+
67
+ ## Content conversion
68
+
69
+ Storage format is XHTML with `ac:` and `ri:` elements. Convert with an XML/HTML parser, not regex.
70
+
71
+ | Storage format | Mintlify |
72
+ | ------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
73
+ | `info` macro | `<Info>` |
74
+ | `tip` macro | `<Tip>` |
75
+ | `note` macro (renders as a yellow caution panel) | `<Warning>` |
76
+ | `warning` macro (renders red) | `<Danger>` |
77
+ | `title` parameter on the above | bold first line (`mint migrate --topic conversion`, Components) |
78
+ | `panel` macro | plain content under its `title` in bold; colors dropped |
79
+ | `code` macro: `<ac:plain-text-body><![CDATA[...]]>` | fence; `language`, `title` → title, `linenumbers` → `lines`, `collapse` → `expandable` |
80
+ | `noformat` macro | fence without a language |
81
+ | `expand` macro | `<Accordion title="...">`; title from the unnamed parameter, else "Click here to expand..." as shown on the source |
82
+ | `status` macro | `<Badge color="...">title</Badge>`; Grey/Red/Yellow/Green/Blue → gray/red/yellow/green/blue |
83
+ | `toc` macro | drop |
84
+ | `children` macro | list of links to the child pages, generated from the tree |
85
+ | `excerpt` macro | its body inline |
86
+ | `excerpt-include`, `include` macros | snippet of the source page's excerpt or body (`mint migrate --topic conversion`, Reusable content) |
87
+ | `anchor` macro | drop; repoint links that target it to the nearest heading |
88
+ | `jira` macro | link to each issue key; JQL tables dropped and reported |
89
+ | `drawio`, `gliffy` macros | image of the diagram (see Assets); report |
90
+ | `<ac:link><ri:page ri:content-title="X">` | root-absolute link to page X, resolved by title within the space |
91
+ | `<ac:link><ri:attachment ri:filename>` | link to the copied file |
92
+ | `<ac:image><ri:attachment ri:filename>` / `<ri:url ri:value>` | image with alt from `ac:alt` or the file name |
93
+ | `<ac:task-list>` | list; prefix each item with its `ac:task-status` |
94
+ | `<ac:emoticon ac:name>` | the matching Unicode emoji or drop |
95
+ | `<ac:layout>`, `<ac:layout-section>`, `<ac:layout-cell>` | unwrap; content in reading order |
96
+ | User mentions (`<ri:user>`) | the user's display name if the customer approves, else drop |
97
+ | Other macros (third-party apps, `ac:adf-extension`) | list in the report with page ids |
98
+
99
+ Count every distinct `ac:name` (`mint migrate --topic conversion`). Confluence tables with merged cells (`rowspan`, `colspan`) and nested tables do not fit markdown tables; keep them as HTML tables made MDX-safe.
100
+
101
+ Links by title resolve through a title → path index (`mint migrate --topic conversion`, Links). Links with `ri:space-key` pointing to another space resolve only if that space is migrated too.
102
+
103
+ ## Assets
104
+
105
+ - XML export: attachments sit in the export's attachments folder keyed by page id and attachment id; map each to its file name through the `Attachment` objects in `entities.xml`. Take the latest version only.
106
+ - HTML export: attachments are in per-page-id folders under `attachments/`.
107
+ - Copy to `images/<page-path>/` (images) or a downloads folder (other files) and rewrite references.
108
+ - draw.io: the macro's `diagramName` names an attachment on the same page. Use an exported PNG or SVG of the diagram if one is attached; otherwise ask the customer to export each diagram as an image. Gliffy works the same way. Never redraw a diagram.
109
+
110
+ ## URLs and redirects
111
+
112
+ Old URLs stay on Confluence, so `redirects` cannot catch them. Produce `route-table.csv` next to the manifest: `page_id, old_url, new_path, title`. Build `old_url` from the page id in the Cloud or Data Center pattern above. The customer can use it to update links elsewhere or archive the space with pointers. Choose new paths from slugified titles nested under the parent's path, and record them in the manifest.
113
+
114
+ ## Known gaps
115
+
116
+ - Page restrictions and space permissions.
117
+ - Third-party app macros, Jira query tables, live `children` listings, `contentbylabel` and similar dynamic macros: static at best.
118
+ - Comments, inline comments, page history, likes, blog posts.
119
+ - Short links (`/x/<code>`) are not in the route table unless the customer provides them.
120
+ - Diagrams without an image export.
@@ -0,0 +1,128 @@
1
+ # Docsify
2
+
3
+ No build step. One `index.html` sets `window.$docsify = {...}` and loads Docsify plus plugin `<script>`s; the browser fetches each page's raw Markdown and renders it. Navigation is Markdown (`_sidebar.md`, `_navbar.md`).
4
+
5
+ ## Detect
6
+
7
+ - An `index.html` with an inline `window.$docsify = {` and a `<script src=".../docsify...">`, usually in `docs/`. That folder is the content root.
8
+ - `_sidebar.md`, `_navbar.md`, `_coverpage.md`, `.nojekyll`, `README.md` beside it; `docsify-cli` in `package.json` or `docsify serve` in scripts.
9
+ - Live site: URLs of the form `/#/page`, and `<site>/README.md` returns raw Markdown.
10
+ - `index.html` with `$docsify` wins. A GitHub wiki (`_Sidebar.md`, `Home.md`, no `index.html`) is not Docsify.
11
+
12
+ ## Get the source
13
+
14
+ ### From the repo
15
+
16
+ - Read all of `index.html` first. The `$docsify` object decides which files are nav (`loadSidebar`, `loadNavbar`, `coverpage` can name other files), which file is home (`homepage`, default `README.md`), and where content comes from (`basePath`, `alias`). Every `<script src>` is a plugin to map.
17
+ - Every `.md` under the content root is a candidate page; files only reached through `:include` are partials, not pages.
18
+ - Nested sidebars: each folder may have its own `_sidebar.md`/`_navbar.md`; Docsify falls back to the parent folder's file. Collect all of them.
19
+ - Locales are plain subfolders (`zh-cn/README.md`, `zh-cn/guide.md`), usually linked from `_navbar.md`.
20
+ - Remote content: a `homepage`, `basePath` or `alias` pointing at `https://raw.githubusercontent.com/...` means the page lives in another repo. Vendor a copy and report it.
21
+
22
+ ### From an export
23
+
24
+ None; the site is served from the repo files.
25
+
26
+ ### From the live site
27
+
28
+ Docsify serves the raw files, so fetch them directly. Route `/#/guide` → `<site><basePath>guide.md`; `/#/folder/` → `folder/README.md`; nav from `<site>/_sidebar.md` and `<site>/_navbar.md`. Respect `basePath` and `ext` from the live `index.html`.
29
+
30
+ ## Config → docs.json
31
+
32
+ | Docsify | docs.json |
33
+ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- |
34
+ | `name` (strip HTML; `true` = `<title>` of `index.html`) | `name` |
35
+ | `<meta name="description">` in `index.html` | `description` |
36
+ | `logo` | `logo` |
37
+ | `nameLink` | `logo.href` (per-locale objects: drop and report) |
38
+ | `<link rel="icon">` in `index.html` | `favicon` |
39
+ | `themeColor` (deprecated) or `--theme-color` CSS variable | `colors.primary` |
40
+ | `repo` | `navbar.links` entry with `type: "github"` |
41
+ | `_navbar.md` | see Navigation |
42
+ | `formatUpdated`, `{docsify-updated}` | `metadata.timestamp: true` only if the user wants dates; delete the placeholder |
43
+ | `notFoundPage`, `_404.md` | drop and report (`errors.404` holds only redirect/title/description) |
44
+ | `alias` local → local | `redirects` |
45
+ | `alias` to sidebar/navbar files (`'/.*/_sidebar.md'`) | drop |
46
+ | `routes` (virtual routes) | static string routes → pages; function routes → drop and report |
47
+ | `fallbackLanguages`, `fallbackDefaultLanguage` | drop and report |
48
+ | `loadSidebar`, `loadNavbar`, `coverpage`, `onlyCover`, `homepage` | drop; use to locate files |
49
+ | `routerMode`, `relativePath`, `basePath`, `ext` | drop; use to compute old URLs and resolve links |
50
+ | `subMaxLevel`, `maxLevel`, `auto2top`, `topMargin`, `mergeNavbar`, `externalLinkTarget`, `cornerExternalLinkTarget`, `collapseSidebarGroups`, `hideSidebar`, `sidebarPosition`, `keyBindings`, `requestHeaders`, `noEmoji`, `markdown` options | drop |
51
+ | `markdown.renderer` overrides | drop and report what they rendered |
52
+ | `executeScript`, `vueComponents`, `vueMounts`, `vueGlobalOptions` | drop and report |
53
+ | Plugin `search`, `docsify-copy-code`, `zoom-image`, `docsify-pagination` | drop (built into Mintlify) |
54
+ | Plugin `gtag` with a `G-` id | `integrations.ga4.measurementId` |
55
+ | Plugin `ga` (`UA-` id) | drop and report (Universal Analytics no longer collects) |
56
+ | Plugin `disqus`, `gitalk`, edit-on-github | drop and report |
57
+ | Plugin `docsify-tabs`, mermaid renderer, math plugin | see Content conversion |
58
+ | Theme CSS, custom stylesheets | drop and report |
59
+
60
+ ## Navigation
61
+
62
+ - `_sidebar.md` is a nested Markdown list. A list item with a link is a page; a list item with plain text and child items is a group header. Map: header → group, linked item → page path, nested list under a linked item → nested group with that page as `root`. Keep order and labels.
63
+ - Label differs from the page H1 → `sidebarTitle`. Link title string (`[Guide](guide.md "Tab title")`) set only the browser tab title: drop and report.
64
+ - Resolve link targets: strip `.md`, `README` → folder index file, `/` → home page. Links resolve from the content root unless `relativePath: true`.
65
+ - External links in the sidebar → a page with frontmatter `title` + `url: <href>`, listed at that position.
66
+ - A folder-level `_sidebar.md` replaces the sidebar for that folder: map that folder to its own tab with its own groups.
67
+ - `_navbar.md`: top-level links to doc sections → `navigation.tabs`; a text item with a nested list → a tab with `menu` or, when the children are locales (`/`, `/zh-cn/`), `navigation.languages`; external links → `navbar.links`.
68
+ - The home page (`README.md` or `homepage`) goes first. Pages not in any sidebar were reachable only by link (`mint migrate --topic navigation`, Structure rules).
69
+ - `_sidebar.md`, `_navbar.md`, `_coverpage.md`, `_404.md` are not pages: do not convert them.
70
+
71
+ ## Content conversion
72
+
73
+ Pages usually have no front matter (the `front-matter` plugin is optional). If content precedes the first H1, use the sidebar label as title (`mint migrate --topic conversion`, Frontmatter).
74
+
75
+ | Docsify | Mintlify |
76
+ | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- |
77
+ | `> [!NOTE]` / `[!TIP]` / `[!IMPORTANT]` / `[!WARNING]` / `[!CAUTION]` | `mint migrate --topic conversion`, GitHub alerts |
78
+ | `!> text` (legacy important) | `<Info>` |
79
+ | `?> text` (legacy tip) | `<Tip>` |
80
+ | `## Heading :id=custom-id` | `mint migrate --topic conversion`, Heading IDs |
81
+ | `<!-- {docsify-ignore} -->`, `{docsify-ignore}`, `{docsify-ignore-all}` on headings | delete |
82
+ | `[x](file.md ':include')` (Markdown) | `mint migrate --topic conversion`, Reusable content |
83
+ | `[x](file.js ':include :type=code')`, `:fragment=name` | `mint migrate --topic conversion`, Code imports; fragments are `/// [name]` markers |
84
+ | `:include` of `.html` / `:type=iframe` | `<iframe>` inside `<Frame>` |
85
+ | `:include` of `.mp4`/`.ogg` / `.mp3` | `<video controls src>` / `<audio controls src>` with a root-relative path |
86
+ | `:include` of a remote URL or gist | vendor the content; report |
87
+ | docsify-tabs `<!-- tabs:start -->`, `#### **Name**` or `<!-- tab:Name -->`, `<!-- tabs:end -->` | `<Tabs>` + `<Tab title="Name">` |
88
+ | `<details><summary>T</summary>` | `<Accordion title="T">` |
89
+ | `[x](/path ':ignore')` | plain link to that path (it pointed outside the docs) |
90
+ | `[x](/path ':disabled')` | plain text `x` |
91
+ | `':target=_blank'`, `':class=...'`, `':id=...'` on links | drop the attribute string |
92
+ | `![a](img.png ':size=WxH')` / `':size=N'` | `<img src="/img.png" alt="a" width="W" height="H" />` |
93
+ | `![a](img.png ':no-zoom')` | `<img ... noZoom />` |
94
+ | `:shortcode:` emoji | Unicode emoji, unless `noEmoji: true` (then leave literal) |
95
+ | ` ```mermaid ` (custom renderer) | keep the fence |
96
+ | `$...$` / `$$...$$` from a math plugin | keep |
97
+ | Vue templates or `<script>` in pages | `mint migrate --topic conversion`, Components |
98
+
99
+ ## Assets
100
+
101
+ - Docsify serves every file in the content root at its path (`mint migrate --topic conversion`, Images and files).
102
+ - Resolve each image path the way the live site did: open the rendered page and read the `<img src>` it produced, then map that to the new location. Do not assume `./`, `../` and `/` paths resolve from the content root.
103
+ - `_media/` is the conventional asset folder; keep its name so paths stay stable.
104
+ - Cover page background (`![](bg.png)` or `![color](#hex)` in `_coverpage.md`): drop and report.
105
+
106
+ ## URLs and redirects
107
+
108
+ - Hash mode (default `routerMode: 'hash'`): every page is `/#/<path>`, folder index `/#/<folder>/`, home `/`. Heading anchors are `?id=<heading-id>` after the route (`/#/guide?id=install`).
109
+ - Hash URLs cannot be redirected (`mint migrate --topic navigation`, Redirects). Tell the user: old links load the new site root. If they need old links to resolve, a client-side script that reads `location.hash` and rewrites `#/<path>?id=<x>` to `/<new-path>#<x>` is the only option; it lives outside `docs.json` (a custom `.js` file in the Mintlify content directory runs on every page). Do not add it without the user's approval.
110
+ - History mode (`routerMode: 'history'`): URLs are real paths (`/guide`), so emit normal `redirects` for any path that changes. Anchors are still `?id=` and fall back to the page top (`mint migrate --topic navigation`, Redirects).
111
+ - Pin `{#id}` on headings that old `?id=` links target, using the id Docsify rendered (read the heading `id` attributes on the live page, or the `:id=`).
112
+ - The `homepage` file is the `/` page.
113
+ - `alias` entries were routes too: redirect the alias path to the new page (history mode) or report it (hash mode).
114
+ - Locales keep folder prefixes (`/zh-cn/...`).
115
+ - `README.md` folder index files (`mint migrate --topic conversion`, Files).
116
+
117
+ ## Known gaps
118
+
119
+ Report each that the site uses:
120
+
121
+ - Hash-route URLs and `?id=` anchors (no server-side redirect).
122
+ - Cover page layout and background, `onlyCover`.
123
+ - Function `routes`, `alias` to remote content, `fallbackLanguages`.
124
+ - Vue components, `executeScript` page scripts, custom `markdown` renderers.
125
+ - Comment plugins (Disqus, Gitalk), Universal Analytics, third-party plugins without a mapping above.
126
+ - Per-heading sidebar TOC control (`subMaxLevel`, `docsify-ignore`).
127
+ - Link and image attributes dropped (`:target`, `:class`, `:id`).
128
+ - Theme CSS and sidebar link title strings.
@@ -0,0 +1,117 @@
1
+ # Document360
2
+
3
+ Knowledge bases hosted by Document360. There is no source repo: content comes from a project export the customer runs, or from the public knowledge base site.
4
+
5
+ ## Detect
6
+
7
+ - Rendered HTML loads images from `cdn.document360.io` and references Document360 throughout the markup.
8
+ - Article URLs follow `/docs/<slug>`, optionally behind workspace and language segments (`/v2/docs/<slug>`, `/docs/en/<slug>`).
9
+ - Callouts render as `<div class="infoBox">`, `warningBox`, `errorBox`, `successBox`.
10
+ - An export ZIP contains per-article `.md`, `.html` or `.json` files and a media folder.
11
+
12
+ ## Get the source
13
+
14
+ Mintlify's guide for this platform: https://www.mintlify.com/docs/migration/document360.md
15
+
16
+ ### From the repo
17
+
18
+ None; content comes from a project export or the live site.
19
+
20
+ ### From an export
21
+
22
+ The customer runs it in the portal: **Content tools > Import and export > Import and export project > Export project**. Steps: https://docs.document360.com/docs/exporting-your-document360-project-as-a-zip-file-json
23
+
24
+ - Select **All** under "Include new or modified articles in"; the default date filter drops older articles.
25
+ - Select every maintained workspace, language and category, and **Include media files** (otherwise images stay as hosted URLs).
26
+ - Each new export overwrites the previous ZIP; download it as soon as it is ready.
27
+ - File type depends on the editor and the export: a single-language export writes `.md` for Markdown-editor articles and `.html` for WYSIWYG and Advanced WYSIWYG articles; a multi-language export writes `.json` for every article. Handle all three.
28
+ - Also ask for the **All articles** CSV export (title, category, status, dates, URL). Use it as the inventory and to reconcile the ZIP.
29
+
30
+ The export does not include snippets, variables, glossary, custom pages, redirects, custom CSS/JS or API specs. Collect those from the live site or ask the customer for them.
31
+
32
+ The Document360 API (`apihub.document360.io`, customer token) can list categories and articles if the customer prefers to script the export themselves; category responses contain only direct children, so recurse. https://apidocs.document360.com
33
+
34
+ ### From the live site
35
+
36
+ For public knowledge bases, `/llms.txt` lists every published article and category page, and each article serves markdown at `<article-url>.md`. The sitemap URL is shown in the customer's SEO settings. Quirks (`mint migrate --topic discovery`, Mirror the raw source):
37
+
38
+ - Strip the `> ## Documentation Index` blockquote after the frontmatter.
39
+ - Its frontmatter (`title`, `slug`, `description`, `tags`, `canonical`, dates) is usable source metadata (`mint migrate --topic conversion`, Frontmatter).
40
+ - Rendered callouts lose their type in `.md` output (only some become `> [!TIP]`-style blockquotes). Take the callout type from the rendered HTML class.
41
+
42
+ Private and mixed-access content is only in the export (`mint migrate --topic discovery`, Gated content).
43
+
44
+ ## Config → docs.json
45
+
46
+ | Document360 | docs.json |
47
+ | ------------------------------------------------ | ------------------------------------------------------ |
48
+ | Project name | `name` |
49
+ | Logo (light/dark), favicon | `logo.light`, `logo.dark`, `favicon` |
50
+ | Brand color | `colors.primary` |
51
+ | Header and secondary navigation links | `navbar.links` |
52
+ | Footer links | `footer.links` |
53
+ | Workspaces used as versions | `navigation.versions` |
54
+ | Workspaces used as separate products | `navigation.products` or `navigation.tabs` |
55
+ | Languages | `navigation.languages` if the customer migrates them |
56
+ | Redirect rules | `redirects` |
57
+ | Home page builder | an MDX home page with the same visible content; report |
58
+ | Reader groups, private articles, SSO | drop and report |
59
+ | Custom CSS / JavaScript, integrations, analytics | drop and report |
60
+ | Feedback, article ratings, search settings | drop and report |
61
+
62
+ ## Navigation
63
+
64
+ Use the category tree from the export folder structure, the CSV `category` column, or the rendered sidebar.
65
+
66
+ | Document360 | Mintlify |
67
+ | ---------------------------------- | ---------------------------------------------------------------- |
68
+ | Workspace | version, product or tab (ask how readers use them) |
69
+ | Folder category (no URL) | group |
70
+ | Index category (URL, article list) | group whose first page is an overview with links to its articles |
71
+ | Page category (URL, content) | group whose first page is the category's content |
72
+ | Subcategory | nested group |
73
+ | Article, sub-article | page |
74
+
75
+ Take sidebar order from the rendered sidebar unless the export carries an explicit order field. Articles in draft status (CSV `status`) are not published; ask before migrating them.
76
+
77
+ ## Content conversion
78
+
79
+ Document360 renders the article title as the H1; bodies start at H2. Do not add an H1.
80
+
81
+ | Document360 | Mintlify |
82
+ | ---------------------------------------------------------- | --------------------------------------------------------------- |
83
+ | Info callout (`infoBox`) | `<Info>` |
84
+ | Warning callout (`warningBox`) | `<Warning>` |
85
+ | Error callout (`errorBox`) | `<Danger>` |
86
+ | Success callout (`successBox`, `> [!TIP]` in `.md` output) | `<Check>` |
87
+ | Callout bold first line | bold first line (`mint migrate --topic conversion`, Components) |
88
+ | `{{snippet.<code>}}` | snippet (`mint migrate --topic conversion`, Reusable content) |
89
+ | `{{variable.<code>}}` | `{{<code>}}` (`mint migrate --topic conversion`, Template tags) |
90
+ | `{{glossary.<term>}}` | `<Tooltip tip="<definition>">term</Tooltip>` |
91
+ | Code block with a heading | fence with `title` |
92
+ | Tabs, accordions | `<Tabs>`, `<AccordionGroup>` |
93
+ | Step-by-step guide | `<Steps>` |
94
+ | Private notes | remove; list them in the report |
95
+ | Embedded video, iframe | supported embed, else link |
96
+ | Decision trees, forms | static content or link; report |
97
+
98
+ Merge codes are case-sensitive. Snippet and variable content is not in the export: get each value from the customer or from a rendered page that uses it.
99
+
100
+ WYSIWYG `.html` articles carry editor wrapper markup; count every distinct `class` value (`mint migrate --topic conversion`).
101
+
102
+ ## Assets
103
+
104
+ With **Include media files**, images ship in the ZIP; rewrite each reference to its local copy under `images/`. Without it, they are `cdn.document360.io` URLs (`mint migrate --topic conversion`, Images and files). Also check Drive file links (downloadable PDFs and attachments), which may point at Document360 storage.
105
+
106
+ ## URLs and redirects
107
+
108
+ - Build the old URL list from the CSV `URL` column plus `llms.txt` or the sitemap; include Index and Page category URLs.
109
+ - Keep the article slug; it is the stable part of the URL. Add redirects for workspace and language prefixes you drop or rename, and for each article whose path changes.
110
+ - Folder categories have no URL and need no redirect.
111
+
112
+ ## Known gaps
113
+
114
+ - Home page builder layouts and custom pages.
115
+ - Reader groups and private-content rules.
116
+ - API documentation: specs are imported (file, URL or CLI) and not in the export. Ask for the spec file, then follow `mint migrate --topic api`; do not convert the generated endpoint articles.
117
+ - Decision trees, article templates, related-articles widgets, feedback and ratings.