ScoreScript Language wiki

Embed on a website

RequirementUse
Display a finished score on any static siteExported SVG, with optional PDF/source downloads
Let visitors change source and redrawSelf-hosted browser WASM and a small component
Publish a copy of the documentationSelf-host this wiki

Neither notation approach needs a ScoreScript account or a rendering server at page-view time. Browser rendering is an engine interface, not a prebuilt drop-in Studio application or a sound player.

Static notation

With the CLI installed, render during your site build:

scorescript check piece.scorescript
scorescript render piece.scorescript -o piece.svg
scorescript pdf piece.scorescript -o piece.pdf

Put the generated files and the source in your site's music/ directory. In an HTML page:

<figure>
  <img src="./music/piece.svg" alt="Flute melody in C major" style="max-width:100%;height:auto">
  <figcaption>
    <a href="./music/piece.pdf">PDF</a>
    <a href="./music/piece.scorescript" download>ScoreScript source</a>
  </figcaption>
</figure>

The SVG contains the notation glyphs; no music-font download is needed. Use a meaningful description for the actual piece. Editing the source does not change an already uploaded SVG: rerun the build and redeploy the outputs. An ordinary Markdown image link to the SVG works when the host permits SVG.

Interactive browser rendering

This path requires authorized repository access and permission to redistribute the engine. Build the web package from the repository root with Rust/Cargo and wasm-pack installed:

bash crates/scorescript_wasm/build.sh web

Copy the generated crates/scorescript_wasm/pkg/ directory into your website as vendor/scorescript/. Copy the package, including its JavaScript, WASM, and notices; do not mix files from different builds.

site/
  index.html
  score.js
  piece.scorescript
  vendor/scorescript/
    scorescript.js
    scorescript_bg.wasm
    ...generated package files

index.html:

<!doctype html>
<html lang="en">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>ScoreScript notation</title>
<label for="source">ScoreScript source</label>
<textarea id="source" rows="12" cols="60"></textarea>
<button id="render" disabled>Render</button>
<pre id="status" role="status"></pre>
<img id="notation" alt="Notation generated from the source above" style="max-width:100%;height:auto">
<script type="module" src="./score.js"></script>
</html>

score.js:

import init, { CompiledDocument } from "./vendor/scorescript/scorescript.js";

const source = document.querySelector("#source");
const status = document.querySelector("#status");
const notation = document.querySelector("#notation");
const button = document.querySelector("#render");
let score;
let imageUrl;

function clearImage() {
  notation.removeAttribute("src");
  if (imageUrl) URL.revokeObjectURL(imageUrl);
  imageUrl = undefined;
}

function render() {
  try {
    score.update(source.value);
    const diagnostics = JSON.parse(score.diagnostics_json());
    status.textContent = diagnostics.map(d => `${d.severity}: ${d.message}`).join("\n");
    clearImage();
    if (diagnostics.some(d => d.severity === "error")) return;
    const svg = score.render_svg(JSON.stringify({ width_px: 800, foreground: "#111" }));
    imageUrl = URL.createObjectURL(new Blob([svg], { type: "image/svg+xml" }));
    notation.src = imageUrl;
    if (!diagnostics.length) status.textContent = "Rendered.";
  } catch (error) {
    clearImage();
    status.textContent = String(error);
  }
}

try {
  await init();
  const response = await fetch("./piece.scorescript");
  if (!response.ok) throw new Error(`Source download failed: ${response.status}`);
  source.value = await response.text();
  score = new CompiledDocument(source.value);
  button.addEventListener("click", render);
  button.disabled = false;
  render();
} catch (error) {
  status.textContent = String(error);
}

window.addEventListener("pagehide", event => {
  if (event.persisted) return;
  clearImage();
  score?.free();
}, { once: false });

Supply a valid piece.scorescript, for example the complete file syntax example. Serve the directory over HTTP(S), not by opening index.html as a file: URL. The initial page loads the local JS, WASM, and score; subsequent render clicks compile in the visitor's browser without uploading their text. This example does not save edits; add explicit save/download controls if needed.

Hosting requirements and boundaries

  • Serve .wasm as application/wasm and JavaScript with a JavaScript MIME type.
  • If your site sets Content Security Policy, allow its own modules and fetches, WebAssembly compilation ('wasm-unsafe-eval' in script-src where required), and blob: in img-src for this example. Do not disable the site's policy.
  • Render generated SVG as an image, as above. Do not insert user source or arbitrary uploaded SVG into the page with innerHTML.
  • For large or untrusted input, impose size/time limits and move compilation to a terminable Web Worker. The minimal example is for bounded scores, not an unrestricted public compilation service.
  • Keep the editable source; SVG and PDF are outputs. Do not edit SVG to change the musical document.

Browser requirements are documented in MDN's WebAssembly streaming reference and script-src policy reference.

render_svg produces flowing notation. render_pages_json provides paginated SVG and a report. performance_json provides note/timing data; your application must supply its own audio engine. It does not start playback by itself.

Updates and distribution

Pin a tested engine revision and replace the generated package as one unit when upgrading. Rerun representative scores and inspect their diagnostics and output. Hosting this wiki does not install the browser engine, and publishing the wiki does not publish an npm package.

The renderer embeds font assets. The current package build does not copy all font license files automatically: include the applicable notices from crates/scorescript_render/assets/*/OFL.txt with any distribution. Repository access alone does not establish permission to redistribute private source or engine artifacts. Confirm the applicable distribution terms before uploading those artifacts publicly.