@thallylabs/migrate 0.2.24 → 0.2.25
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 +74 -2
- package/dist/index.d.ts +73 -2
- package/dist/index.js +11490 -10375
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -171,6 +171,54 @@ from Fern MDX pages (`../../components/...`, resolved against the Fern
|
|
|
171
171
|
project root) are migrated the same way Mintlify and Docusaurus components
|
|
172
172
|
are — see "Mintlify compatibility" below.
|
|
173
173
|
|
|
174
|
+
## Mintlify `sourceRef` repositories
|
|
175
|
+
|
|
176
|
+
A Mintlify navigation node `{"sourceRef": "owner/repo"}` mounts the docs of another
|
|
177
|
+
repository. Mintlify does not document where that mount lives, so it cannot be
|
|
178
|
+
derived from `docs.json`; supply it with a repeatable flag:
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
create-thally-docs migrate https://github.com/OpenRouterTeam/docs my-docs \
|
|
182
|
+
--source-ref OpenRouterTeam/typescript-sdk=client-sdks/typescript
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
Without a mapping the node is skipped with a warning that names the flag.
|
|
186
|
+
|
|
187
|
+
- The repository must be on github.com. Its docs root is the directory holding a
|
|
188
|
+
Mintlify `docs.json` (`docs/` first, then the repository root); without one the
|
|
189
|
+
mapping is skipped with a warning.
|
|
190
|
+
- Every `.md`/`.mdx` file under that root is imported (orphans included) through the
|
|
191
|
+
same pipeline as the main site, under `<mount-path>/...`. Assets are copied under
|
|
192
|
+
`public/<mount-path>/...`. The node is replaced by the referenced `docs.json`
|
|
193
|
+
navigation with page paths prefixed by the mount path; tabs become groups, and the
|
|
194
|
+
parent group keeps its label and icon.
|
|
195
|
+
- Root-absolute links inside those pages (`/models/x`, `/images/x.png`) are prefixed
|
|
196
|
+
with the mount path (sub-site semantics: Mintlify's behavior here is not
|
|
197
|
+
documented, so this is an assumption). Relative links work as-is.
|
|
198
|
+
- Pages, navigation, assets and the referenced repository's custom components are
|
|
199
|
+
imported. Its components are bundled with the main site's under `src/mdx/migrated/`
|
|
200
|
+
and registered in `src/mdx/custom-components.tsx`; their content-hashed names cannot
|
|
201
|
+
clash with the main site's. Branding, colors, redirects, OpenAPI specs and
|
|
202
|
+
access-restricted pages of the referenced repository are ignored (one warning says
|
|
203
|
+
so). Access-restricted pages and the files only they use are withheld from the site
|
|
204
|
+
and are not saved anywhere (the main site saves its own under `migration-quarantine/`;
|
|
205
|
+
a referenced repository's are discarded), so recover them from that repository if
|
|
206
|
+
needed.
|
|
207
|
+
- Safety limits per referenced repository, fixed constants: 5,000 files and 50 MB under
|
|
208
|
+
the docs root. Over a limit the whole repository is refused, never imported
|
|
209
|
+
partially. Symlinks and dot-directories are removed before import, and a docs
|
|
210
|
+
directory that resolves outside the clone is refused. A repository GitHub reports as
|
|
211
|
+
larger than 200 MB is refused before cloning (if the GitHub API is unreachable the
|
|
212
|
+
clone proceeds and the limits above still apply), its submodules are not fetched,
|
|
213
|
+
and a `docs.json` over 1 MB is ignored. `repo` must match `owner/repo`; the mount
|
|
214
|
+
path must be a relative lowercase slug path (no `..`, no leading slash), must not
|
|
215
|
+
start with a name the site itself uses (`api`, `admin`, `_next`, `public`,
|
|
216
|
+
`llms.txt`, `sitemap.xml`, ...), must not collide with an existing page or directory
|
|
217
|
+
of the main site, and mappings must not overlap.
|
|
218
|
+
- A mapping that matches no `sourceRef` in the navigation is reported and imports
|
|
219
|
+
nothing. `migration-report.json` lists each imported repository with its page count
|
|
220
|
+
under `sourceRefs`.
|
|
221
|
+
|
|
174
222
|
## Mintlify compatibility
|
|
175
223
|
|
|
176
224
|
Repository imports preserve named/default local JSX and TSX components and
|
|
@@ -214,8 +262,8 @@ same-length nested fence is widened so the inner fence no longer closes it, and
|
|
|
214
262
|
a bare placeholder tag in prose (`<Feature> requires a plan`) that would stop
|
|
215
263
|
the page compiling is escaped as text rather than losing the page.
|
|
216
264
|
The Mintlify `search-bar-entry` click trigger is mapped to Thally's search
|
|
217
|
-
shortcut. Markdown mixed inside interactive JSX
|
|
218
|
-
|
|
265
|
+
shortcut. Markdown mixed inside interactive JSX and computed imports are
|
|
266
|
+
reported for manual review; unsupported source is
|
|
219
267
|
preserved, not replaced with empty stubs. An external package's JSX usage is
|
|
220
268
|
dropped and replaced with a safe fallback (with a warning); if that package's
|
|
221
269
|
binding is instead referenced outside JSX (an expression, a prop, or an
|
|
@@ -237,6 +285,30 @@ Next) and copied into any extracted client module. A source site's own
|
|
|
237
285
|
passes a page-authored function into a client component needs the client
|
|
238
286
|
wrapper described above; unsupported callback shapes retain their content
|
|
239
287
|
with a warning. An unconfirmed target is warned for review.
|
|
288
|
+
Other relative imports of a copied file are handled the same way: a namespace
|
|
289
|
+
import (`import * as X from './comp.jsx'`) and a dynamic `import('./comp.jsx')`
|
|
290
|
+
point at the copied module, and a relative side-effect import
|
|
291
|
+
(`import './styles.css'`) is removed with a warning, like one from an npm
|
|
292
|
+
package. A page is excluded only when the relative target is not copied (for
|
|
293
|
+
example a Next.js `./metadata` module, or an `export ... from` re-export), with
|
|
294
|
+
a single warning naming it. An MDX expression that names an identifier the page
|
|
295
|
+
never defines (`{missing}`) is removed with a warning, since it would throw at
|
|
296
|
+
render; define the name or escape the braces as `\{ \}` to keep the text.
|
|
297
|
+
A value import from a local snippet (`import { FEE, fee } from
|
|
298
|
+
'/snippets/c.mdx'`) is inlined when each name is a static value (string,
|
|
299
|
+
number, boolean, `null`, or an object/array of those) or a self-contained
|
|
300
|
+
function. Inlined functions may only use pure built-ins (`Math`, `JSON`,
|
|
301
|
+
`String`, `Number`, `Boolean`, `Array`, `Date`, `Intl`, `parseInt`,
|
|
302
|
+
`parseFloat`, `isNaN`, `isFinite`, `encodeURIComponent` and
|
|
303
|
+
`decodeURIComponent`) and may not reach
|
|
304
|
+
`Function`, constructors, `globalThis`, `fetch` or other globals; anything else
|
|
305
|
+
is not inlined. A name the snippet does not export, or one that cannot be
|
|
306
|
+
inlined, is bound to `undefined` (as Mintlify does for a missing export) with a
|
|
307
|
+
warning, while the other names of the same import are still inlined. A snippet
|
|
308
|
+
import that resolves outside the repository through a symlink is refused, and a
|
|
309
|
+
snippet whose frontmatter cannot be read is not inlined (left as a comment with
|
|
310
|
+
a warning). Mintlify `sourceRef` navigation nodes have no Thally equivalent and
|
|
311
|
+
are reported rather than migrated.
|
|
240
312
|
File paths cannot escape the repository checkout; symlinks and oversized
|
|
241
313
|
graphs are rejected. This is compatibility analysis, **not a code sandbox**:
|
|
242
314
|
imported JavaScript executes when the developer builds or runs the resulting
|
package/dist/index.d.ts
CHANGED
|
@@ -81,6 +81,8 @@ interface MigrationDocsConfig {
|
|
|
81
81
|
};
|
|
82
82
|
/** Local site-authored CSS projected from a source docs site, served from public/. */
|
|
83
83
|
stylesheets?: Array<string>;
|
|
84
|
+
/** `false` hides the breadcrumb trail; Mintlify pages show only a group eyebrow. */
|
|
85
|
+
breadcrumbs?: boolean;
|
|
84
86
|
tabs: Array<MigrationNavigationTab>;
|
|
85
87
|
navigation?: {
|
|
86
88
|
/** How sibling documentation collections are presented to readers. */
|
|
@@ -173,6 +175,8 @@ interface MigrationDocsConfig {
|
|
|
173
175
|
playground?: {
|
|
174
176
|
display: 'interactive' | 'simple' | 'none';
|
|
175
177
|
};
|
|
178
|
+
/** `false` hides the visible "OpenAPI specification" line; Mintlify does not show it. */
|
|
179
|
+
specLink?: boolean;
|
|
176
180
|
};
|
|
177
181
|
/** Third-party analytics in Mintlify's `integrations` shape; validated again by the renderer. */
|
|
178
182
|
integrations?: {
|
|
@@ -281,6 +285,12 @@ interface MigrationBundle {
|
|
|
281
285
|
quarantinedFiles?: Array<RenderedMigrationFile>;
|
|
282
286
|
/** Access-restricted pages the file limit dropped: neither published nor saved in quarantinedFiles. */
|
|
283
287
|
droppedGatedPages?: number;
|
|
288
|
+
/** Mintlify `sourceRef` repositories imported under a mount path, with their page counts. */
|
|
289
|
+
sourceRefs?: Array<{
|
|
290
|
+
repo: string;
|
|
291
|
+
mountPath: string;
|
|
292
|
+
pages: number;
|
|
293
|
+
}>;
|
|
284
294
|
docsConfig: MigrationDocsConfig;
|
|
285
295
|
site?: {
|
|
286
296
|
name?: string;
|
|
@@ -324,6 +334,51 @@ interface RenderedMigrationFile {
|
|
|
324
334
|
content: string | Uint8Array;
|
|
325
335
|
}
|
|
326
336
|
|
|
337
|
+
/**
|
|
338
|
+
* Mintlify `sourceRef` navigation nodes mount the docs of another repository
|
|
339
|
+
* (`{"sourceRef": "owner/repo"}`). The mount path is not derivable from any
|
|
340
|
+
* docs.json, so the caller supplies it with `--source-ref owner/repo=<path>`.
|
|
341
|
+
* The referenced repository is untrusted remote content: it is validated,
|
|
342
|
+
* size-capped, stripped of symlinks and dot-directories, then run through the
|
|
343
|
+
* same repository pipeline as the main site and prefixed with its mount path.
|
|
344
|
+
*/
|
|
345
|
+
|
|
346
|
+
/** Per referenced repository: files and bytes under its docs root. Constants on purpose, not configurable. */
|
|
347
|
+
declare const SOURCE_REF_MAX_FILES = 5000;
|
|
348
|
+
declare const SOURCE_REF_MAX_BYTES = 50000000;
|
|
349
|
+
/** GitHub reports repository size in KB; a larger repository is refused before it is cloned. */
|
|
350
|
+
declare const SOURCE_REF_MAX_REPOSITORY_KB = 200000;
|
|
351
|
+
interface SourceRefMapping {
|
|
352
|
+
/** `owner/repo`, exactly as written in the source navigation. */
|
|
353
|
+
repo: string;
|
|
354
|
+
/** Relative slug path the referenced docs are mounted at, e.g. `client-sdks/typescript`. */
|
|
355
|
+
mountPath: string;
|
|
356
|
+
}
|
|
357
|
+
interface SourceRefImport extends SourceRefMapping {
|
|
358
|
+
pages: Array<MigrationPage>;
|
|
359
|
+
assets: Array<MigrationAsset>;
|
|
360
|
+
/** Navigation entries with every page id already prefixed by the mount path. */
|
|
361
|
+
navigation: Array<string | MigrationNavigationGroup>;
|
|
362
|
+
/** Custom component files (and registry) the mounted pages' `<MigratedXXXX/>` tags need; merged into the main bundle. */
|
|
363
|
+
componentFiles?: Array<RenderedMigrationFile>;
|
|
364
|
+
/** Why the import is empty (or partial), plus forwarded pipeline warnings. */
|
|
365
|
+
warnings: Array<MigrationWarning>;
|
|
366
|
+
}
|
|
367
|
+
/** Parse repeated `owner/repo=mount/path` values; throws on anything unsafe. */
|
|
368
|
+
declare function parseSourceRefFlags(values: ReadonlyArray<string>): Array<SourceRefMapping>;
|
|
369
|
+
/**
|
|
370
|
+
* Why a referenced repository is too large to clone, or null when it is small
|
|
371
|
+
* enough or its size is unknown (GitHub API unreachable, rate-limited or
|
|
372
|
+
* private): an unknown size proceeds, and the post-clone caps still apply.
|
|
373
|
+
*/
|
|
374
|
+
declare function sourceRefOversizeReason(repo: string, fetcher?: MigrationFetcher): Promise<string | null>;
|
|
375
|
+
/**
|
|
376
|
+
* Import one cloned referenced repository as a sub-site under its mount path.
|
|
377
|
+
* `repositoryDir` is a disposable clone: symlinks and dot-directories under
|
|
378
|
+
* its docs root are deleted.
|
|
379
|
+
*/
|
|
380
|
+
declare function importSourceRef(mapping: SourceRefMapping, repositoryDir: string): SourceRefImport;
|
|
381
|
+
|
|
327
382
|
/**
|
|
328
383
|
* Repository adapter for the shared migration engine. Traversal is bounded;
|
|
329
384
|
* `scanFiles` follows a symbolic link only when its resolved real path stays
|
|
@@ -346,6 +401,8 @@ interface RepositoryMigrationOptions {
|
|
|
346
401
|
sourceUrl: string;
|
|
347
402
|
docsDir?: string;
|
|
348
403
|
platform?: MigrationPlatform;
|
|
404
|
+
/** @internal Mount path of a sourceRef import; keeps its component files separate from any other copy of the same source. */
|
|
405
|
+
componentNamespace?: string;
|
|
349
406
|
/** @internal Prefix used by additional Docusaurus docs-plugin instances. */
|
|
350
407
|
docusaurusRoutePrefix?: string;
|
|
351
408
|
/** @internal Prevent recursive discovery while importing one plugin root. */
|
|
@@ -360,6 +417,8 @@ interface RepositoryMigrationOptions {
|
|
|
360
417
|
maxSourceFiles?: number;
|
|
361
418
|
/** @internal Redirects are global config, read once, not per plugin instance. */
|
|
362
419
|
docusaurusSkipRedirects?: boolean;
|
|
420
|
+
/** Mintlify `sourceRef` repositories already fetched and prepared by `importSourceRef`. */
|
|
421
|
+
sourceRefs?: ReadonlyArray<SourceRefImport>;
|
|
363
422
|
}
|
|
364
423
|
/** Parse and validate a public GitHub repository URL. */
|
|
365
424
|
declare function parseGitHubRepositoryUrl(rawUrl: string): GitHubRepositorySource;
|
|
@@ -377,7 +436,11 @@ declare function gitmodulePaths(targetDir: string): Array<string>;
|
|
|
377
436
|
* submodule-fetch-failure warning (this function otherwise returns exactly
|
|
378
437
|
* as before, so existing callers are unaffected).
|
|
379
438
|
*/
|
|
380
|
-
declare function cloneGitHubRepository(source: GitHubRepositorySource, targetDir: string, warnings?: Array<MigrationWarning
|
|
439
|
+
declare function cloneGitHubRepository(source: GitHubRepositorySource, targetDir: string, warnings?: Array<MigrationWarning>,
|
|
440
|
+
/** Untrusted referenced repositories: never follow their `.gitmodules` to further remotes. */
|
|
441
|
+
options?: {
|
|
442
|
+
skipSubmodules?: boolean;
|
|
443
|
+
}): Promise<void>;
|
|
381
444
|
/** Detect a supported repository docs platform from unambiguous config files. */
|
|
382
445
|
declare function detectRepositoryPlatform(repositoryDir: string, docsDir?: string): MigrationPlatform;
|
|
383
446
|
/** Pick the first conventional content root containing Markdown. */
|
|
@@ -406,11 +469,19 @@ interface MintlifyNavigationResult {
|
|
|
406
469
|
pageReferences: Array<MintlifyPageReference>;
|
|
407
470
|
/** Pages under a restricted container; withheld from `docsConfig` and `pageReferences`. */
|
|
408
471
|
gatedReferences: Array<MintlifyGatedReference>;
|
|
472
|
+
/** `sourceRef` mounts under a restricted container; never resolved, so nothing of theirs is imported. */
|
|
473
|
+
gatedSourceRefs: Array<string>;
|
|
409
474
|
warnings: Array<MigrationWarning>;
|
|
410
475
|
}
|
|
411
476
|
interface MintlifyProjectionOptions {
|
|
412
477
|
/** Public URL migrations may expose page hrefs including the docs mount path. */
|
|
413
478
|
pathPrefix?: string;
|
|
479
|
+
/**
|
|
480
|
+
* Resolves a `sourceRef` repository (`owner/repo`) to the navigation entries
|
|
481
|
+
* of its imported docs, already prefixed with their mount path. Returns null
|
|
482
|
+
* when the repository was not mapped with `--source-ref`.
|
|
483
|
+
*/
|
|
484
|
+
resolveSourceRef?: (repo: string) => Array<string | MigrationNavigationGroup> | null;
|
|
414
485
|
}
|
|
415
486
|
/** Preserve Mintlify's implicit `/section` route for section landing pages. */
|
|
416
487
|
declare function addMintlifyDirectoryRedirects(config: MigrationDocsConfig, pages: Array<MigrationPage>): MigrationDocsConfig;
|
|
@@ -589,4 +660,4 @@ declare function migrateUrl(options: UrlMigrationOptions): Promise<MigrationBund
|
|
|
589
660
|
*/
|
|
590
661
|
declare function hydrateRemoteApiSpecs(bundle: MigrationBundle, fetcher?: MigrationFetcher): Promise<MigrationBundle>;
|
|
591
662
|
|
|
592
|
-
export { type GitHubRepositorySource, type MigrationAsset, type MigrationBundle, type MigrationDocsConfig, type MigrationFetchRequest, type MigrationFetchResponse, type MigrationFetcher, type MigrationNavigationGroup, type MigrationNavigationTab, type MigrationPage, type MigrationPlatform, type MigrationWarning, type RenderedMigrationFile, type RepositoryMigrationOptions, type UrlMigrationOptions, addMintlifyDirectoryRedirects, buildNavigationFromPages, cloneGitHubRepository, defaultMigrationFetcher, detectRepositoryDocsDir, detectRepositoryPlatform, gitmodulePaths, hydrateRemoteApiSpecs, mergeMigrationConfig, migrateRepository, migrateUrl, normalizeMdx, parseGitHubRepositoryUrl, parseMarkdownPage, projectFernNavigation, projectMintlifyIntegrations, projectMintlifyNavigation, pruneMissingNavigationPages, readFernConfig, readMintlifyConfig, renderMigrationFiles, validateIntegrations, validateMigrationUrl };
|
|
663
|
+
export { type GitHubRepositorySource, type MigrationAsset, type MigrationBundle, type MigrationDocsConfig, type MigrationFetchRequest, type MigrationFetchResponse, type MigrationFetcher, type MigrationNavigationGroup, type MigrationNavigationTab, type MigrationPage, type MigrationPlatform, type MigrationWarning, type RenderedMigrationFile, type RepositoryMigrationOptions, SOURCE_REF_MAX_BYTES, SOURCE_REF_MAX_FILES, SOURCE_REF_MAX_REPOSITORY_KB, type SourceRefImport, type SourceRefMapping, type UrlMigrationOptions, addMintlifyDirectoryRedirects, buildNavigationFromPages, cloneGitHubRepository, defaultMigrationFetcher, detectRepositoryDocsDir, detectRepositoryPlatform, gitmodulePaths, hydrateRemoteApiSpecs, importSourceRef, mergeMigrationConfig, migrateRepository, migrateUrl, normalizeMdx, parseGitHubRepositoryUrl, parseMarkdownPage, parseSourceRefFlags, projectFernNavigation, projectMintlifyIntegrations, projectMintlifyNavigation, pruneMissingNavigationPages, readFernConfig, readMintlifyConfig, renderMigrationFiles, sourceRefOversizeReason, validateIntegrations, validateMigrationUrl };
|