guidex
v0.2.6
Published
Guidex — render plainchant scores from a compact GuidoScript notation, as a web app and an embeddable runtime
Downloads
831
Maintainers
Readme
Guidex
Guidex — plainchant in code, after Guido of Arezzo, whose font renders the scores.
Render plainchant scores from a compact script notation, set in Book
Antiqua with a true red (#d40000) as its hallmark. Works with a
bundler (vanilla JS, React, Next.js) or as a plain script tag on any
site.
Install for bundler users
npm i guidexThe package ships a typed ESM build with an exports map:
guidex— imperative API, no side effects:renderScore(el, source, options?),renderAll(root?),init(options?),dispose(el), plus the sung-text helpers (chantText(script), theGuidoScriptparser,unescape) and the style sets (STYLE_SETS,DEFAULT_STYLE_SET,StyleSetName).guidex/react— theGuidexScoreclient component ('use client'marked, works in Next.js App Router Server Components). React ≥ 18 is an optional peer dependency; only React users install it.guidex/embed— the same API plus auto-render: importing it scans the document for.guido-scriptelements immediately, like the script tag. Don't use this in frameworks that re-render the DOM.
The stylesheet ships as guidex/guidex.css; the fonts load from its
relative ./fonts/… URLs, so bundlers must see the package's
dist/lib/fonts/ (Vite, Next.js, and webpack all handle this).
Vanilla JS
import { renderScore } from 'guidex'
import 'guidex/guidex.css'
renderScore(document.querySelector('#score'), '(M)A(0) di(0q)e(qQ0)bus(1) an(3)ti(1e)quis(qQ0-:)', { textPx: 22 })Sung text
The parser is exported too, so you can pull the sung text out of a script — for a lyrics column, a search index, and the like:
import { chantText, GuidoScript } from 'guidex'
chantText('(M)A(0) di(0q)e(qQ0)bus(1) an(3)ti(1e)quis(qQ0-:)') // 'A diebus antiquis'
new GuidoScript('(M)A(0) di(0q)e(qQ0)bus(1) an(3)ti(1e)quis(qQ0-:)').words
// [{ text: 'A', syllables: [{ text: 'A', notes: '0' }] },
// { text: 'diebus', syllables: [{ text: 'di', notes: '0q' }, { text: 'e', notes: 'qQ0' }, { text: 'bus', notes: '1' }] },
// { text: 'antiquis', syllables: [{ text: 'an', notes: '3' }, { text: 'ti', notes: '1e' }, { text: 'quis', notes: 'qQ0-:' }] }]React / Next.js
import { GuidexScore } from 'guidex/react'
import 'guidex/guidex.css'
<GuidexScore script="(M)A(0) di(0q)e(qQ0)bus(1) an(3)ti(1e)quis(qQ0-:)" textPx={22} />GuidexScore renders into a div on mount, re-renders on resize, and
updates when the script prop changes. Props mirror the options below:
maxWidth, style, bold, textPx, transpose, debug, className.
Options
| Option | Values | Default |
| ----------- | ------------------------------- | -------------- |
| maxWidth | pixels, or auto (fits the element, re-rendered on resize) | auto |
| style | BNS, Vesperale | BNS |
| bold | boolean | false |
| textPx | base text size in px (notes render at 2×) | 18 |
| transpose | pitch-row shift (see transposeBy) | 0 |
| debug | boolean (measurement titles on spans) | false |
Embedding with a script tag (no bundler)
Host the dist-embed/ folder (also attached to every GitHub Release)
on any static server or CDN and drop it into a site's <head>:
<link rel="stylesheet" href="https://your-host/path/guidex-embed.min.css">
<script src="https://your-host/path/guidex-embed.min.js"></script>Any element classed guido-script (or guidex-script) renders its text
content as a score, in place:
<div class="guido-script"
data-max-width="600"
data-style="Vesperale">(MX)Ki(3)rály(3)ként(5) tró(7i)nol(7-:)</div>Parameters ride data attributes on the div (same values as the options
table above, kebab-cased: data-max-width, data-text-px, …);
site-wide defaults can be set with
GuidexEmbed.init({ maxWidth: 'auto', style: 'BNS', … }). Element
attributes win over init options. New elements added after page load
render automatically; already-rendered elements re-render when
GuidexEmbed.renderAll() is called.
A failed render (unknown style, unloadable font) leaves an error note in the target instead of throwing.
The script notation
The source alternates a leading clef group with syllables, each followed by its notes:
(MX)Ki(3)rály(3)ként(5) tró(7i)nol(7-:) *() az(7i) Úr(5-/) mind(5)ö(4t)rök(3)ké.(3-.)- The first parenthesized group is the starting clef with note modifiers.
- Every syllable of text precedes the parenthesized group of notes it is sung to.
- Whitespace in the source marks word boundaries between syllables.
- The Guidohu dash (
-) is pure whitespace; spaces are forbidden inside a notes line. - Marker characters (
,.:?'"+!%/=()ÖÜÓ;=SCORE_MARKERS) carry no pitch; at the edges of a note group they count as whitespace, so a junction after a marker-ending group needs only 2 dashes instead of 3. - Style decorations on syllable text:
__…__renders in the Liturgy font, bold;_…_renders small caps (BNS) or italic (Vesperale);*…*marks an initial (bold, red in BNS). A syllable that is exactly**renders the mediant star glyph.
In the rendered score, notes are set in the Guidohu font at twice the surrounding text size. Notes are measured with a hidden canvas after webfonts load, and each syllable is aligned against the measured ink of its notes — left-aligned when the notes are wider, centered otherwise. When a finite max width is given, the score breaks into multiple line pairs, repeating the clef on every line and hanging a hyphen at line ends that split a word.
State
Parsing and rendering both work end to end: a script is parsed into
syllables and words, and the renderer produces multi-line scores with
correct spacing, junctions, and dash placement. See DEVELOPMENT.md in
the repository for the project layout, development commands, and the
detailed rendering model.
