@mintlify/common 1.0.1257 → 1.0.1259
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/mdx/islands/extractPackageIslands.js +16 -3
- package/dist/mdx/islands/island-module-builder.d.ts +9 -2
- package/dist/mdx/islands/island-module-builder.js +72 -3
- package/dist/mdx/islands/remarkPackageIslands.js +6 -3
- package/dist/mdx/islands/types.d.ts +11 -0
- package/dist/mdx/lib/slug-deduplicator.d.ts +5 -0
- package/dist/mdx/lib/slug-deduplicator.js +24 -0
- package/dist/mdx/plugins/rehype/rehypeDynamicTailwindCss.js +401 -56
- package/dist/mdx/plugins/remark/remarkExtractTableOfContents.js +36 -27
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +2 -2
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
import { getTableOfContentsTitle } from '../lib/remark-utils.js';
|
|
2
|
+
import { createSlugDeduplicator } from '../lib/slug-deduplicator.js';
|
|
3
|
+
import { HEADING_LEVELS } from '../plugins/remark/remarkComponentIds.js';
|
|
1
4
|
import { bindingHead, collectBindings, collectConsts, esmStatements, lineOf, referencesIn, } from './island-bindings.js';
|
|
2
|
-
import { IslandModuleBuilder, MOVE_TO_SNIPPET } from './island-module-builder.js';
|
|
5
|
+
import { claimHeadingSlug, HEADING_ELEMENTS, IslandModuleBuilder, MOVE_TO_SNIPPET, } from './island-module-builder.js';
|
|
3
6
|
import { blockerWithin, childrenPlacements, isIntrinsic, isListLoose, } from './island-placement.js';
|
|
4
7
|
import { sha256Hex } from './sha256.js';
|
|
5
8
|
const CSS_SPECIFIER = /\.css(?:[?#].*)?$/;
|
|
@@ -47,6 +50,7 @@ export const extractPackageIslands = (tree, options) => {
|
|
|
47
50
|
if (statement.type !== 'ImportDeclaration')
|
|
48
51
|
reportReferences(statement, line);
|
|
49
52
|
}
|
|
53
|
+
const headingSlugs = createSlugDeduplicator();
|
|
50
54
|
const tightItems = new WeakSet();
|
|
51
55
|
const placements = new Map();
|
|
52
56
|
const visitChildren = (parent, blocker, outside = blocker, via) => {
|
|
@@ -71,7 +75,7 @@ export const extractPackageIslands = (tree, options) => {
|
|
|
71
75
|
errors.push({ line: lineOf(child), message });
|
|
72
76
|
continue;
|
|
73
77
|
}
|
|
74
|
-
const builder = new IslandModuleBuilder(child.name, options.pagePath, bindings, undeclared, consts, sideEffects, order);
|
|
78
|
+
const builder = new IslandModuleBuilder(child.name, options.pagePath, bindings, undeclared, consts, sideEffects, order, headingSlugs);
|
|
75
79
|
const element = builder.element(child);
|
|
76
80
|
if (builder.errors.length > 0 || !element) {
|
|
77
81
|
errors.push(...builder.errors);
|
|
@@ -92,7 +96,7 @@ export const extractPackageIslands = (tree, options) => {
|
|
|
92
96
|
module,
|
|
93
97
|
});
|
|
94
98
|
}
|
|
95
|
-
roots.push({ id, name: child.name, node: child, parent });
|
|
99
|
+
roots.push({ id, name: child.name, node: child, parent, headings: builder.headings });
|
|
96
100
|
continue;
|
|
97
101
|
}
|
|
98
102
|
if (child.name && head !== undefined && undeclared.has(head)) {
|
|
@@ -102,6 +106,12 @@ export const extractPackageIslands = (tree, options) => {
|
|
|
102
106
|
});
|
|
103
107
|
continue;
|
|
104
108
|
}
|
|
109
|
+
if (child.name && HEADING_ELEMENTS.has(child.name)) {
|
|
110
|
+
const id = child.attributes.find((attribute) => attribute.type === 'mdxJsxAttribute' && attribute.name === 'id');
|
|
111
|
+
if (id === undefined || typeof id.value === 'string') {
|
|
112
|
+
claimHeadingSlug(headingSlugs, getTableOfContentsTitle(child), typeof (id === null || id === void 0 ? void 0 : id.value) === 'string' ? id.value : undefined);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
105
115
|
for (const attribute of child.attributes) {
|
|
106
116
|
let estree;
|
|
107
117
|
if (attribute.type === 'mdxJsxExpressionAttribute') {
|
|
@@ -129,6 +139,9 @@ export const extractPackageIslands = (tree, options) => {
|
|
|
129
139
|
reportReferences(child.data.estree, lineOf(child));
|
|
130
140
|
continue;
|
|
131
141
|
}
|
|
142
|
+
if (child.type === 'heading' && HEADING_LEVELS.includes(child.depth)) {
|
|
143
|
+
claimHeadingSlug(headingSlugs, getTableOfContentsTitle(child));
|
|
144
|
+
}
|
|
132
145
|
if (child.type === 'list' && !isListLoose(child)) {
|
|
133
146
|
for (const item of child.children)
|
|
134
147
|
tightItems.add(item);
|
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
import type { JSXElement, JSXExpressionContainer, JSXFragment } from 'estree-jsx';
|
|
2
2
|
import type { RootContent } from 'mdast';
|
|
3
|
+
import type { SlugDeduplicator } from '../lib/slug-deduplicator.js';
|
|
3
4
|
import { type Binding } from './island-bindings.js';
|
|
4
5
|
import { type ConstEntry } from './static-expressions.js';
|
|
5
|
-
import type { IslandError, IslandImport } from './types.js';
|
|
6
|
+
import type { IslandError, IslandHeading, IslandImport } from './types.js';
|
|
6
7
|
type JsxNode = Extract<RootContent, {
|
|
7
8
|
type: 'mdxJsxFlowElement' | 'mdxJsxTextElement';
|
|
8
9
|
}>;
|
|
9
10
|
type JsxChild = JSXElement | JSXFragment | JSXExpressionContainer;
|
|
10
11
|
export declare const MOVE_TO_SNIPPET = "Move this into a snippet.";
|
|
12
|
+
export declare const claimHeadingSlug: (slugs: SlugDeduplicator, title: string, explicitId?: string) => string | undefined;
|
|
13
|
+
export declare const HEADING_ELEMENTS: Map<string, number>;
|
|
11
14
|
export declare class IslandModuleBuilder {
|
|
12
15
|
private readonly rootName;
|
|
13
16
|
private readonly pagePath;
|
|
@@ -16,14 +19,18 @@ export declare class IslandModuleBuilder {
|
|
|
16
19
|
private readonly consts;
|
|
17
20
|
private readonly sideEffects;
|
|
18
21
|
private readonly order;
|
|
22
|
+
private readonly headingSlugs;
|
|
19
23
|
readonly usedBindings: Map<string, Binding>;
|
|
20
24
|
readonly usedConsts: Set<string>;
|
|
21
25
|
readonly errors: IslandError[];
|
|
22
|
-
|
|
26
|
+
readonly headings: IslandHeading[];
|
|
27
|
+
constructor(rootName: string, pagePath: string, bindings: Map<string, Binding>, undeclared: Map<string, string>, consts: Map<string, ConstEntry>, sideEffects: ReadonlyMap<string, unknown>, order: readonly string[], headingSlugs: SlugDeduplicator);
|
|
23
28
|
private url;
|
|
24
29
|
private fail;
|
|
25
30
|
private insideRoot;
|
|
26
31
|
element(node: JsxNode): JSXElement | JSXFragment | undefined;
|
|
32
|
+
private addHeadingId;
|
|
33
|
+
private headingTitle;
|
|
27
34
|
private attribute;
|
|
28
35
|
private propFailure;
|
|
29
36
|
private intrinsic;
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { jsx as jsxHandlers, toJs } from 'estree-util-to-js';
|
|
2
2
|
import { parseInlineStyle } from '../../parse-inline-style.js';
|
|
3
|
+
import { safeCleanHeadingId, slugify } from '../../slugify.js';
|
|
4
|
+
import { getTableOfContentsTitle } from '../lib/remark-utils.js';
|
|
5
|
+
import { HEADING_LEVELS } from '../plugins/remark/remarkComponentIds.js';
|
|
3
6
|
import { resolveRelativeUrl } from '../plugins/remark/remarkResolveRelativeLinks.js';
|
|
4
7
|
import { allowedComponents } from '../utils.js';
|
|
5
8
|
import { bindingHead, lineOf } from './island-bindings.js';
|
|
@@ -101,9 +104,14 @@ const unravel = (nodes) => nodes.flatMap((node) => node.type === 'paragraph' &&
|
|
|
101
104
|
node.children.every((child) => isJsxPhrasing(child) || (child.type === 'text' && /^[\t\n\v\f\r ]*$/.test(child.value)))
|
|
102
105
|
? node.children.filter((child) => child.type !== 'text' || !/^[\t\r\n ]+$/.test(child.value))
|
|
103
106
|
: [node]);
|
|
107
|
+
export const claimHeadingSlug = (slugs, title, explicitId) => {
|
|
108
|
+
const base = (explicitId === undefined ? undefined : safeCleanHeadingId(explicitId)) || slugify(title);
|
|
109
|
+
return base ? slugs.claim(base) : undefined;
|
|
110
|
+
};
|
|
111
|
+
export const HEADING_ELEMENTS = new Map(HEADING_LEVELS.map((level) => [`h${level}`, level]));
|
|
104
112
|
const truncate = (value, max = 40) => value.length > max ? `${value.slice(0, max - 1)}…` : value;
|
|
105
113
|
export class IslandModuleBuilder {
|
|
106
|
-
constructor(rootName, pagePath, bindings, undeclared, consts, sideEffects, order) {
|
|
114
|
+
constructor(rootName, pagePath, bindings, undeclared, consts, sideEffects, order, headingSlugs) {
|
|
107
115
|
this.rootName = rootName;
|
|
108
116
|
this.pagePath = pagePath;
|
|
109
117
|
this.bindings = bindings;
|
|
@@ -111,9 +119,11 @@ export class IslandModuleBuilder {
|
|
|
111
119
|
this.consts = consts;
|
|
112
120
|
this.sideEffects = sideEffects;
|
|
113
121
|
this.order = order;
|
|
122
|
+
this.headingSlugs = headingSlugs;
|
|
114
123
|
this.usedBindings = new Map();
|
|
115
124
|
this.usedConsts = new Set();
|
|
116
125
|
this.errors = [];
|
|
126
|
+
this.headings = [];
|
|
117
127
|
}
|
|
118
128
|
url(value, isPageLink) {
|
|
119
129
|
return literal(resolveRelativeUrl(this.pagePath, value, isPageLink));
|
|
@@ -168,8 +178,63 @@ export class IslandModuleBuilder {
|
|
|
168
178
|
if (converted)
|
|
169
179
|
attributes.push(converted);
|
|
170
180
|
}
|
|
181
|
+
const headingLevel = HEADING_ELEMENTS.get(name);
|
|
182
|
+
if (headingLevel !== undefined)
|
|
183
|
+
this.addHeadingId(node, headingLevel, attributes);
|
|
171
184
|
return jsxElement(name, attributes, this.children(node.children));
|
|
172
185
|
}
|
|
186
|
+
addHeadingId(node, depth, attributes) {
|
|
187
|
+
var _a;
|
|
188
|
+
const index = attributes.findIndex((attribute) => attribute.name.type === 'JSXIdentifier' && attribute.name.name === 'id');
|
|
189
|
+
let explicitId;
|
|
190
|
+
if (index !== -1) {
|
|
191
|
+
const value = (_a = attributes[index]) === null || _a === void 0 ? void 0 : _a.value;
|
|
192
|
+
if ((value === null || value === void 0 ? void 0 : value.type) !== 'JSXExpressionContainer' ||
|
|
193
|
+
value.expression.type !== 'Literal' ||
|
|
194
|
+
typeof value.expression.value !== 'string') {
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
explicitId = value.expression.value;
|
|
198
|
+
}
|
|
199
|
+
const title = this.headingTitle(node);
|
|
200
|
+
const slug = claimHeadingSlug(this.headingSlugs, title, explicitId);
|
|
201
|
+
if (slug === undefined)
|
|
202
|
+
return;
|
|
203
|
+
const id = jsxAttribute('id', literal(safeCleanHeadingId(slug)));
|
|
204
|
+
if (index === -1)
|
|
205
|
+
attributes.unshift(id);
|
|
206
|
+
else
|
|
207
|
+
attributes[index] = id;
|
|
208
|
+
if (title.trim())
|
|
209
|
+
this.headings.push({ title, slug, depth });
|
|
210
|
+
}
|
|
211
|
+
headingTitle(node) {
|
|
212
|
+
if (!('children' in node))
|
|
213
|
+
return getTableOfContentsTitle(node);
|
|
214
|
+
return node.children
|
|
215
|
+
.map((child, index, children) => {
|
|
216
|
+
var _a, _b, _c;
|
|
217
|
+
if (child.type !== 'mdxTextExpression' && child.type !== 'mdxFlowExpression') {
|
|
218
|
+
return 'children' in child
|
|
219
|
+
? this.headingTitle(child)
|
|
220
|
+
: getTableOfContentsTitle(child, index, children);
|
|
221
|
+
}
|
|
222
|
+
const statement = (_b = (_a = child.data) === null || _a === void 0 ? void 0 : _a.estree) === null || _b === void 0 ? void 0 : _b.body[0];
|
|
223
|
+
if ((statement === null || statement === void 0 ? void 0 : statement.type) !== 'ExpressionStatement')
|
|
224
|
+
return '';
|
|
225
|
+
const converted = toStaticExpression(statement.expression, this.consts, new Set());
|
|
226
|
+
if (!converted.ok)
|
|
227
|
+
return '';
|
|
228
|
+
const expression = converted.expression.type === 'Identifier'
|
|
229
|
+
? (_c = this.consts.get(converted.expression.name)) === null || _c === void 0 ? void 0 : _c.expression
|
|
230
|
+
: converted.expression;
|
|
231
|
+
return (expression === null || expression === void 0 ? void 0 : expression.type) === 'Literal' &&
|
|
232
|
+
(typeof expression.value === 'string' || typeof expression.value === 'number')
|
|
233
|
+
? String(expression.value)
|
|
234
|
+
: '';
|
|
235
|
+
})
|
|
236
|
+
.join('');
|
|
237
|
+
}
|
|
173
238
|
attribute(node, elementName, attribute) {
|
|
174
239
|
var _a;
|
|
175
240
|
const at = attribute.position ? attribute : node;
|
|
@@ -276,8 +341,12 @@ export class IslandModuleBuilder {
|
|
|
276
341
|
return [
|
|
277
342
|
jsxElement('blockquote', [], wrap(unravel(node.children).map((child) => { var _a; return (_a = this.child(child)) !== null && _a !== void 0 ? _a : []; }))),
|
|
278
343
|
];
|
|
279
|
-
case 'heading':
|
|
280
|
-
|
|
344
|
+
case 'heading': {
|
|
345
|
+
const attributes = [];
|
|
346
|
+
if (HEADING_LEVELS.includes(node.depth))
|
|
347
|
+
this.addHeadingId(node, node.depth, attributes);
|
|
348
|
+
return [this.intrinsic(`h${node.depth}`, node.children, attributes)];
|
|
349
|
+
}
|
|
281
350
|
case 'link': {
|
|
282
351
|
const attributes = [jsxAttribute('href', this.url(node.url, true))];
|
|
283
352
|
if (node.title)
|
|
@@ -42,6 +42,7 @@ const placeholder = (type, id) => ({
|
|
|
42
42
|
attributes: [{ type: 'mdxJsxAttribute', name: 'id', value: id }],
|
|
43
43
|
children: [],
|
|
44
44
|
});
|
|
45
|
+
const flowPlaceholder = (id, headings = []) => (Object.assign(Object.assign({}, placeholder('mdxJsxFlowElement', id)), (headings.length > 0 && { data: { islandHeadings: headings } })));
|
|
45
46
|
const isIslandImport = (source, importer, options) => {
|
|
46
47
|
if (isDeclaredPackageImport(source, options.packageNames))
|
|
47
48
|
return true;
|
|
@@ -98,11 +99,13 @@ export const remarkPackageIslands = (options) => (tree) => {
|
|
|
98
99
|
if (own.roots.length === 0)
|
|
99
100
|
return;
|
|
100
101
|
const ids = new Map();
|
|
102
|
+
const headings = new Map();
|
|
101
103
|
const buildErrors = [];
|
|
102
104
|
own.roots.forEach((root, index) => {
|
|
103
105
|
var _a, _b, _c, _d, _e;
|
|
104
106
|
const id = (_b = (_a = plan.roots[index]) === null || _a === void 0 ? void 0 : _a.id) !== null && _b !== void 0 ? _b : root.id;
|
|
105
107
|
ids.set(root.node, id);
|
|
108
|
+
headings.set(root.node, root.headings);
|
|
106
109
|
if (!options.islandHtml)
|
|
107
110
|
return;
|
|
108
111
|
const entry = options.islandHtml[id];
|
|
@@ -134,9 +137,9 @@ export const remarkPackageIslands = (options) => (tree) => {
|
|
|
134
137
|
if (node.type === 'paragraph') {
|
|
135
138
|
const only = soleParagraphChild(node);
|
|
136
139
|
const id = only ? ids.get(only) : undefined;
|
|
137
|
-
if (id === undefined)
|
|
140
|
+
if (id === undefined || !only)
|
|
138
141
|
return;
|
|
139
|
-
parent.children[index] =
|
|
142
|
+
parent.children[index] = flowPlaceholder(id, headings.get(only));
|
|
140
143
|
return SKIP;
|
|
141
144
|
}
|
|
142
145
|
const id = ids.get(node);
|
|
@@ -145,7 +148,7 @@ export const remarkPackageIslands = (options) => (tree) => {
|
|
|
145
148
|
parent.children[index] =
|
|
146
149
|
node.type === 'mdxJsxTextElement'
|
|
147
150
|
? placeholder('mdxJsxTextElement', id)
|
|
148
|
-
:
|
|
151
|
+
: flowPlaceholder(id, headings.get(node));
|
|
149
152
|
return SKIP;
|
|
150
153
|
});
|
|
151
154
|
removeIslandImports(tree, options);
|
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
import type { Parent } from 'mdast';
|
|
2
2
|
import type { MdxJsxFlowElement, MdxJsxTextElement } from 'mdast-util-mdx-jsx';
|
|
3
|
+
declare module 'mdast-util-mdx-jsx' {
|
|
4
|
+
interface MdxJsxFlowElementData {
|
|
5
|
+
islandHeadings?: IslandHeading[];
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
export type IslandHeading = {
|
|
9
|
+
title: string;
|
|
10
|
+
slug: string;
|
|
11
|
+
depth: number;
|
|
12
|
+
};
|
|
3
13
|
export type IslandImport = {
|
|
4
14
|
local: string;
|
|
5
15
|
pkg: string;
|
|
@@ -28,6 +38,7 @@ export type IslandRoot = {
|
|
|
28
38
|
name: string;
|
|
29
39
|
node: MdxJsxFlowElement | MdxJsxTextElement;
|
|
30
40
|
parent: Parent;
|
|
41
|
+
headings: IslandHeading[];
|
|
31
42
|
};
|
|
32
43
|
export type ExtractPackageIslandsResult = {
|
|
33
44
|
islands: IslandSpec[];
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export const createSlugDeduplicator = () => {
|
|
2
|
+
const seen = new Map();
|
|
3
|
+
return {
|
|
4
|
+
claim: (slug) => {
|
|
5
|
+
var _a;
|
|
6
|
+
const count = (_a = seen.get(slug)) !== null && _a !== void 0 ? _a : 0;
|
|
7
|
+
seen.set(slug, count + 1);
|
|
8
|
+
if (count === 0)
|
|
9
|
+
return slug;
|
|
10
|
+
let suffix = count + 1;
|
|
11
|
+
let suffixed = `${slug}-${suffix}`;
|
|
12
|
+
while (seen.has(suffixed)) {
|
|
13
|
+
suffix += 1;
|
|
14
|
+
suffixed = `${slug}-${suffix}`;
|
|
15
|
+
}
|
|
16
|
+
seen.set(suffixed, 1);
|
|
17
|
+
return suffixed;
|
|
18
|
+
},
|
|
19
|
+
reserve: (slug) => {
|
|
20
|
+
var _a;
|
|
21
|
+
seen.set(slug, ((_a = seen.get(slug)) !== null && _a !== void 0 ? _a : 0) + 1);
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
};
|