@glossarist/concept-browser 0.7.35 → 0.7.37
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 +2 -2
- package/scripts/build-edges.js +16 -8
- package/scripts/generate-data.mjs +284 -86
- package/src/__tests__/citation-display.test.ts +165 -3
- package/src/__tests__/cite-ref.test.ts +112 -0
- package/src/__tests__/concept-detail-interaction.test.ts +1 -1
- package/src/__tests__/{math.test.ts → content-renderer.test.ts} +113 -29
- package/src/__tests__/escape.test.ts +76 -0
- package/src/__tests__/graph-data-source.test.ts +155 -0
- package/src/__tests__/model-bridge-bridges.test.ts +150 -0
- package/src/__tests__/model-bridge-citation.test.ts +163 -0
- package/src/__tests__/reference-resolver-cite.test.ts +122 -0
- package/src/__tests__/reference-resolver.test.ts +12 -7
- package/src/__tests__/resolve-view.test.ts +1 -1
- package/src/__tests__/sidebar-nav-highlighting.test.ts +178 -0
- package/src/__tests__/source-refs.test.ts +9 -6
- package/src/__tests__/test-helpers.ts +20 -0
- package/src/__tests__/uri-router.test.ts +39 -12
- package/src/adapters/DatasetAdapter.ts +12 -0
- package/src/adapters/GraphDataSource.ts +3 -3
- package/src/adapters/ReferenceResolver.ts +85 -55
- package/src/adapters/UriRouter.ts +82 -10
- package/src/adapters/factory.ts +34 -10
- package/src/adapters/model-bridge.ts +121 -71
- package/src/adapters/types.ts +3 -0
- package/src/components/AppSidebar.vue +7 -4
- package/src/components/CitationDisplay.vue +86 -30
- package/src/components/ConceptDetail.vue +6 -4
- package/src/components/LanguageDetail.vue +6 -6
- package/src/composables/use-concept-content.ts +8 -8
- package/src/composables/use-render-options.ts +1 -1
- package/src/graph/GraphEngine.ts +3 -3
- package/src/stores/vocabulary.ts +2 -2
- package/src/utils/content-renderer.ts +312 -0
- package/src/utils/markdown-lite.ts +2 -2
- package/src/utils/math.ts +0 -189
package/src/utils/math.ts
DELETED
|
@@ -1,189 +0,0 @@
|
|
|
1
|
-
import { escapeHtml, escapeAttr } from './escape';
|
|
2
|
-
|
|
3
|
-
export type XrefResolver = (uri: string, term: string) => string;
|
|
4
|
-
export type BibResolver = (refId: string, title: string) => string;
|
|
5
|
-
export type FigResolver = (figId: string) => string;
|
|
6
|
-
|
|
7
|
-
export type ConceptRefResolver = (conceptId: string, term: string) => string;
|
|
8
|
-
|
|
9
|
-
export interface RenderOptions {
|
|
10
|
-
xrefResolver?: XrefResolver;
|
|
11
|
-
bibResolver?: BibResolver;
|
|
12
|
-
figResolver?: FigResolver;
|
|
13
|
-
conceptRefResolver?: ConceptRefResolver;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
function replaceBracketed(text: string, prefix: string, handler: (content: string, bold: boolean) => string): string {
|
|
17
|
-
let result = '';
|
|
18
|
-
let i = 0;
|
|
19
|
-
const boldPrefix = '*' + prefix;
|
|
20
|
-
while (i < text.length) {
|
|
21
|
-
if (text.startsWith(boldPrefix + '[', i)) {
|
|
22
|
-
i += boldPrefix.length + 1;
|
|
23
|
-
let j = i;
|
|
24
|
-
let d = 1;
|
|
25
|
-
while (j < text.length && d > 0) {
|
|
26
|
-
if (text[j] === '[') d++;
|
|
27
|
-
else if (text[j] === ']') d--;
|
|
28
|
-
j++;
|
|
29
|
-
}
|
|
30
|
-
const content = text.slice(i, j - 1);
|
|
31
|
-
let end = j;
|
|
32
|
-
if (end < text.length && text[end] === '*') end++;
|
|
33
|
-
result += handler(content, true);
|
|
34
|
-
i = end;
|
|
35
|
-
} else if (text.startsWith(prefix + '[', i)) {
|
|
36
|
-
i += prefix.length + 1;
|
|
37
|
-
let j = i;
|
|
38
|
-
let d = 1;
|
|
39
|
-
while (j < text.length && d > 0) {
|
|
40
|
-
if (text[j] === '[') d++;
|
|
41
|
-
else if (text[j] === ']') d--;
|
|
42
|
-
j++;
|
|
43
|
-
}
|
|
44
|
-
const content = text.slice(i, j - 1);
|
|
45
|
-
result += handler(content, false);
|
|
46
|
-
i = j;
|
|
47
|
-
} else {
|
|
48
|
-
result += text[i];
|
|
49
|
-
i++;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
return result;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
function mathPlaceholder(expr: string, format: string, bold: boolean): string {
|
|
56
|
-
return `<span class="math-pending${bold ? ' math-bold' : ''}" data-expr="${escapeAttr(expr)}" data-format="${format}">${escapeAttr(expr)}</span>`;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
function convertAsciiDocTables(text: string): string {
|
|
60
|
-
return text.replace(/\n?\|===\n([\s\S]*?)\n\|===/g, (_: string, body: string) => {
|
|
61
|
-
const rows: string[] = body.split('\n').filter((line: string) => line.trim() !== '');
|
|
62
|
-
if (!rows.length) return '';
|
|
63
|
-
|
|
64
|
-
const parsedRows: string[][] = rows.map((row: string) => {
|
|
65
|
-
const cellText = row.replace(/^\s*\|/, '').trim();
|
|
66
|
-
const cells = cellText.split(/\s*\|\s*/).map((c: string) => c.trim()).filter((c: string) => c !== '');
|
|
67
|
-
return cells;
|
|
68
|
-
}).filter((r: string[]) => r.length > 0);
|
|
69
|
-
|
|
70
|
-
if (!parsedRows.length) return '';
|
|
71
|
-
|
|
72
|
-
const maxCols = Math.max(...parsedRows.map((r: string[]) => r.length));
|
|
73
|
-
const normalized = parsedRows.map((r: string[]) => {
|
|
74
|
-
while (r.length < maxCols) r.push('');
|
|
75
|
-
return r;
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
const thead = normalized[0].map((c: string) => `<th>${escapeHtml(c)}</th>`).join('');
|
|
79
|
-
const tbody = normalized.slice(1).map((r: string[]) =>
|
|
80
|
-
`<tr>${r.map((c: string) => `<td>${escapeHtml(c)}</td>`).join('')}</tr>`
|
|
81
|
-
).join('');
|
|
82
|
-
|
|
83
|
-
return `\n<table class="concept-table"><thead><tr>${thead}</tr></thead><tbody>${tbody}</tbody></table>`;
|
|
84
|
-
});
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
function convertLists(text: string): string {
|
|
88
|
-
let result = text.replace(/(?:^|\n)((?:[ \t]*\* [^\n]+)(?:\n[ \t]*\* [^\n]+)*)/g, (_, block) => {
|
|
89
|
-
if (/^\*stem:\[/.test(block.trimStart())) return _;
|
|
90
|
-
const items: string[] = [];
|
|
91
|
-
const re = /[ \t]*\* ([^\n]+)/g;
|
|
92
|
-
let m;
|
|
93
|
-
while ((m = re.exec(block)) !== null) {
|
|
94
|
-
items.push(m[1].trim());
|
|
95
|
-
}
|
|
96
|
-
if (!items.length) return _;
|
|
97
|
-
const lis = items.map(item => `<li>${item}</li>`).join('');
|
|
98
|
-
return `\n<ul class="concept-list">${lis}</ul>`;
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
// Numbered lists: 1) item or 1. item
|
|
102
|
-
result = result.replace(/(?:^|\n)((?:[ \t]*\d+[).][ \t]+[^\n]+)(?:\n[ \t]*\d+[).][ \t]+[^\n]+)*)/g, (_, block) => {
|
|
103
|
-
const items: string[] = [];
|
|
104
|
-
const re = /[ \t]*\d+[).][ \t]+([^\n]+)/g;
|
|
105
|
-
let m;
|
|
106
|
-
while ((m = re.exec(block)) !== null) {
|
|
107
|
-
items.push(m[1].trim());
|
|
108
|
-
}
|
|
109
|
-
if (!items.length) return _;
|
|
110
|
-
const lis = items.map(item => `<li>${item}</li>`).join('');
|
|
111
|
-
return `\n<ol class="concept-list concept-list-ordered">${lis}</ol>`;
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
return result;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
export function renderMath(text: string, xrefResolverOrOpts?: XrefResolver | RenderOptions): string {
|
|
118
|
-
if (!text) return '';
|
|
119
|
-
let result = text;
|
|
120
|
-
|
|
121
|
-
const opts: RenderOptions = typeof xrefResolverOrOpts === 'function'
|
|
122
|
-
? { xrefResolver: xrefResolverOrOpts }
|
|
123
|
-
: (xrefResolverOrOpts ?? {});
|
|
124
|
-
|
|
125
|
-
// Math expressions: output placeholders for v-math directive to upgrade
|
|
126
|
-
result = replaceBracketed(result, 'stem:', (expr, bold) => mathPlaceholder(expr, 'asciimath', bold));
|
|
127
|
-
result = replaceBracketed(result, 'latexmath:', (expr, bold) => mathPlaceholder(expr, 'latex', bold));
|
|
128
|
-
|
|
129
|
-
result = convertAsciiDocTables(result);
|
|
130
|
-
result = convertLists(result);
|
|
131
|
-
result = result.replace(/\*([^*]+)\*/g, '<em>$1</em>');
|
|
132
|
-
result = result.replace(/~([^~]+)~/g, '<sub>$1</sub>');
|
|
133
|
-
|
|
134
|
-
result = result.replace(/<<([^,>]+),([^>]+)>>/g, (_, refId, title) => {
|
|
135
|
-
if (opts.bibResolver) {
|
|
136
|
-
return opts.bibResolver(refId.trim(), title.trim());
|
|
137
|
-
}
|
|
138
|
-
return `<span class="bib-ref">${escapeHtml(title.trim())}</span>`;
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
result = result.replace(/<<(fig_[^>]+)>>/g, (_, figId) => {
|
|
142
|
-
if (opts.figResolver) {
|
|
143
|
-
return opts.figResolver(figId.trim());
|
|
144
|
-
}
|
|
145
|
-
return `<span class="fig-ref">${escapeHtml(figId.trim())}</span>`;
|
|
146
|
-
});
|
|
147
|
-
|
|
148
|
-
result = result.replace(/\{\{(urn:[^,}]+),([^,}]+)(?:,([^}]+))?\}\}/g, (_, uri, term, display) => {
|
|
149
|
-
const t = (display || term).trim();
|
|
150
|
-
if (opts.xrefResolver) {
|
|
151
|
-
return opts.xrefResolver(uri, t);
|
|
152
|
-
}
|
|
153
|
-
return t;
|
|
154
|
-
});
|
|
155
|
-
|
|
156
|
-
result = result.replace(/\{(urn:[^,}]+),([^,}]+)(?:,([^}]+))?\}/g, (_, uri, term, display) => {
|
|
157
|
-
const t = (display || term).trim();
|
|
158
|
-
if (opts.xrefResolver) {
|
|
159
|
-
return opts.xrefResolver(uri, t);
|
|
160
|
-
}
|
|
161
|
-
return t;
|
|
162
|
-
});
|
|
163
|
-
|
|
164
|
-
result = result.replace(/\{\{([^,}]+),\s*([^}]+)\}\}/g, (_, term, id) => {
|
|
165
|
-
if (opts.conceptRefResolver) {
|
|
166
|
-
return opts.conceptRefResolver(id.trim(), term.trim());
|
|
167
|
-
}
|
|
168
|
-
return term.trim();
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
return result;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
export function cleanContent(text: string): string {
|
|
175
|
-
if (!text) return '';
|
|
176
|
-
let result = text
|
|
177
|
-
.replace(/<[^>]+>/g, '')
|
|
178
|
-
.replace(/\*([^*]+)\*/g, '$1')
|
|
179
|
-
.replace(/~([^~]+)~/g, '_$1')
|
|
180
|
-
.replace(/\n[ \t]*\* /g, '; ')
|
|
181
|
-
.replace(/<<([^,>]+),([^>]+)>>/g, '$2')
|
|
182
|
-
.replace(/<<(fig_[^>]+)>>/g, '$1')
|
|
183
|
-
.replace(/\{\{urn:[^,}]+,([^,}]+)(?:,[^}]+)?\}\}/g, '$1')
|
|
184
|
-
.replace(/\{urn:[^,}]+,([^,}]+)(?:,[^}]+)?\}/g, '$1')
|
|
185
|
-
.replace(/\{\{([^,}]+)(?:,\s*[^}]+)?\}\}/g, '$1')
|
|
186
|
-
.replace(/(?:\*?)stem:\[([^\]]*)\]/g, '$1')
|
|
187
|
-
.replace(/(?:\*?)latexmath:\[([^\]]*)\]/g, '$1');
|
|
188
|
-
return result;
|
|
189
|
-
}
|