[GH-ISSUE #42] Add support for custom rules #34

Closed
opened 2026-03-03 01:23:11 +03:00 by kerem · 6 comments
Owner

Originally created by @miljan-aleksic on GitHub (Jan 13, 2017).
Original GitHub issue: https://github.com/DavidAnson/markdownlint/issues/42

Hi, nice tool! Thanks.

I would like to add my own custom rules, similar to rules param object, declare custom rules in the config. Would you consider?

Originally created by @miljan-aleksic on GitHub (Jan 13, 2017). Original GitHub issue: https://github.com/DavidAnson/markdownlint/issues/42 Hi, nice tool! Thanks. I would like to add my own custom rules, similar to rules param object, declare custom rules in the config. Would you consider?
kerem 2026-03-03 01:23:11 +03:00
Author
Owner

@DavidAnson commented on GitHub (Jan 14, 2017):

Thanks!

The topic of custom rules was raised before in issue #39 - please have a look at my comments there for more. Briefly, this is an eventual goal, but there are a number of questions I need to answer before starting work.

In the meantime, if you list out the rules you have in mind, they might be things I think are broadly applicable and worth adding to the core set of rules myself.

<!-- gh-comment-id:272601379 --> @DavidAnson commented on GitHub (Jan 14, 2017): Thanks! The topic of custom rules was raised before in issue #39 - please have a look at my comments there for more. Briefly, this is an eventual goal, but there are a number of questions I need to answer before starting work. In the meantime, if you list out the rules you have in mind, they might be things I think are broadly applicable and worth adding to the core set of rules myself.
Author
Owner

@miljan-aleksic commented on GitHub (Jan 14, 2017):

Hi @DavidAnson!

Basically, I would like to be able to fix some common issues when copy/pasting the content (for external checking for example) where the result ends up with double spaces, double dots, a missing space after point or comma, invalid carachters. etc. I would gladly help working on this rule for the core, if you find it useful.

<!-- gh-comment-id:272601770 --> @miljan-aleksic commented on GitHub (Jan 14, 2017): Hi @DavidAnson! Basically, I would like to be able to fix some common issues when copy/pasting the content (for external checking for example) where the result ends up with double spaces, double dots, a missing space after point or comma, invalid carachters. etc. I would gladly help working on this rule for the core, if you find it useful.
Author
Owner

@DavidAnson commented on GitHub (Jan 14, 2017):

Double spaces was already on my list. What you describe seems like a generalization of that. I will add that to my notes. If you want to create this rule, please begin by proposing a name, parameters, and behavior (in a new issue) so we can be sure we agree on the basics first. Thanks!

<!-- gh-comment-id:272602184 --> @DavidAnson commented on GitHub (Jan 14, 2017): Double spaces was already on my list. What you describe seems like a generalization of that. I will add that to my notes. If you want to create this rule, please begin by proposing a name, parameters, and behavior (in a new issue) so we can be sure we agree on the basics first. Thanks!
Author
Owner

@DavidAnson commented on GitHub (May 20, 2017):

More details about a proposed "typography" rule are captured in #51. The idea of custom rules has been on my list, but needs more thought/planning (see #39). I'm going to close this issue since it seems the intent is captured elsewhere. Thanks again!

<!-- gh-comment-id:302852639 --> @DavidAnson commented on GitHub (May 20, 2017): More details about a proposed "typography" rule are captured in #51. The idea of custom rules has been on my list, but needs more thought/planning (see #39). I'm going to close this issue since it seems the intent is captured elsewhere. Thanks again!
Author
Owner

@henrikhaugboelle commented on GitHub (Sep 25, 2017):

I have mixed feelings about posting this, but I badly needed a way to extend the existing rules. So I went on a JavaScript adventure and cooked up a hacky solution for it. I'm using webpack and am using the markdownlint in the browser.

The markdownlint.js file looks for ./rules, which contains the ruleset. We can tell webpack to resolve ./rules to whatever we like using aliases. So we'll tell it to resolve to a custom lint-rules.js file:

{
  resolve: {
    alias: {
      './rules': 'path/to-your-custom/lint-rules.js'
    }
  }
}

In our customlint-rules.js file, we can import and subsequently export the original rules like this:

// Import original ruleset
const rules = require('markdownlint/lib/rules');

// Export ruleset
module.exports = rules;

At this stage, the markdownlint library should pretty much just behave as it usually does. But hey! Know we have got an opportunity to modify the rules. So we can do stuff like this:

// Import original ruleset
const rules = require('markdownlint/lib/rules');

// Copied from markdownlint/lib/rules
function filterTokens(params, type, callback) {
  (params.tokenLists[type] || []).forEach(callback);
}

// Copied from markdownlint/lib/rules
function forEachInlineChild(params, type, callback) {
  filterTokens(params, 'inline', (token) => {
    token.children.forEach((child) => {
      if (child.type === type) {
        callback(child, token);
      }
    });
  });
}

const sneakyRegex = /sneaky/g;

rules.push({
  name: 'KG001',
  desc: 'Sneaky beaky rules',
  tags: ['links'],
  aliases: ['capitalize-internal-links'],
  regexp: null,
  func: function KG001(params, errors) {
    forEachInlineChild(params, 'text', (token) => {
      const match = sneakyRegex.exec(token.content);

      if (match) {
        errors.addDetail(token.lineNumber, match[0]);
      }
    });
  }
});

module.exports = rules;

Now we've effectively added a new rule (KG001) to the ruleset that the markdownlint library uses. (Note: I needed to copy a few of the helper methods from the original rules.js, so I could use them in my new custom rule).

Finally I needed to turn on the rule in the markdownlint options config.

config: {
  (...),
  KG001: true // Custom rule for link formatting
}

Warning: It goes without saying that this is not a viable solution and it will certainly not fit every scenario. Even worse, it relies on the internals of the library, so if these changes, this approach will most likely break. But it is a way to add custom rules.

<!-- gh-comment-id:331895614 --> @henrikhaugboelle commented on GitHub (Sep 25, 2017): I have mixed feelings about posting this, but I badly needed a way to extend the existing rules. So I went on a JavaScript adventure and cooked up a hacky solution for it. I'm using webpack and am using the markdownlint in the browser. The `markdownlint.js` file looks for `./rules`, which contains the ruleset. We can tell webpack to resolve `./rules` to whatever we like using aliases. So we'll tell it to resolve to a custom lint-rules.js file: ```javascript { resolve: { alias: { './rules': 'path/to-your-custom/lint-rules.js' } } } ``` In our custom`lint-rules.js` file, we can import and subsequently export the original rules like this: ```javascript // Import original ruleset const rules = require('markdownlint/lib/rules'); // Export ruleset module.exports = rules; ``` At this stage, the markdownlint library should pretty much just behave as it usually does. But hey! Know we have got an opportunity to modify the rules. So we can do stuff like this: ```javascript // Import original ruleset const rules = require('markdownlint/lib/rules'); // Copied from markdownlint/lib/rules function filterTokens(params, type, callback) { (params.tokenLists[type] || []).forEach(callback); } // Copied from markdownlint/lib/rules function forEachInlineChild(params, type, callback) { filterTokens(params, 'inline', (token) => { token.children.forEach((child) => { if (child.type === type) { callback(child, token); } }); }); } const sneakyRegex = /sneaky/g; rules.push({ name: 'KG001', desc: 'Sneaky beaky rules', tags: ['links'], aliases: ['capitalize-internal-links'], regexp: null, func: function KG001(params, errors) { forEachInlineChild(params, 'text', (token) => { const match = sneakyRegex.exec(token.content); if (match) { errors.addDetail(token.lineNumber, match[0]); } }); } }); module.exports = rules; ``` Now we've effectively added a new rule (`KG001`) to the ruleset that the markdownlint library uses. (Note: I needed to copy a few of the helper methods from the original `rules.js`, so I could use them in my new custom rule). Finally I needed to turn on the rule in the markdownlint options config. ```javascript config: { (...), KG001: true // Custom rule for link formatting } ``` **Warning:** It goes without saying that this is not a viable solution and it will certainly not fit every scenario. Even worse, it relies on the internals of the library, so if these changes, this approach will most likely break. But it is **a** way to add custom rules.
Author
Owner

@DavidAnson commented on GitHub (Sep 25, 2017):

This is awesome! Thank you for sharing. :)

<!-- gh-comment-id:331918382 --> @DavidAnson commented on GitHub (Sep 25, 2017): This is awesome! Thank you for sharing. :)
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/markdownlint#34
No description provided.