diff --git a/app/Services/PdfMaker/Designs/Utilities/DesignHelpers.php b/app/Services/PdfMaker/Designs/Utilities/DesignHelpers.php index 9258740c0122..3081a0c5595a 100644 --- a/app/Services/PdfMaker/Designs/Utilities/DesignHelpers.php +++ b/app/Services/PdfMaker/Designs/Utilities/DesignHelpers.php @@ -209,8 +209,14 @@ trait DesignHelpers $javascript = 'document.querySelectorAll("tbody > tr > td").forEach(t=>{if(""!==t.innerText){let e=t.getAttribute("data-ref").slice(0,-3);document.querySelector(`th[data-ref="${e}-th"]`).removeAttribute("hidden")}}),document.querySelectorAll("tbody > tr > td").forEach(t=>{let e=t.getAttribute("data-ref").slice(0,-3);(e=document.querySelector(`th[data-ref="${e}-th"]`)).hasAttribute("hidden")&&""==t.innerText&&t.setAttribute("hidden","true")});'; + // Previously we've been decoding the HTML on the backend and XML parsing isn't good options because it requires, + // strict & valid HTML to even output/decode. Decoding is now done on the frontend with this piece of Javascript. + + $html_decode = 'document.querySelectorAll(`[data-state="encoded-html"]`).forEach((element) => element.innerHTML = element.innerText)'; + return ['element' => 'div', 'elements' => [ ['element' => 'script', 'content' => $javascript], + ['element' => 'script', 'content' => $html_decode], ]]; } diff --git a/app/Services/PdfMaker/PdfMakerUtilities.php b/app/Services/PdfMaker/PdfMakerUtilities.php index d72664ac2ada..d8631d48e302 100644 --- a/app/Services/PdfMaker/PdfMakerUtilities.php +++ b/app/Services/PdfMaker/PdfMakerUtilities.php @@ -130,19 +130,14 @@ trait PdfMakerUtilities } if ($contains_html) { - // Support for injecting direct HTML into elements. - // Example: Without documentFragment(): Hello! will result: <b>Hello!</b> - // With document fragment we can evaluate HTML directly. + // If the element contains the HTML, we gonna display it as is. DOMDocument, is going to + // encode it for us, preventing any errors on the backend due processing stage. + // Later, we decode this using Javascript so it looks like it's normal HTML being injected. + // To get all elements that need frontend decoding, we use 'data-ref' property. $_child = $this->document->createElement($child['element'], ''); - - $fragment = $this->document->createDocumentFragment(); - - $fragment->appendXML( - strtr($child['content'], ['&' => '&']) - ); - - $_child->appendChild($fragment); + $_child->setAttribute('data-state', 'encoded-html'); + $_child->nodeValue = $child['content']; } else { // .. in case string doesn't contain any HTML, we'll just return // raw $content.