Make pictures of Scratch blocks from text.
scratchblocks-plus is a fork of scratchblocks, and adds the following features:
- matrix support
- try it out!
- issue: scratchblocks#509
- PR: scratchblocks#573
- block highlight
- dropdown menu translate
- try it out!
- issue: scratchblocks#324
- PR: scratchblocks#556
- server-side rendering
- issue: scratchblocks#402
- PR: scratchblocks#589
- basic TypeScript support
- and more!
scratchblocks-plus follows the core text syntax and common browser APIs of
scratchblocks 3.x, including parse, render, renderMatching, and
loadLanguages. Most browser integrations can migrate by changing the package
or script name.
It is not a complete package-level drop-in replacement:
- scratchblocks-plus is ESM-first and does not support CommonJS
require(); - the root package entry is browser-only because it uses
windowand the DOM; - Node.js rendering and syntax-only parsing use dedicated package subpaths;
- internal modules and exact generated SVG markup are not compatibility guarantees.
The classic script build still creates window.scratchblocks, so existing
browser code that uses the documented scratchblocks API generally remains
compatible.
scratchblocks-plus is used to write Scratch scripts:
It's MIT licensed, so you can use it in your projects.
For the full guide to the syntax, see the wiki.
Install the package from npm:
npm install scratchblocks-plusThe root entry is intended for browser applications and bundlers. It default-exports the initialized scratchblocks API and automatically adds the required styles to the page:
import scratchblocks from "scratchblocks-plus"
scratchblocks.renderMatching("pre.blocks", {
style: "scratch3",
languages: ["en"],
// catHats: true,
// fontFamily: '"Noto Sans SC", sans-serif',
})Set catHats to true to render all Scratch 3 hat and custom block
definition hats as cat hats. It defaults to false and has no visual effect
with the scratch2 style.
Use fontFamily to override the font family for all block labels, input
values, and comments in that render. The value uses CSS font-family syntax;
load the font before rendering, for example by waiting for
document.fonts.ready. If the option is omitted or empty, each style keeps its
default fonts.
The ESM entry does not create window.scratchblocks. Import the default export
wherever it is needed.
To load every bundled locale in an ESM application:
import scratchblocks from "scratchblocks-plus"
import locales from "scratchblocks-plus/locales/all"
scratchblocks.loadLanguages(locales)The all-locales entry is large. Import individual locale JSON files when your bundler supports JSON modules and you only need a few languages.
Use the dedicated SSR entry instead of the browser root. Install a DOM and canvas implementation alongside scratchblocks-plus:
npm install scratchblocks-plus @xmldom/xmldom @napi-rs/canvasimport { renderToSVGString } from "scratchblocks-plus/node-ssr"
const svg = renderToSVGString("move (10) steps", {
style: "scratch3",
fontFamily: '"Noto Sans SC", sans-serif',
})For custom fonts in Node.js, register the font with the selected Canvas implementation before rendering so SVG layout measurement uses the same font.
Parsing and document analysis do not require a DOM or canvas implementation:
import { parse } from "scratchblocks-plus/syntax"
const document = parse("move (10) steps")
const block = document.scripts[0].blocks[0]
console.log(block.info.id) // "MOTION_MOVESTEPS"TypeScript model names are available as type-only exports from the browser entry:
import scratchblocks, {
type Block,
type Document,
} from "scratchblocks-plus"
const document: Document = scratchblocks.parse("move (10) steps")
const block: Block = document.scripts[0].blocks[0]block.info.id identifies the registered Scratch block definition. For an
application-defined identity, assign id directly to a Script, Block,
Input, or Comment before creating a view or rendering:
const document = scratchblocks.parse("move (10) steps")
const block = document.scripts[0].blocks[0]
block.id = "workspace-block-42"
const view = scratchblocks.newView(document, { style: "scratch3" })
view.render()
const element = view.getElementById("workspace-block-42")The ID is rendered as data-sb-id; it is not part of scratchblocks text and is
not included by stringify(). Duplicate IDs are allowed, and lookup returns the
first matching element in document order.
To hide a block without removing its layout space, set its optional hidden
property before creating the view:
const doc = scratchblocks.parse(`repeat (10)
move (10) steps
end`)
doc.getBlockByPath("1.1").hidden = true
const view = scratchblocks.newView(doc, { style: "scratch3" })
view.render()When hidden is true, the block, its nested blocks, and attached visual
annotations are invisible, while their original dimensions and positions are
preserved. Hidden blocks remain available through element lookup APIs. The
property is application-only: scratchblocks text cannot set it, and
stringify() does not include it. Create a new view after changing hidden on
an existing document.
Use the scratchblocks-plus-react package to render scratchblocks in React.
ESM is recommended for new projects. The classic IIFE build remains available
for pages that use a global window.scratchblocks object.
You'll need to include a copy of the scratchblocks-plus JS file on your webpage. There are a few ways of getting one:
- Download it from the https://github.com/LuYifei2011/scratchblocks-plus/releases page
- You could clone this repository and build it yourself using Node 16.14.0+ (
npm run build).
<script src="scratchblocks-plus.min.js"></script>The convention is to write scratchblocks inside pre tags with the class blocks:
<pre class="blocks">
when flag clicked
move (10) steps
</pre>You then need to call scratchblocks.renderMatching after the page has loaded.
Make sure this appears at the end of the page (just before the closing </body> tag):
<script>
scratchblocks.renderMatching("pre.blocks", {
style: "scratch3", // Optional, defaults to "scratch2".
languages: ["en", "de"], // Optional, defaults to ["en"].
scale: 1, // Optional, defaults to 1.
})
</script>The renderMatching() function takes a CSS-style selector for the elements that contain scratchblocks code: we use pre.blocks to target pre tags with the class blocks.
The style option controls how the blocks appear. Supported built-in styles are scratch2, scratch3, scratch3-high-contrast, and scratch3-outline.
You might also want to use blocks "inline", inside a paragraph:
I'm rather fond of the <code class="b">stamp</code> block in Scratch.To allow this, make a second call to renderMatching using the inline argument.
<script>
scratchblocks.renderMatching("pre.blocks", ...)
scratchblocks.renderMatching("code.b", {
inline: true,
// Repeat `style` and `languages` options here.
})
</script>This time we use code.b to target code blocks with the class b.
If you want to use languages other than English, you'll need to include a second JS file that contains translations. The releases page includes two options; you can pick one:
translations.jsincludes a limited set of languages, as seen on the Scratch Forumstranslations-all.jsincludes every language that Scratch supports.
The translations files are hundreds of kilobytes in size, so to keep your page bundle size down you might like to build your own file with just the languages you need.
For example, a translations file that just loads the German language (ISO code de) would look something like this:
scratchblocks.loadLanguages({
de: <contents of locales/de.json>
})With ESM, import the locale JSON file when your bundler supports JSON modules:
import de from "scratchblocks-plus/locales/de.json"
scratchblocks.loadLanguages({
de,
})To update the translations:
npm upgrade scratch-l10n
npm run localesEach language requires some additional words which aren't in Scratch itself (mainly the words used for the flag and arrow images).
I'd be happy to accept pull requests for those! You'll need to rebuild the translations with npm run locales after editing the aliases.
This should set you up and start a http-server for development:
npm install
npm startThen open http://localhost:8000/ :-)
For more details, see CONTRIBUTING.md.
Many, many thanks to the contributors!
- Maintained by LuYifei2011
- This is a fork of scratchblocks, so all the credit there still applies here.
- Original scratchblocks library by tjvr
- Original scratchblocks library maintained by tjvr and apple502j
- Icons derived from Scratch Blocks (Apache License 2.0)
- Scratch 2 SVG proof-of-concept, shapes & filters by as-com
- Anna helped with a formula, and pointed out that tjvr can't read graphs
- JSO designed the syntax and wrote the original Block Plugin
- Help with translation code from joooni
- Block translations from the scratch-l10n repository
- Ported to node by arve0