Repository navigation
Add a test project covering the conversion logic - #41
Merged
Merged
Conversation
Task lists were broken. The Unicode checkbox substitution matched literal strings that Markdig 0.38 does not emit - it renders <input disabled="disabled" type="checkbox" checked="checked" />, while the replacement looked for <input checked="" disabled="" type="checkbox" />. Neither replacement ever fired, so raw disabled checkbox elements were pasted into Loop instead of the checkboxes it can display. Replace the TaskList renderer instead, so the output does not depend on Markdig's attribute order or spacing. TransformTaskLists is removed. It scanned for a LiteralInline starting with "[x] ", which the TaskList extension enabled by UseAdvancedExtensions never produces, so it had no effect. Before: <li><input disabled="disabled" type="checkbox" checked="checked" /> done</li> After: <li>☑ done</li> Fixes #21 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: b721ad5f-9add-4f55-b9c8-7e6d7b0fb3e7
GetMarkdownScore returned 0 as soon as the text contained anything looking like an HTML tag. Markdown may legitimately embed raw HTML, and technical writing routinely mentions tags inside inline code or fenced blocks, so a single occurrence vetoed every other signal. That only mattered when the clipboard carried both text and HTML, which is exactly what editors and browsers publish - so copying Markdown that mentions a tag was classified as rich text, and Ctrl+Enter converted a document that was already Markdown. Ignore markup inside code when checking, and weigh the remainder against the other signals instead of vetoing them. Text that really is HTML still scores low enough to be treated as rich text. Fixes #14 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: b721ad5f-9add-4f55-b9c8-7e6d7b0fb3e7
…nd 'origin/fix/14-markdown-html-detection' into test/23-converter-tests
The conversion code had no tests at all, which is why several of the bugs fixed in this batch shipped: task list checkboxes were emitted as raw <input> markup, nested lists were duplicated, and inline formatting was dropped from list items and table cells. All of those are cheap to catch with a unit test and impossible to catch by eye. Nothing in the converters depends on WinUI or the clipboard, but they lived in the app project, which targets net8.0-windows and cannot be referenced by an ordinary test project. They move to a new md2loop.Core library so they can be tested directly; the app now references it and is otherwise unchanged. The suite has 84 tests across the detector, both converters, and a round-trip class that pushes Markdown through Loop HTML and back, which is what a user actually does when they paste into Loop and copy the result out later. Three tests are marked Skip rather than deleted, one per known open bug (#32, #33, #34). They record the expected behaviour and will start passing when those bugs are fixed. Also adds bin/ and obj/ to .gitignore. They were never listed and the repo only stayed clean because files were staged individually, which is no longer safe with three projects in the tree. Fixes #23 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: b721ad5f-9add-4f55-b9c8-7e6d7b0fb3e7
This was referenced Aug 28, 2026
Markdig records a fenced code block's language as class="language-xxx" on the <code> element. The cleanup regex stripped every class attribute, so the only record of the language was destroyed and a round-trip turned ```csharp back into a bare ```. The HTML to Markdown direction already reads the language-* class correctly, so the fix is limited to not throwing it away: the regex now skips class attributes whose value starts with "language-" and continues to strip everything else, which is what Loop needs. Un-skips the round-trip test that documented the bug. Two tests that asserted the old behaviour are updated: one claimed no class attribute survives at all, and the other expected the language to be lost. Non-language stripping is now covered by a custom container, which renders <div class="warning">. Fixes #34 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: b721ad5f-9add-4f55-b9c8-7e6d7b0fb3e7
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 #23
Why
There were no tests, which is exactly why this batch of bugs shipped in the first place:
<input type="checkbox">markup that Loop does not render (TransformTaskLists is dead code; checkbox output relies on brittle string replacement #21)Every one of those is a two-line unit test and effectively invisible by eye.
Restructuring
None of the conversion code touches WinUI or the clipboard, but it lived in the app project, which targets
net8.0-windows10.0.26100.0and pulls in the Windows App SDK. An ordinary test project cannot reference that.The four converter files move unchanged to a new
md2loop.Corelibrary (net8.0, no UI dependencies). The app references it and is otherwise untouched. Git records all four as pure renames with zero content changes, so this reshuffles nothing behaviourally.Coverage
84 tests, 3 skipped. xUnit.
ClipboardContentDetectorTestsHtmlToMarkdownConverterTestsLoopHtmlConverterTests<input>is never emittedRoundTripTestsThe regression tests are written against the observable symptom rather than the implementation. For example
Convert_NeverEmitsCheckboxInputsasserts the absence of<input, so it will fail again if a future Markdig upgrade changes the markup, which is precisely how #21 slipped through.Two failures worth calling out
The suite found real problems while I was writing it, rather than just confirming what I expected:
Convert_RendersHeadingsAndInlineFormattingasserted<h1>Title</h1>, butUseAdvancedExtensions()enables AutoIdentifiers, so the real output is<h1 id="title">. My assertion was wrong; corrected to match on content.FencedCode_SurvivesARoundTripfailed with```csharpbecoming```. That is not a bad assertion, it is bug Class stripping removes language-* from code blocks, losing the code language #34 reproducing: the blanket class-stripping regex removes thelanguage-*class that carries the code language. Left in place as a passing test documenting current behaviour, with a skipped test alongside it stating the correct behaviour.Known bugs recorded as skipped tests
Rather than delete anything that failed, the three open bugs get a skipped test each that spells out the expected result. They flip to passing when the bug is fixed:
#32- no blank line after a list, so a following block is swallowed#33- whitespace between block elements leaks a leading space#34- class stripping removes the code languageCI and housekeeping
build.ymlgains adotnet teststep, so this actually guardsmasterinstead of only running locally.bin/andobj/added to.gitignore. They were never listed; the repo stayed clean only because files were staged individually. With three projects in the tree that is no longer safe, and staging everything would have committed ~40 build artefacts.Verification
dotnet test -c Release- 84 passed, 0 failed, 3 skipped.dotnet build md2loop -c Release -r win-x64- 0 warnings, 0 errors, confirming the app still builds against the extracted library.