@oml/markdown 0.10.0 → 0.12.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 (40) hide show
  1. package/out/md/md-execution.d.ts +16 -0
  2. package/out/md/md-executor.d.ts +1 -0
  3. package/out/md/md-executor.js +219 -35
  4. package/out/md/md-executor.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 +896 -245
  8. package/out/renderers/diagram-renderer.js.map +1 -1
  9. package/out/renderers/graph-renderer.js +452 -18
  10. package/out/renderers/graph-renderer.js.map +1 -1
  11. package/out/renderers/matrix-renderer.d.ts +0 -2
  12. package/out/renderers/matrix-renderer.js +45 -40
  13. package/out/renderers/matrix-renderer.js.map +1 -1
  14. package/out/renderers/renderer.d.ts +4 -1
  15. package/out/renderers/renderer.js +98 -0
  16. package/out/renderers/renderer.js.map +1 -1
  17. package/out/renderers/table-renderer.d.ts +12 -2
  18. package/out/renderers/table-renderer.js +126 -39
  19. package/out/renderers/table-renderer.js.map +1 -1
  20. package/out/renderers/types.d.ts +16 -0
  21. package/out/renderers/wikilink-utils.d.ts +1 -0
  22. package/out/renderers/wikilink-utils.js +60 -32
  23. package/out/renderers/wikilink-utils.js.map +1 -1
  24. package/out/static/browser-runtime.bundle.js +8011 -1292
  25. package/out/static/browser-runtime.bundle.js.map +4 -4
  26. package/out/static/browser-runtime.js +15 -2
  27. package/out/static/browser-runtime.js.map +1 -1
  28. package/package.json +2 -2
  29. package/src/md/md-execution.ts +20 -0
  30. package/src/md/md-executor.ts +268 -40
  31. package/src/renderers/chart-renderer.ts +93 -2
  32. package/src/renderers/diagram-renderer.ts +964 -253
  33. package/src/renderers/graph-renderer.ts +512 -12
  34. package/src/renderers/matrix-renderer.ts +57 -44
  35. package/src/renderers/renderer.ts +105 -1
  36. package/src/renderers/table-renderer.ts +190 -41
  37. package/src/renderers/types.ts +20 -0
  38. package/src/renderers/wikilink-utils.ts +66 -31
  39. package/src/static/browser-runtime.ts +20 -2
  40. package/src/static/markdown-webview.css +44 -15
@@ -1,4 +1,5 @@
1
1
  // Copyright (c) 2026 Modelware. All rights reserved.
2
+ import { appendInlineValue, createWikiLinkElement, isUrlValue, shortLabelFromIri } from './wikilink-utils.js';
2
3
  let iriLabelSnapshot;
3
4
  export function setIriLabelSnapshot(snapshot) {
4
5
  if (!snapshot) {
@@ -88,6 +89,41 @@ export class BaseMarkdownBlockRenderer {
88
89
  }
89
90
  }
90
91
  export class QueryMarkdownBlockRenderer extends BaseMarkdownBlockRenderer {
92
+ renderCellValue(raw, typedValue) {
93
+ const value = document.createElement('span');
94
+ value.className = 'table-value';
95
+ const entries = typedValue?.values ?? [];
96
+ if (entries.length > 0) {
97
+ entries.forEach((entry, index) => {
98
+ if (index > 0) {
99
+ value.appendChild(document.createTextNode(' '));
100
+ }
101
+ value.appendChild(this.renderValueToken(entry));
102
+ });
103
+ return value;
104
+ }
105
+ const display = this.formatCellDisplayText(raw, typedValue);
106
+ const fragment = document.createElement('span');
107
+ fragment.className = 'table-value-part';
108
+ fragment.dataset.value = display;
109
+ appendInlineValue(fragment, display);
110
+ value.appendChild(fragment);
111
+ return value;
112
+ }
113
+ formatCellDisplayText(raw, typedValue) {
114
+ if (typedValue?.values?.length) {
115
+ return typedValue.values.map((entry) => {
116
+ if (entry.kind === 'iri') {
117
+ return shortLabelFromIri(entry.value);
118
+ }
119
+ if (entry.kind === 'bnode') {
120
+ return `_:${entry.value}`;
121
+ }
122
+ return entry.value;
123
+ }).join(' ');
124
+ }
125
+ return raw;
126
+ }
91
127
  getBlockSource(result) {
92
128
  return result.blockSource;
93
129
  }
@@ -97,6 +133,33 @@ export class QueryMarkdownBlockRenderer extends BaseMarkdownBlockRenderer {
97
133
  getBlockRange(result) {
98
134
  return { start: result.blockLineStart, end: result.blockLineEnd };
99
135
  }
136
+ renderValueToken(entry) {
137
+ const fragment = document.createElement('span');
138
+ fragment.className = 'table-value-part';
139
+ fragment.dataset.value = entry.value;
140
+ if (entry.kind === 'iri') {
141
+ if (isBuiltInOntologyIri(entry.value)) {
142
+ appendInlineValue(fragment, shortLabelFromIri(entry.value));
143
+ }
144
+ else {
145
+ fragment.appendChild(createWikiLinkElement(entry.value, shortLabelFromIri(entry.value)));
146
+ }
147
+ return fragment;
148
+ }
149
+ if (entry.kind === 'bnode') {
150
+ appendInlineValue(fragment, `_:${entry.value}`);
151
+ return fragment;
152
+ }
153
+ if (isUrlValue(entry.value)) {
154
+ const link = document.createElement('a');
155
+ link.href = entry.value;
156
+ link.textContent = entry.value;
157
+ fragment.appendChild(link);
158
+ return fragment;
159
+ }
160
+ appendInlineValue(fragment, entry.value);
161
+ return fragment;
162
+ }
100
163
  }
101
164
  export class CanvasMarkdownBlockRenderer extends QueryMarkdownBlockRenderer {
102
165
  canRender(result) {
@@ -111,4 +174,39 @@ export class CanvasMarkdownBlockRenderer extends QueryMarkdownBlockRenderer {
111
174
  return container;
112
175
  }
113
176
  }
177
+ const BUILT_IN_ONTOLOGY_IRIS = new Set([
178
+ 'http://opencaesar.io/oml',
179
+ 'http://www.w3.org/2001/XMLSchema',
180
+ 'http://www.w3.org/1999/02/22-rdf-syntax-ns',
181
+ 'http://www.w3.org/2000/01/rdf-schema',
182
+ 'http://www.w3.org/2002/07/owl',
183
+ 'http://www.w3.org/2003/11/swrl',
184
+ 'http://www.w3.org/2003/11/swrlb',
185
+ ]);
186
+ function ontologyLookupKeyFromIri(value) {
187
+ const iri = String(value ?? '').trim().replace(/^<|>$/g, '');
188
+ if (!iri || !/^[A-Za-z][A-Za-z0-9+.-]*:[^\s]+$/.test(iri)) {
189
+ return undefined;
190
+ }
191
+ const hashIndex = iri.indexOf('#');
192
+ if (hashIndex >= 0) {
193
+ return normalizeOntologyLookupKey(iri.slice(0, hashIndex + 1));
194
+ }
195
+ const schemeIndex = iri.indexOf('://');
196
+ const slashIndex = iri.lastIndexOf('/');
197
+ if (slashIndex > schemeIndex + 2) {
198
+ return normalizeOntologyLookupKey(iri.slice(0, slashIndex + 1));
199
+ }
200
+ return normalizeOntologyLookupKey(iri);
201
+ }
202
+ function normalizeOntologyLookupKey(value) {
203
+ return value.trim().replace(/^<|>$/g, '').replace(/[\/#]+$/, '');
204
+ }
205
+ function isBuiltInOntologyIri(iri) {
206
+ const key = ontologyLookupKeyFromIri(iri);
207
+ if (!key) {
208
+ return false;
209
+ }
210
+ return BUILT_IN_ONTOLOGY_IRIS.has(normalizeOntologyLookupKey(key));
211
+ }
114
212
  //# sourceMappingURL=renderer.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"renderer.js","sourceRoot":"","sources":["../../src/renderers/renderer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"renderer.js","sourceRoot":"","sources":["../../src/renderers/renderer.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { QueryMarkdownBlockRenderer, type TableBlockKind } from './renderer.js';
2
- import type { MdBlockExecutionResult } from './types.js';
2
+ import type { MdBlockExecutionResult, MdTableCell } from './types.js';
3
3
  type TableEditorActionKind = 'add' | 'remove' | 'validate' | 'link' | 'undo' | 'redo' | 'ai' | 'properties';
4
4
  type TableEditorActionContext = {
5
5
  action: TableEditorActionKind;
@@ -48,7 +48,7 @@ export declare class TableMarkdownBlockRenderer extends QueryMarkdownBlockRender
48
48
  protected shouldIgnoreRowDoubleClick(_event: MouseEvent): boolean;
49
49
  protected onRowDoubleClick(_context: Omit<TableEditorActionContext, 'action'>): void;
50
50
  protected dispatchTableEditorAction(context: TableEditorActionContext): void;
51
- protected renderInteractiveTable(columns: string[], rows: string[][], stylesheet: CompiledTableStyleRule[], options: Record<string, unknown> | undefined, blockSource?: string): HTMLElement;
51
+ protected renderInteractiveTable(columns: string[], rows: string[][], rowsTyped: MdTableCell[][] | undefined, stylesheet: CompiledTableStyleRule[], options: Record<string, unknown> | undefined, blockSource?: string, blockId?: string): HTMLElement;
52
52
  protected extractTypeOptions(_blockSource: string | undefined): string[];
53
53
  private resolveTreeSourceRows;
54
54
  private filterTreeRowsBySearch;
@@ -58,6 +58,7 @@ export declare class TableMarkdownBlockRenderer extends QueryMarkdownBlockRender
58
58
  private renderTreeCell;
59
59
  private createTreeActionButton;
60
60
  private applyFiltersAndSorting;
61
+ private getDisplayFilterCells;
61
62
  private applyStylesheet;
62
63
  private matchesRule;
63
64
  private resolveValueTargets;
@@ -67,6 +68,7 @@ export declare class TableMarkdownBlockRenderer extends QueryMarkdownBlockRender
67
68
  private installColumnResizeHandle;
68
69
  private autosizeColumnWidth;
69
70
  private measureTreePrefixWidth;
71
+ private measureRenderedCellContentWidth;
70
72
  private resolveFont;
71
73
  private measureTextWidth;
72
74
  protected formatCellDisplayValue(raw: string, _context: {
@@ -76,6 +78,14 @@ export declare class TableMarkdownBlockRenderer extends QueryMarkdownBlockRender
76
78
  options?: Record<string, unknown>;
77
79
  }): string;
78
80
  private renderValue;
81
+ protected createUploadCsvButton(_columns: string[], _rows: Array<{
82
+ index: number;
83
+ cells: string[];
84
+ }>, _isTree: boolean, _blockSource: string | undefined): HTMLElement | undefined;
85
+ protected transformCsvDownloadData(columns: string[], rows: string[][]): {
86
+ columns: string[];
87
+ rows: string[][];
88
+ };
79
89
  private requestCsvDownload;
80
90
  private requestTreeJsonDownload;
81
91
  private createTreeJsonKeys;
@@ -1,6 +1,6 @@
1
1
  // Copyright (c) 2026 Modelware. All rights reserved.
2
2
  import { QueryMarkdownBlockRenderer } from './renderer.js';
3
- import { appendTokenizedValueParts, isIriValue, shortLabelFromIri } from './wikilink-utils.js';
3
+ import { shortLabelFromIri } from './wikilink-utils.js';
4
4
  export class TableMarkdownBlockRenderer extends QueryMarkdownBlockRenderer {
5
5
  constructor() {
6
6
  super(...arguments);
@@ -16,7 +16,7 @@ export class TableMarkdownBlockRenderer extends QueryMarkdownBlockRenderer {
16
16
  const container = this.createResultContainer(result.status);
17
17
  container.classList.add('oml-md-result-table');
18
18
  const stylesheet = compileTableStylesheet(result.options);
19
- const tableRoot = this.renderInteractiveTable(result.payload?.columns ?? [], result.payload?.rows ?? [], stylesheet, result.options, result.blockSource);
19
+ const tableRoot = this.renderInteractiveTable(result.payload?.columns ?? [], result.payload?.rows ?? [], result.payload?.rowsTyped, stylesheet, result.options, result.blockSource, result.blockId);
20
20
  if (typeof result.blockId === 'string' && result.blockId.length > 0) {
21
21
  tableRoot.dataset.tableBlockId = result.blockId;
22
22
  }
@@ -39,11 +39,15 @@ export class TableMarkdownBlockRenderer extends QueryMarkdownBlockRenderer {
39
39
  const event = new CustomEvent('oml-table-editor-action', { detail: context });
40
40
  window.dispatchEvent(event);
41
41
  }
42
- renderInteractiveTable(columns, rows, stylesheet, options, blockSource) {
42
+ renderInteractiveTable(columns, rows, rowsTyped, stylesheet, options, blockSource, blockId) {
43
43
  const root = document.createElement('div');
44
44
  root.className = 'table-root graph-root';
45
45
  const isTree = this.tableKinds.includes('tree');
46
- const allRowsWithIndex = rows.map((cells, index) => ({ index, cells }));
46
+ const allRowsWithIndex = rows.map((cells, index) => ({
47
+ index,
48
+ cells,
49
+ typedCells: rowsTyped?.[index],
50
+ }));
47
51
  const containmentColumns = isTree ? resolveContainmentColumns(columns, options) : [];
48
52
  const baseVisibleColumnIndexes = isTree
49
53
  ? columns.map((_, index) => index).filter((index) => !containmentColumns.includes(index))
@@ -52,6 +56,7 @@ export class TableMarkdownBlockRenderer extends QueryMarkdownBlockRenderer {
52
56
  const baseRowsWithIndex = allRowsWithIndex.map((row) => ({
53
57
  ...row,
54
58
  cells: baseVisibleColumnIndexes.map((columnIndex) => row.cells[columnIndex] ?? ''),
59
+ typedCells: baseVisibleColumnIndexes.map((columnIndex) => row.typedCells?.[columnIndex]),
55
60
  }));
56
61
  const selectorRowsByIndex = new Map(baseRowsWithIndex.map((row) => [row.index, row]));
57
62
  const baseColumnContexts = createColumnContexts(baseVisibleColumns, baseRowsWithIndex);
@@ -61,7 +66,18 @@ export class TableMarkdownBlockRenderer extends QueryMarkdownBlockRenderer {
61
66
  const rowsWithIndex = allRowsWithIndex.map((row) => ({
62
67
  ...row,
63
68
  cells: visibleColumnIndexes.map((columnIndex) => row.cells[columnIndex] ?? ''),
69
+ typedCells: visibleColumnIndexes.map((columnIndex) => row.typedCells?.[columnIndex]),
64
70
  }));
71
+ root.__omlAiContext = {
72
+ columns: visibleColumns.slice(),
73
+ rows: rowsWithIndex
74
+ .map((row) => ({
75
+ iri: (row.cells[0] ?? '').trim(),
76
+ cells: row.cells.slice(),
77
+ }))
78
+ .filter((row) => row.iri.length > 0),
79
+ blockSource,
80
+ };
65
81
  const columnContexts = createColumnContexts(visibleColumns, rowsWithIndex);
66
82
  const treeModel = isTree
67
83
  ? this.createTreeModel(columns, allRowsWithIndex, visibleColumnIndexes, options)
@@ -69,17 +85,33 @@ export class TableMarkdownBlockRenderer extends QueryMarkdownBlockRenderer {
69
85
  const fullyExpandedTreeRows = isTree && treeModel
70
86
  ? this.flattenAllTreeRows(treeModel)
71
87
  : undefined;
88
+ const persistedState = blockId
89
+ ? window.__omlGetPersistedTableUiState?.(blockId)
90
+ : undefined;
72
91
  const state = {
73
- search: '',
74
- pageSize: 50,
75
- page: 0,
76
- sortKey: '',
77
- sortDir: 'asc',
78
- hasUserSort: false,
92
+ search: persistedState?.search ?? '',
93
+ pageSize: persistedState?.pageSize ?? 50,
94
+ page: persistedState?.page ?? 0,
95
+ sortKey: persistedState?.sortKey ?? '',
96
+ sortDir: persistedState?.sortDir ?? 'asc',
97
+ hasUserSort: persistedState?.hasUserSort ?? false,
79
98
  columnWidths: new Array(columns.length).fill(undefined),
80
99
  initialAutosizeApplied: false,
81
100
  expanded: new Set(treeModel?.expandableNodes ?? []),
82
101
  };
102
+ const persistUiState = () => {
103
+ if (!blockId) {
104
+ return;
105
+ }
106
+ window.__omlSetPersistedTableUiState?.(blockId, {
107
+ search: state.search,
108
+ pageSize: state.pageSize,
109
+ page: state.page,
110
+ sortKey: state.sortKey,
111
+ sortDir: state.sortDir,
112
+ hasUserSort: state.hasUserSort,
113
+ });
114
+ };
83
115
  const controls = document.createElement('div');
84
116
  controls.className = 'table-controls';
85
117
  const controlsLeft = document.createElement('div');
@@ -95,9 +127,11 @@ export class TableMarkdownBlockRenderer extends QueryMarkdownBlockRenderer {
95
127
  }
96
128
  pageSize.appendChild(option);
97
129
  }
130
+ pageSize.value = String(state.pageSize);
98
131
  pageSize.addEventListener('change', () => {
99
132
  state.pageSize = Number.parseInt(pageSize.value, 10);
100
133
  state.page = 0;
134
+ persistUiState();
101
135
  renderPage();
102
136
  });
103
137
  if (!isTree) {
@@ -123,9 +157,11 @@ export class TableMarkdownBlockRenderer extends QueryMarkdownBlockRenderer {
123
157
  searchInput.type = 'search';
124
158
  searchInput.className = 'tree-filter';
125
159
  searchInput.placeholder = 'Filter...';
160
+ searchInput.value = state.search;
126
161
  searchInput.addEventListener('input', () => {
127
162
  state.search = searchInput.value.trim().toLowerCase();
128
163
  state.page = 0;
164
+ persistUiState();
129
165
  renderPage();
130
166
  });
131
167
  controlsRight.appendChild(searchInput);
@@ -146,16 +182,21 @@ export class TableMarkdownBlockRenderer extends QueryMarkdownBlockRenderer {
146
182
  downloadButton.appendChild(iconSvg);
147
183
  downloadButton.addEventListener('click', () => {
148
184
  const sourceRows = isTree && treeModel
149
- ? this.resolveTreeSourceRows(treeModel, visibleColumns, state.expanded, state.search)
185
+ ? this.resolveTreeSourceRows(treeModel, visibleColumns, state.expanded, state.search, blockSource, options)
150
186
  : rowsWithIndex;
151
187
  if (isTree && treeModel) {
152
188
  this.requestTreeJsonDownload(visibleColumns, treeModel, sourceRows);
153
189
  return;
154
190
  }
155
- const filtered = this.applyFiltersAndSorting(columns, sourceRows, state);
156
- this.requestCsvDownload(visibleColumns, filtered.map((entry) => entry.cells));
191
+ const filtered = this.applyFiltersAndSorting(visibleColumns, sourceRows, state, blockSource, options);
192
+ const csvExport = this.transformCsvDownloadData(visibleColumns, filtered.map((entry) => entry.cells));
193
+ this.requestCsvDownload(csvExport.columns, csvExport.rows);
157
194
  });
158
195
  controlsRight.appendChild(downloadButton);
196
+ const uploadButton = this.createUploadCsvButton(visibleColumns, rowsWithIndex, isTree, blockSource);
197
+ if (uploadButton) {
198
+ controlsRight.appendChild(uploadButton);
199
+ }
159
200
  controls.appendChild(controlsLeft);
160
201
  controls.appendChild(controlsRight);
161
202
  root.appendChild(controls);
@@ -191,6 +232,7 @@ export class TableMarkdownBlockRenderer extends QueryMarkdownBlockRenderer {
191
232
  }
192
233
  if (state.page > 0) {
193
234
  state.page -= 1;
235
+ persistUiState();
194
236
  renderPage();
195
237
  }
196
238
  });
@@ -198,10 +240,11 @@ export class TableMarkdownBlockRenderer extends QueryMarkdownBlockRenderer {
198
240
  if (isTree) {
199
241
  return;
200
242
  }
201
- const filtered = this.applyFiltersAndSorting(columns, rowsWithIndex, state);
243
+ const filtered = this.applyFiltersAndSorting(visibleColumns, rowsWithIndex, state, blockSource, options);
202
244
  const totalPages = Math.max(1, Math.ceil(filtered.length / state.pageSize));
203
245
  if (state.page < totalPages - 1) {
204
246
  state.page += 1;
247
+ persistUiState();
205
248
  renderPage();
206
249
  }
207
250
  });
@@ -218,9 +261,11 @@ export class TableMarkdownBlockRenderer extends QueryMarkdownBlockRenderer {
218
261
  root.appendChild(footer);
219
262
  const renderPage = () => {
220
263
  const sourceRows = isTree && treeModel
221
- ? this.resolveTreeSourceRows(treeModel, visibleColumns, state.expanded, state.search)
264
+ ? this.resolveTreeSourceRows(treeModel, visibleColumns, state.expanded, state.search, blockSource, options)
222
265
  : rowsWithIndex;
223
- const filtered = isTree ? sourceRows.slice() : this.applyFiltersAndSorting(columns, sourceRows, state);
266
+ const filtered = isTree
267
+ ? sourceRows.slice()
268
+ : this.applyFiltersAndSorting(visibleColumns, sourceRows, state, blockSource, options);
224
269
  const total = filtered.length;
225
270
  const totalTreeRows = isTree
226
271
  ? (fullyExpandedTreeRows?.length ?? total)
@@ -228,6 +273,7 @@ export class TableMarkdownBlockRenderer extends QueryMarkdownBlockRenderer {
228
273
  const totalPages = isTree ? 1 : Math.max(1, Math.ceil(total / state.pageSize));
229
274
  if (!isTree && state.page >= totalPages) {
230
275
  state.page = totalPages - 1;
276
+ persistUiState();
231
277
  }
232
278
  const gridTemplateColumns = this.buildGridTemplate(visibleColumns.length, state.columnWidths);
233
279
  headerRow.innerHTML = '';
@@ -255,6 +301,7 @@ export class TableMarkdownBlockRenderer extends QueryMarkdownBlockRenderer {
255
301
  }
256
302
  state.hasUserSort = true;
257
303
  state.page = 0;
304
+ persistUiState();
258
305
  renderPage();
259
306
  });
260
307
  }
@@ -281,6 +328,7 @@ export class TableMarkdownBlockRenderer extends QueryMarkdownBlockRenderer {
281
328
  const rowContext = createRowContext(baseVisibleColumns, selectorRow);
282
329
  for (let columnIndex = 0; columnIndex < visibleColumns.length; columnIndex += 1) {
283
330
  const value = rowEntry.cells[columnIndex] ?? '';
331
+ const typedValue = rowEntry.typedCells?.[columnIndex];
284
332
  const td = document.createElement('div');
285
333
  td.className = 'table-cell';
286
334
  const valueElement = this.renderValue(this.formatCellDisplayValue(value, {
@@ -288,7 +336,7 @@ export class TableMarkdownBlockRenderer extends QueryMarkdownBlockRenderer {
288
336
  columns: visibleColumns,
289
337
  blockSource,
290
338
  options,
291
- }));
339
+ }), typedValue);
292
340
  if (isTree && columnIndex === 0) {
293
341
  const treeCell = this.renderTreeCell(valueElement, rowEntry, treeModel, state.expanded, () => renderPage());
294
342
  td.appendChild(treeCell);
@@ -355,13 +403,13 @@ export class TableMarkdownBlockRenderer extends QueryMarkdownBlockRenderer {
355
403
  extractTypeOptions(_blockSource) {
356
404
  return [];
357
405
  }
358
- resolveTreeSourceRows(model, columns, expanded, search) {
406
+ resolveTreeSourceRows(model, columns, expanded, search, blockSource, options) {
359
407
  if (search) {
360
- return this.filterTreeRowsBySearch(model, columns, search);
408
+ return this.filterTreeRowsBySearch(model, columns, search, blockSource, options);
361
409
  }
362
410
  return this.flattenTreeRows(model, expanded);
363
411
  }
364
- filterTreeRowsBySearch(model, columns, search) {
412
+ filterTreeRowsBySearch(model, columns, search, blockSource, options) {
365
413
  const fullyExpanded = this.flattenTreeRows(model, new Set(model.expandableNodes));
366
414
  const matchedIds = new Set();
367
415
  for (const row of fullyExpanded) {
@@ -369,7 +417,7 @@ export class TableMarkdownBlockRenderer extends QueryMarkdownBlockRenderer {
369
417
  if (!nodeId) {
370
418
  continue;
371
419
  }
372
- if (matchesFilterQuery(columns, row.cells, search)) {
420
+ if (matchesFilterQuery(columns, this.getDisplayFilterCells(row, columns, blockSource, options), search)) {
373
421
  matchedIds.add(nodeId);
374
422
  }
375
423
  }
@@ -405,6 +453,7 @@ export class TableMarkdownBlockRenderer extends QueryMarkdownBlockRenderer {
405
453
  const projectRow = (row) => ({
406
454
  ...row,
407
455
  cells: visibleColumnIndexes.map((columnIndex) => row.cells[columnIndex] ?? ''),
456
+ typedCells: visibleColumnIndexes.map((columnIndex) => row.typedCells?.[columnIndex]),
408
457
  });
409
458
  for (const row of allRows) {
410
459
  const id = row.cells[idColumnIndex] ?? '';
@@ -449,7 +498,7 @@ export class TableMarkdownBlockRenderer extends QueryMarkdownBlockRenderer {
449
498
  const syntheticAll = new Array(allColumns.length).fill('');
450
499
  syntheticAll[idColumnIndex] = child;
451
500
  const synthetic = visibleColumnIndexes.map((columnIndex) => syntheticAll[columnIndex] ?? '');
452
- const syntheticRow = { index: allRows.length + rowsById.size, cells: synthetic };
501
+ const syntheticRow = { index: allRows.length + rowsById.size, cells: synthetic, typedCells: new Array(visibleColumnIndexes.length).fill(undefined) };
453
502
  rowsById.set(child, syntheticRow);
454
503
  order.push(child);
455
504
  }
@@ -588,9 +637,9 @@ export class TableMarkdownBlockRenderer extends QueryMarkdownBlockRenderer {
588
637
  button.appendChild(iconSvg);
589
638
  return button;
590
639
  }
591
- applyFiltersAndSorting(columns, rows, state) {
640
+ applyFiltersAndSorting(columns, rows, state, blockSource, options) {
592
641
  const filtered = state.search
593
- ? rows.filter((row) => matchesFilterQuery(columns, row.cells, state.search))
642
+ ? rows.filter((row) => matchesFilterQuery(columns, this.getDisplayFilterCells(row, columns, blockSource, options), state.search))
594
643
  : rows.slice();
595
644
  if (!state.hasUserSort) {
596
645
  return filtered;
@@ -606,6 +655,21 @@ export class TableMarkdownBlockRenderer extends QueryMarkdownBlockRenderer {
606
655
  return a.localeCompare(b, undefined, { numeric: true, sensitivity: 'base' }) * dir;
607
656
  });
608
657
  }
658
+ getDisplayFilterCells(row, columns, blockSource, options) {
659
+ return columns.map((_, columnIndex) => {
660
+ const raw = row.cells[columnIndex] ?? '';
661
+ const typedValue = row.typedCells?.[columnIndex];
662
+ if (typedValue?.values?.length) {
663
+ return this.formatCellDisplayText(raw, typedValue);
664
+ }
665
+ return this.formatCellDisplayValue(raw, {
666
+ columnIndex,
667
+ columns,
668
+ blockSource,
669
+ options,
670
+ });
671
+ });
672
+ }
609
673
  applyStylesheet(cellElement, valueElement, rules, contexts) {
610
674
  for (const rule of rules) {
611
675
  if (rule.target !== 'value') {
@@ -740,13 +804,12 @@ export class TableMarkdownBlockRenderer extends QueryMarkdownBlockRenderer {
740
804
  }
741
805
  autosizeColumnWidth(columnIndex, columns, rows, referenceCellOrFont, headerFontOverride) {
742
806
  const headerText = `${columns[columnIndex] ?? ''} ▲`;
743
- const values = rows.map((row) => formatCellDisplayText(row.cells[columnIndex] ?? ''));
744
807
  const valueFont = typeof referenceCellOrFont === 'string'
745
808
  ? referenceCellOrFont
746
809
  : this.resolveFont(referenceCellOrFont);
747
810
  const headerFont = headerFontOverride ?? valueFont;
748
- const widestValue = values.reduce((max, text) => {
749
- const width = this.measureTextWidth(text, valueFont);
811
+ const widestValue = rows.reduce((max, row) => {
812
+ const width = this.measureRenderedCellContentWidth(row, columnIndex, columns, valueFont);
750
813
  return Math.max(max, width);
751
814
  }, 0);
752
815
  const headerWidth = this.measureTextWidth(headerText, headerFont);
@@ -774,6 +837,34 @@ export class TableMarkdownBlockRenderer extends QueryMarkdownBlockRenderer {
774
837
  return Math.max(max, prefix);
775
838
  }, 0);
776
839
  }
840
+ measureRenderedCellContentWidth(row, columnIndex, columns, font) {
841
+ const rawValue = row.cells[columnIndex] ?? '';
842
+ const typedValue = row.typedCells?.[columnIndex];
843
+ const formattedValue = this.formatCellDisplayValue(rawValue, {
844
+ columnIndex,
845
+ columns,
846
+ });
847
+ const valueElement = this.renderValue(formattedValue, typedValue);
848
+ const decorated = this.decorateCellValueElement({
849
+ row: { index: row.index, cells: row.cells },
850
+ columnIndex,
851
+ columns,
852
+ value: rawValue,
853
+ valueElement,
854
+ });
855
+ const probe = document.createElement('div');
856
+ probe.style.position = 'fixed';
857
+ probe.style.left = '-10000px';
858
+ probe.style.top = '-10000px';
859
+ probe.style.visibility = 'hidden';
860
+ probe.style.whiteSpace = 'nowrap';
861
+ probe.style.font = font;
862
+ probe.appendChild(decorated);
863
+ document.body.appendChild(probe);
864
+ const width = probe.getBoundingClientRect().width;
865
+ probe.remove();
866
+ return width;
867
+ }
777
868
  resolveFont(referenceCell) {
778
869
  const computed = window.getComputedStyle(referenceCell);
779
870
  const lineHeight = computed.lineHeight && computed.lineHeight !== 'normal' ? computed.lineHeight : computed.fontSize;
@@ -791,11 +882,14 @@ export class TableMarkdownBlockRenderer extends QueryMarkdownBlockRenderer {
791
882
  formatCellDisplayValue(raw, _context) {
792
883
  return raw;
793
884
  }
794
- renderValue(raw) {
795
- const value = document.createElement('span');
796
- value.className = 'table-value';
797
- appendTokenizedValueParts(value, raw, 'table-value-part');
798
- return value;
885
+ renderValue(raw, typedValue) {
886
+ return this.renderCellValue(raw, typedValue);
887
+ }
888
+ createUploadCsvButton(_columns, _rows, _isTree, _blockSource) {
889
+ return undefined;
890
+ }
891
+ transformCsvDownloadData(columns, rows) {
892
+ return { columns, rows };
799
893
  }
800
894
  requestCsvDownload(columns, rows) {
801
895
  if (columns.length === 0) {
@@ -1124,13 +1218,6 @@ function resolveHiddenColumns(columns, columnContexts, rules) {
1124
1218
  }
1125
1219
  return hidden;
1126
1220
  }
1127
- function formatCellDisplayText(raw) {
1128
- const parts = raw.split(/[\s,]+/).filter((entry) => entry.length > 0);
1129
- if (parts.length === 0) {
1130
- return raw;
1131
- }
1132
- return parts.map((part) => isIriValue(part) ? shortLabelFromIri(part) : part).join(' ');
1133
- }
1134
1221
  function matchesFilterQuery(columns, cells, rawQuery) {
1135
1222
  const terms = parseFilterTerms(rawQuery);
1136
1223
  if (terms.length === 0) {