init
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
{
|
||||
"name": "@ohmycv/markdown-it-latex-cmds",
|
||||
"version": "0.1.1",
|
||||
"description": "Enable using LaTeX like commands in markdown-it",
|
||||
"keywords": [
|
||||
"markdown",
|
||||
"markdown-it-plugin",
|
||||
"markdown-it"
|
||||
],
|
||||
"homepage": "https://github.com/Renovamen/oh-my-cv/tree/main/packages/markdown-it-latex-cmds",
|
||||
"bugs": {
|
||||
"url": "https://github.com/Renovamen/oh-my-cv"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/Renovamen/oh-my-cv.git",
|
||||
"directory": "packages/markdown-it-latex-cmds"
|
||||
},
|
||||
"license": "MIT",
|
||||
"author": "Renovamen <renovamenzxh@gmail.com>",
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"exports": {
|
||||
"types": "./dist/index.d.ts",
|
||||
"require": "./dist/index.js",
|
||||
"import": "./dist/index.mjs"
|
||||
},
|
||||
"main": "./dist/index.js",
|
||||
"module": "./dist/index.mjs",
|
||||
"types": "./dist/index.d.ts",
|
||||
"scripts": {
|
||||
"build-fast:pkg": "tsup src/index.ts --format cjs,esm",
|
||||
"build:pkg": "pnpm run build-fast:pkg --dts"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/markdown-it": "^14.1.1",
|
||||
"markdown-it": "^14.1.0"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
import type { PluginSimple, Renderer, ParserBlock, StateBlock } from "markdown-it";
|
||||
|
||||
// same as UNESCAPE_MD_RE plus a space
|
||||
const UNESCAPE_RE = /\\([ \\!"#$%&'()*+,.\/:;<=>?@[\]^_`{|}~-])/g;
|
||||
|
||||
const renderNewPage: Renderer.RenderRule = () => `<div class="md-it-newpage"></div>`;
|
||||
|
||||
const renderLineBreak: Renderer.RenderRule = (tokens, idx) =>
|
||||
`<div class="md-it-line-break" style="margin-top:${tokens[idx].meta.h};"></div>`;
|
||||
|
||||
const checkPattern = (
|
||||
state: StateBlock,
|
||||
start: number,
|
||||
pattern: string,
|
||||
options: {
|
||||
minLength?: number;
|
||||
silent?: boolean;
|
||||
} = {}
|
||||
) => {
|
||||
const { minLength = pattern.length, silent = false } = options;
|
||||
|
||||
const pos = state.bMarks[start] + state.tShift[start];
|
||||
const max = state.eMarks[start];
|
||||
|
||||
// Don't run any pairs in validation mode
|
||||
if (silent) return false;
|
||||
|
||||
// Should contain at least minLength characters
|
||||
if (pos + minLength > max) return false;
|
||||
// Should be the same as pattern
|
||||
if (state.src.slice(pos, pos + pattern.length) !== pattern) return false;
|
||||
|
||||
return {
|
||||
pos,
|
||||
max
|
||||
};
|
||||
};
|
||||
|
||||
const newPage: ParserBlock.RuleBlock = (state, start, end, silent) => {
|
||||
if (!checkPattern(state, start, "\\newpage", { silent })) return false;
|
||||
|
||||
// Skip "\newpage"
|
||||
state.line = start + 1;
|
||||
|
||||
// Add newpage div token
|
||||
const token = state.push("renderNewPage", "", 0);
|
||||
token.block = true;
|
||||
token.map = [start, state.line];
|
||||
token.markup = "\\newpage";
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
const lineBreak: ParserBlock.RuleBlock = (state, start, end, silent) => {
|
||||
// Try to find "\\["
|
||||
const res = checkPattern(state, start, "\\\\[", {
|
||||
minLength: 5, // Should be at least "\\[x]"
|
||||
silent
|
||||
});
|
||||
if (!res) return false;
|
||||
|
||||
const { pos, max } = res;
|
||||
|
||||
// Try to find "]"
|
||||
let lastPos = pos + 4;
|
||||
while (lastPos < max && state.src[lastPos] !== "]") lastPos++;
|
||||
|
||||
// Did't find "]"
|
||||
if (lastPos >= max) return false;
|
||||
|
||||
// Parse line break height, e.g. "\\[10px]"
|
||||
const height = state.src.slice(pos + 3, lastPos);
|
||||
// Don't allow unescaped spaces/newlines inside
|
||||
if (height.match(/(^|[^\\])(\\\\)*\s/)) return false;
|
||||
|
||||
// Skip "\\[x]"
|
||||
state.line = start + 1;
|
||||
|
||||
// Add line break div token
|
||||
const token = state.push("renderLineBreak", "", 0);
|
||||
token.meta = { h: height.replace(UNESCAPE_RE, "$1") };
|
||||
token.block = true;
|
||||
token.map = [start, state.line];
|
||||
token.markup = "\\[]";
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* A plugin for markdown-it that adds LaTeX commands. This plugin adds the following commands:
|
||||
* - `\newpage`: Adds a new page.
|
||||
* - `\\[10px]`: Adds a line break with a height of 10px.
|
||||
*/
|
||||
export const MarkdownItLatexCmds: PluginSimple = (md) => {
|
||||
md.renderer.rules.renderNewPage = renderNewPage;
|
||||
md.renderer.rules.renderLineBreak = renderLineBreak;
|
||||
|
||||
md.block.ruler.after("blockquote", "newPage", newPage);
|
||||
md.block.ruler.after("newPage", "lineBreak", lineBreak);
|
||||
};
|
||||
|
||||
export default MarkdownItLatexCmds;
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"include": ["./src"]
|
||||
}
|
||||
Reference in New Issue
Block a user