Repository navigation
Keep a comment that starts a line from hiding its formatting - #95
Merged
Merged
Conversation
Markdown reads a line whose text starts with `<!--` as a raw HTML block, so Reading view showed the whole line unformatted whenever a comment started a paragraph, list item, quote, callout, or footnote. New comments now put a zero-width space in front of the opening marker there, and open after the bullet, `>`, or `#`s a triple-click selects instead of in front of them. The editor hides the guard with its marker as one unit, and deleting a comment removes it. Comments written before this offer Repair on their card, in Live Preview and Reading view, and the repair command now covers lines as well as tables.
A closer moved back is two edits. The whole-note repair dropped whichever one touched a table repair, which could delete the closer outright, so a run's edits are now kept or held back together. An end that can't move back onto a fence, rule, or table row goes past the next line's markup instead of in front of it, and so does a start on an empty list item. Lines are read without a trailing CR, so a rule in a file with Windows line endings is still a rule.
Past four columns of indentation, a marker after a whitespace-only line's spaces or tab starts an indented code block, which shows it as text, or joins the paragraphs that line kept apart. At the line's start it stays an invisible HTML block, as it always was when a selection started there.
A selection that starts or ends on a rule, setext underline, empty bullet, or blank line now anchors on the text beside it; a marker anywhere on a rule or underline stopped it rendering as one. A paragraph's comment no longer writes its thread inside a code block that follows it, and a block with no closing fence refuses a comment instead of filling with comment text. Repair moves a marker off a rule or underline it broke. Reading view now finds a comment's rendered text, not its raw source, and highlights it across elements: through highlights, bold, links and inline code, across line breaks and paragraphs, in syntax-highlighted code blocks (wrapped again once highlighting replaces the block), and where a repeated phrase is, not where it first appears.
A start on a blank line moved on to the next line's text even when that line opened a $$ math block, a %% comment block, or raw HTML, and a marker in front of one stops it opening its block. It now stays on the blank line there, and Repair leaves a rule's marker in place rather than move it onto such a line. Obsidian keeps a rendered block whose source hasn't changed, so the middle block of a comment over three or more blocks kept its highlight after the comment was deleted. Reading view now highlights only the blocks that hold one of the comment's markers.
The stop for HTML blocks took any line starting with `<`, so a blank-line start above inline HTML followed by text (`<b>Note:</b> …`) stayed on the blank line. It now takes only the lines Markdown reads as HTML blocks: block tags, a tag alone on its line, and a comment left open. A line of nothing but a comment is looked past. Obsidian keeps a rendered block whose own source didn't change, so a highlight there outlived its comment when the change happened elsewhere: one end of a multi-block comment deleted, or a code comment removed. Reading view now syncs its highlights with the note on every refresh, unwrapping those whose comment is gone and updating the rest's resolved status and preview.
The sync read the file, but a Reading pane beside an editing pane on the same note shows the editor's text, which is ahead of the file until it saves. A comment added there had its new highlight unwrapped before the save, and nothing wrapped it again. The sync now uses the text the pane shows.
A closer pulled back to the end of a line that ends in a backslash, or a selection that stops there as Obsidian's triple-click does, put the marker right after the backslash. `\<` is an escape, so the marker showed as text and the hard break was lost. Both ends now go in front of a backslash that isn't escaped itself, and Repair moves markers an older version wrote after one. A comment starting or ending on indented code put its markers after the indentation, in the code, where they showed as text, and Repair moved older openers there too. A selection touching indented code now takes in its whole lines, with the markers on the blank lines around the block where there's room, or at a line's start, where they're hidden, where there isn't. Telling code from an indented list item's text follows Obsidian's own rendering, checked in the app: a line of nothing but comments still counts in a list, a quote right after a list item stays in it, and a bullet four columns past its holder's text carries on a paragraph. Reading view dropped HTML and %% comments inside fenced code when matching a code comment's text, so a code comment over such a line highlighted only the rest. Comments that start in code are now kept as the code's text. A marker followed by nothing but comments is no longer guarded, which made an invisible line an empty paragraph.
A comment on part of an indented code block with a blank line in it put a marker on that blank line, splitting the block in two. A comment touching indented code now takes in the whole block, blank lines and all, with its markers on the lines around it. Deleting a comment whose marker sat alone on a line removed the line too. Only a code comment adds lines of its own around its block; any other comment's marker was written onto a line that was already blank, and that line now stays, so adding and deleting a comment gives back the note exactly. With the markers on the lines around the code, selecting the same code again finds the comment, so an empty one toggles off as before. A footnote's indented second paragraph read as code, so a comment there ended the footnote. Its text now counts as four columns in, like a list item's. Checked in the app, a footnote only opens after a blank line, and a comment or quote ends it.
A comment on indented code has its markers on the lines around the block, each a section of its own in Reading view, so the code's section held neither and got no highlight, and the card, placed by the highlight, was hidden. A section right between its comment's marker lines is now highlighted. In a list item, a marker line where the blank line around the code had been let the list run on, pulling the next paragraph into the item. A comment on indented code in a list item now keeps its markers on the code's own line, at the item's text column, where they're hidden and the line shows as text (checked in the app), or ends on a comment line right after the code. An ordered item's text counts as at least four columns in, as Obsidian reads it. A guard in front of an old marker run that sits before a bullet, `>`, or `#`s made Repair read the run as text, so the line stayed broken and its card stopped offering Repair. Repair now looks through the guard.
In front of a raw HTML block's opening tag, a marker made the line a comment block, which ends right there and left the lines after it to render as something else, and a guard made it a paragraph instead. A marker now goes after the tag, and Repair moves one an older version wrote in front of it. A selection of nothing but a lone tag is refused, as it holds no text. The lines of a raw HTML block, up to the blank line ending it, no longer read as code or list items. Indented code's markers stay off a blank line next to a table, which the table repair read as a marker breaking the table, so a new comment was flagged and its repair moved the marker into the code. A selection that would leave an anchor of nothing but line breaks once kept out of indented code is refused. A selection of exactly a highlight's text finds that highlight again, wherever moving its ends would take them now that it's written. Each end of a selection between two code blocks goes by its own block's list.
Writing a comment can move its markers off the ends of the selection that made it, past a bullet, `>`, `#`s, or a guard, or back to the text it ended on, and can put its thread inside that selection. Mapped onto the new text, the selection then takes those in, so running Add comment on it again missed the empty comment it had just made and wrote a second one over it. The lookup now also takes a selection as the comment's when, with the comment's own markers and thread back out, it anchors that comment again.
The check that a selection anchors an empty comment again reads the whole note, and it ran for every empty comment the selection overlapped. Select all and Add comment in a note with hundreds of them took seconds, blocking the editor. The comment a selection made covers nearly all of it, since anchoring only trims an end or widens it to whole code lines, so the check now runs only on the three that cover the most: 11 ms rather than 711 ms per lookup with 250 empty comments in a 47 KB note.
…ion's The lookup ran its full check on the three empty comments that left the least of the selection uncovered. A comment enclosing the selection leaves none of it uncovered, so with three or more around it, the comment the selection had just made never got checked, and Add comment wrote a second one over it. Candidates now rank by how far each of their ends is from the selection's, in the text that shows, with markers and threads left out. The comment a selection made sits right at its ends, and one reaching past it ranks behind.
Obsidian renders every footnote in one section, on the line after the note's last, so the highlighter found no comments there, and Add comment in Reading view couldn't map a selection in a footnote. Each footnote's data-line counts from that line to its definition, so each footnote now highlights against its own definition's text, past its label. Where a definition ends follows Obsidian's rendering: lines indented four columns past the label, and lines right after its text that don't start a block of their own.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #94.
Markdown reads a line whose text starts with
<!--as a raw HTML block, so Reading view shows the whole line as written. A comment that starts a paragraph puts its<!--c:ID-->marker exactly there. Every==highlight==,**bold**and link on that line then comes out as plain text. Live Preview has its own parser, which is why editing looked fine. Rendering through Obsidian's own renderer shows the same for:Headings, table body rows and markers mid-line were fine. It has worked this way since the first release.
A second bug has the same cause. Obsidian's triple-click selects a line from its very start, so commenting on a whole list item, quote or heading put the marker in front of the
-,>or##. The line then stopped being a list item, quote or heading, in Live Preview as well as Reading view.Before: a note written by 0.1.16, opened on this branch. Each card offers the new Repair.
After: the same note with a zero-width space in front of each marker, as new comments and Repair now write it.
What changes
<!--c:ID-->. The line reads as ordinary text again, and the marker as an inline comment. It renders as nothing in Obsidian, GitHub and other Markdown tools. Headings, table body rows and a marker alone on its line don't need one and don't get one.>, callout[!type], footnote label or heading#s now anchors after them. A selection that ends at the start of the next line, or just after its bullet, ends on the text it covers. It isn't pulled back onto the end of a fence, rule or table row, where it would break that line. In that case it goes after the next line's markup and takes the zero-width space instead. A marker on a line of nothing but whitespace goes at the line's start, where it stays invisible.validate_comments.pyflags a marker that starts a line without one, or that comes right after a backslash.Also fixed here
These are the same kind of problem. I found them by rendering thousands of random comments with markdown-it, then checked each shape in Obsidian.
Rules, setext underlines and blank lines. A selection that started or ended on
---,===, an empty bullet or a blank line put a marker on that line. Anywhere on a rule or underline, a marker stops it rendering as one. These selections now anchor on the text beside them. A selection of nothing but a rule is refused.$$math block, a%%comment block or an HTML block. A marker in front of one of those breaks the block, so a start on a blank line above one stays on the blank line, where it's invisible.Code blocks.
Reading view highlights. These cases had no highlight in Reading view:
==hl==, bold, links, inline code);A repeated phrase also highlighted its first occurrence instead of the comment's. The highlight now finds the comment's rendered text and wraps it across elements. Obsidian rebuilds a syntax-highlighted block after the plugin has wrapped it, so a code comment wraps again once that happens.
A comment over three or more blocks highlights its first and last. Obsidian keeps any rendered block whose source didn't change, so a highlighted middle block would keep its highlight after the comment was deleted.
Obsidian renders all of a note's footnotes in one section of their own, after the note's last line, so the plugin found no comments there. Each footnote now maps back to its definition, which holds its comments. Add comment in reading view works on a footnote's text for the same reason. It used to say it couldn't map the selection.
Highlights stay in sync with the note. Each Reading view refresh removes highlights whose comment is gone, and updates resolved status and preview on the rest. That covers a block Obsidian kept from before the change, which used to keep a deleted code comment's highlight, for example. The sync checks against the text the pane shows, not the file. A Reading pane beside an editing pane shows the editor's unsaved text, so a just-added comment would otherwise lose its highlight.
Repair also moves a marker off a rule or underline it broke.
Lines ending in a backslash. A backslash at the end of a line is a hard line break, and
\<is an escape. A selection that stopped there, as Obsidian's triple-click does, or a closing marker pulled back there, put the marker right after the backslash. Reading view then showed the marker as text and dropped the line break. A marker now goes in front of the backslash, and Repair moves one that an older version wrote after it.Indented code. A comment on indented code put its markers into the code, where they showed as text. It now takes in the code block's whole lines.
Raw HTML blocks. A marker in front of a block's opening tag (
<details>,<div>,</details>) turned the line into a comment block. The lines after it then rendered as something else, and the zero-width space would have turned it into a paragraph. A marker now goes after the opening tag, and Repair moves one that an older version wrote in front of it. A selection of nothing but a lone tag is refused.Deleting a comment gives back the note exactly. Deleting a comment used to remove a line that held only its marker, even when that line was blank before the comment. That could join a code block to the paragraph next to it. Now only a code comment, which adds lines of its own around its block, takes them out again.
Testing
npm run checkpasses (602 tests).One expectation from Keep a marker outside a table where the selection put it #93 changes. A selection ending just after the bullet of a list item below a table still leaves its closing marker there, since pulling it back would put it after the table's closing pipe. It now gets the zero-width space, so the item keeps its formatting.
In Obsidian, with this branch's build in the test vault:
Reviews: a fresh agent with no context reviewed each commit, with reproductions and randomized tests.
The first pass found three bugs. The second commit fixes each one, with a regression test:
---rule;---didn't count as a rule, so the repair could add a marker to its end.The second pass confirmed those fixes.
The third pass confirmed that fix and found nothing new. Across 31,600 random comment creations rendered with markdown-it, this branch breaks rendering in fewer cases than main (8,230 against 24,174), and in none that main renders correctly.
A second fresh agent reviewed the "Also fixed here" commit and found two problems:
$$or%%block below it, which then showed as text;Rechecking each fix, it found three more:
<b>Note:</b>;Each fix came with a test that failed first. Its last pass found nothing new.
Five more fresh agents then reviewed the whole branch, one after each round of fixes. They found 15 more problems, most of them in the handling of backslashes, indented code and raw HTML blocks above. Each fix came with a test that failed first. The last full review found one: running Add comment again on the selection that made an empty comment missed it and wrote a second comment over it. The next commit fixes that. A fresh review of that fix found it made Add comment slow on a select-all in a note with hundreds of empty comments: about a second per lookup, blocking the editor. The commit after brings it back to milliseconds. Its own review found that with three or more empty comments around the selection, the speed-up skipped the comment it had just made. The last commit fixes that: a lookup takes 16 ms, against 711 ms, with 250 empty comments in a 47 KB note, and the reviewer's fuzz of nested highlights finds no misses in 2,228 cases, against 440 before.
A fresh agent reviewed the footnote fix and found no bugs. Of its side notes, one was worth fixing here: a selected word that a footnote's label shares mapped into the label, so Add comment refused it. Another, a line right after an indented fence or heading in a footnote, renders inside the footnote in Obsidian, as the fix assumes. The third, a thread written between a footnote's paragraphs, is older and listed under "Known".
Rendering check: the same markdown-it harness ran over the same kinds of random notes and selections. Where a new comment's markers land now breaks the rendering in 0 of 23,102 comments, against 8,230 before this round and 24,174 on main.
A second harness adds hard line breaks, indented code, footnotes, tables and raw HTML blocks to the random notes, about 40,000 comments in all. It renders every case where markdown-it shows a difference in Obsidian itself, through the running app.
In Obsidian: I checked the note in the screenshot above. It covers:
---from an older version, repaired from its Reading view card;In Obsidian, for this round: I added comments with the app's real triple-click on a line ending in a backslash, on top-level indented code and on indented code in a list item. I also added a code comment over a fenced block holding an HTML comment line. In Reading view:
In Obsidian, for footnotes: I made a note with five comments across four footnotes: mid-line, guarded at a footnote's start, over
==formatted==text, in a footnote's second paragraph, and in the footnote defined last. In Reading view each comment was highlighted in its own footnote, with its card, as in the screenshot above. That held:Add comment in reading view on a footnote's first word wrote the marker into its definition, behind a zero-width space, and its highlight and card appeared. Deleting it from its card gave back the note byte for byte. On a word that the footnote's label also holds, it commented on the footnote's text, not the label.
Known, not fixed here:
^[…]) has no highlight in Reading view, as on main.