1
0
mirror of https://github.com/BoostIo/Boostnote synced 2025-12-13 17:56:25 +00:00
Files
Boostnote/browser/main/lib/dataApi/formatHTML.js
2018-11-15 22:48:14 +01:00

296 lines
6.8 KiB
JavaScript

import path from 'path'
import fileUrl from 'file-url'
import { remote } from 'electron'
import consts from 'browser/lib/consts'
import Markdown from 'browser/lib/markdown'
import attachmentManagement from './attachmentManagement'
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`
]
const defaultFontFamily = ['helvetica', 'arial', 'sans-serif']
if (global.process.platform !== 'darwin') {
defaultFontFamily.unshift('Microsoft YaHei')
defaultFontFamily.unshift('meiryo')
}
const defaultCodeBlockFontFamily = [
'Monaco',
'Menlo',
'Ubuntu Mono',
'Consolas',
'source-code-pro',
'monospace'
]
/**
* ```
* {
* fontFamily,
* fontSize,
* lineNumber,
* codeBlockFontFamily,
* codeBlockTheme,
* scrollPastEnd,
* theme,
* allowCustomCSS,
* customCSS
* smartQuotes,
* sanitize,
* breaks,
* storagePath,
* export
* }
* ```
*/
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
const markdown = new Markdown({
typographer: smartQuotes,
sanitize,
breaks
})
const files = [getCodeThemeLink(codeBlockTheme), ...CSS_FILES]
return function (note, targetPath, exportTasks) {
let body = markdown.render(note.content)
const attachmentsAbsolutePaths = attachmentManagement.getAbsolutePathsOfAttachmentsInContent(note.content, props.storagePath)
files.forEach(file => {
if (global.process.platform === 'win32') {
file = file.replace('file:///', '')
} else {
file = file.replace('file://', '')
}
exportTasks.push({
src: 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)
let styles = ''
files.forEach(file => {
styles += `<link rel="stylesheet" href="css/${path.basename(file)}">`
})
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}
</head>
<body>${body}</body>
</html>`
}
}
export function getStyleParams (props) {
const {
fontSize,
lineNumber,
codeBlockTheme,
scrollPastEnd,
theme,
allowCustomCSS,
customCSS
} = 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
}
}
export function getCodeThemeLink (theme) {
if (consts.THEMES.some(_theme => _theme === theme)) {
theme = theme !== 'default' ? theme : 'elegant'
}
return theme.startsWith('solarized')
? `${appPath}/node_modules/codemirror/theme/solarized.css`
: `${appPath}/node_modules/codemirror/theme/${theme}.css`
}
export function buildStyle (
fontFamily,
fontSize,
codeBlockFontFamily,
lineNumber,
scrollPastEnd,
theme,
allowCustomCSS,
customCSS
) {
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;'}
}
@media print {
body {
padding-bottom: initial;
}
}
code {
font-family: '${codeBlockFontFamily.join("','")}';
background-color: rgba(0,0,0,0.04);
}
.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 : ''}
`
}