Skip to content

Add hook to mask input for em/strong processing in extension#3749

Merged
UziTech merged 6 commits intomarkedjs:masterfrom
jonatanschroeder:masked-src-extension
Sep 14, 2025
Merged

Add hook to mask input for em/strong processing in extension#3749
UziTech merged 6 commits intomarkedjs:masterfrom
jonatanschroeder:masked-src-extension

Conversation

@jonatanschroeder
Copy link
Contributor

Marked version: 16.2.0

Markdown flavor: n/a

Description

Adds a hook that allows extensions to mask the source in em/strong input so that constructs in extensions that are expected to take priority over em/strong can ensure the em/strong termination is not considered inside those constructs.

I chose to add a new "hooks" list under the extension list element. If the maintainers decide it's better to move this hook to a different location let me know and I can change it. I'm also open to changes in naming.

Contributor

  • Test(s) exist to ensure functionality and minimize regression (if no tests added, list tests covering this PR); or,
  • no tests required for this PR.
  • If submitting new feature, it has been documented in the appropriate places.

Committer

In most cases, this should be a different person than the contributor.

@vercel
Copy link

vercel bot commented Aug 25, 2025

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

Project Deployment Preview Comments Updated (UTC)
marked-website Ready Ready Preview Comment Sep 1, 2025 1:42pm

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.

Summary of Changes

Hello @jonatanschroeder, 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 introduces a new emStrongMask hook for marked.js extensions, addressing an issue where custom extension content could be misinterpreted as Markdown emphasis or strong delimiters. This enhancement allows extensions to preprocess their input, effectively "masking" specific characters to prevent unintended parsing conflicts, thereby improving the robustness and flexibility of custom Markdown processing.

Highlights

  • New Extension Hook: Introduces hooks.emStrongMask within the extension API, enabling extensions to define a function that masks parts of the source string to prevent misinterpretation of em/strong delimiters.
  • Improved Parsing Logic: The lexer now applies these masking functions from registered extensions before processing emphasis and strong formatting, ensuring that extension-specific syntax is correctly handled without interference.
  • API and Documentation Updates: The core MarkedOptions and TokenizerExtension interfaces are updated to support the new hook, and comprehensive documentation has been added to guide extension developers.
  • Dedicated Unit Test: A new unit test verifies that the emStrongMask hook correctly prevents em/strong termination characters from being misinterpreted within masked content.
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 in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.

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 issue 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 introduces a new emStrongMask hook, allowing extensions to prevent parts of markdown from being interpreted as emphasis or strong text. This is a valuable addition for creating more complex inline extensions. The implementation is solid, with new type definitions, documentation, and a test case. I have one suggestion regarding the registration of these new hooks to ensure consistency with the existing extension mechanism in marked.

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.

I think we should add it to the hooks in https://github.com/markedjs/marked/blob/master/src/Hooks.ts https://marked.js.org/using_pro#hooks

If a marked extension has multiple tokenizer extensions I don't think each tokenizer extension needs their own masking function.

@jonatanschroeder
Copy link
Contributor Author

jonatanschroeder commented Aug 30, 2025

I think we should add it to the hooks in https://github.com/markedjs/marked/blob/master/src/Hooks.ts https://marked.js.org/using_pro#hooks

If a marked extension has multiple tokenizer extensions I don't think each tokenizer extension needs their own masking function.

Understood, I have changed it to use the regular hooks object.

One minor note: contrary to other hooks, this new hook cannot be an async function. I don't think this is a problem, I just want to check if you believe that there should be a note about it in the docs or not.

@UziTech
Copy link
Member

UziTech commented Aug 31, 2025

I think that is fine. The provideLexer and provideParser hooks are also not async.

@UziTech
Copy link
Member

UziTech commented Aug 31, 2025

/gemini review

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 introduces a new emStrongMask hook, which is a valuable addition for extension authors to prevent conflicts with emphasis and strong syntax. The implementation is well-executed, with corresponding updates to documentation and tests. My review includes a suggestion to improve the clarity of the documentation for the new hook to ensure users can easily understand its behavior.

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.

LGTM. Thanks for adding this. 💯

@jonatanschroeder jonatanschroeder marked this pull request as draft August 31, 2025 19:02
@jonatanschroeder
Copy link
Contributor Author

Note: as I was testing this further, even though the function is not expected to be async, the fact that it's listed in passThroughHooks means that, if async: true then the passthrough function will return a promise instead, which causes a problem in the code. I have converted the PR to draft so I have a chance to create a proper passthrough handling of this code.

@jonatanschroeder
Copy link
Contributor Author

Should be good now. Let me know if you'd like me to create a test case for the scenario above.

@UziTech
Copy link
Member

UziTech commented Aug 31, 2025

Nice catch! Ya if you could add a test that is essentially the same as the one you added but with async: true that would work.

@jonatanschroeder
Copy link
Contributor Author

Nice catch! Ya if you could add a test that is essentially the same as the one you added but with async: true that would work.

Done in 3c1a7c1. I also added a test for the passthrough process to ensure multiple hooks are called in sequence.

@UziTech
Copy link
Member

UziTech commented Sep 13, 2025

@styfle @calculuschild any objections to merging this?

@calculuschild
Copy link
Contributor

No objection on its own. I am ok to mgerge this.

My only thought is perhaps this is too narrow, and maybe there ought to be a more universal "ignore XYZ token type when inside this extension" feature.

Referring back to my suggestion earlier about letting an extension point to other tokens that it should be able to interrupt:
#3435, though masking and interruptting are not quite the same behavior.

@UziTech
Copy link
Member

UziTech commented Sep 14, 2025

Ya I think that will be harder than this since it requires a check before every token. I tried in #3594 (comment) but couldn't get it to work without slowing down marked a significant amount.

@UziTech UziTech merged commit cd2b5f4 into markedjs:master Sep 14, 2025
8 checks passed
github-actions bot pushed a commit that referenced this pull request Sep 14, 2025
# [16.3.0](v16.2.1...v16.3.0) (2025-09-14)

### Features

* add emStrongMask hook ([#3749](#3749)) ([cd2b5f4](cd2b5f4))
@jonatanschroeder jonatanschroeder deleted the masked-src-extension branch September 14, 2025 14:53
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.

Add means to ignore/mask source for termination characters in extension

3 participants