@airalogy/aimd-renderer 2.5.0 → 2.6.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.
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Vue rendering exports
3
3
  */
4
- export { type AimdComponentRenderer, type AimdRendererContext, type AssetResolver, createAssetRenderer, createCodeBlockRenderer, createComponentRenderer, createEmbeddedRenderer, createMermaidRenderer, createStepCardRenderer, type ElementRenderer, hastToVue, renderToVNodes, type AimdStepCardRendererOptions, type ShikiHighlighter, type VueRendererOptions, } from './vue-renderer';
4
+ export { type AimdComponentRenderer, type AimdRendererContext, type AssetResolver, createAssetRenderer, createCodeBlockRenderer, createComponentRenderer, createEmbeddedRenderer, createMermaidRenderer, createStepCardRenderer, loadShikiHighlighter, type CodeBlockRendererOptions, type ElementRenderer, hastToVue, renderToVNodes, type LoadShikiHighlighterOptions, type AimdStepCardRendererOptions, type ShikiHighlighter, type VueRendererOptions, } from './vue-renderer';
5
5
  export { renderToVue, createRenderer, defaultRenderer, } from '../common/processor';
6
6
  export { createAimdRendererMessages, DEFAULT_AIMD_RENDERER_LOCALE, resolveAimdRendererLocale, } from '../locales';
7
7
  export type { RenderContext, RenderMode, ProcessorOptions, } from '@airalogy/aimd-core/types';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/vue/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACL,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB,EACxB,KAAK,aAAa,EAClB,mBAAmB,EACnB,uBAAuB,EACvB,uBAAuB,EACvB,sBAAsB,EACtB,qBAAqB,EACrB,sBAAsB,EACtB,KAAK,eAAe,EACpB,SAAS,EACT,cAAc,EACd,KAAK,2BAA2B,EAChC,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,GACxB,MAAM,gBAAgB,CAAA;AAEvB,OAAO,EACL,WAAW,EACX,cAAc,EACd,eAAe,GAChB,MAAM,qBAAqB,CAAA;AAE5B,OAAO,EACL,0BAA0B,EAC1B,4BAA4B,EAC5B,yBAAyB,GAC1B,MAAM,YAAY,CAAA;AAEnB,YAAY,EACV,aAAa,EACb,UAAU,EACV,gBAAgB,GACjB,MAAM,2BAA2B,CAAA;AAElC,YAAY,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AACpG,YAAY,EACV,uBAAuB,EACvB,kBAAkB,EAClB,oBAAoB,EACpB,yBAAyB,GAC1B,MAAM,YAAY,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/vue/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACL,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB,EACxB,KAAK,aAAa,EAClB,mBAAmB,EACnB,uBAAuB,EACvB,uBAAuB,EACvB,sBAAsB,EACtB,qBAAqB,EACrB,sBAAsB,EACtB,oBAAoB,EACpB,KAAK,wBAAwB,EAC7B,KAAK,eAAe,EACpB,SAAS,EACT,cAAc,EACd,KAAK,2BAA2B,EAChC,KAAK,2BAA2B,EAChC,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,GACxB,MAAM,gBAAgB,CAAA;AAEvB,OAAO,EACL,WAAW,EACX,cAAc,EACd,eAAe,GAChB,MAAM,qBAAqB,CAAA;AAE5B,OAAO,EACL,0BAA0B,EAC1B,4BAA4B,EAC5B,yBAAyB,GAC1B,MAAM,YAAY,CAAA;AAEnB,YAAY,EACV,aAAa,EACb,UAAU,EACV,gBAAgB,GACjB,MAAM,2BAA2B,CAAA;AAElC,YAAY,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AACpG,YAAY,EACV,uBAAuB,EACvB,kBAAkB,EAClB,oBAAoB,EACpB,yBAAyB,GAC1B,MAAM,YAAY,CAAA"}
@@ -97,6 +97,16 @@ export interface ShikiHighlighter {
97
97
  lang: string;
98
98
  theme: string;
99
99
  }) => string;
100
+ codeToTokensBase?: (code: string, options: {
101
+ lang: string;
102
+ theme: string;
103
+ }) => Array<Array<{
104
+ content: string;
105
+ color?: string;
106
+ bgColor?: string;
107
+ fontStyle?: number;
108
+ htmlStyle?: string | Record<string, string>;
109
+ }>>;
100
110
  codeToTokensWithThemes?: (code: string, options: {
101
111
  lang: string;
102
112
  themes: Record<string, string>;
@@ -107,12 +117,23 @@ export interface ShikiHighlighter {
107
117
  }>;
108
118
  }>>;
109
119
  }
120
+ export interface CodeBlockRendererOptions {
121
+ theme?: string;
122
+ lineNumbers?: boolean;
123
+ wrap?: boolean;
124
+ className?: string;
125
+ }
126
+ export interface LoadShikiHighlighterOptions {
127
+ themes?: string[];
128
+ langs?: string[];
129
+ }
130
+ export declare function loadShikiHighlighter(options?: LoadShikiHighlighterOptions): Promise<ShikiHighlighter>;
110
131
  /**
111
132
  * Create code block element renderer with Shiki support
112
133
  * @param highlighter - Shiki highlighter instance (can be reactive ref)
113
134
  * @param defaultTheme - Default theme to use
114
135
  */
115
- export declare function createCodeBlockRenderer(highlighter: ShikiHighlighter | null | (() => ShikiHighlighter | null), defaultTheme?: string): ElementRenderer;
136
+ export declare function createCodeBlockRenderer(highlighter: ShikiHighlighter | null | (() => ShikiHighlighter | null), optionsOrTheme?: string | CodeBlockRendererOptions): ElementRenderer;
116
137
  /**
117
138
  * Create Mermaid diagram element renderer
118
139
  * @param MermaidComponent - Vue component to render Mermaid diagrams
@@ -1 +1 @@
1
- {"version":3,"file":"vue-renderer.d.ts","sourceRoot":"","sources":["../../src/vue/vue-renderer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"vue-renderer.d.ts","sourceRoot":"","sources":["../../src/vue/vue-renderer.ts"],"names":[],"mappings":"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"}
package/dist/vue.js CHANGED
@@ -1,17 +1,18 @@
1
- import { D as a, c as d, f as s, g as n, h as t, i as o, j as R, k as c, l as m, m as A, n as E, o as l, q as i, e as C } from "./processor-B2mByErv.js";
1
+ import { D as a, c as s, f as d, g as n, h as t, i as o, j as R, k as c, l as i, m as l, n as m, o as A, q as E, s as h, e as g } from "./processor-CHbNEcN8.js";
2
2
  export {
3
3
  a as DEFAULT_AIMD_RENDERER_LOCALE,
4
- d as createAimdRendererMessages,
5
- s as createAssetRenderer,
4
+ s as createAimdRendererMessages,
5
+ d as createAssetRenderer,
6
6
  n as createCodeBlockRenderer,
7
7
  t as createComponentRenderer,
8
8
  o as createEmbeddedRenderer,
9
9
  R as createMermaidRenderer,
10
10
  c as createRenderer,
11
- m as createStepCardRenderer,
12
- A as defaultRenderer,
13
- E as hastToVue,
14
- l as renderToVNodes,
15
- i as renderToVue,
16
- C as resolveAimdRendererLocale
11
+ i as createStepCardRenderer,
12
+ l as defaultRenderer,
13
+ m as hastToVue,
14
+ A as loadShikiHighlighter,
15
+ E as renderToVNodes,
16
+ h as renderToVue,
17
+ g as resolveAimdRendererLocale
17
18
  };
package/package.json CHANGED
@@ -1,18 +1,18 @@
1
1
  {
2
2
  "name": "@airalogy/aimd-renderer",
3
3
  "type": "module",
4
- "version": "2.5.0",
4
+ "version": "2.6.0",
5
5
  "description": "AIMD (Airalogy Markdown) rendering engines for HTML and Vue",
6
6
  "license": "Apache-2.0",
7
7
  "repository": {
8
8
  "type": "git",
9
- "url": "https://github.com/airalogy/aimd.git",
10
- "directory": "packages/aimd-renderer"
9
+ "url": "https://github.com/airalogy/airalogy.git",
10
+ "directory": "packages/npm/aimd-renderer"
11
11
  },
12
12
  "bugs": {
13
- "url": "https://github.com/airalogy/aimd/issues"
13
+ "url": "https://github.com/airalogy/airalogy/issues"
14
14
  },
15
- "homepage": "https://github.com/airalogy/aimd/tree/main/packages/aimd-renderer#readme",
15
+ "homepage": "https://github.com/airalogy/airalogy/tree/main/packages/npm/aimd-renderer#readme",
16
16
  "keywords": [
17
17
  "aimd",
18
18
  "markdown",
@@ -64,7 +64,7 @@
64
64
  "shiki": "^2.5.0",
65
65
  "unified": "^11.0.5",
66
66
  "vfile": "^6.0.3",
67
- "@airalogy/aimd-core": "^2.6.0"
67
+ "@airalogy/aimd-core": "^2.8.0"
68
68
  },
69
69
  "devDependencies": {
70
70
  "@types/node": "^24.3.0",
@@ -9,7 +9,7 @@ import {
9
9
  createRenderer,
10
10
  } from '../common/processor'
11
11
  import { getFinalIndent, parseFieldTag } from '../index'
12
- import { createStepCardRenderer } from '../vue/vue-renderer'
12
+ import { createCodeBlockRenderer, createStepCardRenderer } from '../vue/vue-renderer'
13
13
 
14
14
  function findVNodeByType(node: any, expectedType: string): any | null {
15
15
  if (!node || typeof node !== 'object') {
@@ -149,6 +149,38 @@ describe('parseAndExtract', () => {
149
149
  expect(fields.var).toContain('age')
150
150
  expect(fields.step.length).toBeGreaterThan(0)
151
151
  })
152
+
153
+ it('extracts multiline var tables with object-list defaults', () => {
154
+ const content = `{{var|monitoring_sites: list[MonitoringSite] = [
155
+ {"site_id": "S01", "latitude": 30.0, "longitude": 120.0, "elevation_m": 128.0},
156
+ {"site_id": "S02", "latitude": 30.1, "longitude": 120.1, "elevation_m": 82.0}
157
+ ],
158
+ title = "Monitoring sites",
159
+ subvars = [
160
+ var(site_id: str, title = "Site ID"),
161
+ var(latitude: float, title = "Latitude"),
162
+ var(longitude: float, title = "Longitude"),
163
+ var(elevation_m: float, title = "Elevation")
164
+ ]
165
+ }}`
166
+ const fields = parseAndExtract(content)
167
+
168
+ expect(fields.var_table[0]).toMatchObject({
169
+ id: 'monitoring_sites',
170
+ title: 'Monitoring sites',
171
+ type_annotation: 'list[MonitoringSite]',
172
+ default: [
173
+ { site_id: 'S01', latitude: 30, longitude: 120, elevation_m: 128 },
174
+ { site_id: 'S02', latitude: 30.1, longitude: 120.1, elevation_m: 82 },
175
+ ],
176
+ })
177
+ expect(fields.var_table[0]?.subvars.map(subvar => subvar.id)).toEqual([
178
+ 'site_id',
179
+ 'latitude',
180
+ 'longitude',
181
+ 'elevation_m',
182
+ ])
183
+ })
152
184
  })
153
185
 
154
186
  // ---------------------------------------------------------------------------
@@ -168,6 +200,51 @@ describe('renderToHtmlSync', () => {
168
200
  expect(html).toContain('temperature')
169
201
  })
170
202
 
203
+ it('renders AIMD var field display metadata', () => {
204
+ const { html, fields } = renderToHtmlSync('{{var|record_date: str, title="Record date", description="ISO date", examples=["2026-05-26", "2026-05-27"]}}')
205
+ expect(fields.var_definitions?.[0]?.title).toBe('Record date')
206
+ expect(fields.var_definitions?.[0]?.description).toBe('ISO date')
207
+ expect(fields.var_definitions?.[0]?.examples).toEqual(['2026-05-26', '2026-05-27'])
208
+ expect(html).toContain('data-aimd-title="Record date"')
209
+ expect(html).toContain('data-aimd-description="ISO date"')
210
+ expect(html).toContain('data-aimd-examples="2026-05-26, 2026-05-27"')
211
+ expect(html).toContain('Record date')
212
+ expect(html).toContain('record_date')
213
+ expect(html).toContain('ISO date')
214
+ expect(html).toContain('aria-label="ISO date')
215
+ expect(html).not.toContain('title="ISO date')
216
+ expect(html).not.toContain('aimd-field__description')
217
+ expect(html).toContain('aimd-field__metadata-popover')
218
+ expect(html).toContain('aimd-field__metadata-examples')
219
+ expect(html).toContain('aimd-field__metadata-example')
220
+ expect(html).toContain('tabindex="0"')
221
+ expect(html).toContain('2026-05-26')
222
+ })
223
+
224
+ it('renders AIMD var_table and column display metadata', () => {
225
+ const { html, fields } = renderToHtmlSync('{{var_table|samples, title="Samples", description="Measured rows", examples=["S-001 row"], subvars=[var(sample_id: str, title="Sample ID", description="Tube identifier", examples=["S-001"])]}}')
226
+ expect(fields.var_table[0]?.title).toBe('Samples')
227
+ expect(fields.var_table[0]?.description).toBe('Measured rows')
228
+ expect(fields.var_table[0]?.examples).toEqual(['S-001 row'])
229
+ expect(fields.var_table[0]?.subvars[0]?.title).toBe('Sample ID')
230
+ expect(fields.var_table[0]?.subvars[0]?.examples).toEqual(['S-001'])
231
+ expect(html).toContain('Samples')
232
+ expect(html).toContain('samples')
233
+ expect(html).toContain('Measured rows')
234
+ expect(html).toContain('S-001 row')
235
+ expect(html).toContain('data-column-id="sample_id"')
236
+ expect(html).toContain('Sample ID')
237
+ expect(html).toContain('Tube identifier')
238
+ expect(html).toContain('aria-label="Measured rows')
239
+ expect(html).toContain('aria-label="Tube identifier')
240
+ expect(html).not.toContain('title="Measured rows')
241
+ expect(html).not.toContain('title="Tube identifier')
242
+ expect(html).not.toContain('aimd-field__description')
243
+ expect(html).toContain('aimd-field__metadata-popover')
244
+ expect(html).toContain('aimd-field__metadata-example')
245
+ expect(html).toContain('S-001')
246
+ })
247
+
171
248
  it('returns extracted fields alongside HTML', () => {
172
249
  const { fields } = renderToHtmlSync('{{step|wash}} and {{check|verify}}')
173
250
  expect(fields.step.length).toBeGreaterThan(0)
@@ -201,6 +278,31 @@ describe('renderToHtmlSync', () => {
201
278
  expect(html).toContain('Answer: true')
202
279
  })
203
280
 
281
+ it('extracts true/false option followups', () => {
282
+ const { fields } = renderToHtmlSync(
283
+ [
284
+ '```quiz',
285
+ 'id: q_true_false_followups',
286
+ 'type: true_false',
287
+ 'stem: "Was precipitate observed?"',
288
+ 'options:',
289
+ ' - key: true',
290
+ ' text: "Yes"',
291
+ ' followups:',
292
+ ' - key: color',
293
+ ' type: str',
294
+ ' title: Color',
295
+ ' - key: false',
296
+ ' text: "No"',
297
+ '```',
298
+ ].join('\n'),
299
+ )
300
+
301
+ expect(fields.quiz[0].options?.[0]?.followups).toEqual([
302
+ { key: 'color', type: 'str', required: true, title: 'Color' },
303
+ ])
304
+ })
305
+
204
306
  it('supports host custom element renderers for AIMD nodes', () => {
205
307
  const { html } = renderToHtmlSync(
206
308
  "{{step|verify, 2, title='Verify Output', subtitle='Cross-check', check=True, result=True}}\n\nStep body content.",
@@ -303,6 +405,94 @@ describe('renderToHtmlSync', () => {
303
405
  })
304
406
 
305
407
  describe('renderToVue', () => {
408
+ it('renders code blocks with line numbers and wrapping classes', async () => {
409
+ const { nodes } = await renderToVue(
410
+ '```json\n{\n "model":"qwen3.6-flash","enable_search":true\n}\n```',
411
+ {
412
+ elementRenderers: {
413
+ pre: createCodeBlockRenderer(null, {
414
+ lineNumbers: true,
415
+ wrap: true,
416
+ }),
417
+ },
418
+ },
419
+ )
420
+
421
+ const pre = findVNodeByType(nodes[0], 'pre') as any
422
+ expect(pre).toBeTruthy()
423
+ expect(pre.props.class).toContain('aimd-code-block')
424
+ expect(pre.props.class).toContain('aimd-code-block--line-numbers')
425
+ expect(pre.props.class).toContain('aimd-code-block--wrap')
426
+ expect(pre.props['data-lang']).toBe('json')
427
+ const code = findVNodeByType(pre, 'code') as any
428
+ expect(code.children).toHaveLength(3)
429
+ expect(code.children[1].children[1].props.style['--aimd-code-wrap-indent']).toBe('2ch')
430
+ expect(collectVNodeText(pre)).toContain('1')
431
+ expect(collectVNodeText(pre)).toContain('qwen3.6-flash')
432
+ })
433
+
434
+ it('keeps blank code lines visible without adding an extra line for the trailing markdown fence newline', async () => {
435
+ const { nodes } = await renderToVue(
436
+ '```json\n{\n\n "model": "qwen3.6-flash"\n}\n```',
437
+ {
438
+ elementRenderers: {
439
+ pre: createCodeBlockRenderer(null, {
440
+ lineNumbers: true,
441
+ wrap: true,
442
+ }),
443
+ },
444
+ },
445
+ )
446
+
447
+ const pre = findVNodeByType(nodes[0], 'pre') as any
448
+ const code = findVNodeByType(pre, 'code') as any
449
+ expect(code.children).toHaveLength(4)
450
+ expect(code.children[1].children[1].children).toBe('\u00a0')
451
+ expect(code.children[2].children[1].props.style['--aimd-code-wrap-indent']).toBe('2ch')
452
+ })
453
+
454
+ it('uses Shiki token output when a highlighter is available', async () => {
455
+ const highlighter = {
456
+ codeToHtml: (code: string) => code,
457
+ codeToTokensBase: () => [
458
+ [
459
+ { content: ' ', color: '#24292e' },
460
+ { content: '"model"', color: '#005cc5' },
461
+ ],
462
+ ],
463
+ }
464
+ const { nodes } = await renderToVue('```json\n "model"\n```', {
465
+ elementRenderers: {
466
+ pre: createCodeBlockRenderer(highlighter, {
467
+ lineNumbers: true,
468
+ wrap: true,
469
+ }),
470
+ },
471
+ })
472
+
473
+ const pre = findVNodeByType(nodes[0], 'pre') as any
474
+ const code = findVNodeByType(pre, 'code') as any
475
+ const tokenSpans = code.children[0].children[1].children
476
+ expect(tokenSpans[0].props.style).toEqual({ color: '#24292e' })
477
+ expect(tokenSpans[1].props.style).toEqual({ color: '#005cc5' })
478
+ expect(tokenSpans[1].children).toBe('"model"')
479
+ })
480
+
481
+ it('keeps the legacy plain pre fallback when called with a theme string and no highlighter', async () => {
482
+ const { nodes } = await renderToVue('```json\n{"model":"qwen"}\n```', {
483
+ elementRenderers: {
484
+ pre: createCodeBlockRenderer(null, 'github-light'),
485
+ },
486
+ })
487
+
488
+ const pre = findVNodeByType(nodes[0], 'pre') as any
489
+ expect(pre.props.class).toBe('language-json')
490
+ expect(pre.props.class).not.toContain('aimd-code-block')
491
+ const code = findVNodeByType(pre, 'code') as any
492
+ expect(code.props.class).toBe('language-json')
493
+ expect(code.children).toBe('{"model":"qwen"}')
494
+ })
495
+
306
496
  it('renders host-ready step cards with grouped body content', async () => {
307
497
  const { nodes } = await renderToVue(
308
498
  "{{step|verify, 2, title='Verify Output', subtitle='Cross-check', check=True}}\n\nStep body content.",
@@ -512,6 +512,14 @@ import remarkRehype from "remark-rehype"
512
512
  import { unified } from "unified"
513
513
 
514
514
  import { protectAimdInlineTemplates, remarkAimd } from "@airalogy/aimd-core/parser"
515
+ import {
516
+ formatAimdExampleValue,
517
+ formatAimdExamples,
518
+ getAimdFieldDescription,
519
+ getAimdFieldDisplayLabel,
520
+ getAimdFieldExamples,
521
+ getAimdFieldTitle,
522
+ } from "@airalogy/aimd-core/utils"
515
523
  import {
516
524
  createAimdRendererMessages,
517
525
  getAimdRendererQuizTypeLabel,
@@ -790,6 +798,121 @@ function buildScaleBandChildren(quizNode: AimdQuizNode): Array<Element | HastTex
790
798
  } as Element]
791
799
  }
792
800
 
801
+ function createTextNode(value: string): HastText {
802
+ return { type: "text", value }
803
+ }
804
+
805
+ interface FieldMetadataHelp {
806
+ tooltip: string
807
+ description?: string
808
+ examples: string[]
809
+ }
810
+
811
+ function getFieldHelpText(definition: { kwargs?: Record<string, unknown> } | undefined): FieldMetadataHelp {
812
+ const description = getAimdFieldDescription(definition)
813
+ const examples = getAimdFieldExamples(definition)
814
+ .map(formatAimdExampleValue)
815
+ .map(example => example.trim())
816
+ .filter(Boolean)
817
+ const exampleText = examples.length > 0 ? `e.g. ${examples.join(", ")}` : undefined
818
+ const tooltipLines = [description, exampleText].filter((value): value is string => Boolean(value))
819
+
820
+ return {
821
+ tooltip: tooltipLines.join("\n"),
822
+ description,
823
+ examples,
824
+ }
825
+ }
826
+
827
+ function createFieldMetadataPopover(help: FieldMetadataHelp): Element | null {
828
+ if (!help.description && help.examples.length === 0) {
829
+ return null
830
+ }
831
+ const children: Array<Element | HastText> = []
832
+ if (help.description) {
833
+ children.push({
834
+ type: "element",
835
+ tagName: "span",
836
+ properties: { className: ["aimd-field__metadata-popover-line"] },
837
+ children: [createTextNode(help.description)],
838
+ } as Element)
839
+ }
840
+ if (help.examples.length > 0) {
841
+ children.push({
842
+ type: "element",
843
+ tagName: "span",
844
+ properties: { className: ["aimd-field__metadata-examples"] },
845
+ children: [
846
+ {
847
+ type: "element",
848
+ tagName: "span",
849
+ properties: { className: ["aimd-field__metadata-examples-label"] },
850
+ children: [createTextNode("e.g.")],
851
+ } as Element,
852
+ ...help.examples.map((example) => ({
853
+ type: "element",
854
+ tagName: "span",
855
+ properties: { className: ["aimd-field__metadata-example"] },
856
+ children: [createTextNode(example)],
857
+ } as Element)),
858
+ ],
859
+ } as Element)
860
+ }
861
+ return {
862
+ type: "element",
863
+ tagName: "span",
864
+ properties: { className: ["aimd-field__metadata-popover"], role: "tooltip" },
865
+ children,
866
+ } as Element
867
+ }
868
+
869
+ function createFieldNameElement(id: string, definition: { kwargs?: Record<string, unknown> } | undefined): Element {
870
+ const displayTitle = getAimdFieldDisplayLabel(id, definition)
871
+ const hasCustomTitle = getAimdFieldTitle(definition) !== undefined && displayTitle !== id
872
+ const help = getFieldHelpText(definition)
873
+ const hasHelp = Boolean(help.description) || help.examples.length > 0
874
+ const className = ["aimd-field__name"]
875
+ if (hasCustomTitle || hasHelp) {
876
+ className.push("aimd-field__name--with-metadata")
877
+ }
878
+ if (hasHelp) {
879
+ className.push("aimd-field__metadata-host")
880
+ }
881
+ const children: Array<Element | HastText> = [
882
+ {
883
+ type: "element",
884
+ tagName: "span",
885
+ properties: { className: ["aimd-field__title"] },
886
+ children: [createTextNode(displayTitle)],
887
+ } as Element,
888
+ ]
889
+
890
+ if (hasCustomTitle) {
891
+ children.push({
892
+ type: "element",
893
+ tagName: "span",
894
+ properties: { className: ["aimd-field__key"] },
895
+ children: [createTextNode(id)],
896
+ } as Element)
897
+ }
898
+
899
+ const popover = createFieldMetadataPopover(help)
900
+ if (popover) {
901
+ children.push(popover)
902
+ }
903
+
904
+ return {
905
+ type: "element",
906
+ tagName: "span",
907
+ properties: cleanProperties({
908
+ className,
909
+ tabIndex: hasHelp ? 0 : undefined,
910
+ "aria-label": help.tooltip || undefined,
911
+ }),
912
+ children,
913
+ } as Element
914
+ }
915
+
793
916
  // ---------------------------------------------------------------------------
794
917
  // AIMD handler (remark-rehype custom handler)
795
918
  // ---------------------------------------------------------------------------
@@ -968,23 +1091,18 @@ function createAimdHandler(options: AimdRendererOptions = {}) {
968
1091
  children: [{ type: "text", value: `[${refs.join(", ")}]` }],
969
1092
  } as Element)
970
1093
  }
971
- else if (fieldType === "var") {
972
- // Variable: type label + id + optional type annotation
973
- const definition = "definition" in node ? node.definition : undefined
974
- children.push(
1094
+ else if (fieldType === "var") {
1095
+ // Variable: type label + id + optional type annotation
1096
+ const definition = "definition" in node ? node.definition : undefined
1097
+ children.push(
975
1098
  {
976
1099
  type: "element",
977
1100
  tagName: "span",
978
- properties: { className: ["aimd-field__scope"] },
979
- children: [{ type: "text", value: getAimdRendererScopeLabel("var", messages) }],
980
- } as Element,
981
- {
982
- type: "element",
983
- tagName: "span",
984
- properties: { className: ["aimd-field__name"] },
985
- children: [{ type: "text", value: id }],
986
- } as Element,
987
- )
1101
+ properties: { className: ["aimd-field__scope"] },
1102
+ children: [{ type: "text", value: getAimdRendererScopeLabel("var", messages) }],
1103
+ } as Element,
1104
+ createFieldNameElement(id, definition),
1105
+ )
988
1106
  if (definition?.type) {
989
1107
  children.push({
990
1108
  type: "element",
@@ -994,11 +1112,13 @@ function createAimdHandler(options: AimdRendererOptions = {}) {
994
1112
  } as Element)
995
1113
  }
996
1114
  }
997
- else if (fieldType === "var_table") {
998
- // var_table: render header + table preview
999
- const columns = "columns" in node ? (node as any).columns as string[] : []
1000
- children.push(
1001
- {
1115
+ else if (fieldType === "var_table") {
1116
+ // var_table: render header + table preview
1117
+ const columns = "columns" in node ? (node as any).columns as string[] : []
1118
+ const definition = "definition" in node ? node.definition : undefined
1119
+ const subvarDefs = definition?.subvars
1120
+ children.push(
1121
+ {
1002
1122
  type: "element",
1003
1123
  tagName: "div",
1004
1124
  properties: { className: ["aimd-field__header"] },
@@ -1006,17 +1126,12 @@ function createAimdHandler(options: AimdRendererOptions = {}) {
1006
1126
  {
1007
1127
  type: "element",
1008
1128
  tagName: "span",
1009
- properties: { className: ["aimd-field__scope"] },
1010
- children: [{ type: "text", value: getAimdRendererScopeLabel("var_table", messages) }],
1011
- } as Element,
1012
- {
1013
- type: "element",
1014
- tagName: "span",
1015
- properties: { className: ["aimd-field__name"] },
1016
- children: [{ type: "text", value: id }],
1017
- } as Element,
1018
- ],
1019
- } as Element,
1129
+ properties: { className: ["aimd-field__scope"] },
1130
+ children: [{ type: "text", value: getAimdRendererScopeLabel("var_table", messages) }],
1131
+ } as Element,
1132
+ createFieldNameElement(id, definition),
1133
+ ],
1134
+ } as Element,
1020
1135
  )
1021
1136
  if (columns && columns.length > 0) {
1022
1137
  children.push({
@@ -1033,12 +1148,14 @@ function createAimdHandler(options: AimdRendererOptions = {}) {
1033
1148
  type: "element",
1034
1149
  tagName: "tr",
1035
1150
  properties: {},
1036
- children: columns.map(col => ({
1037
- type: "element",
1038
- tagName: "th",
1039
- properties: {},
1040
- children: [{ type: "text", value: col }],
1041
- } as Element)),
1151
+ children: columns.map(col => ({
1152
+ type: "element",
1153
+ tagName: "th",
1154
+ properties: cleanProperties({
1155
+ "data-column-id": col,
1156
+ }),
1157
+ children: [createFieldNameElement(col, subvarDefs?.[col])],
1158
+ } as Element)),
1042
1159
  } as Element,
1043
1160
  ],
1044
1161
  } as Element,
@@ -1242,14 +1359,29 @@ function createAimdHandler(options: AimdRendererOptions = {}) {
1242
1359
  }
1243
1360
 
1244
1361
  // Build properties
1245
- const properties: Properties = {
1246
- "className": [baseClass, modifierClass],
1247
- "data-aimd-type": node.fieldType,
1362
+ const properties: Properties = {
1363
+ "className": [baseClass, modifierClass],
1364
+ "data-aimd-type": node.fieldType,
1248
1365
  "data-aimd-id": node.id,
1249
1366
  "data-aimd-scope": node.scope,
1250
1367
  "data-aimd-raw": node.raw,
1251
- "data-aimd-json": aimdJson,
1252
- }
1368
+ "data-aimd-json": aimdJson,
1369
+ }
1370
+
1371
+ if ((node.fieldType === "var" || node.fieldType === "var_table") && "definition" in node) {
1372
+ const title = getAimdFieldTitle(node.definition)
1373
+ const description = getAimdFieldDescription(node.definition)
1374
+ const examples = formatAimdExamples(getAimdFieldExamples(node.definition))
1375
+ if (title) {
1376
+ properties["data-aimd-title"] = title
1377
+ }
1378
+ if (description) {
1379
+ properties["data-aimd-description"] = description
1380
+ }
1381
+ if (examples) {
1382
+ properties["data-aimd-examples"] = examples
1383
+ }
1384
+ }
1253
1385
 
1254
1386
  // Add reference href
1255
1387
  if (isRef) {