Dan Brown

Added plaintext & basic PDF page Export

...@@ -226,13 +226,22 @@ class PageController extends Controller ...@@ -226,13 +226,22 @@ class PageController extends Controller
226 return redirect($page->getUrl()); 226 return redirect($page->getUrl());
227 } 227 }
228 228
229 + /**
230 + * Exports a page to pdf format using barryvdh/laravel-dompdf wrapper.
231 + * https://github.com/barryvdh/laravel-dompdf
232 + * @param $bookSlug
233 + * @param $pageSlug
234 + * @return \Illuminate\Http\Response
235 + */
229 public function exportPdf($bookSlug, $pageSlug) 236 public function exportPdf($bookSlug, $pageSlug)
230 { 237 {
231 $book = $this->bookRepo->getBySlug($bookSlug); 238 $book = $this->bookRepo->getBySlug($bookSlug);
232 $page = $this->pageRepo->getBySlug($pageSlug, $book->id); 239 $page = $this->pageRepo->getBySlug($pageSlug, $book->id);
233 - $cssContent = file_get_contents(public_path('/css/styles.css')); 240 + $pdfContent = $this->exportService->pageToPdf($page);
234 - 241 + return response()->make($pdfContent, 200, [
235 - return $pdf->download($pageSlug . '.pdf'); 242 + 'Content-Type' => 'application/octet-stream',
243 + 'Content-Disposition' => 'attachment; filename="'.$pageSlug.'.pdf'
244 + ]);
236 } 245 }
237 246
238 /** 247 /**
...@@ -251,4 +260,22 @@ class PageController extends Controller ...@@ -251,4 +260,22 @@ class PageController extends Controller
251 'Content-Disposition' => 'attachment; filename="'.$pageSlug.'.html' 260 'Content-Disposition' => 'attachment; filename="'.$pageSlug.'.html'
252 ]); 261 ]);
253 } 262 }
263 +
264 + /**
265 + * Export a page to a simple plaintext .txt file.
266 + * @param $bookSlug
267 + * @param $pageSlug
268 + * @return \Illuminate\Http\Response
269 + */
270 + public function exportPlainText($bookSlug, $pageSlug)
271 + {
272 + $book = $this->bookRepo->getBySlug($bookSlug);
273 + $page = $this->pageRepo->getBySlug($pageSlug, $book->id);
274 + $containedHtml = $this->exportService->pageToPlainText($page);
275 + return response()->make($containedHtml, 200, [
276 + 'Content-Type' => 'application/octet-stream',
277 + 'Content-Disposition' => 'attachment; filename="'.$pageSlug.'.txt'
278 + ]);
279 + }
280 +
254 } 281 }
......
...@@ -24,6 +24,7 @@ Route::group(['middleware' => 'auth'], function () { ...@@ -24,6 +24,7 @@ Route::group(['middleware' => 'auth'], function () {
24 Route::get('/{bookSlug}/page/{pageSlug}', 'PageController@show'); 24 Route::get('/{bookSlug}/page/{pageSlug}', 'PageController@show');
25 Route::get('/{bookSlug}/page/{pageSlug}/export/pdf', 'PageController@exportPdf'); 25 Route::get('/{bookSlug}/page/{pageSlug}/export/pdf', 'PageController@exportPdf');
26 Route::get('/{bookSlug}/page/{pageSlug}/export/html', 'PageController@exportHtml'); 26 Route::get('/{bookSlug}/page/{pageSlug}/export/html', 'PageController@exportHtml');
27 + Route::get('/{bookSlug}/page/{pageSlug}/export/plaintext', 'PageController@exportPlainText');
27 Route::get('/{bookSlug}/page/{pageSlug}/edit', 'PageController@edit'); 28 Route::get('/{bookSlug}/page/{pageSlug}/edit', 'PageController@edit');
28 Route::get('/{bookSlug}/page/{pageSlug}/delete', 'PageController@showDelete'); 29 Route::get('/{bookSlug}/page/{pageSlug}/delete', 'PageController@showDelete');
29 Route::put('/{bookSlug}/page/{pageSlug}', 'PageController@update'); 30 Route::put('/{bookSlug}/page/{pageSlug}', 'PageController@update');
...@@ -46,7 +47,6 @@ Route::group(['middleware' => 'auth'], function () { ...@@ -46,7 +47,6 @@ Route::group(['middleware' => 'auth'], function () {
46 47
47 }); 48 });
48 49
49 -
50 // Users 50 // Users
51 Route::get('/users', 'UserController@index'); 51 Route::get('/users', 'UserController@index');
52 Route::get('/users/create', 'UserController@create'); 52 Route::get('/users/create', 'UserController@create');
......
...@@ -6,7 +6,6 @@ use BookStack\Page; ...@@ -6,7 +6,6 @@ use BookStack\Page;
6 class ExportService 6 class ExportService
7 { 7 {
8 8
9 -
10 /** 9 /**
11 * Convert a page to a self-contained HTML file. 10 * Convert a page to a self-contained HTML file.
12 * Includes required CSS & image content. Images are base64 encoded into the HTML. 11 * Includes required CSS & image content. Images are base64 encoded into the HTML.
...@@ -16,10 +15,33 @@ class ExportService ...@@ -16,10 +15,33 @@ class ExportService
16 public function pageToContainedHtml(Page $page) 15 public function pageToContainedHtml(Page $page)
17 { 16 {
18 $cssContent = file_get_contents(public_path('/css/export-styles.css')); 17 $cssContent = file_get_contents(public_path('/css/export-styles.css'));
18 + $pageHtml = view('pages/export', ['page' => $page, 'css' => $cssContent])->render();
19 + return $this->containHtml($pageHtml);
20 + }
21 +
22 + /**
23 + * Convert a page to a pdf file.
24 + * @param Page $page
25 + * @return mixed|string
26 + */
27 + public function pageToPdf(Page $page)
28 + {
29 + $cssContent = file_get_contents(public_path('/css/export-styles.css'));
19 $pageHtml = view('pages/pdf', ['page' => $page, 'css' => $cssContent])->render(); 30 $pageHtml = view('pages/pdf', ['page' => $page, 'css' => $cssContent])->render();
31 + $containedHtml = $this->containHtml($pageHtml);
32 + $pdf = \PDF::loadHTML($containedHtml);
33 + return $pdf->output();
34 + }
20 35
36 + /**
37 + * Bundle of the contents of a html file to be self-contained.
38 + * @param $htmlContent
39 + * @return mixed|string
40 + */
41 + protected function containHtml($htmlContent)
42 + {
21 $imageTagsOutput = []; 43 $imageTagsOutput = [];
22 - preg_match_all("/\<img.*src\=(\'|\")(.*?)(\'|\").*?\>/i", $pageHtml, $imageTagsOutput); 44 + preg_match_all("/\<img.*src\=(\'|\")(.*?)(\'|\").*?\>/i", $htmlContent, $imageTagsOutput);
23 45
24 // Replace image src with base64 encoded image strings 46 // Replace image src with base64 encoded image strings
25 if (isset($imageTagsOutput[0]) && count($imageTagsOutput[0]) > 0) { 47 if (isset($imageTagsOutput[0]) && count($imageTagsOutput[0]) > 0) {
...@@ -34,12 +56,12 @@ class ExportService ...@@ -34,12 +56,12 @@ class ExportService
34 $imageContent = file_get_contents($pathString); 56 $imageContent = file_get_contents($pathString);
35 $imageEncoded = 'data:image/' . pathinfo($pathString, PATHINFO_EXTENSION) . ';base64,' . base64_encode($imageContent); 57 $imageEncoded = 'data:image/' . pathinfo($pathString, PATHINFO_EXTENSION) . ';base64,' . base64_encode($imageContent);
36 $newImageString = str_replace($srcString, $imageEncoded, $oldImgString); 58 $newImageString = str_replace($srcString, $imageEncoded, $oldImgString);
37 - $pageHtml = str_replace($oldImgString, $newImageString, $pageHtml); 59 + $htmlContent = str_replace($oldImgString, $newImageString, $htmlContent);
38 } 60 }
39 } 61 }
40 62
41 $linksOutput = []; 63 $linksOutput = [];
42 - preg_match_all("/\<a.*href\=(\'|\")(.*?)(\'|\").*?\>/i", $pageHtml, $linksOutput); 64 + preg_match_all("/\<a.*href\=(\'|\")(.*?)(\'|\").*?\>/i", $htmlContent, $linksOutput);
43 65
44 // Replace image src with base64 encoded image strings 66 // Replace image src with base64 encoded image strings
45 if (isset($linksOutput[0]) && count($linksOutput[0]) > 0) { 67 if (isset($linksOutput[0]) && count($linksOutput[0]) > 0) {
...@@ -49,13 +71,45 @@ class ExportService ...@@ -49,13 +71,45 @@ class ExportService
49 if (strpos(trim($srcString), 'http') !== 0) { 71 if (strpos(trim($srcString), 'http') !== 0) {
50 $newSrcString = url($srcString); 72 $newSrcString = url($srcString);
51 $newLinkString = str_replace($srcString, $newSrcString, $oldLinkString); 73 $newLinkString = str_replace($srcString, $newSrcString, $oldLinkString);
52 - $pageHtml = str_replace($oldLinkString, $newLinkString, $pageHtml); 74 + $htmlContent = str_replace($oldLinkString, $newLinkString, $htmlContent);
53 } 75 }
54 } 76 }
55 } 77 }
56 78
57 // Replace any relative links with system domain 79 // Replace any relative links with system domain
58 - return $pageHtml; 80 + return $htmlContent;
81 + }
82 +
83 + /**
84 + * Converts the page contents into simple plain text.
85 + * This method filters any bad looking content to
86 + * provide a nice final output.
87 + * @param Page $page
88 + * @return mixed
89 + */
90 + public function pageToPlainText(Page $page)
91 + {
92 + $text = $page->text;
93 + // Replace multiple spaces with single spaces
94 + $text = preg_replace('/\ {2,}/', ' ', $text);
95 + // Reduce multiple horrid whitespace characters.
96 + $text = preg_replace('/(\x0A|\xA0|\x0A|\r|\n){2,}/su', "\n\n", $text);
97 + $text = html_entity_decode($text);
98 + // Add title
99 + $text = $page->name . "\n\n" . $text;
100 + return $text;
59 } 101 }
60 102
61 -}
...\ No newline at end of file ...\ No newline at end of file
103 +}
104 +
105 +
106 +
107 +
108 +
109 +
110 +
111 +
112 +
113 +
114 +
115 +
......
...@@ -11,7 +11,8 @@ ...@@ -11,7 +11,8 @@
11 "laravel/socialite": "^2.0", 11 "laravel/socialite": "^2.0",
12 "barryvdh/laravel-ide-helper": "^2.1", 12 "barryvdh/laravel-ide-helper": "^2.1",
13 "barryvdh/laravel-debugbar": "^2.0", 13 "barryvdh/laravel-debugbar": "^2.0",
14 - "league/flysystem-aws-s3-v3": "^1.0" 14 + "league/flysystem-aws-s3-v3": "^1.0",
15 + "barryvdh/laravel-dompdf": "0.6.*"
15 }, 16 },
16 "require-dev": { 17 "require-dev": {
17 "fzaninotto/faker": "~1.4", 18 "fzaninotto/faker": "~1.4",
......
...@@ -4,21 +4,21 @@ ...@@ -4,21 +4,21 @@
4 "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", 4 "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
5 "This file is @generated automatically" 5 "This file is @generated automatically"
6 ], 6 ],
7 - "hash": "1ca2bc3308d193a556124513e1f57106", 7 + "hash": "523e654de96df9259fa5dfcb583d6e3e",
8 - "content-hash": "99d01bead4e1ead29f826cd7eae234ea", 8 + "content-hash": "74b5601c253aab71cf55e0885f31ae7f",
9 "packages": [ 9 "packages": [
10 { 10 {
11 "name": "aws/aws-sdk-php", 11 "name": "aws/aws-sdk-php",
12 - "version": "3.13.1", 12 + "version": "3.14.2",
13 "source": { 13 "source": {
14 "type": "git", 14 "type": "git",
15 "url": "https://github.com/aws/aws-sdk-php.git", 15 "url": "https://github.com/aws/aws-sdk-php.git",
16 - "reference": "cc1796d1c21146cdcbfb7628aee816acb7b85e09" 16 + "reference": "2970cb63e7b7b37dd8c07a4fa4e4e18a110ed4e2"
17 }, 17 },
18 "dist": { 18 "dist": {
19 "type": "zip", 19 "type": "zip",
20 - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/cc1796d1c21146cdcbfb7628aee816acb7b85e09", 20 + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/2970cb63e7b7b37dd8c07a4fa4e4e18a110ed4e2",
21 - "reference": "cc1796d1c21146cdcbfb7628aee816acb7b85e09", 21 + "reference": "2970cb63e7b7b37dd8c07a4fa4e4e18a110ed4e2",
22 "shasum": "" 22 "shasum": ""
23 }, 23 },
24 "require": { 24 "require": {
...@@ -84,7 +84,7 @@ ...@@ -84,7 +84,7 @@
84 "s3", 84 "s3",
85 "sdk" 85 "sdk"
86 ], 86 ],
87 - "time": "2016-01-19 22:46:22" 87 + "time": "2016-01-28 21:33:18"
88 }, 88 },
89 { 89 {
90 "name": "barryvdh/laravel-debugbar", 90 "name": "barryvdh/laravel-debugbar",
...@@ -141,6 +141,54 @@ ...@@ -141,6 +141,54 @@
141 "time": "2015-12-22 06:22:38" 141 "time": "2015-12-22 06:22:38"
142 }, 142 },
143 { 143 {
144 + "name": "barryvdh/laravel-dompdf",
145 + "version": "v0.6.1",
146 + "source": {
147 + "type": "git",
148 + "url": "https://github.com/barryvdh/laravel-dompdf.git",
149 + "reference": "b606788108833f7765801dca35455fb23ce9f869"
150 + },
151 + "dist": {
152 + "type": "zip",
153 + "url": "https://api.github.com/repos/barryvdh/laravel-dompdf/zipball/b606788108833f7765801dca35455fb23ce9f869",
154 + "reference": "b606788108833f7765801dca35455fb23ce9f869",
155 + "shasum": ""
156 + },
157 + "require": {
158 + "dompdf/dompdf": "0.6.*",
159 + "illuminate/support": "5.0.x|5.1.x|5.2.x",
160 + "php": ">=5.4.0"
161 + },
162 + "type": "library",
163 + "extra": {
164 + "branch-alias": {
165 + "dev-master": "0.6-dev"
166 + }
167 + },
168 + "autoload": {
169 + "psr-4": {
170 + "Barryvdh\\DomPDF\\": "src"
171 + }
172 + },
173 + "notification-url": "https://packagist.org/downloads/",
174 + "license": [
175 + "MIT"
176 + ],
177 + "authors": [
178 + {
179 + "name": "Barry vd. Heuvel",
180 + "email": "barryvdh@gmail.com"
181 + }
182 + ],
183 + "description": "A DOMPDF Wrapper for Laravel",
184 + "keywords": [
185 + "dompdf",
186 + "laravel",
187 + "pdf"
188 + ],
189 + "time": "2015-12-21 19:51:22"
190 + },
191 + {
144 "name": "barryvdh/laravel-ide-helper", 192 "name": "barryvdh/laravel-ide-helper",
145 "version": "v2.1.2", 193 "version": "v2.1.2",
146 "source": { 194 "source": {
...@@ -358,6 +406,47 @@ ...@@ -358,6 +406,47 @@
358 "time": "2015-11-06 14:35:42" 406 "time": "2015-11-06 14:35:42"
359 }, 407 },
360 { 408 {
409 + "name": "dompdf/dompdf",
410 + "version": "v0.6.2",
411 + "source": {
412 + "type": "git",
413 + "url": "https://github.com/dompdf/dompdf.git",
414 + "reference": "cc06008f75262510ee135b8cbb14e333a309f651"
415 + },
416 + "dist": {
417 + "type": "zip",
418 + "url": "https://api.github.com/repos/dompdf/dompdf/zipball/cc06008f75262510ee135b8cbb14e333a309f651",
419 + "reference": "cc06008f75262510ee135b8cbb14e333a309f651",
420 + "shasum": ""
421 + },
422 + "require": {
423 + "phenx/php-font-lib": "0.2.*"
424 + },
425 + "type": "library",
426 + "autoload": {
427 + "classmap": [
428 + "include/"
429 + ]
430 + },
431 + "notification-url": "https://packagist.org/downloads/",
432 + "license": [
433 + "LGPL"
434 + ],
435 + "authors": [
436 + {
437 + "name": "Fabien Ménager",
438 + "email": "fabien.menager@gmail.com"
439 + },
440 + {
441 + "name": "Brian Sweeney",
442 + "email": "eclecticgeek@gmail.com"
443 + }
444 + ],
445 + "description": "DOMPDF is a CSS 2.1 compliant HTML to PDF converter",
446 + "homepage": "https://github.com/dompdf/dompdf",
447 + "time": "2015-12-07 04:07:13"
448 + },
449 + {
361 "name": "guzzle/guzzle", 450 "name": "guzzle/guzzle",
362 "version": "v3.8.1", 451 "version": "v3.8.1",
363 "source": { 452 "source": {
...@@ -564,16 +653,16 @@ ...@@ -564,16 +653,16 @@
564 }, 653 },
565 { 654 {
566 "name": "guzzlehttp/psr7", 655 "name": "guzzlehttp/psr7",
567 - "version": "1.2.1", 656 + "version": "1.2.2",
568 "source": { 657 "source": {
569 "type": "git", 658 "type": "git",
570 "url": "https://github.com/guzzle/psr7.git", 659 "url": "https://github.com/guzzle/psr7.git",
571 - "reference": "4d0bdbe1206df7440219ce14c972aa57cc5e4982" 660 + "reference": "f5d04bdd2881ac89abde1fb78cc234bce24327bb"
572 }, 661 },
573 "dist": { 662 "dist": {
574 "type": "zip", 663 "type": "zip",
575 - "url": "https://api.github.com/repos/guzzle/psr7/zipball/4d0bdbe1206df7440219ce14c972aa57cc5e4982", 664 + "url": "https://api.github.com/repos/guzzle/psr7/zipball/f5d04bdd2881ac89abde1fb78cc234bce24327bb",
576 - "reference": "4d0bdbe1206df7440219ce14c972aa57cc5e4982", 665 + "reference": "f5d04bdd2881ac89abde1fb78cc234bce24327bb",
577 "shasum": "" 666 "shasum": ""
578 }, 667 },
579 "require": { 668 "require": {
...@@ -618,7 +707,7 @@ ...@@ -618,7 +707,7 @@
618 "stream", 707 "stream",
619 "uri" 708 "uri"
620 ], 709 ],
621 - "time": "2015-11-03 01:34:55" 710 + "time": "2016-01-23 01:23:02"
622 }, 711 },
623 { 712 {
624 "name": "intervention/image", 713 "name": "intervention/image",
...@@ -829,16 +918,16 @@ ...@@ -829,16 +918,16 @@
829 }, 918 },
830 { 919 {
831 "name": "laravel/framework", 920 "name": "laravel/framework",
832 - "version": "v5.2.10", 921 + "version": "v5.2.12",
833 "source": { 922 "source": {
834 "type": "git", 923 "type": "git",
835 "url": "https://github.com/laravel/framework.git", 924 "url": "https://github.com/laravel/framework.git",
836 - "reference": "93dc5b0089eef468157fd7200e575c3861ec59a5" 925 + "reference": "6b6255ad7bfbdb721b8d00b09d52b146c5d363d7"
837 }, 926 },
838 "dist": { 927 "dist": {
839 "type": "zip", 928 "type": "zip",
840 - "url": "https://api.github.com/repos/laravel/framework/zipball/93dc5b0089eef468157fd7200e575c3861ec59a5", 929 + "url": "https://api.github.com/repos/laravel/framework/zipball/6b6255ad7bfbdb721b8d00b09d52b146c5d363d7",
841 - "reference": "93dc5b0089eef468157fd7200e575c3861ec59a5", 930 + "reference": "6b6255ad7bfbdb721b8d00b09d52b146c5d363d7",
842 "shasum": "" 931 "shasum": ""
843 }, 932 },
844 "require": { 933 "require": {
...@@ -953,7 +1042,7 @@ ...@@ -953,7 +1042,7 @@
953 "framework", 1042 "framework",
954 "laravel" 1043 "laravel"
955 ], 1044 ],
956 - "time": "2016-01-13 20:29:10" 1045 + "time": "2016-01-26 04:15:37"
957 }, 1046 },
958 { 1047 {
959 "name": "laravel/socialite", 1048 "name": "laravel/socialite",
...@@ -1343,23 +1432,23 @@ ...@@ -1343,23 +1432,23 @@
1343 }, 1432 },
1344 { 1433 {
1345 "name": "mtdowling/cron-expression", 1434 "name": "mtdowling/cron-expression",
1346 - "version": "v1.0.4", 1435 + "version": "v1.1.0",
1347 "source": { 1436 "source": {
1348 "type": "git", 1437 "type": "git",
1349 "url": "https://github.com/mtdowling/cron-expression.git", 1438 "url": "https://github.com/mtdowling/cron-expression.git",
1350 - "reference": "fd92e883195e5dfa77720b1868cf084b08be4412" 1439 + "reference": "c9ee7886f5a12902b225a1a12f36bb45f9ab89e5"
1351 }, 1440 },
1352 "dist": { 1441 "dist": {
1353 "type": "zip", 1442 "type": "zip",
1354 - "url": "https://api.github.com/repos/mtdowling/cron-expression/zipball/fd92e883195e5dfa77720b1868cf084b08be4412", 1443 + "url": "https://api.github.com/repos/mtdowling/cron-expression/zipball/c9ee7886f5a12902b225a1a12f36bb45f9ab89e5",
1355 - "reference": "fd92e883195e5dfa77720b1868cf084b08be4412", 1444 + "reference": "c9ee7886f5a12902b225a1a12f36bb45f9ab89e5",
1356 "shasum": "" 1445 "shasum": ""
1357 }, 1446 },
1358 "require": { 1447 "require": {
1359 "php": ">=5.3.2" 1448 "php": ">=5.3.2"
1360 }, 1449 },
1361 "require-dev": { 1450 "require-dev": {
1362 - "phpunit/phpunit": "4.*" 1451 + "phpunit/phpunit": "~4.0|~5.0"
1363 }, 1452 },
1364 "type": "library", 1453 "type": "library",
1365 "autoload": { 1454 "autoload": {
...@@ -1383,7 +1472,7 @@ ...@@ -1383,7 +1472,7 @@
1383 "cron", 1472 "cron",
1384 "schedule" 1473 "schedule"
1385 ], 1474 ],
1386 - "time": "2015-01-11 23:07:46" 1475 + "time": "2016-01-26 21:23:30"
1387 }, 1476 },
1388 { 1477 {
1389 "name": "mtdowling/jmespath.php", 1478 "name": "mtdowling/jmespath.php",
...@@ -1540,16 +1629,16 @@ ...@@ -1540,16 +1629,16 @@
1540 }, 1629 },
1541 { 1630 {
1542 "name": "paragonie/random_compat", 1631 "name": "paragonie/random_compat",
1543 - "version": "1.1.5", 1632 + "version": "1.1.6",
1544 "source": { 1633 "source": {
1545 "type": "git", 1634 "type": "git",
1546 "url": "https://github.com/paragonie/random_compat.git", 1635 "url": "https://github.com/paragonie/random_compat.git",
1547 - "reference": "dd8998b7c846f6909f4e7a5f67fabebfc412a4f7" 1636 + "reference": "e6f80ab77885151908d0ec743689ca700886e8b0"
1548 }, 1637 },
1549 "dist": { 1638 "dist": {
1550 "type": "zip", 1639 "type": "zip",
1551 - "url": "https://api.github.com/repos/paragonie/random_compat/zipball/dd8998b7c846f6909f4e7a5f67fabebfc412a4f7", 1640 + "url": "https://api.github.com/repos/paragonie/random_compat/zipball/e6f80ab77885151908d0ec743689ca700886e8b0",
1552 - "reference": "dd8998b7c846f6909f4e7a5f67fabebfc412a4f7", 1641 + "reference": "e6f80ab77885151908d0ec743689ca700886e8b0",
1553 "shasum": "" 1642 "shasum": ""
1554 }, 1643 },
1555 "require": { 1644 "require": {
...@@ -1584,7 +1673,41 @@ ...@@ -1584,7 +1673,41 @@
1584 "pseudorandom", 1673 "pseudorandom",
1585 "random" 1674 "random"
1586 ], 1675 ],
1587 - "time": "2016-01-06 13:31:20" 1676 + "time": "2016-01-29 16:19:52"
1677 + },
1678 + {
1679 + "name": "phenx/php-font-lib",
1680 + "version": "0.2.2",
1681 + "source": {
1682 + "type": "git",
1683 + "url": "https://github.com/PhenX/php-font-lib.git",
1684 + "reference": "c30c7fc00a6b0d863e9bb4c5d5dd015298b2dc82"
1685 + },
1686 + "dist": {
1687 + "type": "zip",
1688 + "url": "https://api.github.com/repos/PhenX/php-font-lib/zipball/c30c7fc00a6b0d863e9bb4c5d5dd015298b2dc82",
1689 + "reference": "c30c7fc00a6b0d863e9bb4c5d5dd015298b2dc82",
1690 + "shasum": ""
1691 + },
1692 + "type": "library",
1693 + "autoload": {
1694 + "classmap": [
1695 + "classes/"
1696 + ]
1697 + },
1698 + "notification-url": "https://packagist.org/downloads/",
1699 + "license": [
1700 + "LGPL"
1701 + ],
1702 + "authors": [
1703 + {
1704 + "name": "Fabien Ménager",
1705 + "email": "fabien.menager@gmail.com"
1706 + }
1707 + ],
1708 + "description": "A library to read, parse, export and make subsets of different types of font files.",
1709 + "homepage": "https://github.com/PhenX/php-font-lib",
1710 + "time": "2014-02-01 15:22:28"
1588 }, 1711 },
1589 { 1712 {
1590 "name": "phpdocumentor/reflection-docblock", 1713 "name": "phpdocumentor/reflection-docblock",
...@@ -2261,16 +2384,16 @@ ...@@ -2261,16 +2384,16 @@
2261 }, 2384 },
2262 { 2385 {
2263 "name": "symfony/polyfill-mbstring", 2386 "name": "symfony/polyfill-mbstring",
2264 - "version": "v1.0.1", 2387 + "version": "v1.1.0",
2265 "source": { 2388 "source": {
2266 "type": "git", 2389 "type": "git",
2267 "url": "https://github.com/symfony/polyfill-mbstring.git", 2390 "url": "https://github.com/symfony/polyfill-mbstring.git",
2268 - "reference": "49ff736bd5d41f45240cec77b44967d76e0c3d25" 2391 + "reference": "1289d16209491b584839022f29257ad859b8532d"
2269 }, 2392 },
2270 "dist": { 2393 "dist": {
2271 "type": "zip", 2394 "type": "zip",
2272 - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/49ff736bd5d41f45240cec77b44967d76e0c3d25", 2395 + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/1289d16209491b584839022f29257ad859b8532d",
2273 - "reference": "49ff736bd5d41f45240cec77b44967d76e0c3d25", 2396 + "reference": "1289d16209491b584839022f29257ad859b8532d",
2274 "shasum": "" 2397 "shasum": ""
2275 }, 2398 },
2276 "require": { 2399 "require": {
...@@ -2282,7 +2405,7 @@ ...@@ -2282,7 +2405,7 @@
2282 "type": "library", 2405 "type": "library",
2283 "extra": { 2406 "extra": {
2284 "branch-alias": { 2407 "branch-alias": {
2285 - "dev-master": "1.0-dev" 2408 + "dev-master": "1.1-dev"
2286 } 2409 }
2287 }, 2410 },
2288 "autoload": { 2411 "autoload": {
...@@ -2316,20 +2439,20 @@ ...@@ -2316,20 +2439,20 @@
2316 "portable", 2439 "portable",
2317 "shim" 2440 "shim"
2318 ], 2441 ],
2319 - "time": "2015-11-20 09:19:13" 2442 + "time": "2016-01-20 09:13:37"
2320 }, 2443 },
2321 { 2444 {
2322 "name": "symfony/polyfill-php56", 2445 "name": "symfony/polyfill-php56",
2323 - "version": "v1.0.1", 2446 + "version": "v1.1.0",
2324 "source": { 2447 "source": {
2325 "type": "git", 2448 "type": "git",
2326 "url": "https://github.com/symfony/polyfill-php56.git", 2449 "url": "https://github.com/symfony/polyfill-php56.git",
2327 - "reference": "e2e77609a9e2328eb370fbb0e0d8b2000ebb488f" 2450 + "reference": "4d891fff050101a53a4caabb03277284942d1ad9"
2328 }, 2451 },
2329 "dist": { 2452 "dist": {
2330 "type": "zip", 2453 "type": "zip",
2331 - "url": "https://api.github.com/repos/symfony/polyfill-php56/zipball/e2e77609a9e2328eb370fbb0e0d8b2000ebb488f", 2454 + "url": "https://api.github.com/repos/symfony/polyfill-php56/zipball/4d891fff050101a53a4caabb03277284942d1ad9",
2332 - "reference": "e2e77609a9e2328eb370fbb0e0d8b2000ebb488f", 2455 + "reference": "4d891fff050101a53a4caabb03277284942d1ad9",
2333 "shasum": "" 2456 "shasum": ""
2334 }, 2457 },
2335 "require": { 2458 "require": {
...@@ -2339,7 +2462,7 @@ ...@@ -2339,7 +2462,7 @@
2339 "type": "library", 2462 "type": "library",
2340 "extra": { 2463 "extra": {
2341 "branch-alias": { 2464 "branch-alias": {
2342 - "dev-master": "1.0-dev" 2465 + "dev-master": "1.1-dev"
2343 } 2466 }
2344 }, 2467 },
2345 "autoload": { 2468 "autoload": {
...@@ -2372,20 +2495,20 @@ ...@@ -2372,20 +2495,20 @@
2372 "portable", 2495 "portable",
2373 "shim" 2496 "shim"
2374 ], 2497 ],
2375 - "time": "2015-12-18 15:10:25" 2498 + "time": "2016-01-20 09:13:37"
2376 }, 2499 },
2377 { 2500 {
2378 "name": "symfony/polyfill-util", 2501 "name": "symfony/polyfill-util",
2379 - "version": "v1.0.1", 2502 + "version": "v1.1.0",
2380 "source": { 2503 "source": {
2381 "type": "git", 2504 "type": "git",
2382 "url": "https://github.com/symfony/polyfill-util.git", 2505 "url": "https://github.com/symfony/polyfill-util.git",
2383 - "reference": "4271c55cbc0a77b2641f861b978123e46b3da969" 2506 + "reference": "8de62801aa12bc4dfcf85eef5d21981ae7bb3cc4"
2384 }, 2507 },
2385 "dist": { 2508 "dist": {
2386 "type": "zip", 2509 "type": "zip",
2387 - "url": "https://api.github.com/repos/symfony/polyfill-util/zipball/4271c55cbc0a77b2641f861b978123e46b3da969", 2510 + "url": "https://api.github.com/repos/symfony/polyfill-util/zipball/8de62801aa12bc4dfcf85eef5d21981ae7bb3cc4",
2388 - "reference": "4271c55cbc0a77b2641f861b978123e46b3da969", 2511 + "reference": "8de62801aa12bc4dfcf85eef5d21981ae7bb3cc4",
2389 "shasum": "" 2512 "shasum": ""
2390 }, 2513 },
2391 "require": { 2514 "require": {
...@@ -2394,7 +2517,7 @@ ...@@ -2394,7 +2517,7 @@
2394 "type": "library", 2517 "type": "library",
2395 "extra": { 2518 "extra": {
2396 "branch-alias": { 2519 "branch-alias": {
2397 - "dev-master": "1.0-dev" 2520 + "dev-master": "1.1-dev"
2398 } 2521 }
2399 }, 2522 },
2400 "autoload": { 2523 "autoload": {
...@@ -2424,7 +2547,7 @@ ...@@ -2424,7 +2547,7 @@
2424 "polyfill", 2547 "polyfill",
2425 "shim" 2548 "shim"
2426 ], 2549 ],
2427 - "time": "2015-11-04 20:28:58" 2550 + "time": "2016-01-20 09:13:37"
2428 }, 2551 },
2429 { 2552 {
2430 "name": "symfony/process", 2553 "name": "symfony/process",
......
...@@ -143,6 +143,7 @@ return [ ...@@ -143,6 +143,7 @@ return [
143 * Third Party 143 * Third Party
144 */ 144 */
145 Intervention\Image\ImageServiceProvider::class, 145 Intervention\Image\ImageServiceProvider::class,
146 + Barryvdh\DomPDF\ServiceProvider::class,
146 Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider::class, 147 Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider::class,
147 Barryvdh\Debugbar\ServiceProvider::class, 148 Barryvdh\Debugbar\ServiceProvider::class,
148 149
...@@ -210,6 +211,7 @@ return [ ...@@ -210,6 +211,7 @@ return [
210 */ 211 */
211 212
212 'ImageTool' => Intervention\Image\Facades\Image::class, 213 'ImageTool' => Intervention\Image\Facades\Image::class,
214 + 'PDF' => Barryvdh\DomPDF\Facade::class,
213 'Debugbar' => Barryvdh\Debugbar\Facade::class, 215 'Debugbar' => Barryvdh\Debugbar\Facade::class,
214 216
215 /** 217 /**
......
1 +<?php
2 +
3 +return array(
4 +
5 + /*
6 + |--------------------------------------------------------------------------
7 + | Settings
8 + |--------------------------------------------------------------------------
9 + |
10 + | Set some default values. It is possible to add all defines that can be set
11 + | in dompdf_config.inc.php. You can also override the entire config file.
12 + |
13 + */
14 + 'show_warnings' => false, // Throw an Exception on warnings from dompdf
15 + 'orientation' => 'portrait',
16 + 'defines' => array(
17 + /**
18 + * The location of the DOMPDF font directory
19 + *
20 + * The location of the directory where DOMPDF will store fonts and font metrics
21 + * Note: This directory must exist and be writable by the webserver process.
22 + * *Please note the trailing slash.*
23 + *
24 + * Notes regarding fonts:
25 + * Additional .afm font metrics can be added by executing load_font.php from command line.
26 + *
27 + * Only the original "Base 14 fonts" are present on all pdf viewers. Additional fonts must
28 + * be embedded in the pdf file or the PDF may not display correctly. This can significantly
29 + * increase file size unless font subsetting is enabled. Before embedding a font please
30 + * review your rights under the font license.
31 + *
32 + * Any font specification in the source HTML is translated to the closest font available
33 + * in the font directory.
34 + *
35 + * The pdf standard "Base 14 fonts" are:
36 + * Courier, Courier-Bold, Courier-BoldOblique, Courier-Oblique,
37 + * Helvetica, Helvetica-Bold, Helvetica-BoldOblique, Helvetica-Oblique,
38 + * Times-Roman, Times-Bold, Times-BoldItalic, Times-Italic,
39 + * Symbol, ZapfDingbats.
40 + */
41 + "DOMPDF_FONT_DIR" => app_path('vendor/dompdf/dompdf/lib/fonts/'), //storage_path('fonts/'), // advised by dompdf (https://github.com/dompdf/dompdf/pull/782)
42 +
43 + /**
44 + * The location of the DOMPDF font cache directory
45 + *
46 + * This directory contains the cached font metrics for the fonts used by DOMPDF.
47 + * This directory can be the same as DOMPDF_FONT_DIR
48 + *
49 + * Note: This directory must exist and be writable by the webserver process.
50 + */
51 + "DOMPDF_FONT_CACHE" => storage_path('fonts/'),
52 +
53 + /**
54 + * The location of a temporary directory.
55 + *
56 + * The directory specified must be writeable by the webserver process.
57 + * The temporary directory is required to download remote images and when
58 + * using the PFDLib back end.
59 + */
60 + "DOMPDF_TEMP_DIR" => sys_get_temp_dir(),
61 +
62 + /**
63 + * ==== IMPORTANT ====
64 + *
65 + * dompdf's "chroot": Prevents dompdf from accessing system files or other
66 + * files on the webserver. All local files opened by dompdf must be in a
67 + * subdirectory of this directory. DO NOT set it to '/' since this could
68 + * allow an attacker to use dompdf to read any files on the server. This
69 + * should be an absolute path.
70 + * This is only checked on command line call by dompdf.php, but not by
71 + * direct class use like:
72 + * $dompdf = new DOMPDF(); $dompdf->load_html($htmldata); $dompdf->render(); $pdfdata = $dompdf->output();
73 + */
74 + "DOMPDF_CHROOT" => realpath(base_path()),
75 +
76 + /**
77 + * Whether to use Unicode fonts or not.
78 + *
79 + * When set to true the PDF backend must be set to "CPDF" and fonts must be
80 + * loaded via load_font.php.
81 + *
82 + * When enabled, dompdf can support all Unicode glyphs. Any glyphs used in a
83 + * document must be present in your fonts, however.
84 + */
85 + "DOMPDF_UNICODE_ENABLED" => true,
86 +
87 + /**
88 + * Whether to enable font subsetting or not.
89 + */
90 + "DOMPDF_ENABLE_FONTSUBSETTING" => false,
91 +
92 + /**
93 + * The PDF rendering backend to use
94 + *
95 + * Valid settings are 'PDFLib', 'CPDF' (the bundled R&OS PDF class), 'GD' and
96 + * 'auto'. 'auto' will look for PDFLib and use it if found, or if not it will
97 + * fall back on CPDF. 'GD' renders PDFs to graphic files. {@link
98 + * Canvas_Factory} ultimately determines which rendering class to instantiate
99 + * based on this setting.
100 + *
101 + * Both PDFLib & CPDF rendering backends provide sufficient rendering
102 + * capabilities for dompdf, however additional features (e.g. object,
103 + * image and font support, etc.) differ between backends. Please see
104 + * {@link PDFLib_Adapter} for more information on the PDFLib backend
105 + * and {@link CPDF_Adapter} and lib/class.pdf.php for more information
106 + * on CPDF. Also see the documentation for each backend at the links
107 + * below.
108 + *
109 + * The GD rendering backend is a little different than PDFLib and
110 + * CPDF. Several features of CPDF and PDFLib are not supported or do
111 + * not make any sense when creating image files. For example,
112 + * multiple pages are not supported, nor are PDF 'objects'. Have a
113 + * look at {@link GD_Adapter} for more information. GD support is
114 + * experimental, so use it at your own risk.
115 + *
116 + * @link http://www.pdflib.com
117 + * @link http://www.ros.co.nz/pdf
118 + * @link http://www.php.net/image
119 + */
120 + "DOMPDF_PDF_BACKEND" => "CPDF",
121 +
122 + /**
123 + * PDFlib license key
124 + *
125 + * If you are using a licensed, commercial version of PDFlib, specify
126 + * your license key here. If you are using PDFlib-Lite or are evaluating
127 + * the commercial version of PDFlib, comment out this setting.
128 + *
129 + * @link http://www.pdflib.com
130 + *
131 + * If pdflib present in web server and auto or selected explicitely above,
132 + * a real license code must exist!
133 + */
134 + //"DOMPDF_PDFLIB_LICENSE" => "your license key here",
135 +
136 + /**
137 + * html target media view which should be rendered into pdf.
138 + * List of types and parsing rules for future extensions:
139 + * http://www.w3.org/TR/REC-html40/types.html
140 + * screen, tty, tv, projection, handheld, print, braille, aural, all
141 + * Note: aural is deprecated in CSS 2.1 because it is replaced by speech in CSS 3.
142 + * Note, even though the generated pdf file is intended for print output,
143 + * the desired content might be different (e.g. screen or projection view of html file).
144 + * Therefore allow specification of content here.
145 + */
146 + "DOMPDF_DEFAULT_MEDIA_TYPE" => "screen",
147 +
148 + /**
149 + * The default paper size.
150 + *
151 + * North America standard is "letter"; other countries generally "a4"
152 + *
153 + * @see CPDF_Adapter::PAPER_SIZES for valid sizes ('letter', 'legal', 'A4', etc.)
154 + */
155 + "DOMPDF_DEFAULT_PAPER_SIZE" => "a4",
156 +
157 + /**
158 + * The default font family
159 + *
160 + * Used if no suitable fonts can be found. This must exist in the font folder.
161 + * @var string
162 + */
163 + "DOMPDF_DEFAULT_FONT" => "dejavu sans",
164 +
165 + /**
166 + * Image DPI setting
167 + *
168 + * This setting determines the default DPI setting for images and fonts. The
169 + * DPI may be overridden for inline images by explictly setting the
170 + * image's width & height style attributes (i.e. if the image's native
171 + * width is 600 pixels and you specify the image's width as 72 points,
172 + * the image will have a DPI of 600 in the rendered PDF. The DPI of
173 + * background images can not be overridden and is controlled entirely
174 + * via this parameter.
175 + *
176 + * For the purposes of DOMPDF, pixels per inch (PPI) = dots per inch (DPI).
177 + * If a size in html is given as px (or without unit as image size),
178 + * this tells the corresponding size in pt.
179 + * This adjusts the relative sizes to be similar to the rendering of the
180 + * html page in a reference browser.
181 + *
182 + * In pdf, always 1 pt = 1/72 inch
183 + *
184 + * Rendering resolution of various browsers in px per inch:
185 + * Windows Firefox and Internet Explorer:
186 + * SystemControl->Display properties->FontResolution: Default:96, largefonts:120, custom:?
187 + * Linux Firefox:
188 + * about:config *resolution: Default:96
189 + * (xorg screen dimension in mm and Desktop font dpi settings are ignored)
190 + *
191 + * Take care about extra font/image zoom factor of browser.
192 + *
193 + * In images, <img> size in pixel attribute, img css style, are overriding
194 + * the real image dimension in px for rendering.
195 + *
196 + * @var int
197 + */
198 + "DOMPDF_DPI" => 96,
199 +
200 + /**
201 + * Enable inline PHP
202 + *
203 + * If this setting is set to true then DOMPDF will automatically evaluate
204 + * inline PHP contained within <script type="text/php"> ... </script> tags.
205 + *
206 + * Enabling this for documents you do not trust (e.g. arbitrary remote html
207 + * pages) is a security risk. Set this option to false if you wish to process
208 + * untrusted documents.
209 + *
210 + * @var bool
211 + */
212 + "DOMPDF_ENABLE_PHP" => false,
213 +
214 + /**
215 + * Enable inline Javascript
216 + *
217 + * If this setting is set to true then DOMPDF will automatically insert
218 + * JavaScript code contained within <script type="text/javascript"> ... </script> tags.
219 + *
220 + * @var bool
221 + */
222 + "DOMPDF_ENABLE_JAVASCRIPT" => true,
223 +
224 + /**
225 + * Enable remote file access
226 + *
227 + * If this setting is set to true, DOMPDF will access remote sites for
228 + * images and CSS files as required.
229 + * This is required for part of test case www/test/image_variants.html through www/examples.php
230 + *
231 + * Attention!
232 + * This can be a security risk, in particular in combination with DOMPDF_ENABLE_PHP and
233 + * allowing remote access to dompdf.php or on allowing remote html code to be passed to
234 + * $dompdf = new DOMPDF(, $dompdf->load_html(...,
235 + * This allows anonymous users to download legally doubtful internet content which on
236 + * tracing back appears to being downloaded by your server, or allows malicious php code
237 + * in remote html pages to be executed by your server with your account privileges.
238 + *
239 + * @var bool
240 + */
241 + "DOMPDF_ENABLE_REMOTE" => true,
242 +
243 + /**
244 + * A ratio applied to the fonts height to be more like browsers' line height
245 + */
246 + "DOMPDF_FONT_HEIGHT_RATIO" => 1.1,
247 +
248 + /**
249 + * Enable CSS float
250 + *
251 + * Allows people to disabled CSS float support
252 + * @var bool
253 + */
254 + "DOMPDF_ENABLE_CSS_FLOAT" => true,
255 +
256 +
257 + /**
258 + * Use the more-than-experimental HTML5 Lib parser
259 + */
260 + "DOMPDF_ENABLE_HTML5PARSER" => true,
261 +
262 +
263 + ),
264 +
265 +
266 +);
...@@ -161,6 +161,12 @@ form.search-box { ...@@ -161,6 +161,12 @@ form.search-box {
161 padding: $-xs 0; 161 padding: $-xs 0;
162 color: #555; 162 color: #555;
163 text-align: left !important; 163 text-align: left !important;
164 + &.wide {
165 + min-width: 220px;
166 + }
167 + .text-muted {
168 + color: #999;
169 + }
164 a { 170 a {
165 display: block; 171 display: block;
166 padding: $-xs $-m; 172 padding: $-xs $-m;
......
...@@ -27,8 +27,8 @@ $-xs: 6px; ...@@ -27,8 +27,8 @@ $-xs: 6px;
27 $-xxs: 3px; 27 $-xxs: 3px;
28 28
29 // Fonts 29 // Fonts
30 -$heading: 'Roboto', Helvetica, Arial, sans-serif; 30 +$heading: 'Roboto', 'DejaVu Sans', Helvetica, Arial, sans-serif;
31 -$text: 'Roboto', Helvetica, Arial, sans-serif; 31 +$text: 'Roboto', 'DejaVu Sans', Helvetica, Arial, sans-serif;
32 $fs-m: 15px; 32 $fs-m: 15px;
33 $fs-s: 14px; 33 $fs-s: 14px;
34 34
......
1 -@import "reset"; 1 +//@import "reset";
2 @import "variables"; 2 @import "variables";
3 @import "mixins"; 3 @import "mixins";
4 @import "html"; 4 @import "html";
......
1 +<!doctype html>
2 +<html lang="en">
3 +<head>
4 + <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
5 + <title>{{ $page->name }}</title>
6 +
7 + <style>
8 + {!! $css !!}
9 + </style>
10 + @yield('head')
11 +</head>
12 +<body>
13 +<div class="container" id="page-show">
14 + <div class="row">
15 + <div class="col-md-8 col-md-offset-2">
16 + <div class="page-content">
17 +
18 + @include('pages/page-display')
19 +
20 + <hr>
21 +
22 + <p class="text-muted small">
23 + Created {{$page->created_at->toDayDateTimeString()}} @if($page->createdBy) by {{$page->createdBy->name}} @endif
24 + <br>
25 + Last Updated {{$page->updated_at->toDayDateTimeString()}} @if($page->updatedBy) by {{$page->updatedBy->name}} @endif
26 + </p>
27 +
28 + </div>
29 + </div>
30 + </div>
31 +</div>
32 +</body>
33 +</html>
1 -<!doctype html> 1 +@extends('pages/export')
2 -<html lang="en">
3 -<head>
4 - <meta charset="UTF-8">
5 - <title>{{ $page->name }}</title>
6 2
3 +@section('head')
7 <style> 4 <style>
8 - {!! $css !!} 5 + body {
9 - </style> 6 + font-size: 15px;
10 -</head> 7 + line-height: 1;
11 -<body> 8 + }
12 -<div class="container" id="page-show" ng-non-bindable>
13 - <div class="row">
14 - <div class="col-md-8 col-md-offset-2">
15 - <div class="page-content">
16 -
17 - @include('pages/page-display')
18 9
19 - <hr> 10 + h1, h2, h3, h4, h5, h6 {
11 + line-height: 1;
12 + }
20 13
21 - <p class="text-muted small"> 14 + table {
22 - Created {{$page->created_at->diffForHumans()}} @if($page->createdBy) by {{$page->createdBy->name}} @endif 15 + max-width: 800px !important;
23 - <br> 16 + font-size: 0.8em;
24 - Last Updated {{$page->updated_at->diffForHumans()}} @if($page->updatedBy) by {{$page->updatedBy->name}} @endif 17 + width: auto !important;
25 - </p> 18 + }
26 19
27 - </div> 20 + table td {
28 - </div> 21 + width: auto !important;
29 - </div> 22 + }
30 -</div> 23 + </style>
31 -</body> 24 +@stop
32 -</html>
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -20,9 +20,11 @@ ...@@ -20,9 +20,11 @@
20 <div class="col-sm-6 faded"> 20 <div class="col-sm-6 faded">
21 <div class="action-buttons"> 21 <div class="action-buttons">
22 <span dropdown class="dropdown-container"> 22 <span dropdown class="dropdown-container">
23 - <div dropdown-toggle class="text-button text-primary"><i class="zmdi zmdi-open-in-new"></i>Export Page</div> 23 + <div dropdown-toggle class="text-button text-primary"><i class="zmdi zmdi-open-in-new"></i>Export</div>
24 - <ul> 24 + <ul class="wide">
25 - <li><a href="{{$page->getUrl() . '/export/html'}}" target="_blank">Contained HTML File</a></li> 25 + <li><a href="{{$page->getUrl() . '/export/html'}}" target="_blank">Contained Web File <span class="text-muted pull-right">.html</span></a></li>
26 + <li><a href="{{$page->getUrl() . '/export/pdf'}}" target="_blank">PDF File <span class="text-muted pull-right">.pdf</span></a></li>
27 + <li><a href="{{$page->getUrl() . '/export/plaintext'}}" target="_blank">Plain Text File <span class="text-muted pull-right">.txt</span></a></li>
26 </ul> 28 </ul>
27 </span> 29 </span>
28 @if($currentUser->can('page-update')) 30 @if($currentUser->can('page-update'))
......
1 +*
2 +!.gitignore
...\ No newline at end of file ...\ No newline at end of file