Skip to content

v0.2.0

Choose a tag to compare

@yousifamanuel yousifamanuel released this 24 Sep 23:36
· 158 commits to main since this release

Morphic Blocks 0.2.0 makes setup much shorter: one mount() call sets up every view, definitions can be imported straight from JSON, and mode CSS can be passed as a simple map. It also fixes several rendering and lifecycle bugs.

This release contains breaking changes. See the migration guide below.

Highlights

  • One call sets up everything. mount() now takes a container for every view (toolboxContainer, codespaceContainer, previewContainer, codeEditorContainer, toolbarContainers) plus editorTheme and previewTheme. It returns a promise that settles once the text editors have loaded; the workspace is ready immediately.
  • Plain JSON definitions. new MorphicBlocks(definitions, behaviors) accepts a JSON import directly, without as unknown as MorphicBlocksFormat. Values are checked when you call mount().
  • shape for statement blocks. One word describes how a block connects: statement, start, end or standalone.
  • default template. A block can write one template under default for every code element it does not list itself.
  • Block sizes follow your mode's font. When a mode's CSS gives block text another font, size or weight, blocks are measured with it, so text no longer spills out of its block.

Migration guide

mount() sets up all views and returns a promise

// 0.1
const workspace = engine.mount({ workspaceContainer, workspaceMode: "pseudo" });
engine.mountToolbox(toolbox);
await engine.mountCodespace();
await engine.mountPreview(preview);

// 0.2
await engine.mount({
  workspaceContainer,
  toolboxContainer: toolbox,
  codespaceContainer,
  previewContainer: preview,
  preset: "conceptual",
});
  • mount() no longer returns the Blockly workspace. Use engine.getWorkspace() in the rare case you need Blockly directly.
  • workspaceMode, toolboxMode, codespaceMode and previewMode are no longer mount options. Views are set by a preset; without presets the first mode in your definitions is used. setModes() still switches views freely at runtime.
  • blocklyOptions is removed. Use blockly, which does the same.
  • Selection sync is now on by default when more than one view is set up. Pass selectionSync: false to turn it off.
  • The separate mount* methods still work for setting up a view later.

modeStyles is a map

// 0.1
modeStyles: [{ mode: "py", href: "/modes/py.css" }, { mode: "js", cssText: jsCss }]

// 0.2
modeStyles: { py: "/modes/py.css", js: jsCss }

Each value is a link or the CSS itself. MorphicModeStyle is no longer exported. modesFolder now also accepts CSS text, for example from Vite's ?raw or ?inline.

Behaviors get plain and quoted field values

proxy.fields now holds each value exactly as the field has it. Use the new proxy.quoted where you need a quoted, escaped string literal:

// 0.2
text_value: (proxy) => proxy.quoted.TEXT ?? '""',

runJavaScript() is quiet by default

It collects every printed line in output as { level, text } and no longer echoes to the browser console. Pass logToConsole: true to restore the echo. A console you pass in still receives every line.

New

  • runJavaScript() returns output with the level of each printed line.
  • getActivePreset() returns the preset currently applied.
  • The workspace keeps itself sized to its container. No more manual Blockly.svgResize calls.
  • Validation reports unknown element types, slot kinds and field types, and invalid shape values.

Fixes

  • Composed operands keep their grouping: 2 * (3 + 4) no longer generates 2 * 3 + 4. Brackets are added only where a template combines several values, so print(%1) stays clean.
  • Empty slot defaults are applied only on the first render, so a deleted value no longer comes back after a mode switch.
  • Several editors on one page keep their own blocks.
  • Framework stylesheets no longer pile up when editors are created again.
  • An editor disposed while still loading no longer appears anyway. This affected React's double mount in development.
  • dispose() also disposes toolbars, so undo and redo keep updating after mounting again.
  • Without presets, the first mode in your definitions is used, not the first stylesheet found.

Other

  • Blockly is a regular dependency and is installed for you. The CodeMirror packages stay optional peer dependencies.
  • The package now has a test suite (Vitest with jsdom), and releases run it before publishing.

Full changelog: v0.1.0...v0.2.0