Skip to content

Generalise markdownlint directive detection#145

Merged
leynos merged 2 commits intomainfrom
a2sx7j-codex/add-test-for-markdownlint-comment-directives
Jul 30, 2025
Merged

Generalise markdownlint directive detection#145
leynos merged 2 commits intomainfrom
a2sx7j-codex/add-test-for-markdownlint-comment-directives

Conversation

@leynos
Copy link
Copy Markdown
Owner

@leynos leynos commented Jul 29, 2025

Summary

  • add a regex helper for recognising markdownlint directives
  • skip wrapping for any line matched by the helper
  • move directive tests to a dedicated module
  • check multiple directive variants with indentation
  • document helper usage

Testing

  • make lint
  • make test

https://chatgpt.com/codex/tasks/task_e_68888eec3afc8322a17eab06cba6d228

Summary by Sourcery

Introduce detection of markdownlint directives in the wrapping logic to prevent them from being wrapped, and add a regex helper along with dedicated tests for directive handling

New Features:

  • Add a regex helper and is_markdownlint_directive function to detect markdownlint directives
  • Skip wrapping for lines matching markdownlint directives to preserve them unchanged

Enhancements:

  • Support multiple directive variants with optional rule codes and indentation in detection

Tests:

  • Add dedicated tests for various markdownlint directive variants, invalid cases, and ensure regular comments still wrap

@sourcery-ai
Copy link
Copy Markdown
Contributor

sourcery-ai Bot commented Jul 29, 2025

Reviewer's Guide

Implements generic detection of markdownlint directives by introducing a regex-based helper, integrating it into text wrapping logic to preserve directive lines, and organizing related tests into a dedicated module.

Class diagram for new markdownlint directive detection helper

classDiagram
    class wrap {
        +is_markdownlint_directive(line: &str) bool
    }
    class MARKDOWNLINT_DIRECTIVE_RE {
        <<static Regex>>
    }
    wrap --> MARKDOWNLINT_DIRECTIVE_RE : uses
Loading

Flow diagram for text wrapping with markdownlint directive detection

flowchart TD
    A[Start wrap_text] --> B{Is line a code fence?}
    B -- Yes --> C[Flush paragraph, push line, continue]
    B -- No --> D{Is line a markdownlint directive?}
    D -- Yes --> E[Flush paragraph, push line, continue]
    D -- No --> F{Is line empty?}
    F -- Yes --> G[Flush paragraph, continue]
    F -- No --> H[Buffer line for wrapping]
Loading

File-Level Changes

Change Details Files
Introduce markdownlint directive recognition via regex helper
  • Add MARKDOWNLINT_DIRECTIVE_RE lazy static regex
  • Implement is_markdownlint_directive() function
src/wrap.rs
Skip wrapping for lines matching markdownlint directives
  • Insert directive check in wrap_text before wrapping logic
  • Flush paragraph and preserve directive lines as-is
src/wrap.rs
Extract directive tests into dedicated module
  • Create tests/markdownlint.rs with focused tests
  • Cover various directive forms, indentation, and invalid cases
tests/markdownlint.rs
Document markdownlint directive helper usage
  • Add doc comments for MARKDOWNLINT_DIRECTIVE_RE
  • Explain supported directive variants
src/wrap.rs

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jul 29, 2025

Summary by CodeRabbit

  • New Features

    • Markdownlint directive comments (such as <!-- markdownlint-disable-next-line -->) are now detected and preserved on their own lines during text wrapping.
  • Tests

    • Added tests to ensure markdownlint directives are handled correctly and remain unwrapped, while regular comments and malformed directives are wrapped as usual.

Walkthrough

Introduce detection and preservation of markdownlint directive comment lines within the text wrapping logic. Add a regex-based function to identify these directives, ensuring they are output verbatim and break paragraphs. Expand test coverage to verify correct handling of various directive forms and confirm regular comments are still wrapped as usual.

Changes

Cohort / File(s) Change Summary
Markdownlint Directive Handling
src/wrap.rs
Add static regex and is_markdownlint_directive function to detect markdownlint directives. Update wrap_text to flush paragraph buffer and output directive lines as-is, treating them as paragraph breaks.
Directive Preservation & Wrapping Tests
tests/markdownlint.rs
Add comprehensive tests to ensure markdownlint directives are preserved on their own lines, not wrapped or merged, and that malformed or non-directive comments are wrapped normally. Cover multiple directive forms, casing, and edge cases.

Sequence Diagram(s)

sequenceDiagram
    participant InputLine as Input Line
    participant WrapText as wrap_text()
    participant Output as Output

    InputLine->>WrapText: Provide next line
    WrapText->>WrapText: Check if line is markdownlint directive
    alt Is directive
        WrapText->>Output: Flush buffer, output directive as-is
        WrapText->>WrapText: Clear buffer and indent
    else Not a directive
        WrapText->>WrapText: Continue normal wrapping logic
    end
    WrapText->>Output: Output wrapped lines
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~15 minutes

Possibly related PRs

Poem

In markdown’s land where comments dwell,
Directives now are handled well—
Regex sharp, detection keen,
They break the flow, remain unseen.
Wrapped lines behave, tests hold tight,
Markdownlint stands bold and right!
📝✨

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch a2sx7j-codex/add-test-for-markdownlint-comment-directives

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Copy Markdown
Contributor

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

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

Hey @leynos - I've reviewed your changes and found some issues that need to be addressed.

  • Consider limiting the visibility of is_markdownlint_directive to pub(crate) (or making it private) if it’s only used internally to avoid exposing it in the public API.
  • You can drop the trim() in is_markdownlint_directive since the regex already allows for leading/trailing whitespace, which also lets you preserve the original indentation.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- Consider limiting the visibility of is_markdownlint_directive to pub(crate) (or making it private) if it’s only used internally to avoid exposing it in the public API.
- You can drop the trim() in is_markdownlint_directive since the regex already allows for leading/trailing whitespace, which also lets you preserve the original indentation.

## Individual Comments

### Comment 1
<location> `src/wrap.rs:29` </location>
<code_context>
+/// - `<!-- markdownlint-enable -->`
+/// - `<!-- markdownlint-disable-line MD001 MD005 -->`
+/// - `<!-- markdownlint-disable-next-line MD001 -->`
+static MARKDOWNLINT_DIRECTIVE_RE: std::sync::LazyLock<Regex> = std::sync::LazyLock::new(|| {
+    Regex::new(
+            r"(?i)^\s*<!--\s*markdownlint-(?:disable|enable|disable-line|disable-next-line)(?:\s+MD\d+)*\s*-->\s*$",
+        )
+        .expect("valid markdownlint regex")
+});
+
 /// Markdown token emitted by [`tokenize_markdown`].
</code_context>

<issue_to_address>
The regex for markdownlint directives may not match all valid rule names.

The regex currently only matches rule names like MD\d+, but markdownlint supports custom and plugin rule names (e.g., MD013/line-length). Please update the pattern to support these cases, or document this limitation if it's intentional.
</issue_to_address>

<suggested_fix>
<<<<<<< SEARCH
/// Matches `markdownlint` comment directives.
///
/// The regex is case-insensitive and supports these forms with optional rule
/// names:
/// - `<!-- markdownlint-disable -->`
/// - `<!-- markdownlint-enable -->`
/// - `<!-- markdownlint-disable-line MD001 MD005 -->`
/// - `<!-- markdownlint-disable-next-line MD001 -->`
static MARKDOWNLINT_DIRECTIVE_RE: std::sync::LazyLock<Regex> = std::sync::LazyLock::new(|| {
    Regex::new(
            r"(?i)^\s*<!--\s*markdownlint-(?:disable|enable|disable-line|disable-next-line)(?:\s+MD\d+)*\s*-->\s*$",
        )
        .expect("valid markdownlint regex")
});
=======
/// Matches `markdownlint` comment directives.
///
/// The regex is case-insensitive and supports these forms with optional rule
/// names (including custom and plugin rules, e.g. `MD013/line-length`):
/// - `<!-- markdownlint-disable -->`
/// - `<!-- markdownlint-enable -->`
/// - `<!-- markdownlint-disable-line MD001 MD005 MD013/line-length custom-rule -->`
/// - `<!-- markdownlint-disable-next-line MD001 plugin/rule-name -->`
static MARKDOWNLINT_DIRECTIVE_RE: std::sync::LazyLock<Regex> = std::sync::LazyLock::new(|| {
    Regex::new(
            r"(?i)^\s*<!--\s*markdownlint-(?:disable|enable|disable-line|disable-next-line)(?:\s+[A-Za-z0-9_\-/]+)*\s*-->\s*$",
        )
        .expect("valid markdownlint regex")
});
>>>>>>> REPLACE

</suggested_fix>

### Comment 2
<location> `tests/markdownlint.rs:63` </location>
<code_context>
+
+/// Comments that resemble directives but are invalid should wrap normally.
+#[test]
+fn test_non_directive_comment_wraps() {
+    let input = lines_vec!["Intro line.", "<!-- markdowndisable -->"];
+    let output = process_stream(&input);
+    assert_eq!(output, lines_vec!["Intro line. <!-- markdowndisable -->"]);
+}
</code_context>

<issue_to_address>
Consider adding tests for malformed or partially correct directives.

Adding tests for nearly correct but invalid directives (e.g., missing closing tag, extra text, or typos) will help verify the regex handles these cases correctly and avoids false matches.
</issue_to_address>

<suggested_fix>
<<<<<<< SEARCH
/// Comments that resemble directives but are invalid should wrap normally.
#[test]
fn test_non_directive_comment_wraps() {
    let input = lines_vec!["Intro line.", "<!-- markdowndisable -->"];
    let output = process_stream(&input);
    assert_eq!(output, lines_vec!["Intro line. <!-- markdowndisable -->"]);
}
=======
/// Comments that resemble directives but are invalid should wrap normally.
#[test]
fn test_non_directive_comment_wraps() {
    let input = lines_vec!["Intro line.", "<!-- markdowndisable -->"];
    let output = process_stream(&input);
    assert_eq!(output, lines_vec!["Intro line. <!-- markdowndisable -->"]);
}

/// Malformed or partially correct directive comments should wrap normally.
#[test]
fn test_malformed_directive_missing_closing() {
    let input = lines_vec!["Text before.", "<!-- markdownlint-disable"];
    let output = process_stream(&input);
    assert_eq!(output, lines_vec!["Text before. <!-- markdownlint-disable"]);
}

#[test]
fn test_malformed_directive_extra_text() {
    let input = lines_vec!["Text before.", "<!-- markdownlint-disable extra -->"];
    let output = process_stream(&input);
    assert_eq!(output, lines_vec!["Text before. <!-- markdownlint-disable extra -->"]);
}

#[test]
fn test_malformed_directive_typo() {
    let input = lines_vec!["Text before.", "<!-- markdownlnt-disable-line MD001 -->"];
    let output = process_stream(&input);
    assert_eq!(output, lines_vec!["Text before. <!-- markdownlnt-disable-line MD001 -->"]);
}

#[test]
fn test_malformed_directive_incomplete_tag() {
    let input = lines_vec!["Text before.", "<!-- markdownlint-disable-line MD001 "];
    let output = process_stream(&input);
    assert_eq!(output, lines_vec!["Text before. <!-- markdownlint-disable-line MD001 "]);
}
>>>>>>> REPLACE

</suggested_fix>

### Comment 3
<location> `tests/markdownlint.rs:15` </location>
<code_context>
+
+/// The disable-next-line directive must remain intact after wrapping.
+#[test]
+fn test_markdownlint_disable_next_line_preserved() {
+    let input = lines_vec![
+        "[roadmap](./roadmap.md) and expands on the design ideas described in",
+        "<!--  markdownlint-disable-next-line  MD013  -->",
+    ];
+    let output = process_stream(&input);
+    assert_eq!(output, input);
+}
+
</code_context>

<issue_to_address>
Test could include a case where the directive is not at the end of the input.

Please add a test where the markdownlint directive appears in the middle of the input to verify it is preserved in all positions.
</issue_to_address>

<suggested_fix>
<<<<<<< SEARCH
/// The disable-next-line directive must remain intact after wrapping.
#[test]
fn test_markdownlint_disable_next_line_preserved() {
    let input = lines_vec![
        "[roadmap](./roadmap.md) and expands on the design ideas described in",
        "<!--  markdownlint-disable-next-line  MD013  -->",
    ];
    let output = process_stream(&input);
    assert_eq!(output, input);
}
=======
/// The disable-next-line directive must remain intact after wrapping.
#[test]
fn test_markdownlint_disable_next_line_preserved() {
    let input = lines_vec![
        "[roadmap](./roadmap.md) and expands on the design ideas described in",
        "<!--  markdownlint-disable-next-line  MD013  -->",
    ];
    let output = process_stream(&input);
    assert_eq!(output, input);
}

/// The disable-next-line directive must remain intact when in the middle of the input.
#[test]
fn test_markdownlint_disable_next_line_preserved_middle() {
    let input = lines_vec![
        "This is the first line.",
        "<!--  markdownlint-disable-next-line  MD013  -->",
        "This is the third line.",
    ];
    let output = process_stream(&input);
    assert_eq!(output, input);
}
>>>>>>> REPLACE

</suggested_fix>

### Comment 4
<location> `src/wrap.rs:29` </location>
<code_context>
+/// - `<!-- markdownlint-enable -->`
+/// - `<!-- markdownlint-disable-line MD001 MD005 -->`
+/// - `<!-- markdownlint-disable-next-line MD001 -->`
+static MARKDOWNLINT_DIRECTIVE_RE: std::sync::LazyLock<Regex> = std::sync::LazyLock::new(|| {
+    Regex::new(
+            r"(?i)^\s*<!--\s*markdownlint-(?:disable|enable|disable-line|disable-next-line)(?:\s+MD\d+)*\s*-->\s*$",
</code_context>

<issue_to_address>
The module does not begin with a `//!` comment as required by the review instructions.

Please add a `//!` module-level comment at the very top of this file to describe its purpose, as per the project guidelines.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread src/wrap.rs
Comment thread tests/markdownlint.rs
Comment thread tests/markdownlint.rs
Comment thread src/wrap.rs
@leynos leynos force-pushed the a2sx7j-codex/add-test-for-markdownlint-comment-directives branch from a0b5ee8 to 5d23b5d Compare July 30, 2025 00:50
@github-actions
Copy link
Copy Markdown

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jul 30, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1d762b6 and 5d23b5d.

📒 Files selected for processing (2)
  • src/wrap.rs (3 hunks)
  • tests/markdownlint.rs (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.rs

⚙️ CodeRabbit Configuration File

**/*.rs: * Seek to keep the cyclomatic complexity of functions no more than 12.

  • Adhere to single responsibility and CQRS

  • Place function attributes after doc comments.

  • Do not use return in single-line functions.

  • Move conditionals with >2 branches into a predicate function.

  • Avoid unsafe unless absolutely necessary.

  • Every module must begin with a //! doc comment that explains the module's purpose and utility.

  • Comments and docs must follow en-GB-oxendict (-ize / -our) spelling and grammar

  • Lints must not be silenced except as a last resort.

    • #[allow] is forbidden.
    • Only narrowly scoped #[expect(lint, reason = "...")] is allowed.
    • No lint groups, no blanket or file-wide suppression.
    • Include FIXME: with link if a fix is expected.
  • Use rstest fixtures for shared setup and to avoid repetition between tests.

  • Replace duplicated tests with #[rstest(...)] parameterised cases.

  • Prefer mockall for mocks/stubs.

  • Prefer .expect() over .unwrap()

  • Ensure that any API or behavioural changes are reflected in the documentation in docs/

  • Ensure that any completed roadmap steps are recorded in the appropriate roadmap in docs/

  • Files must not exceed 400 lines in length

    • Large modules must be decomposed
    • Long match statements or dispatch tables should be decomposed by domain and collocated with targets
    • Large blocks of inline data (e.g., test fixtures, constants or templates) must be moved to external files and inlined at compile-time or loaded at run-time.

Files:

  • tests/markdownlint.rs
  • src/wrap.rs
🧬 Code Graph Analysis (1)
tests/markdownlint.rs (1)
src/process.rs (1)
  • process_stream (206-214)
🔇 Additional comments (6)
src/wrap.rs (3)

21-35: Excellent regex implementation and documentation.

The regex correctly matches markdownlint directives with case-insensitive matching and supports optional rule names including plugin-style names. The documentation clearly explains the supported formats with helpful examples.


325-327: Clean helper function implementation.

The function provides a clear API for checking markdownlint directives. The pub(crate) visibility is appropriate for internal use within the crate.


444-450: Proper integration of markdownlint directive handling.

The implementation correctly flushes the paragraph buffer, clears state, and outputs the directive line verbatim. This ensures markdownlint directives remain isolated and unmodified during text wrapping.

tests/markdownlint.rs (3)

1-5: Clear module documentation.

The module doc comment properly explains the purpose and follows the required //! format from the coding guidelines.


60-71: Excellent use of parameterised testing.

The #[rstest] parameterised test efficiently covers multiple directive variants including case variations and indentation. This follows the coding guideline to use rstest for avoiding test duplication.


73-117: Comprehensive malformed directive testing.

The tests properly verify that invalid or malformed directives are wrapped normally rather than preserved. This ensures the regex doesn't have false positives and maintains expected wrapping behaviour for non-directive comments.

Comment thread tests/markdownlint.rs
Comment on lines +7 to +11
use mdtablefix::process_stream;

#[macro_use]
mod prelude;
use prelude::*;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Consider consolidating imports.

The separate import of mdtablefix::process_stream and the macro use could be organised more cleanly.

Apply this diff to consolidate the imports:

-use mdtablefix::process_stream;
-
-#[macro_use]
-mod prelude;
-use prelude::*;
+#[macro_use]
+mod prelude;
+
+use mdtablefix::process_stream;
+use prelude::*;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
use mdtablefix::process_stream;
#[macro_use]
mod prelude;
use prelude::*;
#[macro_use]
mod prelude;
use mdtablefix::process_stream;
use prelude::*;
🤖 Prompt for AI Agents
In tests/markdownlint.rs around lines 7 to 11, the imports are split between a
macro use declaration and a separate import of mdtablefix::process_stream.
Consolidate these imports by combining the macro use and the process_stream
import into a single organized block at the top of the file, improving clarity
and reducing redundancy.

@leynos leynos merged commit 4c26fca into main Jul 30, 2025
2 checks passed
@leynos leynos deleted the a2sx7j-codex/add-test-for-markdownlint-comment-directives branch July 30, 2025 01:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant