Skip to content

Commit 13a2850

Browse files
committed
use plugin map / remove prerender
1 parent b4330d8 commit 13a2850

File tree

7 files changed

+41
-51
lines changed

7 files changed

+41
-51
lines changed

src/block-parser.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ export const blockParser = (
3131
const line = allLines.pop()!;
3232
// Work with previous multi-line block
3333
if (type) {
34-
const plugin = options.blockPlugins.find((p) => p.type === type);
34+
const plugin = options.blockPlugins.get(type)!;
3535
if (plugin === undefined) throw new Error("undefined plugin");
3636
// Check for end of multi-line block
3737
if (plugin.matchEnd) {
@@ -50,7 +50,7 @@ export const blockParser = (
5050
continue;
5151
}
5252
// Check for new block match
53-
for (const plugin of options.blockPlugins) {
53+
for (const plugin of options.blockPlugins.values()) {
5454
let newMatches = plugin.matchStart(line, 0);
5555
if (newMatches === false) {
5656
continue;

src/block-stream.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ export class BlockStream extends TransformStream<string, HmmBlock> {
3636
};
3737
// Work with previous multi-line block
3838
if (type) {
39-
const plugin = options.blockPlugins.find((p) => p.type === type);
39+
const plugin = options.blockPlugins.get(type)!;
4040
if (plugin === undefined) throw new Error("undefined plugin");
4141
// Check for end of multi-line block
4242
if (plugin.matchEnd) {
@@ -55,7 +55,7 @@ export class BlockStream extends TransformStream<string, HmmBlock> {
5555
return;
5656
}
5757
// Check for new block match
58-
for (const plugin of options.blockPlugins) {
58+
for (const plugin of options.blockPlugins.values()) {
5959
let newMatches = plugin.matchStart(line, 0);
6060
if (newMatches === false) {
6161
continue;

src/inline-plugins/anchor.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,10 @@ const plugin: InlinePlugin = {
8080
}
8181
text = await renderInline(text, {
8282
...options,
83-
inlinePlugins: options.inlinePlugins.filter((plugin) =>
84-
inlinePlugins.includes(plugin.type)
83+
inlinePlugins: new Map(
84+
[...options.inlinePlugins].filter(([type]) =>
85+
inlinePlugins.includes(type)
86+
),
8587
),
8688
});
8789
out = out.replace(anchor, () => `<a href="${escape(href)}">${text}</a>`);

src/inline-plugins/code.ts

-9
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,9 @@
11
import type { InlinePlugin } from "../types.ts";
2-
import { escape, unescape } from "@dbushell/hyperless";
32

43
const REGEXP = /`([^`]+)`/g;
54

65
const plugin: InlinePlugin = {
76
type: "code",
8-
prerender: (text: string) => {
9-
if (text.indexOf("`") === -1) return text;
10-
// Inline code is escaped early to avoid `<div>` being parsed as HTML node
11-
return text.replace(REGEXP, (...match) => {
12-
const text = unescape(match[0]);
13-
return escape(text);
14-
});
15-
},
167
render: (text: string) => {
178
text = text.replace(REGEXP, (...match) => `<code>${match[1]}</code>`);
189
return Promise.resolve(text);

src/mod.ts

+30-32
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import type { HmmBlock, HmmOptions } from "./types.ts";
2+
import { TextLineStream } from "@std/streams/text-line-stream";
3+
import { escape, unescape } from "@dbushell/hyperless";
24
import { blockParser } from "./block-parser.ts";
35
import { BlockStream } from "./block-stream.ts";
4-
import { TextLineStream } from "@std/streams/text-line-stream";
56

67
// Block Plugins
78
import blockBlockquote from "./block-plugins/blockquote.ts";
@@ -25,27 +26,27 @@ import inlineTypography from "./inline-plugins/typography.ts";
2526

2627
// Default options
2728
export const defaultOptions: HmmOptions = {
28-
blockPlugins: [
29-
blockBlockquote,
30-
blockPreformatted,
31-
blockHeading,
32-
blockHorizontalRule,
33-
blockImage,
34-
blockOrderedList,
35-
blockUnorderedList,
36-
blockParagraph,
37-
],
29+
blockPlugins: new Map([
30+
[blockBlockquote.type, blockBlockquote],
31+
[blockPreformatted.type, blockPreformatted],
32+
[blockHeading.type, blockHeading],
33+
[blockHorizontalRule.type, blockHorizontalRule],
34+
[blockImage.type, blockImage],
35+
[blockOrderedList.type, blockOrderedList],
36+
[blockUnorderedList.type, blockUnorderedList],
37+
[blockParagraph.type, blockParagraph],
38+
]),
3839
// Order is significant
39-
inlinePlugins: [
40-
inlineTypography,
41-
inlineEscape,
42-
inlineImage,
43-
inlineAnchor,
44-
inlineCode,
45-
inlineStrong,
46-
inlineEmphasis,
47-
inlineDeleted,
48-
],
40+
inlinePlugins: new Map([
41+
[inlineTypography.type, inlineTypography],
42+
[inlineEscape.type, inlineEscape],
43+
[inlineImage.type, inlineImage],
44+
[inlineAnchor.type, inlineAnchor],
45+
[inlineCode.type, inlineCode],
46+
[inlineStrong.type, inlineStrong],
47+
[inlineEmphasis.type, inlineEmphasis],
48+
[inlineDeleted.type, inlineDeleted],
49+
]),
4950
};
5051

5152
export const parse = async (
@@ -66,26 +67,23 @@ export const parse = async (
6667
.pipeThrough(new BlockStream(options));
6768
}
6869

69-
// Get pre-render plugins
70-
const prerender = options.inlinePlugins.filter((plugin) =>
71-
Object.hasOwn(plugin, "prerender")
72-
);
73-
7470
// Final block renders
7571
const blocks: Array<Promise<string>> = [];
7672

7773
for await (const block of stream) {
78-
// Apply pre-render plugins to all lines
7974
if (block.type !== "preformatted") {
75+
// Inline code is escaped early to avoid `<div>` being parsed as HTML node
8076
for (let i = 0; i < block.lines.length; i++) {
81-
prerender.forEach((plugin) => {
82-
block.lines[i] = plugin.prerender!(block.lines[i], options);
83-
});
77+
if (block.lines[i].includes("`") === false) continue;
78+
block.lines[i] = block.lines[i].replace(
79+
/`([^`]+)`/g,
80+
(...match) => escape(unescape(match[0])),
81+
);
8482
}
8583
}
8684
// Start block render
87-
const plugin = options.blockPlugins.find((p) => p.type === block.type)!;
88-
blocks.push(Promise.resolve(plugin.render(block, options)));
85+
const plugin = options.blockPlugins.get(block.type)!;
86+
blocks.push(plugin.render(block, options));
8987
}
9088
return blocks;
9189
};

src/render.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ export const renderInline = async (
1515
text: string,
1616
options: HmmOptions,
1717
): Promise<string> => {
18-
for (const plugin of options.inlinePlugins) {
18+
for (const plugin of options.inlinePlugins.values()) {
1919
if (["anchor", "code"].includes(plugin.type)) {
2020
text = await plugin.render(text, options);
2121
} else {

src/types.ts

+2-3
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,10 @@ export type BlockPlugin = {
1919
export type InlinePlugin = {
2020
type: string;
2121
render: (text: string, options: HmmOptions) => Promise<string>;
22-
prerender?: (text: string, options: HmmOptions) => string;
2322
};
2423

2524
/** Markdown block stream options */
2625
export type HmmOptions = {
27-
blockPlugins: Array<BlockPlugin>;
28-
inlinePlugins: Array<InlinePlugin>;
26+
blockPlugins: Map<string, BlockPlugin>;
27+
inlinePlugins: Map<string, InlinePlugin>;
2928
};

0 commit comments

Comments
 (0)