Skip to content

Escaped table pipes, links to headings, Contents depth (#44, #43, #42) - #45

Merged
b451c merged 7 commits into
mainfrom
community/2026-10-29
Oct 29, 2026
Merged

b451c merged 7 commits into
mainfrom
community/2026-10-29

Conversation

@b451c

@b451c b451c commented Oct 29, 2026

Copy link
Copy Markdown
Owner

Integrates three GitHub threads for the next release.

  • fix(tables): an escaped pipe stays inside its cell #44 (@rinh): an escaped pipe stays inside its table cell. Follow-up: a pipe right after a backslash never splits, even after \\, so path\\| c and `p\\|q` render as on GitHub (checked with GitHub's renderer).
  • Same document heading links - Traditional Table of Contents #43: a link to a heading in the same document ([Install](#install)) scrolls to it. Headings get GitHub's ids (rendered text, github-slugger duplicates); #Install Guide, README.md#install inside README.md, # and #top work too; an unknown id beeps. Before, such a link opened the document's folder in Finder. Also: an ATX heading's closing #s are no longer shown (## Install ##), as in CommonMark.
  • Option to limit Contents sidebar heading depth #42: how deep the Contents sidebar goes (All Headings, Up to H2/H3/H4), from the sidebar's context menu or Settings > General; one setting, display only.

Tests: parser rows and drawn table string for pipes, heading ids against GitHub's output, fragment lookup, closing sequences, depth filter. E2E on a separate bundle id: every link kind clicked for real, Finder untouched, context menu on header and rows, Settings and sidebar in sync, empty state.

Closes #42
Closes #43

rinh and others added 7 commits October 27, 2026 16:37
parseTableRow split on every `|`, so `\|` (GFM's way to put a pipe in a
cell) started a new column: `` `--part 1\|2` `` became two cells, the row
gained a column and the code span broke apart.

Rows are now scanned character by character: only an unescaped `|`
separates cells, and `\|` becomes a literal `|` in the cell, inside code
spans too, as GFM specifies. `\\|` is an escaped backslash followed by a
real separator. Other escapes are left for the inline renderer as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Follow-up to #44. GitHub (cmark-gfm `unescape_pipes`) treats every `\|`
as an escaped pipe, even after another backslash: `path\\| c` is one cell
"path| c" and `` `p\\|q` `` is code `p\|q`. The scanner from #44 read
`\\|` as an escaped backslash plus a column pipe, which split both rows
and broke the code span. Now a pipe right after a backslash drops that
one backslash and stays in the cell; everything else is left to the
inline renderer. The rows were checked against GitHub's renderer.

Tests: two more parser rows and a drawn-string test for the table view.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`## Install ##` showed "Install ##" in the document and the Contents
sidebar. CommonMark (and GitHub) drop a closing run of `#` that follows
a space or tab; `# C#` and an escaped `\###` keep theirs. GitHub's
heading ids (#43) are built from the title, so this also keeps them equal.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
)

`[Install](#install)` had no scheme and no path, so handleLinkActivation
resolved it to the document's folder and opened Finder. Now an in-document
fragment scrolls to its heading the way a ToC click does.

HeadingAnchors gives headings GitHub's ids, from the rendered heading text
(markup gone): lowercased, only letters, marks, decimal and letter
numbers, `_`, joiners and `-` kept, spaces to `-`, repeats counted like
github-slugger (`intro`, `intro-1`, `intro-1-1`, `intro-2`). The expected
ids in the tests come from GitHub's renderer. A fragment that is not an id
is tried as its own slug (`#Install Guide`); `README.md#install` inside
README.md is the same jump; `#` and `#top` go to the top; an unknown id
beeps. The fragment is read from the link as written, so a destination
URL(string:) rejected on macOS 13 (arrives as `%23…`) still works.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
All Headings (default), Up to H2, Up to H3 or Up to H4. One stored value
(`tocMaxHeadingLevel`), edited from the sidebar's context menu (a "Show
Headings" submenu on the header and every row) and from a "Contents
Sidebar" row in Settings > General, so the two can never disagree. The
filter only changes what the sidebar lists: section copy and in-document
links still see every heading. When every heading is deeper than the
chosen level, the sidebar says so and offers "Show All Headings".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review of the integration range: a heading of only an emoji (`## 🚀`)
slugs to the empty id, so `[top](#)` scrolled to that heading instead of
the top. The decision now lives in HeadingAnchors.target (tested): `#` is
the top, `#top` is the top unless a heading claims that id, an unknown
id beeps. Also documents the accepted cost of reading `%23…` links as
anchors (macOS 13 fallback encoding), and the CHANGELOG now says what
the old behaviour was in each build: Finder, or a permission error in
the sandboxed App Store build (seen in E2E).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@b451c
b451c merged commit 47aa0f1 into main Oct 29, 2026
3 checks passed
@b451c
b451c deleted the community/2026-10-29 branch October 29, 2026 07:28
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.

Same document heading links - Traditional Table of Contents Option to limit Contents sidebar heading depth

2 participants