diff --git a/Makefile b/Makefile index b2e54fcd6..e15f92b0d 100644 --- a/Makefile +++ b/Makefile @@ -50,7 +50,11 @@ SIX_LIBS=$(SIX_ROOT)/six.py SITEPACKAGES=root/lib/python$(PYMINOR)/site-packages -all: build/pyodide.asm.html build/pyodide.js build/pyodide_dev.js build/python.html +all: build/pyodide.asm.html \ + build/pyodide.js \ + build/pyodide_dev.js \ + build/python.html \ + build/renderedhtml.css build/pyodide.asm.html: src/main.bc src/jsimport.bc src/jsproxy.bc src/js2python.bc \ @@ -80,6 +84,10 @@ build/test.html: src/test.html cp $< $@ +build/renderedhtml.css: src/renderedhtml.less + lessc $< $@ + + test: all build/test.html py.test test -v diff --git a/README.md b/README.md index 9353a85b1..df58c585e 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,8 @@ These instructions were tested on Linux. OSX should be substantively the same. Make sure the prerequisites for emsdk are installed. +Install [lessc](https://lesscss.org/) to compile less to css. + Type `make`. (The build downloads and builds a local, patched version of emsdk, then diff --git a/src/pyodide.js b/src/pyodide.js index f97de5dd0..0582b0e48 100644 --- a/src/pyodide.js +++ b/src/pyodide.js @@ -25,6 +25,12 @@ var languagePluginLoader = new Promise((resolve, reject) => { window.pyodide = pyodide(Module); }; document.body.appendChild(script); + + let link = document.createElement('link'); + link.rel = 'stylesheet'; + link.type = 'text/css'; + link.href = `${baseURL}renderedhtml.css`; + document.getElementsByTagName('head')[0].appendChild(link); }; wasmXHR.send(null); @@ -37,14 +43,17 @@ var languagePluginLoader = new Promise((resolve, reject) => { }, render: (val) => { - if (val.hasattr('to_html')) { - return new DOMParser().parseFromString( - val.getattr('to_html').call([], {}), 'text/html').body.firstChild; + let div = document.createElement('div'); + div.className = 'rendered_html'; + if (val.hasattr('_repr_html_')) { + div.appendChild(new DOMParser().parseFromString( + val.getattr('_repr_html_').call([], {}), 'text/html').body.firstChild); } else { let pre = document.createElement('pre'); pre.textContent = window.pyodide.repr(val); - return pre; + div.appendChild(pre); } + return div; } }; window.iodide.addOutputHandler(py_output_handler); diff --git a/src/renderedhtml.less b/src/renderedhtml.less new file mode 100644 index 000000000..687fc5299 --- /dev/null +++ b/src/renderedhtml.less @@ -0,0 +1,144 @@ +// This is a lightly modified version of the renderedhtml.less file included with +// Jupyter + +.rendered_html { + + overflow: auto; + max-height: 30em; + + color: black; + em {font-style: italic;} + strong {font-weight: bold;} + u {text-decoration: underline;} + :link {text-decoration: underline;} + :visited {text-decoration: underline;} + + // For a 14px base font size this goes as: + // font-size = 26, 22, 18, 14, 12, 12 + // margin-top = 14, 14, 14, 14, 8, 8 + h1 {font-size: 185.7%; margin: 1.08em 0 0 0; font-weight: bold; line-height: 1.0;} + h2 {font-size: 157.1%; margin: 1.27em 0 0 0; font-weight: bold; line-height: 1.0;} + h3 {font-size: 128.6%; margin: 1.55em 0 0 0; font-weight: bold; line-height: 1.0;} + h4 {font-size: 100%; margin: 2em 0 0 0; font-weight: bold; line-height: 1.0;} + h5 {font-size: 100%; margin: 2em 0 0 0; font-weight: bold; line-height: 1.0; font-style: italic;} + h6 {font-size: 100%; margin: 2em 0 0 0; font-weight: bold; line-height: 1.0; font-style: italic;} + + // Reduce the top margins by 14px compared to above + h1:first-child {margin-top: 0.538em;} + h2:first-child {margin-top: 0.636em;} + h3:first-child {margin-top: 0.777em;} + h4:first-child {margin-top: 1em;} + h5:first-child {margin-top: 1em;} + h6:first-child {margin-top: 1em;} + + ul:not(.list-inline), + ol:not(.list-inline) {padding-left: 2em;} + ul {list-style:disc;} + ul ul { + list-style:square; + margin-top: 0; + } + ul ul ul {list-style:circle;} + ol {list-style:decimal;} + ol ol { + list-style:upper-alpha; + margin-top: 0; + } + ol ol ol {list-style:lower-alpha; } + ol ol ol ol {list-style:lower-roman; } + /* any extras will just be numbers: */ + ol ol ol ol ol {list-style:decimal;} + * + ul {margin-top: 1em;} + * + ol {margin-top: 1em;} + + hr { + color: black; + background-color: black; + } + + pre { + margin: 1em 2em; + padding: 0px; + background-color: white; + } + + code { + background-color: #eff0f1; + } + + p code { + padding: 1px 5px; + } + + pre code {background-color: white;} + + pre, code { + border: 0; + color: black; + font-size: 100%; + } + + blockquote {margin: 1em 2em;} + + table { + margin-left: auto; + margin-right: auto; + border: none; + border-collapse: collapse; + border-spacing: 0; + color: black; + font-size: 12px; + table-layout: fixed; + } + thead { + border-bottom: 1px solid black; + vertical-align: bottom; + } + tr, th, td { + text-align: right; + vertical-align: middle; + padding: 0.5em 0.5em; + line-height: normal; + white-space: normal; + max-width: none; + border: none; + } + th { + font-weight: bold; + } + tbody tr:nth-child(odd) { + background: #f5f5f5; + } + tbody tr:hover { + background: rgba(66, 165, 245, 0.2); + } + * + table {margin-top: 1em;} + + p {text-align: left;} + * + p {margin-top: 1em;} + + img { + display: block; + margin-left: auto; + margin-right: auto; + } + * + img {margin-top: 1em;} + + img, svg { + max-width: 100%; + height: auto; + &.unconfined { + max-width: none; + } + } + + // Override bootstrap settings, see #1390 + .alert {margin-bottom: initial;} + * + .alert {margin-top: 1em;} +} + +[dir="rtl"] .rendered_html { + p { + text-align : right; + } +}