Skip to content

Commit

Permalink
feat: Add type checking
Browse files Browse the repository at this point in the history
  • Loading branch information
nzakas committed Jul 26, 2024
1 parent 19a2d55 commit 5f48e19
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 31 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ npm-debug.log
yarn.lock
package-lock.json
pnpm-lock.yaml
dist
9 changes: 9 additions & 0 deletions rollup.config.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import copy from "rollup-plugin-copy";

export default {
input: "src/index.js",
output: [
Expand All @@ -6,5 +8,12 @@ export default {
format: "esm",
banner: '// @ts-self-types="./index.d.ts"'
}
],
plugins: [
copy({
targets: [
{ src: "src/types.ts", dest: "dist/esm" }
]
})
]
};
9 changes: 9 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,18 @@

import { processor } from "./processor.js";

//-----------------------------------------------------------------------------
// Type Definitions
//-----------------------------------------------------------------------------

/** @typedef {import("eslint").Linter.RulesRecord} RulesRecord*/
/** @typedef {import("eslint").ESLint.Plugin} Plugin */

//-----------------------------------------------------------------------------
// Exports
//-----------------------------------------------------------------------------

/** @type {RulesRecord} */
const rulesConfig = {

// The Markdown parser automatically trims trailing
Expand All @@ -36,6 +44,7 @@ const rulesConfig = {
"unicode-bom": "off"
};

/** @type {Plugin} */
const plugin = {
meta: {
name: "@eslint/markdown",
Expand Down
76 changes: 45 additions & 31 deletions src/processor.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,30 +3,30 @@
* @author Brandon Mills
*/

/**
* @typedef {import('eslint/lib/shared/types').LintMessage} Message
* @typedef {Object} ASTNode
* @property {string} type The type of node.
* @property {string} [lang] The language that the node is in
* @typedef {Object} RangeMap
* @property {number} indent Number of code block indent characters trimmed from
* the beginning of the line during extraction.
* @property {number} js Offset from the start of the code block's range in the
* extracted JS.
* @property {number} md Offset from the start of the code block's range in the
* original Markdown.
* @typedef {Object} BlockBase
* @property {string} baseIndentText Leading whitespace text for the block.
* @property {string[]} comments Comments inside of the JavaScript code.
* @property {RangeMap[]} rangeMap A list of offset-based adjustments, where
* lookups are done based on the `js` key, which represents the range in the
* linted JS, and the `md` key is the offset delta that, when added to the JS
* range, returns the corresponding location in the original Markdown source.
* @typedef {ASTNode & BlockBase} Block
*/
//-----------------------------------------------------------------------------
// Imports
//-----------------------------------------------------------------------------

import { fromMarkdown } from "mdast-util-from-markdown";

//-----------------------------------------------------------------------------
// Type Definitions
//-----------------------------------------------------------------------------

/** @typedef {import("./types.ts").Block} Block */
/** @typedef {import("./types.ts").RangeMap} RangeMap */
/** @typedef {import("mdast").Node} Node */
/** @typedef {import("mdast").Parent} ParentNode */
/** @typedef {import("mdast").Code} CodeNode */
/** @typedef {import("mdast").Html} HtmlNode */
/** @typedef {import("eslint").Linter.LintMessage} Message */
/** @typedef {import("eslint").Rule.Fix} Fix */
/** @typedef {import("eslint").AST.Range} Range */

//-----------------------------------------------------------------------------
// Helpers
//-----------------------------------------------------------------------------

const UNSATISFIABLE_RULES = new Set([
"eol-last", // The Markdown parser strips trailing newlines in code fences
"unicode-bom" // Code blocks will begin in the middle of Markdown files
Expand All @@ -40,8 +40,8 @@ const blocksCache = new Map();

/**
* Performs a depth-first traversal of the Markdown AST.
* @param {ASTNode} node A Markdown AST node.
* @param {{[key: string]: (node: ASTNode) => void}} callbacks A map of node types to callbacks.
* @param {Node} node A Markdown AST node.
* @param {{[key: string]: (node?: Node) => void}} callbacks A map of node types to callbacks.
* @returns {void}
*/
function traverse(node, callbacks) {
Expand All @@ -51,9 +51,11 @@ function traverse(node, callbacks) {
callbacks["*"]();
}

if (typeof node.children !== "undefined") {
for (let i = 0; i < node.children.length; i++) {
traverse(node.children[i], callbacks);
const parent = /** @type {ParentNode} */ (node);

if (typeof parent.children !== "undefined") {
for (let i = 0; i < parent.children.length; i++) {
traverse(parent.children[i], callbacks);
}
}
}
Expand Down Expand Up @@ -92,7 +94,7 @@ const leadingWhitespaceRegex = /^[>\s]*/u;
/**
* Gets the offset for the first column of the node's first line in the
* original source text.
* @param {ASTNode} node A Markdown code block AST node.
* @param {Node} node A Markdown code block AST node.
* @returns {number} The offset for the first column of the node's first line.
*/
function getBeginningOfLineOffset(node) {
Expand All @@ -103,7 +105,7 @@ function getBeginningOfLineOffset(node) {
* Gets the leading text, typically whitespace with possible blockquote chars,
* used to indent a code block.
* @param {string} text The text of the file.
* @param {ASTNode} node A Markdown code block AST node.
* @param {Node} node A Markdown code block AST node.
* @returns {string} The text from the start of the first line to the opening
* fence of the code block.
*/
Expand Down Expand Up @@ -137,7 +139,7 @@ function getIndentText(text, node) {
* differences within the line, so the mapping need only provide the offset
* delta at the beginning of each line.
* @param {string} text The text of the file.
* @param {ASTNode} node A Markdown code block AST node.
* @param {Node} node A Markdown code block AST node.
* @param {string[]} comments List of configuration comment strings that will be
* inserted at the beginning of the code block.
* @returns {RangeMap[]} A list of offset-based adjustments, where lookups are
Expand Down Expand Up @@ -265,6 +267,12 @@ function preprocess(text, filename) {
"*"() {
htmlComments = [];
},

/**
* Visit a code node.
* @param {CodeNode} node The visited node.
* @returns {void}
*/
code(node) {
if (node.lang) {
const comments = [];
Expand All @@ -288,6 +296,12 @@ function preprocess(text, filename) {
});
}
},

/**
* Visit an HTML node.
* @param {HtmlNode} node The visited node.
* @returns {void}
*/
html(node) {
const comment = getComment(node.value);

Expand Down Expand Up @@ -357,7 +371,7 @@ function adjustBlock(block) {

if (message.fix) {
adjustedFix.fix = {
range: message.fix.range.map(range => {
range: /** @type {Range} */ (message.fix.range.map(range => {

// Advance through the block's range map to find the last
// matching range by finding the first range too far and
Expand All @@ -370,7 +384,7 @@ function adjustBlock(block) {

// Apply the mapping delta for this range.
return range + block.rangeMap[i - 1].md;
}),
})),
text: message.fix.text.replace(/\n/gu, `\n${block.baseIndentText}`)
};
}
Expand Down
19 changes: 19 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import type { Node } from "mdast";
import type { Linter } from "eslint";


export interface RangeMap {
indent: number;
js: number;
md: number;
}

export interface BlockBase {
baseIndentText: string;
comments: string[];
rangeMap: RangeMap[];
}

export interface Block extends Node, BlockBase {}

export type Message = Linter.LintMessage;
1 change: 1 addition & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"compilerOptions": {
"declaration": true,
"emitDeclarationOnly": true,
"allowImportingTsExtensions": true,
"allowJs": true,
"checkJs": true,
"outDir": "dist/esm",
Expand Down

0 comments on commit 5f48e19

Please sign in to comment.