UNPKG

docsify-puml

Version:

Docsify plugin to parse PlantUML content

113 lines (90 loc) 2.79 kB
import { encode } from "plantuml-encoder"; import getSkin from "./skin"; const { dom } = window.Docsify; const LANG = "plantuml"; const SELECTOR = `pre[data-lang='${LANG}'`; const getElements = $ => { return dom.findAll($, SELECTOR); }; const getCurrentUrl = () => { const location = window.location.toString(); return location.substring(0, location.lastIndexOf("/") + 1); }; const createPlant = (element, skin, { renderAsObject, serverPath, asLink }) => { const PUMLserver = serverPath || "//www.plantuml.com/plantuml/svg/"; const svgElement = PUMLserver + encode(skin + element); let planted = ""; if (renderAsObject) { planted = `<object type="image/svg+xml" data="${svgElement}" />`; } else { planted = `<img src="${svgElement}" />`; } if (asLink) { planted = `<a href="${svgElement}" target="_blank">${planted}</a>`; } return planted; }; const createURLs = element => { return element.replace(/\[\[\$((?:\.?\.\/)*)/g, (_, path) => { const segments = (getCurrentUrl() + path).split("/"); const resolved = []; for (const seg of segments) { if (seg === "..") { resolved.pop(); } else if (seg !== ".") { resolved.push(seg); } } return `[[${resolved.join("/")}`; }); }; const resolveIncludes = async element => { const regex = /\[\[!include (.+)\]\]/g; const matches = element.match(regex); let resolved = element; if (matches) { for (const include of matches) { const url = include.split("[[!include").pop().split("]]")[0]; const resp = await fetch(url); const puml = await resp.text(); resolved = resolved.replace(include, puml); } } return resolved; }; const replace = (element, planted) => { const parent = element.parentNode; const newContent = dom.create("p", planted); newContent.dataset.lang = LANG; parent.replaceChild(newContent, element); return parent.innerHTML; }; const main = async (html, config) => { const $ = dom.create("span", html); if (!$.querySelectorAll) { return html; } const pumlElements = getElements($); if (pumlElements) { for (const el of pumlElements) { let puml = el.innerText; const skin = await getSkin(config.skin); puml = await resolveIncludes(puml); puml = createURLs(puml); const planted = createPlant(puml, skin, config); replace(el, planted); } } return $.innerHTML; }; export default (hook, vm) => { const config = { skin: "default", renderAsObject: false, asLink: false, ...vm.config.plantuml, }; hook.afterEach(async (html, next) => { next(await main(html, config)); }); };