Skip to content

Instantly share code, notes, and snippets.

@olliecheng
Last active September 30, 2024 16:26
Show Gist options
  • Save olliecheng/8a5e434bd97154fba81ea91e79a8c99b to your computer and use it in GitHub Desktop.
Save olliecheng/8a5e434bd97154fba81ea91e79a8c99b to your computer and use it in GitHub Desktop.
Notion - Inline Math for the Desktop App (credit https://www.notion.so/Notion-Hacks-27b92f71afcd4ae2ac9a4d14fef0ce47)
// ==UserScript==
// @name Inline Math for Notion.so
// @homepageURL https://www.notion.so/evertheylen/Notion-Inline-Math-9c5047a4e7c84643848b3630db8d5a5e
// @version 0.2.1
// @match https://www.notion.so/*
// @grant GM_addStyle
// @require https://cdn.jsdelivr.net/npm/[email protected]/dist/katex.js
// ==/UserScript==
// Instructions for use:
// - Make sure you have at least one normal math block on your page
// - Use inline code starting with "math:". For example: `math: f(x) = x^2`
// - Press F2 to rerender all inline math. You can of course change the shortcut in the code below.
// - The inline math will revert to inline code when the block becomes active.
const subscript = /_(?!{)(.+?)(?:_|(\^|$| ))/g
const superscript = /\^(?!{)(.+?)(?:\^|(_|$| ))/g
GM_addStyle(`
.notion-frame span .katex {
padding-right: 0 !important;
font-size: 1.3em;
}
`)
function rerender_all(e) {
document.querySelectorAll("body").innerHTML = "";
var code = document.querySelectorAll('span[style*="monospace"]');
code.forEach(function(el) {
if (document.activeElement.contains(el)) {
if (e.key != "F2") {
return;
}
}
var s = el.textContent;
if (s.startsWith("math:")) {
el.style.color = null;
el.style.background = null;
s = s.slice(5).trim();
katex.render(s, el, {throwOnError: true, font: "mathit"});
} else if (s.startsWith(",")) {
el.style.color = null;
el.style.background = null;
s = "\\mathrm{" + s.slice(1).trim() + "}";
var match;
while (match = s.match(subscript)) {
s = s.replace(subscript, "_{$1}$2");
}
while (match = s.match(superscript)) {
s = s.replace(superscript, "^{$1}$2");
}
katex.render(s, el, {throwOnError: true, font: "mathit"});
} else if (s.startsWith("$")) {
el.style.color = null;
el.style.background = null;
s = s.slice(1).trim();
katex.render(s, el, {throwOnError: true, font: "mathit"});
}
});
}
function rerender() {
rerender_all({key: "discard"});
setTimeout(rerender, 500);
}
setTimeout(rerender, 5000);
window.addEventListener("mousedown", rerender_all);
window.addEventListener("keydown", rerender_all, true);
const subscript = /_(?!{)(.+?)(?:_|(\^|$| ))/g
const superscript = /\^(?!{)(.+?)(?:\^|(_|$| ))/g
window.onload = function(e) {
loadJS(
"https://cdn.jsdelivr.net/npm/[email protected]/dist/katex.min.js",
function() {
rerender_all();
},
document.body
);
let customCSS = document.createElement("style");
customCSS.innerHTML = `.notion-frame span .katex {
padding-right: 0 !important;
font-size: 1.3em;
}`;
document.getElementsByTagName("head")[0].appendChild(customCSS);
};
var loadJS = function(url, implementationCode, location) {
//url is URL of external file, implementationCode is the code
//to be called from the file, location is the location to
//insert the <script> element
var scriptTag = document.createElement("script");
scriptTag.src = url;
scriptTag.onload = implementationCode;
scriptTag.onreadystatechange = implementationCode;
location.appendChild(scriptTag);
};
function rerender_all(e) {
document.querySelectorAll("body").innerHTML = "";
var code = document.querySelectorAll('span[style*="monospace"]');
code.forEach(function(el) {
if (document.activeElement.contains(el)) {
if (e.key != "F2") {
return;
}
}
var s = el.textContent;
if (s.startsWith("math:")) {
el.style.color = null;
el.style.background = null;
s = s.slice(5).trim();
katex.render(s, el, {throwOnError: true, font: "mathit"});
} else if (s.startsWith(",")) {
el.style.color = null;
el.style.background = null;
s = "\\mathrm{" + s.slice(1).trim() + "}";
var match;
while (match = s.match(subscript)) {
s = s.replace(subscript, "_{$1}$2");
}
while (match = s.match(superscript)) {
s = s.replace(superscript, "^{$1}$2");
}
katex.render(s, el, {throwOnError: true, font: "mathit"});
} else if (s.startsWith("$")) {
el.style.color = null;
el.style.background = null;
s = s.slice(1).trim();
katex.render(s, el, {throwOnError: true, font: "mathit"});
}
});
}
function rerender() {
rerender_all({key: "discard"});
setTimeout(rerender, 500);
}
setTimeout(rerender, 5000);
window.addEventListener("mousedown", rerender_all);
window.addEventListener("keydown", rerender_all, true);
( cd /Applications/Notion.app/Contents/Resources; asar extract app.asar app )
# cp inlinemath.js /Applications/Notion.app/Contents/Resources/app/renderer/inlinemath.js
# sed -i '' 's/<\/head>/<script src="inlinemath.js"><\/script><\/head>/g' /Applications/Notion.app/Contents/Resources/app/renderer/index.html
echo "\n" >> /Applications/Notion.app/Contents/Resources/app/renderer/preload.js
cat inlinemath.js >> /Applications/Notion.app/Contents/Resources/app/renderer/preload.js
@olliecheng
Copy link
Author

The desktop Notion app loads file contents from the app.azar. By editing app.azar, we can edit the code which loads the Notion webpage (it's not just a frame around the web app, there's also a little bit of wrapper code). @alanzchen

@davidwud
Copy link

davidwud commented Jun 7, 2020

Can someone please walk me through installing this? I have no idea what to do, thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment