From c77bd2a281ef2fa90d83c5d7b86dd0ab46ade664 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9B=B7=E7=94=B5=E8=8A=BD=E8=A1=A3?= Date: Fri, 9 Oct 2026 03:57:56 -0400 Subject: [PATCH] ElyMark: task boxes are drawn at text size on the first line (R2.14) --- apps/ely-mark/examples/markprobe.rs | 11 +++++++++++ apps/ely-mark/web/src/main.css | 14 ++++++++++++-- tests/scripts/mark-content.sh | 4 ++++ 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/apps/ely-mark/examples/markprobe.rs b/apps/ely-mark/examples/markprobe.rs index f2ca9d5..8e856fe 100644 --- a/apps/ely-mark/examples/markprobe.rs +++ b/apps/ely-mark/examples/markprobe.rs @@ -56,6 +56,17 @@ const CHECK: &str = r#" inline: seen(view.querySelector('.milkdown p .katex')), display: seen(view.querySelector('.milkdown p .katex-display')), tasks: view.querySelectorAll('li[data-item-type="task"]').length, + box: (() => { + const item = view.querySelector('li[data-item-type="task"]'); + if (!item) return null; + const mark = getComputedStyle(item, '::before'); + const range = document.createRange(); + range.selectNodeContents(item.querySelector('p')); + const line = range.getClientRects()[0]; + const top = item.getBoundingClientRect().top + parseFloat(mark.marginTop); + const size = parseFloat(getComputedStyle(item).fontSize); + return [parseFloat(mark.width) / size, parseFloat(mark.height) / size, top + parseFloat(mark.height) / 2 - (line.top + line.height / 2)]; + })(), cells: view.querySelectorAll('.milkdown td').length, notes: view.querySelectorAll('[data-type="footnote_definition"]').length, blocks, diff --git a/apps/ely-mark/web/src/main.css b/apps/ely-mark/web/src/main.css index a09adf6..6862cfe 100644 --- a/apps/ely-mark/web/src/main.css +++ b/apps/ely-mark/web/src/main.css @@ -116,12 +116,22 @@ a { list-style: none; } +/* A text-sized box, centred on the first line. */ .milkdown li[data-item-type='task']::before { - content: '☐ '; + content: ''; + flex: none; + box-sizing: border-box; + width: 1em; + height: 1em; + margin-top: calc(0.25em + (1lh - 1em) / 2); + border: 0.09em solid var(--ely-fg-muted); + border-radius: 0.2em; } .milkdown li[data-item-type='task'][data-checked='true']::before { - content: '☑ '; + border-color: var(--ely-link); + background: var(--ely-link); + box-shadow: inset 0 0 0 0.18em var(--ely-bg); } .milkdown hr { diff --git a/tests/scripts/mark-content.sh b/tests/scripts/mark-content.sh index 5c049b8..9109e39 100755 --- a/tests/scripts/mark-content.sh +++ b/tests/scripts/mark-content.sh @@ -62,6 +62,10 @@ for step in ("visual", "themed", "preview"): for key, value in [("title", "Title"), ("heading", True), ("inline", True), ("display", True), ("tasks", 2), ("cells", 2), ("notes", 1), ("font", True), ("editors", 1)]: want(step, key, value) + # The task box: text-sized, centred on its line. + width, height, off = seen[step]["box"] + if abs(width - 1) > 0.01 or abs(height - 1) > 0.01 or abs(off) > 1: + sys.exit(f"FAIL: {step} task box is {seen[step]['box']}") blocks = seen[step]["blocks"] if [block["language"] for block in blocks] != languages: sys.exit(f"FAIL: {step} blocks are {blocks}")