UNPKG

@envsa/remark-config

Version:
261 lines (260 loc) 19.8 kB
import { defaultHandlers as mdastToTextHandlers } from 'mdast-util-to-markdown'; import remarkDirective from 'remark-directive'; import remarkFrontmatter from 'remark-frontmatter'; import remarkGfm from 'remark-gfm'; import remarkLint from 'remark-lint'; import remarkValidateLinks from 'remark-validate-links'; // export { commandDefinition } from './command.js' // Necessary for side-effect type definitions? import 'remark-stringify'; // See https://github.com/remarkjs/remark-lint?tab=readme-ov-file#rules // Official import remarkLintCheckboxContentIndent from 'remark-lint-checkbox-content-indent'; // Warn when too much whitespace follows list item checkboxes // import remarkLintCorrectMediaSyntax from 'remark-lint-correct-media-syntax' // Check for accidental bracket and paren mixup for images and links // import remarkLintDefinitionSort from 'remark-lint-definition-sort' // Check definition order // import remarkLintDirectiveAttributeSort from 'remark-lint-directive-attribute-sort' // Check directive attribute order // import remarkLintDirectiveCollapsedAttribute from 'remark-lint-directive-collapsed-attribute' // Check that collapsed attributes are used in directives // import remarkLintDirectiveQuoteStyle from 'remark-lint-directive-quote-style' // Check quotes of directive attributes // import remarkLintDirectiveShortcutAttribute from 'remark-lint-directive-shortcut-attribute' // Check that shortcut attributes are used in directives // import remarkLintDirectiveUniqueAttributeName from 'remark-lint-directive-unique-attribute-name' // Check that attribute names are unique import remarkLintFencedCodeFlag from 'remark-lint-fenced-code-flag'; // Warn when fenced code blocks occur without language flag // import remarkLintFileExtension from 'remark-lint-file-extension' // (Crashes with "Cannot use 'in' operator to search for 'start' in undefined") Warn when the file’s extension violates the given style import remarkLintFinalDefinition from 'remark-lint-final-definition'; // Warn when definitions are not placed at the end of the file import remarkLintFirstHeadingLevel from 'remark-lint-first-heading-level'; // Warn when the first heading has a level other than a specified value import remarkLintHeadingIncrement from 'remark-lint-heading-increment'; // Warn when headings increment with more than 1 level at a time import remarkLintLinebreakStyle from 'remark-lint-linebreak-style'; // Warn when linebreaks violate a given or detected style import remarkLintMaximumHeadingLength from 'remark-lint-maximum-heading-length'; // Warn when headings are too long // import remarkLintMdxJsxAttributeSort from 'remark-lint-mdx-jsx-attribute-sort' // Check mdx jsx attribute order // import remarkLintMdxJsxNoVoidChildren from 'remark-lint-mdx-jsx-no-void-children' // Check mdx jsx quotes // import remarkLintMdxJsxQuoteStyle from 'remark-lint-mdx-jsx-quote-style' // Check mdx jsx quotes // import remarkLintMdxJsxSelfClose from 'remark-lint-mdx-jsx-self-close' // Check that self-closing tags are used when possible // import remarkLintMdxJsxShorthandAttribute from 'remark-lint-mdx-jsx-shorthand-attribute' // Check that shorthand attributes are used in MDX JSX // import remarkLintMdxJsxUniqueAttributeName from 'remark-lint-mdx-jsx-unique-attribute-name' // Check that mdx jsx attributes are unique // import remarkLintMediaStyle from 'remark-lint-media-style' // Check whether references or resources are used import remarkLintNoDuplicateDefinedUrls from 'remark-lint-no-duplicate-defined-urls'; // Warn on definitions that define the same urls import remarkLintNoDuplicateDefinitions from 'remark-lint-no-duplicate-definitions'; // Warn on duplicate definitions import remarkLintNoDuplicateHeadings from 'remark-lint-no-duplicate-headings'; // Warn on duplicate headings import remarkLintNoDuplicateHeadingsInSection from 'remark-lint-no-duplicate-headings-in-section'; // Warn on duplicate headings in a section // import remarkLintNoEmphasisAsHeading from 'remark-lint-no-emphasis-as-heading' // Warn when emphasis or importance is used instead of a heading import remarkLintNoEmptyUrl from 'remark-lint-no-empty-url'; // Warn on empty URLs in links and images import remarkLintNoFileNameArticles from 'remark-lint-no-file-name-articles'; // Warn when file name start with an article import remarkLintNoFileNameConsecutiveDashes from 'remark-lint-no-file-name-consecutive-dashes'; // Warn when file names contain consecutive dashes import remarkLintNoFileNameIrregularCharacters from 'remark-lint-no-file-name-irregular-characters'; // Warn when file names contain irregular characters // import remarkLintNoFileNameMixedCase from 'remark-lint-no-file-name-mixed-case' // (Crashes with "Cannot use 'in' operator to search for 'start' in undefined") Warn when file names use mixed case import remarkLintNoFileNameOuterDashes from 'remark-lint-no-file-name-outer-dashes'; // Warn when file names contain initial or final dashes import remarkLintNoHeadingIndent from 'remark-lint-no-heading-indent'; // Warn when headings are indented import remarkLintNoHeadingLikeParagraph from 'remark-lint-no-heading-like-paragraph'; // For too many hashes (h7+ “headings”) // import remarkLintNoHeadingPunctuation from 'remark-lint-no-heading-punctuation' // Warn when headings end in illegal characters // import remarkLintNoHiddenTableCell from 'remark-lint-no-hidden-table-cell' // Check superfluous table cells // import remarkLintNoHtml from 'remark-lint-no-html' // Warn when HTML nodes are used // import remarkLintNoLiteralUrls from 'remark-lint-no-literal-urls' // Warn when URLs without angle brackets are used // import remarkLintNoMissingBlankLines from 'remark-lint-no-missing-blank-lines' // Warn when missing blank lines import remarkLintNoMultipleToplevelHeadings from 'remark-lint-no-multiple-toplevel-headings'; // Warn when multiple top level headings are used import remarkLintNoParagraphContentIndent from 'remark-lint-no-paragraph-content-indent'; // Warn when the content in paragraphs are indented import remarkLintNoReferenceLikeUrl from 'remark-lint-no-reference-like-url'; // Warn when URLs are also defined identifiers import remarkLintNoShellDollars from 'remark-lint-no-shell-dollars'; // Warn when shell code is prefixed by dollars import remarkLintNoShortcutReferenceImage from 'remark-lint-no-shortcut-reference-image'; // Warn when shortcut reference images are used import remarkLintNoShortcutReferenceLink from 'remark-lint-no-shortcut-reference-link'; // Warn when shortcut reference links are used import remarkLintNoTabs from 'remark-lint-no-tabs'; // Warn when hard tabs are used instead of spaces import remarkLintNoUndefinedReferences from 'remark-lint-no-undefined-references'; // Warn when references to undefined definitions are found import remarkLintNoUnneededFullReferenceImage from 'remark-lint-no-unneeded-full-reference-image'; // Check that full reference images can be collapsed import remarkLintNoUnneededFullReferenceLink from 'remark-lint-no-unneeded-full-reference-link'; // Check that full reference links can be collapsed import remarkLintNoUnusedDefinitions from 'remark-lint-no-unused-definitions'; // Warn when unused definitions are found import remarkLintStrikethroughMarker from 'remark-lint-strikethrough-marker'; // Warn when strikethrough markers violate the given style // Official rules with Prettier conflicts // Maintained manually via https://github.com/un-ts/remark-preset-prettier?tab=readme-ov-file#disabled-remark-lint-plugins // import remarkLintBlockquoteIndentation from 'remark-lint-blockquote-indentation' // Check whitespace after block quote markers // import remarkLintCheckboxCharacterStyle from 'remark-lint-checkbox-character-style' // Check list item checkbox characters // import remarkLintCodeBlockStyle from 'remark-lint-code-block-style' // Warn when code blocks do not adhere to a given style // import remarkLintDefinitionCase from 'remark-lint-definition-case' // Warn when definition labels are not lowercase // import remarkLintDefinitionSpacing from 'remark-lint-definition-spacing' // Warn when consecutive whitespace is used in a definition // import remarkLintEmphasisMarker from 'remark-lint-emphasis-marker' // Warn when emphasis markers violate the given style // import remarkLintFencedCodeMarker from 'remark-lint-fenced-code-marker' // Warn when fenced code markers violate the given style // import remarkLintFinalNewline from 'remark-lint-final-newline' // Warn when a newline at the end of a file is missing // import remarkLintHardBreakSpaces from 'remark-lint-hard-break-spaces' // Warn when too many spaces are used to create a hard break // import remarkLintHeadingStyle from 'remark-lint-heading-style' // Warn when heading style violates the given style // import remarkLintBlankLines102 from 'remark-lint-blank-lines-1-0-2' // Ensure a specific number of lines between blocks // import remarkLintHeadingWhitespace from 'remark-lint-heading-whitespace' // Ensure heading parsing is not broken by weird whitespace // import remarkLintLinkTitleStyle from 'remark-lint-link-title-style' // Warn when link and definition titles occur with incorrect quotes // import remarkLintListItemBulletIndent from 'remark-lint-list-item-bullet-indent' // Warn when list item bullets are indented // import remarkLintListItemContentIndent from 'remark-lint-list-item-content-indent' // Warn when the content of a list item has mixed indentation // import remarkLintListItemIndent from 'remark-lint-list-item-indent' // Check the spacing between list item bullets and content // import remarkLintListItemSpacing from 'remark-lint-list-item-spacing' // Warn when list looseness is incorrect // import remarkLintMaximumLineLength from 'remark-lint-maximum-line-length' // Warn when lines are too long // import remarkLintNoBlockquoteWithoutMarker from 'remark-lint-no-blockquote-without-marker' // Warn when block quotes have blank lines without markers // import remarkLintNoConsecutiveBlankLines from 'remark-lint-no-consecutive-blank-lines' // Warn for too many consecutive blank lines // import remarkLintNoHeadingContentIndent from 'remark-lint-no-heading-content-indent' // Warn when heading content is indented // import remarkLintNoTableIndentation from 'remark-lint-no-table-indentation' // Warn when tables are indented // import remarkLintOrderedListMarkerStyle from 'remark-lint-ordered-list-marker-style' // Warn when the markers of ordered lists violate a given style // import remarkLintOrderedListMarkerValue from 'remark-lint-ordered-list-marker-value' // Check the marker value of ordered lists // import remarkLintRuleStyle from 'remark-lint-rule-style' // Warn when horizontal rules violate a given style // import remarkLintStrongMarker from 'remark-lint-strong-marker' // Warn when importance (strong) markers violate the given style // import remarkLintTableCellPadding from 'remark-lint-table-cell-padding' // Warn when table cells are incorrectly padded // import remarkLintTablePipeAlignment from 'remark-lint-table-pipe-alignment' // Warn when table pipes are not aligned // import remarkLintTablePipes from 'remark-lint-table-pipes' // Warn when table rows are not fenced with pipes // import remarkLintUnorderedListMarkerStyle from 'remark-lint-unordered-list-marker-style' // Warn when markers of unordered lists violate a given style // Community maintained rules // import remarkLintAlphabetizeLists from 'remark-lint-alphabetize-lists' // Ensure list items are in alphabetical order // import remarkLintAppropriateHeading from 'remark-lint-appropriate-heading' // Check that the top level heading matches the directory name // import remarkLintAreLinksValid from 'remark-lint-are-links-valid' // Check if your links are reachable and/or unique // import remarkLintCheckToc from 'remark-lint-check-toc' // Ensure TOC is correct // import remarkLintCode from 'remark-lint-code' // Lint fenced code blocks by corresponding language tags, currently supporting ESLint // import remarkLintCodeBlockSplitList from 'remark-lint-code-block-split-list' // Ensure code block inside list doesn't split the list // import remarkLintDoubleLink from 'remark-lint-double-link' // Ensure the same URL is not linked multiple times. // import remarkLintEmojiLimit from 'remark-lint-emoji-limit' // Enforce a limit of emoji per paragraph // import remarkLintFencedCodeFlagCase from 'remark-lint-fenced-code-flag-case' // Warn when fenced code blocks have improperly cased language flags // import remarkLintFrontmatterSchema from 'remark-lint-frontmatter-schema' // Validate YAML frontmatter against a JSON schema // import remarkLintHeadingCapitalization from 'remark-lint-heading-capitalization' // Ensure headings capitalization is correct // import remarkLintHeadingLength from 'remark-lint-heading-length' // Ensure headings have the appropriate length // import remarkLintHeadingWordLength from 'remark-lint-heading-word-length' // Warn when headings have too many or too few words with unicode support // import remarkLintListItemStyle from 'remark-lint-list-item-style' // Warn when list items violate a given capitalization or punctuation style // import remarkLintMatchPunctuation from 'remark-lint-match-punctuation' // Ensures punctuations are used in pairs if necessary. // import remarkLintMdashStyle from 'remark-lint-mdash-style' // Ensure em-dash (—) style follows a standard format // import remarkLintNoChinesePunctuationInNumber from 'remark-lint-no-chinese-punctuation-in-number' // Ensures that Chinese punctuation’s not used in numbers // import remarkLintNoDeadUrls from 'remark-lint-no-dead-urls' // Check that external links are alive // import remarkLintNoEmptySections from 'remark-lint-no-empty-sections' // Ensure every heading is followed by content (forming a section) // import remarkLintNoRepeatPunctuation from 'remark-lint-no-repeat-punctuation' // Ensures punctuation is not repeated // import remarkLintNoUrlTrailingSlash from 'remark-lint-no-url-trailing-slash' // Ensure that the href of links has no trailing slash // import remarkLintWriteGood from 'remark-lint-write-good' // Wrapper for write-good // Community maintained rules with Prettier conflicts // Maintained manually via https://github.com/un-ts/remark-preset-prettier?tab=readme-ov-file#disabled-remark-lint-plugins // import remarkLintBooksLinks from 'remark-lint-books-links' // Ensure links in lists of books follow a standard format // import remarkLintNoLongCode from 'remark-lint-no-long-code' // Ensures that each line in code block won't be too long. // import remarkLintSpacesAroundNumber from 'remark-lint-spaces-around-number' // Ensures there are spaces around number and Chinese. // import remarkLintSpacesAroundWord from 'remark-lint-spaces-around-word' // Ensures there are spaces around English word and Chinese. const remarkSharedConfig = { plugins: [ remarkLint, remarkFrontmatter, remarkGfm, remarkDirective, remarkLintCheckboxContentIndent, [remarkLintFencedCodeFlag, { allowEmpty: false }], remarkLintFinalDefinition, remarkLintFirstHeadingLevel, remarkLintHeadingIncrement, remarkLintLinebreakStyle, remarkLintMaximumHeadingLength, remarkLintNoDuplicateDefinedUrls, remarkLintNoDuplicateDefinitions, remarkLintNoDuplicateHeadings, remarkLintNoDuplicateHeadingsInSection, remarkLintNoEmptyUrl, remarkLintNoFileNameArticles, remarkLintNoFileNameConsecutiveDashes, remarkLintNoFileNameIrregularCharacters, remarkLintNoFileNameOuterDashes, remarkLintNoHeadingIndent, remarkLintNoHeadingLikeParagraph, remarkLintNoMultipleToplevelHeadings, remarkLintNoParagraphContentIndent, remarkLintNoReferenceLikeUrl, remarkLintNoShellDollars, remarkLintNoShortcutReferenceImage, remarkLintNoShortcutReferenceLink, remarkLintNoTabs, [ remarkLintNoUndefinedReferences, { allow: [ '…', '...', // GitHub Alerts / Admonitions // https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#alerts // See also the custom text handler below in settings '!NOTE', '!TIP', '!IMPORTANT', '!WARNING', '!CAUTION', ], }, ], remarkLintNoUnneededFullReferenceImage, remarkLintNoUnneededFullReferenceLink, remarkLintNoUnusedDefinitions, remarkLintNoUnusedDefinitions, remarkLintStrikethroughMarker, remarkValidateLinks, ], // Prettier will enforce some of these? settings: { bullet: '-', emphasis: '_', handlers: { // Prevent escaping GFM alerts / admonitions // https://github.com/Xunnamius/symbiote/blob/main/src/assets/transformers/_.remarkrc.mjs.ts // This is necessary in addition to the remark-lint-no-undefined-references rule customization below. text(node, parent, state, info) { // Call the default text handler, then strip the leading "\" from GFM alerts // Case insensitivity is important! const markdownString = mdastToTextHandlers.text(node, parent, state, info); return markdownString.replace(/^\\(?=\[!(?:NOTE|TIP|IMPORTANT|WARNING|CAUTION)\])/i, ''); }, }, rule: '-', strong: '*', }, }; /** * Overrides specific rules in a set of plugins. * * This function searches through an array of plugins to find and override * multiple plugins by their names, replacing their arguments with new ones. * * See this link for why we need this: * https://github.com/remarkjs/remark-lint/issues/165 * */ function overrideRules(plugins, rules) { plugins ??= []; for (let [ruleName, newArguments] of rules) { // Internally, function names are different from the package names ruleName = ruleName.replace(/^remark-lint-/, 'remark-lint:'); let ruleFunction; const index = plugins.findIndex((plugin) => { if (Array.isArray(plugin)) { if (plugin[0].name === ruleName) { ruleFunction = plugin[0]; return true; } } else if ('name' in plugin && plugin.name === ruleName) { ruleFunction = plugin; return true; } return false; }); if (index !== -1) { plugins.splice(index, 1, [ruleFunction, newArguments]); } } return plugins; } /** * **Remark Shared Configuration** * @see [@envsa/remark-config](https://github.com/envsa/shared-config/tree/main/packages/remark-config) * @see [@envsa/shared-config](https://github.com/envsa/shared-config) * @example * ```js * export default remarkConfig({ * rules: [ * ['remark-lint-first-heading-level', 2], * ['remarkValidateLinks', { repository: false }], * ], * }) * ``` */ export function remarkConfig(options) { const { plugins = [], rules = [], settings, } = options ?? { plugins: undefined, rules: undefined, settings: undefined, }; return { ...remarkSharedConfig, plugins: overrideRules([...(remarkSharedConfig.plugins ?? []), ...plugins], rules), settings: { ...remarkSharedConfig.settings, ...settings }, }; } export default remarkSharedConfig;