@valkyrianlabs/payload-markdown 1.3.4 → 1.4.0

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.
Files changed (99) hide show
  1. package/README.md +63 -14
  2. package/dist/components/MarkdownRenderer/index.css +150 -0
  3. package/dist/components/MarkdownRenderer/index.scss +158 -0
  4. package/dist/core/plugins/rehypeResolveIcons.d.ts +4 -0
  5. package/dist/core/plugins/rehypeResolveIcons.js +27 -0
  6. package/dist/core/plugins/rehypeResolveIcons.js.map +1 -0
  7. package/dist/core/plugins/remarkButtonDirectives.d.ts +4 -0
  8. package/dist/core/plugins/remarkButtonDirectives.js +237 -0
  9. package/dist/core/plugins/remarkButtonDirectives.js.map +1 -0
  10. package/dist/core/plugins/remarkCompileLayouts.js +6 -5
  11. package/dist/core/plugins/remarkCompileLayouts.js.map +1 -1
  12. package/dist/core/plugins/remarkLayoutDirectives.js +17 -7
  13. package/dist/core/plugins/remarkLayoutDirectives.js.map +1 -1
  14. package/dist/core/plugins/remarkLiftLayoutDirectives.js +42 -4
  15. package/dist/core/plugins/remarkLiftLayoutDirectives.js.map +1 -1
  16. package/dist/core/renderMarkdown.js +27 -2
  17. package/dist/core/renderMarkdown.js.map +1 -1
  18. package/dist/directives/attributeDiagnostics.d.ts +2 -0
  19. package/dist/directives/attributeDiagnostics.js +35 -0
  20. package/dist/directives/attributeDiagnostics.js.map +1 -0
  21. package/dist/directives/attributes.d.ts +8 -0
  22. package/dist/directives/attributes.js +56 -5
  23. package/dist/directives/attributes.js.map +1 -1
  24. package/dist/directives/buttonSyntax.d.ts +7 -0
  25. package/dist/directives/buttonSyntax.js +26 -0
  26. package/dist/directives/buttonSyntax.js.map +1 -0
  27. package/dist/directives/closeLabels.d.ts +8 -0
  28. package/dist/directives/closeLabels.js +76 -0
  29. package/dist/directives/closeLabels.js.map +1 -0
  30. package/dist/directives/definitions/button.d.ts +15 -0
  31. package/dist/directives/definitions/button.js +96 -0
  32. package/dist/directives/definitions/button.js.map +1 -0
  33. package/dist/directives/definitions/buttons.d.ts +8 -0
  34. package/dist/directives/definitions/buttons.js +82 -0
  35. package/dist/directives/definitions/buttons.js.map +1 -0
  36. package/dist/directives/definitions/callout.js +20 -9
  37. package/dist/directives/definitions/callout.js.map +1 -1
  38. package/dist/directives/definitions/card.d.ts +4 -0
  39. package/dist/directives/definitions/card.js +90 -9
  40. package/dist/directives/definitions/card.js.map +1 -1
  41. package/dist/directives/definitions/cards.d.ts +4 -0
  42. package/dist/directives/definitions/cards.js +119 -4
  43. package/dist/directives/definitions/cards.js.map +1 -1
  44. package/dist/directives/definitions/details.js +4 -3
  45. package/dist/directives/definitions/details.js.map +1 -1
  46. package/dist/directives/definitions/tab.d.ts +1 -0
  47. package/dist/directives/definitions/tab.js +10 -3
  48. package/dist/directives/definitions/tab.js.map +1 -1
  49. package/dist/directives/definitions/tabs.js +3 -3
  50. package/dist/directives/definitions/tabs.js.map +1 -1
  51. package/dist/directives/definitions/toc.js +4 -3
  52. package/dist/directives/definitions/toc.js.map +1 -1
  53. package/dist/directives/diagnostics.js +97 -7
  54. package/dist/directives/diagnostics.js.map +1 -1
  55. package/dist/directives/iconPlaceholder.d.ts +12 -0
  56. package/dist/directives/iconPlaceholder.js +19 -0
  57. package/dist/directives/iconPlaceholder.js.map +1 -0
  58. package/dist/directives/labels.d.ts +3 -0
  59. package/dist/directives/labels.js +12 -0
  60. package/dist/directives/labels.js.map +1 -0
  61. package/dist/directives/registry.d.ts +1 -1
  62. package/dist/directives/registry.js +46 -6
  63. package/dist/directives/registry.js.map +1 -1
  64. package/dist/directives/renderData.d.ts +2 -2
  65. package/dist/directives/renderData.js.map +1 -1
  66. package/dist/directives/types.d.ts +6 -4
  67. package/dist/directives/types.js.map +1 -1
  68. package/dist/editor/MarkdownCodeMirror/Component.client.js +2 -0
  69. package/dist/editor/MarkdownCodeMirror/Component.client.js.map +1 -1
  70. package/dist/editor/directives/closeLabels.d.ts +2 -0
  71. package/dist/editor/directives/closeLabels.js +75 -0
  72. package/dist/editor/directives/closeLabels.js.map +1 -0
  73. package/dist/editor/directives/completions.js +49 -7
  74. package/dist/editor/directives/completions.js.map +1 -1
  75. package/dist/editor/themes/payload.js +197 -9
  76. package/dist/editor/themes/payload.js.map +1 -1
  77. package/dist/exports/advanced.d.ts +1 -0
  78. package/dist/exports/advanced.js +1 -0
  79. package/dist/exports/advanced.js.map +1 -1
  80. package/dist/icons/generateRegistry.d.ts +8 -0
  81. package/dist/icons/generateRegistry.js +36 -0
  82. package/dist/icons/generateRegistry.js.map +1 -0
  83. package/dist/icons/refs.d.ts +10 -0
  84. package/dist/icons/refs.js +42 -0
  85. package/dist/icons/refs.js.map +1 -0
  86. package/dist/icons/resolve.d.ts +9 -0
  87. package/dist/icons/resolve.js +95 -0
  88. package/dist/icons/resolve.js.map +1 -0
  89. package/dist/index.d.ts +1 -1
  90. package/dist/index.js.map +1 -1
  91. package/dist/runtime/index.d.ts +1 -0
  92. package/dist/runtime/index.js +8 -1
  93. package/dist/runtime/index.js.map +1 -1
  94. package/dist/types/core.d.ts +9 -0
  95. package/dist/types/core.js.map +1 -1
  96. package/dist/types/mdast.d.js.map +1 -1
  97. package/dist/types.d.ts +5 -1
  98. package/dist/types.js.map +1 -1
  99. package/package.json +1 -1
@@ -1,3 +1,6 @@
1
+ import { normalizePayloadMarkdownIconRef } from '../icons/refs.js';
2
+ import { hasUnclosedDirectiveAttributeBlock } from './attributes.js';
3
+ import { parseButtonDirectiveLine } from './buttonSyntax.js';
1
4
  import { layoutDirectiveRegistry } from './registry.js';
2
5
  import { hasDirectiveTheme } from './themes.js';
3
6
  function isFenceLine(trimmed) {
@@ -10,12 +13,33 @@ function findNearestFrameIndex(stack, predicate) {
10
13
  }
11
14
  return -1;
12
15
  }
13
- function getTabValue(attributes, index) {
16
+ function getTabValue(attributes, index, label) {
14
17
  const value = attributes?.value;
15
- const label = attributes?.label;
16
- const raw = typeof value === 'string' && value.trim() ? value.trim() : typeof label === 'string' && label.trim() ? label.trim() : `tab-${index + 1}`;
18
+ const attributeLabel = attributes?.label;
19
+ const raw = typeof value === 'string' && value.trim() ? value.trim() : typeof label === 'string' && label.trim() ? label.trim() : typeof attributeLabel === 'string' && attributeLabel.trim() ? attributeLabel.trim() : `tab-${index + 1}`;
17
20
  return raw.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '') || `tab-${index + 1}`;
18
21
  }
22
+ function collectExpandedDirectiveText(lines, startIndex) {
23
+ const firstText = lines[startIndex];
24
+ if (!hasUnclosedDirectiveAttributeBlock(firstText)) return {
25
+ endIndex: startIndex,
26
+ text: firstText
27
+ };
28
+ let text = firstText;
29
+ for(let index = startIndex + 1; index < lines.length; ++index){
30
+ const nextText = lines[index];
31
+ if (nextText.trim().startsWith('::')) break;
32
+ text += `\n${nextText}`;
33
+ if (!hasUnclosedDirectiveAttributeBlock(text)) return {
34
+ endIndex: index,
35
+ text
36
+ };
37
+ }
38
+ return {
39
+ endIndex: startIndex,
40
+ text: firstText
41
+ };
42
+ }
19
43
  function finalizeTabsFrame(frame) {
20
44
  if (frame.name !== 'tabs') return [];
21
45
  const diagnostics = [];
@@ -37,17 +61,32 @@ function findNearestTabsFrame(stack) {
37
61
  }
38
62
  return undefined;
39
63
  }
64
+ function findNearestCardsFrame(stack) {
65
+ for(let index = stack.length - 1; index >= 0; --index){
66
+ const frame = stack[index];
67
+ if (frame.name === 'cards') return frame;
68
+ }
69
+ return undefined;
70
+ }
71
+ function hasAttribute(attributes, name) {
72
+ return Object.prototype.hasOwnProperty.call(attributes ?? {}, name);
73
+ }
40
74
  function updateOpenStack(stack, text, line, from) {
41
75
  const token = layoutDirectiveRegistry.parseMarkdownLineDetailed(text).token;
42
76
  const diagnostics = [];
43
77
  if (!token) return diagnostics;
44
78
  if (token.action === 'open') {
79
+ if (token.name === 'card') {
80
+ const cardsFrame = findNearestCardsFrame(stack);
81
+ const cardsSectionLink = cardsFrame?.cardsHasHref && (cardsFrame.cardsLinkScope === undefined || cardsFrame.cardsLinkScope === 'section');
82
+ if (cardsSectionLink && (hasAttribute(token.attributes, 'href') || hasAttribute(token.attributes, 'linkScope') || hasAttribute(token.attributes, 'newTab'))) diagnostics.push('Directive "cards" with linkScope="section" ignores child "card" link overrides.');
83
+ }
45
84
  if (token.name === 'tab') {
46
85
  const tabsFrame = findNearestTabsFrame(stack);
47
86
  if (!tabsFrame) diagnostics.push('Directive "tab" is usually intended inside "tabs".');
48
87
  else {
49
88
  const nextIndex = tabsFrame.tabCount ?? 0;
50
- const value = getTabValue(token.attributes, nextIndex);
89
+ const value = getTabValue(token.attributes, nextIndex, token.label);
51
90
  tabsFrame.tabCount = nextIndex + 1;
52
91
  tabsFrame.tabValues ??= new Map();
53
92
  tabsFrame.tabValues.set(value, (tabsFrame.tabValues.get(value) ?? 0) + 1);
@@ -57,6 +96,10 @@ function updateOpenStack(stack, text, line, from) {
57
96
  name: token.name,
58
97
  from,
59
98
  line,
99
+ ...token.name === 'cards' ? {
100
+ cardsHasHref: typeof token.attributes?.href === 'string' && Boolean(token.attributes.href.trim()),
101
+ cardsLinkScope: typeof token.attributes?.linkScope === 'string' ? token.attributes.linkScope : undefined
102
+ } : {},
60
103
  ...token.name === 'tabs' ? {
61
104
  defaultValue: typeof token.attributes?.default === 'string' ? token.attributes.default : undefined,
62
105
  tabCount: 0,
@@ -101,6 +144,30 @@ function getThemeDiagnostics(text) {
101
144
  }
102
145
  return diagnostics;
103
146
  }
147
+ function getButtonDiagnostics(text) {
148
+ const parsed = parseButtonDirectiveLine(text);
149
+ if (!parsed) return [];
150
+ const definition = layoutDirectiveRegistry.get('button');
151
+ const diagnostics = [
152
+ ...parsed.warnings,
153
+ ...definition?.validateAttributes?.({
154
+ name: 'button',
155
+ attributes: parsed.attributes
156
+ }) ?? []
157
+ ];
158
+ const icon = parsed.attributes.icon;
159
+ if (typeof icon === 'string') {
160
+ const normalized = normalizePayloadMarkdownIconRef(icon);
161
+ if (normalized.warning) diagnostics.push(normalized.warning);
162
+ }
163
+ if (!parsed.label.trim() && typeof parsed.attributes.ariaLabel !== 'string') diagnostics.push('Icon-only button requires an ariaLabel attribute.');
164
+ return diagnostics;
165
+ }
166
+ function getLeafDirectiveName(text) {
167
+ if (text.startsWith(':::')) return undefined;
168
+ const match = text.match(/^::([\w-]+)(?:$|[\s[{])/);
169
+ return match?.[1];
170
+ }
104
171
  export function lintMarkdownDirectives(markdown) {
105
172
  const diagnostics = [];
106
173
  const stack = [];
@@ -120,7 +187,9 @@ export function lintMarkdownDirectives(markdown) {
120
187
  continue;
121
188
  }
122
189
  if (!inFence && trimmed.startsWith(':::')) {
123
- const result = layoutDirectiveRegistry.parseMarkdownLineDetailed(trimmed);
190
+ const expanded = collectExpandedDirectiveText(lines, index);
191
+ const expandedTrimmed = expanded.text.trim();
192
+ const result = layoutDirectiveRegistry.parseMarkdownLineDetailed(expandedTrimmed);
124
193
  for (const message of result.diagnostics)diagnostics.push({
125
194
  from: markerFrom,
126
195
  line: index + 1,
@@ -128,14 +197,14 @@ export function lintMarkdownDirectives(markdown) {
128
197
  severity: 'warning',
129
198
  to: markerTo
130
199
  });
131
- for (const message of getThemeDiagnostics(trimmed))diagnostics.push({
200
+ for (const message of getThemeDiagnostics(expandedTrimmed))diagnostics.push({
132
201
  from: markerFrom,
133
202
  line: index + 1,
134
203
  message,
135
204
  severity: 'warning',
136
205
  to: markerTo
137
206
  });
138
- for (const message of updateOpenStack(stack, trimmed, index + 1, markerFrom))diagnostics.push({
207
+ for (const message of updateOpenStack(stack, expandedTrimmed, index + 1, markerFrom))diagnostics.push({
139
208
  from: markerFrom,
140
209
  line: index + 1,
141
210
  message,
@@ -143,6 +212,27 @@ export function lintMarkdownDirectives(markdown) {
143
212
  to: markerTo
144
213
  });
145
214
  }
215
+ if (!inFence && trimmed.startsWith('::') && !trimmed.startsWith(':::')) {
216
+ const expanded = collectExpandedDirectiveText(lines, index);
217
+ const expandedTrimmed = expanded.text.trim();
218
+ const leafName = getLeafDirectiveName(trimmed);
219
+ const leafMarkerStart = line.indexOf('::');
220
+ const leafMarkerFrom = leafMarkerStart >= 0 ? lineStart + leafMarkerStart : lineStart;
221
+ if (leafName && leafName !== 'button') diagnostics.push({
222
+ from: leafMarkerFrom,
223
+ line: index + 1,
224
+ message: `Unknown directive "${leafName}".`,
225
+ severity: 'warning',
226
+ to: markerTo
227
+ });
228
+ for (const message of getButtonDiagnostics(expandedTrimmed))diagnostics.push({
229
+ from: leafMarkerFrom,
230
+ line: index + 1,
231
+ message,
232
+ severity: 'warning',
233
+ to: markerTo
234
+ });
235
+ }
146
236
  offset += line.length + 1;
147
237
  }
148
238
  for (const frame of stack){
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/directives/diagnostics.ts"],"sourcesContent":["import { layoutDirectiveRegistry } from './registry.js'\nimport { hasDirectiveTheme } from './themes.js'\n\nexport type DirectiveDiagnostic = {\n from: number\n line: number\n message: string\n severity: 'warning'\n to: number\n}\n\ntype OpenFrame = {\n defaultValue?: string\n from: number\n line: number\n name: string\n tabCount?: number\n tabValues?: Map<string, number>\n}\n\nfunction isFenceLine(trimmed: string): boolean {\n return trimmed.startsWith('```') || trimmed.startsWith('~~~')\n}\n\nfunction findNearestFrameIndex(stack: OpenFrame[], predicate: (frame: OpenFrame) => boolean) {\n for (let index = stack.length - 1; index >= 0; --index) {\n const frame = stack[index]\n if (predicate(frame)) return index\n }\n\n return -1\n}\n\nfunction getTabValue(attributes: Record<string, boolean | string> | undefined, index: number): string {\n const value = attributes?.value\n const label = attributes?.label\n const raw =\n typeof value === 'string' && value.trim()\n ? value.trim()\n : typeof label === 'string' && label.trim()\n ? label.trim()\n : `tab-${index + 1}`\n\n return raw\n .replace(/([a-z0-9])([A-Z])/g, '$1-$2')\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '') || `tab-${index + 1}`\n}\n\nfunction finalizeTabsFrame(frame: OpenFrame): string[] {\n if (frame.name !== 'tabs') return []\n\n const diagnostics: string[] = []\n const tabValues = frame.tabValues ?? new Map<string, number>()\n\n if (!frame.tabCount) diagnostics.push('Directive \"tabs\" has no child \"tab\" directives.')\n\n for (const [value, count] of tabValues)\n if (count > 1) diagnostics.push(`Duplicate tab value \"${value}\" in \"tabs\".`)\n\n if (frame.defaultValue) {\n const defaultValue = getTabValue({ value: frame.defaultValue }, 0)\n if (!tabValues.has(defaultValue))\n diagnostics.push(`Invalid tabs default \"${frame.defaultValue}\". Falling back to the first tab.`)\n }\n\n return diagnostics\n}\n\nfunction findNearestTabsFrame(stack: OpenFrame[]): OpenFrame | undefined {\n for (let index = stack.length - 1; index >= 0; --index) {\n const frame = stack[index]\n if (frame.name === 'tabs') return frame\n }\n\n return undefined\n}\n\nfunction updateOpenStack(\n stack: OpenFrame[],\n text: string,\n line: number,\n from: number,\n): string[] {\n const token = layoutDirectiveRegistry.parseMarkdownLineDetailed(text).token\n const diagnostics: string[] = []\n\n if (!token) return diagnostics\n\n if (token.action === 'open') {\n if (token.name === 'tab') {\n const tabsFrame = findNearestTabsFrame(stack)\n\n if (!tabsFrame) diagnostics.push('Directive \"tab\" is usually intended inside \"tabs\".')\n else {\n const nextIndex = tabsFrame.tabCount ?? 0\n const value = getTabValue(token.attributes, nextIndex)\n\n tabsFrame.tabCount = nextIndex + 1\n tabsFrame.tabValues ??= new Map<string, number>()\n tabsFrame.tabValues.set(value, (tabsFrame.tabValues.get(value) ?? 0) + 1)\n }\n }\n\n stack.push({\n name: token.name,\n from,\n line,\n ...(token.name === 'tabs'\n ? {\n defaultValue:\n typeof token.attributes?.default === 'string'\n ? token.attributes.default\n : undefined,\n tabCount: 0,\n tabValues: new Map<string, number>(),\n }\n : {}),\n })\n return diagnostics\n }\n\n if (token.action === 'close') {\n const frame = stack.pop()\n if (frame) diagnostics.push(...finalizeTabsFrame(frame))\n return diagnostics\n }\n\n if (token.action === 'closeGrid') {\n const index = findNearestFrameIndex(stack, (frame) =>\n layoutDirectiveRegistry.isGridName(frame.name),\n )\n\n if (index >= 0) {\n const frames = stack.splice(index)\n for (const frame of frames) diagnostics.push(...finalizeTabsFrame(frame))\n }\n return diagnostics\n }\n\n const index = findNearestFrameIndex(stack, (frame) => frame.name === 'section')\n if (index >= 0) {\n const frames = stack.splice(index)\n for (const frame of frames) diagnostics.push(...finalizeTabsFrame(frame))\n }\n return diagnostics\n}\n\nfunction getThemeDiagnostics(text: string): string[] {\n const token = layoutDirectiveRegistry.parseMarkdownLineDetailed(text).token\n if (!token || token.action !== 'open') return []\n\n const definition = layoutDirectiveRegistry.get(token.name)\n if (!definition?.themeAttributes) return []\n\n const diagnostics: string[] = []\n\n for (const [attribute, groupName] of Object.entries(definition.themeAttributes)) {\n if (!groupName) continue\n\n const value = token.attributes?.[attribute]\n if (typeof value !== 'string' || !value.trim()) continue\n if (hasDirectiveTheme(groupName, value)) continue\n\n const label = attribute === 'theme' ? 'theme' : attribute\n diagnostics.push(\n `Unknown ${label} \"${value}\" on \"${token.name}\". Falling back to \"default\".`,\n )\n }\n\n return diagnostics\n}\n\nexport function lintMarkdownDirectives(markdown: string): DirectiveDiagnostic[] {\n const diagnostics: DirectiveDiagnostic[] = []\n const stack: OpenFrame[] = []\n const lines = markdown.split(/\\r?\\n/)\n let offset = 0\n let inFence = false\n\n for (let index = 0; index < lines.length; ++index) {\n const line = lines[index]\n const trimmed = line.trim()\n const lineStart = offset\n const markerStart = line.indexOf(':::')\n const markerFrom = markerStart >= 0 ? lineStart + markerStart : lineStart\n const markerTo = lineStart + line.length\n\n if (isFenceLine(trimmed)) {\n inFence = !inFence\n offset += line.length + 1\n continue\n }\n\n if (!inFence && trimmed.startsWith(':::')) {\n const result = layoutDirectiveRegistry.parseMarkdownLineDetailed(trimmed)\n\n for (const message of result.diagnostics)\n diagnostics.push({\n from: markerFrom,\n line: index + 1,\n message,\n severity: 'warning',\n to: markerTo,\n })\n\n for (const message of getThemeDiagnostics(trimmed))\n diagnostics.push({\n from: markerFrom,\n line: index + 1,\n message,\n severity: 'warning',\n to: markerTo,\n })\n\n for (const message of updateOpenStack(stack, trimmed, index + 1, markerFrom))\n diagnostics.push({\n from: markerFrom,\n line: index + 1,\n message,\n severity: 'warning',\n to: markerTo,\n })\n }\n\n offset += line.length + 1\n }\n\n for (const frame of stack) {\n for (const message of finalizeTabsFrame(frame))\n diagnostics.push({\n from: frame.from,\n line: frame.line,\n message,\n severity: 'warning',\n to: frame.from + frame.name.length + 3,\n })\n\n diagnostics.push({\n from: frame.from,\n line: frame.line,\n message: `Unclosed directive \"${frame.name}\".`,\n severity: 'warning',\n to: frame.from + frame.name.length + 3,\n })\n }\n\n return diagnostics\n}\n"],"names":["layoutDirectiveRegistry","hasDirectiveTheme","isFenceLine","trimmed","startsWith","findNearestFrameIndex","stack","predicate","index","length","frame","getTabValue","attributes","value","label","raw","trim","replace","toLowerCase","finalizeTabsFrame","name","diagnostics","tabValues","Map","tabCount","push","count","defaultValue","has","findNearestTabsFrame","undefined","updateOpenStack","text","line","from","token","parseMarkdownLineDetailed","action","tabsFrame","nextIndex","set","get","default","pop","isGridName","frames","splice","getThemeDiagnostics","definition","themeAttributes","attribute","groupName","Object","entries","lintMarkdownDirectives","markdown","lines","split","offset","inFence","lineStart","markerStart","indexOf","markerFrom","markerTo","result","message","severity","to"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/directives/diagnostics.ts"],"sourcesContent":["import { normalizePayloadMarkdownIconRef } from '../icons/refs.js'\nimport { hasUnclosedDirectiveAttributeBlock } from './attributes.js'\nimport { parseButtonDirectiveLine } from './buttonSyntax.js'\nimport { layoutDirectiveRegistry } from './registry.js'\nimport { hasDirectiveTheme } from './themes.js'\n\nexport type DirectiveDiagnostic = {\n from: number\n line: number\n message: string\n severity: 'warning'\n to: number\n}\n\ntype OpenFrame = {\n cardsHasHref?: boolean\n cardsLinkScope?: string\n defaultValue?: string\n from: number\n line: number\n name: string\n tabCount?: number\n tabValues?: Map<string, number>\n}\n\nfunction isFenceLine(trimmed: string): boolean {\n return trimmed.startsWith('```') || trimmed.startsWith('~~~')\n}\n\nfunction findNearestFrameIndex(stack: OpenFrame[], predicate: (frame: OpenFrame) => boolean) {\n for (let index = stack.length - 1; index >= 0; --index) {\n const frame = stack[index]\n if (predicate(frame)) return index\n }\n\n return -1\n}\n\nfunction getTabValue(\n attributes: Record<string, boolean | string> | undefined,\n index: number,\n label?: string,\n): string {\n const value = attributes?.value\n const attributeLabel = attributes?.label\n const raw =\n typeof value === 'string' && value.trim()\n ? value.trim()\n : typeof label === 'string' && label.trim()\n ? label.trim()\n : typeof attributeLabel === 'string' && attributeLabel.trim()\n ? attributeLabel.trim()\n : `tab-${index + 1}`\n\n return raw\n .replace(/([a-z0-9])([A-Z])/g, '$1-$2')\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '') || `tab-${index + 1}`\n}\n\nfunction collectExpandedDirectiveText(\n lines: readonly string[],\n startIndex: number,\n): { endIndex: number; text: string } {\n const firstText = lines[startIndex]\n\n if (!hasUnclosedDirectiveAttributeBlock(firstText))\n return {\n endIndex: startIndex,\n text: firstText,\n }\n\n let text = firstText\n\n for (let index = startIndex + 1; index < lines.length; ++index) {\n const nextText = lines[index]\n\n if (nextText.trim().startsWith('::')) break\n\n text += `\\n${nextText}`\n\n if (!hasUnclosedDirectiveAttributeBlock(text))\n return {\n endIndex: index,\n text,\n }\n }\n\n return {\n endIndex: startIndex,\n text: firstText,\n }\n}\n\nfunction finalizeTabsFrame(frame: OpenFrame): string[] {\n if (frame.name !== 'tabs') return []\n\n const diagnostics: string[] = []\n const tabValues = frame.tabValues ?? new Map<string, number>()\n\n if (!frame.tabCount) diagnostics.push('Directive \"tabs\" has no child \"tab\" directives.')\n\n for (const [value, count] of tabValues)\n if (count > 1) diagnostics.push(`Duplicate tab value \"${value}\" in \"tabs\".`)\n\n if (frame.defaultValue) {\n const defaultValue = getTabValue({ value: frame.defaultValue }, 0)\n if (!tabValues.has(defaultValue))\n diagnostics.push(`Invalid tabs default \"${frame.defaultValue}\". Falling back to the first tab.`)\n }\n\n return diagnostics\n}\n\nfunction findNearestTabsFrame(stack: OpenFrame[]): OpenFrame | undefined {\n for (let index = stack.length - 1; index >= 0; --index) {\n const frame = stack[index]\n if (frame.name === 'tabs') return frame\n }\n\n return undefined\n}\n\nfunction findNearestCardsFrame(stack: OpenFrame[]): OpenFrame | undefined {\n for (let index = stack.length - 1; index >= 0; --index) {\n const frame = stack[index]\n if (frame.name === 'cards') return frame\n }\n\n return undefined\n}\n\nfunction hasAttribute(\n attributes: Record<string, boolean | string> | undefined,\n name: string,\n): boolean {\n return Object.prototype.hasOwnProperty.call(attributes ?? {}, name)\n}\n\nfunction updateOpenStack(\n stack: OpenFrame[],\n text: string,\n line: number,\n from: number,\n): string[] {\n const token = layoutDirectiveRegistry.parseMarkdownLineDetailed(text).token\n const diagnostics: string[] = []\n\n if (!token) return diagnostics\n\n if (token.action === 'open') {\n if (token.name === 'card') {\n const cardsFrame = findNearestCardsFrame(stack)\n const cardsSectionLink =\n cardsFrame?.cardsHasHref &&\n (cardsFrame.cardsLinkScope === undefined || cardsFrame.cardsLinkScope === 'section')\n\n if (\n cardsSectionLink &&\n (hasAttribute(token.attributes, 'href') ||\n hasAttribute(token.attributes, 'linkScope') ||\n hasAttribute(token.attributes, 'newTab'))\n )\n diagnostics.push(\n 'Directive \"cards\" with linkScope=\"section\" ignores child \"card\" link overrides.',\n )\n }\n\n if (token.name === 'tab') {\n const tabsFrame = findNearestTabsFrame(stack)\n\n if (!tabsFrame) diagnostics.push('Directive \"tab\" is usually intended inside \"tabs\".')\n else {\n const nextIndex = tabsFrame.tabCount ?? 0\n const value = getTabValue(token.attributes, nextIndex, token.label)\n\n tabsFrame.tabCount = nextIndex + 1\n tabsFrame.tabValues ??= new Map<string, number>()\n tabsFrame.tabValues.set(value, (tabsFrame.tabValues.get(value) ?? 0) + 1)\n }\n }\n\n stack.push({\n name: token.name,\n from,\n line,\n ...(token.name === 'cards'\n ? {\n cardsHasHref:\n typeof token.attributes?.href === 'string' && Boolean(token.attributes.href.trim()),\n cardsLinkScope:\n typeof token.attributes?.linkScope === 'string'\n ? token.attributes.linkScope\n : undefined,\n }\n : {}),\n ...(token.name === 'tabs'\n ? {\n defaultValue:\n typeof token.attributes?.default === 'string'\n ? token.attributes.default\n : undefined,\n tabCount: 0,\n tabValues: new Map<string, number>(),\n }\n : {}),\n })\n return diagnostics\n }\n\n if (token.action === 'close') {\n const frame = stack.pop()\n if (frame) diagnostics.push(...finalizeTabsFrame(frame))\n return diagnostics\n }\n\n if (token.action === 'closeGrid') {\n const index = findNearestFrameIndex(stack, (frame) =>\n layoutDirectiveRegistry.isGridName(frame.name),\n )\n\n if (index >= 0) {\n const frames = stack.splice(index)\n for (const frame of frames) diagnostics.push(...finalizeTabsFrame(frame))\n }\n return diagnostics\n }\n\n const index = findNearestFrameIndex(stack, (frame) => frame.name === 'section')\n if (index >= 0) {\n const frames = stack.splice(index)\n for (const frame of frames) diagnostics.push(...finalizeTabsFrame(frame))\n }\n return diagnostics\n}\n\nfunction getThemeDiagnostics(text: string): string[] {\n const token = layoutDirectiveRegistry.parseMarkdownLineDetailed(text).token\n if (!token || token.action !== 'open') return []\n\n const definition = layoutDirectiveRegistry.get(token.name)\n if (!definition?.themeAttributes) return []\n\n const diagnostics: string[] = []\n\n for (const [attribute, groupName] of Object.entries(definition.themeAttributes)) {\n if (!groupName) continue\n\n const value = token.attributes?.[attribute]\n if (typeof value !== 'string' || !value.trim()) continue\n if (hasDirectiveTheme(groupName, value)) continue\n\n const label = attribute === 'theme' ? 'theme' : attribute\n diagnostics.push(\n `Unknown ${label} \"${value}\" on \"${token.name}\". Falling back to \"default\".`,\n )\n }\n\n return diagnostics\n}\n\nfunction getButtonDiagnostics(text: string): string[] {\n const parsed = parseButtonDirectiveLine(text)\n if (!parsed) return []\n\n const definition = layoutDirectiveRegistry.get('button')\n const diagnostics = [\n ...parsed.warnings,\n ...(definition?.validateAttributes?.({ name: 'button', attributes: parsed.attributes }) ?? []),\n ]\n const icon = parsed.attributes.icon\n\n if (typeof icon === 'string') {\n const normalized = normalizePayloadMarkdownIconRef(icon)\n if (normalized.warning) diagnostics.push(normalized.warning)\n }\n\n if (!parsed.label.trim() && typeof parsed.attributes.ariaLabel !== 'string')\n diagnostics.push('Icon-only button requires an ariaLabel attribute.')\n\n return diagnostics\n}\n\nfunction getLeafDirectiveName(text: string): string | undefined {\n if (text.startsWith(':::')) return undefined\n\n const match = text.match(/^::([\\w-]+)(?:$|[\\s[{])/)\n\n return match?.[1]\n}\n\nexport function lintMarkdownDirectives(markdown: string): DirectiveDiagnostic[] {\n const diagnostics: DirectiveDiagnostic[] = []\n const stack: OpenFrame[] = []\n const lines = markdown.split(/\\r?\\n/)\n let offset = 0\n let inFence = false\n\n for (let index = 0; index < lines.length; ++index) {\n const line = lines[index]\n const trimmed = line.trim()\n const lineStart = offset\n const markerStart = line.indexOf(':::')\n const markerFrom = markerStart >= 0 ? lineStart + markerStart : lineStart\n const markerTo = lineStart + line.length\n\n if (isFenceLine(trimmed)) {\n inFence = !inFence\n offset += line.length + 1\n continue\n }\n\n if (!inFence && trimmed.startsWith(':::')) {\n const expanded = collectExpandedDirectiveText(lines, index)\n const expandedTrimmed = expanded.text.trim()\n const result = layoutDirectiveRegistry.parseMarkdownLineDetailed(expandedTrimmed)\n\n for (const message of result.diagnostics)\n diagnostics.push({\n from: markerFrom,\n line: index + 1,\n message,\n severity: 'warning',\n to: markerTo,\n })\n\n for (const message of getThemeDiagnostics(expandedTrimmed))\n diagnostics.push({\n from: markerFrom,\n line: index + 1,\n message,\n severity: 'warning',\n to: markerTo,\n })\n\n for (const message of updateOpenStack(stack, expandedTrimmed, index + 1, markerFrom))\n diagnostics.push({\n from: markerFrom,\n line: index + 1,\n message,\n severity: 'warning',\n to: markerTo,\n })\n }\n\n if (!inFence && trimmed.startsWith('::') && !trimmed.startsWith(':::')) {\n const expanded = collectExpandedDirectiveText(lines, index)\n const expandedTrimmed = expanded.text.trim()\n const leafName = getLeafDirectiveName(trimmed)\n const leafMarkerStart = line.indexOf('::')\n const leafMarkerFrom = leafMarkerStart >= 0 ? lineStart + leafMarkerStart : lineStart\n\n if (leafName && leafName !== 'button')\n diagnostics.push({\n from: leafMarkerFrom,\n line: index + 1,\n message: `Unknown directive \"${leafName}\".`,\n severity: 'warning',\n to: markerTo,\n })\n\n for (const message of getButtonDiagnostics(expandedTrimmed))\n diagnostics.push({\n from: leafMarkerFrom,\n line: index + 1,\n message,\n severity: 'warning',\n to: markerTo,\n })\n }\n\n offset += line.length + 1\n }\n\n for (const frame of stack) {\n for (const message of finalizeTabsFrame(frame))\n diagnostics.push({\n from: frame.from,\n line: frame.line,\n message,\n severity: 'warning',\n to: frame.from + frame.name.length + 3,\n })\n\n diagnostics.push({\n from: frame.from,\n line: frame.line,\n message: `Unclosed directive \"${frame.name}\".`,\n severity: 'warning',\n to: frame.from + frame.name.length + 3,\n })\n }\n\n return diagnostics\n}\n"],"names":["normalizePayloadMarkdownIconRef","hasUnclosedDirectiveAttributeBlock","parseButtonDirectiveLine","layoutDirectiveRegistry","hasDirectiveTheme","isFenceLine","trimmed","startsWith","findNearestFrameIndex","stack","predicate","index","length","frame","getTabValue","attributes","label","value","attributeLabel","raw","trim","replace","toLowerCase","collectExpandedDirectiveText","lines","startIndex","firstText","endIndex","text","nextText","finalizeTabsFrame","name","diagnostics","tabValues","Map","tabCount","push","count","defaultValue","has","findNearestTabsFrame","undefined","findNearestCardsFrame","hasAttribute","Object","prototype","hasOwnProperty","call","updateOpenStack","line","from","token","parseMarkdownLineDetailed","action","cardsFrame","cardsSectionLink","cardsHasHref","cardsLinkScope","tabsFrame","nextIndex","set","get","href","Boolean","linkScope","default","pop","isGridName","frames","splice","getThemeDiagnostics","definition","themeAttributes","attribute","groupName","entries","getButtonDiagnostics","parsed","warnings","validateAttributes","icon","normalized","warning","ariaLabel","getLeafDirectiveName","match","lintMarkdownDirectives","markdown","split","offset","inFence","lineStart","markerStart","indexOf","markerFrom","markerTo","expanded","expandedTrimmed","result","message","severity","to","leafName","leafMarkerStart","leafMarkerFrom"],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ export declare function makeDirectiveIconPlaceholder(icon: string, className: string[]): {
2
+ type: "element";
3
+ children: never[];
4
+ properties: {
5
+ ariaHidden: string;
6
+ className: string[];
7
+ dataPmdIcon: string;
8
+ dataPmdIconRef: string;
9
+ focusable: string;
10
+ };
11
+ tagName: string;
12
+ };
@@ -0,0 +1,19 @@
1
+ import { normalizePayloadMarkdownIconRef } from '../icons/refs.js';
2
+ export function makeDirectiveIconPlaceholder(icon, className) {
3
+ const normalized = normalizePayloadMarkdownIconRef(icon);
4
+ const iconKey = normalized.icon?.key ?? icon;
5
+ return {
6
+ type: 'element',
7
+ children: [],
8
+ properties: {
9
+ ariaHidden: 'true',
10
+ className,
11
+ dataPmdIcon: iconKey,
12
+ dataPmdIconRef: icon,
13
+ focusable: 'false'
14
+ },
15
+ tagName: 'span'
16
+ };
17
+ }
18
+
19
+ //# sourceMappingURL=iconPlaceholder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/directives/iconPlaceholder.ts"],"sourcesContent":["import { normalizePayloadMarkdownIconRef } from '../icons/refs.js'\n\nexport function makeDirectiveIconPlaceholder(icon: string, className: string[]) {\n const normalized = normalizePayloadMarkdownIconRef(icon)\n const iconKey = normalized.icon?.key ?? icon\n\n return {\n type: 'element' as const,\n children: [],\n properties: {\n ariaHidden: 'true',\n className,\n dataPmdIcon: iconKey,\n dataPmdIconRef: icon,\n focusable: 'false',\n },\n tagName: 'span',\n }\n}\n"],"names":["normalizePayloadMarkdownIconRef","makeDirectiveIconPlaceholder","icon","className","normalized","iconKey","key","type","children","properties","ariaHidden","dataPmdIcon","dataPmdIconRef","focusable","tagName"],"mappings":"AAAA,SAASA,+BAA+B,QAAQ,mBAAkB;AAElE,OAAO,SAASC,6BAA6BC,IAAY,EAAEC,SAAmB;IAC5E,MAAMC,aAAaJ,gCAAgCE;IACnD,MAAMG,UAAUD,WAAWF,IAAI,EAAEI,OAAOJ;IAExC,OAAO;QACLK,MAAM;QACNC,UAAU,EAAE;QACZC,YAAY;YACVC,YAAY;YACZP;YACAQ,aAAaN;YACbO,gBAAgBV;YAChBW,WAAW;QACb;QACAC,SAAS;IACX;AACF"}
@@ -0,0 +1,3 @@
1
+ import type { ContainerDirective } from 'mdast-util-directive';
2
+ export declare function getDirectiveLabel(node: ContainerDirective): string | undefined;
3
+ export declare function getDirectiveLabelOrAttribute(node: ContainerDirective, attributeName: string): string | undefined;
@@ -0,0 +1,12 @@
1
+ export function getDirectiveLabel(node) {
2
+ const label = node.data?.vlDirectiveLabel;
3
+ return typeof label === 'string' && label.trim() ? label.trim() : undefined;
4
+ }
5
+ export function getDirectiveLabelOrAttribute(node, attributeName) {
6
+ const label = getDirectiveLabel(node);
7
+ const attributeValue = node.attributes?.[attributeName];
8
+ if (label) return label;
9
+ return typeof attributeValue === 'string' && attributeValue.trim() ? attributeValue.trim() : undefined;
10
+ }
11
+
12
+ //# sourceMappingURL=labels.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/directives/labels.ts"],"sourcesContent":["import type { ContainerDirective } from 'mdast-util-directive'\n\nexport function getDirectiveLabel(node: ContainerDirective): string | undefined {\n const label = node.data?.vlDirectiveLabel\n\n return typeof label === 'string' && label.trim() ? label.trim() : undefined\n}\n\nexport function getDirectiveLabelOrAttribute(\n node: ContainerDirective,\n attributeName: string,\n): string | undefined {\n const label = getDirectiveLabel(node)\n const attributeValue = node.attributes?.[attributeName]\n\n if (label) return label\n return typeof attributeValue === 'string' && attributeValue.trim()\n ? attributeValue.trim()\n : undefined\n}\n"],"names":["getDirectiveLabel","node","label","data","vlDirectiveLabel","trim","undefined","getDirectiveLabelOrAttribute","attributeName","attributeValue","attributes"],"mappings":"AAEA,OAAO,SAASA,kBAAkBC,IAAwB;IACxD,MAAMC,QAAQD,KAAKE,IAAI,EAAEC;IAEzB,OAAO,OAAOF,UAAU,YAAYA,MAAMG,IAAI,KAAKH,MAAMG,IAAI,KAAKC;AACpE;AAEA,OAAO,SAASC,6BACdN,IAAwB,EACxBO,aAAqB;IAErB,MAAMN,QAAQF,kBAAkBC;IAChC,MAAMQ,iBAAiBR,KAAKS,UAAU,EAAE,CAACF,cAAc;IAEvD,IAAIN,OAAO,OAAOA;IAClB,OAAO,OAAOO,mBAAmB,YAAYA,eAAeJ,IAAI,KAC5DI,eAAeJ,IAAI,KACnBC;AACN"}
@@ -9,7 +9,7 @@ declare function getPublicDefinitions(): LayoutDirectiveDefinition[];
9
9
  declare function parseMarkdownLineDetailed(text: string): ParseMarkdownLineResult;
10
10
  declare function parseMarkdownLine(text: string): LayoutToken | null;
11
11
  export declare const layoutDirectiveRegistry: {
12
- all: readonly [LayoutDirectiveDefinition, ...LayoutDirectiveDefinition[], LayoutDirectiveDefinition, LayoutDirectiveDefinition, LayoutDirectiveDefinition, LayoutDirectiveDefinition, LayoutDirectiveDefinition, LayoutDirectiveDefinition, LayoutDirectiveDefinition, LayoutDirectiveDefinition, LayoutDirectiveDefinition];
12
+ all: readonly [LayoutDirectiveDefinition, ...LayoutDirectiveDefinition[], LayoutDirectiveDefinition, LayoutDirectiveDefinition, LayoutDirectiveDefinition, LayoutDirectiveDefinition, LayoutDirectiveDefinition, LayoutDirectiveDefinition, LayoutDirectiveDefinition, LayoutDirectiveDefinition, LayoutDirectiveDefinition, LayoutDirectiveDefinition, LayoutDirectiveDefinition];
13
13
  get: typeof getDirectiveDefinition;
14
14
  getPublicDefinitions: typeof getPublicDefinitions;
15
15
  isGridName(name: string | undefined): name is GridDirectiveName;
@@ -1,4 +1,8 @@
1
+ import { normalizePayloadMarkdownIconRef } from '../icons/refs.js';
2
+ import { getUnknownAttributeWarnings } from './attributeDiagnostics.js';
1
3
  import { parseDirectiveLine } from './attributes.js';
4
+ import { buttonDirective } from './definitions/button.js';
5
+ import { buttonsDirective } from './definitions/buttons.js';
2
6
  import { calloutDirective } from './definitions/callout.js';
3
7
  import { cardDirective } from './definitions/card.js';
4
8
  import { cardsDirective } from './definitions/cards.js';
@@ -14,6 +18,8 @@ const directiveDefinitions = [
14
18
  sectionDirective,
15
19
  ...columnDirectives,
16
20
  cellDirective,
21
+ buttonDirective,
22
+ buttonsDirective,
17
23
  calloutDirective,
18
24
  detailsDirective,
19
25
  tocDirective,
@@ -70,9 +76,38 @@ function isSupportedDirectiveName(name) {
70
76
  function getPublicDefinitions() {
71
77
  return directiveDefinitions.filter((definition)=>definition.public);
72
78
  }
73
- function findUnknownAttributes(definition, attributes) {
74
- if (!definition.allowedAttributes) return [];
75
- return Object.keys(attributes).filter((attribute)=>!definition.allowedAttributes?.includes(attribute));
79
+ const preferredLabelAttributes = new Map([
80
+ [
81
+ 'callout',
82
+ 'title'
83
+ ],
84
+ [
85
+ 'card',
86
+ 'title'
87
+ ],
88
+ [
89
+ 'details',
90
+ 'title'
91
+ ],
92
+ [
93
+ 'tab',
94
+ 'label'
95
+ ],
96
+ [
97
+ 'toc',
98
+ 'title'
99
+ ]
100
+ ]);
101
+ function getLabelConflictDiagnostics(name, label, attributes) {
102
+ const labelAttribute = preferredLabelAttributes.get(name);
103
+ if (!labelAttribute) return [];
104
+ const normalizedLabel = label?.trim();
105
+ const attributeTitle = attributes[labelAttribute];
106
+ if (!normalizedLabel || typeof attributeTitle !== 'string' || !attributeTitle.trim()) return [];
107
+ if (normalizedLabel === attributeTitle.trim()) return [];
108
+ return [
109
+ `Directive has both [Label] and ${labelAttribute}. [Label] is preferred; remove one to avoid ambiguity.`
110
+ ];
76
111
  }
77
112
  function parseMarkdownLineDetailed(text) {
78
113
  const trimmed = text.trim();
@@ -110,14 +145,18 @@ function parseMarkdownLineDetailed(text) {
110
145
  token: null
111
146
  };
112
147
  const exactMatch = definition.openMarker === trimmed;
113
- const attributedMatch = definition.supportsAttributes && trimmed.startsWith(`${definition.openMarker} `);
148
+ const attributedMatch = definition.supportsAttributes && (trimmed.startsWith(`${definition.openMarker} `) || trimmed.startsWith(`${definition.openMarker}[`) || trimmed.startsWith(`${definition.openMarker}{`));
114
149
  if (!exactMatch && !attributedMatch) return {
115
150
  diagnostics: [],
116
151
  token: null
117
152
  };
118
153
  const diagnostics = [
119
154
  ...parsed.warnings,
120
- ...findUnknownAttributes(definition, parsed.attributes).map((attribute)=>`Unknown attribute "${attribute}" on "${parsed.name}".`),
155
+ ...getUnknownAttributeWarnings(parsed.name, definition.allowedAttributes, parsed.attributes),
156
+ ...getLabelConflictDiagnostics(parsed.name, parsed.label, parsed.attributes),
157
+ ...typeof parsed.attributes.icon === 'string' ? [
158
+ normalizePayloadMarkdownIconRef(parsed.attributes.icon).warning
159
+ ].filter((warning)=>Boolean(warning)) : [],
121
160
  ...definition.validateAttributes?.({
122
161
  name: parsed.name,
123
162
  attributes: parsed.attributes
@@ -127,7 +166,8 @@ function parseMarkdownLineDetailed(text) {
127
166
  name: parsed.name,
128
167
  type: 'vlLayoutToken',
129
168
  action: 'open',
130
- attributes: parsed.attributes
169
+ attributes: parsed.attributes,
170
+ label: parsed.label
131
171
  };
132
172
  return {
133
173
  diagnostics,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/directives/registry.ts"],"sourcesContent":["import type {\n GridDirectiveName,\n LayoutDirectiveDefinition,\n LayoutName,\n LayoutToken,\n MarkdownDirectiveName,\n} from './types.js'\n\nimport { parseDirectiveLine } from './attributes.js'\nimport { calloutDirective } from './definitions/callout.js'\nimport { cardDirective } from './definitions/card.js'\nimport { cardsDirective } from './definitions/cards.js'\nimport { cellDirective } from './definitions/cell.js'\nimport { columnDirectives } from './definitions/columns.js'\nimport { detailsDirective } from './definitions/details.js'\nimport { sectionDirective } from './definitions/section.js'\nimport { stepsDirective } from './definitions/steps.js'\nimport { tabDirective } from './definitions/tab.js'\nimport { tabsDirective } from './definitions/tabs.js'\nimport { tocDirective } from './definitions/toc.js'\n\nconst directiveDefinitions = [\n sectionDirective,\n ...columnDirectives,\n cellDirective,\n calloutDirective,\n detailsDirective,\n tocDirective,\n stepsDirective,\n cardsDirective,\n cardDirective,\n tabsDirective,\n tabDirective,\n] as const satisfies readonly LayoutDirectiveDefinition[]\n\nconst closeMarkers = new Map<string, LayoutToken>([\n [':::', { type: 'vlLayoutToken', action: 'close' }],\n [':::end', { type: 'vlLayoutToken', action: 'closeSection' }],\n [':::endcol', { type: 'vlLayoutToken', action: 'closeGrid' }],\n [':::endsection', { type: 'vlLayoutToken', action: 'closeSection' }],\n])\n\nfunction cloneToken(token: LayoutToken): LayoutToken {\n return { ...token }\n}\n\ntype ParseMarkdownLineResult = {\n diagnostics: string[]\n token: LayoutToken | null\n}\n\nfunction isLayoutName(name: MarkdownDirectiveName): name is LayoutName {\n return Boolean(directiveDefinitions.find((definition) => definition.name === name)?.openMarker)\n}\n\nfunction getDirectiveDefinition(name: string): LayoutDirectiveDefinition | undefined {\n return directiveDefinitions.find((definition) => definition.name === name)\n}\n\nfunction isSupportedDirectiveName(name: string): name is MarkdownDirectiveName {\n return directiveDefinitions.some((definition) => definition.name === name)\n}\n\nfunction getPublicDefinitions(): LayoutDirectiveDefinition[] {\n return directiveDefinitions.filter((definition) => definition.public)\n}\n\nfunction findUnknownAttributes(\n definition: LayoutDirectiveDefinition,\n attributes: Record<string, boolean | string>,\n): string[] {\n if (!definition.allowedAttributes) return []\n\n return Object.keys(attributes).filter((attribute) => !definition.allowedAttributes?.includes(attribute))\n}\n\nfunction parseMarkdownLineDetailed(text: string): ParseMarkdownLineResult {\n const trimmed = text.trim()\n const closeToken = closeMarkers.get(trimmed)\n\n if (closeToken)\n return {\n diagnostics: [],\n token: cloneToken(closeToken),\n }\n\n const parsed = parseDirectiveLine(trimmed)\n if (!parsed)\n return {\n diagnostics: trimmed.startsWith(':::')\n ? ['Malformed directive marker.']\n : [],\n token: null,\n }\n\n if (!isSupportedDirectiveName(parsed.name))\n return {\n diagnostics: [`Unknown directive \"${parsed.name}\".`],\n token: null,\n }\n\n if (!isLayoutName(parsed.name))\n return {\n diagnostics: [],\n token: null,\n }\n\n const definition = getDirectiveDefinition(parsed.name)\n if (!definition?.openMarker)\n return {\n diagnostics: [],\n token: null,\n }\n\n if (!definition.supportsAttributes && parsed.rawAttributes)\n return {\n diagnostics: [`Directive \"${parsed.name}\" does not support attributes.`],\n token: null,\n }\n\n const exactMatch = definition.openMarker === trimmed\n const attributedMatch =\n definition.supportsAttributes &&\n trimmed.startsWith(`${definition.openMarker} `)\n\n if (!exactMatch && !attributedMatch)\n return {\n diagnostics: [],\n token: null,\n }\n\n const diagnostics = [\n ...parsed.warnings,\n ...findUnknownAttributes(definition, parsed.attributes).map(\n (attribute) => `Unknown attribute \"${attribute}\" on \"${parsed.name}\".`,\n ),\n ...(definition.validateAttributes?.({\n name: parsed.name,\n attributes: parsed.attributes,\n }) ?? []),\n ]\n\n const token: LayoutToken = {\n name: parsed.name,\n type: 'vlLayoutToken',\n action: 'open',\n attributes: parsed.attributes,\n }\n\n return {\n diagnostics,\n token,\n }\n}\n\nfunction parseMarkdownLine(text: string): LayoutToken | null {\n return parseMarkdownLineDetailed(text).token\n}\n\nexport const layoutDirectiveRegistry = {\n all: directiveDefinitions,\n\n get: getDirectiveDefinition,\n\n getPublicDefinitions,\n\n isGridName(name: string | undefined): name is GridDirectiveName {\n return name === '2col' || name === '3col'\n },\n\n isSupportedDirectiveName,\n\n parseMarkdownLine,\n\n parseMarkdownLineDetailed,\n}\n\nexport type { GridDirectiveName, LayoutName, LayoutToken, MarkdownDirectiveName }\n"],"names":["parseDirectiveLine","calloutDirective","cardDirective","cardsDirective","cellDirective","columnDirectives","detailsDirective","sectionDirective","stepsDirective","tabDirective","tabsDirective","tocDirective","directiveDefinitions","closeMarkers","Map","type","action","cloneToken","token","isLayoutName","name","Boolean","find","definition","openMarker","getDirectiveDefinition","isSupportedDirectiveName","some","getPublicDefinitions","filter","public","findUnknownAttributes","attributes","allowedAttributes","Object","keys","attribute","includes","parseMarkdownLineDetailed","text","trimmed","trim","closeToken","get","diagnostics","parsed","startsWith","supportsAttributes","rawAttributes","exactMatch","attributedMatch","warnings","map","validateAttributes","parseMarkdownLine","layoutDirectiveRegistry","all","isGridName"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/directives/registry.ts"],"sourcesContent":["import type {\n GridDirectiveName,\n LayoutDirectiveDefinition,\n LayoutName,\n LayoutToken,\n MarkdownDirectiveName,\n} from './types.js'\n\nimport { normalizePayloadMarkdownIconRef } from '../icons/refs.js'\nimport { getUnknownAttributeWarnings } from './attributeDiagnostics.js'\nimport { parseDirectiveLine } from './attributes.js'\nimport { buttonDirective } from './definitions/button.js'\nimport { buttonsDirective } from './definitions/buttons.js'\nimport { calloutDirective } from './definitions/callout.js'\nimport { cardDirective } from './definitions/card.js'\nimport { cardsDirective } from './definitions/cards.js'\nimport { cellDirective } from './definitions/cell.js'\nimport { columnDirectives } from './definitions/columns.js'\nimport { detailsDirective } from './definitions/details.js'\nimport { sectionDirective } from './definitions/section.js'\nimport { stepsDirective } from './definitions/steps.js'\nimport { tabDirective } from './definitions/tab.js'\nimport { tabsDirective } from './definitions/tabs.js'\nimport { tocDirective } from './definitions/toc.js'\n\nconst directiveDefinitions = [\n sectionDirective,\n ...columnDirectives,\n cellDirective,\n buttonDirective,\n buttonsDirective,\n calloutDirective,\n detailsDirective,\n tocDirective,\n stepsDirective,\n cardsDirective,\n cardDirective,\n tabsDirective,\n tabDirective,\n] as const satisfies readonly LayoutDirectiveDefinition[]\n\nconst closeMarkers = new Map<string, LayoutToken>([\n [':::', { type: 'vlLayoutToken', action: 'close' }],\n [':::end', { type: 'vlLayoutToken', action: 'closeSection' }],\n [':::endcol', { type: 'vlLayoutToken', action: 'closeGrid' }],\n [':::endsection', { type: 'vlLayoutToken', action: 'closeSection' }],\n])\n\nfunction cloneToken(token: LayoutToken): LayoutToken {\n return { ...token }\n}\n\ntype ParseMarkdownLineResult = {\n diagnostics: string[]\n token: LayoutToken | null\n}\n\nfunction isLayoutName(name: MarkdownDirectiveName): name is LayoutName {\n return Boolean(directiveDefinitions.find((definition) => definition.name === name)?.openMarker)\n}\n\nfunction getDirectiveDefinition(name: string): LayoutDirectiveDefinition | undefined {\n return directiveDefinitions.find((definition) => definition.name === name)\n}\n\nfunction isSupportedDirectiveName(name: string): name is MarkdownDirectiveName {\n return directiveDefinitions.some((definition) => definition.name === name)\n}\n\nfunction getPublicDefinitions(): LayoutDirectiveDefinition[] {\n return directiveDefinitions.filter((definition) => definition.public)\n}\n\nconst preferredLabelAttributes = new Map<string, string>([\n ['callout', 'title'],\n ['card', 'title'],\n ['details', 'title'],\n ['tab', 'label'],\n ['toc', 'title'],\n])\n\nfunction getLabelConflictDiagnostics(\n name: string,\n label: string | undefined,\n attributes: Record<string, boolean | string>,\n): string[] {\n const labelAttribute = preferredLabelAttributes.get(name)\n if (!labelAttribute) return []\n\n const normalizedLabel = label?.trim()\n const attributeTitle = attributes[labelAttribute]\n if (!normalizedLabel || typeof attributeTitle !== 'string' || !attributeTitle.trim()) return []\n if (normalizedLabel === attributeTitle.trim()) return []\n\n return [\n `Directive has both [Label] and ${labelAttribute}. [Label] is preferred; remove one to avoid ambiguity.`,\n ]\n}\n\nfunction parseMarkdownLineDetailed(text: string): ParseMarkdownLineResult {\n const trimmed = text.trim()\n const closeToken = closeMarkers.get(trimmed)\n\n if (closeToken)\n return {\n diagnostics: [],\n token: cloneToken(closeToken),\n }\n\n const parsed = parseDirectiveLine(trimmed)\n if (!parsed)\n return {\n diagnostics: trimmed.startsWith(':::')\n ? ['Malformed directive marker.']\n : [],\n token: null,\n }\n\n if (!isSupportedDirectiveName(parsed.name))\n return {\n diagnostics: [`Unknown directive \"${parsed.name}\".`],\n token: null,\n }\n\n if (!isLayoutName(parsed.name))\n return {\n diagnostics: [],\n token: null,\n }\n\n const definition = getDirectiveDefinition(parsed.name)\n if (!definition?.openMarker)\n return {\n diagnostics: [],\n token: null,\n }\n\n if (!definition.supportsAttributes && parsed.rawAttributes)\n return {\n diagnostics: [`Directive \"${parsed.name}\" does not support attributes.`],\n token: null,\n }\n\n const exactMatch = definition.openMarker === trimmed\n const attributedMatch =\n definition.supportsAttributes &&\n (trimmed.startsWith(`${definition.openMarker} `) ||\n trimmed.startsWith(`${definition.openMarker}[`) ||\n trimmed.startsWith(`${definition.openMarker}{`))\n\n if (!exactMatch && !attributedMatch)\n return {\n diagnostics: [],\n token: null,\n }\n\n const diagnostics = [\n ...parsed.warnings,\n ...getUnknownAttributeWarnings(parsed.name, definition.allowedAttributes, parsed.attributes),\n ...getLabelConflictDiagnostics(parsed.name, parsed.label, parsed.attributes),\n ...(typeof parsed.attributes.icon === 'string'\n ? [normalizePayloadMarkdownIconRef(parsed.attributes.icon).warning].filter(\n (warning): warning is string => Boolean(warning),\n )\n : []),\n ...(definition.validateAttributes?.({\n name: parsed.name,\n attributes: parsed.attributes,\n }) ?? []),\n ]\n\n const token: LayoutToken = {\n name: parsed.name,\n type: 'vlLayoutToken',\n action: 'open',\n attributes: parsed.attributes,\n label: parsed.label,\n }\n\n return {\n diagnostics,\n token,\n }\n}\n\nfunction parseMarkdownLine(text: string): LayoutToken | null {\n return parseMarkdownLineDetailed(text).token\n}\n\nexport const layoutDirectiveRegistry = {\n all: directiveDefinitions,\n\n get: getDirectiveDefinition,\n\n getPublicDefinitions,\n\n isGridName(name: string | undefined): name is GridDirectiveName {\n return name === '2col' || name === '3col'\n },\n\n isSupportedDirectiveName,\n\n parseMarkdownLine,\n\n parseMarkdownLineDetailed,\n}\n\nexport type { GridDirectiveName, LayoutName, LayoutToken, MarkdownDirectiveName }\n"],"names":["normalizePayloadMarkdownIconRef","getUnknownAttributeWarnings","parseDirectiveLine","buttonDirective","buttonsDirective","calloutDirective","cardDirective","cardsDirective","cellDirective","columnDirectives","detailsDirective","sectionDirective","stepsDirective","tabDirective","tabsDirective","tocDirective","directiveDefinitions","closeMarkers","Map","type","action","cloneToken","token","isLayoutName","name","Boolean","find","definition","openMarker","getDirectiveDefinition","isSupportedDirectiveName","some","getPublicDefinitions","filter","public","preferredLabelAttributes","getLabelConflictDiagnostics","label","attributes","labelAttribute","get","normalizedLabel","trim","attributeTitle","parseMarkdownLineDetailed","text","trimmed","closeToken","diagnostics","parsed","startsWith","supportsAttributes","rawAttributes","exactMatch","attributedMatch","warnings","allowedAttributes","icon","warning","validateAttributes","parseMarkdownLine","layoutDirectiveRegistry","all","isGridName"],"mappings":"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"}
@@ -1,3 +1,3 @@
1
- import type { ContainerDirective } from 'mdast-util-directive';
1
+ import type { ContainerDirective, LeafDirective } from 'mdast-util-directive';
2
2
  import type { LayoutDirectiveDefinition } from './types.js';
3
- export declare function setDirectiveRenderData(node: ContainerDirective, definition: LayoutDirectiveDefinition, extraProperties?: Record<string, unknown>): void;
3
+ export declare function setDirectiveRenderData(node: ContainerDirective | LeafDirective, definition: LayoutDirectiveDefinition, extraProperties?: Record<string, unknown>): void;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/directives/renderData.ts"],"sourcesContent":["import type { ContainerDirective } from 'mdast-util-directive'\n\nimport type { LayoutDirectiveDefinition } from './types.js'\n\nexport function setDirectiveRenderData(\n node: ContainerDirective,\n definition: LayoutDirectiveDefinition,\n extraProperties?: Record<string, unknown>,\n) {\n const data = (node.data ??= {})\n\n data.hName = definition.tagName\n data.hProperties = {\n ...(data.hProperties ?? {}),\n dataVlLayout: definition.name,\n ...(extraProperties ?? {}),\n }\n}\n"],"names":["setDirectiveRenderData","node","definition","extraProperties","data","hName","tagName","hProperties","dataVlLayout","name"],"mappings":"AAIA,OAAO,SAASA,uBACdC,IAAwB,EACxBC,UAAqC,EACrCC,eAAyC;IAEzC,MAAMC,OAAQH,KAAKG,IAAI,KAAK,CAAC;IAE7BA,KAAKC,KAAK,GAAGH,WAAWI,OAAO;IAC/BF,KAAKG,WAAW,GAAG;QACjB,GAAIH,KAAKG,WAAW,IAAI,CAAC,CAAC;QAC1BC,cAAcN,WAAWO,IAAI;QAC7B,GAAIN,mBAAmB,CAAC,CAAC;IAC3B;AACF"}
1
+ {"version":3,"sources":["../../src/directives/renderData.ts"],"sourcesContent":["import type { ContainerDirective, LeafDirective } from 'mdast-util-directive'\n\nimport type { LayoutDirectiveDefinition } from './types.js'\n\nexport function setDirectiveRenderData(\n node: ContainerDirective | LeafDirective,\n definition: LayoutDirectiveDefinition,\n extraProperties?: Record<string, unknown>,\n) {\n const data = (node.data ??= {})\n\n data.hName = definition.tagName\n data.hProperties = {\n ...(data.hProperties ?? {}),\n dataVlLayout: definition.name,\n ...(extraProperties ?? {}),\n }\n}\n"],"names":["setDirectiveRenderData","node","definition","extraProperties","data","hName","tagName","hProperties","dataVlLayout","name"],"mappings":"AAIA,OAAO,SAASA,uBACdC,IAAwC,EACxCC,UAAqC,EACrCC,eAAyC;IAEzC,MAAMC,OAAQH,KAAKG,IAAI,KAAK,CAAC;IAE7BA,KAAKC,KAAK,GAAGH,WAAWI,OAAO;IAC/BF,KAAKG,WAAW,GAAG;QACjB,GAAIH,KAAKG,WAAW,IAAI,CAAC,CAAC;QAC1BC,cAAcN,WAAWO,IAAI;QAC7B,GAAIN,mBAAmB,CAAC,CAAC;IAC3B;AACF"}
@@ -1,10 +1,10 @@
1
1
  import type { Element, ElementContent } from 'hast';
2
- import type { ContainerDirective } from 'mdast-util-directive';
2
+ import type { ContainerDirective, LeafDirective } from 'mdast-util-directive';
3
3
  import type { Data } from 'unist';
4
4
  import type { MarkdownRenderConfig } from '../types/core.js';
5
5
  import type { DirectiveThemeGroupName, ResolvedDirectiveTheme } from './themes.js';
6
6
  export type LayoutDirectiveName = '2col' | '3col' | 'cell' | 'section';
7
- export type StaticDirectiveName = 'callout' | 'card' | 'cards' | 'details' | 'steps' | 'tab' | 'tabs' | 'toc';
7
+ export type StaticDirectiveName = 'button' | 'buttons' | 'callout' | 'card' | 'cards' | 'details' | 'steps' | 'tab' | 'tabs' | 'toc';
8
8
  export type MarkdownDirectiveName = LayoutDirectiveName | StaticDirectiveName;
9
9
  export type GridDirectiveName = '2col' | '3col';
10
10
  export type LayoutName = MarkdownDirectiveName;
@@ -24,12 +24,14 @@ export type LayoutToken = {
24
24
  action: 'open';
25
25
  attributes?: Record<string, boolean | string>;
26
26
  data?: Data;
27
+ label?: string;
27
28
  name: LayoutName;
28
29
  type: 'vlLayoutToken';
29
30
  };
30
31
  export type DirectiveChild = ContainerDirective['children'][number];
31
- export type LayoutDirectiveKind = 'callout' | 'card' | 'cards' | 'cell' | 'details' | 'grid' | 'section' | 'steps' | 'tab' | 'tabs' | 'toc';
32
- export type LayoutDirectiveRenderTagName = 'article' | 'details' | 'div' | 'nav' | 'section';
32
+ export type MarkdownDirectiveNode = ContainerDirective | LeafDirective;
33
+ export type LayoutDirectiveKind = 'button' | 'buttons' | 'callout' | 'card' | 'cards' | 'cell' | 'details' | 'grid' | 'section' | 'steps' | 'tab' | 'tabs' | 'toc';
34
+ export type LayoutDirectiveRenderTagName = 'a' | 'article' | 'details' | 'div' | 'nav' | 'section';
33
35
  export type LayoutDirectiveTransformContext = {
34
36
  isSupportedDirectiveName: (name: string) => name is MarkdownDirectiveName;
35
37
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/directives/types.ts"],"sourcesContent":["import type { Element, ElementContent } from 'hast'\nimport type { ContainerDirective } from 'mdast-util-directive'\nimport type { Data } from 'unist'\n\nimport type { MarkdownRenderConfig } from '../types/core.js'\nimport type { DirectiveThemeGroupName, ResolvedDirectiveTheme } from './themes.js'\n\nexport type LayoutDirectiveName = '2col' | '3col' | 'cell' | 'section'\nexport type StaticDirectiveName =\n | 'callout'\n | 'card'\n | 'cards'\n | 'details'\n | 'steps'\n | 'tab'\n | 'tabs'\n | 'toc'\nexport type MarkdownDirectiveName = LayoutDirectiveName | StaticDirectiveName\nexport type GridDirectiveName = '2col' | '3col'\nexport type LayoutName = MarkdownDirectiveName\n\nexport type LayoutToken =\n | {\n action: 'close'\n data?: Data\n type: 'vlLayoutToken'\n }\n | {\n action: 'closeGrid'\n data?: Data\n type: 'vlLayoutToken'\n }\n | {\n action: 'closeSection'\n data?: Data\n type: 'vlLayoutToken'\n }\n | {\n action: 'open'\n attributes?: Record<string, boolean | string>\n data?: Data\n name: LayoutName\n type: 'vlLayoutToken'\n }\n\nexport type DirectiveChild = ContainerDirective['children'][number]\n\nexport type LayoutDirectiveKind =\n | 'callout'\n | 'card'\n | 'cards'\n | 'cell'\n | 'details'\n | 'grid'\n | 'section'\n | 'steps'\n | 'tab'\n | 'tabs'\n | 'toc'\n\nexport type LayoutDirectiveRenderTagName =\n | 'article'\n | 'details'\n | 'div'\n | 'nav'\n | 'section'\n\nexport type LayoutDirectiveTransformContext = {\n isSupportedDirectiveName: (name: string) => name is MarkdownDirectiveName\n}\n\nexport type LayoutDirectiveClassHelpers = {\n groupChildrenIntoCells: (\n children: ElementContent[],\n columnClassName?: string,\n cellTheme?: ResolvedDirectiveTheme,\n ) => ElementContent[]\n mergeClassNames: (...values: Array<string | undefined>) => string[]\n}\n\nexport type LayoutDirectiveEditorMetadata = {\n detail?: string\n label: string\n snippet: string\n snippets?: Array<{\n detail?: string\n label: string\n snippet: string\n }>\n}\n\nexport type DirectiveValidationContext = {\n attributes: Record<string, boolean | string>\n name: MarkdownDirectiveName\n}\n\nexport type LayoutDirectiveDefinition = {\n allowedAttributes?: readonly string[]\n applyHast?: (\n node: Element,\n config: MarkdownRenderConfig,\n helpers: LayoutDirectiveClassHelpers,\n ) => void\n attributeValues?: Partial<Record<string, readonly string[]>>\n defaultAttributes?: Record<string, string>\n description?: string\n editor: LayoutDirectiveEditorMetadata\n getMdastRenderProperties?: (node: ContainerDirective) => Record<string, unknown>\n kind: LayoutDirectiveKind\n name: MarkdownDirectiveName\n openMarker?: `:::${string}`\n public?: boolean\n supportsAttributes?: boolean\n tagName: LayoutDirectiveRenderTagName\n themeAttributes?: Partial<Record<string, DirectiveThemeGroupName>>\n transformMdast?: (\n node: ContainerDirective,\n context: LayoutDirectiveTransformContext,\n ) => void\n validateAttributes?: (context: DirectiveValidationContext) => string[]\n validateMdast?: (node: ContainerDirective) => string[]\n}\n"],"names":[],"mappings":"AAgGA,WAyBC"}
1
+ {"version":3,"sources":["../../src/directives/types.ts"],"sourcesContent":["import type { Element, ElementContent } from 'hast'\nimport type { ContainerDirective, LeafDirective } from 'mdast-util-directive'\nimport type { Data } from 'unist'\n\nimport type { MarkdownRenderConfig } from '../types/core.js'\nimport type { DirectiveThemeGroupName, ResolvedDirectiveTheme } from './themes.js'\n\nexport type LayoutDirectiveName = '2col' | '3col' | 'cell' | 'section'\nexport type StaticDirectiveName =\n | 'button'\n | 'buttons'\n | 'callout'\n | 'card'\n | 'cards'\n | 'details'\n | 'steps'\n | 'tab'\n | 'tabs'\n | 'toc'\nexport type MarkdownDirectiveName = LayoutDirectiveName | StaticDirectiveName\nexport type GridDirectiveName = '2col' | '3col'\nexport type LayoutName = MarkdownDirectiveName\n\nexport type LayoutToken =\n | {\n action: 'close'\n data?: Data\n type: 'vlLayoutToken'\n }\n | {\n action: 'closeGrid'\n data?: Data\n type: 'vlLayoutToken'\n }\n | {\n action: 'closeSection'\n data?: Data\n type: 'vlLayoutToken'\n }\n | {\n action: 'open'\n attributes?: Record<string, boolean | string>\n data?: Data\n label?: string\n name: LayoutName\n type: 'vlLayoutToken'\n }\n\nexport type DirectiveChild = ContainerDirective['children'][number]\nexport type MarkdownDirectiveNode = ContainerDirective | LeafDirective\n\nexport type LayoutDirectiveKind =\n | 'button'\n | 'buttons'\n | 'callout'\n | 'card'\n | 'cards'\n | 'cell'\n | 'details'\n | 'grid'\n | 'section'\n | 'steps'\n | 'tab'\n | 'tabs'\n | 'toc'\n\nexport type LayoutDirectiveRenderTagName =\n | 'a'\n | 'article'\n | 'details'\n | 'div'\n | 'nav'\n | 'section'\n\nexport type LayoutDirectiveTransformContext = {\n isSupportedDirectiveName: (name: string) => name is MarkdownDirectiveName\n}\n\nexport type LayoutDirectiveClassHelpers = {\n groupChildrenIntoCells: (\n children: ElementContent[],\n columnClassName?: string,\n cellTheme?: ResolvedDirectiveTheme,\n ) => ElementContent[]\n mergeClassNames: (...values: Array<string | undefined>) => string[]\n}\n\nexport type LayoutDirectiveEditorMetadata = {\n detail?: string\n label: string\n snippet: string\n snippets?: Array<{\n detail?: string\n label: string\n snippet: string\n }>\n}\n\nexport type DirectiveValidationContext = {\n attributes: Record<string, boolean | string>\n name: MarkdownDirectiveName\n}\n\nexport type LayoutDirectiveDefinition = {\n allowedAttributes?: readonly string[]\n applyHast?: (\n node: Element,\n config: MarkdownRenderConfig,\n helpers: LayoutDirectiveClassHelpers,\n ) => void\n attributeValues?: Partial<Record<string, readonly string[]>>\n defaultAttributes?: Record<string, string>\n description?: string\n editor: LayoutDirectiveEditorMetadata\n getMdastRenderProperties?: (node: ContainerDirective) => Record<string, unknown>\n kind: LayoutDirectiveKind\n name: MarkdownDirectiveName\n openMarker?: `:::${string}`\n public?: boolean\n supportsAttributes?: boolean\n tagName: LayoutDirectiveRenderTagName\n themeAttributes?: Partial<Record<string, DirectiveThemeGroupName>>\n transformMdast?: (\n node: ContainerDirective,\n context: LayoutDirectiveTransformContext,\n ) => void\n validateAttributes?: (context: DirectiveValidationContext) => string[]\n validateMdast?: (node: ContainerDirective) => string[]\n}\n"],"names":[],"mappings":"AAuGA,WAyBC"}
@@ -4,6 +4,7 @@ import { defaultKeymap, history, historyKeymap } from '@codemirror/commands';
4
4
  import { EditorState } from '@codemirror/state';
5
5
  import { placeholder as cmPlaceholder, EditorView, keymap } from '@codemirror/view';
6
6
  import React, { useEffect, useRef } from 'react';
7
+ import { directiveCloseLabels } from '../directives/closeLabels.js';
7
8
  import { directiveCompletions } from '../directives/completions.js';
8
9
  import { directiveDiagnostics } from '../directives/diagnostics.js';
9
10
  import { payloadMarkdownTheme } from '../themes/payload.js';
@@ -23,6 +24,7 @@ export const MarkdownCodeMirrorClient = ({ onChangeAction, placeholder = 'Write
23
24
  EditorView.lineWrapping,
24
25
  cmPlaceholder(placeholder),
25
26
  payloadMarkdownTheme,
27
+ directiveCloseLabels,
26
28
  directiveCompletions,
27
29
  directiveDiagnostics,
28
30
  EditorView.updateListener.of((update)=>{
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/editor/MarkdownCodeMirror/Component.client.tsx"],"sourcesContent":["'use client'\n\nimport { defaultKeymap, history, historyKeymap } from '@codemirror/commands'\nimport { EditorState } from '@codemirror/state'\nimport { placeholder as cmPlaceholder, EditorView, keymap } from '@codemirror/view'\nimport React, { useEffect, useRef } from 'react'\n\nimport { directiveCompletions } from '../directives/completions.js'\nimport { directiveDiagnostics } from '../directives/diagnostics.js'\nimport { payloadMarkdownTheme } from '../themes/payload.js'\n\ntype MarkdownCodeMirrorClientProps = {\n onChangeAction: (value: string) => void\n placeholder?: string\n value?: string\n}\n\nexport const MarkdownCodeMirrorClient: React.FC<MarkdownCodeMirrorClientProps> = ({\n onChangeAction,\n placeholder = 'Write markdown...',\n value = '',\n}) => {\n const containerRef = useRef<HTMLDivElement | null>(null)\n const viewRef = useRef<EditorView | null>(null)\n\n useEffect(() => {\n if (!containerRef.current || viewRef.current) return\n\n const state = EditorState.create({\n doc: value,\n extensions: [\n history(),\n keymap.of([...defaultKeymap, ...historyKeymap]),\n EditorView.lineWrapping,\n cmPlaceholder(placeholder),\n payloadMarkdownTheme,\n directiveCompletions,\n directiveDiagnostics,\n EditorView.updateListener.of((update) => {\n if (!update.docChanged) return\n onChangeAction(update.state.doc.toString())\n }),\n ],\n })\n\n viewRef.current = new EditorView({\n parent: containerRef.current,\n state,\n })\n\n return () => {\n viewRef.current?.destroy()\n viewRef.current = null\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [onChangeAction, placeholder])\n\n useEffect(() => {\n const view = viewRef.current\n if (!view) return\n\n const current = view.state.doc.toString()\n if (current === value) return\n\n view.dispatch({\n changes: {\n from: 0,\n insert: value,\n to: current.length,\n },\n })\n }, [value])\n\n return (\n <div\n style={{\n border: '1px solid rgba(120, 120, 120, .5)',\n borderRadius: '5px',\n maxHeight: '80vh',\n minHeight: '125px',\n overflowX: 'hidden',\n overflowY: 'scroll',\n padding: '6px 0',\n }}\n >\n <div ref={containerRef} />\n </div>\n )\n}\n"],"names":["defaultKeymap","history","historyKeymap","EditorState","placeholder","cmPlaceholder","EditorView","keymap","React","useEffect","useRef","directiveCompletions","directiveDiagnostics","payloadMarkdownTheme","MarkdownCodeMirrorClient","onChangeAction","value","containerRef","viewRef","current","state","create","doc","extensions","of","lineWrapping","updateListener","update","docChanged","toString","parent","destroy","view","dispatch","changes","from","insert","to","length","div","style","border","borderRadius","maxHeight","minHeight","overflowX","overflowY","padding","ref"],"mappings":"AAAA;;AAEA,SAASA,aAAa,EAAEC,OAAO,EAAEC,aAAa,QAAQ,uBAAsB;AAC5E,SAASC,WAAW,QAAQ,oBAAmB;AAC/C,SAASC,eAAeC,aAAa,EAAEC,UAAU,EAAEC,MAAM,QAAQ,mBAAkB;AACnF,OAAOC,SAASC,SAAS,EAAEC,MAAM,QAAQ,QAAO;AAEhD,SAASC,oBAAoB,QAAQ,+BAA8B;AACnE,SAASC,oBAAoB,QAAQ,+BAA8B;AACnE,SAASC,oBAAoB,QAAQ,uBAAsB;AAQ3D,OAAO,MAAMC,2BAAoE,CAAC,EAChFC,cAAc,EACdX,cAAc,mBAAmB,EACjCY,QAAQ,EAAE,EACX;IACC,MAAMC,eAAeP,OAA8B;IACnD,MAAMQ,UAAUR,OAA0B;IAE1CD,UAAU;QACR,IAAI,CAACQ,aAAaE,OAAO,IAAID,QAAQC,OAAO,EAAE;QAE9C,MAAMC,QAAQjB,YAAYkB,MAAM,CAAC;YAC/BC,KAAKN;YACLO,YAAY;gBACVtB;gBACAM,OAAOiB,EAAE,CAAC;uBAAIxB;uBAAkBE;iBAAc;gBAC9CI,WAAWmB,YAAY;gBACvBpB,cAAcD;gBACdS;gBACAF;gBACAC;gBACAN,WAAWoB,cAAc,CAACF,EAAE,CAAC,CAACG;oBAC5B,IAAI,CAACA,OAAOC,UAAU,EAAE;oBACxBb,eAAeY,OAAOP,KAAK,CAACE,GAAG,CAACO,QAAQ;gBAC1C;aACD;QACH;QAEAX,QAAQC,OAAO,GAAG,IAAIb,WAAW;YAC/BwB,QAAQb,aAAaE,OAAO;YAC5BC;QACF;QAEA,OAAO;YACLF,QAAQC,OAAO,EAAEY;YACjBb,QAAQC,OAAO,GAAG;QACpB;IACA,uDAAuD;IACzD,GAAG;QAACJ;QAAgBX;KAAY;IAEhCK,UAAU;QACR,MAAMuB,OAAOd,QAAQC,OAAO;QAC5B,IAAI,CAACa,MAAM;QAEX,MAAMb,UAAUa,KAAKZ,KAAK,CAACE,GAAG,CAACO,QAAQ;QACvC,IAAIV,YAAYH,OAAO;QAEvBgB,KAAKC,QAAQ,CAAC;YACZC,SAAS;gBACPC,MAAM;gBACNC,QAAQpB;gBACRqB,IAAIlB,QAAQmB,MAAM;YACpB;QACF;IACF,GAAG;QAACtB;KAAM;IAEV,qBACE,KAACuB;QACCC,OAAO;YACLC,QAAQ;YACRC,cAAc;YACdC,WAAW;YACXC,WAAW;YACXC,WAAW;YACXC,WAAW;YACXC,SAAS;QACX;kBAEA,cAAA,KAACR;YAAIS,KAAK/B;;;AAGhB,EAAC"}
1
+ {"version":3,"sources":["../../../src/editor/MarkdownCodeMirror/Component.client.tsx"],"sourcesContent":["'use client'\n\nimport { defaultKeymap, history, historyKeymap } from '@codemirror/commands'\nimport { EditorState } from '@codemirror/state'\nimport { placeholder as cmPlaceholder, EditorView, keymap } from '@codemirror/view'\nimport React, { useEffect, useRef } from 'react'\n\nimport { directiveCloseLabels } from '../directives/closeLabels.js'\nimport { directiveCompletions } from '../directives/completions.js'\nimport { directiveDiagnostics } from '../directives/diagnostics.js'\nimport { payloadMarkdownTheme } from '../themes/payload.js'\n\ntype MarkdownCodeMirrorClientProps = {\n onChangeAction: (value: string) => void\n placeholder?: string\n value?: string\n}\n\nexport const MarkdownCodeMirrorClient: React.FC<MarkdownCodeMirrorClientProps> = ({\n onChangeAction,\n placeholder = 'Write markdown...',\n value = '',\n}) => {\n const containerRef = useRef<HTMLDivElement | null>(null)\n const viewRef = useRef<EditorView | null>(null)\n\n useEffect(() => {\n if (!containerRef.current || viewRef.current) return\n\n const state = EditorState.create({\n doc: value,\n extensions: [\n history(),\n keymap.of([...defaultKeymap, ...historyKeymap]),\n EditorView.lineWrapping,\n cmPlaceholder(placeholder),\n payloadMarkdownTheme,\n directiveCloseLabels,\n directiveCompletions,\n directiveDiagnostics,\n EditorView.updateListener.of((update) => {\n if (!update.docChanged) return\n onChangeAction(update.state.doc.toString())\n }),\n ],\n })\n\n viewRef.current = new EditorView({\n parent: containerRef.current,\n state,\n })\n\n return () => {\n viewRef.current?.destroy()\n viewRef.current = null\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [onChangeAction, placeholder])\n\n useEffect(() => {\n const view = viewRef.current\n if (!view) return\n\n const current = view.state.doc.toString()\n if (current === value) return\n\n view.dispatch({\n changes: {\n from: 0,\n insert: value,\n to: current.length,\n },\n })\n }, [value])\n\n return (\n <div\n style={{\n border: '1px solid rgba(120, 120, 120, .5)',\n borderRadius: '5px',\n maxHeight: '80vh',\n minHeight: '125px',\n overflowX: 'hidden',\n overflowY: 'scroll',\n padding: '6px 0',\n }}\n >\n <div ref={containerRef} />\n </div>\n )\n}\n"],"names":["defaultKeymap","history","historyKeymap","EditorState","placeholder","cmPlaceholder","EditorView","keymap","React","useEffect","useRef","directiveCloseLabels","directiveCompletions","directiveDiagnostics","payloadMarkdownTheme","MarkdownCodeMirrorClient","onChangeAction","value","containerRef","viewRef","current","state","create","doc","extensions","of","lineWrapping","updateListener","update","docChanged","toString","parent","destroy","view","dispatch","changes","from","insert","to","length","div","style","border","borderRadius","maxHeight","minHeight","overflowX","overflowY","padding","ref"],"mappings":"AAAA;;AAEA,SAASA,aAAa,EAAEC,OAAO,EAAEC,aAAa,QAAQ,uBAAsB;AAC5E,SAASC,WAAW,QAAQ,oBAAmB;AAC/C,SAASC,eAAeC,aAAa,EAAEC,UAAU,EAAEC,MAAM,QAAQ,mBAAkB;AACnF,OAAOC,SAASC,SAAS,EAAEC,MAAM,QAAQ,QAAO;AAEhD,SAASC,oBAAoB,QAAQ,+BAA8B;AACnE,SAASC,oBAAoB,QAAQ,+BAA8B;AACnE,SAASC,oBAAoB,QAAQ,+BAA8B;AACnE,SAASC,oBAAoB,QAAQ,uBAAsB;AAQ3D,OAAO,MAAMC,2BAAoE,CAAC,EAChFC,cAAc,EACdZ,cAAc,mBAAmB,EACjCa,QAAQ,EAAE,EACX;IACC,MAAMC,eAAeR,OAA8B;IACnD,MAAMS,UAAUT,OAA0B;IAE1CD,UAAU;QACR,IAAI,CAACS,aAAaE,OAAO,IAAID,QAAQC,OAAO,EAAE;QAE9C,MAAMC,QAAQlB,YAAYmB,MAAM,CAAC;YAC/BC,KAAKN;YACLO,YAAY;gBACVvB;gBACAM,OAAOkB,EAAE,CAAC;uBAAIzB;uBAAkBE;iBAAc;gBAC9CI,WAAWoB,YAAY;gBACvBrB,cAAcD;gBACdU;gBACAH;gBACAC;gBACAC;gBACAP,WAAWqB,cAAc,CAACF,EAAE,CAAC,CAACG;oBAC5B,IAAI,CAACA,OAAOC,UAAU,EAAE;oBACxBb,eAAeY,OAAOP,KAAK,CAACE,GAAG,CAACO,QAAQ;gBAC1C;aACD;QACH;QAEAX,QAAQC,OAAO,GAAG,IAAId,WAAW;YAC/ByB,QAAQb,aAAaE,OAAO;YAC5BC;QACF;QAEA,OAAO;YACLF,QAAQC,OAAO,EAAEY;YACjBb,QAAQC,OAAO,GAAG;QACpB;IACA,uDAAuD;IACzD,GAAG;QAACJ;QAAgBZ;KAAY;IAEhCK,UAAU;QACR,MAAMwB,OAAOd,QAAQC,OAAO;QAC5B,IAAI,CAACa,MAAM;QAEX,MAAMb,UAAUa,KAAKZ,KAAK,CAACE,GAAG,CAACO,QAAQ;QACvC,IAAIV,YAAYH,OAAO;QAEvBgB,KAAKC,QAAQ,CAAC;YACZC,SAAS;gBACPC,MAAM;gBACNC,QAAQpB;gBACRqB,IAAIlB,QAAQmB,MAAM;YACpB;QACF;IACF,GAAG;QAACtB;KAAM;IAEV,qBACE,KAACuB;QACCC,OAAO;YACLC,QAAQ;YACRC,cAAc;YACdC,WAAW;YACXC,WAAW;YACXC,WAAW;YACXC,WAAW;YACXC,SAAS;QACX;kBAEA,cAAA,KAACR;YAAIS,KAAK/B;;;AAGhB,EAAC"}
@@ -0,0 +1,2 @@
1
+ import type { Extension } from '@codemirror/state';
2
+ export declare const directiveCloseLabels: Extension;