TeXmath support for cc98 markdown posts
Script này sẽ không được không được cài đặt trực tiếp. Nó là một thư viện cho các script khác để bao gồm các chỉ thị meta
// @require https://update.greasyfork.org/scripts/425661/926061/texmath.js
// ==UserScript==
// @name texmath
// @namespace https://www.cc98.org/
// @version 0.1
// @description TeXmath support for cc98 markdown posts
// @author Secant
// @match https://www.cc98.org/topic/*
// @grant none
// jshint esversion: 6
(function () {
"use strict";
function texmath(md, options) {
const delimiters = "dollars";
const imgtexOptions = (options && options.imgtexOptions) || {
apiBase: "https://math.now.sh",
color: "black",
};
if (!texmath.imgtex) {
// else ... depricated `use` method was used ...
if (options && typeof options.engine === "object") {
texmath.imgtex = options.engine;
}
// artifical error object.
else
texmath.imgtex = {
renderToString() {
return "No math renderer found.";
},
};
}
if (delimiters in texmath.rules) {
for (const rule of texmath.rules[delimiters].inline) {
md.inline.ruler.before("escape", rule.name, texmath.inline(rule)); // ! important
md.renderer.rules[rule.name] = (tokens, idx) =>
rule.tmpl.replace(
/\$1/,
texmath.render(
tokens[idx].content,
!!rule.displayMode,
imgtexOptions
)
);
}
for (const rule of texmath.rules[delimiters].block) {
md.block.ruler.before("fence", rule.name, texmath.block(rule)); // ! important for ```math delimiters
md.renderer.rules[rule.name] = (tokens, idx) =>
rule.tmpl.replace(
/\$1/,
texmath.render(tokens[idx].content, true, imgtexOptions)
);
}
}
}
texmath.inline = (rule) =>
function (state, silent) {
const pos = state.pos;
const str = state.src;
const pre =
str.startsWith(rule.tag, (rule.rex.lastIndex = pos)) &&
(!rule.pre || rule.pre(str, pos)); // valid pre-condition ...
const match = pre && rule.rex.exec(str);
const res =
!!match &&
pos < rule.rex.lastIndex &&
(!rule.post || rule.post(str, rule.rex.lastIndex - 1));
if (res) {
if (!silent) {
const token = state.push(rule.name, "math", 0);
token.content = match[1];
token.markup = rule.tag;
}
state.pos = rule.rex.lastIndex;
}
return res;
};
texmath.block = (rule) =>
function block(state, begLine, endLine, silent) {
const pos = state.bMarks[begLine] + state.tShift[begLine];
const str = state.src;
const pre =
str.startsWith(rule.tag, (rule.rex.lastIndex = pos)) &&
(!rule.pre || rule.pre(str, pos)); // valid pre-condition ....
const match = pre && rule.rex.exec(str);
const res =
!!match &&
pos < rule.rex.lastIndex &&
(!rule.post || rule.post(str, rule.rex.lastIndex - 1));
if (res && !silent) {
// match and valid post-condition ...
const endpos = rule.rex.lastIndex - 1;
let curline;
for (curline = begLine; curline < endLine; curline++)
if (
endpos >= state.bMarks[curline] + state.tShift[curline] &&
endpos <= state.eMarks[curline]
)
// line for end of block math found ...
break;
// "this will prevent lazy continuations from ever going past our end marker"
// s. https://github.com/markdown-it/markdown-it-container/blob/master/index.js
const lineMax = state.lineMax;
state.lineMax = curline;
// begin token
let token = state.push(rule.name, "math", 1); // 'math_block'
token.block = true;
token.markup = rule.tag;
token.content = match[1];
token.map = [begLine, curline];
// end token
token = state.push(rule.name + "_end", "math", -1);
token.block = true;
token.markup = rule.tag;
state.lineMax = lineMax;
state.line = curline + 1;
}
return res;
};
texmath.render = function (tex, displayMode, options) {
options.displayMode = displayMode;
let res;
try {
res = texmath.imgtex.renderToString(tex, options);
} catch (err) {
res = tex + ": " + err.message;
}
return res;
};
// used for enable/disable math rendering by `markdown-it`
texmath.inlineRuleNames = ["math_inline"];
texmath.blockRuleNames = ["math_block"];
texmath.$_pre = (str, beg) => {
const prv = beg > 0 ? str[beg - 1].charCodeAt(0) : false;
return (
!prv ||
(prv !== 0x5c && // no backslash,
(prv < 0x30 || prv > 0x39))
); // no decimal digit .. before opening '$'
};
texmath.$_post = (str, end) => {
const nxt = str[end + 1] && str[end + 1].charCodeAt(0);
return !nxt || nxt < 0x30 || nxt > 0x39; // no decimal digit .. after closing '$'
};
texmath.rules = {
dollars: {
inline: [
{
name: "math_inline",
rex: /\$((?:\S)|(?:\S.*?\S))\$/gy,
tmpl: "$1",
tag: "$",
pre: texmath.$_pre,
post: texmath.$_post,
},
],
block: [
{
name: "math_block",
rex: /\${2}([^$]+?)\${2}/gmy,
tmpl: "<center>$1</center>",
tag: "$$",
},
],
},
};
window.texmath = texmath;
})();