hackmd-to-html-cli
Version:
A node.js CLI tool for converting HackMD markdown to HTML.
199 lines • 10.4 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.BlockquoteToken = exports.BlockquoteTokenProperty = void 0;
exports.parseBlockquoteParams = parseBlockquoteParams;
exports.MarkdownItBlockquoteX = MarkdownItBlockquoteX;
const token_1 = require("./token");
var BlockquoteTokenProperty;
(function (BlockquoteTokenProperty) {
BlockquoteTokenProperty[BlockquoteTokenProperty["name"] = 0] = "name";
BlockquoteTokenProperty[BlockquoteTokenProperty["time"] = 1] = "time";
BlockquoteTokenProperty[BlockquoteTokenProperty["color"] = 2] = "color";
BlockquoteTokenProperty[BlockquoteTokenProperty["text"] = 3] = "text";
BlockquoteTokenProperty[BlockquoteTokenProperty["blockquoteXStart"] = 4] = "blockquoteXStart";
BlockquoteTokenProperty[BlockquoteTokenProperty["blockquoteXEnd"] = 5] = "blockquoteXEnd";
})(BlockquoteTokenProperty || (exports.BlockquoteTokenProperty = BlockquoteTokenProperty = {}));
class BlockquoteToken {
constructor(property, value) {
this.property = property;
this.value = value;
}
}
exports.BlockquoteToken = BlockquoteToken;
function parseBlockquoteParams(src) {
var _a, _b, _c, _d, _e, _f, _g, _h;
// [name=ChengHan Wu] [time=Sun, Jun 28, 2015 10:00 PM] [color=red]
const pattern = /\[(.*?)=(.*?)\]/g;
const matching = [...src.matchAll(pattern)];
if (matching.length === 0)
return [];
const tokens = [];
let j = 0;
let blockquoteStart = false; // decide whether close
for (let i = 0; i < matching.length; i++) {
const property = (_b = (_a = matching[i][1]) === null || _a === void 0 ? void 0 : _a.trim()) !== null && _b !== void 0 ? _b : '';
const value = (_c = matching[i][2]) !== null && _c !== void 0 ? _c : '';
const textLen = (_d = matching[i][0].length) !== null && _d !== void 0 ? _d : 0;
const pos = (_f = (_e = matching[i]) === null || _e === void 0 ? void 0 : _e.index) !== null && _f !== void 0 ? _f : 0;
if (pos > j) {
if (blockquoteStart) {
tokens.push(new BlockquoteToken(BlockquoteTokenProperty.blockquoteXEnd, ''));
blockquoteStart = false;
}
// normal text
tokens.push(new BlockquoteToken(BlockquoteTokenProperty.text, src.substring(j, pos)));
}
switch (property) {
case 'name':
if (tokens.length == 0 || ((_g = tokens[tokens.length - 1]) === null || _g === void 0 ? void 0 : _g.property) === BlockquoteTokenProperty.text) {
if (blockquoteStart) {
tokens.push(new BlockquoteToken(BlockquoteTokenProperty.blockquoteXEnd, ''));
}
tokens.push(new BlockquoteToken(BlockquoteTokenProperty.blockquoteXStart, ''));
blockquoteStart = true;
}
tokens.push(new BlockquoteToken(BlockquoteTokenProperty.name, value.trimStart()));
break;
case 'time':
if (tokens.length == 0 || ((_h = tokens[tokens.length - 1]) === null || _h === void 0 ? void 0 : _h.property) === BlockquoteTokenProperty.text) {
if (blockquoteStart) {
tokens.push(new BlockquoteToken(BlockquoteTokenProperty.blockquoteXEnd, ''));
}
tokens.push(new BlockquoteToken(BlockquoteTokenProperty.blockquoteXStart, ''));
blockquoteStart = true;
}
tokens.push(new BlockquoteToken(BlockquoteTokenProperty.time, value.trimStart()));
break;
case 'color':
tokens.push(new BlockquoteToken(BlockquoteTokenProperty.color, value.trimStart()));
break;
default:
tokens.push(new BlockquoteToken(BlockquoteTokenProperty.text, value));
break;
}
j = pos + textLen + 1;
}
if (blockquoteStart) {
tokens.push(new BlockquoteToken(BlockquoteTokenProperty.blockquoteXEnd, ''));
blockquoteStart = false;
}
if (src.length != j) {
tokens.push(new BlockquoteToken(BlockquoteTokenProperty.text, src.substring(j, src.length)));
}
return tokens;
}
function MarkdownItBlockquoteX(md) {
function blockquoteX(state) {
var _a, _b, _c;
const blockTokens = state.tokens;
let detect = false;
let blockquoteOpenAt = 0;
for (let j = 0; j < blockTokens.length; j++) {
if (blockTokens[j].type === 'blockquote_open') {
blockquoteOpenAt = j;
detect = true;
}
if (blockTokens[j].type === 'blockquote_close') {
detect = false;
}
if (!detect) {
continue;
}
if (blockTokens[j].type === 'inline') {
for (let n = 0; n < blockTokens[j].children.length; n++) {
// find text token
if (blockTokens[j].children[n].type !== "text")
continue;
// avoid matching same children[n]
let nextN = n;
// try to parse
const m = parseBlockquoteParams(blockTokens[j].children[n].content);
if (m.length === 0)
continue;
// render
const newTokens = [];
// when the content is
// [invalid] [name] [time]
// we want to render
//
// <span>[invalid]<span>
// <span class="blockquoteX">
// <span class="material-symbols-outlined material-symbols-outlined-fill">
// name
// </span>
// <span class="material-symbols-outlined">
// time
// </span>
// </span>
// we only add the class `blockquoteX` before the `name` or `time`
// In hackMD, it only supports the format [name=blablabla] or [name= blablabla].
// However, in hmd2html, we use looser constraints, meaning it supports spaces between words.
// e.g. [ name = blablabla ]
let token;
// parse name, time, color
let color = '';
for (let s = 0; s < m.length; s++) {
const property = (_a = m[s]) === null || _a === void 0 ? void 0 : _a.property;
const value = (_c = (_b = m[s]) === null || _b === void 0 ? void 0 : _b.value) !== null && _c !== void 0 ? _c : '';
switch (property) {
case BlockquoteTokenProperty.blockquoteXStart:
token = new token_1.MyToken('blockquoteX_open', 'span', 1);
token.attrs = [['class', 'blockquoteX']];
newTokens.push(token);
break;
case BlockquoteTokenProperty.blockquoteXEnd:
token = new token_1.MyToken('blockquoteX_close', 'span', -1);
newTokens.push(token);
break;
case BlockquoteTokenProperty.name:
token = new token_1.MyToken('blockquoteX_name_open', 'span', 1);
token.attrs = [['class', 'material-symbols-outlined material-symbols-outlined-fill']];
newTokens.push(token);
token = new token_1.MyToken('text', '', 0);
nextN++;
token.content = 'person';
newTokens.push(token);
token = new token_1.MyToken('blockquoteX_name_close', 'span', -1);
newTokens.push(token);
token = new token_1.MyToken('text', '', 0);
nextN++;
token.content = value.trim();
newTokens.push(token);
break;
case BlockquoteTokenProperty.time:
token = new token_1.MyToken('blockquoteX_date_open', 'span', 1);
token.attrs = [['class', 'material-symbols-outlined']];
newTokens.push(token);
token = new token_1.MyToken('text', '', 0);
nextN++;
token.content = 'schedule';
newTokens.push(token);
token = new token_1.MyToken('blockquoteX_date_close', 'span', -1);
newTokens.push(token);
token = new token_1.MyToken('text', '', 0);
nextN++;
token.content = value.trim();
newTokens.push(token);
break;
case BlockquoteTokenProperty.text:
token = new token_1.MyToken('text', '', 0);
nextN++;
token.content = value;
newTokens.push(token);
break;
case BlockquoteTokenProperty.color:
color = value !== null && value !== void 0 ? value : '';
}
}
blockTokens[j].children = md.utils.arrayReplaceAt(blockTokens[j].children, n, newTokens);
if (color != '') {
blockTokens[blockquoteOpenAt].attrs = [['style', 'border-color:' + color + ';']];
}
n = nextN;
}
}
}
}
md.core.ruler.push('blockquoteX', blockquoteX);
}
//# sourceMappingURL=blockquotex.js.map