From ee39cafbfa74a373b3da92af1c23582e657f5d20 Mon Sep 17 00:00:00 2001 From: aircwo Date: Thu, 26 Sep 2024 09:33:22 +0100 Subject: [PATCH] chore: add exclude pattern to the class appender (#378) --- lib/_javascripts/markdownClassAppender.js | 45 ++++++++++++++----- lib/_libraries/markdown.js | 20 ++------- .../javascripts/markdownClassAppender.test.js | 26 ++++++++--- 3 files changed, 57 insertions(+), 34 deletions(-) diff --git a/lib/_javascripts/markdownClassAppender.js b/lib/_javascripts/markdownClassAppender.js index b003d3b2d..f9d6f25e7 100644 --- a/lib/_javascripts/markdownClassAppender.js +++ b/lib/_javascripts/markdownClassAppender.js @@ -1,11 +1,22 @@ -function appendRuleNames(md, tokens = [], appendRules = true) { - let ruleNames = Array.from(tokens); +function appendRuleNames( + md, + excludeTokens = [], + appendRules = true, + excludePatterns = [], +) { + let ruleNames = Array.from(excludeTokens); if (appendRules) { - for (let ruleName in md.renderer.rules) { - if (!ruleNames.includes(ruleName)) { - ruleNames.push(ruleName); - } - } + Object.keys(md.renderer.rules) + .filter( + (ruleName) => + !ruleNames.includes(ruleName) && + !excludePatterns.some((pattern) => + typeof pattern === 'string' + ? ruleName.includes(pattern) + : pattern.test(ruleName), + ), + ) + .forEach((ruleName) => ruleNames.push(ruleName)); } return ruleNames; } @@ -27,13 +38,23 @@ function decorate(md, ruleName, cssClass) { }; } -module.exports = (md, tokens = [], appendRules = true, cssClass = 'md') => { - //use all tokens unless specified - let ruleNames = appendRuleNames(md, tokens, appendRules); +module.exports = (md, options = {}) => { + const { + excludeTokens = [], + appendRules = true, + cssClass = 'md', + excludePatterns = [], + } = options; + + let ruleNames = appendRuleNames( + md, + excludeTokens, + appendRules, + excludePatterns, + ); console.log(`configuring CSS class appender for [${ruleNames}]`); - for (let i in ruleNames) { - let ruleName = ruleNames[i]; + for (let ruleName of ruleNames) { decorate(md, ruleName, cssClass); } }; diff --git a/lib/_libraries/markdown.js b/lib/_libraries/markdown.js index b2ec1c043..0a858facd 100644 --- a/lib/_libraries/markdown.js +++ b/lib/_libraries/markdown.js @@ -10,21 +10,6 @@ module.exports = (() => { typographer: true, }); - // Remember the old renderer if overridden, or proxy to the default renderer. - let defaultRender = - md.renderer.rules.link_open || - function (tokens, idx, options, env, self) { - return self.renderToken(tokens, idx, options); - }; - - md.renderer.rules.p = function (tokens, idx, options, env, self) { - // Adds a 'md' CSS class - tokens[idx].attrJoin('class', 'md'); - - // Pass the token to the default renderer. - return defaultRender(tokens, idx, options, env, self); - }; - md.use(require('markdown-it-abbr')) .use(require('markdown-it-attrs')) .use(anchor, { @@ -63,7 +48,10 @@ module.exports = (() => { } }, }) - .use(require('../_javascripts/markdownClassAppender'), ['dl_open']); + .use(require('../_javascripts/markdownClassAppender'), { + excludeTokens: ['dl_open'], + excludePatterns: ['admonition'], + }); return md; })(); diff --git a/lib/tests/javascripts/markdownClassAppender.test.js b/lib/tests/javascripts/markdownClassAppender.test.js index 95d5402dc..baa37a656 100644 --- a/lib/tests/javascripts/markdownClassAppender.test.js +++ b/lib/tests/javascripts/markdownClassAppender.test.js @@ -2,9 +2,10 @@ const appender = require('../../_javascripts/markdownClassAppender'); const markdownit = require('markdown-it'); const fixture_h1 = '# heading 1'; +const fixture_admonition = '!!! note\n This is an admonition.'; -function md(tokens, appendRules) { - return markdownit().use(appender, tokens, appendRules); +function md(options = {}) { + return markdownit().use(appender, options); } describe('markdownClassAppender', () => { @@ -19,14 +20,27 @@ describe('markdownClassAppender', () => { }); test('should add class to configured tokens', () => { - expect(md(['heading_open']).render(fixture_h1)).toEqual( + expect(md({ excludeTokens: ['heading_open'] }).render(fixture_h1)).toEqual( '

heading 1

\n', ); }); test('should miss class when default rules excluded', () => { - expect(md([], false).render('`javascript`')).toEqual( - '

javascript

\n', - ); + expect( + md({ excludeTokens: [], appendRules: false }).render('`javascript`'), + ).toEqual('

javascript

\n'); }); + + test.each(['admonition', /^admonition/])( + 'should exclude patterns specified as types of strings', + (excludePattern) => { + // given / when + const result = md({ excludePatterns: [excludePattern] }).render( + fixture_admonition, + ); + + // then + expect(result).not.toContain('md'); + }, + ); });