Skip to content

Commit 9ae589d

Browse files
panes: loose-match bare @type local names (e.g. 'Tracker' → wf:Tracker)
Hub's tracker docs (and many SolidOS-style docs) emit JSON-LD with the @type compacted via the doc's @context: '@type': 'Tracker' rather than the fully-expanded IRI. Strict equality against the pane's full forClass IRI ('http://www.w3.org/2005/01/wf/flow#Tracker') missed, so the file fell through to a raw new-tab open instead of the Pilot Tracker pane. Two-pass findPaneFor: exact-IRI first, then a loose local-name suffix match guarded to bare terms (no '/' or ':'). The guard prevents 'schema:Tracker' or 'http://other/Tracker' from getting mis-routed. Bare 'Tracker' now correctly resolves to the wf:Tracker pane in the registry.
1 parent 2b6cea7 commit 9ae589d

1 file changed

Lines changed: 22 additions & 2 deletions

File tree

src/panes.js

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,32 @@ function ensureIndex() {
3535
export async function getPanesIndex() { return ensureIndex(); }
3636

3737
/** Given an array of rdf:type IRIs found on a subject, return the
38-
* first registry pane whose forClass matches, or null. */
38+
* first registry pane whose forClass matches, or null.
39+
*
40+
* Two-pass match:
41+
* 1. Exact full-IRI equality (handles docs that emit unprefixed IRIs)
42+
* 2. Local-name suffix on bare terms (handles compacted @type like
43+
* "Tracker" pointing at wf:Tracker via the doc's @context — we
44+
* can't expand the @context cheaply, so a local-name match is
45+
* the practical fallback)
46+
*/
3947
export async function findPaneFor(types) {
4048
if (!Array.isArray(types) || !types.length) return null;
4149
const index = await ensureIndex();
50+
51+
for (const t of types) {
52+
if (typeof t === "string" && index.has(t)) return index.get(t);
53+
}
4254
for (const t of types) {
43-
if (index.has(t)) return index.get(t);
55+
if (typeof t !== "string") continue;
56+
// Loose-match only on bare local names (no `/` or `:`), so a
57+
// fully-qualified IRI that didn't match in pass 1 doesn't get
58+
// mis-resolved here.
59+
if (t.includes("/") || t.includes(":")) continue;
60+
for (const [cls, entry] of index) {
61+
const clsLocal = cls.split(/[#/]/).pop();
62+
if (clsLocal === t) return entry;
63+
}
4464
}
4565
return null;
4666
}

0 commit comments

Comments
 (0)