@blocknote/core
Version:
A "Notion-style" block-based extensible text editor built on top of Prosemirror and Tiptap.
212 lines (182 loc) • 8.29 kB
text/typescript
import { describe, expect, it } from "vitest";
import { isMarkdown } from "./detectMarkdown.js";
describe("isMarkdown", () => {
describe("Headings (H1-H6)", () => {
it("should detect H1 headings", () => {
expect(isMarkdown("# Heading 1\n\nContent")).toBe(true);
expect(isMarkdown(" # Heading 1\n\nContent")).toBe(true);
expect(isMarkdown(" # Heading 1\n\nContent")).toBe(true);
});
it("should detect H2-H6 headings", () => {
expect(isMarkdown("## Heading 2\n\nContent")).toBe(true);
expect(isMarkdown("### Heading 3\n\nContent")).toBe(true);
expect(isMarkdown("#### Heading 4\n\nContent")).toBe(true);
expect(isMarkdown("##### Heading 5\n\nContent")).toBe(true);
expect(isMarkdown("###### Heading 6\n\nContent")).toBe(true);
});
it("should not detect invalid headings", () => {
expect(isMarkdown("####### Heading 7\n\nContent")).toBe(false);
expect(isMarkdown("#Heading without space\n\nContent")).toBe(false);
expect(isMarkdown("# \n\nContent")).toBe(false);
expect(
isMarkdown(
"# Very long heading that exceeds the character limit and should not be detected as a valid markdown heading\n\nContent",
),
).toBe(false);
});
});
describe("Bold, italic, underline, strikethrough, highlight", () => {
it("should detect bold text", () => {
expect(isMarkdown("**bold text**")).toBe(true);
expect(isMarkdown("__bold text__")).toBe(true);
expect(isMarkdown(" *bold text* ")).toBe(true);
expect(isMarkdown(" _bold text_ ")).toBe(true);
});
it("should detect italic text", () => {
expect(isMarkdown("*italic text*")).toBe(true);
expect(isMarkdown("_italic text_")).toBe(true);
});
it("should detect strikethrough text", () => {
expect(isMarkdown("~~strikethrough text~~")).toBe(true);
});
it("should detect highlighted text", () => {
expect(isMarkdown("==highlighted text==")).toBe(true);
expect(isMarkdown("++highlighted text++")).toBe(true);
});
});
describe("Links", () => {
it("should detect basic links", () => {
expect(isMarkdown("[Link text](https://example.com)")).toBe(true);
expect(isMarkdown("[Link text](http://example.com)")).toBe(true);
expect(isMarkdown("[Short](https://ex.com)")).toBe(true);
});
it("should detect image links", () => {
expect(isMarkdown("")).toBe(
true,
);
});
});
describe("Inline code", () => {
it("should detect inline code", () => {
expect(isMarkdown("`code`")).toBe(true);
expect(isMarkdown(" `code` ")).toBe(true);
expect(isMarkdown("`const x = 1;`")).toBe(true);
});
it("should not detect invalid inline code", () => {
expect(isMarkdown("` code `")).toBe(false); // spaces around content
expect(isMarkdown("``")).toBe(false); // empty
expect(isMarkdown("` `")).toBe(false); // only space
});
});
describe("Unordered lists", () => {
it("should detect unordered lists", () => {
expect(isMarkdown("- Item 1\n- Item 2")).toBe(true);
expect(isMarkdown(" - Item 1\n - Item 2")).toBe(true);
expect(isMarkdown(" - Item 1\n - Item 2")).toBe(true);
expect(isMarkdown(" - Item 1\n - Item 2")).toBe(true);
expect(isMarkdown(" - Item 1\n - Item 2")).toBe(true);
expect(isMarkdown(" - Item 1\n - Item 2")).toBe(true);
});
it("should not detect invalid unordered lists", () => {
expect(isMarkdown("- Item 1")).toBe(false); // single item
expect(isMarkdown("-- Item 1\n-- Item 2")).toBe(false); // wrong marker
expect(isMarkdown("-Item 1\n-Item 2")).toBe(false); // no space after marker
});
});
describe("Ordered lists", () => {
it("should detect ordered lists", () => {
expect(isMarkdown("1. Item 1\n2. Item 2")).toBe(true);
expect(isMarkdown(" 1. Item 1\n 2. Item 2")).toBe(true);
expect(isMarkdown(" 1. Item 1\n 2. Item 2")).toBe(true);
expect(isMarkdown(" 1. Item 1\n 2. Item 2")).toBe(true);
expect(isMarkdown(" 1. Item 1\n 2. Item 2")).toBe(true);
expect(isMarkdown(" 1. Item 1\n 2. Item 2")).toBe(true);
});
it("should not detect invalid ordered lists", () => {
expect(isMarkdown("1. Item 1")).toBe(false); // single item
expect(isMarkdown("1 Item 1\n2 Item 2")).toBe(false); // no dot
expect(isMarkdown("1.Item 1\n2.Item 2")).toBe(false); // no space after dot
});
});
describe("Horizontal rules", () => {
it("should detect horizontal rules", () => {
expect(isMarkdown("\n\n ---\n\n")).toBe(true);
expect(isMarkdown("\n\n ----\n\n")).toBe(true);
expect(isMarkdown("\n\n ---\n\n")).toBe(true);
expect(isMarkdown("\n\n ---\n\n")).toBe(true);
});
});
describe("Fenced code blocks", () => {
it("should detect fenced code blocks", () => {
expect(isMarkdown("```\ncode block\n```")).toBe(true);
expect(isMarkdown("~~~\ncode block\n~~~")).toBe(true);
expect(isMarkdown("```javascript\nconst x = 1;\n```")).toBe(true);
expect(isMarkdown("```js\nconst x = 1;\n```")).toBe(true);
});
});
describe("Classical underlined headings", () => {
it("should detect H1 with equals", () => {
expect(isMarkdown("Heading\n===\n\nContent")).toBe(true);
expect(isMarkdown("Heading\n====\n\nContent")).toBe(true);
});
it("should detect H2 with dashes", () => {
expect(isMarkdown("Heading\n---\n\nContent")).toBe(true);
expect(isMarkdown("Heading\n----\n\nContent")).toBe(true);
});
});
describe("Blockquotes", () => {
it("should detect blockquotes", () => {
expect(isMarkdown("> This is a blockquote\n\nContent")).toBe(true);
expect(isMarkdown(" > This is a blockquote\n\nContent")).toBe(true);
expect(isMarkdown(" > This is a blockquote\n\nContent")).toBe(true);
expect(isMarkdown(" > This is a blockquote\n\nContent")).toBe(true);
});
it("should detect multi-line blockquotes", () => {
expect(isMarkdown("> Line 1\n> Line 2\n\nContent")).toBe(true);
expect(isMarkdown("> Line 1\n> Line 2\n> Line 3\n\nContent")).toBe(true);
});
});
describe("Tables", () => {
it("should detect table headers", () => {
expect(isMarkdown("| Header 1 | Header 2 |\n")).toBe(true);
expect(isMarkdown("| Header 1 | Header 2 | Header 3 |\n")).toBe(true);
});
it("should detect table dividers", () => {
expect(isMarkdown("| --- | --- |\n")).toBe(true);
expect(isMarkdown("| :--- | ---: |\n")).toBe(true);
expect(isMarkdown("| :---: | --- |\n")).toBe(true);
});
it("should detect table rows", () => {
expect(isMarkdown("| Cell 1 | Cell 2 |\n")).toBe(true);
expect(isMarkdown("| Cell 1 | Cell 2 | Cell 3 |\n")).toBe(true);
});
it("should detect complete tables", () => {
const table =
"| Header 1 | Header 2 |\n| --- | --- |\n| Cell 1 | Cell 2 |\n";
expect(isMarkdown(table)).toBe(true);
});
it("should not detect invalid tables", () => {
expect(isMarkdown("| Header 1 | Header 2\n")).toBe(false); // missing closing pipe
expect(isMarkdown("Header 1 | Header 2 |\n")).toBe(false); // missing opening pipe
});
});
describe("Edge cases and combinations", () => {
it("should detect mixed markdown content", () => {
const mixedContent =
"# Heading\n\nThis is **bold** and *italic* text with a [link](https://example.com).\n\n- List item 1\n- List item 2\n\n> Blockquote\n\n```\ncode block\n```";
expect(isMarkdown(mixedContent)).toBe(true);
});
it("should not detect plain text", () => {
expect(
isMarkdown("This is just plain text without any markdown formatting."),
).toBe(false);
expect(isMarkdown("")).toBe(false);
expect(isMarkdown(" \n \n ")).toBe(false); // only whitespace
});
it("should handle special characters", () => {
expect(isMarkdown("**text with `backticks`**")).toBe(true);
expect(isMarkdown("**text with [brackets]**")).toBe(true);
expect(isMarkdown("**text with (parentheses)**")).toBe(true);
});
});
});