Releases: gkurt/tegaki
Release list
tegaki@0.20.0
Add TegakiEngine.toSVG() and a canvas accessor (2c578e9)
The engine can now serialize its current text to a standalone SVG string via toSVG({ animated, loop }) — either self-drawing (SMIL mask reveal, variable stroke width) or looping (CSS keyframes, constant width), with the viewBox cropped to the ink. The backing <canvas> is also exposed through a canvas getter so export tooling can read pixels without reaching through the DOM.
Pull request & contributors
Add a tegaki CLI and a textToSvg() export (2c578e9)
npx tegaki renders text to an animated handwriting SVG straight from the command line. The same output is available programmatically through the new textToSvg() export, along with its TextToSvgMode and TextToSvgOptions types.
Pull request & contributors
tegaki@0.19.0
Minor Changes
- 68ee58f: Support Korean (Hangul) writing system and add Nanum Pen Script as a built-in font. The bundle ships ~650 most-frequent precomposed Hangul syllables (KS X 1001 common band ∪ top-N Korean-Wikipedia-frequency, capped by the Google Fonts subsetting ceiling) plus the 40 modern compatibility jamo (19 consonants ㄱ–ㅎ + 21 vowels ㅏ–ㅣ) and the Latin baseline. Hangul is precomposed in Unicode, so no shaper is required.
Patch Changes
-
29e111e: Fix Next.js App Router / Turbopack compatibility. Two build/packaging issues prevented
tegakifrom being used in a Next.js (App Router) app:- The bundler dropped the
'use client'directive from the React adapter's output chunk, so importingTegakiRendererinto a Server Component failed with "You're importing a module that depends onuseStateinto a React Server Component". The directive is now preserved in the built output. - The font subpath exports (
tegaki/fonts/*) resolved thenodecondition to the raw TypeScript source, which usesimport ... with { type: 'url' }import attributes that Turbopack/webpack can't process. Thenodecondition now points to the pre-built.mjsbundle (which loads the font vianew URL('./font.ttf', import.meta.url)), so it works in any Node-based bundler.
- The bundler dropped the
tegaki@0.18.0
Minor Changes
- b6e883b: Update Harfbuzz to v1.1.0
- d358cbd: Add
staggertiming mode where each glyph starts a fixed advance (seconds or"N%"of the previous glyph's effective duration) after the previous one, with an optional static per-glyph duration that scales strokes to fit. Exposed in the website previewer via the newst/sa/sdURL keys.
Patch Changes
- 150296e: Fix the Astro adapter so passing
font={bundle}hydrates without an explicitbundleprop and lookups by human-friendly font name resolve correctly. Animations now also re-hydrate after Astro View Transitions navigations. - 150296e: Make the Vue adapter's
effectsprop generic so custom effect configs are correctly type-inferred. Also drop a redundant Nuxt config type augmentation.
tegaki@0.17.1
Patch Changes
- affe5a5: Add shorthand for setting time property to a percentage for controlled progress mode.
tegaki@0.17.0
tegaki@0.16.0
Minor Changes
- 39e075e: Added support for font features and ligatures, RTL languages like Arabic and Hebrew, and text shaping with Harfbuzz. Three new built-in font bundles ship for non-Latin scripts:
tegaki/fonts/suez-one(Hebrew),tegaki/fonts/amiri(Arabic), andtegaki/fonts/klee-one(Japanese — kana, JP punctuation, and Kyōiku grade 1–2 kanji).
tegaki@0.15.0
Minor Changes
-
ecba479: Split
gradientintostrokeGradient+globalGradient, and add render-stage hooks for layout-spanning effects. Closes #26.Breaking
The
gradienteffect is renamed tostrokeGradientwith unchanged behavior (each stroke independently maps its progress to the color stops;colors: 'rainbow'still works). Rename the key in youreffectsprop:// before effects={{ gradient: { colors: ['#f00', '#00f'] } }} // after effects={{ strokeGradient: { colors: ['#f00', '#00f'] } }}
New —
globalGradientA canvas-space linear gradient that spans the full text bounding box — the leftmost pixel of the first glyph is
colors[0]and the rightmost pixel of the last glyph iscolors[N], regardless of stroke boundaries. Matches CSSbackground-clip: textsemantics.effects={{ globalGradient: { colors: ['#f00', '#00f'], angle: 0, // 0 = left→right (default); 90 = top→bottom; positive = clockwise }, }}
strokeGradientandglobalGradientcan be enabled independently. If both are on,strokeGradientwins per segment (its per-stroke color overridesglobalGradient's canvas-wide paint); this combination is unusual but predictable.New — effect render-stage hooks
Effects can now declare optional
beforeRender(stage, config)/afterRender(stage, config)hooks on theirEffectDefinitionmetadata. The stage context exposes the 2D context, theTextLayout, a pre-computedLayoutBBox, base color, and seed. Hooks run once around the glyph loop (before in forward order, after in reverse), so effects spanning the whole layout — likeglobalGradient— have a natural place to set up canvas state. Built-in per-stroke effects (glow,wobble,pressureWidth,taper,strokeGradient) declare no hooks and are unaffected.New public exports from
tegaki/core:EffectDefinition,RenderStageContext,LayoutBBox,getEffectDefinition,hasRenderHooks,computeLayoutBbox, plus the previously-privatefindEffect/findEffects.
tegaki@0.14.0
Minor Changes
- 79a0e6a: Add Nuxt module and usage example. Fixes #35.
- 9a0d74a: Add
quality.smoothingoption that interpolates stroke points with a centripetal Catmull-Rom spline, hiding the faceted corners visible at large render sizes where the baked polyline resolution shows through. Enabling it forces subdivision on (defaultsegmentSize=2CSS px) and rebuilds the subdivision cache; the original points stay on the curve, so animation timing and wobble phase are unchanged. Default isfalse(existing bundles render identically). Also exposed on the web component as thesmoothingattribute.
Patch Changes
tegaki@0.13.0
Minor Changes
- 8fd875a: Add
clipTextquality option that clips handwriting strokes to the filled text shape using canvas composite operations. Acceptstruefor clipping with normal stroke widths, or a number to scale stroke widths (e.g.2for 2x wider strokes that fill more of the glyph interior).
Patch Changes
-
2a46c09: fix compatibility with old Safari versions, and a bug with text layout when text is wrapped. Fixes #29
-
cdb2993: Fix timing around whitespace characters. Spaces and line breaks no longer consume
unknownDurationon top ofwordGap/lineGap— the gap alone now represents the full pause.\r\nand\rare normalized to\n, and all Unicode whitespace (NBSP, tab, ideographic space, etc.) is treated as a word gap.Fixes #28
tegaki@0.12.0
Minor Changes
-
be16624: Add bundle format versioning. Generated bundles now include a
versionfield (currently0) so the engine can detect incompatible bundles. The engine checks the version when a bundle is registered or resolved and logs a console warning (once per bundle) if the version is missing or unsupported.New exports:
BUNDLE_VERSION,COMPATIBLE_BUNDLE_VERSIONS. New optionalTegakiBundlefield:version. Existing bundles without a version field trigger the warning but continue to work. -
9776ca3: Cache stroke subdivision across glyph instances. Subdivision now depends
only on (stroke points, fontSize, segmentSize) and is reused by every
occurrence of the same glyph in the rendered text. Wobble, progress
truncation, pressure, taper, and gradient are applied at draw time on
top of the shared geometry, and effect config changes no longer
invalidate the cache. Glow draws the full truncated polyline in a single
stroke() call, removing the previous per-sub-segment shadowBlur cost.Wobble is now sampled per sub-vertex (fractional original-point index
keeps phase continuous), giving smoother curves than the previous
lerp-between-wobbled-raw-vertices. -
1ce1324: Add subset font bundling with full-font fallback. Bundles generated from a character subset now ship two font files: a subsetted TTF for the generated glyphs and the full TTF as a CSS fallback. The subset font is registered under a scoped family name (
<family> Tegaki <hash>) to avoid colliding with user-loaded fonts, while the full font uses the original family name. The renderer composes both infont-familyso the browser automatically falls back to the full font for non-generated characters.New
TegakiBundlefields:fullFamily,fullFontUrl. Existing bundles without these fields continue to work unchanged.
Patch Changes
- 73a6b7e: Introduces TegakiQuality ({ pixelRatio, segmentSize }) on the engine
options, replacing the top-level segmentSize. pixelRatio multiplies
devicePixelRatio when sizing the canvas backing store and root
transform, letting the browser downsample to the displayed size for
higher-quality antialiasing at a quadratic cost in pixels filled.
segmentSize retains its prior meaning under the new namespace. - d9b7c85: feat: add stroke and glyph easing functions
- 7aaf5d2: add rtl direction support
- 23757ca: Breaking:
quality.segmentSizeis now measured in CSS pixels instead of
font units. Subdivision count now scales with rendered size, so small
glyphs are no longer over-subdivided. A 100px stroke with segmentSize=1
yields ~100 sub-segments; the same stroke at 10px yields ~10.