@glossarist/concept-browser 0.7.119 → 0.7.120

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.119",
3
+ "version": "0.7.120",
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": {
@@ -0,0 +1,31 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { RelatedConcept } from 'glossarist';
3
+ import { resolveRefTarget } from '../../adapters/GraphDataSource';
4
+
5
+ describe('GraphDataSource.resolveRefTarget — prefers native target field', () => {
6
+ it('returns rc.target when set (cross-dataset resolved URI)', () => {
7
+ const rc = new RelatedConcept({
8
+ type: 'superseded_by',
9
+ target: 'https://example.com/cie-2020/concept/17-21-097',
10
+ ref: { source: 'CIE S 017:2020', id: '17-21-097' },
11
+ });
12
+ const target = resolveRefTarget(rc, 'https://example.com/cie-eilv', 'cie-2011', undefined);
13
+ expect(target).toBe('https://example.com/cie-2020/concept/17-21-097');
14
+ });
15
+
16
+ it('falls back to ref resolution when target is null', () => {
17
+ const rc = new RelatedConcept({
18
+ type: 'supersedes',
19
+ ref: { source: 'cie-2020', id: '42' },
20
+ });
21
+ const urnMap = new Map([['cie-2020', 'cie-2020']]);
22
+ const target = resolveRefTarget(rc, 'https://example.com', 'cie-2011', urnMap);
23
+ expect(target).toBe('https://example.com/cie-2020/concept/42');
24
+ });
25
+
26
+ it('returns empty string when neither target nor ref is set', () => {
27
+ const rc = new RelatedConcept({ type: 'see' });
28
+ const target = resolveRefTarget(rc, 'https://example.com', 'cie-2011', undefined);
29
+ expect(target).toBe('');
30
+ });
31
+ });
@@ -16,7 +16,13 @@ interface DomainNodeJson {
16
16
  children?: DomainNodeJson[];
17
17
  }
18
18
 
19
- function resolveRefTarget(rc: RelatedConcept, uriBase: string, registerId: string, urnMap?: ReadonlyMap<string, string>): string {
19
+ export function resolveRefTarget(rc: RelatedConcept, uriBase: string, registerId: string, urnMap?: ReadonlyMap<string, string>): string {
20
+ // Prefer the native target field — already resolved at build time
21
+ // via refPrefixMap in generate-data.ts. This is the author-provided
22
+ // canonical URL for cross-dataset relations.
23
+ if (rc.target) return rc.target;
24
+
25
+ // Fallback: resolve from ref (for data generated before gl:target existed)
20
26
  if (!rc.ref) return '';
21
27
  const ref = rc.ref;
22
28
  if (ref.id) {
@@ -170,7 +170,8 @@ function attachBridges(concept: Concept, localizations: Record<string, unknown>)
170
170
  /**
171
171
  * Attach bridged fields (ref text, sourceId, citation) to RelatedConcept instances
172
172
  * from the raw deserialized data. Called after Concept.fromJSON creates the model
173
- * instances, since RelatedConcept.fromJSON only reads type/content/ref.
173
+ * instances, since RelatedConcept.fromJSON does not read sourceId/citation/text.
174
+ * (It does read type/content/ref/target natively.)
174
175
  */
175
176
  function attachRelatedBridges(
176
177
  modelRelated: ReadonlyArray<{ type?: string | null; content?: Record<string, string> | string | null; ref?: any; related?: ReadonlyArray<any> }>,