Skip to content

Commit e62a646

Browse files
CopilotMathiasVDA
andauthored
fix: quick describe didn't always work for prefixed URIs (#120)
* Initial plan * Fix quick describe for tokenized prefixed URIs Co-authored-by: MathiasVDA <15101339+MathiasVDA@users.noreply.github.com> * Address code review feedback - use template literals and improved parsing Co-authored-by: MathiasVDA <15101339+MathiasVDA@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: MathiasVDA <15101339+MathiasVDA@users.noreply.github.com>
1 parent 400562a commit e62a646

2 files changed

Lines changed: 115 additions & 3 deletions

File tree

dev/quick-describe-test.html

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+
<title>Quick Describe Test - YASGUI</title>
7+
<style>
8+
html,
9+
body {
10+
height: 100%;
11+
margin: 0;
12+
padding: 0;
13+
font-family: Arial, sans-serif;
14+
}
15+
#yasgui {
16+
height: calc(100% - 160px);
17+
}
18+
.info-banner {
19+
background-color: #e3f2fd;
20+
border: 1px solid #1976d2;
21+
border-radius: 4px;
22+
padding: 16px;
23+
margin: 16px;
24+
font-size: 14px;
25+
}
26+
.info-banner h3 {
27+
margin-top: 0;
28+
color: #1976d2;
29+
}
30+
.info-banner code {
31+
background-color: #f5f5f5;
32+
padding: 2px 6px;
33+
border-radius: 3px;
34+
font-family: monospace;
35+
}
36+
.info-banner ul {
37+
margin: 8px 0;
38+
padding-left: 20px;
39+
}
40+
</style>
41+
</head>
42+
<body>
43+
<div class="info-banner">
44+
<h3>🧪 Quick Describe Feature Test</h3>
45+
<p><strong>Instructions:</strong> Hold <code>Ctrl</code> (or <code>Cmd</code> on Mac) and click on any URI in the query below to trigger a quick describe query.</p>
46+
<p><strong>Test URIs:</strong></p>
47+
<ul>
48+
<li><code>bnd:_subnetwork_bane_KVGB</code> - URI with underscore prefix</li>
49+
<li><code>bno:BaneSubnetwork</code> - URI with camel case</li>
50+
</ul>
51+
<p><strong>Expected behavior:</strong> Clicking on these URIs should execute a CONSTRUCT query to describe the resource (even though the endpoint may not exist).</p>
52+
</div>
53+
<div id="yasgui"></div>
54+
55+
<script type="module">
56+
import Yasgui from '../packages/yasgui/src/index.ts';
57+
58+
const testQuery = `PREFIX bnd: <https://data.banenor.no/data/>
59+
PREFIX rtm: <http://ontology.railml.org/railtopomodel#>
60+
PREFIX time: <http://www.w3.org/2006/time#>
61+
PREFIX dcterms: <http://purl.org/dc/terms/>
62+
PREFIX gsp: <http://www.opengis.net/ont/geosparql#>
63+
PREFIX bno: <https://data.banenor.no/ontology/>
64+
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
65+
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
66+
67+
SELECT *
68+
WHERE {
69+
bnd:_subnetwork_bane_KVGB a bno:BaneSubnetwork .
70+
}
71+
LIMIT 1000`;
72+
73+
const yasgui = new Yasgui(document.getElementById("yasgui"), {
74+
requestConfig: {
75+
endpoint: "https://data.banenor.no/sparql",
76+
},
77+
copyEndpointOnNewTab: true,
78+
});
79+
80+
// Set the test query
81+
yasgui.getTab().yasqe.setValue(testQuery);
82+
83+
// Add a console log to track when quick describe is triggered
84+
console.log("Test page loaded. Hold Ctrl and click on URIs to test quick describe feature.");
85+
</script>
86+
</body>
87+
</html>

packages/yasgui/src/Tab.ts

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1445,14 +1445,38 @@ export class Tab extends EventEmitter {
14451445

14461446
// Check if token is a URI (not a variable)
14471447
// URIs typically have token.type of 'string-2' or might be in angle brackets
1448-
const tokenString = token.string.trim();
1448+
let tokenString = token.string.trim();
14491449

14501450
// Skip if it's a variable (starts with ? or $)
14511451
if (tokenString.startsWith("?") || tokenString.startsWith("$")) return;
14521452

1453+
// Handle prefixed names that may be split into multiple tokens by the tokenizer
1454+
// The tokenizer splits "prefix:localname" into two tokens:
1455+
// - PNAME_LN_PREFIX (e.g., "bnd:") with type "string-2"
1456+
// - PNAME_LN_LOCAL (e.g., "_subnetwork_bane_KVGB") with type "string"
1457+
// We need to combine them to get the full prefixed name
1458+
if (token.type === "string-2" && tokenString.endsWith(":")) {
1459+
// This is a prefix token, get the next token for the local name
1460+
const nextToken = this.yasqe.getTokenAt({ line: pos.line, ch: token.end + 1 });
1461+
if (nextToken && nextToken.type === "string" && nextToken.start === token.end) {
1462+
tokenString = `${tokenString}${nextToken.string.trim()}`;
1463+
}
1464+
} else if (token.type === "string" && token.start > 0) {
1465+
// This might be a local name token, check if previous token is a prefix
1466+
const prevToken = this.yasqe.getTokenAt({ line: pos.line, ch: token.start - 1 });
1467+
if (
1468+
prevToken &&
1469+
prevToken.type === "string-2" &&
1470+
prevToken.string.trim().endsWith(":") &&
1471+
prevToken.end === token.start
1472+
) {
1473+
tokenString = `${prevToken.string.trim()}${tokenString}`;
1474+
}
1475+
}
1476+
14531477
// Check if it's a URI - either in angle brackets or a prefixed name
14541478
const isFullUri = tokenString.startsWith("<") && tokenString.endsWith(">");
1455-
const isPrefixedName = /^[\w-]+:[\w-]+/.test(tokenString);
1479+
const isPrefixedName = /^[\w-]+:/.test(tokenString);
14561480

14571481
if (!isFullUri && !isPrefixedName) return;
14581482

@@ -1467,7 +1491,8 @@ export class Tab extends EventEmitter {
14671491
} else if (isPrefixedName) {
14681492
// Expand prefixed name to full URI
14691493
const prefixes = this.yasqe.getPrefixesFromQuery();
1470-
const [prefix, localName] = tokenString.split(":");
1494+
const [prefix, ...localParts] = tokenString.split(":");
1495+
const localName = localParts.join(":");
14711496
const prefixUri = prefixes[prefix];
14721497
if (prefixUri) {
14731498
uri = prefixUri + localName;

0 commit comments

Comments
 (0)