Skip to content
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
3 changes: 2 additions & 1 deletion src/language/markdown-source-code.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
ConfigCommentParser,
Directive,
} from "@eslint/plugin-kit";
import { lineEndingPattern } from "../util.js";

//-----------------------------------------------------------------------------
// Types
Expand Down Expand Up @@ -152,7 +153,7 @@ export class MarkdownSourceCode extends TextSourceCodeBase {
* @param {Root} options.ast The root AST node.
*/
constructor({ text, ast }) {
super({ ast, text });
super({ ast, text, lineEndingPattern });
this.ast = ast;

// need to traverse the source code to get the inline config nodes
Expand Down
16 changes: 11 additions & 5 deletions src/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@
// Regex Patterns
//-----------------------------------------------------------------------------

/**
* Line ending pattern to match all line endings (CRLF, CR, LF). (CommonMark spec)
* @see https://spec.commonmark.org/0.31.2/#line-ending
*/
export const lineEndingPattern = /\r\n|[\r\n]/u;

/**
* CommonMark does not allow any white space between the brackets in a reference link.
* If that pattern is detected, then it's treated as text and not as a link. This pattern
Expand All @@ -24,16 +30,16 @@ export const htmlCommentPattern = /<!--[\s\S]*?-->/gu;
//-----------------------------------------------------------------------------

/**
* Checks if a frontmatter block contains a title matching the given pattern
* @param {string} value The frontmatter content
* @param {RegExp|null} pattern The pattern to match against
* @returns {boolean} Whether a title was found
* Checks if a frontmatter block contains a title matching the given pattern.
* @param {string} value The frontmatter content.
* @param {RegExp|null} pattern The pattern to match against.
* @returns {boolean} Whether a title was found.
*/
export function frontmatterHasTitle(value, pattern) {
if (!pattern) {
return false;
}
const lines = value.split("\n");
const lines = value.split(lineEndingPattern);
for (const line of lines) {
if (pattern.test(line)) {
return true;
Expand Down
61 changes: 61 additions & 0 deletions tests/language/markdown-source-code.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,67 @@ describe("MarkdownSourceCode", () => {
sourceCode = new MarkdownSourceCode({ text: markdownText, ast });
});

describe("constructor", () => {
it("should create a MarkdownSourceCode instance", () => {
assert.strictEqual(
sourceCode.constructor.name,
"MarkdownSourceCode",
);
assert.strictEqual(sourceCode.ast, ast);
assert.strictEqual(sourceCode.text, markdownText);
});
});

describe("lines", () => {
it("should parse CRLF line endings", () => {
const text = "lumir\r\nlumir";
const sourceCodeWithCRLF = new MarkdownSourceCode({
text,
ast: fromMarkdown(text),
});

assert.deepStrictEqual(sourceCodeWithCRLF.lines, [
"lumir",
"lumir",
]);
});

it("should parse CR line endings", () => {
const text = "lumir\rlumir";
const sourceCodeWithCR = new MarkdownSourceCode({
text,
ast: fromMarkdown(text),
});

assert.deepStrictEqual(sourceCodeWithCR.lines, ["lumir", "lumir"]);
});

it("should parse LF line endings", () => {
const text = "lumir\nlumir";
const sourceCodeWithLF = new MarkdownSourceCode({
text,
ast: fromMarkdown(text),
});

assert.deepStrictEqual(sourceCodeWithLF.lines, ["lumir", "lumir"]);
});

it("should parse CRLF CR LF line endings", () => {
const text = "lumir\r\nlumir\rlumir\nlumir";
const sourceCodeWithCRLFCRLF = new MarkdownSourceCode({
text,
ast: fromMarkdown(text),
});

assert.deepStrictEqual(sourceCodeWithCRLFCRLF.lines, [
"lumir",
"lumir",
"lumir",
"lumir",
]);
});
});

describe("getText()", () => {
it("should return the text of the Markdown source code", () => {
assert.strictEqual(sourceCode.getText(), markdownText);
Expand Down
20 changes: 19 additions & 1 deletion tests/util.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,25 @@ describe("util", () => {
);
});

it("should return true if the pattern matches any line in multiline frontmatter", () => {
it("should return true if the pattern matches any line in multiline frontmatter (CRLF)", () => {
const frontmatter = [
"description: Test",
"title: My Document",
"author: lumirlumir",
].join("\r\n");
assert.strictEqual(frontmatterHasTitle(frontmatter, pattern), true);
});

it("should return true if the pattern matches any line in multiline frontmatter (CR)", () => {
const frontmatter = [
"description: Test",
"title: My Document",
"author: lumirlumir",
].join("\r");
assert.strictEqual(frontmatterHasTitle(frontmatter, pattern), true);
});

it("should return true if the pattern matches any line in multiline frontmatter (LF)", () => {
const frontmatter = [
"description: Test",
"title: My Document",
Expand Down