Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

User-defined RequireJS deps #1247

Open
mortenpi opened this issue Feb 27, 2020 · 14 comments
Open

User-defined RequireJS deps #1247

mortenpi opened this issue Feb 27, 2020 · 14 comments
Labels
Format: HTML Related to the default HTML output Type: Enhancement

Comments

@mortenpi
Copy link
Member

Documenter's generated HTML output uses RequireJS to load JS deps mostly. #1092 generalized the internals so that the RequireJS initialization code in documenter.js gets generated dynamically on each build. The next step is to allow the users to add their own libraries and snippets too.

Note: as a workaround, you may be able to include a library/script with independently of RequireJS with assets. But this does not always work, as the module loading can clash (also happens with Plotly).

Potential implementation:

  • Add a way to for the user to pass additional deps/snippets to the JS in here:
    r = JSDependencies.RequireJS([
    RD.jquery, RD.jqueryui, RD.headroom, RD.headroom_jquery,
    ])
    RD.mathengine!(r, settings.mathengine)
    RD.highlightjs!(r, settings.highlights)
    for filename in readdir(joinpath(ASSETS, "js"))
    path = joinpath(ASSETS, "js", filename)
    endswith(filename, ".js") && isfile(path) || continue
    push!(r, JSDependencies.parse_snippet(path))
    end
    JSDependencies.verify(r; verbose=true) || error("RequireJS declaration is invalid")
    JSDependencies.writejs(joinpath(doc.user.build, "assets", "documenter.js"), r)
  • To pass the configuration, one could re-use the HTML's assets keyword. Any RemoteLibrary and Snippet objects (from JSDependencies) could be filtered out based on their type and looped over during the construction of the RequireJS object.
@mortenpi mortenpi added Type: Enhancement Format: HTML Related to the default HTML output labels Feb 27, 2020
@jebej
Copy link
Contributor

jebej commented Oct 4, 2020

Is requirejs a hard dependency?

I think (from my googling around) that it makes it hard(er)to include plotlyjs plots in documentation. Without requirejs a simple raw HTML block like this:

"""
    <div id="$(p.divid)" style="width:100%;height:500px;"></div>
    <script>
      var plot_json = $(json(p));
      Plotly.newPlot("$(p.divid)", plot_json.data, plot_json.layout, {responsive: true});
    </script>
"""

would just work (tm), but currently I'm getting "Plotly not defined errors".

I think that even with the API in this issue implemented it would still be pretty complicated (based on me not being able to figure out how to make it work by tweaking files manually).

Note that this is a sort-of follow up to #1424, where you helped me include the raw HTML in the page, which worked.

@mortenpi
Copy link
Member Author

mortenpi commented Oct 4, 2020

It's not a hard requirement -- you can always drop <script> tags into <head> (with asset).

If you want to do it with RequireJS and use it that way, I think you have to somehow make sure that you have the Plotly object in the global scope. I am not entirely sure what you'd need to call, but it should be doable in the require callback. You'd also have to make sure that the <script> elements that plot things don't run before RequireJS has initialized everything (I think RequireJS runs asynchronously, so might become an issue).

@jebej
Copy link
Contributor

jebej commented Oct 5, 2020

It's not a hard requirement -- you can always drop <script> tags into <head> (with asset).

Yes, that's what I did, but I got the "not defined" error. Unfortunately I don't know enough about JS to figure out how to handle requirejs properly.

What I meant was: is requirejs a hard requirement for Documenter?

@mortenpi
Copy link
Member Author

mortenpi commented Oct 5, 2020

When you're using asset, you should be bypassing RequireJS altogether. I haven't tried to include Plotly in a site though, so I don't really know what's going wrong. Best I could suggest is to see if you can get it to work in a simple hand-written HTML file and then figure out what's different about Documenter.

What I meant was: is requirejs a hard requirement for Documenter?

I am not sure I quite understand the question. If you mean whether we could drop RequireJS from Documenter completely, then technically, sure, that would be doable. At the time when I implemented it, I was hoping it would help simplify the handling of JS dependencies. It has its pros, but it also complicates things sometimes.

@jebej
Copy link
Contributor

jebej commented Oct 6, 2020

The plot does work with a simple html example, and it works in Franklin as well. As a test I also (just now) removed the requirejs script header tag and it did load the plot correctly.

I am not sure I quite understand the question. If you mean whether we could drop RequireJS from Documenter completely, then technically, sure, that would be doable.

Yes, that is what I meant. Obviously I understand that it would be work. I can't really weigh the pros and cons myself but I suppose the above is a data point.

@mortenpi
Copy link
Member Author

mortenpi commented Oct 6, 2020

Could you post the simple HTML example here?

@jebej
Copy link
Contributor

jebej commented Oct 6, 2020

Sure, this is pretty much the simplest you can get:

<html>
<head>
  <script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
</head>
<body>
  <div id="7979e646-13e6-4f44-8d32-d8effc3816df" style="height: 500; width: 100%;"></div>
  <script>
    Plotly.newPlot("7979e646-13e6-4f44-8d32-d8effc3816df", [{"x": [1, 2, 3], "y": [3, 1, 6]}], {},)
  </script>
</body>
</html>

@jebej
Copy link
Contributor

jebej commented Oct 6, 2020

As I'm sure you'll be testing, adding requirejs does breaks the example, though only if it is added before plotly. This might be a stopgap solution.

@mortenpi
Copy link
Member Author

mortenpi commented Oct 6, 2020

Following this SO answer, it is possible to get Plotly working if you load it via RequireJS. I.e. something like this will work:

require(['plotly'], function(plotly) {
  console.log(plotly); // Object {Lib: Object, util: Object...}
  plotly.newPlot("7979e646-13e6-4f44-8d32-d8effc3816df", [{"x": [1, 2, 3], "y": [3, 1, 6]}], {},)
});

(It does not look like there is any actual need to load D3 or jQuery as deps as the SO answer suggests.. I guess Plotly maybe bundles them nowadays?)

However, as far as I can tell, this does mean that all the plotting code would have to be in the require call. That is, you can't use <script> tags for the plotting, which I assume is how you would like to use Plotly with Documenter.

I did find an old issue that looks related requirejs/requirejs#947. Essentially it looks like the only thing we could do is load Plotly with a <script> tag before we load RequireJS. I am thinking we could introduce a location keyword argument to asset that would allow the location of the <script> tag to be customized.

@jebej
Copy link
Contributor

jebej commented Oct 7, 2020

Essentially it looks like the only thing we could do is load Plotly with a <script> tag before we load RequireJS.

Yes.

I am thinking we could introduce a location keyword argument to asset that would allow the location of the <script> tag to be customized.

Why not simply put all the user dependencies before requirejs? It seems like if they are loaded after there's a chance they wouldn't work anyway.

@mortenpi
Copy link
Member Author

mortenpi commented Oct 8, 2020

Why not simply put all the user dependencies before requirejs? It seems like if they are loaded after there's a chance they wouldn't work anyway.

It may well be the better default, I don't actually have a strong opinion. But since you can have these weird interactions between the libraries, it can be that there are scripts that have issues if they are before RequireJS. Ultimately, allowing the user to control this might be good.

Also, if it's customizable, we could also allow putting scripts at the very end of the HTML file, which can avoid issues with the page not loading if the script is not accessible for some reason or takes a long time to load.

@mortenpi
Copy link
Member Author

mortenpi commented Oct 8, 2020

I opened a dedicated issue about the location of the <script> tags, since that is actually orthogonal to the original issue here (user-defined RequireJS dependencies): #1433.

@MikaelSlevinsky
Copy link

Hey I'd like to use Literate.jl to generate markdown for Documenter.jl for documentation of a package, and I'd like it to use HTML to represent PlotlyJS.jl plots. (See the linked issue just above.)

Currently, the default savefig saves PlotlyJS plots as PNG, which is quite a bit lighter than the HTML but far worse quality in my opinion and strips the interactivity. Could this be something to look forward to?

@fredrikekre
Copy link
Member

See fredrikekre/Literate.jl#126 (comment) for a way to include PlotlyJS plots.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Format: HTML Related to the default HTML output Type: Enhancement
Projects
None yet
Development

No branches or pull requests

4 participants