Skip to content

Commit 0fe4915

Browse files
authored
Add a browser-native LiquidJava playground (#3)
2 parents 775aa99 + 52258b1 commit 0fe4915

26 files changed

Lines changed: 2277 additions & 30 deletions

‎.github/workflows/pages.yml‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,24 @@ jobs:
2828
ruby-version: "2.6"
2929
bundler-cache: true
3030

31+
- name: Setup Node
32+
uses: actions/setup-node@v4
33+
with:
34+
node-version: "22"
35+
cache: npm
36+
37+
- name: Setup Java
38+
uses: actions/setup-java@v4
39+
with:
40+
distribution: temurin
41+
java-version: "17"
42+
43+
- name: Build playground
44+
run: |
45+
npm ci --ignore-scripts --no-audit --no-fund
46+
npm run build:playground
47+
npm run test:playground
48+
3149
- name: Setup Pages
3250
uses: actions/configure-pages@v5
3351

‎.gitignore‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,6 @@ _site/
55
.bundle/
66
vendor/
77
Gemfile.lock
8+
node_modules/
9+
.playground-build/
10+
playground/runtime/

‎README.md‎

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,32 @@ bundle exec jekyll build
3232
## Publishing
3333

3434
The site is configured as a GitHub Pages project site at [https://liquid-java.github.io/liquidjava-docs/](https://liquid-java.github.io/liquidjava-docs/).
35+
36+
## Browser playground
37+
38+
The `/playground/` page runs LiquidJava in a browser worker with CheerpJ 4.3 and the official Z3 WebAssembly package. Code is checked locally. Stop terminates the worker, including a running solver, and the next check creates a fresh runtime.
39+
40+
Build the runtime before building Jekyll:
41+
42+
```bash
43+
npm ci --ignore-scripts --no-audit --no-fund
44+
npm run build:playground
45+
npm run test:playground
46+
bundle exec jekyll build
47+
```
48+
49+
The build requires JDK 17, Python 3, Node.js, and access to Maven Central. It recompiles the published verifier 0.0.35 and annotation API 0.0.7 sources for Java 17 without changing them, packages their dependencies, and adds the docs-owned runner and Z3 loader. The standard-library classpath comes from the build JDK's `java.base.jmod`. Generated runtime files are ignored by Git and included in the Pages artifact. The normal Pages workflow builds everything automatically.
50+
51+
The browser package also adapts Spoon 10.4.2's query initialization: when CheerpJ supplies an empty cast-exception stack trace, it selects Spoon's existing exotic-JVM query mode. The pinned source is downloaded and the adaptation checked during the build. This change is limited to the docs' generated dependency; the verifier repository and published sources remain unchanged.
52+
53+
For local testing, after building the runtime:
54+
55+
```bash
56+
npm run serve:playground
57+
```
58+
59+
Open `http://127.0.0.1:8770/playground/`. This uses a static server with HTTP range support, which CheerpJ needs when loading JARs. Ordinary `jekyll serve` does not supply the required range responses.
60+
61+
`playground/isolation.js` is a service worker scoped to `/playground/`. It adds the cross-origin isolation response headers Z3 requires on static hosting, including GitHub Pages. The first visit registers it and reloads once. Other docs pages are outside its scope. CheerpJ loads from its official CDN inside the verification worker; its runtime is not copied into this repository.
62+
63+
The playground checks a single Java file using Java 8 source syntax, bundled annotations and core standard-library types from `java.base`. External dependencies and other Java modules are not available. Z3 4.16 runs behind the verifier's 4.8.17 Java API; browser integration tests must be repeated when updating either version. Unsupported native operations and unknown solver results fail explicitly instead of reporting success. This integration is kept entirely in `liquidjava-docs`.

‎_config.yml‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,11 @@ defaults:
4646
image: /assets/images/Liquid2.png
4747

4848
exclude:
49+
- node_modules
50+
- scripts
51+
- package.json
52+
- package-lock.json
53+
- .playground-build
4954
- .DS_Store
5055
- vendor
5156
- Gemfile

‎_includes/nav_footer_custom.html‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<p>
2-
Help improve this documentation by contributing on
1+
<footer class="site-footer">
2+
Help improve this documentation by contributing on
33
<a href="https://github.com/liquid-java/liquidjava-docs">GitHub</a>
4-
</p>
4+
</footer>

‎_sass/custom/custom.scss‎

Lines changed: 23 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@
2828
$sidebar-color;
2929
}
3030

31+
.site-footer {
32+
color: $body-text-color;
33+
}
34+
3135
.main-content a {
3236
color: #41586f;
3337
text-decoration-thickness: 0.08em;
@@ -43,7 +47,9 @@
4347
}
4448

4549
.main-content pre.highlight,
46-
.main-content div.highlighter-rouge {
50+
.main-content div.highlighter-rouge,
51+
.main-content #lj-editor,
52+
.main-content .lj-output {
4753
overflow-x: auto;
4854
overflow-y: hidden;
4955
scrollbar-width: thin;
@@ -259,40 +265,30 @@
259265
margin: 1.5rem 0 0;
260266
}
261267

262-
.home-button {
268+
.main-content .home-button {
263269
display: inline-flex;
264270
align-items: center;
265271
justify-content: center;
266-
min-height: 2.9rem;
267-
padding: 0.8rem 1.1rem;
268-
border-radius: 999px;
269-
border: 1px solid transparent;
270-
font-weight: 700;
271-
line-height: 1.1;
272-
text-decoration: none !important;
273-
transition: transform 120ms ease, box-shadow 120ms ease, background-color 120ms ease, border-color 120ms ease;
274-
box-shadow: 0 14px 26px rgba(51, 80, 106, 0.22);
275-
}
276-
277-
.home-button:hover,
278-
.home-button:focus {
279-
transform: translateY(-1px);
280-
}
281-
282-
.home-button:focus {
283-
outline: none;
284-
box-shadow: 0 0 0 3px rgba(65, 88, 111, 0.16);
272+
gap: 0.65rem;
273+
padding: 0.7rem 1.1rem;
274+
border-radius: 0.5rem;
275+
color: #fff;
276+
background: #334e68;
277+
font-weight: 400;
278+
line-height: 1.5;
279+
text-decoration: none;
280+
box-shadow: 0 2px 4px rgba(23, 26, 31, 0.12);
285281
}
286282

287-
.home-button.primary {
283+
.main-content .home-button:hover {
288284
color: #fff;
289-
background: linear-gradient(135deg, #63c093 0%, #4e98a8 50%, #4a80b0 100%);
290-
box-shadow: 0 18px 10px rgba(51, 80, 106, 0.22);
285+
background: #253b50;
286+
text-decoration: none;
291287
}
292288

293-
.home-button.secondary {
294-
color: #2a3642;
295-
border-color: rgba(42, 54, 66, 0.15);
289+
.main-content .home-button:focus-visible {
290+
outline: 3px solid #5f7ea1;
291+
outline-offset: 3px;
296292
}
297293

298294
.card-panel {

0 commit comments

Comments
 (0)