@mintlify/cli 4.0.1751 → 4.0.1753

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.
@@ -1,18 +1,21 @@
1
+ import { htmlVoidElements } from 'html-void-elements';
1
2
  import { maskNonMarkup } from '../../mdx.js';
2
- const VOID_TAG = /<(br|hr|img)(?=[\s/>])((?:"[^"]*"|'[^']*'|\{[^{}]*\}|[^<>"'{}])*?)(\/?)>/g;
3
+ const VOID_TAG_NAMES = htmlVoidElements.filter((tag) => tag !== 'image');
4
+ const ATTRIBUTE = String.raw `"[^"]*"|'[^']*'|\{[^{}]*\}|[^<>"'{}]`;
5
+ const VOID_TAG = new RegExp(String.raw `<(${VOID_TAG_NAMES.join('|')})(?=[\s/>])(?:${ATTRIBUTE})*?(\/?)>`, 'g');
3
6
  export const voidTags = {
4
7
  id: 'void-tags',
5
8
  group: 'content',
6
9
  severity: 'error',
7
10
  scope: 'file',
8
- description: "self-close void HTML tags (<br>, <hr>, <img>); MDX can't parse them unclosed",
11
+ description: "self-close void HTML tags (<br>, <img>, <source>, …); MDX can't parse them unclosed",
9
12
  raw: true,
10
13
  check: ({ content }) => {
11
14
  var _a, _b;
12
15
  const masked = maskNonMarkup(content);
13
16
  const issues = [];
14
17
  for (const match of masked.matchAll(VOID_TAG)) {
15
- if (match[3])
18
+ if (match[2])
16
19
  continue;
17
20
  const start = match.index;
18
21
  const end = start + match[0].length;
@@ -6085,7 +6085,25 @@ var DATABASE_ATTRS = [
6085
6085
  name: "view",
6086
6086
  type: "string",
6087
6087
  options: DATABASE_VIEW_OPTIONS,
6088
- description: "Table or board. Omitted means table."
6088
+ description: "Table or board. Omitted or unknown means table."
6089
+ },
6090
+ {
6091
+ name: "sort",
6092
+ type: "string",
6093
+ placeholder: "-Due, Name",
6094
+ description: "Comma-separated property names. A leading - sorts descending."
6095
+ },
6096
+ {
6097
+ name: "filter",
6098
+ type: "string",
6099
+ placeholder: 'Status != "Done" and Points > 3',
6100
+ description: "Formula that keeps the rows it is true for."
6101
+ },
6102
+ {
6103
+ name: "groupBy",
6104
+ type: "string",
6105
+ placeholder: "Status",
6106
+ description: "Property name to group rows by."
6089
6107
  }
6090
6108
  ];
6091
6109
  var UPDATE_ATTRS = [
@@ -12746,10 +12764,11 @@ function handleTree(node) {
12746
12764
  attrs: Object.assign({ treeData: parseTreeChildren(node) }, extraTreeAttrs)
12747
12765
  };
12748
12766
  }
12767
+ var DATABASE_VIEW_PROPS = ["view", "sort", "filter", "groupBy"];
12749
12768
  function handleDatabase(node, ctx) {
12750
12769
  var _a;
12751
12770
  const parsed = parseMdxAttributes(node.attributes);
12752
- const isValid = ctx.databases === true && !!((_a = ctx.schema) !== null && _a !== void 0 ? _a : mintlifySchema).nodes[BLOCK_TYPES.database] && node.children.length === 0 && !(EXPRESSION_ATTRS_KEY in parsed) && !(NAMED_EXPRESSION_ATTRS_KEY in parsed) && isDatabaseId(parsed.id) && (parsed.view === void 0 || isDatabaseView(parsed.view));
12771
+ const isValid = ctx.databases === true && !!((_a = ctx.schema) !== null && _a !== void 0 ? _a : mintlifySchema).nodes[BLOCK_TYPES.database] && node.children.length === 0 && !(EXPRESSION_ATTRS_KEY in parsed) && !(NAMED_EXPRESSION_ATTRS_KEY in parsed) && isDatabaseId(parsed.id) && DATABASE_VIEW_PROPS.every((key) => parsed[key] === void 0 || typeof parsed[key] === "string");
12753
12772
  if (!isValid)
12754
12773
  return { type: BLOCK_TYPES.unknownTag, attrs: { mdxJsxNode: node } };
12755
12774
  return { type: BLOCK_TYPES.database, attrs: partitionAttrs(parsed, DATABASE_ATTRS) };
@@ -14120,6 +14139,18 @@ var escapeAttributeValue = (value) => value.replace(/[&"<>\n\r`~]/g, (char) => {
14120
14139
  var _a;
14121
14140
  return (_a = ATTRIBUTE_VALUE_ESCAPES[char]) !== null && _a !== void 0 ? _a : char;
14122
14141
  });
14142
+ var READABLE_ESCAPES = Object.assign(Object.assign({}, ATTRIBUTE_VALUE_ESCAPES), { "'": "&#x27;", "*": "&#x2A;", "{": "&#x7B;", "}": "&#x7D;" });
14143
+ var READABLE_UNSAFE = /&(?=#?[A-Za-z0-9]+;)|<(?=[A-Za-z/!?])|(?<=\/)\*|\*(?=\/)|[\n\r`~{}]/g;
14144
+ function serializeReadableJsxAttribute(key, value) {
14145
+ if (typeof value !== "string")
14146
+ return null;
14147
+ const quote = value.includes('"') ? "'" : '"';
14148
+ const escaped = value.replace(new RegExp(`${READABLE_UNSAFE.source}|${quote}`, "g"), (char) => {
14149
+ var _a;
14150
+ return (_a = READABLE_ESCAPES[char]) !== null && _a !== void 0 ? _a : char;
14151
+ });
14152
+ return `${key}=${quote}${escaped}${quote}`;
14153
+ }
14123
14154
  function serializeLiteralJsxAttribute(attrs2, key, value) {
14124
14155
  return typeof value === "string" ? `${key}="${escapeAttributeValue(value)}"` : serializeJsxAttribute(attrs2, key, value);
14125
14156
  }
@@ -15715,7 +15746,10 @@ function writeTreeChild(state, child) {
15715
15746
  state.ensureNewLine();
15716
15747
  }
15717
15748
  function renderDatabase(state, node) {
15718
- const props = ["id", "view"].map((key) => serializeJsxAttribute(node.attrs, key, node.attrs[key])).filter(Boolean);
15749
+ const props = [
15750
+ serializeJsxAttribute(node.attrs, "id", node.attrs.id),
15751
+ ...["view", "sort", "filter", "groupBy"].map((key) => serializeReadableJsxAttribute(key, node.attrs[key]))
15752
+ ].filter(Boolean);
15719
15753
  const propString = props.length > 0 ? ` ${props.join(" ")}` : "";
15720
15754
  state.write(`<Database${propString}${extraAttrsPropString(node.attrs, serializeLiteralJsxAttribute)} />`);
15721
15755
  state.closeBlock();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mintlify/cli",
3
- "version": "4.0.1751",
3
+ "version": "4.0.1753",
4
4
  "description": "The Mintlify CLI",
5
5
  "engines": {
6
6
  "node": ">=18.0.0"
@@ -45,18 +45,19 @@
45
45
  },
46
46
  "dependencies": {
47
47
  "@inquirer/prompts": "7.9.0",
48
- "@mintlify/common": "1.0.1312",
49
- "@mintlify/link-rot": "3.0.1547",
48
+ "@mintlify/common": "1.0.1313",
49
+ "@mintlify/link-rot": "3.0.1548",
50
50
  "@mintlify/models": "0.0.379",
51
- "@mintlify/og": "0.0.111",
52
- "@mintlify/prebuild": "1.0.1482",
53
- "@mintlify/previewing": "4.0.1565",
51
+ "@mintlify/og": "0.0.112",
52
+ "@mintlify/prebuild": "1.0.1483",
53
+ "@mintlify/previewing": "4.0.1566",
54
54
  "@mintlify/validation": "0.1.944",
55
55
  "adm-zip": "0.6.0",
56
56
  "chalk": "5.2.0",
57
57
  "color": "4.2.3",
58
58
  "detect-port": "1.5.1",
59
59
  "fs-extra": "11.2.0",
60
+ "html-void-elements": "3.0.0",
60
61
  "ink": "6.3.0",
61
62
  "inquirer": "12.3.0",
62
63
  "js-yaml": "4.3.1",
@@ -84,7 +85,7 @@
84
85
  "keytar": "7.9.0"
85
86
  },
86
87
  "devDependencies": {
87
- "@mintlify/editor": "0.0.585",
88
+ "@mintlify/editor": "0.0.586",
88
89
  "@mintlify/ts-config": "2.0.2",
89
90
  "@tsconfig/recommended": "1.0.2",
90
91
  "@types/detect-port": "1.3.2",
@@ -103,5 +104,5 @@
103
104
  "vitest": "2.1.9",
104
105
  "vitest-mock-process": "1.0.4"
105
106
  },
106
- "gitHead": "55c38544e0b8fb3fadabe8eeaec5aaa6c5312a1d"
107
+ "gitHead": "611b47d227dd5bf869576f8e8989f8a20f743b45"
107
108
  }
@@ -1,20 +1,28 @@
1
+ import { htmlVoidElements } from 'html-void-elements';
2
+
1
3
  import { maskNonMarkup } from '../../mdx.js';
2
4
  import type { FileRule, FileFinding } from '../../types.js';
3
5
 
4
- const VOID_TAG = /<(br|hr|img)(?=[\s/>])((?:"[^"]*"|'[^']*'|\{[^{}]*\}|[^<>"'{}])*?)(\/?)>/g;
6
+ const VOID_TAG_NAMES = htmlVoidElements.filter((tag) => tag !== 'image');
7
+ const ATTRIBUTE = String.raw`"[^"]*"|'[^']*'|\{[^{}]*\}|[^<>"'{}]`;
8
+ const VOID_TAG = new RegExp(
9
+ String.raw`<(${VOID_TAG_NAMES.join('|')})(?=[\s/>])(?:${ATTRIBUTE})*?(\/?)>`,
10
+ 'g'
11
+ );
5
12
 
6
13
  export const voidTags: FileRule = {
7
14
  id: 'void-tags',
8
15
  group: 'content',
9
16
  severity: 'error',
10
17
  scope: 'file',
11
- description: "self-close void HTML tags (<br>, <hr>, <img>); MDX can't parse them unclosed",
18
+ description:
19
+ "self-close void HTML tags (<br>, <img>, <source>, …); MDX can't parse them unclosed",
12
20
  raw: true,
13
21
  check: ({ content }) => {
14
22
  const masked = maskNonMarkup(content);
15
23
  const issues: FileFinding[] = [];
16
24
  for (const match of masked.matchAll(VOID_TAG)) {
17
- if (match[3]) continue;
25
+ if (match[2]) continue;
18
26
  const start = match.index;
19
27
  const end = start + match[0].length;
20
28
  if (new RegExp(`^\\s*</${match[1]}\\s*>`).test(masked.slice(end))) continue;