summaryrefslogtreecommitdiffstats
path: root/doc/_static
diff options
context:
space:
mode:
Diffstat (limited to 'doc/_static')
-rw-r--r--doc/_static/demo-worker.js74
-rw-r--r--doc/_static/demo.css89
-rw-r--r--doc/_static/demo.js200
-rw-r--r--doc/_static/favicon.icobin0 -> 16958 bytes
-rw-r--r--doc/_static/github.pngbin0 -> 1127 bytes
-rw-r--r--doc/_static/logo_new.pngbin0 -> 40944 bytes
-rw-r--r--doc/_static/logo_only.pngbin0 -> 16424 bytes
-rw-r--r--doc/_static/spinner.gifbin0 -> 10771 bytes
8 files changed, 363 insertions, 0 deletions
diff --git a/doc/_static/demo-worker.js b/doc/_static/demo-worker.js
new file mode 100644
index 0000000..22b8b3d
--- /dev/null
+++ b/doc/_static/demo-worker.js
@@ -0,0 +1,74 @@
+importScripts('/_static/pyodide/pyodide.js');
+
+async function loadPyodideAndPygments() {
+ self.pyodide = await loadPyodide();
+ await self.pyodide.loadPackage(["Pygments"]);
+ const styles = self.pyodide.runPython(`
+ from pygments.formatters.html import HtmlFormatter
+ from pygments.styles import STYLE_MAP
+ {s: HtmlFormatter(style=s).get_style_defs('.demo-highlight') for s in STYLE_MAP}
+ `).toJs();
+ self.postMessage({loaded: {styles}})
+}
+let pyodideReadyPromise = loadPyodideAndPygments();
+
+self.onmessage = async (event) => {
+ // Make sure loading is done.
+ await pyodideReadyPromise;
+ if (event.data.highlight) {
+ self.pyodide.globals.set('code', event.data.highlight.code);
+ self.pyodide.globals.set('lexer_name', event.data.highlight.lexer);
+
+ self.pyodide.runPython(`
+ import pygments.lexers
+
+ lexer = pygments.lexers.get_lexer_by_name(lexer_name)
+ if type(code) == memoryview:
+ code = bytes(code)
+ tokens = lexer.get_tokens(code)
+ `);
+
+ const formatter = event.data.highlight.formatter;
+ if (formatter == 'html') {
+
+ const html = self.pyodide.runPython(`
+ import io
+ from pygments.formatters.html import HtmlFormatter
+
+ fmter = HtmlFormatter(cssclass='demo-highlight')
+ buf = io.StringIO()
+ fmter.format(tokens, buf)
+ buf.getvalue()
+ `);
+ self.postMessage({html});
+ } else if (formatter == 'tokens') {
+ const tokens = self.pyodide.runPython('list(tokens)').toJs();
+ self.postMessage({tokens});
+ } else {
+ console.warn('unknown formatter:', formatter);
+ }
+ } else if (event.data.guess_lexer) {
+ self.pyodide.globals.set('code', event.data.guess_lexer.code);
+ self.pyodide.globals.set('filename', event.data.guess_lexer.filename);
+ const lexer = self.pyodide.runPython(`
+ import sys
+ sys.setrecursionlimit(1000)
+ # TODO: remove after upgrading to Pyodide 0.19
+
+ import pygments.lexers
+ import pygments.util
+
+ if type(code) == memoryview:
+ code = bytes(code)
+
+ if filename:
+ lexer = pygments.lexers.guess_lexer_for_filename(filename, code)
+ else:
+ lexer = pygments.lexers.guess_lexer(code)
+ lexer.aliases[0]
+ `);
+ self.postMessage({lexer});
+ } else {
+ console.warn('unknown command: expected highlight or guess_lexer but received ', event.data);
+ }
+}
diff --git a/doc/_static/demo.css b/doc/_static/demo.css
new file mode 100644
index 0000000..eaa4410
--- /dev/null
+++ b/doc/_static/demo.css
@@ -0,0 +1,89 @@
+#try {
+ background-color: #f6f6f6;
+ border-radius: 0;
+ border: 1px solid #ccc;
+ margin-top: 15px;
+ margin-bottom: 10px;
+ padding: 10px 15px 5px 10px;
+ position: relative;
+}
+
+#try h2 {
+ margin-top: 0;
+}
+
+#try textarea {
+ border: 1px solid #999;
+ padding: 2px;
+ width: 100%;
+ min-height: 150px;
+ resize: vertical;
+}
+
+#hlcode {
+ margin: 10px 0;
+ max-height: 500px;
+ overflow: auto;
+ border: 1px solid #ccc;
+}
+
+#hlcode:empty {
+ display: none;
+}
+
+#hlcode pre {
+ background-color: transparent;
+ border: 0;
+ margin: 0;
+}
+#hlcode table {
+ /* unset negative margin from pygments14.css */
+ margin: unset;
+}
+
+#code-header:not([hidden]) {
+ display: flex;
+ gap: 1em;
+ padding: 0 15px;
+}
+.flex-grow-1 {
+ flex-grow: 1;
+}
+#lexer {
+ margin-right: 0.5em;
+}
+#guessed-lexer:not(:empty):before {
+ content: '(guessed ';
+}
+#guessed-lexer:not(:empty):after {
+ content: ')';
+}
+
+#loading[hidden] {
+ visibility: hidden;
+ display: flex;
+}
+
+#loading {
+ display: flex;
+ align-items: center;
+ gap: 1em;
+}
+
+#format-settings {
+ display: flex;
+ gap: 1em;
+ border-top: 1px solid #ccc;
+ padding-top: 0.5em;
+ margin-top: 0.5em;
+}
+
+.tokens code {
+ /* make whitespace visible */
+ white-space: pre;
+ background: #d9d9d9;
+}
+
+#contrast-warning {
+ color: darkred;
+}
diff --git a/doc/_static/demo.js b/doc/_static/demo.js
new file mode 100644
index 0000000..b193d10
--- /dev/null
+++ b/doc/_static/demo.js
@@ -0,0 +1,200 @@
+const loadingDiv = document.getElementById("loading");
+const langSelect = document.getElementById("lang");
+const styleSelect = document.getElementById("style");
+const formatterSelect = document.getElementById("formatter");
+const outputDiv = document.getElementById("hlcode");
+const codeHeader = document.getElementById("code-header");
+const copyLink = document.getElementById("copylink");
+const style = document.getElementById("css-style");
+const textarea = document.getElementById("code");
+const uriTooLongMsg = document.getElementById('uri-too-long');
+const contrastWarning = document.getElementById('contrast-warning');
+const fileInput = document.getElementById("file");
+const fileInputResetButton = document.getElementById('reset-file');
+
+const qvars = Object.fromEntries(new URLSearchParams(window.location.search));
+if (qvars.lexer) {
+ langSelect.value = qvars.lexer;
+}
+if (qvars.code !== undefined) {
+ textarea.value = qvars.code;
+ loadingDiv.hidden = false;
+}
+if (qvars.style !== undefined) {
+ styleSelect.value = qvars.style;
+ updateContrastWarning();
+}
+if (qvars.formatter !== undefined) {
+ formatterSelect.value = qvars.formatter;
+}
+
+styleSelect.addEventListener('change', () => {
+ if (!styles)
+ // Worker has not loaded yet.
+ return;
+ style.textContent = styles.get(styleSelect.value);
+ updateCopyLink();
+ updateContrastWarning();
+});
+
+function updateContrastWarning() {
+ contrastWarning.hidden = styleSelect.selectedOptions[0].dataset.wcag == 'aa';
+}
+
+function debounce(func, timeout) {
+ let timer;
+ return (...args) => {
+ clearTimeout(timer);
+ timer = setTimeout(() => func.apply(this, args), timeout);
+ };
+}
+
+const highlightShortDebounce = debounce(highlight, 50);
+const highlightLongDebounce = debounce(highlight, 500);
+
+function debouncedUpdate() {
+ if (fileInput.files.length > 0)
+ return;
+
+ if (textarea.value.length < 1000) {
+ highlightShortDebounce();
+ } else {
+ highlightLongDebounce();
+ }
+}
+
+langSelect.addEventListener('change', debouncedUpdate);
+textarea.addEventListener('input', debouncedUpdate);
+formatterSelect.addEventListener('change', debouncedUpdate);
+fileInput.addEventListener('change', () => {
+ fileInputResetButton.hidden = false;
+ highlight();
+});
+fileInputResetButton.hidden = fileInput.files.length == 0;
+fileInputResetButton.addEventListener('click', () => {
+ fileInputResetButton.hidden = true;
+ fileInput.value = '';
+ highlight();
+});
+
+let styles;
+
+const highlightWorker = new Worker("/_static/demo-worker.js");
+highlightWorker.onmessage = (msg) => {
+ if (msg.data.loaded) {
+ styles = msg.data.loaded.styles;
+
+ if (qvars.code !== undefined || textarea.value) {
+ loadingDiv.hidden = true;
+ highlight();
+ }
+ } else if (msg.data.html) {
+ outputDiv.innerHTML = msg.data.html;
+ codeHeader.hidden = false;
+ loadingDiv.hidden = true;
+ style.textContent = styles.get(styleSelect.value);
+ } else if (msg.data.tokens) {
+ const table = document.createElement('table');
+ table.className = 'tokens';
+ for (const [tokenType, value] of msg.data.tokens) {
+ const tr = document.createElement('tr');
+ const td1 = document.createElement('td');
+ td1.textContent = tokenType.join('.');
+ const td2 = document.createElement('td');
+ const inlineCode = document.createElement('code');
+ inlineCode.textContent = value;
+ td2.appendChild(inlineCode);
+ tr.appendChild(td1);
+ tr.appendChild(td2);
+ table.appendChild(tr);
+ }
+ outputDiv.innerHTML = '';
+ outputDiv.appendChild(table);
+
+ codeHeader.hidden = false;
+ loadingDiv.hidden = true;
+ } else if (msg.data.lexer) {
+ highlight(msg.data.lexer);
+ } else {
+ console.warn('unexpected message from highlight worker', msg);
+ }
+};
+
+function updateCopyLink() {
+ var url = document.location.origin + document.location.pathname +
+ "?" + new URLSearchParams({
+ lexer: langSelect.value,
+ style: styleSelect.value,
+ formatter: formatterSelect.value,
+ code: textarea.value,
+ }).toString()
+ if (url.length > 8201) {
+ // pygments.org is hosted on GitHub pages which does not support URIs longer than 8201
+ copyLink.hidden = true;
+ uriTooLongMsg.hidden = false;
+ } else {
+ copyLink.href = url;
+ copyLink.textContent = 'Copy link';
+ copyLink.hidden = false;
+ uriTooLongMsg.hidden = true;
+ }
+}
+
+async function highlight(guessedLexer) {
+ var lexer = langSelect.value || guessedLexer;
+ var file = fileInput.files[0];
+
+ let code;
+ if (file) {
+ code = await file.arrayBuffer();
+ } else {
+ code = textarea.value;
+ }
+
+ loadingDiv.hidden = false;
+
+ if (!lexer) {
+ const guess_lexer = {code};
+ if (file)
+ guess_lexer.filename = file.name;
+ highlightWorker.postMessage({guess_lexer});
+ document.getElementById('loading-text').textContent = 'guessing lexer...';
+ return;
+ }
+
+ document.getElementById('loading-text').textContent = 'highlighting code...';
+
+ document.getElementById('guessed-lexer').textContent = guessedLexer;
+
+ highlightWorker.postMessage({highlight: {code, lexer, formatter: formatterSelect.value}});
+
+ if (code instanceof ArrayBuffer) {
+ copyLink.hidden = true;
+ uriTooLongMsg.hidden = true;
+ } else {
+ updateCopyLink();
+ }
+}
+
+copyLink.addEventListener('click', async (e) => {
+ e.preventDefault();
+ await navigator.clipboard.writeText(e.target.href);
+});
+
+function download_code() {
+ var filename = "highlighted.html";
+ var hlcode = document.getElementById("hlcode").innerHTML + style.outerHTML;
+ var blob = new Blob([hlcode], {type: 'text/html'});
+ if (window.navigator.msSaveOrOpenBlob) {
+ window.navigator.msSaveBlob(blob, filename);
+ }
+ else{
+ var elem = window.document.createElement('a');
+ elem.href = window.URL.createObjectURL(blob);
+ elem.download = filename;
+ document.body.appendChild(elem);
+ elem.click();
+ document.body.removeChild(elem);
+ window.URL.revokeObjectURL(elem.href);
+ }
+}
diff --git a/doc/_static/favicon.ico b/doc/_static/favicon.ico
new file mode 100644
index 0000000..777f617
--- /dev/null
+++ b/doc/_static/favicon.ico
Binary files differ
diff --git a/doc/_static/github.png b/doc/_static/github.png
new file mode 100644
index 0000000..5d146ad
--- /dev/null
+++ b/doc/_static/github.png
Binary files differ
diff --git a/doc/_static/logo_new.png b/doc/_static/logo_new.png
new file mode 100644
index 0000000..0ae4b20
--- /dev/null
+++ b/doc/_static/logo_new.png
Binary files differ
diff --git a/doc/_static/logo_only.png b/doc/_static/logo_only.png
new file mode 100644
index 0000000..fdebcc4
--- /dev/null
+++ b/doc/_static/logo_only.png
Binary files differ
diff --git a/doc/_static/spinner.gif b/doc/_static/spinner.gif
new file mode 100644
index 0000000..2212db9
--- /dev/null
+++ b/doc/_static/spinner.gif
Binary files differ