@mintlify/common 1.0.1021 → 1.0.1022

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.
@@ -15,6 +15,7 @@ export * from './remarkSplitTabs.js';
15
15
  export * from './remarkComponentIds.js';
16
16
  export * from './remarkMdxExtractPanel.js';
17
17
  export * from './remarkValidateSteps.js';
18
+ export * from './remarkValidateVisibility.js';
18
19
  export * from './remarkValidateTabs.js';
19
20
  export * from './remarkVideo.js';
20
21
  export * from './remarkExtractMultiView.js';
@@ -15,6 +15,7 @@ export * from './remarkSplitTabs.js';
15
15
  export * from './remarkComponentIds.js';
16
16
  export * from './remarkMdxExtractPanel.js';
17
17
  export * from './remarkValidateSteps.js';
18
+ export * from './remarkValidateVisibility.js';
18
19
  export * from './remarkValidateTabs.js';
19
20
  export * from './remarkVideo.js';
20
21
  export * from './remarkExtractMultiView.js';
@@ -1,6 +1,6 @@
1
1
  import remarkStringify from 'remark-stringify';
2
2
  import { unified } from 'unified';
3
- import { visit } from 'unist-util-visit';
3
+ import { SKIP, visit } from 'unist-util-visit';
4
4
  import { coreRemarkMdxPlugins } from '../../remark.js';
5
5
  export const remarkExtractMultiView = (mdxExtracts) => {
6
6
  return (tree) => {
@@ -10,7 +10,10 @@ export const remarkExtractMultiView = (mdxExtracts) => {
10
10
  if ('attributes' in sanitized && Array.isArray(sanitized.attributes)) {
11
11
  sanitized.attributes = sanitized.attributes.map((attr) => {
12
12
  if (attr.value != null && typeof attr.value !== 'string') {
13
- return Object.assign(Object.assign({}, attr), { value: String(attr.value) });
13
+ const raw = 'value' in attr.value && typeof attr.value.value === 'string'
14
+ ? attr.value.value
15
+ : String(attr.value);
16
+ return Object.assign(Object.assign({}, attr), { value: raw });
14
17
  }
15
18
  return attr;
16
19
  });
@@ -40,7 +43,9 @@ export const remarkExtractMultiView = (mdxExtracts) => {
40
43
  return attribute.value;
41
44
  }
42
45
  if (typeof attribute.value === 'object' && 'value' in attribute.value) {
43
- return String(attribute.value.value);
46
+ const raw = String(attribute.value.value).trim();
47
+ const quoted = raw.match(/^(["'`])([\s\S]*)\1$/);
48
+ return quoted ? quoted[2] : raw;
44
49
  }
45
50
  return undefined;
46
51
  };
@@ -59,7 +64,7 @@ export const remarkExtractMultiView = (mdxExtracts) => {
59
64
  console.warn(`\n⚠️ Duplicate View title: "${title}"\n` +
60
65
  ` Use one View component per title per page. Duplicate Views are ignored.\n` +
61
66
  ` Learn more: https://www.mintlify.com/docs/components/view\n`);
62
- return;
67
+ return SKIP;
63
68
  }
64
69
  // Extract the id attribute (set by remarkComponentIds or explicit) so the
65
70
  // client can match URL hashes back to the correct view for shareable links.
@@ -79,10 +84,20 @@ export const remarkExtractMultiView = (mdxExtracts) => {
79
84
  }
80
85
  multiViews.push(viewItem);
81
86
  }
87
+ else {
88
+ console.warn(`\n⚠️ View component is missing a title.\n` +
89
+ ` Every View needs a non-empty string title; a View without one is never rendered.\n` +
90
+ ` Learn more: https://www.mintlify.com/docs/components/view\n`);
91
+ }
82
92
  }
83
93
  });
84
- if (mdxExtracts && multiViews.length) {
85
- mdxExtracts.multiViewItems = multiViews;
94
+ if (mdxExtracts) {
95
+ if (multiViews.length) {
96
+ mdxExtracts.multiViewItems = multiViews;
97
+ }
98
+ else {
99
+ delete mdxExtracts.multiViewItems;
100
+ }
86
101
  }
87
102
  return tree;
88
103
  };
@@ -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").Link | import("mdast").Delete | import("mdast").Code | import("mdast").Blockquote | import("mdast").Break | import("mdast").Definition | import("mdast").Emphasis | import("mdast").FootnoteDefinition | import("mdast").FootnoteReference | import("mdast").Heading | 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").Text | 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-mdx").MdxJsxFlowElement | import("mdast-util-mdx").MdxJsxTextElement | import("mdast-util-mdxjs-esm").MdxjsEsm;
4
+ }) => (tree: Root) => Root | import("mdast").Link | import("mdast").Delete | import("mdast").Code | 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").Heading | 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").Text | 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,2 @@
1
+ import type { Root } from 'mdast';
2
+ export declare const remarkValidateVisibility: () => (tree: Root) => void;
@@ -0,0 +1,15 @@
1
+ import { visit } from 'unist-util-visit';
2
+ import { isVisibilityElement, resolveVisibilityFor } from './remarkVisibilityForMarkdown.js';
3
+ export const remarkValidateVisibility = () => (tree) => {
4
+ visit(tree, (node) => {
5
+ if (!isVisibilityElement(node))
6
+ return;
7
+ const resolution = resolveVisibilityFor(node);
8
+ if (resolution.kind === 'invalid') {
9
+ console.warn(`<Visibility for="${resolution.raw}"> has an unknown audience — expected "humans" or "agents". The content will be hidden from humans.`);
10
+ }
11
+ if (resolution.kind === 'missing') {
12
+ console.warn('<Visibility> is missing its "for" audience — expected "humans" or "agents". The content will be hidden from humans.');
13
+ }
14
+ });
15
+ };
@@ -1,2 +1,21 @@
1
1
  import type { Root } from 'mdast';
2
+ import type { MdxJsxFlowElement, MdxJsxTextElement } from 'mdast-util-mdx-jsx';
3
+ type MdxJsxElement = MdxJsxFlowElement | MdxJsxTextElement;
4
+ export declare function isVisibilityElement(node: {
5
+ type: string;
6
+ name?: string | null;
7
+ }): boolean;
8
+ export type VisibilityResolution = {
9
+ kind: 'audience';
10
+ audience: 'humans' | 'agents';
11
+ } | {
12
+ kind: 'invalid';
13
+ raw: string;
14
+ } | {
15
+ kind: 'dynamic';
16
+ } | {
17
+ kind: 'missing';
18
+ };
19
+ export declare function resolveVisibilityFor(node: MdxJsxElement): VisibilityResolution;
2
20
  export declare const remarkVisibilityForMarkdown: () => (tree: Root) => void;
21
+ export {};
@@ -1,26 +1,52 @@
1
+ export function isVisibilityElement(node) {
2
+ return ((node.type === 'mdxJsxFlowElement' || node.type === 'mdxJsxTextElement') &&
3
+ node.name === 'Visibility');
4
+ }
1
5
  function isMdxJsxElement(node) {
2
6
  return node.type === 'mdxJsxFlowElement' || node.type === 'mdxJsxTextElement';
3
7
  }
4
- function getVisibilityFor(node) {
8
+ export function resolveVisibilityFor(node) {
9
+ var _a;
10
+ let invalidRaw;
11
+ let sawDynamic = false;
12
+ let sawAttribute = false;
5
13
  for (const attr of node.attributes) {
6
14
  if (attr.type !== 'mdxJsxAttribute' || attr.name !== 'for')
7
15
  continue;
16
+ sawAttribute = true;
8
17
  if (typeof attr.value === 'string') {
9
- if (attr.value === 'humans' || attr.value === 'agents')
10
- return attr.value;
18
+ if (attr.value === 'humans' || attr.value === 'agents') {
19
+ return { kind: 'audience', audience: attr.value };
20
+ }
21
+ invalidRaw !== null && invalidRaw !== void 0 ? invalidRaw : (invalidRaw = attr.value);
11
22
  continue;
12
23
  }
13
- if (attr.value &&
14
- typeof attr.value === 'object' &&
15
- 'value' in attr.value &&
16
- typeof attr.value.value === 'string') {
17
- const raw = attr.value.value.trim();
18
- const quoted = raw.match(/^(["'])(humans|agents)\1$/);
19
- if (quoted)
20
- return quoted[2];
24
+ if (attr.value && typeof attr.value === 'object') {
25
+ if ('value' in attr.value && typeof attr.value.value === 'string') {
26
+ const raw = attr.value.value.trim();
27
+ const quoted = raw.match(/^(["'`])((?:\\.|(?!\1)[^\\])*)\1$/);
28
+ if (quoted) {
29
+ const inner = (_a = quoted[2]) !== null && _a !== void 0 ? _a : '';
30
+ const isTemplateWithInterpolation = quoted[1] === '`' && inner.includes('${');
31
+ if (!isTemplateWithInterpolation) {
32
+ if (inner === 'humans' || inner === 'agents') {
33
+ return { kind: 'audience', audience: inner };
34
+ }
35
+ invalidRaw !== null && invalidRaw !== void 0 ? invalidRaw : (invalidRaw = inner);
36
+ continue;
37
+ }
38
+ }
39
+ }
40
+ sawDynamic = true;
21
41
  }
22
42
  }
23
- return undefined;
43
+ if (invalidRaw !== undefined)
44
+ return { kind: 'invalid', raw: invalidRaw };
45
+ if (sawDynamic)
46
+ return { kind: 'dynamic' };
47
+ if (sawAttribute)
48
+ return { kind: 'missing' };
49
+ return { kind: 'missing' };
24
50
  }
25
51
  // `export * from` is intentionally ignored: it exposes no statically-knowable
26
52
  // names and creates no page-local JSX bindings in MDX, so there is nothing to
@@ -120,12 +146,15 @@ function collectJsxReferences(node) {
120
146
  // `visibleNames`. Usage inside an agents block counts as visible since that
121
147
  // content survives into the markdown output.
122
148
  function collectJsxUsage(nodes, insideHumans, hiddenNames, visibleNames) {
123
- var _a, _b;
149
+ var _a, _b, _c;
124
150
  for (const node of nodes) {
125
151
  let childInsideHumans = insideHumans;
126
152
  if (isMdxJsxElement(node)) {
127
153
  if (node.name === 'Visibility') {
128
- if (getVisibilityFor(node) === 'humans')
154
+ const resolution = resolveVisibilityFor(node);
155
+ const isHidden = resolution.kind === 'invalid' ||
156
+ (resolution.kind === 'audience' && resolution.audience === 'humans');
157
+ if (isHidden)
129
158
  childInsideHumans = true;
130
159
  }
131
160
  else {
@@ -140,6 +169,15 @@ function collectJsxUsage(nodes, insideHumans, hiddenNames, visibleNames) {
140
169
  if (node.type === 'mdxFlowExpression' || node.type === 'mdxTextExpression') {
141
170
  collectEstreeJsxNames((_b = node.data) === null || _b === void 0 ? void 0 : _b.estree, insideHumans ? hiddenNames : visibleNames);
142
171
  }
172
+ // Attribute-embedded usages like `<Card icon={<Logo />}>` also live in estree.
173
+ if (isMdxJsxElement(node)) {
174
+ for (const attr of node.attributes) {
175
+ const expression = attr.type === 'mdxJsxAttribute' ? attr.value : attr;
176
+ if (expression && typeof expression === 'object' && 'data' in expression) {
177
+ collectEstreeJsxNames((_c = expression.data) === null || _c === void 0 ? void 0 : _c.estree, insideHumans ? hiddenNames : visibleNames);
178
+ }
179
+ }
180
+ }
143
181
  if ('children' in node && Array.isArray(node.children)) {
144
182
  collectJsxUsage(node.children, childInsideHumans, hiddenNames, visibleNames);
145
183
  }
@@ -156,13 +194,17 @@ function transformNode(node, esmToStrip) {
156
194
  return esmToStrip.has(node) ? [] : [node];
157
195
  }
158
196
  if (isMdxJsxElement(node) && node.name === 'Visibility') {
159
- const audience = getVisibilityFor(node);
160
- if (audience === 'humans') {
197
+ const resolution = resolveVisibilityFor(node);
198
+ if (resolution.kind === 'audience' && resolution.audience === 'humans') {
161
199
  return [];
162
200
  }
163
- if (audience === 'agents') {
201
+ if (resolution.kind === 'audience' && resolution.audience === 'agents') {
164
202
  return transformChildren(node.children, esmToStrip);
165
203
  }
204
+ if (resolution.kind === 'invalid') {
205
+ console.warn(`<Visibility for="${resolution.raw}"> has an unknown audience — expected "humans" or "agents". The content was removed from the markdown output.`);
206
+ return [];
207
+ }
166
208
  }
167
209
  if ('children' in node && Array.isArray(node.children)) {
168
210
  const next = transformChildren(node.children, esmToStrip);
@@ -9,7 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  };
10
10
  import { serialize } from '@mintlify/mdx/server';
11
11
  import { getTailwindSelectors } from '../../css/tailwind.js';
12
- import { getMDXOptions, remarkMdxRemoveJs, remarkExpandContent, remarkSplitCodeGroup, remarkSplitTabs, remarkValidateSteps, remarkValidateTabs, } from '../../index.js';
12
+ import { getMDXOptions, remarkMdxRemoveJs, remarkExpandContent, remarkSplitCodeGroup, remarkSplitTabs, remarkValidateSteps, remarkValidateVisibility, remarkValidateTabs, } from '../../index.js';
13
13
  import { codeStylingToThemeOrThemes } from '../getCodeStyling.js';
14
14
  import { preprocessCustomHeadingIds } from '../preprocessCustomHeadingIds.js';
15
15
  import { replaceVariables } from '../replaceVariables.js';
@@ -32,7 +32,12 @@ export function getMdx(_a) {
32
32
  path,
33
33
  };
34
34
  let mdxExtracts = {};
35
- let plugins = [remarkValidateSteps, remarkValidateTabs, ...remarkPlugins];
35
+ let plugins = [
36
+ remarkValidateSteps,
37
+ remarkValidateTabs,
38
+ remarkValidateVisibility,
39
+ ...remarkPlugins,
40
+ ];
36
41
  if (pageType === 'pdf') {
37
42
  plugins = [...plugins, remarkExpandContent, remarkSplitCodeGroup, remarkSplitTabs];
38
43
  }