Skip to content

fix: prevent single-tilde strikethrough false positives#3910

Open
diadorer wants to merge 3 commits intomarkedjs:masterfrom
diadorer:fix/single-tilde-strikethrough-false-positive
Open

fix: prevent single-tilde strikethrough false positives#3910
diadorer wants to merge 3 commits intomarkedjs:masterfrom
diadorer:fix/single-tilde-strikethrough-false-positive

Conversation

@diadorer
Copy link

Summary

  • Fix single-tilde (~) strikethrough incorrectly matching when tildes are used as "approximately" (e.g. ~40 results)
  • Add test case for the fix

Problem

Text like Each of the ~40 results: **~150 tokens** was incorrectly parsed as strikethrough because the parser matched the first ~ (before 40) as an opening delimiter and the second ~ (before 150) as a closing delimiter.

Root cause

This happens because of the GFM flanking delimiter rules. Here is a step-by-step breakdown for Each of the ~40 results: **~150 tokens**:

  1. The first tilde (~40): followed by an alphanumeric character (4), not preceded by whitespace — valid left-flanking (opening) delimiter. The parser adds it to the stack and starts looking for a closing tilde.

  2. The first asterisks (**~): preceded by a space, followed by punctuation (~) — valid left-flanking delimiter for strong emphasis.

  3. The second tilde (**~150): to close the strikethrough, this tilde must be a valid right-flanking delimiter. Per the GFM spec, a right-flanking delimiter cannot be preceded by a punctuation character unless it is also followed by whitespace or punctuation. This tilde is preceded by * (punctuation) and followed by 1 (alphanumeric) — it fails the right-flanking test and is not a valid closing delimiter.

  4. The final asterisks (tokens**): preceded by a letter (s) and at end of string — valid right-flanking delimiter, closing the bold emphasis.

Since the second tilde can never close the first, the entire strikethrough match is invalid.

Fix

When processing a single-tilde strikethrough match, skip it if the closing ~ is immediately followed by an alphanumeric character, as this indicates it fails the GFM right-flanking delimiter rules.

Test plan

  • Added test case in test/specs/new/del_flanking.md / .html
  • All existing tests pass

When a closing single ~ is followed by an alphanumeric character, skip
the strikethrough match since it fails GFM right-flanking delimiter
rules. This prevents text like `~125 GeV ... **~173 GeV**` from being
incorrectly parsed as strikethrough.
@vercel
Copy link

vercel bot commented Mar 10, 2026

Someone is attempting to deploy a commit to the MarkedJS Team on Vercel.

A member of the Team first needs to authorize it.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request resolves an issue where the Markdown parser incorrectly applied strikethrough formatting to text containing single tildes used for approximation. The change introduces a specific check during tokenization to ensure that single tilde delimiters adhere to GitHub Flavored Markdown (GFM) right-flanking rules, thereby preventing unintended formatting and improving parsing accuracy.

Highlights

  • Strikethrough Parsing Fix: Implemented a fix to prevent single-tilde (~) strikethrough from incorrectly matching when tildes are used as "approximately" (e.g., ~40 results), addressing false positives based on GFM flanking delimiter rules.
  • Test Coverage: Added a new test case to validate the corrected parsing behavior for single-tilde strikethrough scenarios.
Changelog
  • src/Tokenizer.ts
    • Added a conditional check within the del token creation logic to skip single-tilde strikethrough matches if the closing tilde is immediately followed by an alphanumeric character, aligning with GFM right-flanking delimiter rules.
  • test/specs/new/del_flanking.html
    • Appended a new paragraph to the expected HTML output, demonstrating the corrected parsing of text with single tildes.
  • test/specs/new/del_flanking.md
    • Appended a new line to the Markdown input, providing a test case for the scenario where single tildes should not trigger strikethrough.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request addresses a false positive in single-tilde strikethrough parsing, where tildes used to denote approximation (e.g., ~40) were incorrectly identified as strikethrough delimiters. The fix correctly implements a check based on GFM's right-flanking delimiter rules, and a corresponding test case is added to prevent regressions. The approach is sound, and I have one suggestion to improve the implementation for better Unicode support.

@vercel
Copy link

vercel bot commented Mar 11, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
marked-website Ready Ready Preview, Comment Mar 11, 2026 3:02pm

Request Review

Copy link
Member

@UziTech UziTech left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like this breaks some strikethrough as well

For example: ~1 a~2

marked follows GFM: 1 a2
this pr: ~1 a~2

It looks like we may need to check that the character to the left is not alphanumeric.

@diadorer
Copy link
Author

Hey Tony!
Thanks for pointing this out — fixed the case.
Btw I really like the idea of npx tonybrix!

@LouisTrezzini
Copy link

Great fix!

I found this PR because we are seeing a similar issue with another edge case worth considering: tildes appearing in both an approximation prefix and inside a URL text fragment (the #:~:text= syntax used by scroll-to-text links):

~Approx date: Event description. [](https://example.com/article/#:~:text=Some%20text,more%20text.)

Here the leading ~ is an approximation marker, and the URL contains #:~:text= (the Text Fragment anchor syntax). It would be great if this were to be addressed in the same PR and verified via a new test case that this doesn't get caught by the strikethrough parser

Hopefully that's helpful. I can also try to open a separate PR if that would be more convenient

@UziTech
Copy link
Member

UziTech commented Mar 11, 2026

@LouisTrezzini you can run markdown against this PR with the demo link below to see if it fixes your use case as well.

https://marked-website-git-fork-diadorer-fix-single-til-f83acb-markedjs.vercel.app/demo/

@LouisTrezzini
Copy link

Thanks, this works! Turns out the fix in 17.0.2 was sufficient, we were still on 17.0.0.

It might still be worth adding a test case for this, but leaving that to your discretion

Thanks again for the help and quick reply

@diadorer diadorer requested a review from UziTech March 11, 2026 20:36
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.

3 participants