@oml/markdown 0.9.0 → 0.11.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 (37) hide show
  1. package/out/md/md-executor.js +2 -9
  2. package/out/md/md-executor.js.map +1 -1
  3. package/out/md/md-runtime.js +2 -26
  4. package/out/md/md-runtime.js.map +1 -1
  5. package/out/renderers/chart-renderer.js +72 -4
  6. package/out/renderers/chart-renderer.js.map +1 -1
  7. package/out/renderers/diagram-renderer.js +738 -252
  8. package/out/renderers/diagram-renderer.js.map +1 -1
  9. package/out/renderers/graph-renderer.js +5 -9
  10. package/out/renderers/graph-renderer.js.map +1 -1
  11. package/out/renderers/renderer.d.ts +3 -0
  12. package/out/renderers/renderer.js +53 -0
  13. package/out/renderers/renderer.js.map +1 -1
  14. package/out/renderers/table-renderer.d.ts +8 -1
  15. package/out/renderers/table-renderer.js +22 -1
  16. package/out/renderers/table-renderer.js.map +1 -1
  17. package/out/renderers/text-renderer.d.ts +0 -1
  18. package/out/renderers/text-renderer.js +2 -9
  19. package/out/renderers/text-renderer.js.map +1 -1
  20. package/out/renderers/wikilink-utils.js +3 -10
  21. package/out/renderers/wikilink-utils.js.map +1 -1
  22. package/out/static/browser-runtime.bundle.js +1591 -6408
  23. package/out/static/browser-runtime.bundle.js.map +4 -4
  24. package/out/static/browser-runtime.js +3 -0
  25. package/out/static/browser-runtime.js.map +1 -1
  26. package/package.json +2 -2
  27. package/src/md/md-executor.ts +2 -9
  28. package/src/md/md-runtime.ts +2 -28
  29. package/src/renderers/chart-renderer.ts +93 -2
  30. package/src/renderers/diagram-renderer.ts +799 -258
  31. package/src/renderers/graph-renderer.ts +5 -9
  32. package/src/renderers/renderer.ts +66 -0
  33. package/src/renderers/table-renderer.ts +39 -3
  34. package/src/renderers/text-renderer.ts +2 -7
  35. package/src/renderers/wikilink-utils.ts +4 -10
  36. package/src/static/browser-runtime.ts +3 -0
  37. package/src/static/markdown-webview.css +1361 -0
@@ -1,7 +1,8 @@
1
1
  // Copyright (c) 2026 Modelware. All rights reserved.
2
2
 
3
- import { CanvasMarkdownBlockRenderer } from './renderer.js';
3
+ import { CanvasMarkdownBlockRenderer, displayLabelFromIri } from './renderer.js';
4
4
  import type { MdBlockExecutionResult } from './types.js';
5
+ import { isIriValue, shortLabelFromIri } from './wikilink-utils.js';
5
6
 
6
7
  // --- CSS variable constants for base styles (auto-update on VS Code theme) ---
7
8
  const CSS_NODE_FILL = 'var(--vscode-button-secondaryBackground, var(--vscode-button-background, #5a5a8a))';
@@ -1637,15 +1638,10 @@ function shortLabel(value: string): string {
1637
1638
  if (value.startsWith('_:')) {
1638
1639
  return value;
1639
1640
  }
1640
- const hash = value.lastIndexOf('#');
1641
- if (hash >= 0 && hash < value.length - 1) {
1642
- return value.slice(hash + 1);
1641
+ if (isIriValue(value)) {
1642
+ return shortLabelFromIri(value);
1643
1643
  }
1644
- const slash = value.lastIndexOf('/');
1645
- if (slash >= 0 && slash < value.length - 1) {
1646
- return value.slice(slash + 1);
1647
- }
1648
- return value;
1644
+ return displayLabelFromIri(value);
1649
1645
  }
1650
1646
 
1651
1647
  function isRecord(value: unknown): value is Record<string, unknown> {
@@ -7,6 +7,72 @@ export interface MarkdownBlockRenderer {
7
7
  render(result: MdBlockExecutionResult): HTMLElement;
8
8
  }
9
9
 
10
+ let iriLabelSnapshot: ReadonlyMap<string, string> | undefined;
11
+
12
+ export function setIriLabelSnapshot(snapshot?: ReadonlyMap<string, string> | Record<string, string>): void {
13
+ if (!snapshot) {
14
+ iriLabelSnapshot = undefined;
15
+ return;
16
+ }
17
+ if (snapshot instanceof Map) {
18
+ iriLabelSnapshot = snapshot;
19
+ return;
20
+ }
21
+ iriLabelSnapshot = new Map(
22
+ Object.entries(snapshot).map(([iri, label]) => [normalizeIriLabelKey(iri), String(label)] as const)
23
+ );
24
+ }
25
+
26
+ export function runWithIriLabelSnapshot<T>(
27
+ snapshot: ReadonlyMap<string, string> | Record<string, string> | undefined,
28
+ action: () => T
29
+ ): T {
30
+ const previous = iriLabelSnapshot;
31
+ setIriLabelSnapshot(snapshot);
32
+ try {
33
+ return action();
34
+ } finally {
35
+ iriLabelSnapshot = previous;
36
+ }
37
+ }
38
+
39
+ export function displayLabelFromIri(iri: string): string {
40
+ const normalized = normalizeIriLabelKey(iri);
41
+ if (!normalized) {
42
+ return iri;
43
+ }
44
+
45
+ const labeled = iriLabelSnapshot?.get(normalized);
46
+ if (typeof labeled === 'string' && labeled.length > 0) {
47
+ return labeled;
48
+ }
49
+
50
+ const fragmentIndex = normalized.lastIndexOf('#');
51
+ if (fragmentIndex >= 0 && fragmentIndex < normalized.length - 1) {
52
+ return decodeIriLabelSegment(normalized.slice(fragmentIndex + 1));
53
+ }
54
+
55
+ const withoutQuery = normalized.split('?')[0]?.replace(/\/+$/, '') ?? normalized;
56
+ const slashIndex = withoutQuery.lastIndexOf('/');
57
+ if (slashIndex >= 0 && slashIndex < withoutQuery.length - 1) {
58
+ return decodeIriLabelSegment(withoutQuery.slice(slashIndex + 1));
59
+ }
60
+
61
+ return normalized;
62
+ }
63
+
64
+ function normalizeIriLabelKey(iri: string): string {
65
+ return String(iri ?? '').trim().replace(/^<|>$/g, '');
66
+ }
67
+
68
+ function decodeIriLabelSegment(value: string): string {
69
+ try {
70
+ return decodeURIComponent(value);
71
+ } catch {
72
+ return value;
73
+ }
74
+ }
75
+
10
76
  export type TableBlockKind = 'table' | 'table-editor' | 'matrix' | 'tree';
11
77
  export type CanvasBlockKind = 'graph' | 'diagram';
12
78
 
@@ -18,7 +18,6 @@ type TableEditorActionContext = {
18
18
  datatypeIri?: string;
19
19
  classIri?: string;
20
20
  nodeKind?: string;
21
- enumValues?: string[];
22
21
  editor?: 'multiline';
23
22
  }>;
24
23
  blockSource?: string;
@@ -28,6 +27,14 @@ type TableEditorActionContext = {
28
27
  pointerY?: number;
29
28
  };
30
29
 
30
+ type TableRootWithAiContext = HTMLDivElement & {
31
+ __omlAiContext?: {
32
+ columns: string[];
33
+ rows: Array<{ iri: string; cells: string[] }>;
34
+ blockSource?: string;
35
+ };
36
+ };
37
+
31
38
  export class TableMarkdownBlockRenderer extends QueryMarkdownBlockRenderer {
32
39
  protected readonly tableKinds: ReadonlyArray<TableBlockKind> = ['table'];
33
40
 
@@ -93,7 +100,7 @@ export class TableMarkdownBlockRenderer extends QueryMarkdownBlockRenderer {
93
100
  options: Record<string, unknown> | undefined,
94
101
  blockSource?: string
95
102
  ): HTMLElement {
96
- const root = document.createElement('div');
103
+ const root = document.createElement('div') as TableRootWithAiContext;
97
104
  root.className = 'table-root graph-root';
98
105
  const isTree = this.tableKinds.includes('tree');
99
106
  const allRowsWithIndex = rows.map((cells, index) => ({ index, cells }));
@@ -115,6 +122,16 @@ export class TableMarkdownBlockRenderer extends QueryMarkdownBlockRenderer {
115
122
  ...row,
116
123
  cells: visibleColumnIndexes.map((columnIndex) => row.cells[columnIndex] ?? ''),
117
124
  }));
125
+ root.__omlAiContext = {
126
+ columns: visibleColumns.slice(),
127
+ rows: rowsWithIndex
128
+ .map((row) => ({
129
+ iri: (row.cells[0] ?? '').trim(),
130
+ cells: row.cells.slice(),
131
+ }))
132
+ .filter((row) => row.iri.length > 0),
133
+ blockSource,
134
+ };
118
135
  const columnContexts = createColumnContexts(visibleColumns, rowsWithIndex);
119
136
  const treeModel = isTree
120
137
  ? this.createTreeModel(columns, allRowsWithIndex, visibleColumnIndexes, options)
@@ -219,10 +236,16 @@ export class TableMarkdownBlockRenderer extends QueryMarkdownBlockRenderer {
219
236
  return;
220
237
  }
221
238
  const filtered = this.applyFiltersAndSorting(columns, sourceRows, state);
222
- this.requestCsvDownload(visibleColumns, filtered.map((entry) => entry.cells));
239
+ const csvExport = this.transformCsvDownloadData(visibleColumns, filtered.map((entry) => entry.cells));
240
+ this.requestCsvDownload(csvExport.columns, csvExport.rows);
223
241
  });
224
242
  controlsRight.appendChild(downloadButton);
225
243
 
244
+ const uploadButton = this.createUploadCsvButton(visibleColumns, rowsWithIndex, isTree, blockSource);
245
+ if (uploadButton) {
246
+ controlsRight.appendChild(uploadButton);
247
+ }
248
+
226
249
  controls.appendChild(controlsLeft);
227
250
  controls.appendChild(controlsRight);
228
251
  root.appendChild(controls);
@@ -958,6 +981,19 @@ export class TableMarkdownBlockRenderer extends QueryMarkdownBlockRenderer {
958
981
  return value;
959
982
  }
960
983
 
984
+ protected createUploadCsvButton(
985
+ _columns: string[],
986
+ _rows: Array<{ index: number; cells: string[] }>,
987
+ _isTree: boolean,
988
+ _blockSource: string | undefined
989
+ ): HTMLElement | undefined {
990
+ return undefined;
991
+ }
992
+
993
+ protected transformCsvDownloadData(columns: string[], rows: string[][]): { columns: string[]; rows: string[][] } {
994
+ return { columns, rows };
995
+ }
996
+
961
997
  private requestCsvDownload(columns: string[], rows: string[][]): void {
962
998
  if (columns.length === 0) {
963
999
  return;
@@ -2,7 +2,7 @@
2
2
 
3
3
  import { QueryMarkdownBlockRenderer } from './renderer.js';
4
4
  import type { MdBlockExecutionResult } from './types.js';
5
- import MarkdownIt from 'markdown-it';
5
+ import { appendInlineValue } from './wikilink-utils.js';
6
6
 
7
7
  type TextStyleSelectorKind = 'paragraph';
8
8
  type TextStyleTarget = 'value';
@@ -23,11 +23,6 @@ type TextSelectorContext = {
23
23
  };
24
24
 
25
25
  export class TextMarkdownBlockRenderer extends QueryMarkdownBlockRenderer {
26
- private readonly markdown = new MarkdownIt({
27
- html: false,
28
- linkify: true,
29
- });
30
-
31
26
  canRender(result: MdBlockExecutionResult): boolean {
32
27
  return result.status === 'ok'
33
28
  && result.kind === 'text'
@@ -51,7 +46,7 @@ export class TextMarkdownBlockRenderer extends QueryMarkdownBlockRenderer {
51
46
  const paragraph = document.createElement('p');
52
47
  const valueSpan = document.createElement('span');
53
48
  valueSpan.className = 'oml-md-result-text-value';
54
- valueSpan.innerHTML = this.markdown.renderInline(row[0] ?? '');
49
+ appendInlineValue(valueSpan, row[0] ?? '');
55
50
  paragraph.appendChild(valueSpan);
56
51
 
57
52
  const context = createParagraphSelectorContext(index, row[0] ?? '', payload.columns, row);
@@ -1,5 +1,7 @@
1
1
  // Copyright (c) 2026 Modelware. All rights reserved.
2
2
 
3
+ import { displayLabelFromIri } from './renderer.js';
4
+
3
5
  export function appendInlineValue(container: HTMLElement, value: string): void {
4
6
  const wikilinkPattern = /\[\[([^\]]+)\]\]/g;
5
7
  let cursor = 0;
@@ -44,7 +46,7 @@ export function appendTokenizedValueParts(container: HTMLElement, raw: string, p
44
46
  if (isIriValue(token)) {
45
47
  fragment.appendChild(createWikiLinkElement(token, shortLabelFromIri(token)));
46
48
  } else {
47
- fragment.textContent = token;
49
+ appendInlineValue(fragment, token);
48
50
  }
49
51
  container.appendChild(fragment);
50
52
  }
@@ -58,15 +60,7 @@ export function splitTokenizedValueParts(raw: string): string[] {
58
60
  }
59
61
 
60
62
  export function shortLabelFromIri(iri: string): string {
61
- const hash = iri.lastIndexOf('#');
62
- if (hash >= 0 && hash < iri.length - 1) {
63
- return iri.slice(hash + 1);
64
- }
65
- const slash = iri.lastIndexOf('/');
66
- if (slash >= 0 && slash < iri.length - 1) {
67
- return iri.slice(slash + 1);
68
- }
69
- return iri;
63
+ return displayLabelFromIri(iri);
70
64
  }
71
65
 
72
66
  export function isIriValue(value: string): boolean {
@@ -1,6 +1,7 @@
1
1
  // Copyright (c) 2026 Modelware. All rights reserved.
2
2
 
3
3
  import { createMarkdownRendererRegistry } from '../renderers/registry.js';
4
+ import { setIriLabelSnapshot } from '../renderers/renderer.js';
4
5
 
5
6
  const SUPPORTED = new Set(['table', 'tree', 'graph', 'chart', 'diagram', 'list', 'text', 'matrix', 'table-editor']);
6
7
 
@@ -203,6 +204,8 @@ async function applyExecutionResults(): Promise<void> {
203
204
  const wikilinkIndex = parseJsonNode<Record<string, string>>('oml-md-wikilink-index', {});
204
205
  const iriAliasIndex = parseJsonNode<Record<string, string>>('oml-md-wikilink-iri-aliases', {});
205
206
  const wikilinkConfig = parseJsonNode<WikilinkConfig>('oml-md-wikilink-config', { linkingEnabled: false });
207
+ const memberLabelSnapshot = parseJsonNode<Record<string, string>>('oml-md-member-labels', {});
208
+ setIriLabelSnapshot(memberLabelSnapshot);
206
209
  const linkingEnabled = Boolean(wikilinkConfig?.linkingEnabled);
207
210
  // Resolve wikilinks in regular markdown content (outside code-block panels).
208
211
  applyWikilinks(document, wikilinkIndex, iriAliasIndex, linkingEnabled);