jamdesk 1.1.196 → 1.1.198

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 +1 @@
1
- {"version":3,"file":"frontmatter-utils.d.ts","sourceRoot":"","sources":["../../src/lib/frontmatter-utils.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CA8D7D;AAqBD;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG;IAExD,IAAI,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;KAAE,CAAC;IAC7B,OAAO,EAAE,MAAM,CAAC;CACjB,CAIA;AAMD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC"}
1
+ {"version":3,"file":"frontmatter-utils.d.ts","sourceRoot":"","sources":["../../src/lib/frontmatter-utils.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAkE7D;AAyFD;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG;IAExD,IAAI,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;KAAE,CAAC;IAC7B,OAAO,EAAE,MAAM,CAAC;CACjB,CAIA;AAMD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC"}
@@ -24,10 +24,15 @@ export function preprocessFrontmatter(content) {
24
24
  const body = content.slice(frontmatterEnd);
25
25
  // Process each line of frontmatter
26
26
  const lines = frontmatter.split('\n');
27
+ // Lines belonging to a previous key's multi-line value are VALUE TEXT, not
28
+ // key/value pairs, and must be left exactly as written.
29
+ const isContinuation = markContinuationLines(lines);
27
30
  const fixedLines = lines.map((line, i) => {
28
31
  // Skip empty lines and comments
29
32
  if (!line.trim() || line.trim().startsWith('#'))
30
33
  return line;
34
+ if (isContinuation[i])
35
+ return line;
31
36
  // Match key: value pattern (simple single-line values only).
32
37
  // The key may contain colon-segments (e.g. `og:title`, `twitter:card`,
33
38
  // `article:published_time`) so we split on the FIRST colon followed by
@@ -35,13 +40,13 @@ export function preprocessFrontmatter(content) {
35
40
  // A plain `[a-zA-Z_][a-zA-Z0-9_]*` key class stopped at the first colon,
36
41
  // misparsing `og:title: Social` as key=`og`, value=`title: Social`, then
37
42
  // quote-wrapping it into `og: "title: Social"` and destroying `og:title`.
38
- const match = line.match(/^(\s*)([a-zA-Z_][a-zA-Z0-9_.-]*(?::[a-zA-Z0-9_.-]+)*):\s*(.*)$/);
43
+ const match = line.match(KEY_LINE);
39
44
  if (!match)
40
45
  return line;
41
46
  const [, indent, key, value] = match;
42
47
  // Skip if value is empty, already quoted, or is a multi-line indicator
43
48
  // Multi-line indicators: | (literal), > (folded), with optional modifiers: |- |+ >- >+
44
- if (!value || value.startsWith('"') || value.startsWith("'") || /^[|>][-+]?$/.test(value)) {
49
+ if (!value || value.startsWith('"') || value.startsWith("'") || isBlockScalar(value)) {
45
50
  return line;
46
51
  }
47
52
  // Skip if value looks like a nested object or array
@@ -69,6 +74,77 @@ export function preprocessFrontmatter(content) {
69
74
  // `---<Info>` and tripping MDX's "expected closing tag" validator.
70
75
  return '---\n' + fixedLines.join('\n') + endMatch[0] + body;
71
76
  }
77
+ /**
78
+ * A `key:` line. Shared with `markContinuationLines` so the two cannot disagree
79
+ * about what counts as a key — if they did, a line would be rewritten as a key
80
+ * by one and treated as value text by the other.
81
+ */
82
+ const KEY_LINE = /^(\s*)([a-zA-Z_][a-zA-Z0-9_.-]*(?::[a-zA-Z0-9_.-]+)*):\s*(.*)$/;
83
+ /** `|`, `>`, `|-`, `>+`, `|2` … — the value is the indented block below. */
84
+ function isBlockScalar(value) {
85
+ return /^[|>][-+]?\d*$/.test(value.trim());
86
+ }
87
+ /**
88
+ * Mark every line that is part of a PREVIOUS key's multi-line value.
89
+ *
90
+ * Those lines are value text. Running the key/value rewrite over them is how a
91
+ * Swedish changelog's continuation line ` Kotlin-SDK:er, Afterpay…` was
92
+ * rebuilt as ` Kotlin-SDK: er, …`: the reconstruction always emits `key: value`
93
+ * with a space, which turned plain prose into what YAML reads as a nested
94
+ * mapping entry, and js-yaml rejected the whole file — so a page lost its
95
+ * frontmatter entirely to a preprocessor whose only job is to RESCUE files.
96
+ *
97
+ * Inside a block scalar the same rewrite does not throw, which is worse: the
98
+ * injected space lands silently in the description text and ships to the page.
99
+ */
100
+ function markContinuationLines(lines) {
101
+ const out = new Array(lines.length).fill(false);
102
+ for (let i = 0; i < lines.length; i++) {
103
+ if (out[i])
104
+ continue;
105
+ const match = lines[i].match(KEY_LINE);
106
+ if (!match)
107
+ continue;
108
+ const [, indent, , value] = match;
109
+ // A block scalar always has a body; a plain value only sometimes wraps.
110
+ const block = isBlockScalar(value);
111
+ if (!block && !hasFoldedContinuation(lines, i))
112
+ continue;
113
+ for (let j = i + 1; j < lines.length; j++) {
114
+ // A blank line inside a block scalar is part of it; one at the end is
115
+ // harmless to mark, since the mapper skips blank lines anyway.
116
+ if (!lines[j].trim()) {
117
+ out[j] = true;
118
+ continue;
119
+ }
120
+ if (lines[j].search(/\S/) <= indent.length)
121
+ break;
122
+ // A block body is opaque text to the last line — `see mode: dark` in a
123
+ // `>-` description is prose and must survive verbatim. Outside one, an
124
+ // indented `key: value` really is a nested entry, and swallowing it was
125
+ // a regression: `seo:` has an empty value, which `hasFoldedContinuation`
126
+ // reads as a wrap whenever the child's name holds a `-` or `.` (its
127
+ // sibling test allows neither), so `seo:\n meta-description: A: B` had
128
+ // its colon left unquoted and js-yaml rejected the file — the very bug
129
+ // this function exists to prevent, re-entered through the back door.
130
+ if (!block && isYamlKeyLine(lines[j]))
131
+ break;
132
+ out[j] = true;
133
+ }
134
+ }
135
+ return out;
136
+ }
137
+ /**
138
+ * True if YAML itself would read this line as a mapping entry: a colon
139
+ * followed by whitespace or end-of-line. That trailing space is the whole
140
+ * distinction between `meta-description: A guide` (a key) and `Kotlin-SDK:er`
141
+ * (prose), and it is why this cannot reuse `KEY_LINE`, whose `\s*` makes the
142
+ * separator optional. The lazy `.*?` lets a colon-compound key like
143
+ * `og:title: Social` match on its real separator rather than its first colon.
144
+ */
145
+ function isYamlKeyLine(line) {
146
+ return /^\s*[^\s#].*?:(\s|$)/.test(line);
147
+ }
72
148
  /**
73
149
  * True if the value on `lines[i]` continues onto a subsequent indented line
74
150
  * (a YAML folded scalar without an explicit `|` or `>` indicator). The next
@@ -1 +1 @@
1
- {"version":3,"file":"frontmatter-utils.js","sourceRoot":"","sources":["../../src/lib/frontmatter-utils.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"frontmatter-utils.js","sourceRoot":"","sources":["../../src/lib/frontmatter-utils.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jamdesk",
3
- "version": "1.1.196",
3
+ "version": "1.1.198",
4
4
  "description": "CLI for Jamdesk — build, preview, and deploy documentation sites from MDX. Dev server with hot reload, 50+ components, OpenAPI support, AI search, and Mintlify migration",
5
5
  "keywords": [
6
6
  "jamdesk",
@@ -28,9 +28,13 @@ export function preprocessFrontmatter(content: string): string {
28
28
 
29
29
  // Process each line of frontmatter
30
30
  const lines = frontmatter.split('\n');
31
+ // Lines belonging to a previous key's multi-line value are VALUE TEXT, not
32
+ // key/value pairs, and must be left exactly as written.
33
+ const isContinuation = markContinuationLines(lines);
31
34
  const fixedLines = lines.map((line, i) => {
32
35
  // Skip empty lines and comments
33
36
  if (!line.trim() || line.trim().startsWith('#')) return line;
37
+ if (isContinuation[i]) return line;
34
38
 
35
39
  // Match key: value pattern (simple single-line values only).
36
40
  // The key may contain colon-segments (e.g. `og:title`, `twitter:card`,
@@ -39,14 +43,14 @@ export function preprocessFrontmatter(content: string): string {
39
43
  // A plain `[a-zA-Z_][a-zA-Z0-9_]*` key class stopped at the first colon,
40
44
  // misparsing `og:title: Social` as key=`og`, value=`title: Social`, then
41
45
  // quote-wrapping it into `og: "title: Social"` and destroying `og:title`.
42
- const match = line.match(/^(\s*)([a-zA-Z_][a-zA-Z0-9_.-]*(?::[a-zA-Z0-9_.-]+)*):\s*(.*)$/);
46
+ const match = line.match(KEY_LINE);
43
47
  if (!match) return line;
44
48
 
45
49
  const [, indent, key, value] = match;
46
50
 
47
51
  // Skip if value is empty, already quoted, or is a multi-line indicator
48
52
  // Multi-line indicators: | (literal), > (folded), with optional modifiers: |- |+ >- >+
49
- if (!value || value.startsWith('"') || value.startsWith("'") || /^[|>][-+]?$/.test(value)) {
53
+ if (!value || value.startsWith('"') || value.startsWith("'") || isBlockScalar(value)) {
50
54
  return line;
51
55
  }
52
56
 
@@ -79,6 +83,74 @@ export function preprocessFrontmatter(content: string): string {
79
83
  return '---\n' + fixedLines.join('\n') + endMatch[0] + body;
80
84
  }
81
85
 
86
+ /**
87
+ * A `key:` line. Shared with `markContinuationLines` so the two cannot disagree
88
+ * about what counts as a key — if they did, a line would be rewritten as a key
89
+ * by one and treated as value text by the other.
90
+ */
91
+ const KEY_LINE =
92
+ /^(\s*)([a-zA-Z_][a-zA-Z0-9_.-]*(?::[a-zA-Z0-9_.-]+)*):\s*(.*)$/;
93
+
94
+ /** `|`, `>`, `|-`, `>+`, `|2` … — the value is the indented block below. */
95
+ function isBlockScalar(value: string): boolean {
96
+ return /^[|>][-+]?\d*$/.test(value.trim());
97
+ }
98
+
99
+ /**
100
+ * Mark every line that is part of a PREVIOUS key's multi-line value.
101
+ *
102
+ * Those lines are value text. Running the key/value rewrite over them is how a
103
+ * Swedish changelog's continuation line ` Kotlin-SDK:er, Afterpay…` was
104
+ * rebuilt as ` Kotlin-SDK: er, …`: the reconstruction always emits `key: value`
105
+ * with a space, which turned plain prose into what YAML reads as a nested
106
+ * mapping entry, and js-yaml rejected the whole file — so a page lost its
107
+ * frontmatter entirely to a preprocessor whose only job is to RESCUE files.
108
+ *
109
+ * Inside a block scalar the same rewrite does not throw, which is worse: the
110
+ * injected space lands silently in the description text and ships to the page.
111
+ */
112
+ function markContinuationLines(lines: string[]): boolean[] {
113
+ const out = new Array<boolean>(lines.length).fill(false);
114
+ for (let i = 0; i < lines.length; i++) {
115
+ if (out[i]) continue;
116
+ const match = lines[i].match(KEY_LINE);
117
+ if (!match) continue;
118
+ const [, indent, , value] = match;
119
+ // A block scalar always has a body; a plain value only sometimes wraps.
120
+ const block = isBlockScalar(value);
121
+ if (!block && !hasFoldedContinuation(lines, i)) continue;
122
+ for (let j = i + 1; j < lines.length; j++) {
123
+ // A blank line inside a block scalar is part of it; one at the end is
124
+ // harmless to mark, since the mapper skips blank lines anyway.
125
+ if (!lines[j].trim()) { out[j] = true; continue; }
126
+ if (lines[j].search(/\S/) <= indent.length) break;
127
+ // A block body is opaque text to the last line — `see mode: dark` in a
128
+ // `>-` description is prose and must survive verbatim. Outside one, an
129
+ // indented `key: value` really is a nested entry, and swallowing it was
130
+ // a regression: `seo:` has an empty value, which `hasFoldedContinuation`
131
+ // reads as a wrap whenever the child's name holds a `-` or `.` (its
132
+ // sibling test allows neither), so `seo:\n meta-description: A: B` had
133
+ // its colon left unquoted and js-yaml rejected the file — the very bug
134
+ // this function exists to prevent, re-entered through the back door.
135
+ if (!block && isYamlKeyLine(lines[j])) break;
136
+ out[j] = true;
137
+ }
138
+ }
139
+ return out;
140
+ }
141
+
142
+ /**
143
+ * True if YAML itself would read this line as a mapping entry: a colon
144
+ * followed by whitespace or end-of-line. That trailing space is the whole
145
+ * distinction between `meta-description: A guide` (a key) and `Kotlin-SDK:er`
146
+ * (prose), and it is why this cannot reuse `KEY_LINE`, whose `\s*` makes the
147
+ * separator optional. The lazy `.*?` lets a colon-compound key like
148
+ * `og:title: Social` match on its real separator rather than its first colon.
149
+ */
150
+ function isYamlKeyLine(line: string): boolean {
151
+ return /^\s*[^\s#].*?:(\s|$)/.test(line);
152
+ }
153
+
82
154
  /**
83
155
  * True if the value on `lines[i]` continues onto a subsequent indented line
84
156
  * (a YAML folded scalar without an explicit `|` or `>` indicator). The next
@@ -9,6 +9,7 @@ import { getContentDir } from './docs';
9
9
  import { injectPromptSources } from './inject-prompt-source';
10
10
  import { mdxSecurityOptions } from './mdx-security-options';
11
11
  import { remarkSvgNamespaceAttrs } from './remark-svg-namespace-attrs';
12
+ import { remarkStyleStringToObject } from './remark-style-string-to-object';
12
13
  import { getShikiOptions } from './shiki-config';
13
14
 
14
15
  export interface DocFrontmatter {
@@ -46,7 +47,7 @@ export async function getDocContent(slug: string[]): Promise<DocContent | null>
46
47
  // Keep expression props (e.g. cols={2}) compatible under next-mdx-remote v6.
47
48
  ...mdxSecurityOptions,
48
49
  mdxOptions: {
49
- remarkPlugins: [remarkGfm, remarkSvgNamespaceAttrs],
50
+ remarkPlugins: [remarkGfm, remarkSvgNamespaceAttrs, remarkStyleStringToObject],
50
51
  rehypePlugins: [[rehypeShiki, shikiOptions]],
51
52
  },
52
53
  scope: data,