quarto-ext / shinylive

Quarto extension to embed Shinylive for Python applications
https://quarto-ext.github.io/shinylive/
MIT License
141 stars 7 forks source link

Use shinylive in a quarto html document rather than a website #10

Open harrylojames opened 1 year ago

harrylojames commented 1 year ago

Hi,

I would like to able to send a single html file document which contains a shinylive component. Is this possible?

If so, what would I need to do? If not, are there plans to make it possible?

If the project type is not a website I get the following error

"ERROR: The shinylive extension must be used in a Quarto project directory (with a _quarto.yml file)."

Many thanks!

wch commented 1 year ago

I'm not sure if this is possible, unless there are some changes in quarto.

The message comes from here:

https://github.com/quarto-ext/shinylive/blob/4af0a720e22e02bd15159a51d411f7b8eb7307fc/_extensions/quarto-ext/shinylive/shinylive.lua#L50-L57

When I modify that code so that it calls shinylive with --sw-dir ., this is the relevant part of the HTML dependency that's generated:

  {
    "name": "shinylive-serviceworker",
    "version": "0.1.2",
    "serviceworkers": [
      {
        "source": "/Users/winston/Library/Caches/shinylive/shinylive-0.1.2/shinylive-sw.js",
        "destination": "/shinylive-sw.js"
      }
    ],
    "meta": {
      "shinylive:serviceworker_dir": "."
    }
  },

And then when I run quarto render index.qmd, this is the error I get:

ERROR: A service worker is being provided with a project relative destination path but no valid Quarto project was found.

Error: A service worker is being provided with a project relative destination path but no valid Quarto project was found.
    at resolveDestination (file:///Users/winston/nobackup/quarto-cli/src/command/render/pandoc-dependencies-html.ts:298:21)
    at file:///Users/winston/nobackup/quarto-cli/src/command/render/pandoc-dependencies-html.ts:309:33
    at Array.forEach (<anonymous>)
    at processHtmlDependencies (file:///Users/winston/nobackup/quarto-cli/src/command/render/pandoc-dependencies-html.ts:274:33)
    at readAndInjectDependencies (file:///Users/winston/nobackup/quarto-cli/src/command/render/pandoc-dependencies-html.ts:80:22)
    at file:///Users/winston/nobackup/quarto-cli/src/command/render/pandoc.ts:1091:17
    at withTiming (file:///Users/winston/nobackup/quarto-cli/src/core/timing.ts:37:20)
    at htmlDependenciesPostProcesor (file:///Users/winston/nobackup/quarto-cli/src/command/render/pandoc.ts:1088:14)
    at file:///Users/winston/nobackup/quarto-cli/src/command/render/render.ts:392:30
    at async withTimingAsync (file:///Users/winston/nobackup/quarto-cli/src/core/timing.ts:50:20)

I also tried modifying it so that the shinylive:serviceworker_dir is an absolute path, but it still gives the same error.

@cscheid Would it be possible to make this extension work without a _quarto.yml file?

cscheid commented 1 year ago

@wch Here's the relevant source code:

          if (worker.destination.startsWith("/")) {
            if (project) {
              // This is a project relative path
              const projectDir = projectOutputDir(project);
              return join(projectDir, worker.destination.slice(1));
            } else {
              throw new Error(
                "A service worker is being provided with a project relative destination path but no valid Quarto project was found.",
              );
            }
          } else {
            // this is an input relative path
            return join(inputDir, worker.destination);
          }

The problem here is you have destination: "/shinylive-sw.js" in that generated dependency. In quarto parlance, that's a "project relative" path. But outside of projects, we don't allow those paths, because they become absolute paths and that is 100% not what you want.

That dependency, instead, needs to declare something like destination: "shinylive-sw.js" instead (or some other relative path). That's what we need to figure out.

kkmann commented 10 months ago

Would love to be able to do that as well :) This is like apptainer/singularity for shiny