fasthtml icon indicating copy to clipboard operation
fasthtml copied to clipboard

[BUG] ScriptableJS() requires presence of Script(type='module')

Open miklevin opened this issue 4 months ago • 0 comments

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.

miklevin avatar Oct 09 '24 20:10 miklevin