diff --git a/client/homebrew/navbar/print.navitem.jsx b/client/homebrew/navbar/print.navitem.jsx
index ea262cf03..e669214b3 100644
--- a/client/homebrew/navbar/print.navitem.jsx
+++ b/client/homebrew/navbar/print.navitem.jsx
@@ -1,9 +1,25 @@
-import React from 'react';
+import React, { useState, useEffect } from 'react';
import Nav from './nav.jsx';
import { printCurrentBrew } from '@shared/helpers.js';
export default function(){
+ const [printing, setPrinting] = useState(false);
+
+ // listen for print cycle events to display "loading" message since it can take some time.
+ useEffect(()=>{
+ document.addEventListener('print:startprep', handlePrintStartPrep);
+ document.addEventListener('print:finishedprep', handlePrintPrepFinished);
+ return ()=>{
+ document.removeEventListener('print:startprep', handlePrintStartPrep);
+ document.removeEventListener('print:finishedprep', handlePrintPrepFinished);
+ }
+ }, []);
+
+ const handlePrintStartPrep = ()=>{ setPrinting(true); };
+
+ const handlePrintPrepFinished = ()=>{ setPrinting(false); };
+
return
- get PDF
+ {printing ? 'loading' : 'get PDF'}
;
};
diff --git a/shared/helpers.js b/shared/helpers.js
index eb3dba6d8..3610ccea4 100644
--- a/shared/helpers.js
+++ b/shared/helpers.js
@@ -105,14 +105,35 @@ const splitTextStyleAndMetadata = (brew)=>{
if(typeof brew.tags === 'string') brew.tags = brew.tags ? [brew.tags] : [];
};
-const printCurrentBrew = ()=>{
+const printCurrentBrew = async ()=>{
if(window.typeof !== 'undefined') {
- window.frames['BrewRenderer'].contentWindow.print();
- //Force DOM reflow; Print dialog causes a repaint, and @media print CSS somehow makes out-of-view pages disappear
- const node = window.frames['BrewRenderer'].contentDocument.getElementsByClassName('brewRenderer').item(0);
- node.style.display='none';
- node.offsetHeight; // accessing this is enough to trigger a reflow
- node.style.display='';
+ // fire a custom event for the print cycle
+ document.dispatchEvent(new CustomEvent('print:startprep'));
+ try {
+ const iframeDoc = window.frames['BrewRenderer'].contentDocument;
+
+ // get all img elements with lazy loading (currently only elements generated through MarkedJS)
+ const lazyImages = [...iframeDoc.querySelectorAll('img[loading="lazy"]')];
+ lazyImages.forEach((img)=>{ img.loading = 'eager'; });
+
+ // waits for images to load before resolving promise and opening print dialog
+ await Promise.all(
+ lazyImages
+ .filter((img)=>!img.complete)
+ .map((img)=>new Promise((resolve)=>{ img.onload = resolve; img.onerror = resolve; }))
+ );
+
+ window.frames['BrewRenderer'].contentWindow.print();
+
+ //Force DOM reflow; Print dialog causes a repaint, and @media print CSS somehow makes out-of-view pages disappear
+ const node = iframeDoc.getElementsByClassName('brewRenderer').item(0);
+ node.style.display='none';
+ node.offsetHeight; // accessing this is enough to trigger a reflow
+ node.style.display='';
+ } finally {
+ // when lazy load images have all been loaded, and the doc re-rendered for print preview, emit 'finished' event.
+ document.dispatchEvent(new CustomEvent('print:finishedprep'));
+ }
}
};
diff --git a/shared/markdown.js b/shared/markdown.js
index d2a108e01..05a564254 100644
--- a/shared/markdown.js
+++ b/shared/markdown.js
@@ -83,7 +83,7 @@ renderer.image = function (token) {
if(href === null)
return text;
- let out = `
{
it('Renders an image element with injected style', function() {
const source = '{position:absolute}';
const rendered = Markdown.render(source).trimReturns();
- expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('

');
+ expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('
');
});
it('Renders an element modified by only the first of two consecutive injections', function() {
@@ -343,19 +343,19 @@ describe('Injection: When an injection tag follows an element', ()=>{
it('Renders an image with added attributes', function() {
const source = ` {position:absolute,bottom:20px,left:130px,width:220px,a="b and c",d=e}`;
const rendered = Markdown.render(source).trimReturns();
- expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`
`);
+ expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`
`);
});
it('Renders an image with "=" in the url, and added attributes', function() {
const source = ` {position:absolute,bottom:20px,left:130px,width:220px,a="b and c",d=e}`;
const rendered = Markdown.render(source).trimReturns();
- expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`
`);
+ expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`
`);
});
it('Renders an image and added attributes with "=" in the value, ', function() {
const source = ` {position:absolute,bottom:20px,left:130px,width:220px,a="b and c",d=e,otherUrl="url?auth=12345"}`;
const rendered = Markdown.render(source).trimReturns();
- expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`
`);
+ expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`
`);
});
});
diff --git a/tests/markdown/variables.test.js b/tests/markdown/variables.test.js
index 884553703..ad23c87c1 100644
--- a/tests/markdown/variables.test.js
+++ b/tests/markdown/variables.test.js
@@ -315,21 +315,21 @@ describe('Normal Links and Images', ()=>{
const source = ``;
const rendered = Markdown.render(source).trimReturns();
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(dedent`
- 
`.trimReturns());
+ 
`.trimReturns());
});
it('Renders normal images with a title', function() {
const source = 'An image !';
const rendered = Markdown.render(source).trimReturns();
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(dedent`
- An image
!
`.trimReturns());
+ An image
!
`.trimReturns());
});
it('Applies curly injectors to images', function() {
const source = `{width:100px}`;
const rendered = Markdown.render(source).trimReturns();
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(dedent`
- 
`.trimReturns());
+ 
`.trimReturns());
});
it('Renders normal links', function() {
@@ -438,25 +438,25 @@ describe('Regression Tests', ()=>{
it('Handle Extra spaces in image alt-text 1', function(){
const source='';
const rendered = Markdown.render(source).trimReturns();
- expect(rendered).toBe('
');
+ expect(rendered).toBe('
');
});
it('Handle Extra spaces in image alt-text 2', function(){
const source='';
const rendered = Markdown.render(source).trimReturns();
- expect(rendered).toBe('
');
+ expect(rendered).toBe('
');
});
it('Handle Extra spaces in image alt-text 3', function(){
const source='';
const rendered = Markdown.render(source).trimReturns();
- expect(rendered).toBe('
');
+ expect(rendered).toBe('
');
});
it('Handle Extra spaces in image alt-text 4', function(){
const source='{height=20%,width=20%}';
const rendered = Markdown.render(source).trimReturns();
- expect(rendered).toBe('
');
+ expect(rendered).toBe('
');
});
});