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,115 @@
/**
* @fileoverview Rule to prevent empty definitions in Markdown.
* @author Pixel998
*/
//-----------------------------------------------------------------------------
// Imports
//-----------------------------------------------------------------------------
import { normalizeIdentifier } from "micromark-util-normalize-identifier";
import { htmlCommentPattern } from "../util.js";
//-----------------------------------------------------------------------------
// Type Definitions
//-----------------------------------------------------------------------------
/**
* @import { MarkdownRuleDefinition } from "../types.js";
* @typedef {"emptyDefinition" | "emptyFootnoteDefinition"} NoEmptyDefinitionsMessageIds
* @typedef {[{ allowDefinitions?: string[], allowFootnoteDefinitions?: string[], checkFootnoteDefinitions?: boolean }]} NoEmptyDefinitionsOptions
* @typedef {MarkdownRuleDefinition<{ RuleOptions: NoEmptyDefinitionsOptions, MessageIds: NoEmptyDefinitionsMessageIds }>} NoEmptyDefinitionsRuleDefinition
*/
//-----------------------------------------------------------------------------
// Helpers
//-----------------------------------------------------------------------------
/**
* Checks if a string contains only HTML comments.
* @param {string} value The input string to check.
* @returns {boolean} True if the string contains only HTML comments, false otherwise.
*/
function isOnlyComments(value) {
const withoutComments = value.replace(htmlCommentPattern, "");
return withoutComments.trim().length === 0;
}
//-----------------------------------------------------------------------------
// Rule Definition
//-----------------------------------------------------------------------------
export default /** @satisfies {NoEmptyDefinitionsRuleDefinition} */ ({
meta: {
type: "problem",
docs: {
recommended: true,
description: "Disallow empty definitions",
url: "https://github.com/eslint/markdown/blob/main/docs/rules/no-empty-definitions.md",
},
messages: {
emptyDefinition: "Unexpected empty definition `{{ identifier }}` (label: `{{ label }}`) found.",
emptyFootnoteDefinition: "Unexpected empty footnote definition `{{ identifier }}` (label: `{{ label }}`) found.",
},
schema: [
{
type: "object",
properties: {
allowDefinitions: {
type: "array",
items: {
type: "string",
},
uniqueItems: true,
},
allowFootnoteDefinitions: {
type: "array",
items: {
type: "string",
},
uniqueItems: true,
},
checkFootnoteDefinitions: {
type: "boolean",
},
},
additionalProperties: false,
},
],
defaultOptions: [
{
allowDefinitions: ["//"],
allowFootnoteDefinitions: [],
checkFootnoteDefinitions: true,
},
],
},
create(context) {
const allowDefinitions = new Set(context.options[0].allowDefinitions.map(identifier => normalizeIdentifier(identifier).toLowerCase()));
const allowFootnoteDefinitions = new Set(context.options[0].allowFootnoteDefinitions.map(identifier => normalizeIdentifier(identifier).toLowerCase()));
const [{ checkFootnoteDefinitions }] = context.options;
return {
definition(node) {
if ((!node.url || node.url === "#") &&
!allowDefinitions.has(node.identifier)) {
context.report({
loc: node.position,
messageId: "emptyDefinition",
data: {
identifier: node.identifier,
label: node.label.trim(),
},
});
}
},
footnoteDefinition(node) {
if (checkFootnoteDefinitions &&
!allowFootnoteDefinitions.has(node.identifier) &&
(node.children.length === 0 ||
node.children.every(child => child.type === "html" &&
isOnlyComments(child.value)))) {
context.report({
loc: node.position,
messageId: "emptyFootnoteDefinition",
data: {
identifier: node.identifier,
label: node.label,
},
});
}
},
};
},
});