Skip to content

v0.2.0

Choose a tag to compare

@github-actions github-actions released this 26 Oct 12:07
· 608 commits to main since this release
v0.2.0
bb1c8c4

Compatibility with v0.1.10

This release is not machine-compatible with v0.1.10.

  • Seven REST routes removed, none added or renamed: GET /s/:token,
    GET /api/v1/share/:token, POST /api/v1/share/:token/unlock,
    POST /api/v1/share/:token/join, POST /api/v1/decks/:id/sharing/links,
    DELETE /api/v1/decks/:id/sharing/links and
    DELETE /api/v1/decks/:id/sharing/links/revoke/:digest. Stored share links stop working.
    deck_grants, share_invites, the sharing page and the grant endpoints remain.
  • Two tables dropped: migration 0008_drop_share_link_tables removes share_links and
    share_session_decks. Migration 0009_unique_default_preset_names renames duplicate
    Default presets and changes no table, column or index; every decks.preset_id and
    deck_member_settings.preset_id reference stays in place.
  • No MCP tool was removed or renamed. delete_deck is new; get_due_cards keeps its name
    and its arguments.
  • A single newline inside a paragraph now renders <br>. Card content and mail templates
    follow GitHub Flavored Markdown, so tables, strikethrough, bare-URL links and task lists
    render too. Content with no single newline and no GFM syntax renders as before.
  • POST /api/v1/keys rejects an expires_at that is not strictly in the future with
    400 invalid_request, where it previously returned a key that was already unusable. Omitting
    the field, or sending a future time, behaves as before.
  • From-source builds need Go 1.27 and Node 26 / npm 12. Published images and binaries are
    unaffected.
  • Additive only: the optional option_order field on due cards and on the
    POST /api/v1/review/render response, and the ruby/rt/rp elements with their named
    data-* attributes in rendered card HTML. No configuration key and no environment variable
    was added, removed or renamed, and the deck-package and note-import schemas keep their shape.

Features

Review

  • Each (user, card, state version) gets a derived option display order, so a choice answer
    cannot be memorised by position; submitting a review produces a new one. The submitted
    answer is still a stored index.
  • Answer controls receive one sanitized HTML fragment per option and typeset it, so TeX
    delimiters no longer appear literally.
  • A cloze deletion whose whole content sits inside a formula separates its accepted answers
    with \alt; validation rejects \alt where it cannot split.
  • The four rating buttons show only their names, and the help popover no longer promises an
    interval under each one.
  • Each checkbox and radio is named through aria-labelledby from the element that shows the
    option, so a typeset formula is announced as its rendered text.
  • The completion text waits for the another-batch quota request, so text and offer form appear
    together.

Card content and rendering

  • Card text accepts {{tts:…}}, {{audio:…}} and {{ruby:…}}; the server expands each into an
    element with named data-* attributes and the review page and editor preview attach speech
    and audio controls to them. An unknown name, a malformed parameter or a body that is not a
    single inline-Markdown paragraph stays literal, and mail bodies render plain text.
  • A shortcode body is inline Markdown, so emphasis, code spans, links and a cloze highlight
    render inside it. Three nesting shapes are accepted, at most two shortcode levels deep:
    tts around ruby, tts around a cloze highlight, and tts around ruby around a cloze
    highlight. Speech reads the visible text only; mail flattens tts around ruby to
    base(reading).
  • Audio gets a seekable progress track with an elapsed/total clock, pause/resume from the paused
    position and five-second back/forward buttons; the tts hide flag hides the body only while
    a speech control exists. Both controls fit inside their line box with a 40×40 pointer target.
  • /help/shortcodes documents the grammar, parameters and fallback rules in both languages;
    each editor text field carries its own image and shortcode tools, with the media library and
    composer in dialogs.
  • Card content and mail templates render GitHub Flavored Markdown: tables, strikethrough,
    bare-URL autolinks and task lists with read-only checkboxes.

Authoring

  • Insertion tools sit on the field they write into; below lg the live preview is an on-demand
    drawer. The page-level field selector, upload area and standalone composer block are gone.
  • Each text field carries bold, italic and strikethrough buttons plus Ctrl/Cmd+B, Ctrl/Cmd+I
    and Ctrl/Cmd+Shift+X. The stored value stays Markdown source.

Accounts, keys and access

  • The SPA login page links to /register when the anonymous policy probe reports open.
  • The personal key page sets an expiry on create — never, 7 / 30 / 90 days, one year, or a
    custom date meaning the end of that local day — lists each key's expiry, and groups
    already-expired keys separately with an expired badge while keeping the revoke action.

Notifications and mail

  • Saving notification preferences sends only closable mail types, so the locked class-A entries
    the form keeps for rendering no longer fail every request with class_locked.
  • Class-D admin notifications carry RFC 8058 one-click unsubscribe headers.
  • The built-in body of every mail type is designed Markdown rendered through the same pipeline
    as an admin template: a title, a primary action, a note and a footer, a derived plain-text
    part, and a shell that survives clients without rounded corners or <style>. All thirteen
    types were rewritten in both languages.
  • The toast close button follows the page theme, including a live switch.

Data, imports and MCP

  • Importing a package derives the preset name from the deck when the package carries no name or
    the reserved Default, and makes it unique among the importer's presets, so an import can no
    longer add a preset named Default.
  • delete_deck removes a deck together with its notes, cards and progress. Only the owner may
    call it, and the deletion is irreversible; it calls the same service method as
    DELETE /api/v1/decks/:id and returns the same body.

Full changelog: v0.1.10...v0.2.0

Container images: nite07/engram:v0.2.0 (Docker Hub) and ghcr.io/bestnite/engram:v0.2.0.