Last active
August 4, 2023 01:46
-
-
Save rhee-elten/b4c1b3c9892500a0c2e0884f11965e1d to your computer and use it in GitHub Desktop.
[WIP] gitea renderer - jupyter notebook using nb.js (TBD frame security check workaround) /////////////////////////////
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
mkdir -p "${GITEA_CUSTOM}/tmp/render-notebook" | |
exec 2>> "${GITEA_CUSTOM}/tmp/render-notebook/trace.txt" | |
## DEBUG: echo params & envs | |
## PARAMS: | |
echo "=== Script: $(dirname $0)" 1>&2 | |
echo "=== Date: $(date +'%Y-%m-%d %H:%M:%S')" 1>&2 | |
echo "=== Args:" "$@" 1>&2 | |
echo "=== Env:" 1>&2 | |
env 1>&2 | |
t_start=$(date +%s) | |
notebook_url="data:text/html;base64,$(/bin/base64 -w 0 -)" | |
t_elapsed=$(expr $(date +%s) - $t_start) | |
echo "Encoded bytes: ${#notebook_url}, elapsed: ${t_elapsed} seconds" 1>&2 | |
## ========================================================= | |
## README | |
## ========================================================= | |
<<EEE | |
[[custom modifications required]] | |
config/app.ini: | |
=============== | |
[cors] | |
# ENABLED: false: enable cors headers (disabled by default) | |
# SCHEME: http: scheme of allowed requests | |
# ALLOW_DOMAIN: *: list of requesting domains that are allowed | |
# ALLOW_SUBDOMAIN: false: allow subdomains of headers listed above to request | |
# METHODS: GET,HEAD,POST,PUT,PATCH,DELETE,OPTIONS: list of methods allowed to request | |
# MAX_AGE: 10m: max time to cache response | |
# ALLOW_CREDENTIALS: false: allow request with credentials | |
# HEADERS: Content-Type,User-Agent: additional headers that are permitted in requests | |
# X_FRAME_OPTIONS: SAMEORIGIN: Set the X-Frame-Options header value. | |
ENABLED = true | |
ALLOW_DOMAIN = * | |
ALLOW_CREDENTIALS = true | |
# [markup.jupyter] | |
# ENABLED = true | |
# FILE_EXTENSIONS = .ipynb | |
# RENDER_COMMAND = "jupyter nbconvert --stdin --stdout --to html --template basic" | |
# IS_INPUT_FILE = false | |
[markup.jupyter] | |
ENABLED = true | |
FILE_EXTENSIONS = .ipynb | |
RENDER_COMMAND = "/data/gitea/public/app/render-notebook/script/render-notebook" | |
IS_INPUT_FILE = false | |
RENDER_CONTENT_MODE = iframe | |
[markup.sanitizer.jupyter.img] | |
ALLOW_DATA_URI_IMAGES = true | |
custom/header.tmpl: | |
=================== | |
<!-- | |
<style type="text/css"> | |
.markup.jupyter iframe { | |
height:900px!important; | |
overflow:scroll!important; | |
} | |
</style> | |
--> | |
custom/footer.tmpl: | |
=================== | |
<!-- | |
<script> | |
(function(){ | |
const iframe = document.getElementsByName("giteaExternalRender")[0]; | |
const src = iframe.src; | |
iframe.sandbox.add("allow-scripts") | |
iframe.sandbox.add("allow-same-origin") | |
//iframe.setAttribute("src","about:blank") | |
iframe.contentWindow.addEventListener("load",function(){ | |
this.height=giteaExternalRender.document.documentElement.scrollHeight | |
}) | |
iframe.setAttribute("src",src) | |
})() | |
</script> | |
--> | |
<script> | |
// Function to resize the iframe based on the received height message | |
function resizeIframe(event) { | |
const iframe = document.querySelector("div.markup.jupyter iframe"); | |
if (iframe) { | |
iframe.style.height = event.data + "px"; | |
} | |
} | |
// Listen for the 'message' event and call resizeIframe function | |
window.addEventListener("message", resizeIframe); | |
</script> | |
base/head.tmpl | |
============== | |
head.tmpl 에서 referrer 에 no-referrer 대신 same-origin 이나 strict-origin-when-cross-origin 추가 고려: | |
<meta name="referrer" content="no-referrer"> <!-- content="strict-origin-when-cross-origin"> --> | |
renderer.go (?) | |
=============== | |
<iframe ... onload="this.height=haha.document.documentElement.scrollHeight" sandbox="allow-scripts"> | |
처럼 onload 와 sandbox=allow-scripts 를 함께 사용시 onload 에서 cross-origin frame 예외 발생 | |
gitea cheatsheet 중에서 다음 문장 검토 | |
RENDER_CONTENT_MODE: sanitized How the content will be rendered. | |
* sanitized: Sanitize the content and render it inside current page, | |
default to only allow a few HTML tags and attributes. Customized | |
sanitizer rules can be defined in [markup.sanitizer.*]. | |
* no-sanitizer: Disable the sanitizer and render the content inside | |
current page. It's insecure and may lead to XSS attack if the | |
content contains malicious code. | |
* iframe: Render the content in a separate standalone page and | |
embed it into current page by iframe. | |
***The iframe is in sandbox mode with same-origin disabled, | |
and the JS code are safely isolated from parent page.*** | |
==> sandbox="allow-scripts allow-same-origin" 으로 수정 필요 | |
EEE | |
## ========================================================= | |
## HTML template | |
## ========================================================= | |
cat <<EEE | |
<!-- <h1>BEGIN Rendered Notebook</h1> --> | |
<div id="nbjs-nb-$$"> | |
<!--Inserts Notebook HTML here--> | |
</div> | |
<!-- <script src="/assets/js/nb.js"></script> --> | |
<!-- <script src="http://192.168.1.146:3000/assets/js/nb.js"></script> --> | |
<script src="https://cdn.jsdelivr.net/gh/psthomas/notebook-html/nb.min.js"></script> | |
<!--highlight.js--> | |
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@9.12.0/build/styles/default.min.css"> | |
<script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@9.12.0/build/highlight.min.js"></script> | |
<!--showdown.js--> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/showdown/1.8.6/showdown.min.js"></script> | |
<script> | |
const url="$notebook_url"; | |
const id="user-content-nbjs-nb-$$"; | |
//Create converter object and modify some settings | |
const converter = new showdown.Converter(); | |
converter.setOption('headerLevelStart', 2); //Maximum header is <h2> | |
converter.setFlavor('github'); //Use Github flavored markdown | |
nb.insertNotebook(url, id, { | |
"code": true, //Include code cells | |
"markdown": true, //Include markdown cells | |
"tables": true, //Include html data tables | |
"images": true, //Include .png outputs | |
"headline": false, //Include the first <h*> headline, removing is useful if page has title already | |
"tableoutline": false, //Removes the black table outline | |
"codehighlighter": "highlightjs", //No code highlighting. Options: "none", "highlightjs", "prettyprint" | |
"mdconverter": converter //Use included simple markdown converter. Options: "default", showdown object | |
}); | |
// Wait for the iframe content to load and then send the height to the parent page | |
window.addEventListener("load", function(){ | |
const height = document.body.scrollHeight; | |
parent.postMessage(height, "*"); | |
}); | |
</script> | |
<!-- <h1>END Rendered Notebook</h1> --> | |
EEE | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment