import { parseBBCodeTag } from "pretty-text/engines/discourse-markdown/bbcode-block"; const WRAP_CLASS = "d-wrap"; function parseAttributes(tagInfo) { const attributes = tagInfo.attrs._default || ""; return ( parseBBCodeTag(`[wrap wrap=${attributes}]`, 0, attributes.length + 12) .attrs || {} ); } function camelCaseToDash(str) { return str.replace(/([a-zA-Z])(?=[A-Z])/g, "$1-").toLowerCase(); } function applyDataAttributes(token, state, attributes) { Object.keys(attributes).forEach((tag) => { const value = state.md.utils.escapeHtml(attributes[tag]); tag = camelCaseToDash( state.md.utils.escapeHtml(tag.replace(/[^A-Za-z\-0-9]/g, "")) ); if (value && tag && tag.length > 1) { token.attrs.push([`data-${tag}`, value]); } }); } const blockRule = { tag: "wrap", before(state, tagInfo) { let token = state.push("wrap_open", "div", 1); token.attrs = [["class", WRAP_CLASS]]; applyDataAttributes(token, state, parseAttributes(tagInfo)); }, after(state) { state.push("wrap_close", "div", -1); }, }; const inlineRule = { tag: "wrap", replace(state, tagInfo, content) { let token = state.push("wrap_open", "span", 1); token.attrs = [["class", WRAP_CLASS]]; applyDataAttributes(token, state, parseAttributes(tagInfo)); if (content) { token = state.push("text", "", 0); token.content = content; } state.push("wrap_close", "span", -1); return true; }, }; export function setup(helper) { helper.registerPlugin((md) => { md.inline.bbcode.ruler.push("inline-wrap", inlineRule); md.block.bbcode.ruler.push("block-wrap", blockRule); }); helper.allowList([`div.${WRAP_CLASS}`, `span.${WRAP_CLASS}`, "span[data-*]"]); }