@glossarist/concept-browser 0.7.124 → 0.7.125

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@glossarist/concept-browser",
3
- "version": "0.7.124",
3
+ "version": "0.7.125",
4
4
  "description": "Vue SPA for browsing Glossarist terminology datasets with cross-reference resolution, graph visualization, and multi-language support",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,6 +1,6 @@
1
1
  // scripts/lib/concept-uri.ts
2
2
  function buildConceptUri(uriBase, registerId, conceptId) {
3
- return `${uriBase}/${registerId}/concept/${conceptId}`;
3
+ return `${uriBase}/dataset/${registerId}/concept/${conceptId}`;
4
4
  }
5
5
 
6
6
  // scripts/bridge-to-astro.ts
@@ -1,6 +1,6 @@
1
1
  // scripts/lib/concept-uri.ts
2
2
  function buildConceptUri(uriBase, registerId, conceptId) {
3
- return `${uriBase}/${registerId}/concept/${conceptId}`;
3
+ return `${uriBase}/dataset/${registerId}/concept/${conceptId}`;
4
4
  }
5
5
 
6
6
  // scripts/extract-source-refs.js
@@ -543,7 +543,7 @@ function normalizeBibliography(raw) {
543
543
 
544
544
  // scripts/lib/concept-uri.ts
545
545
  function buildConceptUri(uriBase, registerId, conceptId) {
546
- return `${uriBase}/${registerId}/concept/${conceptId}`;
546
+ return `${uriBase}/dataset/${registerId}/concept/${conceptId}`;
547
547
  }
548
548
 
549
549
  // scripts/lib/harmonize-concept.ts
@@ -1887,18 +1887,47 @@ function processNewsPage(config2, page) {
1887
1887
  writeJson(path3.join(PUBLIC, "news.json"), index);
1888
1888
  console.log(`Generated news index: ${index.length} posts, ${postFiles.length} files copied to public/news/`);
1889
1889
  }
1890
+ function convertAsciiDocTables(text) {
1891
+ return text.replace(/\n?\|===\n([\s\S]*?)\n\|===/g, (_, body) => {
1892
+ const rows = body.split("\n").filter((line) => line.trim() !== "");
1893
+ if (!rows.length) return "";
1894
+ const parsedRows = rows.map((row) => {
1895
+ const cellText = row.replace(/^\s*\|/, "").trim();
1896
+ return cellText.split(/\s*\|\s*/).map((c) => c.trim()).filter((c) => c !== "");
1897
+ }).filter((r) => r.length > 0);
1898
+ if (!parsedRows.length) return "";
1899
+ const maxCols = Math.max(...parsedRows.map((r) => r.length));
1900
+ const normalized = parsedRows.map((r) => {
1901
+ while (r.length < maxCols) r.push("");
1902
+ return r;
1903
+ });
1904
+ const thead = "<thead><tr>" + normalized[0].map((c) => `<th>${c}</th>`).join("") + "</tr></thead>";
1905
+ const tbody = "<tbody>" + normalized.slice(1).map(
1906
+ (r) => "<tr>" + r.map((c) => `<td>${c}</td>`).join("") + "</tr>"
1907
+ ).join("") + "</tbody>";
1908
+ return `<table class="asciidoc-table">${thead}${tbody}</table>`;
1909
+ });
1910
+ }
1890
1911
  function renderMarkdown(input) {
1912
+ let text = convertAsciiDocTables(input);
1913
+ const HTML_PASS_THROUGH = /<span\s+class="math-pending"[^>]*>[^<]*<\/span>/g;
1914
+ const htmlPlaceholders = [];
1915
+ text = text.replace(HTML_PASS_THROUGH, (match) => {
1916
+ const idx = htmlPlaceholders.length;
1917
+ htmlPlaceholders.push(match);
1918
+ return `\0HTML${idx}\0`;
1919
+ });
1891
1920
  const INLINE_PATTERNS = [
1892
1921
  [/\*\*(.+?)\*\*/g, (m) => `<strong>${m[1]}</strong>`],
1893
1922
  [/(?<!\*)\*([^*]+?)\*(?!\*)/g, (m) => `<em>${m[1]}</em>`],
1894
1923
  [/`([^`]+?)`/g, (m) => `<code>${m[1]}</code>`],
1895
1924
  [/\[([^\]]+)\]\(([^)]+)\)/g, (m) => `<a href="${m[2]}" target="_blank">${m[1]}</a>`]
1896
1925
  ];
1897
- function renderInline(text) {
1926
+ function renderInline(text2) {
1898
1927
  for (const [re, fn] of INLINE_PATTERNS) {
1899
- text = text.replace(re, (...args) => fn(args));
1928
+ text2 = text2.replace(re, (...args) => fn(args));
1900
1929
  }
1901
- return text;
1930
+ return text2;
1902
1931
  }
1903
1932
  function escapeHtml(s) {
1904
1933
  return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
@@ -1982,7 +2011,8 @@ function renderMarkdown(input) {
1982
2011
  }
1983
2012
  if (pl.length) blocks.push(`<p>${renderInline(pl.join(" "))}</p>`);
1984
2013
  }
1985
- return blocks.join("\n");
2014
+ const result = blocks.join("\n").replace(/ HTML(\d+) /g, (_, idx) => htmlPlaceholders[parseInt(idx)]);
2015
+ return result;
1986
2016
  }
1987
2017
  function processContentPage(config2, page) {
1988
2018
  if (!page.source) {
@@ -1265,7 +1265,45 @@ function processNewsPage(config, page) {
1265
1265
 
1266
1266
  // --- Markdown-lite renderer (isomorphic, same logic as src/utils/markdown-lite.ts) ---
1267
1267
 
1268
+ // Convert AsciiDoc table syntax to HTML table.
1269
+ // Matches: |=== ... |=== (with optional leading newline)
1270
+ // Row format: | cell1 | cell2 | cell3 |
1271
+ function convertAsciiDocTables(text: string): string {
1272
+ return text.replace(/\n?\|===\n([\s\S]*?)\n\|===/g, (_: string, body: string) => {
1273
+ const rows = body.split('\n').filter(line => line.trim() !== '');
1274
+ if (!rows.length) return '';
1275
+ const parsedRows = rows.map(row => {
1276
+ const cellText = row.replace(/^\s*\|/, '').trim();
1277
+ return cellText.split(/\s*\|\s*/).map(c => c.trim()).filter(c => c !== '');
1278
+ }).filter(r => r.length > 0);
1279
+ if (!parsedRows.length) return '';
1280
+ const maxCols = Math.max(...parsedRows.map(r => r.length));
1281
+ const normalized = parsedRows.map(r => {
1282
+ while (r.length < maxCols) r.push('');
1283
+ return r;
1284
+ });
1285
+ const thead = '<thead><tr>' + normalized[0].map(c => `<th>${c}</th>`).join('') + '</tr></thead>';
1286
+ const tbody = '<tbody>' + normalized.slice(1).map(r =>
1287
+ '<tr>' + r.map(c => `<td>${c}</td>`).join('') + '</tr>'
1288
+ ).join('') + '</tbody>';
1289
+ return `<table class="asciidoc-table">${thead}${tbody}</table>`;
1290
+ });
1291
+ }
1292
+
1268
1293
  function renderMarkdown(input: string): string {
1294
+ // First convert AsciiDoc tables to HTML
1295
+ let text = convertAsciiDocTables(input);
1296
+
1297
+ // Allow specific HTML tags to pass through (math spans, etc.)
1298
+ // These are author-controlled content embedded in the dataset, not user input.
1299
+ const HTML_PASS_THROUGH = /<span\s+class="math-pending"[^>]*>[^<]*<\/span>/g;
1300
+ const htmlPlaceholders: string[] = [];
1301
+ text = text.replace(HTML_PASS_THROUGH, (match) => {
1302
+ const idx = htmlPlaceholders.length;
1303
+ htmlPlaceholders.push(match);
1304
+ return `HTML${idx}`;
1305
+ });
1306
+
1269
1307
  const INLINE_PATTERNS: [RegExp, (m: string[]) => string][] = [
1270
1308
  [/\*\*(.+?)\*\*/g, m => `<strong>${m[1]}</strong>`],
1271
1309
  [/(?<!\*)\*([^*]+?)\*(?!\*)/g, m => `<em>${m[1]}</em>`],
@@ -1332,7 +1370,9 @@ function renderMarkdown(input: string): string {
1332
1370
  while (i < lines.length && lines[i].trim() && !/^#{1,4}\s/.test(lines[i]) && !/^\s*[-*]\s+/.test(lines[i]) && !/^\s*\d+\.\s+/.test(lines[i]) && !/^>\s?/.test(lines[i]) && !lines[i].trimStart().startsWith('```')) { pl.push(lines[i]); i++; }
1333
1371
  if (pl.length) blocks.push(`<p>${renderInline(pl.join(' '))}</p>`);
1334
1372
  }
1335
- return blocks.join('\n');
1373
+ // Restore HTML pass-through placeholders
1374
+ const result = blocks.join('\n').replace(/ HTML(\d+) /g, (_, idx) => htmlPlaceholders[parseInt(idx)]);
1375
+ return result;
1336
1376
  }
1337
1377
 
1338
1378
  function processContentPage(config: Record<string, any>, page: Record<string, any>) {
@@ -7,8 +7,11 @@
7
7
  * scripts/build-edges.ts
8
8
  *
9
9
  * DRY: all three now import from here.
10
+ *
11
+ * The /dataset/ segment matches the Vue Router route pattern
12
+ * /dataset/:register/concept/:conceptId used by the deployed SPA.
10
13
  */
11
14
 
12
15
  export function buildConceptUri(uriBase: string, registerId: string, conceptId: string | number): string {
13
- return `${uriBase}/${registerId}/concept/${conceptId}`;
16
+ return `${uriBase}/dataset/${registerId}/concept/${conceptId}`;
14
17
  }