@refrakt-md/runes 0.14.4 → 0.16.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.
- package/dist/aggregate-resolve.d.ts +4 -0
- package/dist/aggregate-resolve.d.ts.map +1 -0
- package/dist/aggregate-resolve.js +209 -0
- package/dist/aggregate-resolve.js.map +1 -0
- package/dist/collection-helpers.d.ts +101 -0
- package/dist/collection-helpers.d.ts.map +1 -0
- package/dist/collection-helpers.js +206 -0
- package/dist/collection-helpers.js.map +1 -0
- package/dist/collection-resolve.d.ts +5 -0
- package/dist/collection-resolve.d.ts.map +1 -0
- package/dist/collection-resolve.js +209 -0
- package/dist/collection-resolve.js.map +1 -0
- package/dist/config.d.ts +46 -4
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +208 -88
- package/dist/config.js.map +1 -1
- package/dist/deferred-body.d.ts +19 -0
- package/dist/deferred-body.d.ts.map +1 -0
- package/dist/deferred-body.js +70 -0
- package/dist/deferred-body.js.map +1 -0
- package/dist/drawer-pipeline.d.ts +33 -0
- package/dist/drawer-pipeline.d.ts.map +1 -0
- package/dist/drawer-pipeline.js +206 -0
- package/dist/drawer-pipeline.js.map +1 -0
- package/dist/expand-pipeline.d.ts +51 -0
- package/dist/expand-pipeline.d.ts.map +1 -0
- package/dist/expand-pipeline.js +314 -0
- package/dist/expand-pipeline.js.map +1 -0
- package/dist/field-match.d.ts +43 -0
- package/dist/field-match.d.ts.map +1 -0
- package/dist/field-match.js +121 -0
- package/dist/field-match.js.map +1 -0
- package/dist/functions.d.ts +36 -0
- package/dist/functions.d.ts.map +1 -0
- package/dist/functions.js +74 -0
- package/dist/functions.js.map +1 -0
- package/dist/index.d.ts +34 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +95 -4
- package/dist/index.js.map +1 -1
- package/dist/lang-map.d.ts +32 -0
- package/dist/lang-map.d.ts.map +1 -0
- package/dist/lang-map.js +76 -0
- package/dist/lang-map.js.map +1 -0
- package/dist/lib/index.d.ts +6 -0
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/index.js +9 -0
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/read-file.d.ts +78 -0
- package/dist/lib/read-file.d.ts.map +1 -0
- package/dist/lib/read-file.js +166 -0
- package/dist/lib/read-file.js.map +1 -0
- package/dist/nodes.d.ts.map +1 -1
- package/dist/nodes.js +18 -2
- package/dist/nodes.js.map +1 -1
- package/dist/outline-scope.d.ts +46 -0
- package/dist/outline-scope.d.ts.map +1 -0
- package/dist/outline-scope.js +208 -0
- package/dist/outline-scope.js.map +1 -0
- package/dist/plugins.d.ts +13 -0
- package/dist/plugins.d.ts.map +1 -1
- package/dist/plugins.js +65 -1
- package/dist/plugins.js.map +1 -1
- package/dist/relationships-resolve.d.ts +4 -0
- package/dist/relationships-resolve.d.ts.map +1 -0
- package/dist/relationships-resolve.js +180 -0
- package/dist/relationships-resolve.js.map +1 -0
- package/dist/snippet-pipeline.d.ts +42 -0
- package/dist/snippet-pipeline.d.ts.map +1 -0
- package/dist/snippet-pipeline.js +219 -0
- package/dist/snippet-pipeline.js.map +1 -0
- package/dist/tags/aggregate.d.ts +19 -0
- package/dist/tags/aggregate.d.ts.map +1 -0
- package/dist/tags/aggregate.js +59 -0
- package/dist/tags/aggregate.js.map +1 -0
- package/dist/tags/card.d.ts +25 -0
- package/dist/tags/card.d.ts.map +1 -0
- package/dist/tags/card.js +138 -0
- package/dist/tags/card.js.map +1 -0
- package/dist/tags/collection.d.ts +10 -0
- package/dist/tags/collection.d.ts.map +1 -0
- package/dist/tags/collection.js +54 -0
- package/dist/tags/collection.js.map +1 -0
- package/dist/tags/conversation.d.ts.map +1 -1
- package/dist/tags/conversation.js +26 -6
- package/dist/tags/conversation.js.map +1 -1
- package/dist/tags/drawer.d.ts +26 -0
- package/dist/tags/drawer.d.ts.map +1 -0
- package/dist/tags/drawer.js +134 -0
- package/dist/tags/drawer.js.map +1 -0
- package/dist/tags/expand.d.ts +22 -0
- package/dist/tags/expand.d.ts.map +1 -0
- package/dist/tags/expand.js +76 -0
- package/dist/tags/expand.js.map +1 -0
- package/dist/tags/progress.d.ts +9 -0
- package/dist/tags/progress.d.ts.map +1 -0
- package/dist/tags/progress.js +96 -0
- package/dist/tags/progress.js.map +1 -0
- package/dist/tags/relationships.d.ts +12 -0
- package/dist/tags/relationships.d.ts.map +1 -0
- package/dist/tags/relationships.js +62 -0
- package/dist/tags/relationships.js.map +1 -0
- package/dist/tags/snippet.d.ts +19 -0
- package/dist/tags/snippet.d.ts.map +1 -0
- package/dist/tags/snippet.js +49 -0
- package/dist/tags/snippet.js.map +1 -0
- package/dist/util.d.ts +11 -0
- package/dist/util.d.ts.map +1 -1
- package/dist/util.js +35 -0
- package/dist/util.js.map +1 -1
- package/dist/xref-patterns.d.ts +57 -0
- package/dist/xref-patterns.d.ts.map +1 -0
- package/dist/xref-patterns.js +140 -0
- package/dist/xref-patterns.js.map +1 -0
- package/dist/xref-resolve.d.ts +22 -5
- package/dist/xref-resolve.d.ts.map +1 -1
- package/dist/xref-resolve.js +203 -79
- package/dist/xref-resolve.js.map +1 -1
- package/package.json +3 -3
package/dist/xref-resolve.js
CHANGED
|
@@ -2,29 +2,41 @@
|
|
|
2
2
|
* Xref (cross-reference) resolution utilities.
|
|
3
3
|
*
|
|
4
4
|
* Walks a Markdoc renderable tree and converts xref placeholder spans
|
|
5
|
-
* (produced by the xref/ref tag transform) into resolved `<a>` links
|
|
6
|
-
*
|
|
5
|
+
* (produced by the xref/ref tag transform) into resolved `<a>` links.
|
|
6
|
+
*
|
|
7
|
+
* Resolution model (SPEC-065):
|
|
8
|
+
*
|
|
9
|
+
* 1. **Entity lookup** — find the entity in the registry (exact ID, then
|
|
10
|
+
* case-insensitive name/title). Captures metadata (label, type) for use
|
|
11
|
+
* in rendering even if the URL ends up coming from a pattern.
|
|
12
|
+
* 2. **URL resolution** — if the matched entity has a usable `sourceUrl`,
|
|
13
|
+
* that's the href (`data-xref-source="registry"`). Otherwise iterate
|
|
14
|
+
* configured patterns (compiled via `compileXrefPatterns`); first regex
|
|
15
|
+
* that matches the ID provides the URL (`data-xref-source="pattern"`).
|
|
16
|
+
* 3. **Unresolved fallback** — if neither the entity nor any pattern produces
|
|
17
|
+
* a URL, render `rf-xref--unresolved` with a build warning.
|
|
18
|
+
*
|
|
19
|
+
* The separation lets entity-lookup and URL-resolution succeed independently.
|
|
20
|
+
* SPEC-064 plan content registered without a `sourceUrl` (because it isn't
|
|
21
|
+
* published to any site) still resolves correctly: the registry provides
|
|
22
|
+
* label and type; user-configured patterns provide the URL.
|
|
7
23
|
*/
|
|
8
24
|
import Markdoc from '@markdoc/markdoc';
|
|
9
25
|
const { Tag } = Markdoc;
|
|
10
26
|
import { XREF_RUNE_MARKER } from './tags/xref.js';
|
|
11
|
-
/**
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
|
|
15
|
-
function findEntityById(registry, id, typeHint) {
|
|
27
|
+
/** Find an entity by exact ID across all types in the registry. `pageUrl`
|
|
28
|
+
* scopes the search so page-scoped entries from the resolving page take
|
|
29
|
+
* precedence over site-scoped entries of the same id (SPEC-060). */
|
|
30
|
+
function findEntityById(registry, id, pageUrl, typeHint) {
|
|
16
31
|
const types = typeHint ? [typeHint] : registry.getTypes();
|
|
17
32
|
for (const type of types) {
|
|
18
|
-
const entity = registry.getById(type, id);
|
|
33
|
+
const entity = registry.getById(type, id, pageUrl);
|
|
19
34
|
if (entity)
|
|
20
|
-
return
|
|
35
|
+
return entity;
|
|
21
36
|
}
|
|
22
37
|
return undefined;
|
|
23
38
|
}
|
|
24
|
-
/**
|
|
25
|
-
* Find entities by name/title match (case-insensitive) across all types.
|
|
26
|
-
* If typeHint is provided, only search that type.
|
|
27
|
-
*/
|
|
39
|
+
/** Find entities by case-insensitive name/title match. */
|
|
28
40
|
function findEntitiesByName(registry, name, typeHint) {
|
|
29
41
|
const nameLower = name.toLowerCase();
|
|
30
42
|
const types = typeHint ? [typeHint] : registry.getTypes();
|
|
@@ -40,31 +52,197 @@ function findEntitiesByName(registry, name, typeHint) {
|
|
|
40
52
|
}
|
|
41
53
|
return matches;
|
|
42
54
|
}
|
|
43
|
-
/**
|
|
55
|
+
/** Compute the canonical URL for a registry-matched entity, honoring
|
|
56
|
+
* per-entity `data.url` overrides and `data.headingId` fragment hints. */
|
|
44
57
|
function resolveEntityHref(entity) {
|
|
45
58
|
const baseUrl = entity.data.url || entity.sourceUrl;
|
|
59
|
+
if (!baseUrl)
|
|
60
|
+
return undefined;
|
|
46
61
|
const headingId = entity.data.headingId;
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
62
|
+
return headingId ? `${baseUrl}#${headingId}` : baseUrl;
|
|
63
|
+
}
|
|
64
|
+
/** Choose the rendered label for a resolved xref. Priority: explicit `label=`
|
|
65
|
+
* attribute > entity `data.title` / `data.name` / `data.text` > the raw ID. */
|
|
66
|
+
function deriveEntityLabel(id, authoredLabel, entity) {
|
|
67
|
+
if (authoredLabel)
|
|
68
|
+
return authoredLabel;
|
|
69
|
+
if (entity) {
|
|
70
|
+
const title = entity.data.title;
|
|
71
|
+
const name = entity.data.name;
|
|
72
|
+
const text = entity.data.text;
|
|
73
|
+
return title || name || text || id;
|
|
74
|
+
}
|
|
75
|
+
return id;
|
|
76
|
+
}
|
|
77
|
+
/** Match `{name}` placeholders in template / label strings. */
|
|
78
|
+
const PLACEHOLDER_RE = /\{([a-zA-Z_$][a-zA-Z0-9_$]*)\}/g;
|
|
79
|
+
/** URL-encode per segment: split on `/`, encode each segment with
|
|
80
|
+
* `encodeURIComponent`, rejoin with `/`. Single-segment values are
|
|
81
|
+
* unaffected (the split is a no-op); multi-segment paths preserve their
|
|
82
|
+
* slash structure. This is what the SPEC-065 "per-segment encoding"
|
|
83
|
+
* contract delivers. */
|
|
84
|
+
function encodePerSegment(value) {
|
|
85
|
+
return value.split('/').map(encodeURIComponent).join('/');
|
|
86
|
+
}
|
|
87
|
+
/** Substitute `{id}` and `{name}` placeholders in a template, with each
|
|
88
|
+
* substituted value encoded per URL segment. */
|
|
89
|
+
function applyTemplate(template, id, groups) {
|
|
90
|
+
return template.replace(PLACEHOLDER_RE, (_match, name) => {
|
|
91
|
+
const value = name === 'id' ? id : (groups[name] ?? '');
|
|
92
|
+
return encodePerSegment(value);
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
/** Apply a label template without URL encoding — labels are human-readable
|
|
96
|
+
* text, not URL components. Missing named groups render as empty strings. */
|
|
97
|
+
function applyLabelTemplate(template, id, groups) {
|
|
98
|
+
return template.replace(PLACEHOLDER_RE, (_match, name) => {
|
|
99
|
+
if (name === 'id')
|
|
100
|
+
return id;
|
|
101
|
+
return groups[name] ?? '';
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
/** Try each pattern in order; first match wins. Returns the resolved URL
|
|
105
|
+
* along with the pattern's `type` and computed `label`. */
|
|
106
|
+
function tryPatternMatch(id, patterns) {
|
|
107
|
+
for (const p of patterns) {
|
|
108
|
+
const m = p.match.exec(id);
|
|
109
|
+
if (!m)
|
|
110
|
+
continue;
|
|
111
|
+
const groups = (m.groups ?? {});
|
|
112
|
+
return {
|
|
113
|
+
url: applyTemplate(p.template, id, groups),
|
|
114
|
+
label: applyLabelTemplate(p.label, id, groups),
|
|
115
|
+
type: p.type,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
return undefined;
|
|
119
|
+
}
|
|
120
|
+
/** Reduce an absolute href that points at the current page + fragment down
|
|
121
|
+
* to the fragment alone. Handles both URL shapes seen in practice — page
|
|
122
|
+
* URLs that end with a trailing slash and ones that don't. Returns the
|
|
123
|
+
* original href when it doesn't target the current page. */
|
|
124
|
+
function compactSamePageHref(href, pageUrl) {
|
|
125
|
+
const hashIdx = href.indexOf('#');
|
|
126
|
+
if (hashIdx < 0)
|
|
127
|
+
return href;
|
|
128
|
+
const hrefPath = href.slice(0, hashIdx);
|
|
129
|
+
const fragment = href.slice(hashIdx);
|
|
130
|
+
// Normalise trailing slashes for the comparison so `/x/` and `/x` are
|
|
131
|
+
// treated as the same page (different adapters normalise differently).
|
|
132
|
+
const stripTrail = (s) => s.endsWith('/') ? s.slice(0, -1) : s;
|
|
133
|
+
if (stripTrail(hrefPath) === stripTrail(pageUrl))
|
|
134
|
+
return fragment;
|
|
135
|
+
return href;
|
|
136
|
+
}
|
|
137
|
+
/** Resolve a single xref placeholder. Drives the SPEC-065 chain:
|
|
138
|
+
* entity lookup → URL resolution → unresolved fallback. */
|
|
139
|
+
function resolvePlaceholder(id, authoredLabel, typeHint, rc) {
|
|
140
|
+
// Step 1: entity lookup (capture metadata, may or may not yield a URL).
|
|
141
|
+
let entity = findEntityById(rc.registry, id, rc.pageUrl, typeHint);
|
|
142
|
+
if (!entity) {
|
|
143
|
+
const nameMatches = findEntitiesByName(rc.registry, id, typeHint);
|
|
144
|
+
if (nameMatches.length === 1) {
|
|
145
|
+
entity = nameMatches[0];
|
|
146
|
+
}
|
|
147
|
+
else if (nameMatches.length > 1) {
|
|
148
|
+
const matchList = nameMatches
|
|
149
|
+
.map(e => `${e.type} "${e.data.title || e.data.name || e.id}" on ${e.sourceUrl ?? '(no URL)'}`)
|
|
150
|
+
.join(', ');
|
|
151
|
+
rc.ctx.warn(`xref "${id}" on ${rc.pageUrl} — matches ${nameMatches.length} entities (${matchList}). Add type hint to disambiguate.`, rc.pageUrl);
|
|
152
|
+
entity = nameMatches[0];
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
const entityHref = entity ? resolveEntityHref(entity) : undefined;
|
|
156
|
+
// Step 2a: URL from the entity, if any.
|
|
157
|
+
let resolved;
|
|
158
|
+
if (entity && entityHref) {
|
|
159
|
+
resolved = {
|
|
160
|
+
href: entityHref,
|
|
161
|
+
label: deriveEntityLabel(id, authoredLabel, entity),
|
|
162
|
+
type: entity.type,
|
|
163
|
+
source: 'registry',
|
|
164
|
+
targetType: entity.type,
|
|
165
|
+
entityId: entity.id,
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
// Step 2b: URL from a pattern. Entity metadata still wins for label/type
|
|
170
|
+
// when present; the pattern only contributes the URL in that case.
|
|
171
|
+
const patternHit = tryPatternMatch(id, rc.patterns);
|
|
172
|
+
if (patternHit) {
|
|
173
|
+
resolved = {
|
|
174
|
+
href: patternHit.url,
|
|
175
|
+
label: deriveEntityLabel(id, authoredLabel, entity) || patternHit.label,
|
|
176
|
+
type: entity?.type ?? patternHit.type,
|
|
177
|
+
source: 'pattern',
|
|
178
|
+
targetType: entity?.type,
|
|
179
|
+
entityId: entity?.id,
|
|
180
|
+
};
|
|
181
|
+
// When no entity is matched, the label has to come from the
|
|
182
|
+
// pattern (or the authored label); `deriveEntityLabel` falls back
|
|
183
|
+
// to the raw ID which is rarely what the author wanted from a
|
|
184
|
+
// pattern. Use the pattern label in that case.
|
|
185
|
+
if (!entity && !authoredLabel) {
|
|
186
|
+
resolved.label = patternHit.label;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
// Step 3: unresolved.
|
|
191
|
+
if (!resolved) {
|
|
192
|
+
rc.ctx.warn(`xref "${id}" on ${rc.pageUrl} — entity not found`, rc.pageUrl);
|
|
193
|
+
return {
|
|
194
|
+
tag: new Tag('span', {
|
|
195
|
+
class: 'rf-xref rf-xref--unresolved',
|
|
196
|
+
'data-xref-id': id,
|
|
197
|
+
}, [authoredLabel || id]),
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
// Self-reference detection on the resolved href (covers both registry and
|
|
201
|
+
// pattern cases — a pattern that produces a same-page URL is still a
|
|
202
|
+
// self-reference).
|
|
203
|
+
if (resolved.href === rc.pageUrl) {
|
|
204
|
+
rc.ctx.info(`xref "${id}" on ${rc.pageUrl} — references itself`, rc.pageUrl);
|
|
205
|
+
}
|
|
206
|
+
// Same-page anchor compaction: when the entity's resolved href is the
|
|
207
|
+
// current page plus a fragment, drop the page URL portion so the link
|
|
208
|
+
// renders as a fragment-only anchor (`#drawer-x`) — matches the SPEC-060
|
|
209
|
+
// drawer-trigger contract and is how authors normally write same-page
|
|
210
|
+
// anchors. Behaves identically to the absolute form for the browser; the
|
|
211
|
+
// progressive-enhancement layer (drawer behaviors) reads the fragment
|
|
212
|
+
// directly without needing to compare against location.pathname.
|
|
213
|
+
const renderedHref = compactSamePageHref(resolved.href, rc.pageUrl);
|
|
214
|
+
const attributes = {
|
|
215
|
+
class: `rf-xref rf-xref--${resolved.type}`,
|
|
216
|
+
href: renderedHref,
|
|
217
|
+
'data-xref-id': resolved.entityId ?? id,
|
|
218
|
+
'data-xref-source': resolved.source,
|
|
219
|
+
};
|
|
220
|
+
if (resolved.targetType) {
|
|
221
|
+
attributes['data-target-type'] = resolved.targetType;
|
|
222
|
+
}
|
|
223
|
+
return { tag: new Tag('a', attributes, [resolved.label]) };
|
|
50
224
|
}
|
|
51
225
|
/**
|
|
52
226
|
* Walk a Markdoc renderable tree, resolving any xref placeholders into
|
|
53
|
-
* clickable links using the entity registry
|
|
54
|
-
* styled spans with an `rf-xref--unresolved` class.
|
|
227
|
+
* clickable links using the entity registry and configured patterns.
|
|
228
|
+
* Unresolved xrefs become styled spans with an `rf-xref--unresolved` class.
|
|
55
229
|
*/
|
|
56
|
-
export function resolveXrefs(renderable, pageUrl, registry, ctx) {
|
|
230
|
+
export function resolveXrefs(renderable, pageUrl, registry, patterns, ctx) {
|
|
231
|
+
const rc = { pageUrl, registry, patterns, ctx };
|
|
232
|
+
return walk(renderable, rc);
|
|
233
|
+
}
|
|
234
|
+
function walk(renderable, rc) {
|
|
57
235
|
if (!Tag.isTag(renderable)) {
|
|
58
236
|
if (Array.isArray(renderable)) {
|
|
59
|
-
const
|
|
60
|
-
|
|
237
|
+
const arr = renderable;
|
|
238
|
+
const newChildren = arr.map(c => walk(c, rc));
|
|
239
|
+
if (newChildren.every((c, i) => c === arr[i]))
|
|
61
240
|
return renderable;
|
|
62
241
|
return newChildren;
|
|
63
242
|
}
|
|
64
243
|
return renderable;
|
|
65
244
|
}
|
|
66
245
|
const tag = renderable;
|
|
67
|
-
// Check if this is an xref placeholder
|
|
68
246
|
if (tag.attributes?.['data-rune'] === XREF_RUNE_MARKER) {
|
|
69
247
|
const id = tag.attributes['data-xref-id'];
|
|
70
248
|
const label = tag.attributes['data-xref-label'];
|
|
@@ -74,63 +252,9 @@ export function resolveXrefs(renderable, pageUrl, registry, ctx) {
|
|
|
74
252
|
class: 'rf-xref rf-xref--unresolved',
|
|
75
253
|
}, [label || '?']);
|
|
76
254
|
}
|
|
77
|
-
|
|
78
|
-
const idMatch = findEntityById(registry, id, typeHint);
|
|
79
|
-
if (idMatch) {
|
|
80
|
-
const entity = idMatch.entity;
|
|
81
|
-
const href = resolveEntityHref(entity);
|
|
82
|
-
const text = label || entity.data.title || entity.data.name || entity.data.text || id;
|
|
83
|
-
if (entity.sourceUrl === pageUrl) {
|
|
84
|
-
ctx.info(`xref "${id}" on ${pageUrl} — references itself`, pageUrl);
|
|
85
|
-
}
|
|
86
|
-
return new Tag('a', {
|
|
87
|
-
class: `rf-xref rf-xref--${entity.type}`,
|
|
88
|
-
href,
|
|
89
|
-
'data-entity-type': entity.type,
|
|
90
|
-
'data-entity-id': entity.id,
|
|
91
|
-
}, [text]);
|
|
92
|
-
}
|
|
93
|
-
// Try name/title match
|
|
94
|
-
const nameMatches = findEntitiesByName(registry, id, typeHint);
|
|
95
|
-
if (nameMatches.length === 1) {
|
|
96
|
-
const entity = nameMatches[0];
|
|
97
|
-
const href = resolveEntityHref(entity);
|
|
98
|
-
const text = label || entity.data.title || entity.data.name || entity.data.text || id;
|
|
99
|
-
if (entity.sourceUrl === pageUrl) {
|
|
100
|
-
ctx.info(`xref "${id}" on ${pageUrl} — references itself`, pageUrl);
|
|
101
|
-
}
|
|
102
|
-
return new Tag('a', {
|
|
103
|
-
class: `rf-xref rf-xref--${entity.type}`,
|
|
104
|
-
href,
|
|
105
|
-
'data-entity-type': entity.type,
|
|
106
|
-
'data-entity-id': entity.id,
|
|
107
|
-
}, [text]);
|
|
108
|
-
}
|
|
109
|
-
if (nameMatches.length > 1) {
|
|
110
|
-
const matchList = nameMatches
|
|
111
|
-
.map(e => `${e.type} "${e.data.title || e.data.name || e.id}" on ${e.sourceUrl}`)
|
|
112
|
-
.join(', ');
|
|
113
|
-
ctx.warn(`xref "${id}" on ${pageUrl} — matches ${nameMatches.length} entities (${matchList}). Add type hint to disambiguate.`, pageUrl);
|
|
114
|
-
// Use first match
|
|
115
|
-
const entity = nameMatches[0];
|
|
116
|
-
const href = resolveEntityHref(entity);
|
|
117
|
-
const text = label || entity.data.title || entity.data.name || entity.data.text || id;
|
|
118
|
-
return new Tag('a', {
|
|
119
|
-
class: `rf-xref rf-xref--${entity.type}`,
|
|
120
|
-
href,
|
|
121
|
-
'data-entity-type': entity.type,
|
|
122
|
-
'data-entity-id': entity.id,
|
|
123
|
-
}, [text]);
|
|
124
|
-
}
|
|
125
|
-
// No match — unresolved
|
|
126
|
-
ctx.warn(`xref "${id}" on ${pageUrl} — entity not found`, pageUrl);
|
|
127
|
-
return new Tag('span', {
|
|
128
|
-
class: 'rf-xref rf-xref--unresolved',
|
|
129
|
-
'data-entity-id': id,
|
|
130
|
-
}, [label || id]);
|
|
255
|
+
return resolvePlaceholder(id, label, typeHint, rc).tag;
|
|
131
256
|
}
|
|
132
|
-
|
|
133
|
-
const newChildren = (tag.children ?? []).map((c) => resolveXrefs(c, pageUrl, registry, ctx));
|
|
257
|
+
const newChildren = (tag.children ?? []).map((c) => walk(c, rc));
|
|
134
258
|
if (newChildren.every((c, i) => c === tag.children[i]))
|
|
135
259
|
return tag;
|
|
136
260
|
return { ...tag, children: newChildren };
|
package/dist/xref-resolve.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"xref-resolve.js","sourceRoot":"","sources":["../src/xref-resolve.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"xref-resolve.js","sourceRoot":"","sources":["../src/xref-resolve.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@refrakt-md/runes",
|
|
3
3
|
"description": "Semantic Markdoc runes for refrakt.md",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.16.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"repository": {
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
"build": "tsc"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@refrakt-md/types": "0.
|
|
33
|
-
"@refrakt-md/transform": "0.
|
|
32
|
+
"@refrakt-md/types": "0.16.0",
|
|
33
|
+
"@refrakt-md/transform": "0.16.0",
|
|
34
34
|
"@markdoc/markdoc": "0.4.0",
|
|
35
35
|
"reflect-metadata": "^0.2.0",
|
|
36
36
|
"fast-xml-parser": "4.5.1",
|