From 9c176575081046570ba9992e40f4155e8ebf6811 Mon Sep 17 00:00:00 2001 From: Rachael Sewell Date: Fri, 7 Jul 2023 14:19:37 -0700 Subject: [PATCH 01/13] add code fence markdownlint rules --- .../linting-rules/code-fence-line-length.js | 32 +++++++++++++ .../code-fence-uses-copy-directive.js | 46 +++++++++++++++++++ .../lib/markdownlint-helpers.js | 9 ++++ .../tests/fixtures/code-fence-line-length.md | 31 +++++++++++++ .../code-fence-uses-copy-directive.md | 35 ++++++++++++++ .../tests/unit/code-fence-line-length.js | 29 ++++++++++++ .../unit/code-fence-uses-copy-directive.js | 31 +++++++++++++ .../unit/image-alt-text-end-punctuation.js | 18 ++++---- .../tests/unit/image-alt-text-length.js | 18 ++++---- .../tests/unit/image-file-kebab.js | 18 ++++---- src/content-linter/tests/unit/init-test.js | 8 ++++ .../tests/unit/internal-links-lang.js | 21 ++++----- .../tests/unit/internal-links-slash.js | 18 ++++---- 13 files changed, 267 insertions(+), 47 deletions(-) create mode 100644 src/content-linter/lib/linting-rules/code-fence-line-length.js create mode 100644 src/content-linter/lib/linting-rules/code-fence-uses-copy-directive.js create mode 100644 src/content-linter/lib/markdownlint-helpers.js create mode 100644 src/content-linter/tests/fixtures/code-fence-line-length.md create mode 100644 src/content-linter/tests/fixtures/code-fence-uses-copy-directive.md create mode 100644 src/content-linter/tests/unit/code-fence-line-length.js create mode 100644 src/content-linter/tests/unit/code-fence-uses-copy-directive.js create mode 100644 src/content-linter/tests/unit/init-test.js diff --git a/src/content-linter/lib/linting-rules/code-fence-line-length.js b/src/content-linter/lib/linting-rules/code-fence-line-length.js new file mode 100644 index 0000000000..3476315a20 --- /dev/null +++ b/src/content-linter/lib/linting-rules/code-fence-line-length.js @@ -0,0 +1,32 @@ +import { addError } from 'markdownlint-rule-helpers' + +import { getCodeFenceTokens, getCodeFenceLines } from '../markdownlint-helpers.js' + +export const codeFenceLineLength = { + names: ['GH011', 'code-fence-line-length'], + description: 'Code fence lines should not exceed a maximum length', + tags: ['code'], + severity: 'warning', + function: function GH011(params, onError) { + const MAX_LINE_LENGTH = String(params.config.maxLength || 60) + const codeFenceTokens = getCodeFenceTokens(params) + codeFenceTokens.forEach((token) => { + const lines = getCodeFenceLines(token) + lines.forEach((line, index) => { + if (line.length > MAX_LINE_LENGTH) { + // The token line number is the line number of the first line of the + // code fence. We want to report the line number of the content within + // the code fence so we need to add 1 + the index. + const lineNumber = token.lineNumber + index + 1 + addError( + onError, + lineNumber, + `Code fence line exceeds ${MAX_LINE_LENGTH} characters.`, + undefined, // N/A + undefined // N/A + ) + } + }) + }) + }, +} diff --git a/src/content-linter/lib/linting-rules/code-fence-uses-copy-directive.js b/src/content-linter/lib/linting-rules/code-fence-uses-copy-directive.js new file mode 100644 index 0000000000..25aa92ee49 --- /dev/null +++ b/src/content-linter/lib/linting-rules/code-fence-uses-copy-directive.js @@ -0,0 +1,46 @@ +import { addError } from 'markdownlint-rule-helpers' + +import { getCodeFenceTokens, getCodeFenceLines } from '../markdownlint-helpers.js' + +const dollarCommandRe = /^(\s*)(\$\s+)/ + +export const codeFenceUsesCopyDirective = { + names: ['GH001', 'code-fences-use-copy-directive'], + description: 'Code fence blocks should use the copy directive when no output is shown', + tags: ['code'], + severity: 'error', + function: function GH001(params, onError) { + const codeFenceTokens = getCodeFenceTokens(params) + codeFenceTokens.forEach((token) => { + const lines = getCodeFenceLines(token) + let dollarsExist = false + lines.forEach((line, index) => { + const lineTrim = line.trim() + if (lineTrim) { + const match = dollarCommandRe.exec(line) + if (match) { + dollarsExist = true + } + } + }) + if (!dollarsExist && !token.info.trim().includes('copy')) { + addError( + onError, + token.lineNumber, + 'Code fence block should include the copy directive.', + undefined, + undefined + ) + } + if (dollarsExist && token.info.trim().includes('copy')) { + addError( + onError, + token.lineNumber, + 'Code fence block should NOT include the copy directive.', + undefined, + undefined + ) + } + }) + }, +} diff --git a/src/content-linter/lib/markdownlint-helpers.js b/src/content-linter/lib/markdownlint-helpers.js new file mode 100644 index 0000000000..26825b0876 --- /dev/null +++ b/src/content-linter/lib/markdownlint-helpers.js @@ -0,0 +1,9 @@ +import { newLineRe } from 'markdownlint-rule-helpers' + +export function getCodeFenceTokens(params) { + return params.tokens.filter((t) => t.type === 'fence') +} + +export function getCodeFenceLines(token) { + return token.content.split(newLineRe) +} diff --git a/src/content-linter/tests/fixtures/code-fence-line-length.md b/src/content-linter/tests/fixtures/code-fence-line-length.md new file mode 100644 index 0000000000..f336f17a6b --- /dev/null +++ b/src/content-linter/tests/fixtures/code-fence-line-length.md @@ -0,0 +1,31 @@ +# Heading + +Line length exceeds max length by 1 + +```shell copy +111 +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +bbb +``` + +Line length equals max length + +```shell copy +111 +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +bbbbbbb +``` + +Line length is less than max length + +```shell copy +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +``` + +Multiple lines in code fence exceed max length by 1 + +```shell copy +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaccc +1 +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbb +``` diff --git a/src/content-linter/tests/fixtures/code-fence-uses-copy-directive.md b/src/content-linter/tests/fixtures/code-fence-uses-copy-directive.md new file mode 100644 index 0000000000..1fcbaeb29b --- /dev/null +++ b/src/content-linter/tests/fixtures/code-fence-uses-copy-directive.md @@ -0,0 +1,35 @@ +# Heading + +Copy directive does not exist because example contains both output and a command. + +```shell +$ this +that +``` + +Copy directive should exist because example only contains command. + +```shell +echo "hello" +echo "there" +``` + +Copy directive should not exist when example only starts with $. + +```shell +$ echo "hello" +$ echo "there" +``` + +Copy directive should not exist because example only contains command. + +```shell copy +$ one +two +``` + +Copy directive exists because example only contains a command. + +```shell copy +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +``` diff --git a/src/content-linter/tests/unit/code-fence-line-length.js b/src/content-linter/tests/unit/code-fence-line-length.js new file mode 100644 index 0000000000..d0cad67c21 --- /dev/null +++ b/src/content-linter/tests/unit/code-fence-line-length.js @@ -0,0 +1,29 @@ +import { jest } from '@jest/globals' + +import { runRule } from './init-test.js' +import { codeFenceLineLength } from '../../lib/linting-rules/code-fence-line-length.js' + +jest.setTimeout(60 * 1000) + +const fixtureFilePath = 'src/content-linter/tests/fixtures/code-fence-line-length.md' +const result = await runRule(codeFenceLineLength, fixtureFilePath) +const errors = result[fixtureFilePath] + +describe(codeFenceLineLength.names.join(' - '), () => { + test('line length of max length + 1 fails', async () => { + expect(errors.map((error) => error.lineNumber).includes(7)).toBe(true) + }) + test('line length equals max length passes', async () => { + expect(errors.map((error) => error.lineNumber).includes(15)).toBe(false) + }) + test('line length less than max length passes', async () => { + expect(errors.map((error) => error.lineNumber).includes(22)).toBe(false) + }) + test('multiple lines in code block that exceed max length fail', async () => { + expect(errors.map((error) => error.lineNumber).includes(28)).toBe(true) + expect(errors.map((error) => error.lineNumber).includes(30)).toBe(true) + }) + test('errors only occur on expected lines', async () => { + expect(errors.length).toBe(3) + }) +}) diff --git a/src/content-linter/tests/unit/code-fence-uses-copy-directive.js b/src/content-linter/tests/unit/code-fence-uses-copy-directive.js new file mode 100644 index 0000000000..dc6d38c84e --- /dev/null +++ b/src/content-linter/tests/unit/code-fence-uses-copy-directive.js @@ -0,0 +1,31 @@ +import { jest } from '@jest/globals' + +import { runRule } from './init-test.js' +import { codeFenceUsesCopyDirective } from '../../lib/linting-rules/code-fence-uses-copy-directive.js' + +jest.setTimeout(60 * 1000) + +const fixtureFilePath = 'src/content-linter/tests/fixtures/code-fence-uses-copy-directive.md' +const result = await runRule(codeFenceUsesCopyDirective, fixtureFilePath) +const errors = result[fixtureFilePath] + +describe(codeFenceUsesCopyDirective.names.join(' - '), () => { + test('code fence that includes both output and command and no copy directive passes', () => { + expect(errors.map((error) => error.lineNumber).includes(5)).toBe(false) + }) + test('code fence with only commands and no copy directive fails', () => { + expect(errors.map((error) => error.lineNumber).includes(12)).toBe(true) + }) + test('code fence with only $ and no copy directive passes', () => { + expect(errors.map((error) => error.lineNumber).includes(19)).toBe(false) + }) + test('code fence with command and output and copy directive should fail', () => { + expect(errors.map((error) => error.lineNumber).includes(26)).toBe(true) + }) + test('code fence with copy directive and command passes', () => { + expect(errors.map((error) => error.lineNumber).includes(33)).toBe(false) + }) + test('errors only occur on expected lines', () => { + expect(errors.length).toBe(2) + }) +}) diff --git a/src/content-linter/tests/unit/image-alt-text-end-punctuation.js b/src/content-linter/tests/unit/image-alt-text-end-punctuation.js index 69d399d7d2..41a33482aa 100644 --- a/src/content-linter/tests/unit/image-alt-text-end-punctuation.js +++ b/src/content-linter/tests/unit/image-alt-text-end-punctuation.js @@ -1,18 +1,18 @@ import { jest } from '@jest/globals' -import markdownlint from 'markdownlint' +import { runRule } from './init-test.js' import { imageAltTextEndPunctuation } from '../../lib/linting-rules/image-alt-text-end-punctuation.js' -import { testOptions } from '../../lib/default-markdownlint-options.js' jest.setTimeout(60 * 1000) const fixtureFile = 'src/content-linter/tests/fixtures/image-alt-text-end-punctuation.md' -const options = testOptions('MD112', imageAltTextEndPunctuation, fixtureFile) -const result = await markdownlint.promises.markdownlint(options) +const result = await runRule(imageAltTextEndPunctuation, fixtureFile) +const errors = result[fixtureFile] -test('image alt text must have an end punctuation', () => { - const errors = result[fixtureFile] - expect(Object.keys(result).length).toBe(1) - expect(errors.length).toBe(2) - expect(errors.map((error) => error.lineNumber)).toEqual([3, 15]) +describe(imageAltTextEndPunctuation.names.join(' - '), () => { + test('image alt text must have an end punctuation', () => { + expect(Object.keys(result).length).toBe(1) + expect(errors.length).toBe(2) + expect(errors.map((error) => error.lineNumber)).toEqual([3, 15]) + }) }) diff --git a/src/content-linter/tests/unit/image-alt-text-length.js b/src/content-linter/tests/unit/image-alt-text-length.js index 7c8e9f6bec..5c70a35cd0 100644 --- a/src/content-linter/tests/unit/image-alt-text-length.js +++ b/src/content-linter/tests/unit/image-alt-text-length.js @@ -1,18 +1,18 @@ import { jest } from '@jest/globals' -import markdownlint from 'markdownlint' +import { runRule } from './init-test.js' import { incorrectAltTextLength } from '../../lib/linting-rules/image-alt-text-length.js' -import { testOptions } from '../../lib/default-markdownlint-options.js' jest.setTimeout(60 * 1000) const fixtureFile = 'src/content-linter/tests/fixtures/image-alt-text-length.md' -const options = testOptions('MD111', incorrectAltTextLength, fixtureFile) -const result = await markdownlint.promises.markdownlint(options) +const result = await runRule(incorrectAltTextLength, fixtureFile) +const errors = result[fixtureFile] -test('image with correct length alt text', () => { - const errors = result[fixtureFile] - expect(Object.keys(result).length).toBe(1) - expect(errors.length).toBe(2) - expect(errors.map((error) => error.lineNumber)).toEqual([1, 7]) +describe(incorrectAltTextLength.names.join(' - '), () => { + test('image with correct length alt text', () => { + expect(Object.keys(result).length).toBe(1) + expect(errors.length).toBe(2) + expect(errors.map((error) => error.lineNumber)).toEqual([1, 7]) + }) }) diff --git a/src/content-linter/tests/unit/image-file-kebab.js b/src/content-linter/tests/unit/image-file-kebab.js index dd94d5ddb1..678c19fa40 100644 --- a/src/content-linter/tests/unit/image-file-kebab.js +++ b/src/content-linter/tests/unit/image-file-kebab.js @@ -1,18 +1,18 @@ import { jest } from '@jest/globals' -import markdownlint from 'markdownlint' +import { runRule } from './init-test.js' import { imageFileKebab } from '../../lib/linting-rules/image-file-kebab' -import { testOptions } from '../../lib/default-markdownlint-options.js' jest.setTimeout(20 * 1000) const fixtureFile = 'src/content-linter/tests/fixtures/image-file-kebab.md' -const options = testOptions('MD115', imageFileKebab, fixtureFile) -const result = await markdownlint.promises.markdownlint(options) +const result = await runRule(imageFileKebab, fixtureFile) +const errors = result[fixtureFile] -test('image file with lowercase kebab case', () => { - const errors = result[fixtureFile] - expect(Object.keys(result).length).toBe(1) - expect(errors.length).toBe(4) - expect(errors.map((error) => error.lineNumber)).toEqual([4, 5, 6, 7]) +describe(imageFileKebab.names.join(' - '), () => { + test('image file with lowercase kebab case', () => { + expect(Object.keys(result).length).toBe(1) + expect(errors.length).toBe(4) + expect(errors.map((error) => error.lineNumber)).toEqual([4, 5, 6, 7]) + }) }) diff --git a/src/content-linter/tests/unit/init-test.js b/src/content-linter/tests/unit/init-test.js new file mode 100644 index 0000000000..f1a81d110b --- /dev/null +++ b/src/content-linter/tests/unit/init-test.js @@ -0,0 +1,8 @@ +import markdownlint from 'markdownlint' + +import { testOptions } from '../../lib/default-markdownlint-options.js' + +export async function runRule(module, fixtureFile) { + const options = testOptions(module.names[0], module, fixtureFile) + return await markdownlint.promises.markdownlint(options) +} diff --git a/src/content-linter/tests/unit/internal-links-lang.js b/src/content-linter/tests/unit/internal-links-lang.js index 48c6546b43..a495fbbe66 100644 --- a/src/content-linter/tests/unit/internal-links-lang.js +++ b/src/content-linter/tests/unit/internal-links-lang.js @@ -1,18 +1,17 @@ import { jest } from '@jest/globals' -import markdownlint from 'markdownlint' +import { runRule } from './init-test.js' import { internalLinksLang } from '../../lib/linting-rules/internal-links-lang.js' -import { testOptions } from '../../lib/default-markdownlint-options.js' - -const fixtureFile = 'src/content-linter/tests/fixtures/internal-links-lang.md' jest.setTimeout(30 * 1000) -const options = testOptions('MD114', internalLinksLang, fixtureFile) +const fixtureFilePath = 'src/content-linter/tests/fixtures/internal-links-lang.md' +const result = await runRule(internalLinksLang, fixtureFilePath) +const errors = result[fixtureFilePath] -const result = await markdownlint.promises.markdownlint(options) -test('internal links and hardcoded language codes', () => { - const errors = result[fixtureFile] - expect(Object.keys(result).length).toBe(1) - expect(errors.length).toBe(3) - expect(errors.map((error) => error.lineNumber)).toEqual([3, 4, 8]) +describe(internalLinksLang.names.join(' - '), () => { + test('internal links and hardcoded language codes', () => { + expect(Object.keys(result).length).toBe(1) + expect(errors.length).toBe(3) + expect(errors.map((error) => error.lineNumber)).toEqual([3, 4, 8]) + }) }) diff --git a/src/content-linter/tests/unit/internal-links-slash.js b/src/content-linter/tests/unit/internal-links-slash.js index 524ad95a21..29652fe565 100755 --- a/src/content-linter/tests/unit/internal-links-slash.js +++ b/src/content-linter/tests/unit/internal-links-slash.js @@ -1,18 +1,18 @@ import { jest } from '@jest/globals' -import markdownlint from 'markdownlint' +import { runRule } from './init-test.js' import { internalLinksSlash } from '../../lib/linting-rules/internal-links-slash.js' -import { testOptions } from '../../lib/default-markdownlint-options.js' jest.setTimeout(60 * 1000) const fixtureFile = 'src/content-linter/tests/fixtures/internal-links-slash.md' -const options = testOptions('MD113', internalLinksSlash, fixtureFile) -const result = await markdownlint.promises.markdownlint(options) +const result = await runRule(internalLinksSlash, fixtureFile) +const errors = result[fixtureFile] -test('relative links start with /', () => { - const errors = result[fixtureFile] - expect(Object.keys(result).length).toBe(1) - expect(errors.length).toBe(1) - expect(errors.map((error) => error.lineNumber)).toEqual([5]) +describe(internalLinksSlash.names.join(' - '), () => { + test('relative links start with /', () => { + expect(Object.keys(result).length).toBe(1) + expect(errors.length).toBe(1) + expect(errors.map((error) => error.lineNumber)).toEqual([5]) + }) }) From 1382ff6b88d071dc3a7bd2f4d3c00244036cccb2 Mon Sep 17 00:00:00 2001 From: Rachael Sewell Date: Mon, 10 Jul 2023 10:04:32 -0700 Subject: [PATCH 02/13] update markdown rule numbers --- .../lib/linting-rules/code-fence-line-length.js | 4 ++-- .../lib/linting-rules/code-fence-uses-copy-directive.js | 4 ++-- src/content-linter/scripts/markdownlint.js | 2 ++ 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/content-linter/lib/linting-rules/code-fence-line-length.js b/src/content-linter/lib/linting-rules/code-fence-line-length.js index 3476315a20..e63c3771ad 100644 --- a/src/content-linter/lib/linting-rules/code-fence-line-length.js +++ b/src/content-linter/lib/linting-rules/code-fence-line-length.js @@ -3,11 +3,11 @@ import { addError } from 'markdownlint-rule-helpers' import { getCodeFenceTokens, getCodeFenceLines } from '../markdownlint-helpers.js' export const codeFenceLineLength = { - names: ['GH011', 'code-fence-line-length'], + names: ['MD117', 'code-fence-line-length'], description: 'Code fence lines should not exceed a maximum length', tags: ['code'], severity: 'warning', - function: function GH011(params, onError) { + function: function MD117(params, onError) { const MAX_LINE_LENGTH = String(params.config.maxLength || 60) const codeFenceTokens = getCodeFenceTokens(params) codeFenceTokens.forEach((token) => { diff --git a/src/content-linter/lib/linting-rules/code-fence-uses-copy-directive.js b/src/content-linter/lib/linting-rules/code-fence-uses-copy-directive.js index 25aa92ee49..f79a62fc44 100644 --- a/src/content-linter/lib/linting-rules/code-fence-uses-copy-directive.js +++ b/src/content-linter/lib/linting-rules/code-fence-uses-copy-directive.js @@ -5,11 +5,11 @@ import { getCodeFenceTokens, getCodeFenceLines } from '../markdownlint-helpers.j const dollarCommandRe = /^(\s*)(\$\s+)/ export const codeFenceUsesCopyDirective = { - names: ['GH001', 'code-fences-use-copy-directive'], + names: ['MD116', 'code-fences-use-copy-directive'], description: 'Code fence blocks should use the copy directive when no output is shown', tags: ['code'], severity: 'error', - function: function GH001(params, onError) { + function: function MD116(params, onError) { const codeFenceTokens = getCodeFenceTokens(params) codeFenceTokens.forEach((token) => { const lines = getCodeFenceLines(token) diff --git a/src/content-linter/scripts/markdownlint.js b/src/content-linter/scripts/markdownlint.js index 31a313388a..ea76c39e88 100755 --- a/src/content-linter/scripts/markdownlint.js +++ b/src/content-linter/scripts/markdownlint.js @@ -85,6 +85,8 @@ async function main() { MD113: true, MD114: true, MD115: true, + MD116: true, + MD117: true, } const files = walkFiles(path, ['.md'], { includeBasePath: true }) From a020943b4ef6188a5947b86679f72967436e3873 Mon Sep 17 00:00:00 2001 From: Rachael Sewell Date: Mon, 10 Jul 2023 10:11:20 -0700 Subject: [PATCH 03/13] move to lib directory --- src/content-linter/{tests/unit => lib}/init-test.js | 2 +- src/content-linter/tests/unit/code-fence-uses-copy-directive.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename src/content-linter/{tests/unit => lib}/init-test.js (75%) diff --git a/src/content-linter/tests/unit/init-test.js b/src/content-linter/lib/init-test.js similarity index 75% rename from src/content-linter/tests/unit/init-test.js rename to src/content-linter/lib/init-test.js index f1a81d110b..91b84f4edb 100644 --- a/src/content-linter/tests/unit/init-test.js +++ b/src/content-linter/lib/init-test.js @@ -1,6 +1,6 @@ import markdownlint from 'markdownlint' -import { testOptions } from '../../lib/default-markdownlint-options.js' +import { testOptions } from './default-markdownlint-options.js' export async function runRule(module, fixtureFile) { const options = testOptions(module.names[0], module, fixtureFile) diff --git a/src/content-linter/tests/unit/code-fence-uses-copy-directive.js b/src/content-linter/tests/unit/code-fence-uses-copy-directive.js index dc6d38c84e..0c82f8f3ff 100644 --- a/src/content-linter/tests/unit/code-fence-uses-copy-directive.js +++ b/src/content-linter/tests/unit/code-fence-uses-copy-directive.js @@ -1,6 +1,6 @@ import { jest } from '@jest/globals' -import { runRule } from './init-test.js' +import { runRule } from '../../lib/init-test.js' import { codeFenceUsesCopyDirective } from '../../lib/linting-rules/code-fence-uses-copy-directive.js' jest.setTimeout(60 * 1000) From 4a12aaff516e07274dfc556269baa6051c7fdf07 Mon Sep 17 00:00:00 2001 From: Rachael Sewell Date: Mon, 10 Jul 2023 10:13:11 -0700 Subject: [PATCH 04/13] update require path --- src/content-linter/tests/unit/code-fence-line-length.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content-linter/tests/unit/code-fence-line-length.js b/src/content-linter/tests/unit/code-fence-line-length.js index d0cad67c21..2d5587bf8e 100644 --- a/src/content-linter/tests/unit/code-fence-line-length.js +++ b/src/content-linter/tests/unit/code-fence-line-length.js @@ -1,6 +1,6 @@ import { jest } from '@jest/globals' -import { runRule } from './init-test.js' +import { runRule } from '../../lib/init-test.js' import { codeFenceLineLength } from '../../lib/linting-rules/code-fence-line-length.js' jest.setTimeout(60 * 1000) From 0accdde43d068564abd0a616b566d5e3fba8aaba Mon Sep 17 00:00:00 2001 From: Rachael Sewell Date: Mon, 10 Jul 2023 10:14:49 -0700 Subject: [PATCH 05/13] update path --- src/content-linter/tests/unit/image-alt-text-end-punctuation.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content-linter/tests/unit/image-alt-text-end-punctuation.js b/src/content-linter/tests/unit/image-alt-text-end-punctuation.js index 41a33482aa..49571646e4 100644 --- a/src/content-linter/tests/unit/image-alt-text-end-punctuation.js +++ b/src/content-linter/tests/unit/image-alt-text-end-punctuation.js @@ -1,6 +1,6 @@ import { jest } from '@jest/globals' -import { runRule } from './init-test.js' +import { runRule } from '../../lib/init-test.js' import { imageAltTextEndPunctuation } from '../../lib/linting-rules/image-alt-text-end-punctuation.js' jest.setTimeout(60 * 1000) From 9de551f268eca694ee97b350b084f52fd34e83d8 Mon Sep 17 00:00:00 2001 From: Rachael Sewell Date: Mon, 10 Jul 2023 10:15:54 -0700 Subject: [PATCH 06/13] update paths --- src/content-linter/tests/unit/image-alt-text-length.js | 2 +- src/content-linter/tests/unit/image-file-kebab.js | 2 +- src/content-linter/tests/unit/internal-links-lang.js | 2 +- src/content-linter/tests/unit/internal-links-slash.js | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/content-linter/tests/unit/image-alt-text-length.js b/src/content-linter/tests/unit/image-alt-text-length.js index 5c70a35cd0..7e9c30967f 100644 --- a/src/content-linter/tests/unit/image-alt-text-length.js +++ b/src/content-linter/tests/unit/image-alt-text-length.js @@ -1,6 +1,6 @@ import { jest } from '@jest/globals' -import { runRule } from './init-test.js' +import { runRule } from '../../lib/init-test.js' import { incorrectAltTextLength } from '../../lib/linting-rules/image-alt-text-length.js' jest.setTimeout(60 * 1000) diff --git a/src/content-linter/tests/unit/image-file-kebab.js b/src/content-linter/tests/unit/image-file-kebab.js index 678c19fa40..b75762b750 100644 --- a/src/content-linter/tests/unit/image-file-kebab.js +++ b/src/content-linter/tests/unit/image-file-kebab.js @@ -1,6 +1,6 @@ import { jest } from '@jest/globals' -import { runRule } from './init-test.js' +import { runRule } from '../../lib/init-test.js' import { imageFileKebab } from '../../lib/linting-rules/image-file-kebab' jest.setTimeout(20 * 1000) diff --git a/src/content-linter/tests/unit/internal-links-lang.js b/src/content-linter/tests/unit/internal-links-lang.js index a495fbbe66..f47e1a0a1b 100644 --- a/src/content-linter/tests/unit/internal-links-lang.js +++ b/src/content-linter/tests/unit/internal-links-lang.js @@ -1,6 +1,6 @@ import { jest } from '@jest/globals' -import { runRule } from './init-test.js' +import { runRule } from '../../lib/init-test.js' import { internalLinksLang } from '../../lib/linting-rules/internal-links-lang.js' jest.setTimeout(30 * 1000) diff --git a/src/content-linter/tests/unit/internal-links-slash.js b/src/content-linter/tests/unit/internal-links-slash.js index 29652fe565..ea169fc0b4 100755 --- a/src/content-linter/tests/unit/internal-links-slash.js +++ b/src/content-linter/tests/unit/internal-links-slash.js @@ -1,6 +1,6 @@ import { jest } from '@jest/globals' -import { runRule } from './init-test.js' +import { runRule } from '../../lib/init-test.js' import { internalLinksSlash } from '../../lib/linting-rules/internal-links-slash.js' jest.setTimeout(60 * 1000) From 47b4d716ea69c31b0f092958684c9f9378892ddd Mon Sep 17 00:00:00 2001 From: Rachael Sewell Date: Mon, 10 Jul 2023 10:35:12 -0700 Subject: [PATCH 07/13] update readme --- src/content-linter/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/content-linter/README.md b/src/content-linter/README.md index c072251536..7a97f2f64f 100644 --- a/src/content-linter/README.md +++ b/src/content-linter/README.md @@ -34,6 +34,8 @@ We are using the [markdownlint](https://github.com/DavidAnson/markdownlint) fram | [MD113](./linting-rules/internal-links-slash.js) | Internal links must start with a `/`. | error | | [MD114](./linting-rules/internal-links-lang.js) | Internal links must not have a hardcoded language code. | error | | [MD115](./linting-rules/image-file-kebab.js) | Image file names should be lowercase kebab case. | error | +| [MD116](./linting-rules/code-fences-use-copy-directive.js) | Code fences must use the copy directive when the example is a command only and must not use the copy directive when the example contains output. | error | +| [MD117](./linting-rules/code-fence-line-length.js) | Code fence content should be 60 lines or less in length. | warning | ## Linting Tests From eb7909e34666122a76660b751b18f713c5357ccf Mon Sep 17 00:00:00 2001 From: Rachael Sewell Date: Tue, 11 Jul 2023 13:19:06 -0700 Subject: [PATCH 08/13] remove copy button rule --- src/content-linter/README.md | 1 - .../code-fence-uses-copy-directive.js | 46 ------------------- src/content-linter/scripts/markdownlint.js | 1 - 3 files changed, 48 deletions(-) delete mode 100644 src/content-linter/lib/linting-rules/code-fence-uses-copy-directive.js diff --git a/src/content-linter/README.md b/src/content-linter/README.md index 7a97f2f64f..e0b9ca4feb 100644 --- a/src/content-linter/README.md +++ b/src/content-linter/README.md @@ -34,7 +34,6 @@ We are using the [markdownlint](https://github.com/DavidAnson/markdownlint) fram | [MD113](./linting-rules/internal-links-slash.js) | Internal links must start with a `/`. | error | | [MD114](./linting-rules/internal-links-lang.js) | Internal links must not have a hardcoded language code. | error | | [MD115](./linting-rules/image-file-kebab.js) | Image file names should be lowercase kebab case. | error | -| [MD116](./linting-rules/code-fences-use-copy-directive.js) | Code fences must use the copy directive when the example is a command only and must not use the copy directive when the example contains output. | error | | [MD117](./linting-rules/code-fence-line-length.js) | Code fence content should be 60 lines or less in length. | warning | ## Linting Tests diff --git a/src/content-linter/lib/linting-rules/code-fence-uses-copy-directive.js b/src/content-linter/lib/linting-rules/code-fence-uses-copy-directive.js deleted file mode 100644 index f79a62fc44..0000000000 --- a/src/content-linter/lib/linting-rules/code-fence-uses-copy-directive.js +++ /dev/null @@ -1,46 +0,0 @@ -import { addError } from 'markdownlint-rule-helpers' - -import { getCodeFenceTokens, getCodeFenceLines } from '../markdownlint-helpers.js' - -const dollarCommandRe = /^(\s*)(\$\s+)/ - -export const codeFenceUsesCopyDirective = { - names: ['MD116', 'code-fences-use-copy-directive'], - description: 'Code fence blocks should use the copy directive when no output is shown', - tags: ['code'], - severity: 'error', - function: function MD116(params, onError) { - const codeFenceTokens = getCodeFenceTokens(params) - codeFenceTokens.forEach((token) => { - const lines = getCodeFenceLines(token) - let dollarsExist = false - lines.forEach((line, index) => { - const lineTrim = line.trim() - if (lineTrim) { - const match = dollarCommandRe.exec(line) - if (match) { - dollarsExist = true - } - } - }) - if (!dollarsExist && !token.info.trim().includes('copy')) { - addError( - onError, - token.lineNumber, - 'Code fence block should include the copy directive.', - undefined, - undefined - ) - } - if (dollarsExist && token.info.trim().includes('copy')) { - addError( - onError, - token.lineNumber, - 'Code fence block should NOT include the copy directive.', - undefined, - undefined - ) - } - }) - }, -} diff --git a/src/content-linter/scripts/markdownlint.js b/src/content-linter/scripts/markdownlint.js index ea76c39e88..0396f27cca 100755 --- a/src/content-linter/scripts/markdownlint.js +++ b/src/content-linter/scripts/markdownlint.js @@ -85,7 +85,6 @@ async function main() { MD113: true, MD114: true, MD115: true, - MD116: true, MD117: true, } From bc242d901e3771e264557d2b9917527502ddaa52 Mon Sep 17 00:00:00 2001 From: Rachael Sewell Date: Tue, 11 Jul 2023 13:24:34 -0700 Subject: [PATCH 09/13] remove copy directive rule --- .../code-fence-uses-copy-directive.md | 35 ------------------- .../unit/code-fence-uses-copy-directive.js | 31 ---------------- 2 files changed, 66 deletions(-) delete mode 100644 src/content-linter/tests/fixtures/code-fence-uses-copy-directive.md delete mode 100644 src/content-linter/tests/unit/code-fence-uses-copy-directive.js diff --git a/src/content-linter/tests/fixtures/code-fence-uses-copy-directive.md b/src/content-linter/tests/fixtures/code-fence-uses-copy-directive.md deleted file mode 100644 index 1fcbaeb29b..0000000000 --- a/src/content-linter/tests/fixtures/code-fence-uses-copy-directive.md +++ /dev/null @@ -1,35 +0,0 @@ -# Heading - -Copy directive does not exist because example contains both output and a command. - -```shell -$ this -that -``` - -Copy directive should exist because example only contains command. - -```shell -echo "hello" -echo "there" -``` - -Copy directive should not exist when example only starts with $. - -```shell -$ echo "hello" -$ echo "there" -``` - -Copy directive should not exist because example only contains command. - -```shell copy -$ one -two -``` - -Copy directive exists because example only contains a command. - -```shell copy -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -``` diff --git a/src/content-linter/tests/unit/code-fence-uses-copy-directive.js b/src/content-linter/tests/unit/code-fence-uses-copy-directive.js deleted file mode 100644 index 0c82f8f3ff..0000000000 --- a/src/content-linter/tests/unit/code-fence-uses-copy-directive.js +++ /dev/null @@ -1,31 +0,0 @@ -import { jest } from '@jest/globals' - -import { runRule } from '../../lib/init-test.js' -import { codeFenceUsesCopyDirective } from '../../lib/linting-rules/code-fence-uses-copy-directive.js' - -jest.setTimeout(60 * 1000) - -const fixtureFilePath = 'src/content-linter/tests/fixtures/code-fence-uses-copy-directive.md' -const result = await runRule(codeFenceUsesCopyDirective, fixtureFilePath) -const errors = result[fixtureFilePath] - -describe(codeFenceUsesCopyDirective.names.join(' - '), () => { - test('code fence that includes both output and command and no copy directive passes', () => { - expect(errors.map((error) => error.lineNumber).includes(5)).toBe(false) - }) - test('code fence with only commands and no copy directive fails', () => { - expect(errors.map((error) => error.lineNumber).includes(12)).toBe(true) - }) - test('code fence with only $ and no copy directive passes', () => { - expect(errors.map((error) => error.lineNumber).includes(19)).toBe(false) - }) - test('code fence with command and output and copy directive should fail', () => { - expect(errors.map((error) => error.lineNumber).includes(26)).toBe(true) - }) - test('code fence with copy directive and command passes', () => { - expect(errors.map((error) => error.lineNumber).includes(33)).toBe(false) - }) - test('errors only occur on expected lines', () => { - expect(errors.length).toBe(2) - }) -}) From 9564e5ea79702e29430ba81cc5efae6ae4106bb5 Mon Sep 17 00:00:00 2001 From: Rachael Sewell Date: Tue, 11 Jul 2023 13:32:48 -0700 Subject: [PATCH 10/13] add fixinfo undefined --- src/content-linter/lib/linting-rules/code-fence-line-length.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/content-linter/lib/linting-rules/code-fence-line-length.js b/src/content-linter/lib/linting-rules/code-fence-line-length.js index e63c3771ad..ae8ecbcf7d 100644 --- a/src/content-linter/lib/linting-rules/code-fence-line-length.js +++ b/src/content-linter/lib/linting-rules/code-fence-line-length.js @@ -23,6 +23,7 @@ export const codeFenceLineLength = { lineNumber, `Code fence line exceeds ${MAX_LINE_LENGTH} characters.`, undefined, // N/A + undefined, // N/A undefined // N/A ) } From 94a59e26dd40bf24fb4c9e38a6ede9ba636b2b42 Mon Sep 17 00:00:00 2001 From: Rachael Sewell Date: Tue, 11 Jul 2023 13:36:12 -0700 Subject: [PATCH 11/13] Update src/content-linter/tests/fixtures/code-fence-line-length.md Co-authored-by: Grace Park --- src/content-linter/tests/fixtures/code-fence-line-length.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content-linter/tests/fixtures/code-fence-line-length.md b/src/content-linter/tests/fixtures/code-fence-line-length.md index f336f17a6b..d6f31fb1fc 100644 --- a/src/content-linter/tests/fixtures/code-fence-line-length.md +++ b/src/content-linter/tests/fixtures/code-fence-line-length.md @@ -2,7 +2,7 @@ Line length exceeds max length by 1 -```shell copy +```shell 111 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbb From 49ba6e99ddd8016334a93bb80753c8f63871dcaa Mon Sep 17 00:00:00 2001 From: Rachael Sewell Date: Tue, 11 Jul 2023 13:36:27 -0700 Subject: [PATCH 12/13] update prettier and re-run --- src/content-linter/lib/linting-rules/code-fence-line-length.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content-linter/lib/linting-rules/code-fence-line-length.js b/src/content-linter/lib/linting-rules/code-fence-line-length.js index ae8ecbcf7d..7b6576282a 100644 --- a/src/content-linter/lib/linting-rules/code-fence-line-length.js +++ b/src/content-linter/lib/linting-rules/code-fence-line-length.js @@ -24,7 +24,7 @@ export const codeFenceLineLength = { `Code fence line exceeds ${MAX_LINE_LENGTH} characters.`, undefined, // N/A undefined, // N/A - undefined // N/A + undefined, // N/A ) } }) From 8a3ac39417bf3baa18cb37b35864bea08b21ccf8 Mon Sep 17 00:00:00 2001 From: Rachael Sewell Date: Tue, 11 Jul 2023 13:39:32 -0700 Subject: [PATCH 13/13] remove copy button --- src/content-linter/tests/fixtures/code-fence-line-length.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/content-linter/tests/fixtures/code-fence-line-length.md b/src/content-linter/tests/fixtures/code-fence-line-length.md index d6f31fb1fc..b0af054972 100644 --- a/src/content-linter/tests/fixtures/code-fence-line-length.md +++ b/src/content-linter/tests/fixtures/code-fence-line-length.md @@ -10,7 +10,7 @@ bbb Line length equals max length -```shell copy +```shell 111 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbb @@ -18,13 +18,13 @@ bbbbbbb Line length is less than max length -```shell copy +```shell aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ``` Multiple lines in code fence exceed max length by 1 -```shell copy +```shell aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaccc 1 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbb