Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 87 additions & 0 deletions dev/quick-describe-test.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Quick Describe Test - YASGUI</title>
<style>
html,
body {
height: 100%;
margin: 0;
padding: 0;
font-family: Arial, sans-serif;
}
#yasgui {
height: calc(100% - 160px);
}
.info-banner {
background-color: #e3f2fd;
border: 1px solid #1976d2;
border-radius: 4px;
padding: 16px;
margin: 16px;
font-size: 14px;
}
.info-banner h3 {
margin-top: 0;
color: #1976d2;
}
.info-banner code {
background-color: #f5f5f5;
padding: 2px 6px;
border-radius: 3px;
font-family: monospace;
}
.info-banner ul {
margin: 8px 0;
padding-left: 20px;
}
</style>
</head>
<body>
<div class="info-banner">
<h3>🧪 Quick Describe Feature Test</h3>
<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>
<p><strong>Test URIs:</strong></p>
<ul>
<li><code>bnd:_subnetwork_bane_KVGB</code> - URI with underscore prefix</li>
<li><code>bno:BaneSubnetwork</code> - URI with camel case</li>
</ul>
<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>
</div>
<div id="yasgui"></div>

<script type="module">
import Yasgui from '../packages/yasgui/src/index.ts';

const testQuery = `PREFIX bnd: <https://data.banenor.no/data/>
PREFIX rtm: <http://ontology.railml.org/railtopomodel#>
PREFIX time: <http://www.w3.org/2006/time#>
PREFIX dcterms: <http://purl.org/dc/terms/>
PREFIX gsp: <http://www.opengis.net/ont/geosparql#>
PREFIX bno: <https://data.banenor.no/ontology/>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>

SELECT *
WHERE {
bnd:_subnetwork_bane_KVGB a bno:BaneSubnetwork .
}
LIMIT 1000`;

const yasgui = new Yasgui(document.getElementById("yasgui"), {
requestConfig: {
endpoint: "https://data.banenor.no/sparql",
},
copyEndpointOnNewTab: true,
});

// Set the test query
yasgui.getTab().yasqe.setValue(testQuery);

// Add a console log to track when quick describe is triggered
console.log("Test page loaded. Hold Ctrl and click on URIs to test quick describe feature.");
</script>
</body>
</html>
31 changes: 28 additions & 3 deletions packages/yasgui/src/Tab.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1445,14 +1445,38 @@ export class Tab extends EventEmitter {

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

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

// Handle prefixed names that may be split into multiple tokens by the tokenizer
// The tokenizer splits "prefix:localname" into two tokens:
// - PNAME_LN_PREFIX (e.g., "bnd:") with type "string-2"
// - PNAME_LN_LOCAL (e.g., "_subnetwork_bane_KVGB") with type "string"
// We need to combine them to get the full prefixed name
if (token.type === "string-2" && tokenString.endsWith(":")) {
// This is a prefix token, get the next token for the local name
const nextToken = this.yasqe.getTokenAt({ line: pos.line, ch: token.end + 1 });
if (nextToken && nextToken.type === "string" && nextToken.start === token.end) {
tokenString = `${tokenString}${nextToken.string.trim()}`;
}
} else if (token.type === "string" && token.start > 0) {
// This might be a local name token, check if previous token is a prefix
const prevToken = this.yasqe.getTokenAt({ line: pos.line, ch: token.start - 1 });
if (
prevToken &&
prevToken.type === "string-2" &&
prevToken.string.trim().endsWith(":") &&
prevToken.end === token.start
) {
tokenString = `${prevToken.string.trim()}${tokenString}`;
}
}

// Check if it's a URI - either in angle brackets or a prefixed name
const isFullUri = tokenString.startsWith("<") && tokenString.endsWith(">");
const isPrefixedName = /^[\w-]+:[\w-]+/.test(tokenString);
const isPrefixedName = /^[\w-]+:/.test(tokenString);

if (!isFullUri && !isPrefixedName) return;

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