Changes
7 changed files (+213/-3)
-
-
@@ -7,6 +7,11 @@ import { gfmFromMarkdown } from "../../deps/esm.sh/mdast-util-gfm/mod.ts";import { mathFromMarkdown } from "../../deps/esm.sh/mdast-util-math/mod.ts"; import { ofmBlockIdentifierFromMarkdown, ofmBlockIdentifierToHastHandlers, type OfmBlockIdentifierToHastHandlersOptions, } from "./mdast_util_ofm_block_identifier.ts"; import { ofmCommentFromMarkdown, ofmCommentToHastHandlers, type OfmCommentToHastHandlersOptions,
-
@@ -27,6 +32,7 @@ export function ofmFromMarkdown(): Extension[] {return [ ...gfmFromMarkdown(), mathFromMarkdown(), ofmBlockIdentifierFromMarkdown(), ofmCommentFromMarkdown(), ofmHighlightFromMarkdown(), ofmWikilinkFromMarkdown(),
-
@@ -38,12 +44,14 @@export interface OfmToHastHandlersOptions { comment?: OfmCommentToHastHandlersOptions; callout?: OfmCalloutToHastHandlersOptions; blockIdentifier?: OfmBlockIdentifierToHastHandlersOptions; } export function ofmToHastHandlers( { comment, callout }: OfmToHastHandlersOptions = {}, { comment, callout, blockIdentifier }: OfmToHastHandlersOptions = {}, ) { return { ...ofmBlockIdentifierToHastHandlers(blockIdentifier), ...ofmCalloutToHastHandlers(callout), ...ofmWikilinkToHastHandlers, ...ofmCommentToHastHandlers(comment),
-
-
-
@@ -0,0 +1,70 @@// SPDX-FileCopyrightText: 2024 Shota FUJI <pockawoooh@gmail.com> // // SPDX-License-Identifier: Apache-2.0 import type { Extension } from "../../deps/esm.sh/mdast-util-from-markdown/mod.ts"; import type { State } from "../../deps/esm.sh/mdast-util-to-hast/mod.ts"; import type * as Hast from "../../deps/esm.sh/hast/types.ts"; import type * as Mdast from "../../deps/esm.sh/mdast/types.ts"; export interface OfmBlockIdentifier extends Mdast.Node { type: "ofmBlockIdentifier"; /** * Identifier name. This does not include the leading caret. */ value: string; } export function ofmBlockIdentifierFromMarkdown(): Extension { return { enter: { ofmBlockIdentifierIdentifier(token) { const ident = this.sliceSerialize(token); this.enter( { type: "ofmBlockIdentifier", value: ident, data: { hName: "span", hProperties: { id: ident, }, }, } satisfies OfmBlockIdentifier as unknown as Mdast.Nodes, token, ); }, }, exit: { ofmBlockIdentifierIdentifier(token) { this.exit(token); }, }, }; } export interface OfmBlockIdentifierToHastHandlersOptions { /** * A function takes an identifier string and returns value for `id` attribute. */ id?(identifier: string): string; } export function ofmBlockIdentifierToHastHandlers( { id }: OfmBlockIdentifierToHastHandlersOptions = {}, ) { return { ofmBlockIdentifier(_state: State, node: OfmBlockIdentifier): Hast.Nodes { return { type: "element", tagName: "span", properties: { id: id ? id(node.value) : node.value, }, children: [], }; }, }; }
-
-
-
@@ -17,6 +17,10 @@ mathHtml,} from "../../deps/esm.sh/micromark-extension-math/mod.ts"; import { ofmBlockIdentifier, ofmBlockIdentifierHtml, } from "./micromark_extension_ofm_block_identifier.ts"; import { ofmComment, ofmCommentHtml, } from "./micromark_extension_ofm_comment.ts";
-
@@ -36,6 +40,7 @@ } from "../../deps/esm.sh/micromark-util-types/types.ts";export function ofm(): Extension { return combineExtensions([ ofmBlockIdentifier(), ofmComment(), ofmWikilink(), ofmHighlight(),
-
@@ -55,6 +60,7 @@ export function ofmHtml({ preserveComment = false, ...rest }: OfmHtmlOptions = {}, ): HtmlExtension { return combineHtmlExtensions([ ofmBlockIdentifierHtml(), ofmCommentHtml({ preserveAsHtmlComment: preserveComment }), ofmHighlightHtml(), ofmWikilinkHtml(),
-
-
-
@@ -0,0 +1,39 @@// SPDX-FileCopyrightText: 2024 Shota FUJI <pockawoooh@gmail.com> // // SPDX-License-Identifier: Apache-2.0 import { assertEquals } from "../../deps/deno.land/std/assert/mod.ts"; import { micromark } from "../../deps/esm.sh/micromark/mod.ts"; import { ofmBlockIdentifier, ofmBlockIdentifierHtml, } from "./micromark_extension_ofm_block_identifier.ts"; function f(markdown: string): string { return micromark(markdown, { extensions: [ofmBlockIdentifier()], htmlExtensions: [ofmBlockIdentifierHtml()], }); } Deno.test("Should parse block identifier", () => { assertEquals( f("Foo Bar ^Baz"), `<p>Foo Bar <span id="Baz"></span></p>`, ); }); Deno.test("Should abort parse when encountered space", () => { assertEquals( f("Foo Bar ^Baz Qux"), `<p>Foo Bar ^Baz Qux</p>`, ); }); Deno.test("Should parse when at the end of block", () => { assertEquals( f("Foo Bar ^Baz\n\nQux"), `<p>Foo Bar <span id="Baz"></span></p>\n<p>Qux</p>`, ); });
-
-
-
@@ -0,0 +1,87 @@// SPDX-FileCopyrightText: 2024 Shota FUJI <pockawoooh@gmail.com> // // SPDX-License-Identifier: Apache-2.0 import type { CompileContext, Extension, HtmlExtension, State, Token, } from "../../deps/esm.sh/micromark-util-types/types.ts"; import { codes } from "../../deps/esm.sh/micromark-util-symbol/mod.ts"; import { asciiAlphanumeric, markdownSpace, } from "../../deps/esm.sh/micromark-util-character/mod.ts"; const enum TokenTypeMap { block = "ofmBlockIdentifier", caret = "ofmBlockIdentifierCaret", ident = "ofmBlockIdentifierIdentifier", } export function ofmBlockIdentifierHtml(): HtmlExtension { return { enter: { // @ts-expect-error: micromark heavily relies on ambient module declarations, // which Deno does not support. APIs also don't accept type parameters. [TokenTypeMap.ident](this: CompileContext, token: Token) { this.tag(`<span id="${this.sliceSerialize(token)}"></span>`); }, }, }; } export function ofmBlockIdentifier(): Extension { return { text: { [codes.caret]: { tokenize(effects, ok, nok) { const { previous } = this; const start: State = (code) => { if (!markdownSpace(previous) || code !== codes.caret) { return nok(code); } // @ts-expect-error: micromark heavily relies on ambient module declarations, // which Deno does not support. APIs also don't accept type parameters. effects.enter(TokenTypeMap.block); // @ts-expect-error: micromark heavily relies on ambient module declarations, // which Deno does not support. APIs also don't accept type parameters. effects.enter(TokenTypeMap.caret); effects.consume(code); // @ts-expect-error: micromark heavily relies on ambient module declarations, // which Deno does not support. APIs also don't accept type parameters. effects.exit(TokenTypeMap.caret); // @ts-expect-error: micromark heavily relies on ambient module declarations, // which Deno does not support. APIs also don't accept type parameters. effects.enter(TokenTypeMap.ident); return ident; }; const ident: State = (code) => { if (asciiAlphanumeric(code) || code === codes.dash) { effects.consume(code); return ident; } if (code === codes.eof) { // @ts-expect-error: micromark heavily relies on ambient module declarations, // which Deno does not support. APIs also don't accept type parameters. effects.exit(TokenTypeMap.ident); return ok(code); } return nok(code); }; return start; }, }, }, }; }
-
-
-
@@ -90,7 +90,7 @@- [Basic writing and formatting syntax - GitHub Docs](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#alerts) Syntax-wise, a valid GFM Alert is a valid OFM Callout: <math><mi>Alert</mi><mo>⊂</mo><mi>Callout</mi></math>. However, the `CAUTION` type will be rendered as same variant as `WARNING` type, as shown below. However, the `CAUTION` type will be rendered as same variant as `WARNING` type, as shown below. ^alert-callout-compat ```markdown > [!WARNING]
-
-
-
@@ -47,7 +47,7 @@ - [x] Wikilink- [x] Label - [x] Heading - [ ] Block reference - [ ] Defining a block - [x] Defining a block - [x] Image size annotation - [ ] Embeddings - [x] Image file
-