Skip to content

โ† All Skills Knowledge History

Memo types: text | checklist (with checklist editor + .txt round-trip)

completed๐Ÿ“ฆ my-memo๐Ÿ‘ค YCEJ9999๐Ÿ—“ 2026-06-21 14:00:00

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 }.
  • Memo gains type: MemoType and items: ChecklistItem[] โ€” text memos use content, checklist memos use items (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 content lines into items, stripping 1. / - / * bullets (/^\s*(?:[-*]|\d+[.)])\s*/).
    • checklist โ†’ text: join item texts back into lines.
  • addInputItem() / removeInputItem(i) / toggleInputItem(i) edit input.items; item text uses plain v-model on store.input.items[i].text.
  • save() canonicalizes by type and drops blank-text items. filtered also searches item text. applyImported() copies type + 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-DOM mono-* can't be styled into that). This is Rule 13's native-CSS-in-src/assets fallback, 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

FileOperationNote
src/datas/tables/memo.tsmodifiedMemoType + ChecklistItem; Memo gains type + items; memoTypes/memoTypeLabel; 'Tipe' table column
src/stores/use-memo.tsmodifiedblank() 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.tsmodifiedSerialize 'Tipe' + checklist body as - [ ]/- [x]; parse type + items; plain-text fallback -> type text
src/pages/memo/index.vuemodifiedType toggle; conditional textarea vs checklist editor; table type badge + progress; import memoTypes/memoTypeLabel
src/assets/memo-paper.cssmodifiedmemo-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


โ† All Skills Knowledge History