import juice from 'juice' import prettier from 'prettier/standalone' import prettierCss from 'prettier/parser-postcss' import prettierMarkdown from 'prettier/parser-markdown' import { prefix } from '@/config' export function addPrefix(str) { return `${prefix}__${str}` } export function customizeTheme(theme, options) { const newTheme = JSON.parse(JSON.stringify(theme)) const { fontSize, color } = options if (fontSize) { for (let i = 1; i <= 4; i++) { const v = newTheme.block[`h${i}`][`font-size`] newTheme.block[`h${i}`][`font-size`] = `${fontSize * Number.parseFloat(v)}px` } } if (color) { newTheme.base[`--md-primary-color`] = color } return newTheme } export function customCssWithTemplate(jsonString, color, theme) { const newTheme = customizeTheme(theme, { color }); const mergeProperties = (target, source, keys) => { keys.forEach(key => { if (source[key]) { target[key] = Object.assign(target[key] || {}, source[key]); } }); }; const blockKeys = [ 'h1', 'h2', 'h3', 'h4', 'code', 'p', 'hr', 'blockquote', 'blockquote_p', 'image', 'ul', 'ol' ]; const inlineKeys = ['strong', 'codespan', 'link', 'wx_link', 'listitem']; mergeProperties(newTheme.block, jsonString, blockKeys); mergeProperties(newTheme.inline, jsonString, inlineKeys); return newTheme; } /** * 将 CSS 字符串转换为 JSON 对象 * * @param {string} css - CSS 字符串 * @returns {object} - JSON 格式的 CSS */ export function css2json(css) { // 去除所有 CSS 注释 css = css.replace(/\/\*[\s\S]*?\*\//g, ``) const json = {} // 辅助函数:将声明数组转换为对象 const toObject = array => array.reduce((obj, item) => { const [property, value] = item.split(`:`).map(part => part.trim()) if (property) obj[property] = value return obj }, {}) while (css.includes(`{`) && css.includes(`}`)) { const lbracket = css.indexOf(`{`) const rbracket = css.indexOf(`}`) // 获取声明块并转换为对象 const declarations = css.substring(lbracket + 1, rbracket) .split(`;`) .map(e => e.trim()) .filter(Boolean) // 获取选择器并去除空格 const selectors = css.substring(0, lbracket) .split(`,`) .map(selector => selector.trim()) const declarationObj = toObject(declarations) // 将声明对象关联到相应的选择器 selectors.forEach((selector) => { json[selector] = { ...(json[selector] || {}), ...declarationObj } }) // 处理下一个声明块 css = css.slice(rbracket + 1).trim() } return json } /** * 将编辑器内容保存到 LocalStorage * @param {*} editor * @param {*} name */ export function saveEditorContent(editor, name) { const content = editor.getValue(0) if (content) { localStorage.setItem(name, content) } else { localStorage.removeItem(name) } } /** * 格式化文档 * @param {string} content - 文档内容 */ export function formatDoc(content) { return prettier.format(content, { parser: `markdown`, plugins: [prettierMarkdown], }) } /** * 格式化css * @param {string} content - css内容 */ export function formatCss(content) { return prettier.format(content, { parser: `css`, plugins: [prettierCss], }) } /** * 导出原始 Markdown 文档 * @param {string} doc - 文档内容 */ export function downloadMD(doc) { const downLink = document.createElement(`a`) downLink.download = `content.md` downLink.style.display = `none` const blob = new Blob([doc]) downLink.href = URL.createObjectURL(blob) document.body.appendChild(downLink) downLink.click() document.body.removeChild(downLink) } /** * 导出 HTML 生成内容 */ export function exportHTML() { const element = document.querySelector(`#output`) setStyles(element) const htmlStr = element.innerHTML const downLink = document.createElement(`a`) downLink.download = `content.html` downLink.style.display = `none` const blob = new Blob([ `