Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
da3d4a7
feat!: migrate from CodeMirror 5 to Monaco editor (VSCode) with a lan…
vemonet Jun 9, 2026
c86c8cb
feat: upgrade monaco-languageclient version, add popular public endpo…
vemonet Jun 9, 2026
ff3922d
doc: add docs website with VitePress, main page is a bare Yasgui with…
vemonet Jun 9, 2026
0eee2f5
feat!: Drop UMD support, now only builds Yasgui for ESM-only (which i…
vemonet Jun 9, 2026
7468b05
test: skip most tests, now deprecated
vemonet Jun 9, 2026
ed379ff
feat: enable import the main JS and CSS from `@zazuko/yasgui` and `@z…
vemonet Jun 9, 2026
5cc438d
fix: improve demo, fix setting input background, set qlue-ls wasm log…
vemonet Jun 9, 2026
c8e8242
feat: update CodeMirror used by the YASR component to display raw res…
vemonet Jun 9, 2026
5d0c53f
doc: add docs page about Yasr plugins, fix close tab button color
vemonet Jun 10, 2026
7f93650
chore: improve dev setup
vemonet Jun 10, 2026
6241fbb
doc: update yasr plugins `helpReference` links (previous one were dead)
vemonet Jun 10, 2026
e614fb2
refactor: move from using monaco editor in extended mode, to use it i…
vemonet Jun 10, 2026
9d57ef2
test: update some tests to work with the new monaco editor, make the …
vemonet Jun 10, 2026
9b60002
refactor: replace default SPARQL endpoint dbpedia by https://sparql.d…
vemonet Jun 10, 2026
9379da9
doc: improve `fallbackPrefixMap` for demo vitepress deployment
vemonet Jun 10, 2026
383d0cd
fix: fix small visual issues in settings panel
vemonet Jun 10, 2026
3956efb
doc: improve types of yasqe fields, add auto generated API reference …
vemonet Jun 10, 2026
071921c
chore: add prefixes to list of demo default prefixes, delete unused p…
vemonet Jun 10, 2026
24be665
fix: remove deadlinks in docs, fix small screen banner on index of vi…
vemonet Jun 10, 2026
bf6ea68
doc: in docs editor change the language server settings used bu qlue-ls
vemonet Jun 11, 2026
3047460
refactor: use `DeepPartial` for partial configs in yasgui/yasqe/yasr
vemonet Jun 11, 2026
f83dbba
refactor: create `languageServers/` folder in `yasqe` for helper type…
vemonet Jun 11, 2026
927bf3f
doc: move theme switch button to the bottom of the page just on top o…
vemonet Jun 11, 2026
c96758c
fix: derive SPARQL query type from query text instead of hardcoded SE…
vemonet Jun 11, 2026
7a3cb00
feat: add yasqe-codemirror package
vemonet Jun 12, 2026
7708e76
feat: improve display of error messages from the LSP
vemonet Jun 13, 2026
e23f07a
feat: add code blocks folding to monaco and codemirror, improve intro…
vemonet Jun 13, 2026
01898d0
feat: support multiple language servers with runtime switching and pe…
vemonet Jun 15, 2026
0973f78
test: fix tests
vemonet Jun 15, 2026
acf18e0
fix: fix codemirror language server picker
vemonet Jun 16, 2026
512cb39
fix: fix qlueLs import
vemonet Jun 19, 2026
0d82cbb
fi: improve init of language servers when multiple
vemonet Jun 19, 2026
4ffb229
feat: add swls and traqula language servers
vemonet Jun 19, 2026
d58ae80
fix: fix qlue-ls diagnostics
vemonet Jun 21, 2026
fe0ea55
feat: add generic settings panel generated from settings JSON schema,…
vemonet Jun 21, 2026
35dd32a
fix: store language server settings to localStorage, fix qlueLs import
vemonet Jun 21, 2026
5b436b2
fix: persistent language servers settings in yasgui
vemonet Jun 21, 2026
9b4dcac
feat: unified interface for language servers in monaco and codemirror
vemonet Jun 22, 2026
d964c9e
feat: add default syntax highlight to Yasqe CodeMirror when no semant…
vemonet Jun 22, 2026
957c0f6
docs: update docs website to be served from sparql.studio
vemonet Jun 22, 2026
bda8e25
refactor: rename packages from @zazuko/yasgui|yasqe|yasr to @rdfjs/sp…
vemonet Jun 22, 2026
173cb33
feat: improve editor
vemonet Jun 23, 2026
22156f5
refactor: rename `IYasqe` to `IEditor`, improve docs, rename dev file…
vemonet Jun 23, 2026
cd487d1
test: fix tests, improve readme
vemonet Jun 23, 2026
243b472
refactor: rename `SparqlStudio.Yasr.registerPlugin` to `SparqlStudio.…
vemonet Jun 23, 2026
f8da33d
doc: improve build from source docs
vemonet Jun 23, 2026
8789d0e
doc: improve docs, add details on API
vemonet Jun 23, 2026
7b7864b
Finish to update yasgui/yasqe/yasr names to sparqlStudio/sparqlEditor…
vemonet Jul 30, 2026
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
2 changes: 1 addition & 1 deletion .changeset/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"$schema": "https://unpkg.com/@changesets/config@3.0.0/schema.json",
"changelog": "@changesets/cli/changelog",
"commit": false,
"fixed": [["@zazuko/*"]],
"fixed": [["@rdfjs/*"]],
"linked": [],
"access": "public",
"baseBranch": "main",
Expand Down
42 changes: 42 additions & 0 deletions .changeset/migrate-to-monaco.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
---
"@rdfjs/sparql-studio": major
"@rdfjs/sparql-utils": major
"@rdfjs/sparql-editor-monaco": major
"@rdfjs/sparql-editor-codemirror": major
"@rdfjs/sparql-results": major
---

- Migrate from CodeMirror 5 to Monaco/CodeMirror 6 editors with language servers
- Users can now choose between 2 editors: one based on Monaco, the other based on CodeMirror 6
- The editor now extends `EventEmitter` instead of `CodeMirror`, with a shared `IEditor` interface both editors implement
- Enable use of language servers for diagnostics, syntax highlighting, autocompletion, code actions, hover and formatting
- Delete the editor's built-in autocomplete and grammar code (now handled by the language server)
- CodeMirror falls back to static SPARQL syntax highlighting when the language server provides no semantic tokens
- Update some of the puppeteer tests
- Language servers
- Unified, editor-agnostic language server interface for both Monaco and CodeMirror: you pass a `Worker` (instance or factory) and the editor connects the client for you, waiting for the worker's `ready` signal
- Support multiple language servers via a `languageServers` array, with runtime switching (right-click menu in Monaco, dropdown in CodeMirror) and a per-endpoint preference persisted to localStorage
- Generic settings panel generated from a JSON schema, with a callback to apply settings to the active server
- Improved display of error messages coming from the language server
- Ship qlue-ls plumbing (settings, types, backend/endpoint registration, prefix discovery, completion-query templates) in utils under the `qlueLs` namespace, so consumers can wire it up easily
- The demo implements 3 language servers: **qlue-ls** (WASM, endpoint-powered completions), **swls** (WASM, semantic web language server) and **Traqula** (JS SPARQL 1.2 parser, diagnostics only)
- App and editor improvements
- Enable light/dark theme
- Add a "Share query URL" entry to the Monaco right-click menu (under Execute query) bound to Cmd/Ctrl+S
- Update the CodeMirror used by the results viewer to display the raw response JSON from v5 to v6
- Update the default SPARQL endpoint from DBpedia to https://sparql.dblp.org/sparql (faster for completion queries)
- Improve the partial config implementation (`DeepPartial`)
- Enable importing the main JS and CSS from `@rdfjs/sparql-studio` and `@rdfjs/sparql-studio/style.css`
- Docs
- Add a documentation website built with VitePress (served from https://sparql.studio), with an auto-generated API reference (TypeDoc)
- The home page is the full app with the 3 language servers, a second page demos the CodeMirror editor
- Drop UMD support: the libraries are now ESM-only (Monaco loads its workers/wasm via `import.meta.url`, which UMD cannot express). ESM imports work in plain HTML `<script type="module">` in every browsers.
- Rename the packages and exported classes:
- `@zazuko/yasgui` -> `@rdfjs/sparql-studio` (class `Yasgui` -> `SparqlStudio`)
- `@zazuko/yasqe` -> `@rdfjs/sparql-editor-monaco` and a new `@rdfjs/sparql-editor-codemirror` (class `Yasqe` -> `SparqlEditor`)
- `@zazuko/yasr` -> `@rdfjs/sparql-results` (class `Yasr` -> `SparqlResults`)
- `@zazuko/yasgui-utils` -> `@rdfjs/sparql-utils`
- The `SparqlStudio` config keys `yasqe`/`yasr` are now `editor`/`results`
- Rename `window.yasgui` & cie to `window.sparqlStudio`
- Rename CSS classes (`.yasgui* -> `.sparqlStudio*`)
- add `postcss-nested` to flatten nested CSS
8 changes: 4 additions & 4 deletions .changeset/migrate-to-vite.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
---
"@zazuko/yasgui": patch
"@zazuko/yasgui-utils": patch
"@zazuko/yasqe": patch
"@zazuko/yasr": patch
"@rdfjs/sparql-studio": patch
"@rdfjs/sparql-utils": patch
"@rdfjs/sparql-editor-monaco": patch
"@rdfjs/sparql-results": patch
---

- Migrate from `webpack` to `vite` for the bundler and dev server
Expand Down
55 changes: 52 additions & 3 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
name: Run tests

on: push
on:
push:
workflow_dispatch:

jobs:
tests:
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v5
uses: actions/checkout@v6.0.3

- name: Set up NodeJS
uses: actions/setup-node@v6
uses: actions/setup-node@v6.4.0
with:
node-version: "lts/*"
cache: npm
Expand All @@ -27,3 +29,50 @@ jobs:

- name: Run tests
run: npm run test

docs:
name: Deploy to GitHub Pages
needs: tests
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
permissions:
contents: read
pages: write
id-token: write
# Allow only one concurrent deployment, skip runs queued between the in-progress and latest.
concurrency:
group: pages
cancel-in-progress: false
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Checkout
uses: actions/checkout@v6.0.3

- name: Set up NodeJS
uses: actions/setup-node@v6.4.0
with:
node-version: "lts/*"
cache: npm

- name: Install dependencies
run: npm ci

- name: Build libraries
run: npm run build:lib

- name: Build docs
run: npm run docs:build

- name: Setup Pages
uses: actions/configure-pages@v6.0.0

- name: Upload artifact
uses: actions/upload-pages-artifact@v5.0.0
with:
path: docs/.vitepress/dist

- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v5.0.0
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
node_modules
build
yarn.lock
cache/
dist/
# Generated by TypeDoc
docs/api/
4 changes: 4 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ Using Changesets allows for precise control over releases and supports versionin
- [Changesets GitHub repository](https://github.com/changesets/changesets)
- [Common Questions about Changesets](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)

### Upgrade dependencies

Checkout [`monaco-languageclient` version compatiblity table](https://github.com/TypeFox/monaco-languageclient/blob/main/docs/versions-and-history.md) to upgrade the packages version related to the monaco editor and language client.

### Code of Conduct

We are committed to fostering a welcoming and inclusive environment.
Expand Down
46 changes: 26 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,50 +1,56 @@
# YASGUI
# SPARQL Studio

SPARQL Studio is a SPARQL query editor and results viewer for the web. It is a fork of [Yasgui](https://github.com/zazuko/Yasgui) and stays compatible with all existing Yasr result-view plugins.

Useful links:

- User documentation: https://docs.triply.cc/yasgui/
- Developer documentation: https://docs.triply.cc/yasgui-api/
- Documentation Github repository (feel free to add a PR for improvements): https://github.com/TriplyDB/Documentation
- Live demo: [sparql.studio](https://sparql.studio)
- Documentation: [sparql.studio/docs/introduction](https://sparql.studio/docs/introduction)
- Source code: [github.com/rdfjs/Yasgui](https://github.com/rdfjs/Yasgui)

## Packages

| Package | Description |
| ---------------------------------- | ------------------------------------------------------ |
| `@rdfjs/sparql-studio` | Full app: tabbed editor + results (formerly Yasgui) |
| `@rdfjs/sparql-editor-monaco` | SPARQL query editor based on Monaco (formerly Yasqe) |
| `@rdfjs/sparql-editor-codemirror` | SPARQL query editor based on CodeMirror 6 |
| `@rdfjs/sparql-results` | SPARQL results viewer (formerly Yasr) |
| `@rdfjs/sparql-utils` | Shared utilities |

## Installation

Below are instructions on how to include Yasgui in your project.
If you only want to install Yasr or Yasqe, replace yasgui in the commands below.
Below is how to include the full app in your project. To install only the editor or the
results viewer, swap `@rdfjs/sparql-studio` for the relevant package above.

### npm

```sh
npm i @zazuko/yasgui
npm i @rdfjs/sparql-studio
```

### Yarn

```sh
yarn add @zazuko/yasgui
yarn add @rdfjs/sparql-studio
```

## Local development

#### Installing dependencies
### Installing dependencies

Run `npm install`.

#### Running Yasgui locally

To develop locally, run `npm run dev`
### Running locally

#### Compiling Yasgui
To develop locally, run `npm run dev`.

Run `npm run build`. It'll store the transpiled js/css files in the `build` directory.
### Compiling

Update prefixes from http://prefix.cc:

```sh
npm run util:prefixes
```
Run `npm run build`. It stores the transpiled js/css files in the `build` directory.

## License

This is a fork from Zazuko from software written by Triply.
SPARQL Studio is a fork of [Yasgui](https://github.com/TriplyDB/Yasgui/) maintained by Zazuko, originally written by Triply.

This code is released under the MIT license.
73 changes: 73 additions & 0 deletions dev/codemirror.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/sparql-studio.svg" />
<link rel="stylesheet" href="./style.css" />
<title>SPARQL Studio · CodeMirror</title>
</head>
<body>
<div class="navBar">
<nav style="display: flex">
<img class="logo" src="/sparql-studio.svg" style="max-height:50px;padding:5px;margin-left: 10px" alt="SPARQL Studio Logo" />
<ul style="display: flex; list-style: none; align-self: center">
<li class="navItem"><a class="nav-link" href="/">SPARQL Studio</a></li>
<li class="navItem active"><a class="nav-link" href="codemirror">CodeMirror</a></li>
<li class="navItem"><a class="nav-link" href="editor_results">Editor & Results</a></li>
</ul>
<button class="themeToggle" id="darkModeToggle" type="button"></button>
</nav>
</div>

<div id="sparqlStudio"></div>

<script type="module">
import SparqlStudio from "@rdfjs/sparql-studio";
import SparqlEditor from "@rdfjs/sparql-editor-codemirror";
import { qlueLs } from "@rdfjs/sparql-utils";
import QlueLsWorker from "./qluels.worker?worker";
import SwlsWorker from "./swls.worker?worker";
import TraqulaWorker from "./traqula.worker?worker";
import { setupThemeToggle, DEMO_ENDPOINT } from "./utils";

const theme = setupThemeToggle((t) => window.sparqlStudio.editor?.setTheme(t));

const endpointOf = () => window.sparqlStudio?.getTab()?.getEndpoint() ?? DEMO_ENDPOINT;
const onReady = (conn) => {
qlueLs.configureSettings(conn, qlueLs.defaultSettings);
qlueLs.configureBackend(conn, endpointOf());
};
const onEndpointChange = (conn, endpoint) => qlueLs.configureBackend(conn, endpoint);

window.sparqlStudio = new SparqlStudio(document.getElementById("sparqlStudio"), {
requestConfig: { endpoint: DEMO_ENDPOINT },
editor: (parent, conf) =>
new SparqlEditor(parent, {
...conf,
theme,
languageServers: [
{
label: "Qlue-ls",
description: "SPARQL language server with endpoint-powered completions",
worker: () => new QlueLsWorker({ name: "qlue-ls" }),
onReady,
onEndpointChange,
configSchema: qlueLs.settingsSchema,
configCallback: (conn, settings) => qlueLs.configureSettings(conn, settings),
},
{
label: "swls",
description: "Semantic web language server",
worker: () => new SwlsWorker({ name: "swls" }),
},
{
label: "Traqula",
description: "JS SPARQL 1.2 parser (diagnostics only)",
worker: () => new TraqulaWorker({ name: "traqula-ls" }),
},
],
}),
});
</script>
</body>
</html>
53 changes: 53 additions & 0 deletions dev/editor_results.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/sparql-studio.svg" />
<link rel="stylesheet" href="./style.css" />
<title>SPARQL Editor & Results</title>
</head>
<body>
<div class="navBar">
<nav style="display: flex">
<img class="logo" src="/sparql-studio.svg" style="max-height:50px;padding:5px;margin-left: 10px" alt="SPARQL Studio Logo" />
<ul style="display: flex; list-style: none; align-self: center">
<li class="navItem"><a class="nav-link" href="/">SPARQL Studio</a></li>
<li class="navItem"><a class="nav-link" href="codemirror">CodeMirror</a></li>
<li class="navItem active"><a class="nav-link" href="editor_results">Editor & Results</a></li>
</ul>
<button class="themeToggle" id="darkModeToggle" type="button"></button>
</nav>
</div>
<div id="sparqlEditor"></div>
<div id="sparqlResults"></div>
<script type="module">
import SparqlEditor, { qlueLs } from "@rdfjs/sparql-editor-monaco";
import SparqlResults from "@rdfjs/sparql-results";
import QlueLsWorker from "./qluels.worker?worker";
import { setupThemeToggle, DEMO_ENDPOINT } from "./utils";

window.onpageshow = function () {
const theme = setupThemeToggle((t) => window.sparqlEditor?.setTheme(t));
window.sparqlEditor = new SparqlEditor(document.getElementById("sparqlEditor"), {
theme,
languageServers: [
{
label: "Qlue-ls",
worker: () => new QlueLsWorker({ name: "qlue-ls" }),
onReady: (client) => qlueLs.configureBackend(client, DEMO_ENDPOINT),
},
],
});
window.sparqlResults = new SparqlResults(document.getElementById("sparqlResults"), {
prefixes: function () {
return window.sparqlEditor.getPrefixesFromQuery();
},
});
window.sparqlEditor.on("queryResponse", function (sparqlEditor, response, duration) {
console.log({ response: response });
window.sparqlResults.setResponse(response, duration);
});
};
</script>
</body>
</html>
Loading
Loading