@mintlify/common 1.0.1159 → 1.0.1161
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/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/live-preview.d.ts +0 -1
- package/dist/live-preview.js +0 -1
- package/dist/mdx/plugins/remark/remarkMdxRemoveUnknownJsx/index.d.ts +1 -1
- package/dist/seo/resolveSeoMetatags.d.ts +12 -0
- package/dist/seo/resolveSeoMetatags.js +18 -0
- package/dist/seo/resolveSeoMetatags.test.d.ts +1 -0
- package/dist/seo/resolveSeoMetatags.test.js +81 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +4 -4
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
package/dist/live-preview.d.ts
CHANGED
|
@@ -9,7 +9,6 @@ export declare const LIVE_PREVIEW_NAVIGATION_UPDATE_MESSAGE_TYPE = "livePreviewN
|
|
|
9
9
|
export declare const LIVE_PREVIEW_REQUEST_CONTENT_MESSAGE_TYPE = "livePreviewRequestContent";
|
|
10
10
|
export declare const LIVE_PREVIEW_CONTENT_UNAVAILABLE_MESSAGE_TYPE = "livePreviewContentUnavailable";
|
|
11
11
|
export declare const LIVE_PREVIEW_CSS_SNAPSHOT_MESSAGE_TYPE = "livePreviewCssSnapshot";
|
|
12
|
-
export declare const LIVE_PREVIEW_GENERATION_STATE_MESSAGE_TYPE = "livePreviewGenerationState";
|
|
13
12
|
export declare function normalizeLivePreviewPath(path: string): string;
|
|
14
13
|
export declare function normalizeLivePreviewBasePath(basePath: string | undefined): string;
|
|
15
14
|
export declare function stripLivePreviewBasePath(path: string, basePath: string | undefined): string;
|
package/dist/live-preview.js
CHANGED
|
@@ -9,7 +9,6 @@ export const LIVE_PREVIEW_NAVIGATION_UPDATE_MESSAGE_TYPE = 'livePreviewNavigatio
|
|
|
9
9
|
export const LIVE_PREVIEW_REQUEST_CONTENT_MESSAGE_TYPE = 'livePreviewRequestContent';
|
|
10
10
|
export const LIVE_PREVIEW_CONTENT_UNAVAILABLE_MESSAGE_TYPE = 'livePreviewContentUnavailable';
|
|
11
11
|
export const LIVE_PREVIEW_CSS_SNAPSHOT_MESSAGE_TYPE = 'livePreviewCssSnapshot';
|
|
12
|
-
export const LIVE_PREVIEW_GENERATION_STATE_MESSAGE_TYPE = 'livePreviewGenerationState';
|
|
13
12
|
function normalizeLivePreviewHref(path) {
|
|
14
13
|
return path.replace(/^\/+|\/+$/g, '').replace(/\.mdx?$/, '');
|
|
15
14
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { Root } from 'mdast';
|
|
2
2
|
export declare const remarkMdxRemoveUnknownJsx: ({ allowlist }?: {
|
|
3
3
|
allowlist?: string[];
|
|
4
|
-
}) => (tree: Root) => Root | import("mdast
|
|
4
|
+
}) => (tree: Root) => Root | import("mdast").Link | import("mdast").Delete | import("mdast").Code | import("mdast").Text | import("mdast").Heading | import("mdast-util-mdx").MdxJsxFlowElement | import("mdast-util-mdx").MdxJsxTextElement | import("mdast").Blockquote | import("mdast").Break | import("mdast").Definition | import("mdast").Emphasis | import("mdast").FootnoteDefinition | import("mdast").FootnoteReference | import("mdast").Html | import("mdast").Image | import("mdast").ImageReference | import("mdast").InlineCode | import("mdast").LinkReference | import("mdast").List | import("mdast").ListItem | import("mdast").Paragraph | import("mdast").Strong | import("mdast").Table | import("mdast").TableCell | import("mdast").TableRow | import("mdast").ThematicBreak | import("mdast").Yaml | import("mdast-util-math").InlineMath | import("mdast-util-math").Math | import("mdast-util-mdx-expression").MdxTextExpression | import("mdast-util-mdx-expression").MdxFlowExpression | import("mdast-util-mdxjs-esm").MdxjsEsm;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export type SeoMetatagsConfig = {
|
|
2
|
+
metatags?: Record<string, string>;
|
|
3
|
+
paths?: {
|
|
4
|
+
path: string;
|
|
5
|
+
metatags: Record<string, string>;
|
|
6
|
+
}[];
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* Merges `seo.metatags` with every `seo.paths` entry whose folder contains the page.
|
|
10
|
+
* Shorter paths apply first, so the most specific folder wins.
|
|
11
|
+
*/
|
|
12
|
+
export declare function resolveSeoMetatags(seo: SeoMetatagsConfig | undefined, href: string | undefined): Record<string, string>;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
function toPagePath(href) {
|
|
2
|
+
return href.split(/[?#]/)[0].replace(/^\/+/, '').replace(/\/+$/, '');
|
|
3
|
+
}
|
|
4
|
+
/**
|
|
5
|
+
* Merges `seo.metatags` with every `seo.paths` entry whose folder contains the page.
|
|
6
|
+
* Shorter paths apply first, so the most specific folder wins.
|
|
7
|
+
*/
|
|
8
|
+
export function resolveSeoMetatags(seo, href) {
|
|
9
|
+
var _a, _b;
|
|
10
|
+
const siteMetatags = (_a = seo === null || seo === void 0 ? void 0 : seo.metatags) !== null && _a !== void 0 ? _a : {};
|
|
11
|
+
if (!((_b = seo === null || seo === void 0 ? void 0 : seo.paths) === null || _b === void 0 ? void 0 : _b.length) || !href)
|
|
12
|
+
return Object.assign({}, siteMetatags);
|
|
13
|
+
const pagePath = toPagePath(href);
|
|
14
|
+
const matches = seo.paths
|
|
15
|
+
.filter(({ path }) => pagePath === path || pagePath.startsWith(`${path}/`))
|
|
16
|
+
.sort((a, b) => a.path.length - b.path.length);
|
|
17
|
+
return Object.assign({}, siteMetatags, ...matches.map(({ metatags }) => metatags));
|
|
18
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { resolveSeoMetatags } from './resolveSeoMetatags.js';
|
|
3
|
+
const seo = {
|
|
4
|
+
metatags: { tenant: 'Acme', product: 'Docs' },
|
|
5
|
+
paths: [
|
|
6
|
+
{ path: 'guides/v2', metatags: { 'doc-version': '2', latest: 'true' } },
|
|
7
|
+
{ path: 'guides', metatags: { latest: 'false', should_index: 'true' } },
|
|
8
|
+
{ path: 'sdk', metatags: { product: 'SDK' } },
|
|
9
|
+
],
|
|
10
|
+
};
|
|
11
|
+
describe('resolveSeoMetatags', () => {
|
|
12
|
+
it('returns site metatags when no path matches', () => {
|
|
13
|
+
expect(resolveSeoMetatags(seo, '/changelog')).toEqual({ tenant: 'Acme', product: 'Docs' });
|
|
14
|
+
});
|
|
15
|
+
it('returns an empty object without seo config', () => {
|
|
16
|
+
expect(resolveSeoMetatags(undefined, '/guides/intro')).toEqual({});
|
|
17
|
+
});
|
|
18
|
+
it('returns site metatags without an href', () => {
|
|
19
|
+
expect(resolveSeoMetatags(seo, undefined)).toEqual({ tenant: 'Acme', product: 'Docs' });
|
|
20
|
+
});
|
|
21
|
+
it('applies a matching folder on top of site metatags', () => {
|
|
22
|
+
expect(resolveSeoMetatags(seo, '/guides/intro')).toEqual({
|
|
23
|
+
tenant: 'Acme',
|
|
24
|
+
product: 'Docs',
|
|
25
|
+
latest: 'false',
|
|
26
|
+
should_index: 'true',
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
it('lets the longest path win regardless of declaration order', () => {
|
|
30
|
+
expect(resolveSeoMetatags(seo, '/guides/v2/install')).toEqual({
|
|
31
|
+
tenant: 'Acme',
|
|
32
|
+
product: 'Docs',
|
|
33
|
+
'doc-version': '2',
|
|
34
|
+
latest: 'true',
|
|
35
|
+
should_index: 'true',
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
it('lets a folder override a site metatag', () => {
|
|
39
|
+
expect(resolveSeoMetatags(seo, 'sdk/node')).toEqual({ tenant: 'Acme', product: 'SDK' });
|
|
40
|
+
});
|
|
41
|
+
it('only matches on whole path segments', () => {
|
|
42
|
+
expect(resolveSeoMetatags(seo, '/guides/v20/install')).toEqual({
|
|
43
|
+
tenant: 'Acme',
|
|
44
|
+
product: 'Docs',
|
|
45
|
+
latest: 'false',
|
|
46
|
+
should_index: 'true',
|
|
47
|
+
});
|
|
48
|
+
expect(resolveSeoMetatags(seo, '/sdk-legacy/node')).toEqual({
|
|
49
|
+
tenant: 'Acme',
|
|
50
|
+
product: 'Docs',
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
it('matches a page whose href equals the path', () => {
|
|
54
|
+
expect(resolveSeoMetatags(seo, '/sdk')).toEqual({ tenant: 'Acme', product: 'SDK' });
|
|
55
|
+
});
|
|
56
|
+
it.each([
|
|
57
|
+
['a query string', '/sdk?ref=nav'],
|
|
58
|
+
['a fragment', '/sdk#overview'],
|
|
59
|
+
['a query string and fragment', '/sdk?ref=nav#overview'],
|
|
60
|
+
['a trailing slash', '/sdk/'],
|
|
61
|
+
])('matches a folder href with %s', (_label, href) => {
|
|
62
|
+
expect(resolveSeoMetatags(seo, href)).toEqual({ tenant: 'Acme', product: 'SDK' });
|
|
63
|
+
});
|
|
64
|
+
it('matches a nested page whose href carries a query string or fragment', () => {
|
|
65
|
+
expect(resolveSeoMetatags(seo, '/sdk/node?ref=nav#install')).toEqual({
|
|
66
|
+
tenant: 'Acme',
|
|
67
|
+
product: 'SDK',
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
it('does not match a different folder that shares a prefix', () => {
|
|
71
|
+
expect(resolveSeoMetatags(seo, '/sdk-legacy?ref=nav')).toEqual({
|
|
72
|
+
tenant: 'Acme',
|
|
73
|
+
product: 'Docs',
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
it('does not mutate the config', () => {
|
|
77
|
+
const before = JSON.stringify(seo);
|
|
78
|
+
resolveSeoMetatags(seo, '/guides/v2/install');
|
|
79
|
+
expect(JSON.stringify(seo)).toBe(before);
|
|
80
|
+
});
|
|
81
|
+
});
|