Skip to content

Commit 79f0de6

Browse files
committed
rewrite, add tons of output options
1 parent 4b849dd commit 79f0de6

57 files changed

Lines changed: 4751 additions & 1197 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.github/workflows/checks.yaml‎

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
name: Checks
2+
3+
on:
4+
push:
5+
branches: [main, master]
6+
pull_request:
7+
branches: [main, master]
8+
9+
permissions:
10+
contents: read
11+
12+
jobs:
13+
checks:
14+
runs-on: ubuntu-latest
15+
steps:
16+
- uses: actions/checkout@v4
17+
- uses: pnpm/action-setup@v4
18+
- uses: actions/setup-node@v4
19+
with:
20+
node-version: "22"
21+
cache: pnpm
22+
- run: pnpm install --frozen-lockfile --ignore-scripts
23+
- name: Type and formatting checks
24+
run: pnpm lint
25+
- name: Unit tests
26+
run: pnpm test
27+
- name: Build
28+
env:
29+
GH_TOKEN: ${{ github.token }}
30+
RELEASE_REPOSITORY: ${{ github.repository }}
31+
run: pnpm prepare

‎.prettierignore‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
dist
2+
dist-hosted
3+
node_modules
4+
packages
5+
public/wasm
6+
pnpm-lock.yaml
7+
THIRD_PARTY_NOTICES.md

‎README.md‎

Lines changed: 107 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# clangd in the browser
22

3-
This package turns ordinary `<codeblock>` tags into editable, runnable C++ examples. It starts with a small textarea editor, upgrades to Monaco when the main bundle is ready, and runs a WebAssembly build of clangd for code help. Multiple blocks on one page share the same runtime, worker, and clangd download.
3+
This package turns ordinary `<codeblock>` tags into editable, runnable examples. It starts with an immediate syntax-highlighted simple editor, upgrades to Monaco when the block approaches the viewport, and runs a WebAssembly build of clangd for C++ code help. Multiple blocks share one VS Code runtime, worker, clangd process, and download.
44

55
This project started as a fork of the excellent https://github.com/guyutongxue/clangd-in-browser/.
66

@@ -12,7 +12,7 @@ Copy the complete contents of `dist/` to one public directory, then include one
1212
<link rel="stylesheet" href="./codeblocks.css" />
1313
<script src="./codeblocks.js"></script>
1414

15-
<codeblock compiler="gsnapshot" args="-std=c++26 -freflection">
15+
<codeblock compiler="gsnapshot" compiler-args="-std=c++26 -freflection">
1616
#include &lt;print&gt; int main() { std::println("foo {} bar", 42); }
1717
</codeblock>
1818
```
@@ -24,25 +24,50 @@ Add as many `<codeblock>` elements as needed. Tags inserted later are upgraded a
2424
A block can also contain multiple tabbed sources:
2525

2626
```html
27-
<codeblock compiler="clang2110" args="-std=c++23" height="360px">
27+
<codeblock compiler="clang2110" compiler-args="-std=c++23" height="360px">
2828
<codeblock-tab name="first.cpp"> int main() { return 1; } </codeblock-tab>
2929
<codeblock-tab name="second.cpp"> int main() { return 2; } </codeblock-tab>
3030
</codeblock>
3131
```
3232

33-
Each tab keeps its own source. Run compiles the active tab. Use separate `<codeblock>` elements when examples need different compiler settings.
33+
Tabs are independent examples by default. Add `multi-file` to send the inactive
34+
tabs to Compiler Explorer as extra files. A hidden supporting tab implies
35+
multi-file mode. Use `build-system="cmake"` and a hidden `CMakeLists.txt` tab
36+
for a CMake request. Switching independent or grouped tabs always clears stale
37+
output.
3438

3539
Supported attributes are:
3640

37-
- `compiler`: Compiler Explorer compiler ID, defaulting to `clang2110`.
38-
- `args`: arguments sent unchanged to Compiler Explorer.
41+
- `language`: editor/simple-mode and Compiler Explorer language, defaulting to `c++`.
42+
- `compiler`: Compiler Explorer compiler ID. C++ defaults to `clang2110`; languages without an explicit default require this attribute.
43+
- `compiler-args` (JavaScript: `compiler_args`): arguments sent to the compiler. The old `args` name remains a deprecated alias.
44+
- `run-args` (JavaScript: `run_args`): arguments passed to the compiled program.
45+
- `stdin`: standard input passed to the compiled program.
46+
- `output-views`: comma-separated `execution`, `compiler`, `assembly`, or `tool:TOOL_ID` views. Requesting `execution` controls whether the compiled program runs; assembly is returned by the same compile request.
47+
- `output-position`: `below`, `side`, or `custom`. Custom suppresses built-in output rendering.
48+
- `live`: enable live output with a 500 ms debounce, or set the debounce as milliseconds.
49+
- `readonly`: prevent reader edits. It has no reader-facing toggle.
50+
- `inline`: transparent, automatically sized, read-only presentation with Monaco/clangd support. The shorter `<cb>code</cb>` tag is equivalent to an inline, read-only `<codeblock>`.
51+
- `simple`: keep the simple editor/highlighter and never initialize Monaco or clangd. It works on both `<codeblock>` and `<cb>`.
52+
- `src`: load source from a same-origin or CORS-enabled URL.
53+
- `range="START[:COLUMN]-END[:COLUMN]"`: show only a source window while compiling the complete file. Columns follow C++ source-range semantics: the start is included and the end is excluded. The equivalent `start-line`, `end-line`, `start-column`, and `end-column` attributes are also available. Ranged views are read-only.
54+
- `highlight-lines="2-4,7"`: persistently highlight source lines. Line numbers refer to the complete source file and are translated into a visible `range` automatically.
55+
- `fit`, `fit="height"`, or `fit="width"`: fit the editor to its content in both dimensions or one dimension.
56+
- `multi-file`: compile the active tab with the remaining tabs as extra files. `build-system="cmake"` uses the CMake API and treats `CMakeLists.txt` as the project source.
57+
- `editable-options`: show the reader-editable compiler and execution settings, or name a comma-separated subset. Result views are selected by the output tabs; the legacy `output` field is only shown when named explicitly.
58+
- `hide-toolbar`, `hide-tabs`, `hide-run`, `hide-compiler-explorer`, `hide-info`, and `hide-output`: author-only UI visibility controls. Corresponding `show-*` attributes override configured defaults.
59+
- `compiler-explorer-link`: replace the generated Compiler Explorer destination with an author-provided URL. JavaScript consumers use `compilerExplorerLinkUrl`.
60+
- `info-name`, `info-description`, and `source-url`: customize the information popover.
61+
- `editor-options` and `styles`: JSON objects matching the JavaScript options.
62+
- `no-render-output`: send results only to the JavaScript callback/API.
3963
- `ce-url`: Compiler Explorer base URL, defaulting to `https://godbolt.org/`.
4064
- `ce-language`: language stored in the Compiler Explorer client state, defaulting to `c++`.
4165
- `ce-compiler`: legacy fallback for the compiler when `compiler` is absent.
42-
- `ce-options`: legacy fallback for arguments when `args` is absent.
66+
- `ce-options`: legacy fallback for arguments when `compiler-args` is absent.
67+
- `ce-libs`, `ce-special-outputs`, `ce-tools`, and `ce-overrides`: JSON values forwarded to Compiler Explorer.
4368
- `ce-filters`: JSON object overriding Compiler Explorer output filters, such as `'{"intel":false,"demangle":true}'`.
4469
- `theme`: `auto`, `light`, or `dark`.
45-
- `debug`: show the basic/full editor and light/dark switches. These are hidden by default.
70+
- `debug`: log editor and clangd lifecycle details to the console.
4671
- `width`: any valid CSS width for the complete block.
4772
- `height`: any valid CSS height for the editor area, such as `280px`, `40vh`, or `clamp(240px, 50vh, 600px)`.
4873
- `min-height`: any valid CSS minimum height for the editor area.
@@ -74,24 +99,28 @@ Supported attributes are:
7499
```
75100

76101
Call `CodeBlocks.configure(options)` before a block is upgraded to set defaults
77-
for later blocks. The available options are `theme`, `showDebugControls`,
78-
`compiler`, `args`, `compilerExplorer`, `editorOptions`, `styles`,
102+
for later blocks. Configuration includes `theme`, `showDebugControls`,
103+
`language`, `compiler`, `compiler_args`, `run_args`, `stdin`, `readOnly`,
104+
`inline`, `simple`, `fit`, `outputViews`, `outputPosition`, `live`, `ui`,
105+
`editableOptions`, `info`, `compilerExplorer`, `compilerExplorerLinkUrl`, `editorOptions`, `styles`,
79106
`renderOutput`, `onResult`, and `onStatus`.
80107

81108
The Compiler Explorer link contains the active source, filename, compiler,
82109
arguments, execution view, and output filters in its `/clientstate/` URL. No
83110
upload or short-link request is needed. Additional client-state fields can be
84111
configured globally or when creating an individual block. The nested
85112
`compiler` and `options` values are fallbacks; the code box's top-level
86-
`compiler` and `args` always win so Run and the link cannot diverge:
113+
`compiler` and `compiler_args` always win so the action and link cannot diverge:
87114

88115
```js
89116
CodeBlocks.configure({
117+
language: "c++",
118+
compiler: "gsnapshot",
119+
compiler_args: "-std=c++26 -O2",
120+
run_args: "--verbose",
121+
stdin: "example input\n",
90122
compilerExplorer: {
91123
baseUrl: "https://godbolt.org/",
92-
language: "c++",
93-
compiler: "gsnapshot",
94-
options: "-std=c++26 -O2",
95124
filters: {
96125
intel: false,
97126
demangle: true,
@@ -105,26 +134,57 @@ CodeBlocks.configure({
105134
});
106135
```
107136

137+
The module also exports `listCompilerExplorerLanguages`,
138+
`listCompilerExplorerCompilers`, `listCompilerExplorerLibraries`, and
139+
`listCompilerExplorerTools`. Compiler fields use the language-specific endpoint
140+
to offer current compiler IDs while still accepting custom/private-service IDs.
141+
`compilerExplorer` and `editorOptions` are passed through as the consumer-facing
142+
escape hatches for Compiler Explorer filters/tools/libraries and Monaco options.
143+
108144
The legacy `compilerExplorerUrl` JavaScript option remains available as an alias for `compilerExplorer.baseUrl`.
109145

110146
`CodeBlocks.get(element)` returns the upgraded block instance. It exposes
111147
`getValue`, `setValue`, `getTabs`, `selectTab`, `getCompilerExplorerUrl`,
112-
`focus`, `compile`, `run`, `setTheme`, `dispose`, `onDidChange`, `editorReady`,
113-
`monacoReady`, and `clangdReady`. `getValue` and `setValue` act on the active
148+
`focus`, `compile`, `run`, `setOutputView`, `setEditorMode`, `setTheme`, `dispose`, `onDidChange`, `editorReady`,
149+
`monacoReady`, `clangdReady`, and `sourceReady`. `getValue` and `setValue` act on the active
114150
tab. `monacoReady` resolves to the underlying Monaco standalone editor for
115151
integrations that need the native editor API.
116152

153+
`CodeBlocks.setEditorMode("full" | "simple", root?)` and
154+
`CodeBlocks.setTheme("auto" | "light" | "dark", root?)` update every existing
155+
block under a page or container. The Pages examples use these for global
156+
controls instead of placing editor/theme switches inside every block.
157+
117158
`compile()` is the presentation-independent path: it returns the structured
118159
Compiler Explorer JSON result, including execution output and assembly. Set
119160
`renderOutput: false` to suppress the built-in drawer, and use `onResult` to
120161
observe results produced by either `compile()` or the Run button. The exported
121162
`compileWithCompilerExplorer(request)` function is available for consumers that
122163
do not need a code-block UI at all.
123164

124-
Run and the generated Compiler Explorer link resolve one shared compiler,
125-
language, and argument set. The link enables execution and includes both the
126-
assembly compiler and an execution/output view using that same compiler ID and
127-
options.
165+
The requested output determines the work: an `execution` view runs the program,
166+
while assembly, diagnostics, and tools use compilation only. Side output is
167+
height-constrained to the editor and scrolls independently. Compiler diagnostics
168+
are hidden when a successful compile produced none, and execution output reports
169+
the process exit code. `outputPosition: "custom"` or `renderOutput: false`
170+
leaves presentation to `onResult` or the returned `CompilationResult`.
171+
172+
The first source line may be a runline such as
173+
`// clang2110 -std=c++23 -O2`. The compiler and remaining text become defaults
174+
unless attributes or JavaScript options override them; the runline is removed
175+
from the editor, compile request, and Compiler Explorer link.
176+
177+
Source-bearing custom elements in formatted HTML should have a
178+
`<!-- prettier-ignore -->` comment immediately before the `<codeblock>` node.
179+
The bundled examples do this so Prettier formats the surrounding page without
180+
rewriting code text nodes. Runtime extraction also removes the common host-HTML
181+
indent while retaining indentation inside the source itself.
182+
183+
Blocks outside an 800px viewport margin keep the simple editor until
184+
they approach the viewport. Set `deferMonaco: false` or add `eager` when an
185+
off-screen integration must initialize immediately. Simultaneously visible
186+
blocks need separate Monaco renderers, but they still share the expensive VS
187+
Code services and clangd process.
128188

129189
Styling uses CSS custom properties. Common properties include:
130190

@@ -151,11 +211,10 @@ Debug mode also writes lifecycle messages to the browser console, including Mona
151211
></script>
152212
```
153213

154-
The lower-level ES module entries remain available as `editor.js`, `fallback.js`,
155-
and `ansi.js`. The fallback editor is language-agnostic internally; its current
156-
C++ adapter uses [Microlighter](https://github.com/davatron5000/microlighter),
157-
which applies an on-demand TextMate grammar through the CSS Custom Highlight
158-
API while keeping the code DOM as plain text.
214+
The lower-level ES module entries remain available as `editor.js`, `simple.js`,
215+
and `ansi.js`. The simple-editor implementation and its language adapter live
216+
together under `editor/simple/`. [Microlighter](https://github.com/davatron5000/microlighter)
217+
loads the selected TextMate grammar on demand and keeps the code DOM as plain text.
159218

160219
## Cross-origin isolation
161220

@@ -189,30 +248,45 @@ do not rebuild LLVM or clangd.
189248

190249
```bash
191250
pnpm install
192-
pnpm build
193-
pnpm demo:origins
251+
pnpm dev
194252
```
195253

196-
Open `http://localhost:4173/`. The example includes `debug`, so both visual editor and theme switches are shown.
254+
`pnpm dev` performs an initial production-equivalent build, watches source and
255+
types, and serves the same site published to Pages at `http://localhost:4173/`.
256+
The complete examples are at `http://localhost:4173/examples/`.
197257

198-
Run the browser suite in another terminal:
258+
The default checks are fully headless and require no browser:
199259

200260
```bash
201-
pnpm exec playwright install chromium
202-
pnpm test:browser
261+
pnpm test
262+
pnpm lint
263+
pnpm build
203264
```
204265

266+
CI runs unit tests, TypeScript, Prettier verification, and the production build
267+
for pull requests and pushes to `main` or `master`.
268+
205269
The heavyweight LLVM/clangd build recipe and its required source patch live in
206270
`scripts/clangd/`. Front-end work normally uses released artifacts. To build
207271
clangd itself, run `scripts/clangd/build.sh`; to install a local artifact set,
208272
run `scripts/clangd/install-artifacts.sh PATH`.
209273

210274
The TypeScript source is split by responsibility: `codeblocks/` owns UI
211275
orchestration, `compiler-explorer/` owns the headless API and link state,
212-
`editor/` contains fallback and Monaco adapters, `languages/` contains small
213-
syntax adapters, and `clangd/` owns the WebAssembly worker transport. Files at
276+
`editor/` contains simple, language-highlighting, and Monaco adapters, and
277+
`clangd/` owns the WebAssembly worker transport. Files at
214278
the top of `src/` are stable public build entrypoints.
215279

280+
Language support is deliberately layered. The simple highlighter accepts a
281+
language ID and loads its grammar, Monaco accepts the corresponding model
282+
language plus consumer options, and Compiler Explorer discovery/compilation is
283+
language-driven. C and C++ have maintained compiler defaults; other languages
284+
(including Python) require an explicit compiler or runline until a stable
285+
project default is chosen. New tools can be requested through `ce-tools` or the
286+
headless API without coupling them to clangd. Additional WASM language services
287+
can later be added beside `clangd/` without changing the code-block/Compiler
288+
Explorer model.
289+
216290
## npm packages
217291

218292
The release workflow publishes two scoped packages from the same source and version:

‎package.json‎

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
},
2929
"scripts": {
3030
"clean": "node scripts/build-package.mjs --clean",
31-
"dev": "pnpm build",
31+
"dev": "node scripts/dev.mjs",
3232
"watch": "tsc -w",
3333
"build": "node scripts/build-package.mjs",
3434
"build:hosted": "node scripts/build-package.mjs --outdir=dist-hosted --without-wasm",
@@ -37,16 +37,22 @@
3737
"package:npm:hosted": "node scripts/prepare-npm-package.mjs dist-hosted packages/codeblocks-hosted @cppsocial/codeblocks-hosted",
3838
"pack:runtime": "pnpm build && bash scripts/package-runtime.sh",
3939
"release:wasm": "bash scripts/clangd/release-wasm.sh",
40-
"demo:origins": "node scripts/serve-test.mjs",
41-
"test:browser": "playwright test"
40+
"test": "vitest run",
41+
"test:watch": "vitest",
42+
"format": "prettier --write .",
43+
"format:check": "prettier --check .",
44+
"lint": "tsc --noEmit && prettier --check .",
45+
"check": "pnpm lint && pnpm test && pnpm build"
4246
},
4347
"devDependencies": {
44-
"@playwright/test": "^1.55.0",
4548
"@types/emscripten": "^1.39.10",
4649
"@types/node": "~20.12.12",
4750
"@types/vscode": "~1.89.0",
51+
"happy-dom": "^15.11.7",
52+
"prettier": "^3.6.2",
4853
"typescript": "^5.4.5",
49-
"vite": "^5.4.8"
54+
"vite": "^5.4.8",
55+
"vitest": "^2.1.9"
5056
},
5157
"dependencies": {
5258
"@codingame/esbuild-import-meta-url-plugin": "~1.0.2",

‎playwright.config.ts‎

Lines changed: 0 additions & 15 deletions
This file was deleted.

0 commit comments

Comments
 (0)