Skip to content

feat(board): render block-level markdown (headings + lists) in card text (t-mkd1) - #58

Open
ArgonQQ wants to merge 1 commit into
mainfrom
task/t-mkd1-block-markdown
Open

feat(board): render block-level markdown (headings + lists) in card text (t-mkd1)#58
ArgonQQ wants to merge 1 commit into
mainfrom
task/t-mkd1-block-markdown

Conversation

@ArgonQQ

@ArgonQQ ArgonQQ commented Aug 4, 2026

Copy link
Copy Markdown
Member

What

Renders block-level markdown in story card text. mdToHtml (media/board.js) is rewritten from an inline-only renderer into a line-oriented block pass:

  • ATX headings #..######<h1>..<h6>
  • unordered (- / * ) runs → <ul>, ordered (1. ) runs → <ol> (a marker-style switch ends one list and starts the other)
  • every other line = paragraph text, keeping the legacy soft-wrap exactly (single \n = space, blank line = <br><br>, no <p> wrapper)

A new renderInline(text) helper (escape → `code` split → renderInlineMd) is reused by headings, list items, and paragraphs, so inline bold/italic/code/links keep working inside every block.

Scope

Applies to all three mdToHtml consumers (Rule: it's shared): card description, done/delivered detail, and question text. The question-text container is switched <span><div class="q-text"> so emitting <hN>/<ul>/<ol> inside it is valid HTML. New heading/list CSS is shared across .desc-rendered / .done-detail-text / .q-text, sized down for compact cards.

Webview-render-only — no parser/writer/store/grammar changes.

Safety (escape-first XSS invariant preserved)

The block classifier only inspects raw markers; every user-text fragment is escapeHtml'd before it lands in a tag. Verified inert-escaping of <script>, - <img onerror=…>, and non-http(s) links stay non-linkified.

Verification

  • make check green (build + 103 Docker parser/writer fixpoint tests + package).
  • media/board.js is not in the Docker unit set, so I ran the new renderer in Docker node against 16 cases — headings, ul/ol, ul→ol split, inline-inside-block, para/list boundaries, <br><br> between paragraphs, soft-wrap, byte-for-byte parity with the legacy renderer on plain text, XSS (<script>, - <img onerror>), #nospace not a heading, javascript: link not linkified — all pass.
  • ⚠️ Manual F5 (Extension Development Host, per VERIFICATION.md) not run in this headless session — needs a human to eyeball the three consumers and confirm card-appropriate sizing.

Closes t-mkd1.

Rewrite mdToHtml as a line-oriented block pass: ATX headings #..###### ->
<h1>..<h6>, unordered (- / *) and ordered (1.) runs -> <ul>/<ol>, other lines
= paragraph text keeping the legacy soft-wrap (single newline = space, blank
line = <br><br>). Extract a renderInline() helper (escape -> code split ->
renderInlineMd) reused by headings, list items, and paragraphs so inline
bold/italic/code/links work inside every block. Escape-first XSS invariant
preserved: markers classified on raw text, all user text escaped before it
reaches a tag.

Applies to all three mdToHtml consumers (description, done/delivered detail,
question text); the question-text container is switched from <span> to
<div class=q-text> so block tags are valid HTML inside it. New heading/list
CSS shared across .desc-rendered/.done-detail-text/.q-text, sized for cards.

Webview-render-only; no parser/writer/store/grammar changes.
@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

📦 Build succeeded — installable .vsix for task/t-mkd1-block-markdown (commit c7012bd):

loopboard-todo-mkd1-block-markdown.vsix

Download from the run's Artifacts, unzip, then install: code --install-extension loopboard-todo-mkd1-block-markdown.vsix (or VS Code → Extensions → ⋯ → Install from VSIX…).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant