Skip to content

Commit

Permalink
feat(remark): add support for ==mark==
Browse files Browse the repository at this point in the history
  • Loading branch information
memset0 committed Sep 16, 2024
1 parent fa98399 commit b32b5e4
Show file tree
Hide file tree
Showing 4 changed files with 202 additions and 71 deletions.
8 changes: 7 additions & 1 deletion plugins/gatsby-remark-custom/index.mjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import mdastDisableLocalLink from "./mdastDisableLocalLink.mjs";
import mdastImageControl from "./mdastImageControl.mjs";
import remarkSpoiler from "./remarkSpoiler.mjs";
import remarkMark from "./remarkMark.mjs";

function gatsbyRemarkCustom({ markdownAST }) {
// 禁用指向本地文件的链接
Expand All @@ -11,6 +12,11 @@ function gatsbyRemarkCustom({ markdownAST }) {
}

// 注入自定义remark插件
gatsbyRemarkCustom.setParserPlugins = () => [remarkSpoiler];
gatsbyRemarkCustom.setParserPlugins = () => [
// 支持标记语法
remarkMark,
// 支持Spoiler语法
remarkSpoiler,
];

export default gatsbyRemarkCustom;
123 changes: 123 additions & 0 deletions plugins/gatsby-remark-custom/remarkMark.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
/**
* @import {Processor} from 'unified'
*/

import { markdownLineEnding } from "micromark-util-character";
import { factorySpace } from "micromark-factory-space";
import { codes, types, constants } from "micromark-util-symbol";

function micromarkExt() {
const marker = {
partial: true,
tokenize: function (effects, ok, nok) {
let markerSize = 0;
if (this.previous === codes.equalsTo) {
return nok;
}
const start = function (code) {
effects.enter("markMarker");
return marker;
};
const marker = function (code) {
if (code === codes.equalsTo) {
effects.consume(code);
markerSize++;
return marker;
}
if (markerSize == 2) {
effects.exit("markMarker");
markerSize = 0;
return ok;
}
return nok;
};
return factorySpace(effects, start, types.whitespace);
},
};

const mark = {
name: "mark",
tokenize: function (effects, ok, nok) {
const start = function (code) {
effects.enter("mark");
return effects.attempt(marker, factorySpace(effects, contentStart, types.whitespace), nok);
};
const contentStart = function (code) {
effects.enter(types.chunkText, {
contentType: constants.contentTypeText,
});
return content;
};
const content = function (code) {
return effects.check(marker, factorySpace(effects, contentAfter, types.whitespace), comsumeData);
};
const comsumeData = function (code) {
if (markdownLineEnding(code) || code === codes.eof) {
return nok;
}
effects.consume(code);
return content;
};
const contentAfter = function (code) {
effects.exit(types.chunkText);
return effects.attempt(marker, after, nok);
};
const after = function (code) {
effects.exit("mark");
return ok;
};
return start;
},
};

return {
text: {
[codes.equalsTo]: mark,
},
};
}

function fromMarkdownExt() {
const enterMark = function (token) {
this.enter(
{
type: "mark",
children: [],
},
token
);
};
const exitMark = function (token) {
const node = this.exit(token);
node.data = {
...node.data,
hName: "mark",
hProperties: {
className: "m-mark",
},
};
};
return {
enter: {
mark: enterMark,
},
exit: {
mark: exitMark,
},
};
}

export default function remarkMark() {
const self = /** @type {Processor<Root>} */ (this);
const data = self.data();
function add(key, value) {
if (Array.isArray(data[key])) {
data[key].push(value);
} else {
data[key] = [value];
}
}

add("micromarkExtensions", micromarkExt());
add("fromMarkdownExtensions", fromMarkdownExt());
}
134 changes: 64 additions & 70 deletions plugins/gatsby-remark-custom/remarkSpoiler.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -6,84 +6,78 @@ import { markdownLineEnding } from "micromark-util-character";
import { factorySpace } from "micromark-factory-space";
import { codes, types, constants } from "micromark-util-symbol";

function tokenizeSpoiler(effects, ok, nok) {
const self = this;
const start = function (code) {
effects.enter("spoiler");
return effects.attempt(marker, factorySpace(effects, contentStart, types.whitespace), nok);
};
const contentStart = function (code) {
effects.enter(types.chunkText, {
contentType: constants.contentTypeText,
});
return content;
};
const content = function (code) {
return effects.check(marker, factorySpace(effects, contentAfter, types.whitespace), comsumeData);
};
const comsumeData = function (code) {
if (markdownLineEnding(code) || code === codes.eof) {
return nok;
}
effects.consume(code);
return content;
};
const contentAfter = function (code) {
effects.exit(types.chunkText);
return effects.attempt(marker, after, nok);
};
const after = function (code) {
effects.exit("spoiler");
return ok;
function micromarkExt() {
const marker = {
partial: true,
tokenize: function (effects, ok, nok) {
let markerSize = 0;
if (this.previous === codes.exclamationMark) {
return nok;
}
const start = function (code) {
effects.enter("spoilerMarker");
return marker;
};
const marker = function (code) {
if (code === codes.exclamationMark) {
effects.consume(code);
markerSize++;
return marker;
}
if (markerSize == 2) {
effects.exit("spoilerMarker");
markerSize = 0;
return ok;
}
return nok;
};
return factorySpace(effects, start, types.whitespace);
},
};
return start;
}

// 定义分界符 (!!) 的 Tokenizer
const tokenizeMarker = function (effects, ok, nok) {
let markerSize = 0;
if (this.previous === codes.exclamationMark) {
return nok;
}
const start = function (code) {
effects.enter("spoilerMarker");
return marker;
};
const marker = function (code) {
if (code === codes.exclamationMark) {
effects.consume(code);
markerSize++;
return marker;
}
if (markerSize == 2) {
effects.exit("spoilerMarker");
markerSize = 0;
return ok;
}
return nok;
const spoiler = {
name: "spoiler",
tokenize: function (effects, ok, nok) {
const start = function (code) {
effects.enter("spoiler");
return effects.attempt(marker, factorySpace(effects, contentStart, types.whitespace), nok);
};
const contentStart = function (code) {
effects.enter(types.chunkText, {
contentType: constants.contentTypeText,
});
return content;
};
const content = function (code) {
return effects.check(marker, factorySpace(effects, contentAfter, types.whitespace), comsumeData);
};
const comsumeData = function (code) {
if (markdownLineEnding(code) || code === codes.eof) {
return nok;
}
effects.consume(code);
return content;
};
const contentAfter = function (code) {
effects.exit(types.chunkText);
return effects.attempt(marker, after, nok);
};
const after = function (code) {
effects.exit("spoiler");
return ok;
};
return start;
},
};
return factorySpace(effects, start, types.whitespace);
};

const marker = {
tokenize: tokenizeMarker,
partial: true,
};

const spoiler = {
name: "spoiler",
tokenize: tokenizeSpoiler,
};

function syntax() {
return {
text: {
[codes.exclamationMark]: spoiler,
},
};
}

function fromMarkdown() {
function fromMarkdownExt() {
const enterSpoiler = function (token) {
this.enter(
{
Expand All @@ -97,7 +91,7 @@ function fromMarkdown() {
const node = this.exit(token);
node.data = {
...node.data,
hName: "span",
hName: "del",
hProperties: {
className: "m-spoiler",
},
Expand All @@ -124,6 +118,6 @@ export default function remarkSpoiler() {
}
}

add("micromarkExtensions", syntax());
add("fromMarkdownExtensions", fromMarkdown());
add("micromarkExtensions", micromarkExt());
add("fromMarkdownExtensions", fromMarkdownExt());
}
8 changes: 8 additions & 0 deletions src/style/typography-extend.less
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,20 @@
cursor: not-allowed;
}

// 标记
&mark {
background-color: #fff8c5;
padding: 2px 4px;
border-radius: 4px;
}

// Spoiler
&spoiler {
color: transparent;
background-color: black;
cursor: pointer;
border-radius: 4px;
text-decoration: none;
transition: color 250ms cubic-bezier(0.4, 0, 0.2, 1), background-color 250ms cubic-bezier(0.4, 0, 0.2, 1);
&:hover {
color: inherit;
Expand Down

0 comments on commit b32b5e4

Please sign in to comment.