Repository navigation
v0.1: working markupit — local serving + annotation overlay - #1
Conversation
Eight source files covering icon, wordmark, horizontal lockup, and stacked lockup — each in light and dark background variants. Based on logo concept 6 (nested rounded squares with arrow mark). ViewBox dimensions measured via Inkscape to eliminate trailing whitespace. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Pure-ESM, zero-runtime-dependency package skeleton for the v0.1 build: - package.json (bin, exports, files whitelist, engines >=20.10, empty deps) - ESLint flat config + Prettier - GitHub Actions CI: node 20/22/24 matrix (lint, unit, server, id-gate, zero-dep assertion) + separate Playwright job - scripts/coverage-ids.mjs: fails CI on any MUST with no [ID]-tagged assertion - test harness (linkedom DOM loader, server boot + mock-remote helpers) and fixtures (static site with varied + non-content nodes, single file, hostile stylesheet) - docs/PLAN-0.1.md Tests green: [NFR-1] zero runtime deps, [CLI-1] markupit bin. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
CLI + HTTP server for the two local source modes: - args.js (pure): flag parsing with validation [CLI-5,6,7] - source.js: classify dir / file / url, banner labels [CLI-2,3,4] - server: static serving with traversal guard, MIME table, no-store headers, reserved /__markupit__/ namespace checked first [SRC-1,2,6,8] - net.js: port fallback on EADDRINUSE [CLI-5] - cli.js: startup banner, --open, clean SIGINT/SIGTERM shutdown [CLI-8] - bin/markupit.js entry; proxy.js stub returns a friendly "coming soon" 22 tests green (13 unit, 9 server). CLI verified end-to-end. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- inject.js (pure): insert the overlay module script before the last </body>, preserving document casing; idempotent via the injection marker so re-serving never doubles it [ACT-1, ACT-4] - wire injection into HTML responses only; non-HTML passes through - activation lives in the URL: the dormant overlay is injected into every page identically and self-gates on ?markupit, so a path's served bytes are the same with or without the flag [ACT-5] 10 new tests green (inject unit + server injection). 32 total. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The DOM-simulator-testable heart of the overlay (no browser globals): - ids.js: composite anchor (authored-id -> structural nth-of-type path -> FNV-1a text fingerprint) with cascade re-anchoring; orphans resolve to null rather than mis-match [SEL-7] - selectable.js: content-element predicate, candidate resolution, parent/ child widening; non-content + chrome excluded [SEL-3,5,6] - model.js: pure reducer, one entry per element with coexisting comment/ edit/remove slots, all reversible [ANN-2,4,5] - export.js: state -> document-ordered markdown brief + raw JSON [EXP-2..7] - label.js, snippet.js: human labels and content snippets [QUE-2] Also fixes a sharp test hazard: asserting on a linkedom DOM node deep- inspects its circular graph (>100MB) on failure and OOMs the process. candidateAt now resolves text nodes to their element, and tests compare node identity via a sameNode() helper so a failure only inspects a boolean. 44 unit tests green (up from 19). 57 total. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The full annotation surface, vanilla JS in a single shadow root so it is style-isolated from the page (UX-10) and our chrome is never selectable as content (SEL-5): - shadow.js + styles.js: design-system stylesheet adopted into the root; :host inherited resets are !important so a hostile page `*` rule can't bleed font/colour into chrome - selection.js + highlight.js: hover highlight and click-to-select drawn in the shadow layer, never touching the page [SEL-1,2] - popover.js: anchored action popover that grows from the click point; comment / edit (focused textarea) / remove, all reversible [ANN-1,2,3,4,6] - markers.js: in-page edit/remove treatments (owned inline styles) + on-page dots [ANN-3, QUE-5] - queue.js + toolbar.js: sliding overview with human labels, live count, copy + reset [QUE-1,2,4, ANN-8, EXP-1] - persistence.js + anchor.js: localStorage keyed to the page, re-anchoring on load, orphans kept not dropped [ANN-7] - keyboard: c/e/r, [ ] widen, Esc, ⌘/Ctrl+Shift+C export [UX-7]; respects prefers-reduced-motion [UX-5] Note: 0.1 uses a system font stack; bundling the brand font is a follow-up. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
16 specs against a real markupit server and headless Chromium: - activation: clean page without the flag, no console errors with it, shadow host mounts, page scripts keep working [ACT-2,3, NFR-2,4] - annotate: hover highlight, click-to-select, add comment, remove treatment, persist-across-reload + clipboard export round trip [SEL-1,2, ANN-1,3,7, EXP-1] - encapsulation: hostile page stylesheet can't bleed into chrome and chrome can't leak onto the page; chrome not selectable; reduced motion [UX-10,5, SEL-5] - queue + motion: queue lists all annotations with human labels, distinct per-kind treatments, motion present by default [QUE-1,2, UX-3,4] Every MUST requirement is now covered by a tagged assertion or recorded as exempt (proxy mode + subjective UX). Suite: 44 unit, 13 server, 16 browser. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- README: drop the design-phase notice; document usage, options, the activation flag, marking-up flow, how-it-works, and the proxy roadmap - CONTRIBUTING.md: test-first + ID-tracing workflow, the hard constraints (zero deps, clean-room, page-disappears, UX bar), and the linkedom/assert OOM gotcha - docs/UX-CHECKLIST.md: human pass for the subjective UX-* qualities - package.json: prepublishOnly runs lint + tests; verified the publish tarball ships only bin/src/overlay/README/LICENSE Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The inline `node -e` contained a colon-space ("found: ") that GitHub's YAML
parser read as a nested mapping, failing the whole workflow at parse time.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- test runner: replace `node --test "glob"` (needs Node 21+) with a small portable discovery script so test:unit/test:server run on Node 20/22/24 and on Windows - fixture: regenerate team.png as a valid PNG (correct zlib stream + CRCs); the previous bytes decoded on Chromium but Firefox flagged them, tripping the [NFR-2] no-console-errors check - browser tests: clipboard-read/write permissions are Chromium-only in Playwright — split [ANN-7] persistence (all browsers) from [EXP-1] clipboard export (chromium-only via test.skip) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
UX feedback — comment/edit panel behaviour Noted while reviewing real content with the overlay:
|
Follow-up: review-note history (instead of destructive clear)Feedback from dogfooding — the system is working well. Two related asks about the review notes, now scoped into a concrete plan. 1. Keep notes as history instead of discarding on clearToday
History entries are read-only data — the page treatments (edit/remove) are still reverted on clear, and anchors may go stale on later loads, so we don't try to re-apply them. 2. Confirmation + no undo
History UI / export
Out of scope for now: undo, re-applying archived treatments, history size caps. |
Reset was destructive — clearing the page wiped every annotation and removed the localStorage key. Make it non-destructive: each clear is archived as a timestamped history batch (one entry per clear) that persists across reloads, and the queue panel grows a collapsible History section to review, copy, delete, or clear past notes. - model: history[] state with archiveAndReset / deleteHistoryBatch / clearHistory / historyBatches; summarizeKinds (liveCount reuses it). - persistence: default missing history on load (back-compat); reset now saves the archived state instead of removing the storage key. - queue: History section with per-entry copy (full notes brief via the existing markdown export) and delete, plus a total clear. ANN-8 is now non-destructive; adds QUE-6 (history) and QUE-7 (copy/delete/clear). Confirmation still uses the native dialog — the styled replacement follows in the next commit. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The browser's window.confirm is jarring and out of place inside the shadow-DOM overlay. Add a styled, promise-based confirmation rendered in the overlay itself (danger variant, Esc / backdrop to cancel, focus on the primary button) and use it for both Reset and Clear history. - confirm.js: createConfirm(root) factory matching the other UI modules. - app: await the styled dialog instead of window.confirm. - styles: dialog + backdrop, reusing the design tokens and mk-grow. - browser tests cover the styled (non-native) confirm and the full history flow: archive-on-reset, cancel, persistence, copy, delete, and total clear. Adds UX-11 (no native dialogs); covers QUE-6/QUE-7 in the browser suite. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Implemented ✅Both pieces of feedback are in, on
Per the discussion: no undo this pass; history entries are individually deletable with a total clear; each entry copies out as a single text block via its Copy button. RequirementsANN-8 is now non-destructive; added QUE-6 (history), QUE-7 (copy/delete/clear), and UX-11 (no native dialogs). Verification
|
Polish from review feedback on the confirm/history flow:
- Reset dialog: clearer two-line prompt ("Clear all annotations for this
page / and reset for a new review?"), primary button reads "Reset", and
a third action "Copy notes and Clear" copies the brief then clears in
one step.
- Deleting a history entry now asks for confirmation (no accidental loss)
and the control uses a trash-can icon instead of a bare ×.
- createConfirm generalised to resolve 'confirm' | 'cancel' | 'extra',
supporting an optional third button and multi-line messages.
Updates ANN-8 (copy-and-clear); browser tests cover the new dialog
actions and the delete confirmation.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…omposing Two popover fixes from review feedback: - The selected-element outline gains a white contrast ring so it stays legible on dark page backgrounds, where the ink border alone vanished. It remains drawn while the popover is open, including in comment/edit mode (ANN-9). - While composing a comment or edit, a stray click elsewhere on the page no longer swaps or dismisses the popover or discards the in-progress text (ANN-10). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…views Record the larger ideas raised in review for a future release: moving the popover aside while composing, annotating content that only appears after a page-driven interaction, and collecting feedback across multiple pages. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Round 2 — review-note UX refinements ✅Pushed to
Mapped to: #1 trash icon ✓, #2 delete confirm ✓, #3 reset wording + "Reset" label ✓, #4 "Copy notes and Clear" ✓, #5 focus highlight ✓, #6 no-dismiss while composing ✓. Verification
Backlog (recorded in README roadmap)
|
Implements the markupit specification clean-room, test-first. Turns the design-phase repo into a working tool:
npx markupit ./dir(or a single.html), open the printed?markupitURL, click any element to comment / edit / remove, then copy a structured markdown brief for an agent.Scope
Covered (all MUSTs for local modes):
/__markupit__/namespace, port fallback, clean shutdown, idempotent overlay injection, activation gating via?markupit.prefers-reduced-motion, keyboard fluency.Deferred to a follow-up (stubbed with a clear notice):
SRC-3/4/5/7) — reviewing a livehttp(s)page.Constraints held
dependenciesstays empty.docs/.Tests
node:test+ linkedom) · 13 server integration · 16 Playwright.npm run test:idsgates that every MUST requirement has an[ID]-tagged assertion (or a recorded exemption).Commit trail
Each commit is one milestone, leaves the suite green, and cites the requirement IDs it satisfies —
git logreads as a spec-coverage walk.Notes
prepublishOnlyruns lint + tests; tarball verified to ship onlybin/,src/,assets/overlay/, README, LICENSE) but not yet published —markupitis available on npm.🤖 Generated with Claude Code