@airalogy/aimd-renderer 2.4.1 → 2.5.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 (41) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +5 -1
  3. package/README.zh-CN.md +5 -1
  4. package/dist/__tests__/renderer.test.d.ts +2 -0
  5. package/dist/__tests__/renderer.test.d.ts.map +1 -0
  6. package/dist/common/annotateStepReferences.d.ts +10 -0
  7. package/dist/common/annotateStepReferences.d.ts.map +1 -0
  8. package/dist/common/assignerHighlighting.d.ts +14 -0
  9. package/dist/common/assignerHighlighting.d.ts.map +1 -0
  10. package/dist/common/assignerVisibility.d.ts +33 -0
  11. package/dist/common/assignerVisibility.d.ts.map +1 -0
  12. package/dist/common/eventKeys.d.ts +20 -0
  13. package/dist/common/eventKeys.d.ts.map +1 -0
  14. package/dist/common/figureNumbering.d.ts +30 -0
  15. package/dist/common/figureNumbering.d.ts.map +1 -0
  16. package/dist/common/processor.d.ts +96 -0
  17. package/dist/common/processor.d.ts.map +1 -0
  18. package/dist/common/quiz-preview.d.ts +11 -0
  19. package/dist/common/quiz-preview.d.ts.map +1 -0
  20. package/dist/common/unified-token-renderer.d.ts +124 -0
  21. package/dist/common/unified-token-renderer.d.ts.map +1 -0
  22. package/dist/html/index.d.ts +9 -0
  23. package/dist/html/index.d.ts.map +1 -0
  24. package/dist/html.js +1 -1
  25. package/dist/index.d.ts +23 -0
  26. package/dist/index.d.ts.map +1 -0
  27. package/dist/index.js +43 -43
  28. package/dist/locales.d.ts +52 -0
  29. package/dist/locales.d.ts.map +1 -0
  30. package/dist/{processor-Cv8E7QsA.js → processor-B2mByErv.js} +1699 -1527
  31. package/dist/vue/index.d.ts +10 -0
  32. package/dist/vue/index.d.ts.map +1 -0
  33. package/dist/vue/vue-renderer.d.ts +138 -0
  34. package/dist/vue/vue-renderer.d.ts.map +1 -0
  35. package/dist/vue.js +1 -1
  36. package/package.json +13 -13
  37. package/src/__tests__/renderer.test.ts +29 -1
  38. package/src/common/processor.ts +4 -2
  39. package/src/common/unified-token-renderer.ts +2 -2
  40. package/src/locales.ts +5 -0
  41. package/src/vue/vue-renderer.ts +2 -2
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Vue rendering exports
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';
5
+ export { renderToVue, createRenderer, defaultRenderer, } from '../common/processor';
6
+ export { createAimdRendererMessages, DEFAULT_AIMD_RENDERER_LOCALE, resolveAimdRendererLocale, } from '../locales';
7
+ export type { RenderContext, RenderMode, ProcessorOptions, } from '@airalogy/aimd-core/types';
8
+ export type { AimdAssignerVisibility, AimdRendererOptions, RenderResult } from '../common/processor';
9
+ export type { AimdRendererI18nOptions, AimdRendererLocale, AimdRendererMessages, AimdRendererMessagesInput, } from '../locales';
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +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"}
@@ -0,0 +1,138 @@
1
+ import type { Element, Root as HastRoot, RootContent } from "hast";
2
+ import type { Component, VNode, VNodeChild } from "vue";
3
+ import type { AimdNode, RenderContext } from "@airalogy/aimd-core/types";
4
+ import type { AimdRendererI18nOptions, AimdRendererLocale, AimdRendererMessages } from "../locales";
5
+ /**
6
+ * Extended Element data type
7
+ */
8
+ export interface AimdElementData {
9
+ aimd?: AimdNode;
10
+ }
11
+ /**
12
+ * AIMD component renderer function type
13
+ * Can return VNode directly or a Promise for async rendering
14
+ */
15
+ export type AimdComponentRenderer = (node: AimdNode, ctx: AimdRendererContext, children?: VNodeChild[]) => VNode | Promise<VNode> | null;
16
+ /**
17
+ * Element renderer function type
18
+ */
19
+ export type ElementRenderer = (node: Element, children: VNodeChild[], ctx: AimdRendererContext) => VNode | null;
20
+ export interface AimdRendererContext extends RenderContext {
21
+ locale: AimdRendererLocale;
22
+ messages: AimdRendererMessages;
23
+ }
24
+ export interface AimdStepCardRendererOptions {
25
+ showScopeLabel?: boolean;
26
+ showCheckBadge?: boolean;
27
+ bodyClassName?: string;
28
+ className?: string;
29
+ }
30
+ /**
31
+ * Render options
32
+ */
33
+ export interface VueRendererOptions {
34
+ /**
35
+ * Built-in renderer locale
36
+ */
37
+ locale?: AimdRendererI18nOptions["locale"];
38
+ /**
39
+ * Optional overrides for built-in renderer copy
40
+ */
41
+ messages?: AimdRendererI18nOptions["messages"];
42
+ /**
43
+ * Render mode shorthand (used when context is not provided)
44
+ */
45
+ mode?: RenderContext["mode"];
46
+ /**
47
+ * Quiz preview visibility shorthand (used when context is not provided)
48
+ */
49
+ quizPreview?: RenderContext["quizPreview"];
50
+ /**
51
+ * Render context
52
+ */
53
+ context?: RenderContext & Partial<Pick<AimdRendererContext, "locale" | "messages">>;
54
+ /**
55
+ * Custom AIMD component renderers
56
+ * Override default renderers or add new ones
57
+ */
58
+ aimdRenderers?: Record<string, AimdComponentRenderer>;
59
+ /**
60
+ * Custom HTML element renderers
61
+ * Render specific HTML tags with custom components
62
+ */
63
+ elementRenderers?: Record<string, ElementRenderer>;
64
+ /**
65
+ * Component map for rendering Vue components by tag name
66
+ * e.g., { 'step-renderer': StepRendererComponent }
67
+ */
68
+ componentMap?: Record<string, Component>;
69
+ }
70
+ /**
71
+ * Figure context for tracking figure numbers and references
72
+ */
73
+ export interface FigureContext {
74
+ /** Map from fig ID to sequence number */
75
+ figureNumbers: Map<string, number>;
76
+ /** Current figure sequence counter */
77
+ sequence: number;
78
+ }
79
+ /**
80
+ * Convert HAST node to Vue VNode
81
+ */
82
+ export declare function hastToVue(node: HastRoot | RootContent, options?: VueRendererOptions, figCtx?: FigureContext): VNodeChild;
83
+ /**
84
+ * Convert HAST tree to Vue VNode array
85
+ */
86
+ export declare function renderToVNodes(tree: HastRoot, options?: VueRendererOptions): VNode[];
87
+ /**
88
+ * Create a custom AIMD renderer that wraps a Vue component
89
+ */
90
+ export declare function createComponentRenderer(component: Component, propsMapper?: (node: AimdNode, ctx: AimdRendererContext) => Record<string, unknown>): AimdComponentRenderer;
91
+ export declare function createStepCardRenderer(options?: AimdStepCardRendererOptions): AimdComponentRenderer;
92
+ /**
93
+ * Shiki highlighter type (compatible with @shikijs/core)
94
+ */
95
+ export interface ShikiHighlighter {
96
+ codeToHtml: (code: string, options: {
97
+ lang: string;
98
+ theme: string;
99
+ }) => string;
100
+ codeToTokensWithThemes?: (code: string, options: {
101
+ lang: string;
102
+ themes: Record<string, string>;
103
+ }) => Array<Array<{
104
+ content: string;
105
+ variants: Record<string, {
106
+ color: string;
107
+ }>;
108
+ }>>;
109
+ }
110
+ /**
111
+ * Create code block element renderer with Shiki support
112
+ * @param highlighter - Shiki highlighter instance (can be reactive ref)
113
+ * @param defaultTheme - Default theme to use
114
+ */
115
+ export declare function createCodeBlockRenderer(highlighter: ShikiHighlighter | null | (() => ShikiHighlighter | null), defaultTheme?: string): ElementRenderer;
116
+ /**
117
+ * Create Mermaid diagram element renderer
118
+ * @param MermaidComponent - Vue component to render Mermaid diagrams
119
+ */
120
+ export declare function createMermaidRenderer(MermaidComponent: Component): ElementRenderer;
121
+ /**
122
+ * Asset resolver function type
123
+ */
124
+ export type AssetResolver = (id: string) => Promise<{
125
+ url: string;
126
+ } | null>;
127
+ /**
128
+ * Create image element renderer with asset resolution
129
+ * @param AssetComponent - Vue component to render assets (optional)
130
+ * @param getAsset - Function to resolve asset ID to URL
131
+ */
132
+ export declare function createAssetRenderer(getAsset?: AssetResolver, AssetComponent?: Component): ElementRenderer;
133
+ /**
134
+ * Create iframe/video element renderer for embedded content
135
+ * @param EmbeddedComponent - Vue component to render embedded content
136
+ */
137
+ export declare function createEmbeddedRenderer(EmbeddedComponent: Component): ElementRenderer;
138
+ //# sourceMappingURL=vue-renderer.d.ts.map
@@ -0,0 +1 @@
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,4 +1,4 @@
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-Cv8E7QsA.js";
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";
2
2
  export {
3
3
  a as DEFAULT_AIMD_RENDERER_LOCALE,
4
4
  d as createAimdRendererMessages,
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@airalogy/aimd-renderer",
3
3
  "type": "module",
4
- "version": "2.4.1",
5
- "description": "AIMD rendering engines for HTML and Vue",
4
+ "version": "2.5.0",
5
+ "description": "AIMD (Airalogy Markdown) rendering engines for HTML and Vue",
6
6
  "license": "Apache-2.0",
7
7
  "repository": {
8
8
  "type": "git",
@@ -47,21 +47,13 @@
47
47
  "dist",
48
48
  "src"
49
49
  ],
50
- "scripts": {
51
- "type-check": "tsc --noEmit",
52
- "build:types": "tsc --emitDeclarationOnly --declaration --outDir dist",
53
- "build": "vite build && pnpm run build:types",
54
- "dev": "vite build --watch",
55
- "test": "pnpm run build && node --test ./tests/*.test.mjs"
56
- },
57
50
  "peerDependencies": {
58
51
  "vue": "^3.5.17"
59
52
  },
60
53
  "dependencies": {
61
- "@airalogy/aimd-core": "workspace:^",
62
54
  "@types/hast": "^3.0.4",
63
55
  "hast-util-to-html": "^9.0.5",
64
- "katex": "catalog:",
56
+ "katex": "^0.16.28",
65
57
  "rehype-katex": "^7.0.1",
66
58
  "rehype-raw": "^7.0.0",
67
59
  "remark-breaks": "^4.0.0",
@@ -71,7 +63,8 @@
71
63
  "remark-rehype": "^11.1.2",
72
64
  "shiki": "^2.5.0",
73
65
  "unified": "^11.0.5",
74
- "vfile": "^6.0.3"
66
+ "vfile": "^6.0.3",
67
+ "@airalogy/aimd-core": "^2.6.0"
75
68
  },
76
69
  "devDependencies": {
77
70
  "@types/node": "^24.3.0",
@@ -80,5 +73,12 @@
80
73
  "vite": "^7.1.3",
81
74
  "vite-tsconfig-paths": "^5.1.4",
82
75
  "vue": "^3.5.17"
76
+ },
77
+ "scripts": {
78
+ "type-check": "tsc --noEmit",
79
+ "build:types": "tsc --emitDeclarationOnly --declaration --outDir dist",
80
+ "build": "vite build && pnpm run build:types",
81
+ "dev": "vite build --watch",
82
+ "test": "pnpm run build && node --test ./tests/*.test.mjs"
83
83
  }
84
- }
84
+ }
@@ -109,8 +109,16 @@ describe('resolveQuizPreviewOptions', () => {
109
109
 
110
110
  describe('parseAndExtract', () => {
111
111
  it('extracts var fields', () => {
112
- const fields = parseAndExtract('{{var|temperature: float = 36.5}}')
112
+ const fields = parseAndExtract('{{var|temperature: float = 36.5, gt = 0}}')
113
113
  expect(fields.var).toContain('temperature')
114
+ expect(fields.var_definitions?.[0]).toMatchObject({
115
+ id: 'temperature',
116
+ type: 'float',
117
+ default: 36.5,
118
+ kwargs: {
119
+ gt: 0,
120
+ },
121
+ })
114
122
  })
115
123
 
116
124
  it('extracts step fields', () => {
@@ -173,6 +181,26 @@ describe('renderToHtmlSync', () => {
173
181
  expect(html).toContain('<td')
174
182
  })
175
183
 
184
+ it('renders true/false quiz options and report answers', () => {
185
+ const { html, fields } = renderToHtmlSync(
186
+ [
187
+ '```quiz',
188
+ 'id: q_true_false',
189
+ 'type: true_false',
190
+ 'stem: "The sample stayed cold."',
191
+ 'answer: true',
192
+ '```',
193
+ ].join('\n'),
194
+ { mode: 'report' },
195
+ )
196
+
197
+ expect(fields.quiz[0].type).toBe('true_false')
198
+ expect(html).toContain('True/false')
199
+ expect(html).toContain('true. True')
200
+ expect(html).toContain('false. False')
201
+ expect(html).toContain('Answer: true')
202
+ })
203
+
176
204
  it('supports host custom element renderers for AIMD nodes', () => {
177
205
  const { html } = renderToHtmlSync(
178
206
  "{{step|verify, 2, title='Verify Output', subtitle='Cross-check', check=True, result=True}}\n\nStep body content.",
@@ -531,6 +531,7 @@ let mathStylesLoadPromise: Promise<unknown> | null = null
531
531
 
532
532
  const EMPTY_EXTRACTED_FIELDS: ExtractedAimdFields = {
533
533
  var: [],
534
+ var_definitions: [],
534
535
  var_table: [],
535
536
  client_assigner: [],
536
537
  quiz: [],
@@ -573,6 +574,7 @@ function createAimdParseInput(content: string) {
573
574
  function createEmptyExtractedFields(): ExtractedAimdFields {
574
575
  return {
575
576
  var: [...EMPTY_EXTRACTED_FIELDS.var],
577
+ var_definitions: [...(EMPTY_EXTRACTED_FIELDS.var_definitions || [])],
576
578
  var_table: [...EMPTY_EXTRACTED_FIELDS.var_table],
577
579
  client_assigner: [...EMPTY_EXTRACTED_FIELDS.client_assigner],
578
580
  quiz: [...EMPTY_EXTRACTED_FIELDS.quiz],
@@ -1171,7 +1173,7 @@ function createAimdHandler(options: AimdRendererOptions = {}) {
1171
1173
  } as Element)
1172
1174
  }
1173
1175
 
1174
- if (quizType === "choice" && Array.isArray(quizNode.options) && quizNode.options.length > 0) {
1176
+ if ((quizType === "choice" || quizType === "true_false") && Array.isArray(quizNode.options) && quizNode.options.length > 0) {
1175
1177
  children.push({
1176
1178
  type: "element",
1177
1179
  tagName: "ul",
@@ -1190,7 +1192,7 @@ function createAimdHandler(options: AimdRendererOptions = {}) {
1190
1192
  children.push(...buildScaleBandChildren(quizNode))
1191
1193
  }
1192
1194
 
1193
- if (quizPreview.showAnswers && quizType === "choice" && quizNode.answer !== undefined) {
1195
+ if (quizPreview.showAnswers && (quizType === "choice" || quizType === "true_false") && quizNode.answer !== undefined) {
1194
1196
  const answerText = Array.isArray(quizNode.answer)
1195
1197
  ? quizNode.answer.join(", ")
1196
1198
  : String(quizNode.answer)
@@ -381,7 +381,7 @@ function createAimdRenderers(options: UnifiedTokenRendererOptions): Record<strin
381
381
  previewChildren.push(h("div", { class: "aimd-quiz__description" }, quizNode.description))
382
382
  }
383
383
 
384
- if (quizType === "choice" && Array.isArray(quizNode.options) && quizNode.options.length > 0) {
384
+ if ((quizType === "choice" || quizType === "true_false") && Array.isArray(quizNode.options) && quizNode.options.length > 0) {
385
385
  previewChildren.push(
386
386
  h("ul", { class: "aimd-quiz__options" }, quizNode.options.map(opt =>
387
387
  h("li", `${opt.key}. ${opt.text}`),
@@ -396,7 +396,7 @@ function createAimdRenderers(options: UnifiedTokenRendererOptions): Record<strin
396
396
 
397
397
  const quizPreview = getQuizPreview()
398
398
 
399
- if (quizPreview.showAnswers && quizType === "choice" && quizNode.answer !== undefined) {
399
+ if (quizPreview.showAnswers && (quizType === "choice" || quizType === "true_false") && quizNode.answer !== undefined) {
400
400
  const answerText = Array.isArray(quizNode.answer)
401
401
  ? quizNode.answer.join(", ")
402
402
  : String(quizNode.answer)
package/src/locales.ts CHANGED
@@ -26,6 +26,7 @@ export interface AimdRendererMessages {
26
26
  choice: string
27
27
  singleChoice: string
28
28
  multipleChoice: string
29
+ trueFalse: string
29
30
  blank: string
30
31
  open: string
31
32
  scale: string
@@ -86,6 +87,7 @@ const EN_US_MESSAGES: AimdRendererMessages = {
86
87
  choice: "choice",
87
88
  singleChoice: "Single choice",
88
89
  multipleChoice: "Multiple choice",
90
+ trueFalse: "True/false",
89
91
  blank: "blank",
90
92
  open: "open",
91
93
  scale: "scale",
@@ -122,6 +124,7 @@ const ZH_CN_MESSAGES: AimdRendererMessages = {
122
124
  choice: "选择",
123
125
  singleChoice: "单选",
124
126
  multipleChoice: "多选",
127
+ trueFalse: "判断",
125
128
  blank: "填空",
126
129
  open: "开放",
127
130
  scale: "量表",
@@ -246,6 +249,8 @@ export function getAimdRendererQuizTypeLabel(
246
249
  return messages.quiz.types.choice
247
250
  case "blank":
248
251
  return messages.quiz.types.blank
252
+ case "true_false":
253
+ return messages.quiz.types.trueFalse
249
254
  case "open":
250
255
  return messages.quiz.types.open
251
256
  case "scale":
@@ -298,7 +298,7 @@ const defaultAimdRenderers: Record<string, AimdComponentRenderer> = {
298
298
  : null,
299
299
  ]
300
300
 
301
- if (quizType === "choice" && Array.isArray(quizNode.options) && quizNode.options.length > 0) {
301
+ if ((quizType === "choice" || quizType === "true_false") && Array.isArray(quizNode.options) && quizNode.options.length > 0) {
302
302
  previewChildren.push(
303
303
  h("ul", { class: "aimd-quiz__options" }, quizNode.options.map(opt =>
304
304
  h("li", `${opt.key}. ${opt.text}`),
@@ -313,7 +313,7 @@ const defaultAimdRenderers: Record<string, AimdComponentRenderer> = {
313
313
 
314
314
  const quizPreview = resolveQuizPreviewOptionsFromContext(ctx)
315
315
 
316
- if (quizPreview.showAnswers && quizType === "choice" && quizNode.answer !== undefined) {
316
+ if (quizPreview.showAnswers && (quizType === "choice" || quizType === "true_false") && quizNode.answer !== undefined) {
317
317
  const answerText = Array.isArray(quizNode.answer)
318
318
  ? quizNode.answer.join(", ")
319
319
  : String(quizNode.answer)