Updated page include logic to use blade-style tags
It will also snippets of a page if and id is provided in a tag
Showing
7 changed files
with
66 additions
and
50 deletions
| ... | @@ -156,12 +156,11 @@ class PageController extends Controller | ... | @@ -156,12 +156,11 @@ class PageController extends Controller |
| 156 | return redirect($page->getUrl()); | 156 | return redirect($page->getUrl()); |
| 157 | } | 157 | } |
| 158 | 158 | ||
| 159 | - | ||
| 160 | $this->checkOwnablePermission('page-view', $page); | 159 | $this->checkOwnablePermission('page-view', $page); |
| 161 | 160 | ||
| 162 | $pageContent = $this->entityRepo->renderPage($page); | 161 | $pageContent = $this->entityRepo->renderPage($page); |
| 163 | $sidebarTree = $this->entityRepo->getBookChildren($page->book); | 162 | $sidebarTree = $this->entityRepo->getBookChildren($page->book); |
| 164 | - $pageNav = $this->entityRepo->getPageNav($page); | 163 | + $pageNav = $this->entityRepo->getPageNav($pageContent); |
| 165 | 164 | ||
| 166 | Views::add($page); | 165 | Views::add($page); |
| 167 | $this->setPageTitle($page->getShortName()); | 166 | $this->setPageTitle($page->getShortName()); |
| ... | @@ -434,6 +433,7 @@ class PageController extends Controller | ... | @@ -434,6 +433,7 @@ class PageController extends Controller |
| 434 | { | 433 | { |
| 435 | $page = $this->entityRepo->getBySlug('page', $pageSlug, $bookSlug); | 434 | $page = $this->entityRepo->getBySlug('page', $pageSlug, $bookSlug); |
| 436 | $pdfContent = $this->exportService->pageToPdf($page); | 435 | $pdfContent = $this->exportService->pageToPdf($page); |
| 436 | +// return $pdfContent; | ||
| 437 | return response()->make($pdfContent, 200, [ | 437 | return response()->make($pdfContent, 200, [ |
| 438 | 'Content-Type' => 'application/octet-stream', | 438 | 'Content-Type' => 'application/octet-stream', |
| 439 | 'Content-Disposition' => 'attachment; filename="' . $pageSlug . '.pdf' | 439 | 'Content-Disposition' => 'attachment; filename="' . $pageSlug . '.pdf' | ... | ... |
| ... | @@ -13,7 +13,6 @@ use Carbon\Carbon; | ... | @@ -13,7 +13,6 @@ use Carbon\Carbon; |
| 13 | use DOMDocument; | 13 | use DOMDocument; |
| 14 | use DOMXPath; | 14 | use DOMXPath; |
| 15 | use Illuminate\Support\Collection; | 15 | use Illuminate\Support\Collection; |
| 16 | -use Symfony\Component\DomCrawler\Crawler; | ||
| 17 | 16 | ||
| 18 | class EntityRepo | 17 | class EntityRepo |
| 19 | { | 18 | { |
| ... | @@ -140,7 +139,7 @@ class EntityRepo | ... | @@ -140,7 +139,7 @@ class EntityRepo |
| 140 | */ | 139 | */ |
| 141 | public function getById($type, $id, $allowDrafts = false) | 140 | public function getById($type, $id, $allowDrafts = false) |
| 142 | { | 141 | { |
| 143 | - return $this->entityQuery($type, $allowDrafts)->findOrFail($id); | 142 | + return $this->entityQuery($type, $allowDrafts)->find($id); |
| 144 | } | 143 | } |
| 145 | 144 | ||
| 146 | /** | 145 | /** |
| ... | @@ -805,34 +804,42 @@ class EntityRepo | ... | @@ -805,34 +804,42 @@ class EntityRepo |
| 805 | */ | 804 | */ |
| 806 | public function renderPage(Page $page) | 805 | public function renderPage(Page $page) |
| 807 | { | 806 | { |
| 808 | - libxml_use_internal_errors(true); | 807 | + $content = $page->html; |
| 809 | - $doc = new DOMDocument(); | 808 | + $matches = []; |
| 810 | - $doc->loadHTML(mb_convert_encoding('<body>'.$page->html.'</body>', 'HTML-ENTITIES', 'UTF-8')); | 809 | + preg_match_all("/{{@\s?([0-9].*?)}}/", $content, $matches); |
| 811 | - $xpath = new DOMXpath($doc); | 810 | + if (count($matches[0]) === 0) return $content; |
| 812 | - | 811 | + |
| 813 | - $bsElems = $xpath->query('body/div[@bs-embed-page]'); | 812 | + foreach ($matches[1] as $index => $includeId) { |
| 814 | - if (is_null($bsElems)) return $page->html; | 813 | + $splitInclude = explode('#', $includeId, 2); |
| 815 | - foreach ($bsElems as $bsElem) { | 814 | + $pageId = intval($splitInclude[0]); |
| 816 | - $pageId = intval($bsElem->getAttribute('bs-embed-page')); | 815 | + if (is_nan($pageId)) continue; |
| 817 | - $embeddedPage = $this->getById('page', $pageId); | 816 | + |
| 818 | - if ($embeddedPage !== null) { | 817 | + $page = $this->getById('page', $pageId); |
| 819 | - $innerPage = $doc->createDocumentFragment(); | 818 | + if ($page === null) { |
| 820 | - $innerPage->appendXML($embeddedPage->html); | 819 | + $content = str_replace($matches[0][$index], '', $content); |
| 821 | - // Empty div then append in child content | 820 | + continue; |
| 822 | - foreach ($bsElem->childNodes as $child) { | ||
| 823 | - $bsElem->removeChild($child); | ||
| 824 | - } | ||
| 825 | - $bsElem->appendChild($innerPage); | ||
| 826 | } | 821 | } |
| 827 | - } | ||
| 828 | 822 | ||
| 829 | - $body = $doc->getElementsByTagName('body')->item(0); | 823 | + if (count($splitInclude) === 1) { |
| 830 | - $html = ''; | 824 | + $content = str_replace($matches[0][$index], $page->html, $content); |
| 831 | - foreach ($body->childNodes as $node) { | 825 | + continue; |
| 832 | - $html .= $doc->saveHTML($node); | 826 | + } |
| 827 | + | ||
| 828 | + $doc = new DOMDocument(); | ||
| 829 | + $doc->loadHTML(mb_convert_encoding('<body>'.$page->html.'</body>', 'HTML-ENTITIES', 'UTF-8')); | ||
| 830 | + $matchingElem = $doc->getElementById($splitInclude[1]); | ||
| 831 | + if ($matchingElem === null) { | ||
| 832 | + $content = str_replace($matches[0][$index], '', $content); | ||
| 833 | + continue; | ||
| 834 | + } | ||
| 835 | + $innerContent = ''; | ||
| 836 | + foreach ($matchingElem->childNodes as $childNode) { | ||
| 837 | + $innerContent .= $doc->saveHTML($childNode); | ||
| 838 | + } | ||
| 839 | + $content = str_replace($matches[0][$index], trim($innerContent), $content); | ||
| 833 | } | 840 | } |
| 834 | 841 | ||
| 835 | - return $html; | 842 | + return $content; |
| 836 | } | 843 | } |
| 837 | 844 | ||
| 838 | /** | 845 | /** |
| ... | @@ -874,15 +881,15 @@ class EntityRepo | ... | @@ -874,15 +881,15 @@ class EntityRepo |
| 874 | 881 | ||
| 875 | /** | 882 | /** |
| 876 | * Parse the headers on the page to get a navigation menu | 883 | * Parse the headers on the page to get a navigation menu |
| 877 | - * @param Page $page | 884 | + * @param String $pageContent |
| 878 | * @return array | 885 | * @return array |
| 879 | */ | 886 | */ |
| 880 | - public function getPageNav(Page $page) | 887 | + public function getPageNav($pageContent) |
| 881 | { | 888 | { |
| 882 | - if ($page->html == '') return []; | 889 | + if ($pageContent == '') return []; |
| 883 | libxml_use_internal_errors(true); | 890 | libxml_use_internal_errors(true); |
| 884 | $doc = new DOMDocument(); | 891 | $doc = new DOMDocument(); |
| 885 | - $doc->loadHTML(mb_convert_encoding($page->html, 'HTML-ENTITIES', 'UTF-8')); | 892 | + $doc->loadHTML(mb_convert_encoding($pageContent, 'HTML-ENTITIES', 'UTF-8')); |
| 886 | $xPath = new DOMXPath($doc); | 893 | $xPath = new DOMXPath($doc); |
| 887 | $headers = $xPath->query("//h1|//h2|//h3|//h4|//h5|//h6"); | 894 | $headers = $xPath->query("//h1|//h2|//h3|//h4|//h5|//h6"); |
| 888 | 895 | ... | ... |
| 1 | <?php namespace BookStack\Services; | 1 | <?php namespace BookStack\Services; |
| 2 | 2 | ||
| 3 | use BookStack\Page; | 3 | use BookStack\Page; |
| 4 | +use BookStack\Repos\EntityRepo; | ||
| 4 | 5 | ||
| 5 | class ExportService | 6 | class ExportService |
| 6 | { | 7 | { |
| 7 | 8 | ||
| 9 | + protected $entityRepo; | ||
| 10 | + | ||
| 11 | + /** | ||
| 12 | + * ExportService constructor. | ||
| 13 | + * @param $entityRepo | ||
| 14 | + */ | ||
| 15 | + public function __construct(EntityRepo $entityRepo) | ||
| 16 | + { | ||
| 17 | + $this->entityRepo = $entityRepo; | ||
| 18 | + } | ||
| 19 | + | ||
| 8 | /** | 20 | /** |
| 9 | * Convert a page to a self-contained HTML file. | 21 | * Convert a page to a self-contained HTML file. |
| 10 | * Includes required CSS & image content. Images are base64 encoded into the HTML. | 22 | * Includes required CSS & image content. Images are base64 encoded into the HTML. |
| ... | @@ -14,7 +26,7 @@ class ExportService | ... | @@ -14,7 +26,7 @@ class ExportService |
| 14 | public function pageToContainedHtml(Page $page) | 26 | public function pageToContainedHtml(Page $page) |
| 15 | { | 27 | { |
| 16 | $cssContent = file_get_contents(public_path('/css/export-styles.css')); | 28 | $cssContent = file_get_contents(public_path('/css/export-styles.css')); |
| 17 | - $pageHtml = view('pages/export', ['page' => $page, 'css' => $cssContent])->render(); | 29 | + $pageHtml = view('pages/export', ['page' => $page, 'pageContent' => $this->entityRepo->renderPage($page), 'css' => $cssContent])->render(); |
| 18 | return $this->containHtml($pageHtml); | 30 | return $this->containHtml($pageHtml); |
| 19 | } | 31 | } |
| 20 | 32 | ||
| ... | @@ -26,7 +38,8 @@ class ExportService | ... | @@ -26,7 +38,8 @@ class ExportService |
| 26 | public function pageToPdf(Page $page) | 38 | public function pageToPdf(Page $page) |
| 27 | { | 39 | { |
| 28 | $cssContent = file_get_contents(public_path('/css/export-styles.css')); | 40 | $cssContent = file_get_contents(public_path('/css/export-styles.css')); |
| 29 | - $pageHtml = view('pages/pdf', ['page' => $page, 'css' => $cssContent])->render(); | 41 | + $pageHtml = view('pages/pdf', ['page' => $page, 'pageContent' => $this->entityRepo->renderPage($page), 'css' => $cssContent])->render(); |
| 42 | +// return $pageHtml; | ||
| 30 | $useWKHTML = config('snappy.pdf.binary') !== false; | 43 | $useWKHTML = config('snappy.pdf.binary') !== false; |
| 31 | $containedHtml = $this->containHtml($pageHtml); | 44 | $containedHtml = $this->containHtml($pageHtml); |
| 32 | if ($useWKHTML) { | 45 | if ($useWKHTML) { |
| ... | @@ -59,9 +72,13 @@ class ExportService | ... | @@ -59,9 +72,13 @@ class ExportService |
| 59 | $pathString = $srcString; | 72 | $pathString = $srcString; |
| 60 | } | 73 | } |
| 61 | if ($isLocal && !file_exists($pathString)) continue; | 74 | if ($isLocal && !file_exists($pathString)) continue; |
| 62 | - $imageContent = file_get_contents($pathString); | 75 | + try { |
| 63 | - $imageEncoded = 'data:image/' . pathinfo($pathString, PATHINFO_EXTENSION) . ';base64,' . base64_encode($imageContent); | 76 | + $imageContent = file_get_contents($pathString); |
| 64 | - $newImageString = str_replace($srcString, $imageEncoded, $oldImgString); | 77 | + $imageEncoded = 'data:image/' . pathinfo($pathString, PATHINFO_EXTENSION) . ';base64,' . base64_encode($imageContent); |
| 78 | + $newImageString = str_replace($srcString, $imageEncoded, $oldImgString); | ||
| 79 | + } catch (\ErrorException $e) { | ||
| 80 | + $newImageString = ''; | ||
| 81 | + } | ||
| 65 | $htmlContent = str_replace($oldImgString, $newImageString, $htmlContent); | 82 | $htmlContent = str_replace($oldImgString, $newImageString, $htmlContent); |
| 66 | } | 83 | } |
| 67 | } | 84 | } |
| ... | @@ -88,14 +105,14 @@ class ExportService | ... | @@ -88,14 +105,14 @@ class ExportService |
| 88 | 105 | ||
| 89 | /** | 106 | /** |
| 90 | * Converts the page contents into simple plain text. | 107 | * Converts the page contents into simple plain text. |
| 91 | - * This method filters any bad looking content to | 108 | + * This method filters any bad looking content to provide a nice final output. |
| 92 | - * provide a nice final output. | ||
| 93 | * @param Page $page | 109 | * @param Page $page |
| 94 | * @return mixed | 110 | * @return mixed |
| 95 | */ | 111 | */ |
| 96 | public function pageToPlainText(Page $page) | 112 | public function pageToPlainText(Page $page) |
| 97 | { | 113 | { |
| 98 | - $text = $page->text; | 114 | + $html = $this->entityRepo->renderPage($page); |
| 115 | + $text = strip_tags($html); | ||
| 99 | // Replace multiple spaces with single spaces | 116 | // Replace multiple spaces with single spaces |
| 100 | $text = preg_replace('/\ {2,}/', ' ', $text); | 117 | $text = preg_replace('/\ {2,}/', ' ', $text); |
| 101 | // Reduce multiple horrid whitespace characters. | 118 | // Reduce multiple horrid whitespace characters. | ... | ... |
| ... | @@ -136,9 +136,6 @@ | ... | @@ -136,9 +136,6 @@ |
| 136 | background-color: #EEE; | 136 | background-color: #EEE; |
| 137 | padding: $-s; | 137 | padding: $-s; |
| 138 | display: block; | 138 | display: block; |
| 139 | - > * { | ||
| 140 | - display: inline-block; | ||
| 141 | - } | ||
| 142 | &:before { | 139 | &:before { |
| 143 | font-family: 'Material-Design-Iconic-Font'; | 140 | font-family: 'Material-Design-Iconic-Font'; |
| 144 | padding-right: $-s; | 141 | padding-right: $-s; | ... | ... |
| ... | @@ -70,9 +70,6 @@ body.flexbox-support #entity-selector-wrap .popup-body .form-group { | ... | @@ -70,9 +70,6 @@ body.flexbox-support #entity-selector-wrap .popup-body .form-group { |
| 70 | #entity-selector-wrap .popup-body .form-group { | 70 | #entity-selector-wrap .popup-body .form-group { |
| 71 | margin: 0; | 71 | margin: 0; |
| 72 | } | 72 | } |
| 73 | -//body.ie #entity-selector-wrap .popup-body .form-group { | ||
| 74 | -// min-height: 60vh; | ||
| 75 | -//} | ||
| 76 | 73 | ||
| 77 | .image-manager-body { | 74 | .image-manager-body { |
| 78 | min-height: 70vh; | 75 | min-height: 70vh; | ... | ... |
-
Please register or sign in to post a comment