From ffbf1ccfd7cda7ac1750aea8ab18f253e96dad4d Mon Sep 17 00:00:00 2001 From: ctcpip Date: Tue, 22 Aug 2023 17:29:44 -0500 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20add=20bad=20linebreaks=20linter+fix?= =?UTF-8?q?er?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 6 +++- scripts/bad-linebreaks.mjs | 74 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 scripts/bad-linebreaks.mjs diff --git a/package.json b/package.json index 9fb7d214..2ad27c85 100644 --- a/package.json +++ b/package.json @@ -1,18 +1,22 @@ { "private": true, "scripts": { + "bad-linebreaks": "node ./scripts/bad-linebreaks.mjs", + "bad-linebreaks:fix": "npm run bad-linebreaks fix", "check-delegates": "node -e 'import(\"./scripts/check-delegates.mjs\").then(cd => cd.checkDelegates())'", "check-delegates-test": "node ./scripts/check-delegates-test.mjs", + "fix:all": "npm run lint:fix && npm run mdlint:fix && npm run bad-linebreaks:fix", "lint": "eslint . --ext .js,.mjs,.cjs", "lint:fix": "npm run lint -- --fix", "//": "markdownlint commands ignore old files", "mdlint": "markdownlint-cli2 '**/*.md' '!node_modules' '!meetings/201*/*.md' '!meetings/202[0-2]*/*.md' '!meetings/2023-0[1-3]/*.md'", "mdlint:fix": "markdownlint-cli2-fix '**/*.md' '!node_modules' '!meetings/201*/*.md' '!meetings/202[0-2]*/*.md' '!meetings/2023-0[1-3]/*.md'", "//": "markdownlint most likely to fail, so run that first", - "test": "npm run mdlint && npm run lint && npm run check-delegates-test && npm run check-delegates" + "test": "npm run mdlint && npm run bad-linebreaks && npm run lint && npm run check-delegates-test && npm run check-delegates" }, "devDependencies": { "eslint": "^8.41.0", + "glob": "^10.3.3", "markdownlint-cli2": "^0.7.1" } } diff --git a/scripts/bad-linebreaks.mjs b/scripts/bad-linebreaks.mjs new file mode 100644 index 00000000..1b93516f --- /dev/null +++ b/scripts/bad-linebreaks.mjs @@ -0,0 +1,74 @@ +#!/usr/bin/env node + +import fs from 'fs'; +import { glob } from 'glob'; + +function getLine(txt, index) { + + let line = 1; + + for (let i = 0; i < index; i++) { + if (txt[i] === '\n') { + line += 1; + } + } + + return line; + +} + +export function findBadLinebreaks(file, fix = false) { + + let contents = fs.readFileSync(file, 'utf8').toString(); + + const re = /(?<=[\w\d ])\n(?=[\w\d])/g; + const matches = Array.from(contents.matchAll(re)); + + for (const m of matches) { + + if (fix) { + contents = `${contents.slice(0, m.index).trimEnd()} ${contents.slice(m.index + 1)}`; + } + else { + + const start = Math.max(0, m.index - 33); + const end = Math.min(contents.length - 1, m.index + 33); + + console.log(`found erroneous linebreak at line ${getLine(contents, m.index)}:\n${contents.slice(start, end)}\n`); + + } + + } + + if (matches.length > 0) { + + if (fix) { + fs.writeFileSync(file, contents); + console.log(`fixed ${matches.length} erroneous linebreaks`); + } + else { + process.exitCode = 1; + } + + } + +} + +// patterns match what is in package.json mdlint scripts +const files = await glob( + '**/*.md', + { + ignore: [ + 'node_modules/**', + 'meetings/201*/*.md', + 'meetings/202[0-2]*/*.md', + 'meetings/2023-0[1-3]/*.md', + ] + } +); + +const fix = process.argv?.[2] === 'fix'; + +for (const f of files) { + findBadLinebreaks(f, fix); +}