first commit

This commit is contained in:
2026-08-06 12:00:39 +10:00
commit 91221f5a8e
3259 changed files with 569069 additions and 0 deletions
@@ -0,0 +1,106 @@
/**
* @fileoverview Rule to enforce languages for fenced code.
* @author Nicholas C. Zakas
*/
//-----------------------------------------------------------------------------
// Type Definitions
//-----------------------------------------------------------------------------
/**
* @import { MarkdownRuleDefinition } from "../types.js";
* @typedef {"missingLanguage" | "disallowedLanguage"} FencedCodeLanguageMessageIds
* @typedef {[{ required?: string[] }]} FencedCodeLanguageOptions
* @typedef {MarkdownRuleDefinition<{ RuleOptions: FencedCodeLanguageOptions, MessageIds: FencedCodeLanguageMessageIds }>} FencedCodeLanguageRuleDefinition
*/
//-----------------------------------------------------------------------------
// Helpers
//-----------------------------------------------------------------------------
const fencedCodeCharacters = new Set(["`", "~"]);
//-----------------------------------------------------------------------------
// Rule Definition
//-----------------------------------------------------------------------------
export default /** @satisfies {FencedCodeLanguageRuleDefinition} */ ({
meta: {
type: "problem",
docs: {
recommended: true,
description: "Require languages for fenced code blocks",
url: "https://github.com/eslint/markdown/blob/main/docs/rules/fenced-code-language.md",
},
messages: {
missingLanguage: "Missing code block language.",
disallowedLanguage: 'Code block language "{{lang}}" is not allowed.',
},
schema: [
{
type: "object",
properties: {
required: {
type: "array",
items: {
type: "string",
},
uniqueItems: true,
},
},
additionalProperties: false,
},
],
defaultOptions: [
{
required: [],
},
],
},
create(context) {
const required = new Set(context.options[0].required);
const { sourceCode } = context;
return {
code(node) {
if (!node.lang) {
// only check fenced code blocks
if (!fencedCodeCharacters.has(sourceCode.text[node.position.start.offset])) {
return;
}
/** @type {number} */
let openingCodeFenceEndOffset;
for (openingCodeFenceEndOffset = node.position.start.offset; fencedCodeCharacters.has(sourceCode.text[openingCodeFenceEndOffset]); openingCodeFenceEndOffset++) {
// Find the end offset of the opening code fence.
}
context.report({
loc: {
start: node.position.start,
end: {
line: node.position.start.line,
column: node.position.start.column +
openingCodeFenceEndOffset -
node.position.start.offset,
},
},
messageId: "missingLanguage",
});
return;
}
if (required.size && !required.has(node.lang)) {
const langIndex = sourceCode
.getText(node)
.indexOf(node.lang);
context.report({
loc: {
start: node.position.start,
end: {
line: node.position.start.line,
column: node.position.start.column +
langIndex +
node.lang.length,
},
},
messageId: "disallowedLanguage",
data: {
lang: node.lang,
},
});
}
},
};
},
});