MathJax icon indicating copy to clipboard operation
MathJax copied to clipboard

Notify client to take screenshot after formula rendering is completed

Open Daisy1213 opened this issue 2 years ago • 11 comments

Notify client to take screenshot after formula rendering is completed

Issue Summary

I hope to notify the client to take a screenshot after the formula rendering is completed. At present, the screenshot is notified after the typesetPromise is successfully resolved, but it was found that the content has not been rendered yet. This method seems unreliable, and I hope to provide a reasonable solution to help solve this problem. @dpvc

Steps to Reproduce:

Provide a reliable event or callback that can be triggered after the formula rendering has completed.

Any other information you want to share that is relevant to the issue being reported. Especially, why do you consider this to be a bug? What do you expect to happen instead?

If possible, provide a more accurate timing for the existing typesetPromise to resolve, so it can be used efficiently for notifying the client to take a screenshot.

It is crucial for our application that the screenshot is taken as soon as the rendering is completed, to ensure that the captured image is accurate and complete.

Technical details:

  • MathJax Version: 3.2
  • Client OS: (e.g., Mac OS X 10.8.4)
  • Browser: (e.g., Chrome 29.0.1547.57)

I am using the following MathJax configuration:

      window.MathJax = {
        chtml: {
          matchFontHeight: false,
          mtextInheritFont: false
        },
        options: {
          enableMenu: false,
          renderActions: {
            handleErrors: [199,
              function (doc) {
                try {
                  // 低版本手机解决symbol兼容性问题
                  for (var math of doc.math) MathJax.config.handleError(math)
                } catch(e) {
                  //
                }
              },
              function (doc, math) { MathJax.config.handleError(math) }
            ]
          },
          skipHtmlTags: ['script', 'noscript', 'style', 'textarea', 'a', 'pre', 'code'],
          includeHtmlTags: {
            br: '\n',
            wbr: '',
            '#comment': ''
          },
          ignoreHtmlClass: 'tex2jax_ignore',
          processHtmlClass: 'tex2jax_process'
        },
        tex: {
          inlineMath: [['<latex>', '</latex>'], ['$', '$'], ['_mathjax_','_mathjax_'], ['$','$'], ['$$','$$'], ['\\(','\\)']],
          displayMath: [],
          macros: {
            ykparallelogram: '\\unicode{x25B1}',
            ykparallel: '//'
          },
          autoload: {
            color: [],
            colorV2: ['color']
          },
          packages: {
            '[+]': ['trap-undefined'],
            '[-]': ['noundefined']
          }
        },
        loader: {
          load: ['[tex]/noerrors']
        },
        startup: {
          ready: function () {
            var tex = null;
            // 根据chrome版本解决字体问题
            try {
              var ua = navigator.userAgent.toLowerCase();
              if (ua.match) { // 兼容match做版本判断
                var matchs = ua.match(/chrome\/([0-9.]+)/);
                if (matchs.length && matchs[1] && matchs[1][0]) {
                  var version = matchs[1][0]
                  if (matchs[1][1]) {
                    version = version + matchs[1][1]
                  }
                  if (matchs[1][2] && /[0-9]/.test(matchs[1][2])) {
                    version = version + matchs[1][2]
                  }
                  if (+version < 42) {
                    var TeXFont = MathJax._.output.chtml.fonts.tex_ts.TeXFont
                    TeXFont.defaultStyles['.MJX-TEX'] = {
                      'font-family': 'sans-serif'
                    }
                    TeXFont.defaultStyles['.TEX-I'] = {
                      'font-family': 'sans-serif'
                    }
                    TeXFont.defaultStyles['.TEX-B'] = {
                      'font-family': 'sans-serif'
                    }
                    TeXFont.defaultStyles['.TEX-MI'] = {
                      'font-family': 'sans-serif'
                    }
                    TeXFont.defaultStyles['.TEX-BI'] = {
                      'font-family': 'sans-serif'
                    }
                    TeXFont.defaultStyles['.TEX-S'] = {
                      'font-family': 'sans-serif'
                    }
                    TeXFont.defaultStyles['.TEX-S2'] = {
                      'font-family': 'sans-serif'
                    }
                    TeXFont.defaultStyles['.TEX-S3'] = {
                      'font-family': 'sans-serif'
                    }
                    TeXFont.defaultStyles['.TEX-S4'] = {
                      'font-family': 'sans-serif'
                    }
                    TeXFont.defaultStyles['.TEX-A'] = {
                      'font-family': 'sans-serif'
                    }
                    TeXFont.defaultStyles['.TEX-C'] = {
                      'font-family': 'sans-serif'
                    }
                    TeXFont.defaultStyles['.TEX-CB'] = {
                      'font-family': 'sans-serif'
                    }
                    TeXFont.defaultStyles['.TEX-FR'] = {
                      'font-family': 'sans-serif'
                    }
                    TeXFont.defaultStyles['.TEX-FRB'] = {
                      'font-family': 'sans-serif'
                    }
                    TeXFont.defaultStyles['.TEX-SS'] = {
                      'font-family': 'sans-serif'
                    }
                    TeXFont.defaultStyles['.TEX-SSB'] = {
                      'font-family': 'sans-serif'
                    }
                    TeXFont.defaultStyles['.TEX-SSI'] = {
                      'font-family': 'sans-serif'
                    }
                    TeXFont.defaultStyles['.TEX-SC'] = {
                      'font-family': 'sans-serif'
                    }
                    TeXFont.defaultStyles['.TEX-T'] = {
                      'font-family': 'sans-serif'
                    }
                    TeXFont.defaultStyles['.TEX-V'] = {
                      'font-family': 'sans-serif'
                    }
                    TeXFont.defaultStyles['.TEX-VB'] = {
                      'font-family': 'sans-serif'
                    }
                    TeXFont.defaultStyles['mjx-stretchy-v mjx-c, mjx-stretchy-h mjx-c'] = {
                      'font-family': 'sans-serif'
                    }
                  }
                }
              } else { // 不兼容match,webview版本较低直接替换字体
                var TeXFont = MathJax._.output.chtml.fonts.tex_ts.TeXFont
                TeXFont.defaultStyles['.MJX-TEX'] = {
                  'font-family': 'sans-serif'
                }
                TeXFont.defaultStyles['.TEX-I'] = {
                  'font-family': 'sans-serif'
                }
                TeXFont.defaultStyles['.TEX-B'] = {
                  'font-family': 'sans-serif'
                }
                TeXFont.defaultStyles['.TEX-MI'] = {
                  'font-family': 'sans-serif'
                }
                TeXFont.defaultStyles['.TEX-BI'] = {
                  'font-family': 'sans-serif'
                }
                TeXFont.defaultStyles['.TEX-S'] = {
                  'font-family': 'sans-serif'
                }
                TeXFont.defaultStyles['.TEX-S2'] = {
                  'font-family': 'sans-serif'
                }
                TeXFont.defaultStyles['.TEX-S3'] = {
                  'font-family': 'sans-serif'
                }
                TeXFont.defaultStyles['.TEX-S4'] = {
                  'font-family': 'sans-serif'
                }
                TeXFont.defaultStyles['.TEX-A'] = {
                  'font-family': 'sans-serif'
                }
                TeXFont.defaultStyles['.TEX-C'] = {
                  'font-family': 'sans-serif'
                }
                TeXFont.defaultStyles['.TEX-CB'] = {
                  'font-family': 'sans-serif'
                }
                TeXFont.defaultStyles['.TEX-FR'] = {
                  'font-family': 'sans-serif'
                }
                TeXFont.defaultStyles['.TEX-FRB'] = {
                  'font-family': 'sans-serif'
                }
                TeXFont.defaultStyles['.TEX-SS'] = {
                  'font-family': 'sans-serif'
                }
                TeXFont.defaultStyles['.TEX-SSB'] = {
                  'font-family': 'sans-serif'
                }
                TeXFont.defaultStyles['.TEX-SSI'] = {
                  'font-family': 'sans-serif'
                }
                TeXFont.defaultStyles['.TEX-SC'] = {
                  'font-family': 'sans-serif'
                }
                TeXFont.defaultStyles['.TEX-T'] = {
                  'font-family': 'sans-serif'
                }
                TeXFont.defaultStyles['.TEX-V'] = {
                  'font-family': 'sans-serif'
                }
                TeXFont.defaultStyles['.TEX-VB'] = {
                  'font-family': 'sans-serif'
                }
                TeXFont.defaultStyles['mjx-stretchy-v mjx-c, mjx-stretchy-h mjx-c'] = {
                  'font-family': 'sans-serif'
                }
              }
            } catch(e) {
              //
            }
            var Configuration = MathJax._.input.tex.Configuration.Configuration;
            var TexError = MathJax._.input.tex.TexError.default;
            Configuration.create('trap-undefined', {
              fallback: {
                macro: function (parser, cs) {
                  tex.inputData.codecogs = true;
                },
                environment: function (parser, env) {
                  tex.inputData.codecogs = true;
                }
              }
            });
            var toDOM = function (math, node, html) {
              this.setDocument(html);
              if (math.inputData.codecogs) {
                var adaptor = html.adaptor;
                if (math.display) adaptor.setAttribute(node, 'display', true);
                // 兜底src
                var encodeLatex = encodeURIComponent(math.math.trim() + '\\quad')
                var questiontoken = math.start.node.parentElement.getAttribute('questiontoken') || ''
                var defaultSrc = 'https://gallery.fbcontent.cn/latex?decode=false&fontSize=34&latex=' + encodeLatex + (questiontoken ? '&questiontoken=' + questiontoken : '')
                var originSrc = math.start.node && math.start.node.parentElement && math.start.node.parentElement.getAttribute && math.start.node.parentElement.getAttribute('origin-src')
                var imageNode = adaptor.node('img', {
                  src: originSrc || defaultSrc,
                  alt: tex.math.trim()
                })
                imageNode.onload = function () {
                  imageNode.style.height = imageNode.naturalHeight / 2 + 'px'
                  imageNode.style.width = imageNode.naturalWidth / 2 + 'px'
                }
                html.adaptor.append(node, imageNode);
                math.display = null;
                var src = originSrc || defaultSrc
                window.VUE_APP && window.VUE_APP.$emit('sendError', {
                  url: '/debug/solarResultsPage/parseError',
                  src: src,
                  alt: math.math.trim(),
                  srcWithOutQuestionToken: src && src.replace(/[&?]questiontoken=.*/, '')
                })
              } else {
                this._toDOM(math, node, html);
              }
            };

            var getOutputJax = MathJax.startup.getOutputJax;
            MathJax.startup.getOutputJax = function () {
              var output = getOutputJax();
              output._toDOM = output.toDOM;
              output.toDOM = toDOM;
              return output;
            }

            MathJax.startup.defaultReady();

            MathJax.startup.input[0].preFilters.add(function (filter) {
              var math = filter.math
              tex = math
            });

            MathJax.startup.output._toDOM = MathJax.startup.output.toDOM;
            MathJax.startup.output.toDOM = toDOM;

          }
        },
        handleError: function(math) {
          var node = math.root.childNodes[0];
          if (node && !node.getProperty('error-reported') && node.childNodes[0] && node.childNodes[0].attributes.get('data-mjx-error')) {
            var div = math.typesetRoot = document.createElement(math.display ? 'div' : 'span');
            var imageNode = document.createElement('img')
            // 兜底src
            var encodeLatex = encodeURIComponent(math.math.trim() + '\\quad')
            var questiontoken = math.start.node.parentElement.getAttribute('questiontoken') || ''
            var defaultSrc = 'https://gallery.fbcontent.cn/latex?decode=false&fontSize=34&latex=' + encodeLatex + (questiontoken ? '&questiontoken=' + questiontoken : '')
            var originSrc = math.start.node && math.start.node.parentElement && math.start.node.parentElement.getAttribute && math.start.node.parentElement.getAttribute('origin-src')
            imageNode.src = originSrc || defaultSrc;
            imageNode.alt = math.math.trim()
            imageNode.onload = function () {
              imageNode.style.height = imageNode.naturalHeight / 2 + 'px';
              imageNode.style.width = imageNode.naturalWidth / 2 + 'px';
            }
            div.appendChild(imageNode)
            node.setProperty('error-reported', true)
            var src = originSrc || defaultSrc
            window.VUE_APP && window.VUE_APP.$emit('sendError', {
              url: '/debug/solarResultsPage/mathjaxError',
              src: src,
              alt: math.math.trim(),
              srcWithOutQuestionToken: src && src.replace(/[&?]questiontoken=.*/, '')
            })
          }
        }
      }

and loading MathJax via

<script defer src="https://solar.fbcontent.cn/h5/solar-web-mathjax3/es5/tex-chtml.js"></script>

Supplementary content

replenishment a easy demo, The background color is expected to turn red when the formula is rendered, but it is already red when the formula is processed

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>MathJax 3 Example</title>
    <script>
    window.MathJax = {
      tex: {
        inlineMath: [['$', '$'], ['\\(', '\\)']],
        displayMath: [['$$', '$$'], ['\\[', '\\]']],
        // processEscapes: true,
        // packages: {'[+]': ['noerrors']}
      },
      startup: {
        ready: function () {
          MathJax.startup.defaultReady();
        },
      }
    };
    </script>
    <script src="https://solar.fbcontent.cn/h5/solar-web-mathjax3/es5/tex-chtml.js"></script>
    <script>
        window.addEventListener('load', function () {
          const dom = document.getElementById('test')
          console.log(dom, 'dom')
          MathJax.typesetPromise([dom]).then(() => {
            document.body.style.color = 'red';
            alert('xxxx');
          });;
        });
    </script>
</head>
<body id="test">
<h1>MathJax 3 Example</h1>
<p>Here's an inline math example: $x = \frac{-b \pm \sqrt{b^2 - 4ac}}{2a}$.</p>
<p>And a display math example:</p>
$$
\int_{-\infty}^\infty e^{-x^2} dx = \sqrt{\pi}
$$



<h1>MathJax 3 Example</h1>
<p>Here's an inline math example: $x = \frac{-b \pm \sqrt{b^4 - 4ac}}{5a}$.</p>
<p>And a display math example:</p>
$$
\int_{-\infty}^\infty e^{-x^4} dx = \sqrt{\pi}
$$

$$\frac{8}{31}$$
$$\frac{8}{31}$$
$$\frac{8}{31}$$
$$\frac{18}{31}-$$
$$\frac{10}{31}=0.25806452$$
$$\frac{9}{19}+$$
$$\frac{4}{19}=$$
$$\frac{13}{19}","content":"$$
$$\frac{9}{19}+$$
$$\frac{4}{19}$$
$$\frac{9}{19}+$$
$$\frac{4}{19}$$
$$\frac{9+4}{19}$$
$$\frac{13}{19}$$
$$\frac{9}{19}+$$
$$\frac{4}{19}=0.68421053$$
$$\frac{19}{37}+$$
$$\frac{4}{31}=$$
$$\frac{737}{1147}$$
$$\frac{19}{37}+$$
$$\frac{4}{31}$$
$$\frac{19}{37}+$$
$$\frac{4}{31}$$
$$\frac{19}{23}$$
$$\frac{4}{56}$$
$$\frac{589}{1147}$$
$$\frac{148}{1147}$$
$$\frac{589+148}{1147}$$

</body>
</html>

Daisy1213 avatar Aug 02 '23 07:08 Daisy1213

I hope the authorities can help me look at this problem as soon as possible, The situation is urgent. Thanks a million! @dpvc

Daisy1213 avatar Aug 03 '23 03:08 Daisy1213

I hope the authorities can help me look at this problem as soon as possible, The situation is urgent.

Everyone feels their problem is urgent. Support here is provided by volunteers in their off time, and we respond when we are able. Poking us after one day doesn't improve your chances of getting help (indeed, it often leads to moving you to the bottom of the queue).

It is good that you added the additional example file, as your original description didn't make it clear whether you were using typesetPromise() properly.

The issue you are having is that typesetPromise() resolves when MathJax has processed the math expression and added the needed elements to the DOM, but that doesn't mean that the browser has displayed those changes yet. DOM changes are buffered but the browser until the running javascript completes and the browser is idle; at that point, the display is updated (called a "repaint" of the display). So even though MathJax has done the work of typesetting the math and inserted the typeset expression into the page when typesetPromise() resolves, the browser needs to pass through an idle state in order to have those changes be displayed. MathJax has done its work, but the browser needs a chance to do its repaint. That means you can't do the screen shot immediately after the promise resolves; you need to wait until after the next idle state of the browser before you do.

There are several ways that can be accomplished. One is to use setTimeout() to delay the screen shot until after the browser updates the screen. For example, in your code above, if you use

          MathJax.typesetPromise([dom]).then(() => {
            console.log(document.querySelector('mjx-container').outerHTML);
            document.body.style.color = 'red';
            setTimeout(() => alert('xxxx'), 1);
          });

you will see (from the console.log()) that MathJax has added the typeset math to the DOM when the promise resolves, but the alert() it put off until after then next idle state, giving the browser the chance to repaint the screen (showing both the typeset math and the color change), whereas your original alert() gets performed before the screen is repainted (and before the color change occurs in some browsers).

An alternative is to use the more modern requestAnimationFrame(callback), where the callback is performed just before the next repaint. Of course, since this is before the next repaint, that is too early, as the repaint won't have occurred yet. So you need to use requestAnimationFrame() a second time to get a callback to run before the next repaint (i.e., after the first repaint). For example,

          MathJax.typesetPromise([dom]).then(() => {
            console.log(document.querySelector('mjx-container').outerHTML);
            document.body.style.color = 'red';
            requestAnimationFrame(() => {requestAnimationFrame(() => alert('xxxx'));});
          });

should do the trick.

There is another issue, however: MathJax's CHTML output relies on web fonts, and it takes time for those to be downloaded when first used. Neither of the approaches above take that into account, so when the alert occurs, the web fonts may not have been downloaded yet, and they equations may only be partially visible. So you need to wait for the fonts as well. For that, you can use the document.fonts.ready promise, as in:

          MathJax.typesetPromise([dom]).then(() => {
            document.body.style.color = 'red';
            setTimeout(() => {document.fonts.ready.then(() => alert('xxxx'))}, 1);
          });

or

          MathJax.typesetPromise([dom]).then(() => {
            document.body.style.color = 'red';
            requestAnimationFrame(() => {
              requestAnimationFrame(() => {
                document.fonts.ready.then (() => alert('xxxx'));
              });
            });
          });

So the upshot is that typesetPromise() is working as designed (it resolves when MathJax finishes its work), but does not do what you expect because you need to wait for a repaint and fonts to load before doing your screen shot.

dpvc avatar Aug 04 '23 12:08 dpvc

Hello, thank you very much for your reply and solutions you provided. @dpvc

Everyone feels their problem is urgent. Support here is provided by volunteers in their off time, and we respond when we are able. Poking us after one day doesn't improve your chances of getting help (indeed, it often leads to moving you to the bottom of the queue).

I'm sincerely sorry about the rush last time :(


After vefiy two solutions you provided, below are my gains:

  1. The setTimeout method has been tried, but setting it for 200ms has not waited for the browser to draw
  2. We just tried requestAnimationFrame, but occasionally the page is not painted

Summary: these two solutions are not working.

More information add:

  1. Because the local screenshots are not easy to simulate, I interrupt them by alert(). I am not sure whether the detection method such as alert is accurate or not, if yes, now solution 2 in my case sometimes it works and sometimes it doesn't.
  2. Actually I am building a Vue project. In order to let you help me locate the problem more accurately, I wrote a simple demo and pushed it to my github. The link is repo url please check it if you can :)

Looking forward to your next reply:)

Daisy1213 avatar Aug 05 '23 13:08 Daisy1213

these two solutions are not working.

Did you try these out in the "easy demo" you provided above? They work there for me, so if they don't for you, then it may be a browser difference that needs to be addressed.

If they do work for you there, but not in your app, then it is some interaction with your larger app that is the issue. You mention that you are using Vue; I'm not familiar with its details, but my understanding is that Vue uses a virtual DOM (see the guide page on that), which means that Vue keeps a separate DOM structure that it uses to update the actual browser DOM periodically. You may have to wait for that to occur before taking your screen snapshot.

Since I don't really know anything about Vue, I can't help you with that. You will need to check the documentation, or reach out the Vue community to see how that is done.

dpvc avatar Aug 09 '23 23:08 dpvc

Did you try these out in the "easy demo" you provided above? They work there for me, so if they don't for you, then it may be a browser difference that needs to be addressed.

Hello, I made changes based on the easy demo you gave, trying to reproduce the problem I encountered.

I've provided a screen recording, you can see that the problem still occasionally appears (the alert method triggers before the formula render finished).

In the screen recording, I try to refresh the page repeatedly to see if the render callback of the formula is working. At about 11 seconds, I can see behaviours of the exception case.

You can use the code sample I've provided to debug it.

The code this time is not about vue framework, it is written in native js, but the problem still exist, so it also shows that the problem is not related to the vue framework.

Please help me, thank you :-)

https://github.com/mathjax/MathJax/assets/18098766/dac39878-c0df-4599-b13d-bc78347064c1

<!DOCTYPE html>
<html style="font-size: 55.2px;">
<head>
    <meta charset="utf-8">
    <title>MathJax 3 Example</title>
    <style type="text/css">.auto-answer-500[data-v-7e39d66f] {
        list-style-type: none;
        counter-reset: sectioncounter;
    }
    .auto-answer-500 .tip[data-v-7e39d66f] {
        color: #909090;
        font-size: 0.24rem;
        margin-bottom: 0.24rem;
    }
    .auto-answer-500 .tag-content[data-v-7e39d66f] {
        display: -webkit-box;
        display: -webkit-flex;
        display: -moz-box;
        display: -ms-flexbox;
        display: flex;
        margin-bottom: 0.36rem;
    }
    .auto-answer-500 .tag-content .tag-item[data-v-7e39d66f] {
        border: 1px solid #F4F4F4;
        color: #272727;
        background-color: #F4F4F4;
        -webkit-border-radius: 0.12rem;
        border-radius: 0.12rem;
        font-size: 0.28rem;
        display: -webkit-box;
        display: -webkit-flex;
        display: -moz-box;
        display: -ms-flexbox;
        display: flex;
        -webkit-box-align: center;
        -webkit-align-items: center;
        -moz-box-align: center;
        -ms-flex-align: center;
        align-items: center;
        -webkit-box-pack: center;
        -webkit-justify-content: center;
        -moz-box-pack: center;
        -ms-flex-pack: center;
        justify-content: center;
        margin-right: 0.32rem;
        width: 1.4rem;
        height: 0.56rem;
    }
    .auto-answer-500 .tag-content .tag-item.isSelected[data-v-7e39d66f] {
        border: 1px solid #3D94FF;
        background: rgba(61, 148, 255, 0.1);
        color: #3D94FF;
    }
    .auto-answer-500 .latex-answer-steps[data-v-7e39d66f] {
        display: inline-block;
        margin-bottom: 0.46rem;
        vertical-align: top;
        margin-right: 0.5rem;
        max-width: 100%;
        position: relative;
    }
    .auto-answer-500 .latex-answer-steps[data-v-7e39d66f]:before {
        content: counter(sectioncounter);
        counter-increment: sectioncounter;
        color: #272727;
        display: inline-block;
        -webkit-border-radius: 0.5rem;
        border-radius: 0.5rem;
        font-size: 0.26rem;
        border: 1px solid #272727;
        width: 0.36rem;
        height: 0.36rem;
        text-align: center;
        position: absolute;
        left: 0;
    }
    .auto-answer-500 .latex-answer-step[data-v-7e39d66f] {
        padding-bottom: 0.08rem;
        margin-left: 0.46rem;
    }
    </style>
    <script>
    window.MathJax = {
      tex: {
        inlineMath: [['$', '$'], ['\\\\(', '\\\\)']],
        displayMath: [['$$', '$$'], ['\\\\[', '\\\\]']],
        // processEscapes: true,
        // packages: {'[+]': ['noerrors']}
      },
      startup: {
        ready: function () {
          MathJax.startup.defaultReady();
        },
      }
    }
    </script>
    <script src="https://solar.fbcontent.cn/h5/solar-web-mathjax3/es5/tex-chtml.js"></script>
    <script>
    window.addEventListener('load', function () {
      // 用延时模拟数据请求,异步渲染公式
      setTimeout(() => {
        const dom = document.getElementById('container')
        const mathDom = document.createElement('div')
        mathDom.id = 'math-dom'
        mathDom.innerHTML = '<div data-v-7e39d66f="" class="auto-answer-500"><div data-v-7e39d66f="" class="latex-contents"><div data-v-7e39d66f="" class="latex-answer-steps"><div data-v-7e39d66f="" class="latex-answer-step">$\\quad\\frac{18}{31}-\\frac{10}{31}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{18-10}{31}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{8}{31}$</div></div><div data-v-7e39d66f="" class="latex-answer-steps"><div data-v-7e39d66f="" class="latex-answer-step">$\\quad\\frac{9}{19}+\\frac{4}{19}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{9+4}{19}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{13}{19}$</div></div><div data-v-7e39d66f="" class="latex-answer-steps"><div data-v-7e39d66f="" class="latex-answer-step">$\\quad\\frac{19}{37}+\\frac{4}{31}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{19\\times 31}{37\\times 31}+\\frac{4\\times 37}{31\\times 37}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{589}{1147}+\\frac{148}{1147}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{589+148}{1147}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{737}{1147}$</div></div><div data-v-7e39d66f="" class="latex-answer-steps"><div data-v-7e39d66f="" class="latex-answer-step">$\\quad\\frac{13}{23}-\\frac{5}{23}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{13-5}{23}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{8}{23}$</div></div><div data-v-7e39d66f="" class="latex-answer-steps"><div data-v-7e39d66f="" class="latex-answer-step">$\\quad\\frac{4}{5}-\\frac{2}{5}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{4-2}{5}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{2}{5}$</div></div><div data-v-7e39d66f="" class="latex-answer-steps"><div data-v-7e39d66f="" class="latex-answer-step">$\\quad\\frac{6}{12}+\\frac{7}{26}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{1}{2}+\\frac{7}{26}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{1\\times 13}{2\\times 13}+\\frac{7}{26}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{13}{26}+\\frac{7}{26}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{13+7}{26}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{20}{26}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{10}{13}$</div></div><div data-v-7e39d66f="" class="latex-answer-steps"><div data-v-7e39d66f="" class="latex-answer-step">$\\quad\\frac{7}{24}+\\frac{5}{24}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{7+5}{24}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{12}{24}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{1}{2}$</div></div><div data-v-7e39d66f="" class="latex-answer-steps"><div data-v-7e39d66f="" class="latex-answer-step">$\\quad\\frac{7}{26}+\\frac{5}{24}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{7\\times 12}{26\\times 12}+\\frac{5\\times 13}{24\\times 13}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{84}{312}+\\frac{65}{312}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{84+65}{312}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{149}{312}$</div></div><div data-v-7e39d66f="" class="latex-answer-steps"><div data-v-7e39d66f="" class="latex-answer-step">$\\quad\\frac{5}{24}+\\frac{3}{8}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{5}{24}+\\frac{3\\times 3}{8\\times 3}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{5}{24}+\\frac{9}{24}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{5+9}{24}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{14}{24}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{7}{12}$</div></div><div data-v-7e39d66f="" class="latex-answer-steps"><div data-v-7e39d66f="" class="latex-answer-step">$\\quad\\frac{15}{21}+\\frac{11}{31}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{5}{7}+\\frac{11}{31}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{5\\times 31}{7\\times 31}+\\frac{11\\times 7}{31\\times 7}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{155}{217}+\\frac{77}{217}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{155+77}{217}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{232}{217}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=1\\frac{15}{217}$</div></div><div data-v-7e39d66f="" class="latex-answer-steps"><div data-v-7e39d66f="" class="latex-answer-step">$\\quad\\frac{5}{37}+\\frac{12}{31}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{5\\times 31}{37\\times 31}+\\frac{12\\times 37}{31\\times 37}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{155}{1147}+\\frac{444}{1147}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{155+444}{1147}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{599}{1147}$</div></div><div data-v-7e39d66f="" class="latex-answer-steps"><div data-v-7e39d66f="" class="latex-answer-step">$\\quad\\frac{1}{31}+\\frac{13}{31}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{1+13}{31}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{14}{31}$</div></div><div data-v-7e39d66f="" class="latex-answer-steps"><div data-v-7e39d66f="" class="latex-answer-step">$\\quad\\frac{2}{11}+\\frac{6}{11}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{2+6}{11}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{8}{11}$</div></div><div data-v-7e39d66f="" class="latex-answer-steps"><div data-v-7e39d66f="" class="latex-answer-step">$\\quad\\frac{2}{21}\\div \\frac{1}{21}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{2}{21}\\times 21$</div><div data-v-7e39d66f="" class="latex-answer-step">$=2\\times 1$</div><div data-v-7e39d66f="" class="latex-answer-step">$=2$</div></div><div data-v-7e39d66f="" class="latex-answer-steps"><div data-v-7e39d66f="" class="latex-answer-step">$\\quad\\frac{1}{3}+\\frac{1}{3}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{1+1}{3}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{2}{3}$</div></div><div data-v-7e39d66f="" class="latex-answer-steps"><div data-v-7e39d66f="" class="latex-answer-step">$\\quad\\frac{4}{5}+\\frac{1}{2}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{4\\times 2}{5\\times 2}+\\frac{1\\times 5}{2\\times 5}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{8}{10}+\\frac{5}{10}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{8+5}{10}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{13}{10}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=1\\frac{3}{10}$</div></div><div data-v-7e39d66f="" class="latex-answer-steps"><div data-v-7e39d66f="" class="latex-answer-step">$\\quad\\frac{13}{10}-\\frac{1}{6}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{13\\times 3}{10\\times 3}-\\frac{1\\times 5}{6\\times 5}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{39}{30}-\\frac{5}{30}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{39-5}{30}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{34}{30}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{17}{15}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=1\\frac{2}{15}$</div></div><div data-v-7e39d66f="" class="latex-answer-steps"><div data-v-7e39d66f="" class="latex-answer-step">$\\quad\\frac{8}{25}-\\frac{3}{15}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{8}{25}-\\frac{1}{5}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{8}{25}-\\frac{1\\times 5}{5\\times 5}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{8}{25}-\\frac{5}{25}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{8-5}{25}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{3}{25}$</div></div><div data-v-7e39d66f="" class="latex-answer-steps"><div data-v-7e39d66f="" class="latex-answer-step">$\\quad\\frac{2}{21}+\\frac{4}{21}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{2+4}{21}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{6}{21}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{2}{7}$</div></div><div data-v-7e39d66f="" class="latex-answer-steps"><div data-v-7e39d66f="" class="latex-answer-step">$\\quad\\frac{1}{34}+\\frac{5}{14}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{1\\times 7}{34\\times 7}+\\frac{5\\times 17}{14\\times 17}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{7}{238}+\\frac{85}{238}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{7+85}{238}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{92}{238}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{46}{119}$</div></div><div data-v-7e39d66f="" class="latex-answer-steps"><div data-v-7e39d66f="" class="latex-answer-step">$\\quad\\frac{3}{20}+\\frac{1}{20}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{3+1}{20}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{4}{20}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{1}{5}$</div></div><div data-v-7e39d66f="" class="latex-answer-steps"><div data-v-7e39d66f="" class="latex-answer-step">$\\quad\\frac{1}{25}+\\frac{10}{23}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{1\\times 23}{25\\times 23}+\\frac{10\\times 25}{23\\times 25}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{23}{575}+\\frac{250}{575}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{23+250}{575}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{273}{575}$</div></div><div data-v-7e39d66f="" class="latex-answer-steps"><div data-v-7e39d66f="" class="latex-answer-step">$\\quad\\frac{6}{11}+\\frac{4}{11}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{6+4}{11}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{10}{11}$</div></div><div data-v-7e39d66f="" class="latex-answer-steps"><div data-v-7e39d66f="" class="latex-answer-step">$\\quad\\frac{7}{11}+\\frac{5}{22}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{7\\times 2}{11\\times 2}+\\frac{5}{22}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{14}{22}+\\frac{5}{22}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{14+5}{22}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{19}{22}$</div></div><div data-v-7e39d66f="" class="latex-answer-steps"><div data-v-7e39d66f="" class="latex-answer-step">$\\quad\\frac{5}{8}-\\frac{5}{12}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{5\\times 3}{8\\times 3}-\\frac{5\\times 2}{12\\times 2}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{15}{24}-\\frac{10}{24}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{15-10}{24}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{5}{24}$</div></div><div data-v-7e39d66f="" class="latex-answer-steps"><div data-v-7e39d66f="" class="latex-answer-step">$\\quad\\frac{9}{16}-\\frac{3}{36}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{9}{16}-\\frac{1}{12}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{9\\times 3}{16\\times 3}-\\frac{1\\times 4}{12\\times 4}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{27}{48}-\\frac{4}{48}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{27-4}{48}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{23}{48}$</div></div><div data-v-7e39d66f="" class="latex-answer-steps"><div data-v-7e39d66f="" class="latex-answer-step">$\\quad\\frac{1}{23}-\\frac{5}{23}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{1-5}{23}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=-\\frac{4}{23}$</div></div><div data-v-7e39d66f="" class="latex-answer-steps"><div data-v-7e39d66f="" class="latex-answer-step">$\\quad\\frac{7}{22}+\\frac{4}{26}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{7}{22}+\\frac{2}{13}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{7\\times 13}{22\\times 13}+\\frac{2\\times 22}{13\\times 22}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{91}{286}+\\frac{44}{286}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{91+44}{286}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{135}{286}$</div></div><div data-v-7e39d66f="" class="latex-answer-steps"><div data-v-7e39d66f="" class="latex-answer-step">$\\quad\\frac{1}{30}\\div \\frac{13}{36}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{1}{30}\\times \\frac{36}{13}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{1}{5}\\times \\frac{6}{13}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{1\\times 6}{5\\times 13}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{6}{65}$</div></div><div data-v-7e39d66f="" class="latex-answer-steps"><div data-v-7e39d66f="" class="latex-answer-step">$\\quad\\frac{7}{34}+\\frac{3}{24}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{7}{34}+\\frac{1}{8}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{7\\times 4}{34\\times 4}+\\frac{1\\times 17}{8\\times 17}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{28}{136}+\\frac{17}{136}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{28+17}{136}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{45}{136}$</div></div><div data-v-7e39d66f="" class="latex-answer-steps"><div data-v-7e39d66f="" class="latex-answer-step">$\\quad\\frac{2}{3}-\\frac{11}{27}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{2\\times 9}{3\\times 9}-\\frac{11}{27}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{18}{27}-\\frac{11}{27}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{18-11}{27}$</div><div data-v-7e39d66f="" class="latex-answer-step">$=\\frac{7}{27}$</div></div></div></div>'

        dom.append(mathDom)
        window.MathJax.typesetPromise([mathDom]).then(() => {
          requestAnimationFrame(() => {
            console.log('第yi次')
            requestAnimationFrame(() => {
              console.log('第二次')
              document.fonts.ready.then (() => {
                alert('xxxx')
              });
              requestAnimationFrame(() => {
                console.log('第三次')
              })
            });
          });
        });
      }, 400)
    });
    </script>
</head>
<body id="container">
</body>
</html>

Daisy1213 avatar Aug 13 '23 11:08 Daisy1213

Your screencast shows that the fonts have not been displayed when your alert occurs in that one bad instance. That suggests that the documents.fonts.ready promise only means the font has arrived, not that the screen has been updated (just like the MathJax.typesetPromise() just means the DOM has been updated, not not necessarily displayed).

So the order for the promises should be MathJax.typesetPromise() then document.fonts.ready, then the two resetAnimationFrame() calls. That way, your alert (or screen snapshot) will be after both MathJax has completed and its fonts have arrived, and the screen has updated. (Regrettably, I gave you the wrong order before.) So try

        window.MathJax.typesetPromise([mathDom]).then(() => {
          document.fonts.ready.then (() => {
            requestAnimationFrame(() => {
              console.log('第yi次')
              requestAnimationFrame(() => {
                console.log('第二次')
                alert('xxxx')
              });
            });
          });
        });

and see if that works better.

Also, you should not need the setTimout() at all, and technically you should use

MathJax.startup.promise.then(() => {

rather than

    window.addEventListener('load', function () {

since you should wait for MathJax to finish its setup and initial typesetting pass before calling MathJax.typesetPromise(), and your current setup doesn't guarantee that. Also, the startup block in your MathJax configuration is unneeded, as it doesn't actually do anything.

In any case, I think that switching the order of the promises will finally get you what you need.

dpvc avatar Aug 23 '23 19:08 dpvc

Your screencast shows that the fonts have not been displayed when your alert occurs in that one bad instance. That suggests that the documents.fonts.ready promise only means the font has arrived, not that the screen has been updated (just like the MathJax.typesetPromise() just means the DOM has been updated, not not necessarily displayed).

So the order for the promises should be MathJax.typesetPromise() then document.fonts.ready, then the two resetAnimationFrame() calls. That way, your alert (or screen snapshot) will be after both MathJax has completed and its fonts have arrived, and the screen has updated. (Regrettably, I gave you the wrong order before.) So try

        window.MathJax.typesetPromise([mathDom]).then(() => {
          document.fonts.ready.then (() => {
            requestAnimationFrame(() => {
              console.log('第yi次')
              requestAnimationFrame(() => {
                console.log('第二次')
                alert('xxxx')
              });
            });
          });
        });

and see if that works better.

Also, you should not need the setTimout() at all, and technically you should use

MathJax.startup.promise.then(() => {

rather than

    window.addEventListener('load', function () {

since you should wait for MathJax to finish its setup and initial typesetting pass before calling MathJax.typesetPromise(), and your current setup doesn't guarantee that. Also, the startup block in your MathJax configuration is unneeded, as it doesn't actually do anything.

In any case, I think that switching the order of the promises will finally get you what you need.

  1. I use setTimeout just to simulate the network request and get the data. This is necessary.
  2. I process the whole logic in the load event because I want to insert the data into the dom, so I need to get the body element first
  3. I tried to use your latest code order to execute, found that there is still a problem

Daisy1213 avatar Aug 28 '23 11:08 Daisy1213

I tried to use your latest code order to execute, found that there is still a problem

I'm sorry, I am no longer able to offer any advice.

dpvc avatar Aug 28 '23 12:08 dpvc

I tried to use your latest code order to execute, found that there is still a problem

I'm sorry, I am no longer able to offer any advice.

Doesn't anyone have needs like mine? This is supposed to be a very common scenario. I'm confused. If there is no solution, what should I do[流泪]

Daisy1213 avatar Aug 29 '23 02:08 Daisy1213

I tried to use your latest code order to execute, found that there is still a problem

I'm sorry, I am no longer able to offer any advice.

I have also tested that the loading of the font file does not affect the rendering, even if the font file is loaded incorrectly, at most, the font effect after rendering does not meet the expectations, but at least there should be content. But you can see from the video why it took so long for the numbers to come out, so I decided that the focus here should not be on the font file, unless there is some other logic in the internal implementation that I am not clear about, please advise!

Or is there a configuration where you can display system fonts before the font files are loaded, rather than displaying nothing at all, at least without confusing the user

Daisy1213 avatar Aug 29 '23 08:08 Daisy1213

Doesn't anyone have needs like mine?

What I can say is that no one else has asked about the problem you are facing in the 14 years that MathJax has been available.

If there is no solution, what should I do[?]

I didn't say there was no solution, I said I was out of ideas to offer you.

I have also tested that the loading of the font file does not affect the rendering,

That is not correct. Your video clearly shows that the timing of when the font is loaded compared to when your alert() is issued makes a difference. The problem you point out in that video is because the font hasn't yet appeared on screen. MathJax's layout is all in place (as evidenced by the presence of the fraction lines; it is the font that is missing at that point.

even if the font file is loaded incorrectly, at most, the font effect after rendering does not meet the expectations, but at least there should be content.

What happens with a font that is corrupted ("loaded incorrectly") or not available is different from what happens when the browser is waiting for the font to arrive. This can be controlled by the font-display CSS attribute (see the MDN documentation for details), but MathJax doesn't set this, so the auto value is used, which means the behavior is up to the browsers. Currently, most browsers seem to use the invisible font until the actual font arrives. That is what is occurring in your video, for example.

so I decided that the focus here should not be on the font file

This is a mistake, as waiting for the font to arrive is the key step that isn't working for you.

I did some more experimenting, and it turns out that the document.fonts.ready promise is not reliable in some browsers. In WebKit (e.g., Safari) and Blink (e.g., Chrome and Edge), it appears that when new CSS is added that loads web fonts, document.fonts.ready is not set to a new promise for the download of that font immediately, and there needs to be a pause before checking it. Furthermore, in WebKit, it never seems to be updated, and so it fires immediately, even when the fonts haven't been downloaded. In Firefox, it is updated immediately when the CSS is added, and so the code I gave you worked for me in Firefox, where I did my testing. But it doesn't work as expected in WebKit or Blink browsers. You haven't indicated which browser or OS you are using, as requested in the bug report template, so I can't tell if this might be the issue for you, but unless you are using Firefox, it probably is.

Since documents.fonts.ready is unreliable in WebKit, that means you have to use another method. One would be to fall back on polling the document.fonts.status value, which is not great, but seems to work for me in Safari and Chrome. Here is one approach to doing that. It uses a short setTimeout() call to allow the status to update, and then checks to see if the fonts are loaded; if not, it waits a bit and tries again, and tries again. We use document.fonts.ready to wait before trying again, so that for those browsers where it works (Firefox, Chrome, Edge), you will only have to poll one more time, but for those where it doesn't work (Safari), you will continue to poll document.fonts.status until it is loaded, indicating that the fonts are all loaded.

This worked for me in all browsers I tested. If that doesn't work for you, the only other option I have is to suggest that you try the SVG output rather than CHTML output, as that doesn't rely on web fonts.

dpvc avatar Aug 30 '23 14:08 dpvc