fasthtml
fasthtml copied to clipboard
[BUG] ScriptableJS() requires presence of Script(type='module')
Describe the bug SortableJS() requires presence of Script(type='module')
Minimal Reproducible Example
External scripts can be included through the fast_html()
wrapper, like so:
app, rt = fast_app(
hdrs=(SortableJS())
)
...but this results in:
<!doctype html>
<html>
<head>
<title>Botifython / Another / Home </title> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
<script src="https://unpkg.com/htmx.org@next/dist/htmx.min.js"></script><script src="https://cdn.jsdelivr.net/gh/answerdotai/[email protected]/fasthtml.js"></script><script src="https://unpkg.com/htmx-ext-ws/ws.js"></script><script src="https://cdn.jsdelivr.net/gh/answerdotai/surreal@main/surreal.js"></script><script src="https://cdn.jsdelivr.net/gh/gnat/css-scope-inline@main/script.js"></script> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@picocss/pico@latest/css/pico.min.css">
<style>:root { --pico-font-size: 100%; }</style>
import {Sortable} from 'https://cdn.jsdelivr.net/npm/sortablejs/+esm';
proc_htmx('.sortable', Sortable.create);
<script>
(function() {
var socket = new WebSocket(`ws://${window.location.host}/live-reload`);
var maxReloadAttempts = 1;
var reloadInterval = 1000; // time between reload attempts in ms
socket.onclose = function() {
let reloadAttempts = 0;
const intervalFn = setInterval(function(){
window.location.reload();
reloadAttempts++;
if (reloadAttempts === maxReloadAttempts) clearInterval(intervalFn);
}, reloadInterval);
}
})();
</script> </head><!-- ... -->
...which if you look close you will see that the JavaScript import is not
wrapped in a <script type="module">
tag resulting in <head>
-leakage. In
experimenting, I find that this will fix it:
app, rt = fast_app(
hdrs=(SortableJS(), Script(type="module"))
)
...because even though it ends up with an empty script module tag, it also wraps the SortableJS one properly:
<!doctype html>
<html>
<head>
<title>Botifython / Another / Home </title> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
<script src="https://unpkg.com/htmx.org@next/dist/htmx.min.js"></script><script src="https://cdn.jsdelivr.net/gh/answerdotai/[email protected]/fasthtml.js"></script><script src="https://unpkg.com/htmx-ext-ws/ws.js"></script><script src="https://cdn.jsdelivr.net/gh/answerdotai/surreal@main/surreal.js"></script><script src="https://cdn.jsdelivr.net/gh/gnat/css-scope-inline@main/script.js"></script> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@picocss/pico@latest/css/pico.min.css">
<style>:root { --pico-font-size: 100%; }</style>
<script type="module">
import {Sortable} from 'https://cdn.jsdelivr.net/npm/sortablejs/+esm';
proc_htmx('.sortable', Sortable.create);
</script><script type="module"></script><script>
(function() {
var socket = new WebSocket(`ws://${window.location.host}/live-reload`);
var maxReloadAttempts = 1;
var reloadInterval = 1000; // time between reload attempts in ms
socket.onclose = function() {
let reloadAttempts = 0;
const intervalFn = setInterval(function(){
window.location.reload();
reloadAttempts++;
if (reloadAttempts === maxReloadAttempts) clearInterval(intervalFn);
}, reloadInterval);
}
})();
</script> </head><!-- ... -->
It's a hack.
Expected behavior
app, rt = fast_app(
hdrs=(SortableJS())
)
...should result in:
<script type="module">
import {Sortable} from 'https://cdn.jsdelivr.net/npm/sortablejs/+esm';
proc_htmx('.sortable', Sortable.create);
</script>
Environment Information
- fasthtml version: 0.6.9
Confirmation Please confirm the following:
- [✅] I have read the FAQ (https://docs.fastht.ml/explains/faq.html)
- [👨🎨] I have provided a minimal reproducible example
- [💯] I have included the versions of fastlite, fastcore, and fasthtml
- [🔥] I understand that this is a volunteer open source project with no commercial support.