โ All Skills Knowledge History
Memo types: text | checklist (with checklist editor + .txt round-trip)
memomemo-typechecklistlocalStorage-migrationtxt-round-tripnotebook-paper-uistore-centric
Request
- Give memos a type: text | checklist; the current memo is plain text.
- Checklist example: a shopping list โ '5kg Tomato', '2kg apple' โ with checkable items.
- Flag the type in the table (text | checklist).
- The form must show a checklist-style editor for checklist memos.
- Add a Mono Skills entry.
Summary
Memo types: text | checklist
Added a type to memos so a memo is either free text (the original) or a checklist of
checkable items (e.g. a shopping list: 5kg Tomato, 2kg apple). The table flags the type; the
notebook-paper form shows a checklist editor when the type is checklist. Fully backward-compatible
and round-trips through the existing .txt import/export.
Data model (src/datas/tables/memo.ts)
type MemoType = 'text' | 'checklist';interface ChecklistItem { text: string; done: boolean }.Memogainstype: MemoTypeanditems: ChecklistItem[]โ text memos usecontent, checklist memos useitems(kept mutually exclusive: on save, text โitems: [], checklist โcontent: '').memoTypes+memoTypeLabel(Teks/Checklist); a{ field: 'type', caption: 'Tipe' }table column.
Backward compatibility (the important bit)
Memos saved before this feature have no type/items. load() runs a normalize() over every
record: type ??= 'text', items = Array.isArray(items) ? items : []. So old localStorage data keeps
working โ no migration step, no crashes on m.items.some(...).
Store logic (src/stores/use-memo.ts, Rule 15)
setType(t)migrates between representations so the toggle "just works":- text โ checklist: split non-empty
contentlines into items, stripping1./-/*bullets (/^\s*(?:[-*]|\d+[.)])\s*/). - checklist โ text: join item texts back into lines.
- text โ checklist: split non-empty
addInputItem()/removeInputItem(i)/toggleInputItem(i)editinput.items; item text uses plainv-modelonstore.input.items[i].text.save()canonicalizes by type and drops blank-text items.filteredalso searches item text.applyImported()copiestype+items.exportMemo()empty-guard also considers items.checklistProgress(m) โ { done, total }for the table badge.
.txt round-trip (use-memo-utils.ts)
The block gained a Tipe: text|checklist header. Checklist bodies serialize as markdown
checkboxes, one per line โ exactly the user's list:
Tipe: checklist
----- ISI -----
- [ ] 5kg Tomato
- [x] 2kg apple
parseMemos reads Tipe (default text) and parses ^\s*-\s*\[( |x)\]\s?(.*)$ into items (done from
x); text memos keep content. Plain-text imports default to type: 'text'. A standalone test
confirmed full round-trip incl. done-state.
UI (src/pages/memo/index.vue + src/assets/memo-paper.css)
- A type toggle (Teks | Checklist segmented pills) above the title; clicking calls
setType. type==='text'โ the existing lined textarea.type==='checklist'โ a checklist editor on the ruled paper: each row = native checkbox (accent-color: var(--memo-accent)) + a borderless text input (Enter adds a new item) + a hover โ remove; a "+ Tambah item" button; done items get a strike-through. Table shows a type badge with progress (e.g. "Checklist ยท 1/2").- Rule 13 note: native checkbox + input (styled in the page-local
memo-paper.css), not<mono-checkbox>โ the form is a custom notebook-paper surface where every field is native so it can sit on the ruled lines (shadow-DOMmono-*can't be styled into that). This is Rule 13's native-CSS-in-src/assetsfallback, consistent with the title/content/category fields.
Files
src/datas/tables/memo.ts,src/stores/use-memo.ts,src/composables/use-memo-utils.ts,src/pages/memo/index.vue,src/assets/memo-paper.css.
Outcome
successvite module transform + standalone round-trip test /memo, page, store, use-memo-utils.ts, datas all transform 200 UnoCSS generates i-mdi-format-list-checks / i-mdi-text / i-mdi-close Round-trip test passed: checklist serializes to 'Tipe: checklist' + '- [ ] '/'- [x] ' lines and parses back with item text + done state; text memos round-trip; text->checklist migration strips '1.'/'-' bullets
Decisions
type + items[] on Memo (mutually exclusive bodies)
Added type: 'text'|'checklist' and items: ChecklistItem[]. On save, text โ items:[], checklist โ content:''.
Why: Keeps each type's body canonical and avoids stale data; the table/search/export branch on type cleanly.
Normalize old records on load (no migration step)
load() backfills type='text' and items=[] for any record missing them.
Why: Existing localStorage memos predate the feature; normalizing on read keeps them working and prevents undefined.items crashes.
Smart type-toggle migration
setType converts content lines โ items (stripping 1./- bullets when going to checklist).
Why: The user's flow is 'list my checklist'; toggling should turn their typed lines into checkable items (and back), not lose data.
Markdown checkboxes in the .txt round-trip
Serialize checklist items as '- [ ]'/'- [x]' under a 'Tipe: checklist' header; parse them back.
Why: Human-readable, standard, and preserves done-state across export/import (and arbitrary .txt with such lines could be imported).
Native checkbox/input styled in memo-paper.css (Rule 13 fallback)
Did not use <mono-checkbox>; used native elements styled in the page-local CSS.
Why: The memo form is a custom notebook-paper surface; shadow-DOM mono-* can't be styled onto the ruled lines. Consistent with the existing native title/content/category fields; Rule 13 permits native CSS when components/UnoCSS can't express the styling.
Files changed
| File | Operation | Note |
|---|---|---|
src/datas/tables/memo.ts | modified | MemoType + ChecklistItem; Memo gains type + items; memoTypes/memoTypeLabel; 'Tipe' table column |
src/stores/use-memo.ts | modified | blank() type/items; load() normalize old records; setType migration; add/remove/toggle item; save canonicalize+trim; filtered searches items; applyImported copies type/items; exportMemo guard; checklistProgress |
src/composables/use-memo-utils.ts | modified | Serialize 'Tipe' + checklist body as - [ ]/- [x]; parse type + items; plain-text fallback -> type text |
src/pages/memo/index.vue | modified | Type toggle; conditional textarea vs checklist editor; table type badge + progress; import memoTypes/memoTypeLabel |
src/assets/memo-paper.css | modified | memo-type-toggle; checklist rows on ruled lines (checkbox/input/remove, is-done strike); memo-add-item; small-screen flex-grow |
Commands
pnpm dev
curl /memo + page + store + utils + datas (all 200)
node round-trip + migration test (all passed)
MONO_SKILLS=true MONO_SKILLS_GITHUB_TOKEN=[REDACTED] pnpm exec mono skills save --app my-memo --dir .mono/skills/pending/<id>Validation
Tests: not run Build: passed