gzuidhof / starboard-notebook

In-browser literate notebooks
Mozilla Public License 2.0
1.22k stars 97 forks source link

Standalone HTML document #38

Closed ghost closed 3 years ago

ghost commented 3 years ago

Starboard Notebook looks like a very exciting project!

Are there any plans to create completely independent stand-alone HTML notebook files? I've played with starboard-cli, but I'm looking to create completely portable stand-alone reports, with bring-your-own data functionality.

e.g. perhaps an "Export as HTML" button would download a stand-alone HTML file which could be emailed to other people. Perhaps a subcommand could be added to starboard-cli? Something like starboard build.

I'm imagining a situation where different people have a CSV file on their computer. I would create a report using Starboard, and send it without the data. Then, a user could open the Starboard file in their browser, and click a button to load in their local CSV file, and it would automatically generate the report.

At the moment I'm doing this using R Markdown and Shiny, but it's not particularly convenient to create a portable stand-alone R Shiny app.

Is this sort of thing in scope for Starboard?

unhott commented 3 years ago

That's a neat idea!

For an immediate solution, check this out: https://starboard.gg/gz/loading-csv-nuvwkqs :)

gzuidhof commented 3 years ago

Hi David,

Definitely it's possible :), let me understand it a bit better: would your end users have access to the internet? If so it's pretty trivial :). Here is the notebook that unhott linked as a standalone file (try view source).

For relability and future proofing probably you should use jsdelivr as the CDN so you don't depend on me paying my server bills, so it would become:

<!doctype html>
<html>
    <head>
        <meta charset="utf-8">
        <title>My Notebook Title</title>
        <meta name="viewport" content="width=device-width,initial-scale=1">
        <link rel="icon" href="https://cdn.jsdelivr.net/npm/starboard-notebook@0.10.1/dist/favicon.ico">
        <link href="https://cdn.jsdelivr.net/npm/starboard-notebook@0.10.1/dist/starboard-notebook.css" rel="stylesheet">
    </head>
    <body>
        <script>
            window.initialNotebookContent = `# %% [md]\n# Loading a CSV file using a file input\n\nThis notebook shows how to load CSV file using a file input. After that we load it into Pandas.\n# %% [js]\nasync function onFileSelection(event) {\n  const textContent = await event.target.files[0].text()\n  window.csvContent = textContent;\n}\n\nhtml\`<input @change=\${onFileSelection} type="file" id="file-input" name="file-input" accept=".csv, .txt">\`\n# %% [js]\nif (window.csvContent === undefined) {\n  console.error("Select a file first!")\n  return;\n}\n\nconsole.log(window.csvContent.split("\\n")[0]) // Print the first line\nconsole.log(window.csvContent.split("\\n")[1]) // Print the second line\n# %% [py]\nfrom js import csvContent\nimport pandas as pd\nimport io\n\ndf = pd.read_csv(io.StringIO(csvContent))\ndf\n# %% [py]\n\n# %% [markdown]\n`;
            window.starboardArtifactsUrl = `https://cdn.jsdelivr.net/npm/starboard-notebook@0.10.1/dist/`;
        </script>
        <script src="https://cdn.jsdelivr.net/npm/starboard-notebook@0.10.1/dist/starboard-notebook.js"></script>
    </body>
</html>

We could maybe add a download standalone HTML file export button into the notebook itself that just generates the file above and downloads it to your machine. You could just do it for any notebook you see on the internet then.

The string value for the notebook is generated using the jsesc NPM package with these options:

const escapedNb = jsesc(notebookContentString, {quotes: "backtick", minimal: true, es6: true, isScriptContext: true});
ghost commented 3 years ago

Thanks @gzuidhof, that's amazing! The linked standalone file couldn't load the javascript file when I ran it from my computer (Loading failed for the <script> with source “https://cdn.starboard.host/0.10.0/starboard-notebook.js”.), but the jsdeliver version worked perfectly.

How hard would it be to embed the remote content directly in the HTML file with Data URLs?

gzuidhof commented 3 years ago

Ah yeah, I think the cdn.starboard.host is setup to only accept a few origins (starboard.gg, starboard.host).

Instead of embedding the remote content, you would need to instead bake the entire project into a single JS file and embed that in a <script> tag. Any other dependencies (e.g. fonts for displaying math) will have to be embedded some other way, for instance using data URLS..

Maybe there is some sort of crazy webpack config you can write to bundle it all into one file (which would be larger than 13MB). By stripping out Monaco you can probably remove around half of that, but that's still kind of crazy and it would quite some effort - I'm not sure for what gain!

To keep everything within your secure network you could (1) host the files on an internal webserver (at that point you may as well put your notebook HTML files there too) or (2) ship them a zip with the files and have them use their favorite webserver to view it on localhost.

ghost commented 3 years ago

Thanks @gzuidhof, perhaps I'm on the wrong track here! Let's assume for now that the jsdeliver version is good enough, and I'll open another issue if I have a more concrete use case for the "Run it on a desert island" version.