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

reveal-hugo not working offline #168

Open
FilouPlains opened this issue Oct 17, 2024 · 9 comments
Open

reveal-hugo not working offline #168

FilouPlains opened this issue Oct 17, 2024 · 9 comments

Comments

@FilouPlains
Copy link

reveal-hugo not working offline

Hi !

First, thanks for this extension, it helps to make presentation way easier! I was trying to make a presentation 100% offline. You never know if the Wi-Fi connection will be there during a presentation… But it is not working.

The error

ERROR 2024/10/17 16:11:48 render of "section" failed: "/home/rouaud/Documents/
reveal_hugo_tutorial/themes/reveal-hugo/layouts/_default/baseof.reveal.html:44
:8": execute of template failed: template: _default/list.reveal.html:44:8:
executing "_default/list.reveal.html" at <partial "layout/javascript" .>: error
calling partial: "/home/rouaud/Documents/reveal_hugo_tutorial/themes/reveal-
hugo/layouts/partials/layout/javascript.html:109:76": execute of template
failed: template: partials/layout/javascript.html:109:76: executing "partials/
layout/javascript.html" at <$mathjaxSrc.RelPermalink>: error calling
RelPermalink: error calling resources.GetRemote: Get "https://cdn.jsdelivr.net/
npm/mathjax@3/es5/tex-svg.js": dial tcp: lookup cdn.jsdelivr.net on 127.0.0.53:
53: server misbehaving

It cannot load MathJax (and same for Mermaid).

Investigation

I think it comes from there for Mermaid:

{{ $mermaidSrc := resources.GetRemote "https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js" }}

and from here for MathJax:

{{ $mathjaxSrc := resources.GetRemote "https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js" }}

Solution?

I do not know if that me who has done something wrong. But, a workarround that I see should be to simply let the user give the path to Mermaid and MathJax JS. Like that, I would be abble to point to a JS in static/ directory! Like I am doing for Mol* or Plotly integration for instance.

@joshed-io
Copy link
Owner

@FilouPlains Thanks for opening the issue and glad you're getting use from the project 🙏🏻 It looks like when those features were added there wasn't a way to fallback to a local version or at least to not make the remote call and fail. I will check on it. For now you may have to comment those lines out locally or in a fork and load the files you need statically instead. I'll keep you posted.

@FilouPlains
Copy link
Author

FilouPlains commented Oct 24, 2024

@joshed-io

Just to maintain you updated, I have made a fork of your project: https://github.com/FilouPlains/reveal-hugo/blob/master/layouts/partials/layout/javascript.html

Additions

In the file that I ping you, I added:

{{- $mermaid_location := $.Param "reveal_hugo.mermaid_cdn" | default "__fetch_cdn__" -}} 

{{ if eq $mermaid_location "__fetch_cdn__"  }}
  {{ $mermaid_location := resources.GetRemote "https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js" }}
  <script type="text/javascript" src="{{ $mermaid_location.RelPermalink }}"></script>
{{ else }}
  <script type="text/javascript" src="{{ $mermaid_location }}"></script>
{{ end  }}

And:

{{- $mathjax_location := $.Param "reveal_hugo.mathjax_cdn" | default "__fetch_cdn__" -}} 

{{ if eq $mathjax_location "__fetch_cdn__"  }}
  {{ $mathjax_location := resources.GetRemote "https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js" }}
  <script type="text/javascript" id="MathJax-script" async src="{{ $mathjax_location.RelPermalink }}"></script>
{{ else }}
  <script type="text/javascript" id="MathJax-script" async src="{{ $mathjax_location }}"></script>
{{ end  }}

What it does

You can add in the hugo.toml the next parameters:

[params.reveal_hugo]
mermaid_cdn = "path"
mathjax_cdn = "path

In order to point to the path you want to! Note that I did not test it fully offline. I am very new to hugo, so the syntax might not be that good, but I do hope you understand the idea behind what I tried to add.

Have a lovely day and I keep you in touch if the addition work or not fully offline!

@joshed-io
Copy link
Owner

@FilouPlains Great work 🙏🏻 I'll be happy to accept a PR and merge this in once you've been able to test it out. We can ping some other developers active on the repo like @davidovich or @jerdog and perhaps they'd be kind enough to review the syntax & changes.

@jerdog
Copy link
Contributor

jerdog commented Oct 31, 2024

@FilouPlains - So my initial thoughts (and I have not tested this yet, but it's the first thing that comes to mind)... is that you set identify a default of __fetch_cdn__ in the $mermaid_location but you call it __fetch_mermaid_cdn__ following...

{{- $mermaid_location := $.Param "reveal_hugo.mermaid_cdn" | default "__fetch_cdn__" -}} 

{{ if eq $mermaid_location "__fetch_mermaid_cdn__"  }}

but you use __fetch_cdn__ for $mathjax_location as well.

{{- $mathjax_location := $.Param "reveal_hugo.mathjax_cdn" | default "__fetch_cdn__" -}} 

{{ if eq $mathjax_location "__fetch_cdn__"  }}

I suggest using __fetch_mermaid_cdn__ for Mermaid, and __fetch_mathjax_cdn__ for Mathjax so it's clear.

Let us know when you've tested locally.

@FilouPlains
Copy link
Author

Hi,

Sorry for answering that late. Some student exam to grade… 💀

Some precision and correction

So @jerdog, here is the “pseudocode“ of what I am doing (surely badly), for the case of mermaid:

Assign to $mermaid_location whether:
    if reveal_hugo.mermaid_cdn parameter is set:
        reveal_hugo.mermaid_cdn parameter value 
    else:
         "__fetch_cdn__" string

if $mermaid_location is equal to the string "__fetch_cdn__":
    Assign to $mermaid_location "https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js" after fetching online ressources
    Set a HTML JS tag with src pointing to the fetched ressources in $mermaid_location after redefining the path
else:
    Set a HTML JS tag with src pointing to $mermaid_location

I correct it on my previous post, sorry for the typo. But:

{{ if eq $mermaid_location "__fetch_mermaid_cdn__"  }}

Is wrong and should be:

{{ if eq $mermaid_location "__fetch_cdn__"  }}

The code works the same in the case of mermaid and MathJax. Sorry for the confusion. But, if I use __fetch_cdn__ in both case, it is because it is a string stock in two different variables. Hope it is more clear.

For the test

I should be able to make my test today or tomorrow. I ping you ASAP ;) ! Furthermore, I will make a pull request after that.

@jerdog
Copy link
Contributor

jerdog commented Nov 1, 2024

Thanks for the clarification. Look forward to reviewing and testing out!

@FilouPlains
Copy link
Author

Hi,

The famous #ping I were talking about… I made some test, but half was inconclusive…

MathJax: good

In the file layouts/partials/layout/javascript.html I change this:

{{ if $hasMath }}
<script>
  MathJax = {
    tex: {
      inlineMath: [['$', '$'], ['\\(', '\\)']]
    },
    svg: {
      fontCache: 'global'
    }
  };
</script>
  
{{ $mathjaxSrc := resources.GetRemote "https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js" }}
<script type="text/javascript" id="MathJax-script" async src="{{ $mathjaxSrc.RelPermalink }}"></script>
{{ end }}

Into that:

{{ if $hasMath }}
<script>
  MathJax = {
    tex: {
      inlineMath: [['$', '$'], ['\\(', '\\)']]
    },
    svg: {
      fontCache: 'global'
    }
  };
</script>

  {{- $mathjax_location := $.Param "reveal_hugo.mathjax_cdn" | default "__fetch_cdn__" -}} 

  {{ if eq $mathjax_location "__fetch_cdn__"  }}
    {{ $mathjax_location := resources.GetRemote "https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js" }}
    <script type="text/javascript" id="MathJax-script" async src="{{ $mathjax_location.RelPermalink }}"></script>
  {{ else }}
    <script type="text/javascript" id="MathJax-script" async src="{{ $mathjax_location }}"></script>
  {{ end  }}
{{ end }}

My offline test for this part work well! I add in a project the text-svg.js file in the static/module/mathjax/ directory. Then I add this line in my hugo.toml:

[params.reveal_hugo]
mathjax_cdn = "/module/mathjax/tex-svg.js"

It shows the equation correctly. So after, need to test on other people computer…

Mermaid: bad

Modification

In the file layouts/partials/layout/javascript.html I change this:

{{ if $hasMermaid }}
  {{ $mermaidSrc := resources.GetRemote "https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js" }}
  <script type="text/javascript" src="{{ $mermaidSrc.RelPermalink }}"></script>
  <script type="text/javascript">
    mermaid.initialize({startOnLoad: false});
    let render = (event) => {
      let mermaidElems = event.currentSlide.querySelectorAll('.mermaid');
      if (!mermaidElems.length){
          return
      }
      mermaidElems.forEach(mermaidElem => {
          let processed = mermaidElem.getAttribute('data-processed');
          if (!processed){
              // https://github.com/mermaid-js/mermaid/issues/311#issuecomment-332557344
              mermaid.init(undefined, mermaidElem);
          }
      });
    };
    // support current page reload with possible mermaid element
    render({currentSlide: Reveal.getCurrentSlide()});

    Reveal.on('slidechanged', render);
    Reveal.on('ready', render);
  </script>
{{ end }}

Into that:

{{ if $hasMermaid }}
  {{- $mermaid_location := $.Param "reveal_hugo.mermaid_cdn" | default "__fetch_cdn__" -}} 

  {{ if eq $mermaid_location "__fetch_cdn__"  }}
    {{ $mermaid_location := resources.GetRemote "https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js" }}
    <script type="text/javascript" async src="{{ $mermaid_location }}"></script>
  {{ else }}
    <script type="text/javascript" async src="{{ $mermaid_location }}"></script>
  {{ end  }}

  <script type="text/javascript">
    mermaid.initialize({startOnLoad: false});

    let render = (event) => {
      let mermaidElems = event.currentSlide.querySelectorAll('.mermaid');

      if (!mermaidElems.length){
          return
      }

      mermaidElems.forEach(mermaidElem => {
          let processed = mermaidElem.getAttribute('data-processed');
          if (!processed){
              // https://github.com/mermaid-js/mermaid/issues/311#issuecomment-332557344
              mermaid.init(undefined, mermaidElem);
          }
      });
    };

    // support current page reload with possible mermaid element
    render({currentSlide: Reveal.getCurrentSlide()});

    Reveal.on('slidechanged', render);
    Reveal.on('ready', render);
  </script>
{{ end }}

But it does not work as intended. And I have 0 clue of the “why”. I tried to make some test…

Problem description

The online charging work well:

{{ $mermaid_location := resources.GetRemote "https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js" }}
<script type="text/javascript" async src="{{ $mermaid_location }}"></script>

But this not the case for the local version:

<script type="text/javascript" async src="{{ $mermaid_location }}"></script>

The mermaid chart simply does not charge fully… Here is an example:

image

When it should look like the next chart:

flowchart LR
    A --> B
Loading

Using next template:

flowchart LR
    A --> B

[TESTED] Adding the attribute async

At first, the line:

    <script type="text/javascript" async src="{{ $mermaid_location }}"></script>

Where looking like that:

    <script type="text/javascript" src="{{ $mermaid_location }}"></script>

Notice the addition of the attribute async. For some reason, when not added, the mermaid chart was simply not charging. It throws an error:

Uncaught TypeError: event.currentSlide is undefined

Indeed, in the render() function, event.currentSlide was returning nothing. What is weirder is that by launching in the inspector JS terminal the command after everything was loaded:

render({currentSlide: Reveal.getCurrentSlide()});

The plot start to charge…

[TESTED] Adding a alert()

Changing this:

    <script type="text/javascript" async src="{{ $mermaid_location }}"></script>

To that:

    <script type="text/javascript">alert("toto");</script>
    <script type="text/javascript" async src="{{ $mermaid_location }}"></script>

And the mermaid chart load…

Any ideas?

If you have ideas of how to deal the problem, I can take solutions and keep going with testes on my side!

@FilouPlains
Copy link
Author

Hi again,

So, I cannot figure out why mermaid is not loading correctly… Actually, I have no idea of what to look for. So what I suggest is that I make (hopefully soon) a pull request only for the MathJax issue.

If you have idea to what to look for the mermaid issue, I am open to suggestion. Like that, I could test things on my own.

Does it sound good, for now ?

@FilouPlains
Copy link
Author

Hi,

So I might have found a “solution” for Mermaid. I transform this (original code):

{{ if $hasMermaid }}
  {{ $mermaidSrc := resources.GetRemote "https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js" }}
  <script type="text/javascript" src="{{ $mermaidSrc.RelPermalink }}"></script>
  <script type="text/javascript">
    mermaid.initialize({startOnLoad: false});
    let render = (event) => {
      let mermaidElems = event.currentSlide.querySelectorAll('.mermaid');
      if (!mermaidElems.length){
          return
      }
      mermaidElems.forEach(mermaidElem => {
          let processed = mermaidElem.getAttribute('data-processed');
          if (!processed){
              // https://github.com/mermaid-js/mermaid/issues/311#issuecomment-332557344
              mermaid.init(undefined, mermaidElem);
          }
      });
    };
    // support current page reload with possible mermaid element
    render({currentSlide: Reveal.getCurrentSlide()});

    Reveal.on('slidechanged', render);
    Reveal.on('ready', render);
  </script>
{{ end }}

To that:

{{ if $hasMermaid }}
  {{- $mermaid_location := $.Param "reveal_hugo.mermaid_cdn" | default "__fetch_cdn__" -}} 

  {{ if eq $mermaid_location "__fetch_cdn__"  }}
    {{ $mermaid_location = resources.GetRemote "https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js" }}
    {{ $mermaid_location = $mermaid_location.RelPermalink }}
  {{ end  }}

  <script type="text/javascript" async src="{{ $mermaid_location }}?nocache={{ now.Unix }}">
    mermaid.initialize({startOnLoad: false});

    let render = (event) => {
      let mermaidElems = event.currentSlide.querySelectorAll('.mermaid');

      if (!mermaidElems.length){
          return
      }

      mermaidElems.forEach(mermaidElem => {
          let processed = mermaidElem.getAttribute('data-processed');
          if (!processed){
              // https://github.com/mermaid-js/mermaid/issues/311#issuecomment-332557344
              mermaid.init(undefined, mermaidElem);
          }
      });
    };

    // support current page reload with possible mermaid element
    render({currentSlide: Reveal.getCurrentSlide()});

    Reveal.on('slidechanged', render);
    Reveal.on('ready', render);
  </script>
{{ end }}

Notice two things:

  1. The fuse of the two <script> tag in one.
  2. The addition of the attributes async.

It has a huge downside, that I do not know how to correct. Basically, when loading for the first time, there will be no problem. But after a second or third refresh, something (I suppose the JS file) is cached. Then, the chart will not be able to load correctly. Either closing fully the server and the navigator and refresh or manually empty cached files.

I search for a way to automatically delete cached file, but I did not find any… I will make two separate pull request in order for you to evaluate the situation…

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants