@thallylabs/migrate 0.2.14 → 0.2.18

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 CHANGED
@@ -11,7 +11,13 @@ authored nesting or order. The adapter supports tabs, dropdowns, products,
11
11
  versions, languages, and reusable `$ref` navigation files; it also preserves
12
12
  dropdown presentation, collection descriptions and icons, explicit default
13
13
  versions, page route casing, redirects, local snippets, static assets,
14
- compatible page frontmatter, site identity, and OpenAPI configuration. For public Mintlify
14
+ compatible page frontmatter, site identity, and OpenAPI configuration.
15
+ Analytics come across too: docs.json `integrations` and legacy mint.json
16
+ `analytics` for GA4, Google Tag Manager, PostHog, and Plausible are validated
17
+ and written to `docs.json` `integrations` (`integrations` wins per provider when
18
+ both exist). Invalid values are skipped with a warning, and every other
19
+ Mintlify provider (Amplitude, Mixpanel, Segment, and so on) is listed once in a
20
+ warning instead of being dropped silently. For public Mintlify
15
21
  sites, the URL adapter reads the structured configuration embedded in the
16
22
  rendered application before falling back to DOM link inference.
17
23
 
@@ -245,6 +251,56 @@ YouTube-embed package (e.g. a custom `LiteYouTube` wrapping
245
251
  page that imports that package directly, instead of losing the embed to the
246
252
  generic unknown-component fallback.
247
253
 
254
+ ### Access-restricted pages
255
+
256
+ A gated Mintlify page must never migrate as public. A page is withheld when its
257
+ frontmatter sets a non-empty `groups` (list or string) or `public: false`
258
+ (also `"false"`, `no`, `off`, `0`; empty `groups` restricts nothing), or when it sits
259
+ under a navigation group or tab that sets `groups` (a list of strings) or
260
+ `public: false`. `public: true` alone is not gating. Withheld pages are not
261
+ written to `src/content` and are removed from navigation (emptied groups and
262
+ tabs included), whether or not navigation lists them. The original file is
263
+ written unchanged to `migration-quarantine/<original path>` at the project
264
+ root, which no runtime content reader, search index, or `llms` output walks;
265
+ `create-thally-docs` also adds it to the project's `.gitignore` (appended once,
266
+ existing entries kept) so it is never committed or pushed. A public page that
267
+ imports a withheld page as a component does not inline it (a `gated-page`
268
+ warning names the importer). Invalid frontmatter fails the run rather than
269
+ importing the page. Each page gets a
270
+ `gated-page` warning, plus a summary; `create-thally-docs` prints these last
271
+ under an "ACCESS-RESTRICTED CONTENT" heading and the report records them and a
272
+ `quarantined` count. Links from other pages to a withheld page are left as
273
+ authored and will fail `thally check`; images and other assets used only by
274
+ gated pages are still copied to `public/`. Mintlify's site-wide authentication mode lives in its
275
+ dashboard and cannot be read from a repository, so when any page sets
276
+ `public: true` (which implies the source site required sign-in for everything
277
+ else) one `gated-page` warning says Thally will publish every imported page.
278
+ Restricted-container `groups` and `public: false` are honored fail-closed even
279
+ though Mintlify documents only `"public": true` on a group.
280
+
281
+ ### Site-wide scripts, styles, fonts, and settings
282
+
283
+ Mintlify serves every `.css` and `.js` file in the content directory on every
284
+ page. Those files are copied to `public/` (tooling config such as
285
+ `*.config.js`, `tailwind.*`, `postcss.*`, plus `dist`/`build`/`coverage`
286
+ output, dot-directories, and `node_modules` are not) under the normal asset
287
+ size limits. Scripts are added to `docs.json` `customScripts` (URL-encoded),
288
+ except modules that pages import as components, which are copied as components
289
+ instead. Thally cannot
290
+ load a stylesheet from `docs.json`, so each `.css` is preserved with a warning
291
+ that it is not applied and likely targets Mintlify's DOM. Fonts named by
292
+ `fonts.source` (top level, `heading`, `body`) that are local `.woff`, `.woff2`,
293
+ `.ttf`, or `.otf` files are copied; Thally's `fonts` setting loads Google Fonts
294
+ by family only, so a warning says the file is not applied. Remote font URLs
295
+ are not downloaded, and unsafe or missing paths are warned about.
296
+
297
+ Legacy `mint.json` `topbarLinks` and `topbarCtaButton` (including
298
+ `type: github`) map to `navbar.links` and `navbar.primary`; `docs.json`
299
+ `navbar` fields win, with a warning. `appearance.default`, `appearance.strict`
300
+ (`showToggle: false`), and legacy `modeToggle.default` / `isHidden` map to
301
+ `appearance`; invalid values are skipped with a warning. Mintlify sources set
302
+ `markdown.enabled: true`, matching Mintlify's default Markdown mirrors.
303
+
248
304
  ## Branding
249
305
 
250
306
  A source site's logo, favicon, and theme accent color(s) are extracted where
package/dist/index.d.ts CHANGED
@@ -113,6 +113,10 @@ interface MigrationDocsConfig {
113
113
  feedback?: {
114
114
  thumbsRating?: boolean;
115
115
  };
116
+ customScripts?: Array<{
117
+ src: string;
118
+ strategy?: 'beforeInteractive' | 'afterInteractive' | 'lazyOnload';
119
+ }>;
116
120
  ai?: {
117
121
  chat?: boolean;
118
122
  label?: string;
@@ -124,6 +128,24 @@ interface MigrationDocsConfig {
124
128
  analytics?: {
125
129
  enabled?: boolean;
126
130
  };
131
+ /** Third-party analytics in Mintlify's `integrations` shape; validated again by the renderer. */
132
+ integrations?: {
133
+ ga4?: {
134
+ measurementId: string;
135
+ };
136
+ gtm?: {
137
+ tagId: string;
138
+ };
139
+ posthog?: {
140
+ apiKey: string;
141
+ apiHost?: string;
142
+ sessionRecording?: boolean;
143
+ };
144
+ plausible?: {
145
+ domain: string;
146
+ server?: string;
147
+ };
148
+ };
127
149
  redirects?: Array<{
128
150
  source: string;
129
151
  destination: string;
@@ -170,7 +192,9 @@ interface MigrationAsset {
170
192
  projectRelative?: boolean;
171
193
  }
172
194
  interface MigrationWarning {
173
- code: 'collision' | 'invalid-page' | 'missing-page' | 'unsupported-config' | 'limit-reached' | 'fetch-failed' | 'skipped-file';
195
+ code: 'collision' | 'invalid-page' | 'missing-page' | 'unsupported-config' | 'limit-reached' | 'fetch-failed' | 'skipped-file'
196
+ /** Access-restricted source page withheld from the published site (or a site-wide auth risk). */
197
+ | 'gated-page';
174
198
  message: string;
175
199
  source?: string;
176
200
  }
@@ -190,6 +214,10 @@ interface MigrationBundle {
190
214
  }>;
191
215
  /** Customer-owned component source and registry; paths are repository-relative. */
192
216
  componentFiles?: Array<RenderedMigrationFile>;
217
+ /** Access-restricted source pages, written outside every published path. */
218
+ quarantinedFiles?: Array<RenderedMigrationFile>;
219
+ /** Access-restricted pages the file limit dropped: neither published nor saved in quarantinedFiles. */
220
+ droppedGatedPages?: number;
193
221
  docsConfig: MigrationDocsConfig;
194
222
  site?: {
195
223
  name?: string;
@@ -265,6 +293,8 @@ interface RepositoryMigrationOptions {
265
293
  docusaurusSidebarPath?: string;
266
294
  /** @internal Static assets are shared across docs-plugin instances. */
267
295
  docusaurusSkipAssets?: boolean;
296
+ /** @internal Test seam: lowers the 5,000-file budget so budget behaviour can be exercised with small fixtures. */
297
+ maxSourceFiles?: number;
268
298
  /** @internal Redirects are global config, read once, not per plugin instance. */
269
299
  docusaurusSkipRedirects?: boolean;
270
300
  }
@@ -303,9 +333,16 @@ interface MintlifyPageReference {
303
333
  navigationId: string;
304
334
  locale?: string;
305
335
  }
336
+ /** A page listed under an access-restricted navigation container. */
337
+ interface MintlifyGatedReference {
338
+ ref: string;
339
+ reason: string;
340
+ }
306
341
  interface MintlifyNavigationResult {
307
342
  docsConfig: MigrationDocsConfig;
308
343
  pageReferences: Array<MintlifyPageReference>;
344
+ /** Pages under a restricted container; withheld from `docsConfig` and `pageReferences`. */
345
+ gatedReferences: Array<MintlifyGatedReference>;
309
346
  warnings: Array<MigrationWarning>;
310
347
  }
311
348
  interface MintlifyProjectionOptions {
@@ -428,6 +465,26 @@ declare function parseMarkdownPage(input: {
428
465
  resolveIdentity?: (frontmatter: Record<string, unknown>, fallback: MarkdownPageIdentity) => MarkdownPageIdentity;
429
466
  }): MigrationPage | null;
430
467
 
468
+ /**
469
+ * Mintlify analytics -> Thally `docs.json` `integrations`.
470
+ *
471
+ * Reads docs.json `integrations` and the legacy mint.json `analytics` block.
472
+ * Values land in an inline script on the rendered site, so each is validated
473
+ * here with the same patterns the renderer applies (src/lib/analytics-config.ts;
474
+ * a test keeps the two in agreement). Invalid values are skipped with a warning,
475
+ * never coerced, and no warning echoes a full value.
476
+ */
477
+ type MigrationIntegrations = NonNullable<MigrationDocsConfig['integrations']>;
478
+ declare function projectMintlifyIntegrations(config: Record<string, unknown>): {
479
+ integrations?: MigrationIntegrations;
480
+ warnings: Array<MigrationWarning>;
481
+ };
482
+ /**
483
+ * Validate an authored Thally `docs.json` `integrations` value with the same
484
+ * rules as the import and the renderer; one value-free message per problem.
485
+ */
486
+ declare function validateIntegrations(integrations: unknown): Array<string>;
487
+
431
488
  /** Render canonical migration bundles into a portable Thally repository tree. */
432
489
 
433
490
  /** Merge imported tabs into an existing site without duplicating changelog tabs. */
@@ -467,4 +524,4 @@ declare function migrateUrl(options: UrlMigrationOptions): Promise<MigrationBund
467
524
  */
468
525
  declare function hydrateRemoteApiSpecs(bundle: MigrationBundle, fetcher?: MigrationFetcher): Promise<MigrationBundle>;
469
526
 
470
- 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, projectMintlifyNavigation, pruneMissingNavigationPages, readFernConfig, readMintlifyConfig, renderMigrationFiles, validateMigrationUrl };
527
+ 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 };