Spaces:
Runtime error
Runtime error
feat: monkey-patch mhchem
Browse files- app.py +4 -0
- mh_chem_markdown.py +156 -0
- monomer_dimer.ipynb +1 -2
app.py
CHANGED
@@ -3,6 +3,10 @@ from pathlib import Path
|
|
3 |
import solara
|
4 |
from solara.website.components.notebook import Notebook
|
5 |
|
|
|
|
|
|
|
|
|
6 |
|
7 |
@solara.component
|
8 |
def Page():
|
|
|
3 |
import solara
|
4 |
from solara.website.components.notebook import Notebook
|
5 |
|
6 |
+
from mh_chem_markdown import _markdown_template
|
7 |
+
|
8 |
+
solara.components.markdown._markdown_template = _markdown_template
|
9 |
+
|
10 |
|
11 |
@solara.component
|
12 |
def Page():
|
mh_chem_markdown.py
ADDED
@@ -0,0 +1,156 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
def _markdown_template(
|
2 |
+
html,
|
3 |
+
style="",
|
4 |
+
):
|
5 |
+
template = (
|
6 |
+
"""
|
7 |
+
<template>
|
8 |
+
<div class="solara-markdown rendered_html jp-RenderedHTMLCommon" style=\""""
|
9 |
+
+ style
|
10 |
+
+ """\">"""
|
11 |
+
+ html
|
12 |
+
+ r"""</div>
|
13 |
+
</template>
|
14 |
+
|
15 |
+
<script>
|
16 |
+
module.exports = {
|
17 |
+
async mounted() {
|
18 |
+
await this.loadRequire();
|
19 |
+
this.mermaid = await this.loadMermaid();
|
20 |
+
this.mermaid.init();
|
21 |
+
await this.loadMHchem();
|
22 |
+
this.latexSettings = {
|
23 |
+
delimiters: [
|
24 |
+
{left: "$$", right: "$$", display: true},
|
25 |
+
{left: "$", right: "$", display: false},
|
26 |
+
{left: "\\[", right: "\\]", display: true},
|
27 |
+
{left: "\\(", right: "\\)", display: false}
|
28 |
+
]
|
29 |
+
};
|
30 |
+
if (window.renderMathInElement) {
|
31 |
+
window.renderMathInElement(this.$el, this.latexSettings);
|
32 |
+
} else if (window.MathJax && MathJax.Hub) {
|
33 |
+
MathJax.Hub.Queue(['Typeset', MathJax.Hub, this.$el]);
|
34 |
+
} else {
|
35 |
+
window.renderMathInElement = await this.loadKatexExt();
|
36 |
+
window.renderMathInElement(this.$el, this.latexSettings);
|
37 |
+
}
|
38 |
+
this.$el.querySelectorAll("a").forEach(a => this.setupRouter(a))
|
39 |
+
window.md = this.$el
|
40 |
+
},
|
41 |
+
methods: {
|
42 |
+
setupRouter(a) {
|
43 |
+
let href = a.attributes['href'].value;
|
44 |
+
if(href.startsWith("./")) {
|
45 |
+
// TODO: should we really do this?
|
46 |
+
href = location.pathname + href.substr(1);
|
47 |
+
a.attributes['href'].href = href;
|
48 |
+
}
|
49 |
+
if(href.startsWith("./") || href.startsWith("/")) {
|
50 |
+
a.onclick = e => {
|
51 |
+
console.log("clicked", href)
|
52 |
+
if(href.startsWith("./")) {
|
53 |
+
solara.router.push(href);
|
54 |
+
} else {
|
55 |
+
solara.router.push(href);
|
56 |
+
}
|
57 |
+
e.preventDefault()
|
58 |
+
}
|
59 |
+
} else if(href.startsWith("#")) {
|
60 |
+
href = location.pathname + href;
|
61 |
+
a.attributes['href'].value = href;
|
62 |
+
} else {
|
63 |
+
console.log("href", href, "is not a local link")
|
64 |
+
}
|
65 |
+
},
|
66 |
+
async loadKatex() {
|
67 |
+
require.config({
|
68 |
+
map: {
|
69 |
+
'*': {
|
70 |
+
'katex': `${this.getCdn()}/[email protected]/dist/katex.min.js`,
|
71 |
+
}
|
72 |
+
}
|
73 |
+
});
|
74 |
+
const link = document.createElement('link');
|
75 |
+
link.type = "text/css";
|
76 |
+
link.rel = "stylesheet";
|
77 |
+
link.href = `${this.getCdn()}/[email protected]/dist/katex.min.css`;
|
78 |
+
document.head.appendChild(link);
|
79 |
+
},
|
80 |
+
async loadKatexExt() {
|
81 |
+
this.loadKatex();
|
82 |
+
return (await this.import([`${this.getCdn()}/[email protected]/dist/contrib/auto-render.min.js`]))[0]
|
83 |
+
},
|
84 |
+
async loadMermaid() {
|
85 |
+
return (await this.import([`${this.getCdn()}/[email protected]/dist/mermaid.min.js`]))[0]
|
86 |
+
},
|
87 |
+
async loadMHchem() {
|
88 |
+
await this.loadKatex();
|
89 |
+
return (await this.import([`${this.getCdn()}/[email protected]/dist/contrib/mhchem.min.js`]))[0];
|
90 |
+
},
|
91 |
+
|
92 |
+
import(dependencies) {
|
93 |
+
return this.loadRequire().then(
|
94 |
+
() => {
|
95 |
+
if (window.jupyterVue) {
|
96 |
+
// in jupyterlab, we take Vue from ipyvue/jupyterVue
|
97 |
+
define("vue", [], () => window.jupyterVue.Vue);
|
98 |
+
} else {
|
99 |
+
define("vue", ['jupyter-vue'], jupyterVue => jupyterVue.Vue);
|
100 |
+
}
|
101 |
+
return new Promise((resolve, reject) => {
|
102 |
+
requirejs(dependencies, (...modules) => resolve(modules));
|
103 |
+
})
|
104 |
+
}
|
105 |
+
);
|
106 |
+
},
|
107 |
+
loadRequire() {
|
108 |
+
if (window.requirejs) {
|
109 |
+
return Promise.resolve();
|
110 |
+
}
|
111 |
+
return new Promise((resolve, reject) => {
|
112 |
+
const script = document.createElement('script');
|
113 |
+
script.src = `${this.getCdn()}/[email protected]/require.min.js`;
|
114 |
+
script.onload = resolve;
|
115 |
+
script.onerror = reject;
|
116 |
+
document.head.appendChild(script);
|
117 |
+
});
|
118 |
+
},
|
119 |
+
getBaseUrl() {
|
120 |
+
if (window.solara && window.solara.rootPath !== undefined) {
|
121 |
+
return solara.rootPath + "/";
|
122 |
+
}
|
123 |
+
// if base url is set, we use ./ for relative paths compared to the base url
|
124 |
+
if (document.getElementsByTagName("base").length) {
|
125 |
+
return "./";
|
126 |
+
}
|
127 |
+
const labConfigData = document.getElementById('jupyter-config-data');
|
128 |
+
if (labConfigData) {
|
129 |
+
/* lab and Voila */
|
130 |
+
return JSON.parse(labConfigData.textContent).baseUrl;
|
131 |
+
}
|
132 |
+
let base = document.body.dataset.baseUrl || document.baseURI;
|
133 |
+
if (!base.endsWith('/')) {
|
134 |
+
base += '/';
|
135 |
+
}
|
136 |
+
return base
|
137 |
+
},
|
138 |
+
getCdn() {
|
139 |
+
return this.cdn || (typeof solara_cdn !== "undefined" && solara_cdn) || `${this.getBaseUrl()}_solara/cdn`;
|
140 |
+
}
|
141 |
+
},
|
142 |
+
updated() {
|
143 |
+
// if the html gets update, re-run mermaid
|
144 |
+
this.mermaid.init();
|
145 |
+
|
146 |
+
if(window.MathJax && MathJax.Hub) {
|
147 |
+
MathJax.Hub.Queue(['Typeset', MathJax.Hub, this.$el]);
|
148 |
+
} else {
|
149 |
+
window.renderMathInElement(this.$el, this.latexSettings);
|
150 |
+
}
|
151 |
+
}
|
152 |
+
}
|
153 |
+
</script>
|
154 |
+
"""
|
155 |
+
)
|
156 |
+
return template
|
monomer_dimer.ipynb
CHANGED
@@ -18,10 +18,9 @@
|
|
18 |
"## Monomer - Dimer kinetics\n",
|
19 |
"\n",
|
20 |
"Lets start with the simple example of dimer formation from two identical protomers:\n",
|
21 |
-
"(TODO: mhchem package)\n",
|
22 |
"\n",
|
23 |
"$$\n",
|
24 |
-
"
|
25 |
"$$\n",
|
26 |
"\n",
|
27 |
"From the kinetic scheme above, we can write down the differential equations describing this system. These differential equations tell us how the concentrations of the reaction (in this case dimerization) change in time. \n",
|
|
|
18 |
"## Monomer - Dimer kinetics\n",
|
19 |
"\n",
|
20 |
"Lets start with the simple example of dimer formation from two identical protomers:\n",
|
|
|
21 |
"\n",
|
22 |
"$$\n",
|
23 |
+
"\\ce{P1 + P1 <=>[k_{on}][k_{off}] P2}\n",
|
24 |
"$$\n",
|
25 |
"\n",
|
26 |
"From the kinetic scheme above, we can write down the differential equations describing this system. These differential equations tell us how the concentrations of the reaction (in this case dimerization) change in time. \n",
|