Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: Use @eslint/plugin-kit #280

Merged
merged 1 commit into from
Sep 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ import markdown from "./src/index.js";

export default [
...eslintConfigESLint,
{
name: "markdown/js",
files: ["**/*.js"],
rules: {
"no-undefined": "off",
},
},
{
name: "markdown/plugins",
plugins: {
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@
"test:jsr": "npx jsr@latest publish --dry-run"
},
"devDependencies": {
"@eslint/core": "^0.3.0",
"@eslint/core": "^0.6.0",
"@eslint/js": "^9.4.0",
"@types/eslint": "^9.6.0",
"c8": "^10.1.2",
Expand All @@ -77,6 +77,7 @@
"yorkie": "^2.0.0"
},
"dependencies": {
"@eslint/plugin-kit": "^0.2.0",
"mdast-util-from-markdown": "^2.0.1",
"mdast-util-gfm": "^3.0.0",
"micromark-extension-gfm": "^3.0.0"
Expand Down
177 changes: 10 additions & 167 deletions src/language/markdown-source-code.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
// Imports
//-----------------------------------------------------------------------------

import { VisitNodeStep, TextSourceCodeBase } from "@eslint/plugin-kit";

//-----------------------------------------------------------------------------
// Types
//-----------------------------------------------------------------------------
Expand All @@ -22,74 +24,17 @@
/** @typedef {import("@eslint/core").SourceLocation} SourceLocation */
/** @typedef {import("@eslint/core").SourceRange} SourceRange */

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

/**
* A class to represent a step in the traversal process.
* @implements {VisitTraversalStep}
*/
class MarkdownTraversalStep {
/**
* The type of the step.
* @type {"visit"}
* @readonly
*/
type = "visit";

/**
* The kind of the step. Represents the same data as the `type` property
* but it's a number for performance.
* @type {1}
* @readonly
*/
kind = 1;

/**
* The target of the step.
* @type {MarkdownNode}
*/
target;

/**
* The phase of the step.
* @type {1|2}
*/
phase;

/**
* The arguments of the step.
* @type {Array<any>}
*/
args;

/**
* Creates a new instance.
* @param {Object} options The options for the step.
* @param {MarkdownNode} options.target The target of the step.
* @param {1|2} options.phase The phase of the step.
* @param {Array<any>} options.args The arguments of the step.
*/
constructor({ target, phase, args }) {
this.target = target;
this.phase = phase;
this.args = args;
}
}

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

/**
* JSON Source Code Object
* @implements {TextSourceCode}
* Markdown Source Code Object
*/
export class MarkdownSourceCode {
export class MarkdownSourceCode extends TextSourceCodeBase {
/**
* Cached traversal steps.
* @type {Array<MarkdownTraversalStep>|undefined}
* @type {Array<VisitNodeStep>|undefined}
*/
#steps;

Expand All @@ -99,29 +44,11 @@ export class MarkdownSourceCode {
*/
#parents = new WeakMap();

/**
* The lines of text in the source code.
* @type {Array<string>}
*/
#lines;

/**
* Cache of ranges.
* @type {WeakMap<MarkdownNode, SourceRange>}
*/
#ranges = new WeakMap();

/**
* The AST of the source code.
* @type {RootNode}
*/
ast;

/**
* The text of the source code.
* @type {string}
*/
text;
ast = undefined;

/**
* Creates a new instance.
Expand All @@ -130,38 +57,10 @@ export class MarkdownSourceCode {
* @param {RootNode} options.ast The root AST node.
*/
constructor({ text, ast }) {
super({ ast, text });
this.ast = ast;
this.text = text;
}

/* eslint-disable class-methods-use-this -- Required to complete interface. */
/**
* Gets the location of the node.
* @param {MarkdownNode} node The node to get the location of.
* @returns {SourceLocation} The location of the node.
*/
getLoc(node) {
return node.position;
}

/**
* Gets the range of the node.
* @param {MarkdownNode} node The node to get the range of.
* @returns {SourceRange} The range of the node.
*/
getRange(node) {
if (!this.#ranges.has(node)) {
this.#ranges.set(node, [
node.position.start.offset,
node.position.end.offset,
]);
}

return this.#ranges.get(node);
}

/* eslint-enable class-methods-use-this -- Required to complete interface. */

/**
* Returns the parent of the given node.
* @param {MarkdownNode} node The node to get the parent of.
Expand All @@ -171,63 +70,6 @@ export class MarkdownSourceCode {
return this.#parents.get(node);
}

/**
* Gets all the ancestors of a given node
* @param {MarkdownNode} node The node
* @returns {Array<MarkdownNode>} All the ancestor nodes in the AST, not including the provided node, starting
* from the root node at index 0 and going inwards to the parent node.
* @throws {TypeError} When `node` is missing.
*/
getAncestors(node) {
if (!node) {
throw new TypeError("Missing required argument: node.");
}

const ancestorsStartingAtParent = [];

for (
let ancestor = this.#parents.get(node);
ancestor;
ancestor = this.#parents.get(ancestor)
) {
ancestorsStartingAtParent.push(ancestor);
}

return ancestorsStartingAtParent.reverse();
}

/**
* Gets the source code for the given node.
* @param {MarkdownNode} [node] The AST node to get the text for.
* @param {number} [beforeCount] The number of characters before the node to retrieve.
* @param {number} [afterCount] The number of characters after the node to retrieve.
* @returns {string} The text representing the AST node.
* @public
*/
getText(node, beforeCount = 0, afterCount = 0) {
if (node) {
const range = this.getRange(node);

return this.text.slice(
Math.max(range[0] - beforeCount, 0),
range[1] + afterCount,
);
}
return this.text;
}

/**
* Gets the entire source text split into an array of lines.
* @returns {Array} The source text as an array of lines.
* @public
*/
get lines() {
if (!this.#lines) {
this.#lines = this.text.split(/\r?\n/gu);
}
return this.#lines;
}

/**
* Traverse the source code and return the steps that were taken.
* @returns {Iterable<TraversalStep>} The steps that were taken while traversing the source code.
Expand All @@ -238,6 +80,7 @@ export class MarkdownSourceCode {
return this.#steps.values();
}

/** @type {Array<VisitNodeStep>} */
const steps = (this.#steps = []);

const visit = (node, parent) => {
Expand All @@ -246,7 +89,7 @@ export class MarkdownSourceCode {

// then add the step
steps.push(
new MarkdownTraversalStep({
new VisitNodeStep({
target: node,
phase: 1,
args: [node, parent],
Expand All @@ -262,7 +105,7 @@ export class MarkdownSourceCode {

// then add the exit step
steps.push(
new MarkdownTraversalStep({
new VisitNodeStep({
target: node,
phase: 2,
args: [node, parent],
Expand Down