markdown-it-graph
Version:
A markdown-it plugin that parses custom graph syntax like ```graph bar and outputs structured graph data
67 lines (66 loc) • 3.02 kB
JavaScript
/*! markdown-it-graph 0.1.1 https://github.com/[object Object] @license MIT */
(function(global, factory) {
typeof exports === "object" && typeof module !== "undefined" ? module.exports = factory() : typeof define === "function" && define.amd ? define(factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self,
global.markdownitGraph = factory());
})(this, (function() {
"use strict";
/** @typedef {import('./index')} */ function graph_plugin(md) {
const defaultType = "bar";
// Add renderer override for "graph" fences
const originalFence = md.renderer.rules.fence || function(tokens, idx, options, env, self) {
return self.renderToken(tokens, idx, options);
};
md.renderer.rules.fence = function(tokens, idx, options, env, self) {
const token = tokens[idx];
const info = token.info.trim();
const [typeKeyword, graphType = defaultType] = info.split(/\s+/);
if (typeKeyword !== "graph") {
return originalFence(tokens, idx, options, env, self);
}
const lines = token.content.trim().split("\n");
const data = lines.map((line => {
const [labelPart, valuePart] = line.split("|").map((s => s.trim()));
if (!labelPart || !valuePart) return null;
const match = valuePart.match(/^([\u2588\u2589\u258a\u258b\u258c\u258d\u258e\u258f ]*)([-+]?[\d.]+.*)$/);
let valueRaw = valuePart;
if (match && match.length >= 3) {
valueRaw = match[2] ? match[2].trim() : valuePart;
}
const value = parseFloat(valueRaw.replace(/[^0-9.-]/g, ""));
return {
label: labelPart,
value: value
};
})).filter(Boolean);
const payload = {
type: graphType,
data: data
};
return `<graph-block type="${graphType}" data-graph='${JSON.stringify(payload)}'></graph-block>`;
};
// Add custom block rule to detect ```graph blocks
md.block.ruler.before("fence", "graph_block", (function(state, startLine, endLine, silent) {
const startPos = state.bMarks[startLine] + state.tShift[startLine];
const maxPos = state.eMarks[startLine];
const marker = state.src.slice(startPos, maxPos).trim();
if (!marker.startsWith("```graph")) return false;
if (silent) return true;
let nextLine = startLine;
while (++nextLine < endLine) {
const lineStart = state.bMarks[nextLine] + state.tShift[nextLine];
const lineEnd = state.eMarks[nextLine];
const lineText = state.src.slice(lineStart, lineEnd).trim();
if (lineText.startsWith("```")) break;
}
const token = state.push("fence", "code", 0);
token.info = marker.slice(3).trim();
// e.g., "graph bar"
token.content = state.getLines(startLine + 1, nextLine, state.tShift[startLine], true);
token.map = [ startLine, nextLine + 1 ];
token.markup = "```";
state.line = nextLine + 1;
return true;
}));
}
return graph_plugin;
}));