mirror of
https://github.com/streetwriters/notesnook.git
synced 2025-12-16 19:57:52 +01:00
core: pre-render math & code blocks before HTML export
This commit is contained in:
committed by
Abdullah Atta
parent
69dee3be78
commit
75e62a3fac
@@ -136,3 +136,28 @@ export async function exportNotes(
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function renderMath(content: string) {
|
||||
const katex = require("katex");
|
||||
require("katex/contrib/mhchem");
|
||||
|
||||
const div = document.createElement("div");
|
||||
div.innerHTML = content;
|
||||
|
||||
const mathBlocks = div.querySelectorAll(".math-block.math-node");
|
||||
const mathInlines = div.querySelectorAll(".math-inline.math-node");
|
||||
|
||||
for (const mathBlock of mathBlocks) {
|
||||
const text = mathBlock.textContent;
|
||||
mathBlock.innerHTML = katex.renderToString(text, {
|
||||
displayMode: true,
|
||||
output: "mathml"
|
||||
});
|
||||
}
|
||||
for (const mathInline of mathInlines) {
|
||||
const text = mathInline.textContent;
|
||||
mathInline.innerHTML = katex.renderToString(text, { output: "mathml" });
|
||||
}
|
||||
|
||||
return div.innerHTML;
|
||||
}
|
||||
|
||||
@@ -120,7 +120,7 @@ export default class Note {
|
||||
case "html":
|
||||
templateData.content = rawHTML || content.toHTML();
|
||||
return template
|
||||
? HTMLBuilder.buildHTML(templateData)
|
||||
? await HTMLBuilder.buildHTML(templateData)
|
||||
: templateData.content;
|
||||
case "txt":
|
||||
templateData.content = rawHTML || content.toTXT();
|
||||
|
||||
88
packages/core/package-lock.json
generated
88
packages/core/package-lock.json
generated
@@ -18,9 +18,11 @@
|
||||
"entities": "^4.3.1",
|
||||
"html-to-text": "^9.0.5",
|
||||
"htmlparser2": "^8.0.1",
|
||||
"katex": "^0.16.8",
|
||||
"linkedom": "^0.14.17",
|
||||
"liqe": "^1.13.0",
|
||||
"mime-db": "1.52.0",
|
||||
"prismjs": "^1.29.0",
|
||||
"qclone": "^1.2.0",
|
||||
"spark-md5": "^3.0.2"
|
||||
},
|
||||
@@ -32,6 +34,8 @@
|
||||
"@notesnook/crypto": "file:../crypto",
|
||||
"@types/html-to-text": "^9.0.0",
|
||||
"@types/jest": "^28.1.6",
|
||||
"@types/katex": "^0.16.1",
|
||||
"@types/prismjs": "^1.26.0",
|
||||
"@types/showdown": "^2.0.0",
|
||||
"abortcontroller-polyfill": "^1.7.3",
|
||||
"analyze-es6-modules": "^0.6.2",
|
||||
@@ -2743,6 +2747,12 @@
|
||||
"pretty-format": "^28.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/katex": {
|
||||
"version": "0.16.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/katex/-/katex-0.16.1.tgz",
|
||||
"integrity": "sha512-cwglq2A63Yk082CQk0t8LIoDhZAVgJqkumLyk3grpg3K8sevaDW//Qsspmxj9Sf+97biqt79CfAlPrvizHlP0w==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "18.11.9",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.9.tgz",
|
||||
@@ -2755,6 +2765,12 @@
|
||||
"integrity": "sha512-ri0UmynRRvZiiUJdiz38MmIblKK+oH30MztdBVR95dv/Ubw6neWSb8u1XpRb72L4qsZOhz+L+z9JD40SJmfWow==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/prismjs": {
|
||||
"version": "1.26.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/prismjs/-/prismjs-1.26.0.tgz",
|
||||
"integrity": "sha512-ZTaqn/qSqUuAq1YwvOFQfVW1AR/oQJlLSZVustdjwI+GZ8kr0MSHBj0tsXPW1EqHubx50gtBEjbPGsdZwQwCjQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/showdown": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/showdown/-/showdown-2.0.0.tgz",
|
||||
@@ -7943,6 +7959,29 @@
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/katex": {
|
||||
"version": "0.16.8",
|
||||
"resolved": "https://registry.npmjs.org/katex/-/katex-0.16.8.tgz",
|
||||
"integrity": "sha512-ftuDnJbcbOckGY11OO+zg3OofESlbR5DRl2cmN8HeWeeFIV7wTXvAOx8kEjZjobhA+9wh2fbKeO6cdcA9Mnovg==",
|
||||
"funding": [
|
||||
"https://opencollective.com/katex",
|
||||
"https://github.com/sponsors/katex"
|
||||
],
|
||||
"dependencies": {
|
||||
"commander": "^8.3.0"
|
||||
},
|
||||
"bin": {
|
||||
"katex": "cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/katex/node_modules/commander": {
|
||||
"version": "8.3.0",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz",
|
||||
"integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==",
|
||||
"engines": {
|
||||
"node": ">= 12"
|
||||
}
|
||||
},
|
||||
"node_modules/kleur": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz",
|
||||
@@ -8587,6 +8626,14 @@
|
||||
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/prismjs": {
|
||||
"version": "1.29.0",
|
||||
"resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.29.0.tgz",
|
||||
"integrity": "sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/private": {
|
||||
"version": "0.1.8",
|
||||
"resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz",
|
||||
@@ -11630,6 +11677,12 @@
|
||||
"pretty-format": "^28.0.0"
|
||||
}
|
||||
},
|
||||
"@types/katex": {
|
||||
"version": "0.16.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/katex/-/katex-0.16.1.tgz",
|
||||
"integrity": "sha512-cwglq2A63Yk082CQk0t8LIoDhZAVgJqkumLyk3grpg3K8sevaDW//Qsspmxj9Sf+97biqt79CfAlPrvizHlP0w==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "18.11.9",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.9.tgz",
|
||||
@@ -11642,6 +11695,12 @@
|
||||
"integrity": "sha512-ri0UmynRRvZiiUJdiz38MmIblKK+oH30MztdBVR95dv/Ubw6neWSb8u1XpRb72L4qsZOhz+L+z9JD40SJmfWow==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/prismjs": {
|
||||
"version": "1.26.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/prismjs/-/prismjs-1.26.0.tgz",
|
||||
"integrity": "sha512-ZTaqn/qSqUuAq1YwvOFQfVW1AR/oQJlLSZVustdjwI+GZ8kr0MSHBj0tsXPW1EqHubx50gtBEjbPGsdZwQwCjQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/showdown": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/showdown/-/showdown-2.0.0.tgz",
|
||||
@@ -15296,7 +15355,8 @@
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz",
|
||||
"integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"jest-regex-util": {
|
||||
"version": "28.0.2",
|
||||
@@ -15970,7 +16030,8 @@
|
||||
"version": "8.11.0",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz",
|
||||
"integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -15992,6 +16053,21 @@
|
||||
"integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==",
|
||||
"dev": true
|
||||
},
|
||||
"katex": {
|
||||
"version": "0.16.8",
|
||||
"resolved": "https://registry.npmjs.org/katex/-/katex-0.16.8.tgz",
|
||||
"integrity": "sha512-ftuDnJbcbOckGY11OO+zg3OofESlbR5DRl2cmN8HeWeeFIV7wTXvAOx8kEjZjobhA+9wh2fbKeO6cdcA9Mnovg==",
|
||||
"requires": {
|
||||
"commander": "^8.3.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"commander": {
|
||||
"version": "8.3.0",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz",
|
||||
"integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"kleur": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz",
|
||||
@@ -16483,6 +16559,11 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"prismjs": {
|
||||
"version": "1.29.0",
|
||||
"resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.29.0.tgz",
|
||||
"integrity": "sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q=="
|
||||
},
|
||||
"private": {
|
||||
"version": "0.1.8",
|
||||
"resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz",
|
||||
@@ -17230,7 +17311,8 @@
|
||||
"ws": {
|
||||
"version": "7.5.9",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz",
|
||||
"integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q=="
|
||||
"integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==",
|
||||
"requires": {}
|
||||
},
|
||||
"xml-name-validator": {
|
||||
"version": "4.0.0",
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
"@notesnook/crypto": "file:../crypto",
|
||||
"@types/html-to-text": "^9.0.0",
|
||||
"@types/jest": "^28.1.6",
|
||||
"@types/katex": "^0.16.1",
|
||||
"@types/prismjs": "^1.26.0",
|
||||
"@types/showdown": "^2.0.0",
|
||||
"abortcontroller-polyfill": "^1.7.3",
|
||||
"analyze-es6-modules": "^0.6.2",
|
||||
@@ -45,9 +47,11 @@
|
||||
"entities": "^4.3.1",
|
||||
"html-to-text": "^9.0.5",
|
||||
"htmlparser2": "^8.0.1",
|
||||
"katex": "^0.16.8",
|
||||
"linkedom": "^0.14.17",
|
||||
"liqe": "^1.13.0",
|
||||
"mime-db": "1.52.0",
|
||||
"prismjs": "^1.29.0",
|
||||
"qclone": "^1.2.0",
|
||||
"spark-md5": "^3.0.2"
|
||||
},
|
||||
|
||||
@@ -17,10 +17,69 @@ You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { parseHTML } from "../../html-parser";
|
||||
import HTMLTemplate from "./template";
|
||||
|
||||
function buildHTML(templateData) {
|
||||
return HTMLTemplate(templateData);
|
||||
const LANGUAGE_REGEX = /(?:^|\s)lang(?:uage)?-([\w-]+)(?=\s|$)/i;
|
||||
|
||||
async function buildHTML(templateData) {
|
||||
return HTMLTemplate(await preprocessHTML(templateData));
|
||||
}
|
||||
|
||||
async function preprocessHTML(templateData) {
|
||||
const { content } = templateData;
|
||||
const doc = parseHTML(
|
||||
content.replaceAll(/<p(.+?)><\/p>/gm, "<p$1><br/></p>")
|
||||
);
|
||||
|
||||
const mathBlocks = doc.querySelectorAll(".math-block.math-node");
|
||||
const mathInlines = doc.querySelectorAll(".math-inline.math-node");
|
||||
|
||||
if (mathBlocks.length || mathInlines.length) {
|
||||
const { default: katex } = require("katex");
|
||||
require("katex/contrib/mhchem");
|
||||
|
||||
for (const mathBlock of mathBlocks) {
|
||||
const text = mathBlock.textContent;
|
||||
mathBlock.innerHTML = katex.renderToString(text, {
|
||||
displayMode: true,
|
||||
output: "mathml"
|
||||
});
|
||||
}
|
||||
|
||||
for (const mathInline of mathInlines) {
|
||||
const text = mathInline.textContent;
|
||||
mathInline.innerHTML = katex.renderToString(text, { output: "mathml" });
|
||||
}
|
||||
templateData.hasMathBlocks = true;
|
||||
}
|
||||
|
||||
const codeblocks = doc.querySelectorAll("pre > code");
|
||||
if (codeblocks.length) {
|
||||
const { default: prismjs } = require("prismjs");
|
||||
prismjs.register = () => {};
|
||||
for (const codeblock of codeblocks) {
|
||||
const language = LANGUAGE_REGEX.exec(
|
||||
codeblock.parentElement.className
|
||||
)?.[1];
|
||||
if (!language) continue;
|
||||
const {
|
||||
default: grammar
|
||||
} = require(`../../../../editor/languages/${language}.js`);
|
||||
|
||||
grammar(prismjs);
|
||||
|
||||
codeblock.innerHTML = prismjs.highlight(
|
||||
codeblock.textContent,
|
||||
prismjs.languages[language],
|
||||
language
|
||||
);
|
||||
}
|
||||
templateData.hasCodeblock = true;
|
||||
}
|
||||
|
||||
templateData.content = doc.body.innerHTML;
|
||||
return templateData;
|
||||
}
|
||||
|
||||
export default { buildHTML };
|
||||
|
||||
@@ -30,6 +30,8 @@ const template = (data) => `<!DOCTYPE html>
|
||||
<meta name="created-on" content="${data.createdOn}" />
|
||||
<meta name="last-edited-on" content="${data.editedOn}" />
|
||||
${data.tags ? `<meta name="tags" content="${data.tags}" />` : ""}
|
||||
<link rel="stylesheet" href="https://app.notesnook.com/assets/index-b3954e4fc2fc.css">
|
||||
|
||||
<style>
|
||||
img {
|
||||
max-width: 100% !important;
|
||||
@@ -40,8 +42,7 @@ const template = (data) => `<!DOCTYPE html>
|
||||
body {
|
||||
background-color: transparent !important;
|
||||
color: #202124;
|
||||
font-family: "Open Sans", "Noto Sans", Frutiger, Calibri, Myriad, Arial,
|
||||
Ubuntu, Helvetica, -apple-system, BlinkMacSystemFont, sans-serif;
|
||||
font-family: "Open Sans", "Noto Sans", Frutiger, Calibri, Myriad, Arial, Ubuntu, Helvetica, -apple-system, BlinkMacSystemFont, sans-serif;
|
||||
}
|
||||
|
||||
h1,
|
||||
@@ -123,22 +124,19 @@ const template = (data) => `<!DOCTYPE html>
|
||||
border: 1px solid #e5e5e5;
|
||||
border-radius: 5px;
|
||||
padding: 3px 5px 0px 5px;
|
||||
font-family: ui-monospace, SFMono-Regular, SF Mono, Consolas,
|
||||
Liberation Mono, Menlo, monospace !important;
|
||||
font-family: Hack, Consolas, "Andale Mono", "Lucida Console", "Liberation Mono", "Courier New", Courier, monospace !important;
|
||||
font-size: 10pt !important;
|
||||
}
|
||||
|
||||
.ProseMirror code > span {
|
||||
font-family: ui-monospace, SFMono-Regular, SF Mono, Consolas,
|
||||
Liberation Mono, Menlo, monospace !important;
|
||||
font-family: Hack, Consolas, "Andale Mono", "Lucida Console", "Liberation Mono", "Courier New", Courier, monospace !important;
|
||||
}
|
||||
|
||||
pre {
|
||||
padding: 10px;
|
||||
background-color: #e5e5e5;
|
||||
border-radius: 5px;
|
||||
font-family: ui-monospace, SFMono-Regular, SF Mono, Consolas,
|
||||
Liberation Mono, Menlo, monospace !important;
|
||||
font-family: Hack, Consolas, "Andale Mono", "Lucida Console", "Liberation Mono", "Courier New", Courier, monospace !important;
|
||||
margin-bottom: 16px !important;
|
||||
}
|
||||
|
||||
@@ -172,47 +170,6 @@ const template = (data) => `<!DOCTYPE html>
|
||||
table p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
code[class*="language-"],
|
||||
pre[class*="language-"]
|
||||
{
|
||||
color: #F8F8F2;
|
||||
background: #282A36;
|
||||
text-shadow: none;
|
||||
font-family: PT Mono, Consolas, Monaco, "Andale Mono", "Ubuntu Mono",
|
||||
monospace;
|
||||
text-align: left;
|
||||
white-space: pre-wrap;
|
||||
word-spacing: normal;
|
||||
word-break: break-word;
|
||||
word-wrap: normal;
|
||||
line-height: 1.5;
|
||||
|
||||
-moz-tab-size: 4;
|
||||
-o-tab-size: 4;
|
||||
tab-size: 4;
|
||||
|
||||
-webkit-hyphens: none;
|
||||
-moz-hyphens: none;
|
||||
-ms-hyphens: none;
|
||||
hyphens: none;
|
||||
}
|
||||
|
||||
pre[class*="language-"]
|
||||
{
|
||||
background: #282A36;
|
||||
border-radius: 0.5em;
|
||||
padding: 1em;
|
||||
margin: 0.5em 0;
|
||||
overflow: auto;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
:not(pre) > code[class*="language-"],
|
||||
pre[class*="language-"]
|
||||
{
|
||||
background: #282A36;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
Reference in New Issue
Block a user