From 1a5f3f33463f56a60c48cae32a6647a9fd5f3d48 Mon Sep 17 00:00:00 2001 From: Spencer Lyon Date: Wed, 21 Aug 2024 11:07:33 -0400 Subject: [PATCH] =?UTF-8?q?=E2=90=A1=20Enable=20strikethrough=20as=20markd?= =?UTF-8?q?ownit=20extension=20(#1427)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Rowan Cockett --- .changeset/tasty-fireants-behave.md | 5 +++ packages/myst-parser/src/fromMarkdown.ts | 1 + packages/myst-parser/src/myst.ts | 2 + packages/myst-parser/src/tokensToMyst.ts | 1 + .../myst-parser/tests/strikethrough.spec.ts | 42 +++++++++++++++++++ 5 files changed, 51 insertions(+) create mode 100644 .changeset/tasty-fireants-behave.md create mode 100644 packages/myst-parser/tests/strikethrough.spec.ts diff --git a/.changeset/tasty-fireants-behave.md b/.changeset/tasty-fireants-behave.md new file mode 100644 index 000000000..a10e61692 --- /dev/null +++ b/.changeset/tasty-fireants-behave.md @@ -0,0 +1,5 @@ +--- +"myst-parser": patch +--- + +Enable strikethrough as markdownit extension diff --git a/packages/myst-parser/src/fromMarkdown.ts b/packages/myst-parser/src/fromMarkdown.ts index 66c7f98ed..ded429ecd 100644 --- a/packages/myst-parser/src/fromMarkdown.ts +++ b/packages/myst-parser/src/fromMarkdown.ts @@ -55,6 +55,7 @@ export type AllOptions = { tasklist?: boolean; tables?: boolean; blocks?: boolean; + strikethrough?: boolean; }; mdast: MdastOptions; directives: DirectiveSpec[]; diff --git a/packages/myst-parser/src/myst.ts b/packages/myst-parser/src/myst.ts index 4c1f4b20e..c0424f338 100644 --- a/packages/myst-parser/src/myst.ts +++ b/packages/myst-parser/src/myst.ts @@ -41,6 +41,7 @@ export const defaultOptions: Omit = { tasklist: true, tables: true, blocks: true, + strikethrough: false, }, mdast: {}, directives: defaultDirectives, @@ -75,6 +76,7 @@ export function createTokenizer(opts?: Options) { if (markdownit.linkify) { tokenizer.linkify.tlds(tlds.filter((tld) => !EXCLUDE_TLDS.includes(tld))); } + if (extensions.strikethrough) tokenizer.enable('strikethrough'); if (extensions.smartquotes) tokenizer.enable('smartquotes'); if (extensions.tables) tokenizer.enable('table'); if (extensions.colonFences) tokenizer.use(colonFencePlugin); diff --git a/packages/myst-parser/src/tokensToMyst.ts b/packages/myst-parser/src/tokensToMyst.ts index 9a4e37d06..d69473882 100644 --- a/packages/myst-parser/src/tokensToMyst.ts +++ b/packages/myst-parser/src/tokensToMyst.ts @@ -91,6 +91,7 @@ const defaultMdast: Record = { }; }, }, + s: { type: 'delete' }, hr: { type: 'thematicBreak', noCloseToken: true, diff --git a/packages/myst-parser/tests/strikethrough.spec.ts b/packages/myst-parser/tests/strikethrough.spec.ts new file mode 100644 index 000000000..d78feb992 --- /dev/null +++ b/packages/myst-parser/tests/strikethrough.spec.ts @@ -0,0 +1,42 @@ +import { describe, expect, it } from 'vitest'; +import { visit } from 'unist-util-visit'; +import { mystParse } from '../src'; +import type { GenericParent } from 'myst-common'; + +function stripPositions(tree: GenericParent) { + visit(tree, (node) => { + delete node.position; + }); + return tree; +} + +describe('strikethrough', () => { + it('strikethrough in paragraph', () => { + const content = 'A ~~div~~ paragraph!'; + expect(stripPositions(mystParse(content))).toEqual({ + type: 'root', + children: [ + { + type: 'paragraph', + children: [{ type: 'text', value: 'A ~~div~~ paragraph!' }], + }, + ], + }); + expect(stripPositions(mystParse(content, { extensions: { strikethrough: true } }))).toEqual({ + type: 'root', + children: [ + { + type: 'paragraph', + children: [ + { type: 'text', value: 'A ' }, + { + type: 'delete', + children: [{ type: 'text', value: 'div' }], + }, + { type: 'text', value: ' paragraph!' }, + ], + }, + ], + }); + }); +});