mirror of
https://github.com/BoostIo/Boostnote
synced 2025-12-11 00:36:26 +00:00
797 lines
18 KiB
JavaScript
797 lines
18 KiB
JavaScript
import path from 'path'
|
|
import fileUrl from 'file-url'
|
|
import fs from 'fs'
|
|
import { remote } from 'electron'
|
|
import consts from 'browser/lib/consts'
|
|
import Markdown from 'browser/lib/markdown'
|
|
import attachmentManagement from './attachmentManagement'
|
|
import { version as codemirrorVersion } from 'codemirror/package.json'
|
|
import { escapeHtmlCharacters } from 'browser/lib/utils'
|
|
|
|
const { app } = remote
|
|
const appPath = fileUrl(
|
|
process.env.NODE_ENV === 'production' ? app.getAppPath() : path.resolve()
|
|
)
|
|
|
|
let markdownStyle = ''
|
|
try {
|
|
markdownStyle = require('!!css!stylus?sourceMap!../../../components/markdown.styl')[0][1]
|
|
} catch (e) {}
|
|
|
|
export const CSS_FILES = [
|
|
`${appPath}/node_modules/katex/dist/katex.min.css`,
|
|
`${appPath}/node_modules/codemirror/lib/codemirror.css`,
|
|
`${appPath}/node_modules/react-image-carousel/lib/css/main.min.css`
|
|
]
|
|
|
|
const macos = global.process.platform === 'darwin'
|
|
|
|
const defaultFontFamily = ['helvetica', 'arial', 'sans-serif']
|
|
if (!macos) {
|
|
defaultFontFamily.unshift('Microsoft YaHei')
|
|
defaultFontFamily.unshift('meiryo')
|
|
}
|
|
|
|
const defaultCodeBlockFontFamily = [
|
|
'Monaco',
|
|
'Menlo',
|
|
'Ubuntu Mono',
|
|
'Consolas',
|
|
'source-code-pro',
|
|
'monospace'
|
|
]
|
|
|
|
function unprefix(file) {
|
|
if (global.process.platform === 'win32') {
|
|
return file.replace('file:///', '')
|
|
} else {
|
|
return file.replace('file://', '')
|
|
}
|
|
}
|
|
|
|
/**
|
|
* ```
|
|
* {
|
|
* fontFamily,
|
|
* fontSize,
|
|
* lineNumber,
|
|
* codeBlockFontFamily,
|
|
* codeBlockTheme,
|
|
* scrollPastEnd,
|
|
* theme,
|
|
* allowCustomCSS,
|
|
* customCSS
|
|
* smartQuotes,
|
|
* sanitize,
|
|
* breaks,
|
|
* storagePath,
|
|
* export,
|
|
* indentSize
|
|
* }
|
|
* ```
|
|
*/
|
|
export default function formatHTML(props) {
|
|
const {
|
|
fontFamily,
|
|
fontSize,
|
|
codeBlockFontFamily,
|
|
lineNumber,
|
|
codeBlockTheme,
|
|
scrollPastEnd,
|
|
theme,
|
|
allowCustomCSS,
|
|
customCSS
|
|
} = getStyleParams(props)
|
|
|
|
const inlineStyles = buildStyle(
|
|
fontFamily,
|
|
fontSize,
|
|
codeBlockFontFamily,
|
|
lineNumber,
|
|
scrollPastEnd,
|
|
theme,
|
|
allowCustomCSS,
|
|
customCSS
|
|
)
|
|
|
|
const { smartQuotes, sanitize, breaks } = props
|
|
|
|
let indentSize = parseInt(props.indentSize, 10)
|
|
if (!(indentSize > 0 && indentSize < 132)) {
|
|
indentSize = 4
|
|
}
|
|
|
|
const files = [getCodeThemeLink(codeBlockTheme), ...CSS_FILES]
|
|
|
|
return function(note, targetPath, exportTasks) {
|
|
const styles = files
|
|
.map(file => `<link rel="stylesheet" href="css/${path.basename(file)}">`)
|
|
.join('\n')
|
|
|
|
let inlineScripts = ''
|
|
let scripts = ''
|
|
|
|
let decodeEntities = false
|
|
function addDecodeEntities() {
|
|
if (decodeEntities) {
|
|
return
|
|
}
|
|
|
|
decodeEntities = true
|
|
|
|
inlineScripts += `
|
|
function decodeEntities (text) {
|
|
var entities = [
|
|
['apos', '\\''],
|
|
['amp', '&'],
|
|
['lt', '<'],
|
|
['gt', '>'],
|
|
['#63', '\\?'],
|
|
['#36', '\\$']
|
|
]
|
|
|
|
for (var i = 0, max = entities.length; i < max; ++i) {
|
|
text = text.replace(new RegExp(\`&\${entities[i][0]};\`, 'g'), entities[i][1])
|
|
}
|
|
|
|
return text
|
|
}`
|
|
}
|
|
|
|
let lodash = false
|
|
function addLodash() {
|
|
if (lodash) {
|
|
return
|
|
}
|
|
|
|
lodash = true
|
|
|
|
exportTasks.push({
|
|
src: unprefix(`${appPath}/node_modules/lodash/lodash.min.js`),
|
|
dst: 'js'
|
|
})
|
|
|
|
scripts += `<script src="js/lodash.min.js"></script>`
|
|
}
|
|
|
|
let raphael = false
|
|
function addRaphael() {
|
|
if (raphael) {
|
|
return
|
|
}
|
|
|
|
raphael = true
|
|
|
|
exportTasks.push({
|
|
src: unprefix(`${appPath}/node_modules/raphael/raphael.min.js`),
|
|
dst: 'js'
|
|
})
|
|
|
|
scripts += `<script src="js/raphael.min.js"></script>`
|
|
}
|
|
|
|
let yaml = false
|
|
function addYAML() {
|
|
if (yaml) {
|
|
return
|
|
}
|
|
|
|
yaml = true
|
|
|
|
exportTasks.push({
|
|
src: unprefix(`${appPath}/node_modules/js-yaml/dist/js-yaml.min.js`),
|
|
dst: 'js'
|
|
})
|
|
|
|
scripts += `<script src="js/js-yaml.min.js"></script>`
|
|
}
|
|
|
|
let chart = false
|
|
function addChart() {
|
|
if (chart) {
|
|
return
|
|
}
|
|
|
|
chart = true
|
|
|
|
addLodash()
|
|
|
|
exportTasks.push({
|
|
src: unprefix(`${appPath}/node_modules/chart.js/dist/Chart.min.js`),
|
|
dst: 'js'
|
|
})
|
|
|
|
scripts += `<script src="js/Chart.min.js"></script>`
|
|
|
|
inlineScripts += `
|
|
function displayCharts() {
|
|
_.forEach(
|
|
document.querySelectorAll('.chart'),
|
|
el => {
|
|
try {
|
|
const format = el.attributes.getNamedItem('data-format').value
|
|
const chartConfig = format === 'yaml' ? jsyaml.load(el.innerHTML) : JSON.parse(el.innerHTML)
|
|
el.innerHTML = ''
|
|
|
|
const canvas = document.createElement('canvas')
|
|
el.appendChild(canvas)
|
|
|
|
const height = el.attributes.getNamedItem('data-height')
|
|
if (height && height.value !== 'undefined') {
|
|
el.style.height = height.value + 'vh'
|
|
canvas.height = height.value + 'vh'
|
|
}
|
|
|
|
const chart = new Chart(canvas, chartConfig)
|
|
} catch (e) {
|
|
el.className = 'chart-error'
|
|
el.innerHTML = 'chartjs diagram parse error: ' + e.message
|
|
}
|
|
}
|
|
)
|
|
}
|
|
|
|
document.addEventListener('DOMContentLoaded', displayCharts);
|
|
`
|
|
}
|
|
|
|
let codemirror = false
|
|
function addCodeMirror() {
|
|
if (codemirror) {
|
|
return
|
|
}
|
|
|
|
codemirror = true
|
|
|
|
addDecodeEntities()
|
|
addLodash()
|
|
|
|
exportTasks.push(
|
|
{
|
|
src: unprefix(`${appPath}/node_modules/codemirror/lib/codemirror.js`),
|
|
dst: 'js/codemirror'
|
|
},
|
|
{
|
|
src: unprefix(`${appPath}/node_modules/codemirror/mode/meta.js`),
|
|
dst: 'js/codemirror/mode'
|
|
},
|
|
{
|
|
src: unprefix(
|
|
`${appPath}/node_modules/codemirror/addon/mode/loadmode.js`
|
|
),
|
|
dst: 'js/codemirror/addon/mode'
|
|
},
|
|
{
|
|
src: unprefix(
|
|
`${appPath}/node_modules/codemirror/addon/runmode/runmode.js`
|
|
),
|
|
dst: 'js/codemirror/addon/runmode'
|
|
}
|
|
)
|
|
|
|
scripts += `
|
|
<script src="js/codemirror/codemirror.js"></script>
|
|
<script src="js/codemirror/mode/meta.js"></script>
|
|
<script src="js/codemirror/addon/mode/loadmode.js"></script>
|
|
<script src="js/codemirror/addon/runmode/runmode.js"></script>
|
|
`
|
|
|
|
let className = `cm-s-${codeBlockTheme}`
|
|
if (codeBlockTheme.indexOf('solarized') === 0) {
|
|
const [refThema, color] = codeBlockTheme.split(' ')
|
|
className = `cm-s-${refThema} cm-s-${color}`
|
|
}
|
|
|
|
inlineScripts += `
|
|
CodeMirror.modeURL = 'https://cdn.jsdelivr.net/npm/codemirror@${codemirrorVersion}/mode/%N/%N.js';
|
|
|
|
function displayCodeBlocks() {
|
|
_.forEach(
|
|
document.querySelectorAll('.code code'),
|
|
el => {
|
|
el.parentNode.className += ' ${className}'
|
|
let syntax = CodeMirror.findModeByName(el.className)
|
|
if (syntax == null) syntax = CodeMirror.findModeByName('Plain Text')
|
|
CodeMirror.requireMode(syntax.mode, () => {
|
|
const content = decodeEntities(el.innerHTML)
|
|
el.innerHTML = ''
|
|
CodeMirror.runMode(content, syntax.mime, el, {
|
|
tabSize: ${indentSize}
|
|
})
|
|
})
|
|
}
|
|
)
|
|
}
|
|
|
|
document.addEventListener('DOMContentLoaded', displayCodeBlocks);
|
|
`
|
|
}
|
|
|
|
let flowchart = false
|
|
function addFlowchart() {
|
|
if (flowchart) {
|
|
return
|
|
}
|
|
|
|
flowchart = true
|
|
|
|
addDecodeEntities()
|
|
addLodash()
|
|
addRaphael()
|
|
|
|
exportTasks.push({
|
|
src: unprefix(
|
|
`${appPath}/node_modules/flowchart.js/release/flowchart.min.js`
|
|
),
|
|
dst: 'js'
|
|
})
|
|
|
|
scripts += `<script src="js/flowchart.min.js"></script>`
|
|
|
|
inlineScripts += `
|
|
function displayFlowcharts() {
|
|
_.forEach(
|
|
document.querySelectorAll('.flowchart'),
|
|
el => {
|
|
try {
|
|
const diagram = flowchart.parse(
|
|
decodeEntities(el.innerHTML)
|
|
)
|
|
el.innerHTML = ''
|
|
diagram.drawSVG(el)
|
|
} catch (e) {
|
|
el.className = 'flowchart-error'
|
|
el.innerHTML = 'Flowchart parse error: ' + e.message
|
|
}
|
|
}
|
|
)
|
|
}
|
|
|
|
document.addEventListener('DOMContentLoaded', displayFlowcharts);
|
|
`
|
|
}
|
|
|
|
let mermaid = false
|
|
function addMermaid() {
|
|
if (mermaid) {
|
|
return
|
|
}
|
|
|
|
mermaid = true
|
|
|
|
addLodash()
|
|
|
|
exportTasks.push({
|
|
src: unprefix(`${appPath}/node_modules/mermaid/dist/mermaid.min.js`),
|
|
dst: 'js'
|
|
})
|
|
|
|
scripts += `<script src="js/mermaid.min.js"></script>`
|
|
|
|
inlineScripts += `
|
|
function displayMermaids() {
|
|
_.forEach(
|
|
document.querySelectorAll('.mermaid'),
|
|
el => {
|
|
const height = el.attributes.getNamedItem('data-height')
|
|
if (height && height.value !== 'undefined') {
|
|
el.style.height = height.value + 'vh'
|
|
}
|
|
}
|
|
)
|
|
}
|
|
|
|
document.addEventListener('DOMContentLoaded', displayMermaids);
|
|
`
|
|
}
|
|
|
|
let sequence = false
|
|
function addSequence() {
|
|
if (sequence) {
|
|
return
|
|
}
|
|
|
|
sequence = true
|
|
|
|
addDecodeEntities()
|
|
addLodash()
|
|
addRaphael()
|
|
|
|
exportTasks.push({
|
|
src: unprefix(
|
|
`${appPath}/node_modules/@rokt33r/js-sequence-diagrams/dist/sequence-diagram-min.js`
|
|
),
|
|
dst: 'js'
|
|
})
|
|
|
|
scripts += `<script src="js/sequence-diagram-min.js"></script>`
|
|
|
|
inlineScripts += `
|
|
function displaySequences() {
|
|
_.forEach(
|
|
document.querySelectorAll('.sequence'),
|
|
el => {
|
|
try {
|
|
const diagram = Diagram.parse(
|
|
decodeEntities(el.innerHTML)
|
|
)
|
|
el.innerHTML = ''
|
|
diagram.drawSVG(el, { theme: 'simple' })
|
|
} catch (e) {
|
|
el.className = 'sequence-error'
|
|
el.innerHTML = 'Sequence diagram parse error: ' + e.message
|
|
}
|
|
}
|
|
)
|
|
}
|
|
|
|
document.addEventListener('DOMContentLoaded', displaySequences);
|
|
`
|
|
}
|
|
|
|
const modes = {}
|
|
const markdown = new Markdown({
|
|
typographer: smartQuotes,
|
|
sanitize,
|
|
breaks,
|
|
onFence(type, mode) {
|
|
if (type === 'chart') {
|
|
addChart()
|
|
|
|
if (mode === 'yaml') {
|
|
addYAML()
|
|
}
|
|
} else if (type === 'code') {
|
|
addCodeMirror()
|
|
|
|
if (mode && modes[mode] !== true) {
|
|
const file = unprefix(
|
|
`${appPath}/node_modules/codemirror/mode/${mode}/${mode}.js`
|
|
)
|
|
|
|
if (fs.existsSync(file)) {
|
|
exportTasks.push({
|
|
src: file,
|
|
dst: `js/codemirror/mode/${mode}`
|
|
})
|
|
|
|
modes[mode] = true
|
|
}
|
|
}
|
|
} else if (type === 'flowchart') {
|
|
addFlowchart()
|
|
} else if (type === 'mermaid') {
|
|
addMermaid()
|
|
} else if (type === 'sequence') {
|
|
addSequence()
|
|
}
|
|
}
|
|
})
|
|
|
|
let body = note.content
|
|
|
|
if (sanitize === 'NONE') {
|
|
body = escapeHtmlCharactersInCodeTag(body.split('```'))
|
|
}
|
|
|
|
body = markdown.render(note.content)
|
|
|
|
const attachmentsAbsolutePaths = attachmentManagement.getAbsolutePathsOfAttachmentsInContent(
|
|
note.content,
|
|
props.storagePath
|
|
)
|
|
|
|
files.forEach(file => {
|
|
exportTasks.push({
|
|
src: unprefix(file),
|
|
dst: 'css'
|
|
})
|
|
})
|
|
|
|
const destinationFolder = props.export.prefixAttachmentFolder
|
|
? `${path.parse(targetPath).name} - ${
|
|
attachmentManagement.DESTINATION_FOLDER
|
|
}`
|
|
: attachmentManagement.DESTINATION_FOLDER
|
|
|
|
attachmentsAbsolutePaths.forEach(attachment => {
|
|
exportTasks.push({
|
|
src: attachment,
|
|
dst: destinationFolder
|
|
})
|
|
})
|
|
|
|
body = attachmentManagement.replaceStorageReferences(
|
|
body,
|
|
note.key,
|
|
destinationFolder
|
|
)
|
|
|
|
return `
|
|
<html>
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name = "viewport" content = "width = device-width, initial-scale = 1, maximum-scale = 1">
|
|
<style id="style">${inlineStyles}</style>
|
|
${styles}
|
|
${scripts}
|
|
<script>${inlineScripts}</script>
|
|
</head>
|
|
<body data-theme="${theme}">
|
|
${body}
|
|
</body>
|
|
</html>
|
|
`
|
|
}
|
|
}
|
|
|
|
export function getStyleParams(props) {
|
|
const {
|
|
fontSize,
|
|
lineNumber,
|
|
codeBlockTheme,
|
|
scrollPastEnd,
|
|
theme,
|
|
allowCustomCSS,
|
|
customCSS,
|
|
RTL
|
|
} = props
|
|
|
|
let { fontFamily, codeBlockFontFamily } = props
|
|
|
|
fontFamily =
|
|
_.isString(fontFamily) && fontFamily.trim().length > 0
|
|
? fontFamily
|
|
.split(',')
|
|
.map(fontName => fontName.trim())
|
|
.concat(defaultFontFamily)
|
|
: defaultFontFamily
|
|
|
|
codeBlockFontFamily =
|
|
_.isString(codeBlockFontFamily) && codeBlockFontFamily.trim().length > 0
|
|
? codeBlockFontFamily
|
|
.split(',')
|
|
.map(fontName => fontName.trim())
|
|
.concat(defaultCodeBlockFontFamily)
|
|
: defaultCodeBlockFontFamily
|
|
|
|
return {
|
|
fontFamily,
|
|
fontSize,
|
|
codeBlockFontFamily,
|
|
lineNumber,
|
|
codeBlockTheme,
|
|
scrollPastEnd,
|
|
theme,
|
|
allowCustomCSS,
|
|
customCSS,
|
|
RTL
|
|
}
|
|
}
|
|
|
|
export function getCodeThemeLink(name) {
|
|
const theme = consts.THEMES.find(theme => theme.name === name)
|
|
|
|
return theme != null
|
|
? theme.path
|
|
: `${appPath}/node_modules/codemirror/theme/elegant.css`
|
|
}
|
|
|
|
export function buildStyle(
|
|
fontFamily,
|
|
fontSize,
|
|
codeBlockFontFamily,
|
|
lineNumber,
|
|
scrollPastEnd,
|
|
theme,
|
|
allowCustomCSS,
|
|
customCSS,
|
|
RTL
|
|
) {
|
|
return `
|
|
@font-face {
|
|
font-family: 'Lato';
|
|
src: url('${appPath}/resources/fonts/Lato-Regular.woff2') format('woff2'), /* Modern Browsers */
|
|
url('${appPath}/resources/fonts/Lato-Regular.woff') format('woff'), /* Modern Browsers */
|
|
url('${appPath}/resources/fonts/Lato-Regular.ttf') format('truetype');
|
|
font-style: normal;
|
|
font-weight: normal;
|
|
text-rendering: optimizeLegibility;
|
|
}
|
|
@font-face {
|
|
font-family: 'Lato';
|
|
src: url('${appPath}/resources/fonts/Lato-Black.woff2') format('woff2'), /* Modern Browsers */
|
|
url('${appPath}/resources/fonts/Lato-Black.woff') format('woff'), /* Modern Browsers */
|
|
url('${appPath}/resources/fonts/Lato-Black.ttf') format('truetype');
|
|
font-style: normal;
|
|
font-weight: 700;
|
|
text-rendering: optimizeLegibility;
|
|
}
|
|
@font-face {
|
|
font-family: 'Material Icons';
|
|
font-style: normal;
|
|
font-weight: 400;
|
|
src: local('Material Icons'),
|
|
local('MaterialIcons-Regular'),
|
|
url('${appPath}/resources/fonts/MaterialIcons-Regular.woff2') format('woff2'),
|
|
url('${appPath}/resources/fonts/MaterialIcons-Regular.woff') format('woff'),
|
|
url('${appPath}/resources/fonts/MaterialIcons-Regular.ttf') format('truetype');
|
|
}
|
|
${markdownStyle}
|
|
|
|
body {
|
|
font-family: '${fontFamily.join("','")}';
|
|
font-size: ${fontSize}px;
|
|
${scrollPastEnd && 'padding-bottom: 90vh;box-sizing: border-box;'}
|
|
${RTL && 'direction: rtl;text-align: right;'}
|
|
}
|
|
@media print {
|
|
body {
|
|
padding-bottom: initial;
|
|
}
|
|
}
|
|
|
|
code {
|
|
font-family: '${codeBlockFontFamily.join("','")}';
|
|
background-color: rgba(0,0,0,0.04);
|
|
text-align: left;
|
|
direction: ltr;
|
|
}
|
|
|
|
p code.inline,
|
|
li code.inline,
|
|
td code.inline
|
|
{
|
|
padding: 2px;
|
|
border-width: 1px;
|
|
border-style: solid;
|
|
border-radius: 5px;
|
|
}
|
|
[data-theme="default"] p code.inline,
|
|
[data-theme="default"] li code.inline,
|
|
[data-theme="default"] td code.inline
|
|
{
|
|
background-color: #F4F4F4;
|
|
border-color: #d9d9d9;
|
|
color: inherit;
|
|
}
|
|
[data-theme="white"] p code.inline,
|
|
[data-theme="white"] li code.inline,
|
|
[data-theme="white"] td code.inline
|
|
{
|
|
background-color: #F4F4F4;
|
|
border-color: #d9d9d9;
|
|
color: inherit;
|
|
}
|
|
[data-theme="dark"] p code.inline,
|
|
[data-theme="dark"] li code.inline,
|
|
[data-theme="dark"] td code.inline
|
|
{
|
|
background-color: #444444;
|
|
border-color: #555;
|
|
color: #FFFFFF;
|
|
}
|
|
[data-theme="dracula"] p code.inline,
|
|
[data-theme="dracula"] li code.inline,
|
|
[data-theme="dracula"] td code.inline
|
|
{
|
|
background-color: #444444;
|
|
border-color: #555;
|
|
color: #FFFFFF;
|
|
}
|
|
[data-theme="monokai"] p code.inline,
|
|
[data-theme="monokai"] li code.inline,
|
|
[data-theme="monokai"] td code.inline
|
|
{
|
|
background-color: #444444;
|
|
border-color: #555;
|
|
color: #FFFFFF;
|
|
}
|
|
[data-theme="nord"] p code.inline,
|
|
[data-theme="nord"] li code.inline,
|
|
[data-theme="nord"] td code.inline
|
|
{
|
|
background-color: #444444;
|
|
border-color: #555;
|
|
color: #FFFFFF;
|
|
}
|
|
[data-theme="solarized-dark"] p code.inline,
|
|
[data-theme="solarized-dark"] li code.inline,
|
|
[data-theme="solarized-dark"] td code.inline
|
|
{
|
|
background-color: #444444;
|
|
border-color: #555;
|
|
color: #FFFFFF;
|
|
}
|
|
[data-theme="vulcan"] p code.inline,
|
|
[data-theme="vulcan"] li code.inline,
|
|
[data-theme="vulcan"] td code.inline
|
|
{
|
|
background-color: #444444;
|
|
border-color: #555;
|
|
color: #FFFFFF;
|
|
}
|
|
|
|
.lineNumber {
|
|
${lineNumber && 'display: block !important;'}
|
|
font-family: '${codeBlockFontFamily.join("','")}';
|
|
}
|
|
|
|
.clipboardButton {
|
|
color: rgba(147,147,149,0.8);;
|
|
fill: rgba(147,147,149,1);;
|
|
border-radius: 50%;
|
|
margin: 0px 10px;
|
|
border: none;
|
|
background-color: transparent;
|
|
outline: none;
|
|
height: 15px;
|
|
width: 15px;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.clipboardButton:hover {
|
|
transition: 0.2s;
|
|
color: #939395;
|
|
fill: #939395;
|
|
background-color: rgba(0,0,0,0.1);
|
|
}
|
|
|
|
h1, h2 {
|
|
border: none;
|
|
}
|
|
|
|
h1 {
|
|
padding-bottom: 4px;
|
|
margin: 1em 0 8px;
|
|
}
|
|
|
|
h2 {
|
|
padding-bottom: 0.2em;
|
|
margin: 1em 0 0.37em;
|
|
}
|
|
|
|
body p {
|
|
white-space: normal;
|
|
}
|
|
|
|
@media print {
|
|
body[data-theme="${theme}"] {
|
|
color: #000;
|
|
background-color: #fff;
|
|
}
|
|
.clipboardButton {
|
|
display: none
|
|
}
|
|
}
|
|
|
|
${allowCustomCSS ? customCSS : ''}
|
|
`
|
|
}
|
|
|
|
/**
|
|
* @description Convert special characters between three ```
|
|
* @param {string[]} splitWithCodeTag Array of HTML strings separated by three ```
|
|
* @returns {string} HTML in which special characters between three ``` have been converted
|
|
*/
|
|
export function escapeHtmlCharactersInCodeTag(splitWithCodeTag) {
|
|
for (let index = 0; index < splitWithCodeTag.length; index++) {
|
|
const codeTagRequired =
|
|
splitWithCodeTag[index] !== '```' && index < splitWithCodeTag.length - 1
|
|
if (codeTagRequired) {
|
|
splitWithCodeTag.splice(index + 1, 0, '```')
|
|
}
|
|
}
|
|
let inCodeTag = false
|
|
let result = ''
|
|
for (let content of splitWithCodeTag) {
|
|
if (content === '```') {
|
|
inCodeTag = !inCodeTag
|
|
} else if (inCodeTag) {
|
|
content = escapeHtmlCharacters(content)
|
|
}
|
|
result += content
|
|
}
|
|
return result
|
|
}
|