Changes
6 changed files (+160/-15)
-
-
@@ -105,7 +105,10 @@ >,): Promise<Mdast.Root> { const mdast = fromMarkdown(markdown, { extensions: [ofm()], mdastExtensions: [ofmFromMarkdown(), autoHeadingIdFromMarkdown()], mdastExtensions: [ ofmFromMarkdown({ blockIdentifier: { hoist: true } }), autoHeadingIdFromMarkdown(), ], }); await macanaMarkAssets(mdast, getAssetToken);
-
@@ -114,6 +117,26 @@return mdast; } function haveId<Node extends Mdast.Node>( node: Node, ): node is Node & { data: { hProperties: { id: string } } } { if ( !node.data || !("hProperties" in node.data) || typeof node.data.hProperties !== "object" || !node.data.hProperties ) { return false; } if ( !("id" in node.data.hProperties) || typeof node.data.hProperties.id !== "string" ) { return false; } return true; } function findNodeId( root: Mdast.Root, selectors: readonly string[],
-
@@ -127,10 +150,22 @@if (selector.startsWith("^")) { const ident = selector.slice(1); const found = findNode(root, (node) => ( !!(node.data && node.type === "ofmBlockIdentifier" && (node as OfmBlockIdentifier).value === ident) )); const found = findNode(root, (node) => { // Non-hoisted block identifier if ( node.type === "ofmBlockIdentifier" && (node as OfmBlockIdentifier).value === ident ) { return true; } // Hoisted parent block if (!haveId(node)) { return false; } return node.data.hProperties.id === ident; }); if (!found) { logger().error(
-
@@ -160,12 +195,7 @@ found = findNodeId({ type: "root", children: nodes }, rest);return; } if ( !start.data || !("hProperties" in start.data) || typeof start.data.hProperties !== "object" || !start.data.hProperties || !("id" in start.data.hProperties) || typeof start.data.hProperties.id !== "string" ) { if (!haveId(start)) { return; }
-
-
-
@@ -8,6 +8,7 @@ import { mathFromMarkdown } from "../../deps/esm.sh/mdast-util-math/mod.ts";import { ofmBlockIdentifierFromMarkdown, type OfmBlockIdentifierFromMarkdownOptions, ofmBlockIdentifierToHastHandlers, type OfmBlockIdentifierToHastHandlersOptions, } from "./mdast_util_ofm_block_identifier.ts";
-
@@ -30,11 +31,17 @@ import { ofmImageSize } from "./mdast_util_ofm_image_size.ts";export type { OfmBlockIdentifier } from "./mdast_util_ofm_block_identifier.ts"; export function ofmFromMarkdown(): Extension[] { export interface OfmFromMarkdownOptions { blockIdentifier?: OfmBlockIdentifierFromMarkdownOptions; } export function ofmFromMarkdown( { blockIdentifier }: OfmFromMarkdownOptions = {}, ): Extension[] { return [ ...gfmFromMarkdown(), mathFromMarkdown(), ofmBlockIdentifierFromMarkdown(), ofmBlockIdentifierFromMarkdown(blockIdentifier), ofmCommentFromMarkdown(), ofmHighlightFromMarkdown(), ofmWikilinkFromMarkdown(),
-
-
-
@@ -0,0 +1,37 @@// SPDX-FileCopyrightText: 2024 Shota FUJI <pockawoooh@gmail.com> // // SPDX-License-Identifier: Apache-2.0 import { assertObjectMatch } from "../../deps/deno.land/std/assert/mod.ts"; import { fromMarkdown } from "../../deps/esm.sh/mdast-util-from-markdown/mod.ts"; import { ofmBlockIdentifierFromMarkdown } from "./mdast_util_ofm_block_identifier.ts"; import { ofmBlockIdentifier } from "./micromark_extension_ofm_block_identifier.ts"; Deno.test("Should hoist ID", () => { const mdast = fromMarkdown("Foo Bar ^Baz", { extensions: [ofmBlockIdentifier()], mdastExtensions: [ofmBlockIdentifierFromMarkdown({ hoist: true })], }); assertObjectMatch(mdast, { type: "root", children: [ { type: "paragraph", data: { hProperties: { id: "Baz", }, }, children: [ { type: "text", value: "Foo Bar ", }, ], }, ], }); });
-
-
-
@@ -6,6 +6,7 @@ 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"; import { visit } from "../../deps/esm.sh/unist-util-visit/mod.ts"; export interface OfmBlockIdentifier extends Mdast.Node { type: "ofmBlockIdentifier";
-
@@ -16,7 +17,21 @@ */value: string; } export function ofmBlockIdentifierFromMarkdown(): Extension { function isOfmBlockIdentifier(node: Mdast.Node): node is OfmBlockIdentifier { return node.type === "ofmBlockIdentifier"; } export interface OfmBlockIdentifierFromMarkdownOptions { /** * Whether to set the ID to the parent node, instead of leaving * "ofmBlockIdentifier" node. */ hoist?: boolean; } export function ofmBlockIdentifierFromMarkdown( { hoist = false }: OfmBlockIdentifierFromMarkdownOptions = {}, ): Extension { return { enter: { ofmBlockIdentifierIdentifier(token) {
-
@@ -42,6 +57,33 @@ ofmBlockIdentifierIdentifier(token) {this.exit(token); }, }, transforms: hoist ? [ (nodes) => { visit(nodes, (node) => isOfmBlockIdentifier(node), (node, index, parent) => { if ( !isOfmBlockIdentifier(node) || typeof index !== "number" || !parent ) { return; } parent.data = { ...parent.data, hProperties: { id: (node as OfmBlockIdentifier).value, ...(parent.data && "hProperties" in parent.data && parent.data.hProperties || {}), }, }; parent.children.splice(index, 1); return; }); }, ] : [], }; }
-
-
-
@@ -8,6 +8,8 @@ import { type Handlers } from "../../../deps/esm.sh/mdast-util-to-hast/mod.ts";import { buildClasses, css } from "../css.ts"; import { getRequestedId } from "./utils.ts"; const c = buildClasses("fm-p", ["paragraph"]); export const paragraphStyles = css`
-
@@ -22,7 +24,9 @@export function paragraphHandlers(): Handlers { return { paragraph(state, node: Mdast.Paragraph) { return h("p", { class: c.paragraph }, state.all(node)); const id = getRequestedId(node) ?? undefined; return h("p", { id, class: c.paragraph }, state.all(node)); }, }; }
-
-
-
@@ -0,0 +1,25 @@// SPDX-FileCopyrightText: 2024 Shota FUJI <pockawoooh@gmail.com> // // SPDX-License-Identifier: Apache-2.0 import type * as Mdast from "../../../deps/esm.sh/mdast/types.ts"; export function getRequestedId<Node extends Mdast.Node>( node: Node, ): string | null { if ( !node.data || !("hProperties" in node.data) || typeof node.data.hProperties !== "object" || !node.data.hProperties ) { return null; } if ( !("id" in node.data.hProperties) || typeof node.data.hProperties.id !== "string" ) { return null; } return node.data.hProperties.id; }
-