Repository navigation
v0.2.0
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/linksand
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_tablesremovesshare_linksand
share_session_decks. Migration0009_unique_default_preset_namesrenames duplicate
Defaultpresets and changes no table, column or index; everydecks.preset_idand
deck_member_settings.preset_idreference stays in place. - No MCP tool was removed or renamed.
delete_deckis new;get_due_cardskeeps 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/keysrejects anexpires_atthat 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_orderfield on due cards and on the
POST /api/v1/review/renderresponse, and theruby/rt/rpelements 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
answeris 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\altwhere 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-labelledbyfrom 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 nameddata-*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:
ttsaroundruby,ttsaround a cloze highlight, andttsaroundrubyaround a cloze
highlight. Speech reads the visible text only; mail flattensttsaroundrubyto
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; thettshideflag hides the body only while
a speech control exists. Both controls fit inside their line box with a 40×40 pointer target. /help/shortcodesdocuments 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
lgthe 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
/registerwhen the anonymous policy probe reportsopen. - 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 anexpiredbadge 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 withclass_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 reservedDefault, and makes it unique among the importer's presets, so an import can no
longer add a preset namedDefault. delete_deckremoves 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/:idand 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.