Skip to content

Bug: False positive markdown/no-missing-label-refs on GFM Alerts #294

Open

Description

@midskyey

Environment

ESLint version: 9.12.0
@eslint/markdown version: 6.2.1
Node version: 22.9.0
npm version: 10.8.3
Operating System: macOS 14.7

Which language are you using?

gfm

What did you do?

Configuration
import pluginMd from "@eslint/markdown"

export default [
  // Silly type narrowing for spreading in full-fledged typechecked `eslint.config.js`
  ...[pluginMd.configs?.recommended].filter(Boolean).flat(),
  {
    files: ["**/*.md"],
    language: "markdown/gfm",
  },
]
> [!NOTE]
> Useful information that users should know, even when skimming content.

> [!TIP]
> Helpful advice for doing things better or more easily.

> [!IMPORTANT]
> Key information users need to know to achieve their goal.

> [!WARNING]
> Urgent info that needs immediate user attention to avoid problems.

> [!CAUTION]
> Advises about risks or negative outcomes of certain actions.

Which is being rendered on GH as:

Note

Useful information that users should know, even when skimming content.

Tip

Helpful advice for doing things better or more easily.

Important

Key information users need to know to achieve their goal.

Warning

Urgent info that needs immediate user attention to avoid problems.

Caution

Advises about risks or negative outcomes of certain actions.

What did you expect to happen?

No violations.

What actually happened?

   1:4  error  Label reference '!NOTE' not found       markdown/no-missing-label-refs
   4:4  error  Label reference '!TIP' not found        markdown/no-missing-label-refs
   7:4  error  Label reference '!IMPORTANT' not found  markdown/no-missing-label-refs
  10:4  error  Label reference '!WARNING' not found    markdown/no-missing-label-refs
  13:4  error  Label reference '!CAUTION' not found    markdown/no-missing-label-refs

Link to Minimal Reproducible Example

https://stackblitz.com/edit/118f65b5-5b7b-4190-9fbe-b023b0542a4e?file=package.json

Participation

  • I am willing to submit a pull request for this issue.

Additional comments

More info on GFM Alerts:

Activity

  1. added
    repro:yesIssues with a reproducible example
    and removed
    repro:neededThis issue should include a reproducible example
    on Oct 18, 2024
  2. moved this from Needs Triage to Triaging in Triageon Oct 18, 2024
  3. mdjermanovic commented on Oct 18, 2024

    @mdjermanovic
    Member

    Thanks for the issue! I can reproduce this with @eslint/markdown v6.2.1 (and v6.2.0 as well, so this isn't a regression introduced in v6.2.1).

    I think this should be fixed in the parser as it treats [!NOTE] and others as just plain text, while it should probably be a new node type. @eslint/eslint-team thoughts?

  4. moved this from Triaging to Feedback Needed in Triageon Oct 18, 2024
  5. nzakas commented on Oct 18, 2024

    @nzakas
    Member

    Yes, this is an issue with the parser not supporting GitHub alerts. It needs to be fixed there. Opened: syntax-tree/mdast-util-gfm#2

  6. moved this from Feedback Needed to Blocked in Triageon Oct 18, 2024
  7. nzakas commented on Oct 18, 2024

    @nzakas
    Member

    So it looks like alerts are not actually part of GFM and are just an HTML transform:
    syntax-tree/mdast-util-gfm#2 (comment)

    By "HTML transform", they mean that the parsing of the Markdown isn't any different, it's just the way that the Markdown is interpreted while transforming to HTML that changes.

    Here's the GFM spec:
    https://github.github.com/gfm/

    We have a couple options for what to do here:

    1. We could create a plugin that generates a separate AST for this syntax to make it more easily identifiable in the AST.
    2. We could add an option to the rule that filters out known GitHub alert labels.
  8. JoshuaKGoldberg commented on Oct 19, 2024

    @JoshuaKGoldberg
    Contributor

    Agreed on 1, this feels like a plugin to me. GitHub alert labels are just one example of a nonstandard extension to GFM. Folks writing .md for other platforms won't want them.

  9. mdjermanovic commented on Oct 20, 2024

    @mdjermanovic
    Member
    1. We could create a plugin that generates a separate AST for this syntax to make it more easily identifiable in the AST.

    We would then always use this plugin when parsing in gfm mode? That seems like a nice solution, though our parser would be doing something unique because other markdown parsers treat this as plain text, so that might be surprising to rule authors?

  10. nzakas commented on Oct 21, 2024

    @nzakas
    Member

    We would then always use this plugin when parsing in gfm mode? That seems like a nice solution, though our parser would be doing something unique because other markdown parsers treat this as plain text, so that might be surprising to rule authors?

    Yes. I think we should maintain the sanctity of what "GFM" means and ensure it matches the spec by default. If we want to create an AST representation of alerts, then I think that should be opt-in as a language option for markdown/gfm.

  11. 7 remaining items

  12. nzakas commented on Apr 29, 2025

    @nzakas
    Member

    @lumirlumir thanks for the suggestion. I'm not sure that makes sense because block quotes don't really have defined labels in markdown (spec: https://spec.commonmark.org/0.31.2/#block-quotes). We'd just be overlaying a GitHub-specific meaning on top of this, which I don't think is the right approach. I also think people expect that in GFM this type of behavior would be automatic, rather than requiring all users to add this configuration.

  13. lumirlumir commented on Jun 26, 2025

    @lumirlumir
    Member

    I'm back to revisit this issue. Since this bug currently requires certain files in @eslint/markdown to include eslint-disable directives, I think it would be nicer to decide how we want to proceed with this issue.

    Since eslint/rewrite#221 hasn’t progressed, I considered some alternatives — but ultimately, I think there may be only one viable solution.

    ✅ Solution: Add an allowLabels option (as suggested in the comment above)

    The no-missing-label-refs rule is based on Markdownlint’s MD052. That rule includes an ignored_labels option, which behaves similarly to what was suggested in the earlier comment.

    Image

    This approach would be intuitive for users and easier to implement than the alternatives.

    Since many of the rules in @eslint/markdown follow the implementations of Markdownlint and Remarklint, I think it's a good approach that allows users to align their rules with existing Markdown linters.

    ⚠️ Alternative: Add a custom MDAST plugin that understands GitHub Alert Syntax

    I previously shared a discussion about this, but the consensus was that this syntax is a purely HTML-based transform.

    Even when reviewing the GFM spec, GitHub Alert blocks are not officially recognized, since they are not part of the specification.

    Although GitHub supports this custom Alert Syntax, it hasn’t been incorporated into the GFM spec (which hasn’t been updated since 2019 😅). Supporting it via a custom plugin could introduce inconsistencies, as it would be deviating from standardized behavior.


    So in conclusion, I'm proposing to add an allowLabels option, and I'd like to hear other team members' thoughts on this approach — @eslint/eslint-team.

    Once we reach a consensus on how to proceed with this issue, I'd be happy to take a look at it.

  14. JoshuaKGoldberg commented on Jun 26, 2025

    @JoshuaKGoldberg
    Contributor

    I don't think the ideal solution here is to add anything rule-specific. markdown/no-missing-label-refs might be the only rule impacted by this issue now, but it's likely there'll be other rules later on that interact with these kinds of nodes. I think the right solution would be to add a way to let users opt into the alternate parsing mode. Perhaps a parserOptions option?

    It's kind of unfortunate that the current implementation in userland for the GitHub alerts is an html transform, https://github.com/orgs/syntax-tree/discussions/144#discussioncomment-12652504 -> rehype-github-alert. But:

    Although GitHub supports this custom Alert Syntax, it hasn’t been incorporated into the GFM spec (which hasn’t been updated since 2019 😅). Supporting it via a custom plugin could introduce inconsistencies, as it would be deviating from standardized behavior.

    GitHub doesn't change their Markdown parsing very often. And as noted, the spec changes even less often. This is relatively pretty small addition to the spec (compared to, say, the TypeScript types work in core). I think writing that custom plugin would be the right way to go.

    If the custom plugin is just absolutely not doable, I suppose the allowLabels option would be a reasonable fallback. But it's kind of odd to add an option only for one use case that has a different "ideal" solution.

  15. nzakas commented on Jun 27, 2025

    @nzakas
    Member

    I agree with @JoshuaKGoldberg -- I don't think this is something that should be handled on a rule-by-rule basis, we should have something that just works. That's why I think the best approach is creating a plugin that creates a new AST node type for these alerts. That way, they're kept out of the logic that shouldn't relate to them.

    At this point, I'd say the new AST node should be the default and there's no need to provide an opt-out unless users experience problems.

  16. lumirlumir commented on Jun 28, 2025

    @lumirlumir
    Member

    Ah, I truly understood what the team aims for 👍 Thank you all for the detailed comments.

    Then, maybe creating the spec for how to treat GitHub Alert syntax, and apply it by creating custom mdast-util-gfm-alert or similar would make sense?

  17. nzakas commented on Jun 30, 2025

    @nzakas
    Member

    Yes, it would be great for someone to propose something. 😄 We probably don't want to get into having a separate package unless we get a request for it.

  18. lumirlumir commented on Jun 30, 2025

    @lumirlumir
    Member

    Sounds good to me 👍 If it's okay, I’d be happy to take a look at this.

  19. nzakas commented on Jul 2, 2025

    @nzakas
    Member

    Sounds good. Just to be clear: we'd still like you to describe an idea on this issue before submitting a PR to make sure everyone is aligned on the approach.

  20. lumirlumir commented on Jul 3, 2025

    @lumirlumir
    Member

    @nzakas I'll make sure to create an RFC document before proceeding, just like we did in #230.

  21. moved this from Blocked to Waiting for RFC in Triageon Jul 3, 2025
  22. lumirlumir commented on Aug 19, 2025

    @lumirlumir
    Member

    RFC has been opened: eslint/rfcs#138

  23. moved this from Waiting for RFC to RFC Opened in Triageon Nov 2, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

  • Status
    RFC Opened

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions