Skip to content

Commit

Permalink
[repo] Add markdown lint rule to convert directional quotes
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewnicols committed May 11, 2022
1 parent b3fe504 commit 12ba022
Show file tree
Hide file tree
Showing 6 changed files with 106 additions and 4 deletions.
1 change: 1 addition & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ module.exports = {
// Ignore code examples.
'docs/**/_examples/*',
'general/**/_examples/*',
'!.markdownlint',
],
env: {
browser: true,
Expand Down
2 changes: 1 addition & 1 deletion .lintstagedrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"*.css": ["stylelint --allow-empty-input --fix"],
"*.{js,jsx,ts,tsx,mjs}": ["eslint --fix"],
"*.md": [
"markdownlint --fix",
"markdownlint --rules .markdownlint/no-directional-quotation-marks --fix",
"cspell --no-must-find-files --no-progress"
],
"src/**/*.{js,jsx,ts,tsx,mjs}": [
Expand Down
97 changes: 97 additions & 0 deletions .markdownlint/no-directional-quotation-marks.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/**
* Copyright (c) Moodle Pty Ltd.
*
* Moodle is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Moodle is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Moodle. If not, see <http://www.gnu.org/licenses/>.
*/

/* eslint-disable import/no-extraneous-dependencies */

const {
addErrorDetailIf,
forEachLine,
getLineMetadata,
} = require('markdownlint-rule-helpers');

/**
* Get the whole word at the position, given a position within the word.
*
* @param {string} line The full line of texct
* @param {number} position The position within the line that the word is found
* @returns {string}
*/
const getWord = (line, position) => {
const left = line.slice(0, position + 1).search(/\S+$/);
const right = line.slice(left).search(/\s/);

if (right < 0) {
// This is the last word in the line.
// Return from the start of the word to the end of the line.
return line.slice(left);
}

return line.slice(left, left + right);
};

const characterReplacementMap = {
'“': '"',
'”': '"',
'‘': "'",
'’': "'",
};

const punctuation = /(?<character>[])/g;
module.exports = {
names: ['MDLDOC001', 'no-directional-quotation-marks'],
description: 'Do not use directional quotations (use apostrophe or double-quote)',
tags: ['punctuation'],
function: function MDLDOC001(params, onError) {
forEachLine(getLineMetadata(params), (line, lineIndex, inCode) => {
if (inCode) {
// Do not make changes to code stanzas.
return;
}

const lineNumber = lineIndex + 1;
let matches = punctuation.exec(line);
if (!matches) {
return;
}
do {
const foundCharacter = matches.groups.character;
const replacementCharacter = characterReplacementMap[foundCharacter];
const column = matches.index + 1;
const fixInfo = {
editColumn: column,
deleteCount: 1,
insertText: replacementCharacter,
};

const word = getWord(line, matches.index);
const expectedWord = word.replace(foundCharacter, replacementCharacter);

addErrorDetailIf(
onError,
lineNumber,
expectedWord,
word,
null,
line,
[matches.index + 1, 1],
fixInfo,
);
matches = punctuation.exec(line);
} while (matches !== null);
});
},
};
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
{
"markdownlint.customRules": [
"./.markdownlint/no-directional-quotation-marks"
],
"stylelint.packageManager": "yarn"
}
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"wikimedia-sync": "scripts/wikimedia-sync.js",
"component-spellings": "scripts/component-helper.js spelling",
"test": "jest",
"lint": "markdownlint 'docs/**/*.md' 'general/**/*.md' '*.md'",
"lint": "markdownlint --rules .markdownlint/no-directional-quotation-marks 'docs/**/*.md' 'general/**/*.md' '*.md'",
"prepare": "husky install",
"spell": "cspell '*.md' '**/*.md' 'docs/*.md' 'docs/**/*.md' 'general/*.md' 'general/**/*.md'"
},
Expand Down Expand Up @@ -82,9 +82,10 @@
"jest": "^27.5.1",
"lint-staged": "^12.3.7",
"markdownlint-cli": "^0.31.1",
"markdownlint-rule-helpers": "^0.16.0",
"stylelint-config-standard": "^25.0.0",
"ts-jest": "^27.1.4",
"typescript": "^4.6.3",
"unist-util-inspect": "6.0.0"
}
}
}
2 changes: 1 addition & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -8853,7 +8853,7 @@ markdownlint-cli@^0.31.1:
minimatch "~3.0.5"
run-con "~1.2.10"

markdownlint-rule-helpers@~0.16.0:
markdownlint-rule-helpers@^0.16.0, markdownlint-rule-helpers@~0.16.0:
version "0.16.0"
resolved "https://registry.yarnpkg.com/markdownlint-rule-helpers/-/markdownlint-rule-helpers-0.16.0.tgz#c327f72782bd2b9475127a240508231f0413a25e"
integrity sha512-oEacRUVeTJ5D5hW1UYd2qExYI0oELdYK72k1TKGvIeYJIbqQWAz476NAc7LNixSySUhcNl++d02DvX0ccDk9/w==
Expand Down

0 comments on commit 12ba022

Please sign in to comment.