diff --git a/packages/app-mobile/pluginAssets/index.js b/packages/app-mobile/pluginAssets/index.js index 0638520a0..c7b6d4f76 100644 --- a/packages/app-mobile/pluginAssets/index.js +++ b/packages/app-mobile/pluginAssets/index.js @@ -1,5 +1,5 @@ module.exports = { -hash:"6cf170562f87803f3d6b9455bc66ccc9", files: { +hash:"d4cb80ea030d8b01caeb56299491f244", files: { 'highlight.js/atom-one-dark-reasonable.css': { data: require('./highlight.js/atom-one-dark-reasonable.css.base64.js'), mime: 'text/css', encoding: 'base64' }, 'highlight.js/atom-one-light.css': { data: require('./highlight.js/atom-one-light.css.base64.js'), mime: 'text/css', encoding: 'base64' }, 'katex/fonts/KaTeX_AMS-Regular.woff2': { data: require('./katex/fonts/KaTeX_AMS-Regular.woff2.base64.js'), mime: 'application/octet-stream', encoding: 'base64' }, diff --git a/packages/app-mobile/pluginAssets/mermaid/mermaid_render.js.base64.js b/packages/app-mobile/pluginAssets/mermaid/mermaid_render.js.base64.js index d5e80dcdd..bf1535415 100644 --- a/packages/app-mobile/pluginAssets/mermaid/mermaid_render.js.base64.js +++ b/packages/app-mobile/pluginAssets/mermaid/mermaid_render.js.base64.js @@ -1 +1 @@ -module.exports = `LyogZ2xvYmFsIG1lcm1haWQgKi8KCmZ1bmN0aW9uIG1lcm1haWRSZWFkeSgpIHsKCS8vIFRoZSBNZXJtYWlkIGluaXRpYWxpemF0aW9uIGNvZGUgcmVuZGVycyB0aGUgTWVybWFpZCBjb2RlIHdpdGhpbiBhbnkgZWxlbWVudCB3aXRoIGNsYXNzICJtZXJtYWlkIiBvcgoJLy8gSUQgIm1lcm1haWQiLiBIb3dldmVyIGluIHNvbWUgY2FzZXMgc29tZSBlbGVtZW50cyBtaWdodCBoYXZlIHRoaXMgSUQgYnV0IG5vdCBiZSBNZXJtYWlkIGNvZGUuCgkvLyBGb3IgZXhhbXBsZSwgTWFya2Rvd24gY29kZSBsaWtlIHRoaXM6CgkvLwoJLy8gICAgICMgTWVybWFpZAoJLy8KCS8vIFdpbGwgZ2VuZXJhdGUgdGhpcyBIVE1MOgoJLy8KCS8vICAgICA8aDEgaWQ9Im1lcm1haWQiPk1lcm1haWQ8L2gxPgoJLy8KCS8vIEFuZCB0aGF0J3MgZ29pbmcgdG8gbWFrZSB0aGUgbGliIHNldCB0aGUgYG1lcm1haWRgIG9iamVjdCB0byB0aGUgSDEgZWxlbWVudC4KCS8vIFNvIGJlbG93LCB3ZSBkb3VibGUtY2hlY2sgdGhhdCB3aGF0IHdlIGhhdmUgcmVhbGx5IGlzIGFuIGluc3RhbmNlIG9mIHRoZSBsaWJyYXJ5LgoJcmV0dXJuIHR5cGVvZiBtZXJtYWlkICE9PSAndW5kZWZpbmVkJyAmJiBtZXJtYWlkICE9PSBudWxsICYmIHR5cGVvZiBtZXJtYWlkID09PSAnb2JqZWN0JyAmJiAhIW1lcm1haWQuaW5pdDsKfQoKZnVuY3Rpb24gbWVybWFpZEluaXQoKSB7CgkvLyBNZXJtYWlkJ3Mgd29uZGVyZnVsIEFQSSBoYXMgdHdvIGluaXQgbWV0aG9kczogaW5pdCgpIGFuZCBpbml0aWFsaXplKCkuCgkvLyBpbml0KCkgaXMgZGVwcmVjdGF0ZWQgYnV0IHdvcmtzLCBhbmQgaW5pdGlhbGl6ZSgpIGlzIHJlY29tbWVuZGVkIGJ1dCBkb2Vzbid0CgkvLyB3b3JrLCBzbyBsZXQncyB1c2UgaW5pdCgpIGZvciBub3cuCglpZiAobWVybWFpZFJlYWR5KCkpIHsKCQl0cnkgewoJCQltZXJtYWlkLmluaXQoKTsKCQl9IGNhdGNoIChlcnJvcikgewoJCQljb25zb2xlLmVycm9yKCdNZXJtYWlkIGVycm9yJywgZXJyb3IpOwoJCX0KCgkJLy8gUmVzZXR0aW5nIGVsZW1lbnRzIHNpemUgLSBzZWUgbWVybWFpZC50cwoJCWNvbnN0IGVsZW1lbnRzID0gZG9jdW1lbnQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZSgnbWVybWFpZCcpOwoJCWZvciAoY29uc3QgZWxlbWVudCBvZiBlbGVtZW50cykgewoJCQllbGVtZW50LnN0eWxlLndpZHRoID0gJzEwMCUnOwoJCX0KCX0KfQoKZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignam9wbGluLW5vdGVEaWRVcGRhdGUnLCAoKSA9PiB7CgltZXJtYWlkSW5pdCgpOwp9KTsKCmNvbnN0IGluaXRJSURfID0gc2V0SW50ZXJ2YWwoKCkgPT4gewoJY29uc3QgaXNSZWFkeSA9IG1lcm1haWRSZWFkeSgpOwoJaWYgKGlzUmVhZHkpIHsKCQljbGVhckludGVydmFsKGluaXRJSURfKTsKCQltZXJtYWlkSW5pdCgpOwoJfQp9LCAxMDApOwo=`; \ No newline at end of file +module.exports = `LyogZ2xvYmFsIG1lcm1haWQgKi8KCmZ1bmN0aW9uIG1lcm1haWRSZWFkeSgpIHsKCS8vIFRoZSBNZXJtYWlkIGluaXRpYWxpemF0aW9uIGNvZGUgcmVuZGVycyB0aGUgTWVybWFpZCBjb2RlIHdpdGhpbiBhbnkgZWxlbWVudCB3aXRoIGNsYXNzICJtZXJtYWlkIiBvcgoJLy8gSUQgIm1lcm1haWQiLiBIb3dldmVyIGluIHNvbWUgY2FzZXMgc29tZSBlbGVtZW50cyBtaWdodCBoYXZlIHRoaXMgSUQgYnV0IG5vdCBiZSBNZXJtYWlkIGNvZGUuCgkvLyBGb3IgZXhhbXBsZSwgTWFya2Rvd24gY29kZSBsaWtlIHRoaXM6CgkvLwoJLy8gICAgICMgTWVybWFpZAoJLy8KCS8vIFdpbGwgZ2VuZXJhdGUgdGhpcyBIVE1MOgoJLy8KCS8vICAgICA8aDEgaWQ9Im1lcm1haWQiPk1lcm1haWQ8L2gxPgoJLy8KCS8vIEFuZCB0aGF0J3MgZ29pbmcgdG8gbWFrZSB0aGUgbGliIHNldCB0aGUgYG1lcm1haWRgIG9iamVjdCB0byB0aGUgSDEgZWxlbWVudC4KCS8vIFNvIGJlbG93LCB3ZSBkb3VibGUtY2hlY2sgdGhhdCB3aGF0IHdlIGhhdmUgcmVhbGx5IGlzIGFuIGluc3RhbmNlIG9mIHRoZSBsaWJyYXJ5LgoJcmV0dXJuIHR5cGVvZiBtZXJtYWlkICE9PSAndW5kZWZpbmVkJyAmJiBtZXJtYWlkICE9PSBudWxsICYmIHR5cGVvZiBtZXJtYWlkID09PSAnb2JqZWN0JyAmJiAhIW1lcm1haWQuaW5pdGlhbGl6ZTsKfQoKY29uc3QgaXNEYXJrTW9kZSA9ICgpID0+IHsKCS8vIElmIGFueSBtZXJtYWlkIGVsZW1lbnRzIGFyZSBtYXJrZWQgYXMgcmVxdWlyaW5nIGRhcmsgbW9kZSwgcmVuZGVyICphbGwqCgkvLyBtZXJtYWlkIGVsZW1lbnRzIGluIGRhcmsgbW9kZS4KCXJldHVybiAhIWRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJy5tZXJtYWlkLmpvcGxpbi0tbWVybWFpZC11c2UtZGFyay10aGVtZScpOwp9OwoKZnVuY3Rpb24gbWVybWFpZEluaXQoKSB7CglpZiAobWVybWFpZFJlYWR5KCkpIHsKCQljb25zdCBtZXJtYWlkVGFyZ2V0Tm9kZXMgPSBkb2N1bWVudC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKCdtZXJtYWlkJyk7CgoJCXRyeSB7CgkJCWNvbnN0IGRhcmtNb2RlID0gaXNEYXJrTW9kZSgpOwoJCQltZXJtYWlkLmluaXRpYWxpemUoewoJCQkJLy8gV2UgY2FsbCBtZXJtYWlkLnJ1biBvdXJzZWx2ZXMgd2hlbmV2ZXIgdGhlIG5vdGUgdXBkYXRlcy4gRG9uJ3QgYXV0by1zdGFydAoJCQkJc3RhcnRPbkxvYWQ6IGZhbHNlLAoKCQkJCWRhcmtNb2RlLAoJCQkJdGhlbWU6IGRhcmtNb2RlID8gJ2RhcmsnIDogJ2RlZmF1bHQnLAoJCQl9KTsKCQkJbWVybWFpZC5ydW4oewoJCQkJbm9kZXM6IG1lcm1haWRUYXJnZXROb2RlcywKCQkJfSk7CgkJfSBjYXRjaCAoZXJyb3IpIHsKCQkJY29uc29sZS5lcnJvcignTWVybWFpZCBlcnJvcicsIGVycm9yKTsKCQl9CgoJCS8vIFJlc2V0dGluZyBlbGVtZW50cyBzaXplIC0gc2VlIG1lcm1haWQudHMKCQlmb3IgKGNvbnN0IGVsZW1lbnQgb2YgbWVybWFpZFRhcmdldE5vZGVzKSB7CgkJCWVsZW1lbnQuc3R5bGUud2lkdGggPSAnMTAwJSc7CgkJfQoJfQp9Cgpkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdqb3BsaW4tbm90ZURpZFVwZGF0ZScsICgpID0+IHsKCW1lcm1haWRJbml0KCk7Cn0pOwoKY29uc3QgaW5pdElJRF8gPSBzZXRJbnRlcnZhbCgoKSA9PiB7Cgljb25zdCBpc1JlYWR5ID0gbWVybWFpZFJlYWR5KCk7CglpZiAoaXNSZWFkeSkgewoJCWNsZWFySW50ZXJ2YWwoaW5pdElJRF8pOwoJCW1lcm1haWRJbml0KCk7Cgl9Cn0sIDEwMCk7Cgpkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdET01Db250ZW50TG9hZGVkJywgKCkgPT4gewoJLy8gSW4gc29tZSBlbnZpcm9ubWVudHMsIHdlIGNhbiBsb2FkIE1lcm1haWQgaW1tZWRpYXRlbHkgKGUuZy4gbW9iaWxlKS4KCS8vIElmIHdlIGRvbid0IGxvYWQgaXQgaW1tZWRpYXRlbHkgaW4gdGhlc2UgZW52aXJvbm1lbnRzLCBNZXJtYWlkIHNlZW1zCgkvLyB0byBpbml0aWFsaXplIGFuZCBhdXRvLXJ1biwgYnV0IHdpdGhvdXQgb3VyIGNvbmZpZ3VyYXRpb24gY2hhbmdlcy4KCWlmIChtZXJtYWlkUmVhZHkoKSkgewoJCW1lcm1haWRJbml0KCk7Cgl9IGVsc2UgewoJCWNsZWFySW50ZXJ2YWwoaW5pdElJRF8pOwoJfQp9KTsK`; \ No newline at end of file diff --git a/packages/renderer/MdToHtml/rules/mermaid.ts b/packages/renderer/MdToHtml/rules/mermaid.ts index 5b26699ca..abae6869e 100644 --- a/packages/renderer/MdToHtml/rules/mermaid.ts +++ b/packages/renderer/MdToHtml/rules/mermaid.ts @@ -11,7 +11,7 @@ export default { // Note: Mermaid is buggy when rendering below a certain width (500px?) // so set an arbitrarily high width here for the container. Once the // diagram is rendered it will be reset to 100% in mermaid_render.js - text: '.mermaid { background-color: white; width: 640px; }', + text: '.mermaid { width: 640px; }', mime: 'text/css', }, { @@ -40,6 +40,15 @@ export default { const token = tokens[idx]; if (token.info !== 'mermaid') return defaultRender(tokens, idx, options, env, self); const contentHtml = markdownIt.utils.escapeHtml(token.content); + + const cssClasses = ['mermaid']; + if (ruleOptions.theme.appearance === 'dark') { + // This class applies globally -- if any elements have this class, all mermaid + // elements will be rendered in dark mode. + // (See mermaid_render.js for details). + cssClasses.push('joplin--mermaid-use-dark-theme'); + } + // Note: The mermaid script (`contentHtml`) needs to be wrapped // in a `pre` tag, otherwise in WYSIWYG mode TinyMCE removes // all the white space from it, which causes mermaid to fail. @@ -48,7 +57,7 @@ export default {
${contentHtml}
${exportButtonMarkup} -
${contentHtml}
+
${contentHtml}
`; }; diff --git a/packages/renderer/MdToHtml/rules/mermaid_render.js b/packages/renderer/MdToHtml/rules/mermaid_render.js index 320882236..7c5b93c57 100644 --- a/packages/renderer/MdToHtml/rules/mermaid_render.js +++ b/packages/renderer/MdToHtml/rules/mermaid_render.js @@ -13,23 +13,37 @@ function mermaidReady() { // // And that's going to make the lib set the `mermaid` object to the H1 element. // So below, we double-check that what we have really is an instance of the library. - return typeof mermaid !== 'undefined' && mermaid !== null && typeof mermaid === 'object' && !!mermaid.init; + return typeof mermaid !== 'undefined' && mermaid !== null && typeof mermaid === 'object' && !!mermaid.initialize; } +const isDarkMode = () => { + // If any mermaid elements are marked as requiring dark mode, render *all* + // mermaid elements in dark mode. + return !!document.querySelector('.mermaid.joplin--mermaid-use-dark-theme'); +}; + function mermaidInit() { - // Mermaid's wonderful API has two init methods: init() and initialize(). - // init() is deprectated but works, and initialize() is recommended but doesn't - // work, so let's use init() for now. if (mermaidReady()) { + const mermaidTargetNodes = document.getElementsByClassName('mermaid'); + try { - mermaid.init(); + const darkMode = isDarkMode(); + mermaid.initialize({ + // We call mermaid.run ourselves whenever the note updates. Don't auto-start + startOnLoad: false, + + darkMode, + theme: darkMode ? 'dark' : 'default', + }); + mermaid.run({ + nodes: mermaidTargetNodes, + }); } catch (error) { console.error('Mermaid error', error); } // Resetting elements size - see mermaid.ts - const elements = document.getElementsByClassName('mermaid'); - for (const element of elements) { + for (const element of mermaidTargetNodes) { element.style.width = '100%'; } } @@ -46,3 +60,14 @@ const initIID_ = setInterval(() => { mermaidInit(); } }, 100); + +document.addEventListener('DOMContentLoaded', () => { + // In some environments, we can load Mermaid immediately (e.g. mobile). + // If we don't load it immediately in these environments, Mermaid seems + // to initialize and auto-run, but without our configuration changes. + if (mermaidReady()) { + mermaidInit(); + } else { + clearInterval(initIID_); + } +}); diff --git a/packages/renderer/assets/mermaid/mermaid_render.js b/packages/renderer/assets/mermaid/mermaid_render.js index 320882236..7c5b93c57 100644 --- a/packages/renderer/assets/mermaid/mermaid_render.js +++ b/packages/renderer/assets/mermaid/mermaid_render.js @@ -13,23 +13,37 @@ function mermaidReady() { // // And that's going to make the lib set the `mermaid` object to the H1 element. // So below, we double-check that what we have really is an instance of the library. - return typeof mermaid !== 'undefined' && mermaid !== null && typeof mermaid === 'object' && !!mermaid.init; + return typeof mermaid !== 'undefined' && mermaid !== null && typeof mermaid === 'object' && !!mermaid.initialize; } +const isDarkMode = () => { + // If any mermaid elements are marked as requiring dark mode, render *all* + // mermaid elements in dark mode. + return !!document.querySelector('.mermaid.joplin--mermaid-use-dark-theme'); +}; + function mermaidInit() { - // Mermaid's wonderful API has two init methods: init() and initialize(). - // init() is deprectated but works, and initialize() is recommended but doesn't - // work, so let's use init() for now. if (mermaidReady()) { + const mermaidTargetNodes = document.getElementsByClassName('mermaid'); + try { - mermaid.init(); + const darkMode = isDarkMode(); + mermaid.initialize({ + // We call mermaid.run ourselves whenever the note updates. Don't auto-start + startOnLoad: false, + + darkMode, + theme: darkMode ? 'dark' : 'default', + }); + mermaid.run({ + nodes: mermaidTargetNodes, + }); } catch (error) { console.error('Mermaid error', error); } // Resetting elements size - see mermaid.ts - const elements = document.getElementsByClassName('mermaid'); - for (const element of elements) { + for (const element of mermaidTargetNodes) { element.style.width = '100%'; } } @@ -46,3 +60,14 @@ const initIID_ = setInterval(() => { mermaidInit(); } }, 100); + +document.addEventListener('DOMContentLoaded', () => { + // In some environments, we can load Mermaid immediately (e.g. mobile). + // If we don't load it immediately in these environments, Mermaid seems + // to initialize and auto-run, but without our configuration changes. + if (mermaidReady()) { + mermaidInit(); + } else { + clearInterval(initIID_); + } +}); diff --git a/packages/server/public/css/items/note.css b/packages/server/public/css/items/note.css index c246fa4f9..ae8c58f15 100644 --- a/packages/server/public/css/items/note.css +++ b/packages/server/public/css/items/note.css @@ -29,6 +29,11 @@ border-bottom: none; } +/* Overrides Bulma's style for
s to prevent Mermaid elements from having a grey background */
+.mermaid {
+	background-color: white;
+}
+
 /* Need to set overflow so that long tables for example are scrollable. We put
 it here and not in noteStyle because the desktop app handles scrolling
 differently at the viewer level.