Prism syntax highlighting for the Raven programming language.
npm install @unkindnesses/prism-raven
Importing the package registers the grammar as raven, with rv as an alias:
import Prism from "prismjs"
import "@unkindnesses/prism-raven"
Prism.highlight(source, Prism.languages.raven, "raven")Markup uses the usual language- class, so Prism.highlightAll() picks up:
<pre><code class="language-raven">fn square(x) { x * x }</code></pre>To register on a different Prism instance — a bundler's copy, or
prism-react-renderer — pass it in:
import { raven, register } from "@unkindnesses/prism-raven"
register(otherPrism) // or use `raven` as a grammar directlyRaven has no reserved words. fn, if, while, for and bundle are
macros, and a b c is just the macro a applied to b and c, so the grammar
recognises the shape of a syntax block rather than a fixed word list — a
user-defined macro highlights like a built-in one.
The rule that does the work is where a macro head may appear. A macro's arguments are parsed with syntax disabled, so in
for x = xs { show x }for and show are heads but xs is not, even though it sits after an
operator and before a block — brackets reset to statement level, which is why
show gets to be a head again. At statement level the same shape is a macro:
ref = wasm call(support.identity): refAlongside that: line comments, strings in every delimiter form (including
\"a "b" c"\ and triple quotes), template strings like r`\d` and
tag"/Foo", @doc-style annotations, numbers, operators and calls. Inline
JavaScript is handed to Prism's JavaScript grammar, with \name interpolation
marked:
p = ```js
return new Promise(resolve => setTimeout(resolve, \n * 1000))
```Token types are the standard Prism ones. Macro heads are keyword macro,
string tags are string-tag function, and annotations are annotation symbol,
so a theme can single them out without extra CSS.
Two deliberate departures, both because the alternative reads worse:
- A word after a closing brace is highlighted as a keyword, which covers the
elseof anifand thefromof an import. The parser treats both as arguments of the preceding macro. - A bare
break,continueorreturnwith no argument is highlighted, even though with nothing to apply to it is an ordinary identifier.
npm test
If a built Raven checkout is linked at ./raven, the suite additionally
tokenizes every .rv file in it and checks the macro heads against the ones the
real parser found, at the same offsets, along with the two departures above:
ln -s ../raven raven && (cd raven && npm run build)
Without it those cases skip and the rest of the suite runs unchanged.