Skip to content

v1.11.0

Choose a tag to compare

@moiku moiku released this 26 Oct 07:48
· 137 commits to main since this release

Added

  • m-keyboard (series music 音楽, purpose music; not in the free pack for now): a piano keyboard for school music lessons. Child JSON {"range": "C4-C6", "names": "solfa" | "abc" | "iroha" | "none", "cumulative": bool, "dur": s, "steps": [{"keys": ["C4", "E4", "G4"], "label", "t": [s per key], "tone", "dur"}]}. range covers 1–3 octaves (12–36 semitones) and starts and ends on white keys; the part draws its own SVG keyboard: white keys as rectangles, black keys 0.58 wide and 0.62 long, on top, centred as on a real keyboard (the C–E group split into fifths and the F–B group into sevenths: C♯/D♯ and F♯/A♯ lean outwards, G♯ is centred). White-key names under the keyboard (ドレミファソラシ, CDEFGAB or ハニホヘトイロ); black-key names (ド♯ / C♯ / 嬰ハ, レ♭ / D♭ / 変ニ) only on lit keys, above the keyboard (a second row when two would touch). Each step lights its keys in --emph (or the step's tone) with a filled dot; a lit black key keeps its dark rim around the coloured inside; cumulative: true keeps earlier steps' keys lit, faded, with a ring instead of the dot (never colour alone). Per-key t staggers a scale or arpeggio, equal t is a chord. events(k) (spec §8.4 "Component sounds"): one note per key, pitch the key name, vel 0.7, dur from dur (step, then top level) or else to the next later t (0.8 s for the last); duration(k) reaches the end of the last note. Sound is never the only carrier: the lit keys show the same. Step labels 30 px above the keyboard. The lecture view (ctx.preview, or ctx.mode === "lecture" from older players) shows later steps' keys faint without the dot, at the theme's --preview-opacity read with getComputedStyle (spec §8.4 "Answers under preview"; 0.45 only when the variable is missing). The part has no controls. Variants light (0, the light fades in), press (the key dips 4 px and comes back), rise (the light fills the key from the bottom), all within 0.3 s and within the note. Range, key-name and t-length errors show the placeholder
  • Series music (音楽, a subject series like kokugo) in tools/lint.mjs (SERIES, SERIES_LABEL) and CONTRIBUTING; purpose music (「音楽(音の高さ・和音・リズム)」 / "Music (pitch, chords, rhythm)", tile: "none" like text-structure, icon key music) in purposes.json and docs/conventions(.ja).md §4. tools/lint.mjs now also fails when a series has no label
  • tools/test-keyboard.mjs (in tools/test-all.mjs): m-keyboard's key geometry without a browser (black-key centres 0.9, 2.1, 3+6/7, 5, 3+22/7 in white-key widths, width 0.58, over the line between their two white keys, the same offsets in every octave and from a range starting on D), key names (solfa, abc, iroha with 嬰・変, none, ♯ and ♭, E♯/B♯/F♭/C♭ refused), the events per step (a chord at one t, a scale with increasing t, pitches, dur to the next t or 0.8 s, step dur and top-level dur, the step length), the key state per step and time (current, cumulative, and the lecture preview: later steps faint, the current step's unlit keys and keys lit now not marked) and the range errors (one key, not key names, black ends, under 1 or over 3 octaves, backwards)
  • tools/test-keyboard-preview.mjs (in tools/test-all.mjs): m-keyboard's lecture preview in a browser: later steps' keys faint without the dot at the theme's --preview-opacity (0.45 when missing; 0.3 when set), also with ctx.mode === "lecture", keys lit now unchanged, nothing without preview
  • tools/test-shape.mjs: m-keyboard's wrong-shape case (notes instead of keys)
  • m-timeline: project-plan (Gantt) features, as an extension of the timeline (standards decision, owner-approved; not a new part). Node after: ["id", …] draws a finish-to-start arrow (--muted, 3 px, right angles) from the end of each predecessor to the start of the dependent item, in the step where the dependent item appears, drawn while it appears; vertical runs are placed so as not to cross other bands or their names where that is possible; a dependent that starts on its predecessor's end day is entered from its edge near the start. With any after, each item of a lane gets its own row (author order). Node progress (0–100) fills the band from its start in a stronger tone, with the % after the name when it fits (24 px). Attribute today="2026-11-02" draws a vertical --accent2 line with 今日 / Today (with periods only). Attribute unit="day" | "week" | "month" chooses the axis ticks: labels at the finest interval whose 24 px labels do not overlap, short unlabelled ticks between, weekends shaded lightly in day mode; without unit the ticks are as before. A lesson that uses none of these renders as before (tools/test-seed0.mjs). The today line is drawn beneath the bars and their names, so it never strikes through bar text. Demo slide 「アプリ開発の工程表(架空)」. Pack-visible bytes (tools/pack-bytes.mjs) +278 for m-timeline (README one bullet, the unit / today prop docs, after? progress? in the shape summary; details in an llm: omit block)
  • tools/pack-bytes.mjs: the pack-visible bytes of each component (README outside llm: omit without lines about demo.html, examples/, tools/ or the motion-components skill; frontmatter name, summary, steps; each prop's type, default and doc; the shape summary), at a git ref or the working tree, with --base <ref> for the difference to report in release notes
  • tools/test-timeline-gantt.mjs (in tools/test-all.mjs): arrows start at the predecessor's end and end at the dependent's start with right angles and without crossing bands, the progress fill is progress % of the band, the today line sits at the date's position, and day / week / month tick labels do not overlap and stay at 24 px (the demo's plan and four made-up cases, including orient="v")
  • m-kakijun (series kokugo 国語, purpose process; not in the free pack for now): stroke order (書き順) of kana. text="あさ" (ひらがな・カタカナ, 濁音・半濁音, small kana, ー; 166 characters), one step per character with its strokes drawn one by one within the step (about 0.6 s a stroke, scaled by its inked length; per="stroke": one step per stroke; cues at each stroke start). The shapes are derived from strokesvg (Klee One), SIL OFL 1.1: data/kana/strokes.ofl.json, embedded verbatim (its _license first) in index.js as the only thing between /* BEGIN OFL-1.1 data … */ and /* END OFL-1.1 data */; the part's licence is MIT AND OFL-1.1 (README license:, manifest components.kakijun.license), with OFL.txt, LICENSE-strokesvg.txt and strokes-CHANGES.md in the part's folder and a NOTICE entry (Studio inlines only a part's index.js, so a separate data file cannot ship yet). Each stroke is drawn as strokesvg does (data/kana/proto.html): a round brush along the centreline, clipped by the stroke's own outline, advanced by dash offset, no fleck behind the start; finished strokes in full, nothing of a later stroke early. grid="cross" | "none" (box with dashed 十字 guides), ghost (unwritten strokes faint), nums (circled stroke numbers at each start, 24 px, placed off each other, off the ink and without crossing leaders), ends="on" (とめ・はね・はらい at each end, 24 px, with a dotted leader when moved away), writing="tate" (top to bottom, columns right to left, boxes of a column touching; small kana in the upper-right quarter, lower-left in horizontal writing; a small kana's numbers and ending labels stay inside its own square on the empty side, and other characters' labels keep out of it; a warning when they cannot fit), size. A character without data warns and is drawn plainly in the theme font. The drawing is aria-hidden; accessible name 「あさ(書き順)」 and a readable layer (characters, stroke counts, endings) in real kana. Under ctx.preview, later steps at the theme's --preview-opacity (0.45 without it). Variants draw (the default, first), pen (no fade: the order and direction are the content); the chooser is the seedless one. The part is about 210 KB (the shapes about 175 KB) Without numbers and ending labels (nums="off", no ends), the margin around the boxes shrinks from 36 to 8 px.
  • tools/kana-embed.mjs: writes components/kakijun/index.js's two data blocks (kakijun-data, MIT: count, ends, place and each stroke's inked length from data/kana/kana.json; the OFL-1.1 data between /* BEGIN OFL-1.1 data … */ and /* END OFL-1.1 data */: data/kana/strokes.ofl.json verbatim) and copies the licence files into the part's folder; --check compares them
  • tools/test-kakijun.mjs (in tools/test-all.mjs): both embedded blocks equal the data files (the OFL block verbatim, _license first) and the licence files are in place; for all 166 characters the final state covers 100 % of the outlines and nothing outside them, and in the middle of a stroke the ink stays inside the outlines drawn so far (no bleed); small kana inside their quarter in both writings, and their labels inside their own square on the empty side; the OFL-1.1 data markers and the manifest licence; steps, unknown characters, the accessible name and readable layer in real kana
  • NOTICE: lists the licence of m-kakijun's stroke shapes (SIL OFL 1.1) next to the repository's MIT licence; README.md / README.ja.md say that components/kakijun/index.js contains an OFL-1.1 data block
  • README frontmatter license: (optional SPDX expression, MIT AND <id>; checked by tools/lint.mjs, the licence text must be in the part's folder) goes into manifest.json as components.<name>.license (tools/release.mjs)

Changed

  • Visible change: preview views. In the lecture or preview view (ctx.preview, or ctx.mode === "lecture" from the current bundled player) every component except m-predict, m-hissan and m-timer now shows its later steps faintly, at the theme's --preview-opacity; 13 components do so for the first time and the others change how faint they are (details below). Talk, learn and video views are unchanged
  • m-predict, m-hissan: visible change. Under preview they no longer show anything ahead: no later step is drawn faintly, so the answer (m-predict) and the digits still to be computed (m-hissan) appear only at their own step. Lessons pinned to v1.10.0 or earlier keep the faint later steps
  • Answers under preview (egatari-spec §8.4, Egatari Player P1): visible change, in the lecture or preview view only (ctx.preview, or ctx.mode === "lecture" from the current bundled player); normal rendering is byte-identical. Every component now draws the content its later steps would add, in its final state, at the theme's --preview-opacity (read with getComputedStyle on the element; 0.45 only when the variable is missing), with controls inert for that content; the current step renders as usual. Newly previewing: m-bars (later bars that fit the current axis), m-codetree (the later codewords' pixel cells and bit brackets; not the tree paths, whose window moves each step), m-collect (the summary boxes), m-curves, m-flow, m-gendai, m-kanbun (訓点, reading-order numbers and arcs, 書き下し文), m-kobun (slashes, part-of-speech labels and 現代語訳; the text keeps its colour until its step), m-kpi, m-market, m-quad, m-seq (the final curve and later dots), m-sweep (the curves for later values). Components that already previewed read --preview-opacity instead of a fixed 0.45 (m-boxplot m-cycle m-fishbone m-hist m-map-japan m-numberline m-pie m-scatter m-tape m-timeline m-tree), --lecture-dim (m-compare m-venn) or 0.28 (m-menu, whose faint cards are no longer clickable or focusable); m-numberline and m-tape also honour ctx.preview. Exempt: m-predict (the answer), m-hissan (the digits are the computation) and m-timer (time ahead is not content) declare static preview = "none" and show nothing ahead (m-predict and m-hissan no longer show later steps faintly); tools/lint.mjs checks the flag and tools/release.mjs writes it to manifest.json as components.<name>.preview: "none". Authors hide a particular answer with data-preview="none", honoured by the player. New tools/test-preview.mjs (in tools/test-all.mjs); docs/conventions(.ja).md §1.2. Pack-visible README text: m-cycle m-fishbone m-pie m-scatter m-timeline m-tree +5 bytes each (「薄く(0.45)」 became 「テーマの薄さで」); all other README notes, including the parts whose preview is partial (m-bars m-codetree m-kobun m-seq m-sweep), are in llm: omit blocks (pack-visible bytes unchanged)
  • No lesson seed (egatari-spec 28d8801, spec §8.4; Studio no longer writes data-egatari-seed): a part's variant is its variant="<name>" attribute when it names one of its variants, otherwise the first name in static variants. tools/variant.js drops the seed steps (the component's seed attribute, the lesson's data-egatari-seed, the hashing and the seeded generator; VARIANT now has only of), re-synced into every part with variants (17, and m-kakijun, merged after it). No visible change for lessons without a seed: seed 0 always gave the first variant, checked for every part (boxplot, compare, cycle, fishbone, hissan, hist, keyboard, kpi, map-japan, numberline, pie, predict, scatter, tape, timeline, tree, venn), and no part read the seed elsewhere. A lesson that carried a non-zero seed and pins v1.10.0 or earlier keeps its look; moved to this release, its parts without variant show their first variant. seed and data-egatari-seed are ignored without a warning; an unknown variant still warns
  • tools/test-seed0.mjs becomes tools/test-default-variant.mjs (same comparison: each part's demo, built with the last release's index.js and with the current one, must be pixel-identical; the default is now "the first variant" rather than "seed 0"). tools/test-variant.mjs checks every part with variants: nothing written gives the first variant, seed and data-egatari-seed are ignored, each name selects itself, an unknown name warns
  • READMEs of m-compare m-cycle m-fishbone m-kpi m-pie m-scatter m-timeline m-tree m-venn: 「書かなければ資料のシード値(data-egatari-seed)で選ばれる」 became 「書かなければ最初の見せ方」 (pack-visible bytes −43 each). The variants slides of 13 demos say 「→ 書かなければ最初の見せ方(fade)になる」 (m-kpi: count); m-hist's demo drops 「見せ方はシード値で選ばれる」. docs/conventions(.ja).md §1 (variants without a seed; §5 item 1 withdrawn), CONTRIBUTING(.ja), docs/input-components.ja.md

Fixed

  • .gitattributes: data/** -text, so a Windows checkout keeps data/kana/ byte-identical to the copies in components/kakijun/ (tools/kana-embed.mjs --check failed there)
  • m-tree, m-venn, m-numberline: the same step could come out with tens of different edge pixels (rounded box corners, circles, arcs) depending on how often it had been drawn before, so Egatari Studio's determinism check, its call-order check and test-step-reset failed now and then on CI's Linux and Windows (#1101). The DOM was always the same: Chrome draws an SVG shape that is rasterized again without being rebuilt (because something near it changed) with a different outline from its second raster on, on a software GPU, and how often that happened depended on the frames painted between calls. render now rebuilds the part's shapes at its end (the same attribute values; the DOM and a single render's pixels are unchanged). m-tree and m-venn had this since their first release (v1.9.1 behaves the same)
  • tools/test-raster-history.mjs (in tools/test-all.mjs): for each demo step of the three parts, the pixels after the step was drawn again several times and after a click with ctx.reset equal those of a fresh draw
  • m-numberline demo: the 2本の数直線 slide overflowed the slide body by 47 px in Egatari Studio's checker (the part needed 478 px with arcs on both lines). It now shows the ×2/3 arc on the price line only, at 440 px; the part is unchanged
  • The same step left a different DOM depending on the calls before it (docs/contract.md §3; Egatari Studio's harness now compares the component DOM byte for byte between two renders of the same state). Drawing is unchanged. m-cycle: a hidden arrowhead kept the transform of an earlier render (demo slide 3, step 4); render now removes it. m-codetree: colours were written with style.fill = … (serialised as fill: var(--muted);) next to DECK.el's fill:var(--muted);, so the style text depended on the history; render now writes the style attribute in DECK.el's form. A hidden run swatch is reset to its x="0" instead of losing x, which had moved the attribute. m-seq, m-sweep: the faint curves' stroke is written the same way (same style.stroke issue). m-seq: the mark line and its label go back to x = 0 on steps without a mark instead of keeping the previous step's position. m-hist: the frequency polygon drops stroke-dashoffset with stroke-dasharray when it is not being drawn in (grow). m-map-japan (variant="draw"): areas and lines not yet shown get the same outline, fill and dash attributes as at the start of their draw, instead of keeping an earlier render's. m-menu: each render writes the card's style as one string after the author's own, and tabindex / aria-hidden in a fixed order (with style.pointerEvents and toggled attributes, the attribute text and order depended on the steps shown before)
  • tools/test-dom-order.mjs (in tools/test-all.mjs): for every part's demo, every slide and every step k at its end, in the talk and lecture views, the components' DOM (outerHTML, byte for byte, no tolerance and no pixels) after seeking straight to k on a fresh deck equals the DOM after then seeking k+1, 0 and k. It caught the seven parts above

Pack-visible bytes (Egatari Studio's AI pack), change since v1.10.0

Counted with node tools/pack-bytes.mjs --base v1.10.0 (README outside llm: omit, frontmatter, props, shape summary).

  • Free core: m-bars +0, m-flow +0, m-menu +0, m-predict +0
  • Free by subject: m-curves +0, m-kpi −43, m-quad +0
  • Kokugo: m-gendai +0, m-kanbun +0, m-kobun +0
  • Paid only: m-timeline +240, m-compare −43, m-venn −43, m-cycle −38, m-fishbone −38, m-pie −38, m-scatter −38, m-tree −38; new m-kakijun 1586, m-keyboard 839; every other part +0

sha256 dd75a0e048e9de44865ad9ae8e0ddb0ae37cd13d2fb8b037d75c9e0d87238756 egatari-components-v1.11.0.tar.gz