Dan Brown

Added page HTML export

...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
3 namespace BookStack\Http\Controllers; 3 namespace BookStack\Http\Controllers;
4 4
5 use Activity; 5 use Activity;
6 +use BookStack\Services\ExportService;
6 use Illuminate\Http\Request; 7 use Illuminate\Http\Request;
7 8
8 use Illuminate\Support\Facades\Auth; 9 use Illuminate\Support\Facades\Auth;
...@@ -18,18 +19,21 @@ class PageController extends Controller ...@@ -18,18 +19,21 @@ class PageController extends Controller
18 protected $pageRepo; 19 protected $pageRepo;
19 protected $bookRepo; 20 protected $bookRepo;
20 protected $chapterRepo; 21 protected $chapterRepo;
22 + protected $exportService;
21 23
22 /** 24 /**
23 * PageController constructor. 25 * PageController constructor.
24 - * @param PageRepo $pageRepo 26 + * @param PageRepo $pageRepo
25 - * @param BookRepo $bookRepo 27 + * @param BookRepo $bookRepo
26 - * @param ChapterRepo $chapterRepo 28 + * @param ChapterRepo $chapterRepo
29 + * @param ExportService $exportService
27 */ 30 */
28 - public function __construct(PageRepo $pageRepo, BookRepo $bookRepo, ChapterRepo $chapterRepo) 31 + public function __construct(PageRepo $pageRepo, BookRepo $bookRepo, ChapterRepo $chapterRepo, ExportService $exportService)
29 { 32 {
30 $this->pageRepo = $pageRepo; 33 $this->pageRepo = $pageRepo;
31 $this->bookRepo = $bookRepo; 34 $this->bookRepo = $bookRepo;
32 $this->chapterRepo = $chapterRepo; 35 $this->chapterRepo = $chapterRepo;
36 + $this->exportService = $exportService;
33 parent::__construct(); 37 parent::__construct();
34 } 38 }
35 39
...@@ -221,4 +225,30 @@ class PageController extends Controller ...@@ -221,4 +225,30 @@ class PageController extends Controller
221 Activity::add($page, 'page_restore', $book->id); 225 Activity::add($page, 'page_restore', $book->id);
222 return redirect($page->getUrl()); 226 return redirect($page->getUrl());
223 } 227 }
228 +
229 + public function exportPdf($bookSlug, $pageSlug)
230 + {
231 + $book = $this->bookRepo->getBySlug($bookSlug);
232 + $page = $this->pageRepo->getBySlug($pageSlug, $book->id);
233 + $cssContent = file_get_contents(public_path('/css/styles.css'));
234 +
235 + return $pdf->download($pageSlug . '.pdf');
236 + }
237 +
238 + /**
239 + * Export a page to a self-contained HTML file.
240 + * @param $bookSlug
241 + * @param $pageSlug
242 + * @return \Illuminate\Http\Response
243 + */
244 + public function exportHtml($bookSlug, $pageSlug)
245 + {
246 + $book = $this->bookRepo->getBySlug($bookSlug);
247 + $page = $this->pageRepo->getBySlug($pageSlug, $book->id);
248 + $containedHtml = $this->exportService->pageToContainedHtml($page);
249 + return response()->make($containedHtml, 200, [
250 + 'Content-Type' => 'application/octet-stream',
251 + 'Content-Disposition' => 'attachment; filename="'.$pageSlug.'.html'
252 + ]);
253 + }
224 } 254 }
......
...@@ -18,17 +18,18 @@ Route::group(['middleware' => 'auth'], function () { ...@@ -18,17 +18,18 @@ Route::group(['middleware' => 'auth'], function () {
18 Route::get('/{bookSlug}/sort', 'BookController@sort'); 18 Route::get('/{bookSlug}/sort', 'BookController@sort');
19 Route::put('/{bookSlug}/sort', 'BookController@saveSort'); 19 Route::put('/{bookSlug}/sort', 'BookController@saveSort');
20 20
21 -
22 // Pages 21 // Pages
23 Route::get('/{bookSlug}/page/create', 'PageController@create'); 22 Route::get('/{bookSlug}/page/create', 'PageController@create');
24 Route::post('/{bookSlug}/page', 'PageController@store'); 23 Route::post('/{bookSlug}/page', 'PageController@store');
25 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');
26 + Route::get('/{bookSlug}/page/{pageSlug}/export/html', 'PageController@exportHtml');
26 Route::get('/{bookSlug}/page/{pageSlug}/edit', 'PageController@edit'); 27 Route::get('/{bookSlug}/page/{pageSlug}/edit', 'PageController@edit');
27 Route::get('/{bookSlug}/page/{pageSlug}/delete', 'PageController@showDelete'); 28 Route::get('/{bookSlug}/page/{pageSlug}/delete', 'PageController@showDelete');
28 Route::put('/{bookSlug}/page/{pageSlug}', 'PageController@update'); 29 Route::put('/{bookSlug}/page/{pageSlug}', 'PageController@update');
29 Route::delete('/{bookSlug}/page/{pageSlug}', 'PageController@destroy'); 30 Route::delete('/{bookSlug}/page/{pageSlug}', 'PageController@destroy');
30 31
31 - //Revisions 32 + // Revisions
32 Route::get('/{bookSlug}/page/{pageSlug}/revisions', 'PageController@showRevisions'); 33 Route::get('/{bookSlug}/page/{pageSlug}/revisions', 'PageController@showRevisions');
33 Route::get('/{bookSlug}/page/{pageSlug}/revisions/{revId}', 'PageController@showRevision'); 34 Route::get('/{bookSlug}/page/{pageSlug}/revisions/{revId}', 'PageController@showRevision');
34 Route::get('/{bookSlug}/page/{pageSlug}/revisions/{revId}/restore', 'PageController@restoreRevision'); 35 Route::get('/{bookSlug}/page/{pageSlug}/revisions/{revId}/restore', 'PageController@restoreRevision');
......
1 +<?php namespace BookStack\Services;
2 +
3 +
4 +use BookStack\Page;
5 +
6 +class ExportService
7 +{
8 +
9 +
10 + /**
11 + * Convert a page to a self-contained HTML file.
12 + * Includes required CSS & image content. Images are base64 encoded into the HTML.
13 + * @param Page $page
14 + * @return mixed|string
15 + */
16 + public function pageToContainedHtml(Page $page)
17 + {
18 + $cssContent = file_get_contents(public_path('/css/export-styles.css'));
19 + $pageHtml = view('pages/pdf', ['page' => $page, 'css' => $cssContent])->render();
20 +
21 + $imageTagsOutput = [];
22 + preg_match_all("/\<img.*src\=(\'|\")(.*?)(\'|\").*?\>/i", $pageHtml, $imageTagsOutput);
23 +
24 + // Replace image src with base64 encoded image strings
25 + if (isset($imageTagsOutput[0]) && count($imageTagsOutput[0]) > 0) {
26 + foreach ($imageTagsOutput[0] as $index => $imgMatch) {
27 + $oldImgString = $imgMatch;
28 + $srcString = $imageTagsOutput[2][$index];
29 + if (strpos(trim($srcString), 'http') !== 0) {
30 + $pathString = public_path($srcString);
31 + } else {
32 + $pathString = $srcString;
33 + }
34 + $imageContent = file_get_contents($pathString);
35 + $imageEncoded = 'data:image/' . pathinfo($pathString, PATHINFO_EXTENSION) . ';base64,' . base64_encode($imageContent);
36 + $newImageString = str_replace($srcString, $imageEncoded, $oldImgString);
37 + $pageHtml = str_replace($oldImgString, $newImageString, $pageHtml);
38 + }
39 + }
40 +
41 + $linksOutput = [];
42 + preg_match_all("/\<a.*href\=(\'|\")(.*?)(\'|\").*?\>/i", $pageHtml, $linksOutput);
43 +
44 + // Replace image src with base64 encoded image strings
45 + if (isset($linksOutput[0]) && count($linksOutput[0]) > 0) {
46 + foreach ($linksOutput[0] as $index => $linkMatch) {
47 + $oldLinkString = $linkMatch;
48 + $srcString = $linksOutput[2][$index];
49 + if (strpos(trim($srcString), 'http') !== 0) {
50 + $newSrcString = url($srcString);
51 + $newLinkString = str_replace($srcString, $newSrcString, $oldLinkString);
52 + $pageHtml = str_replace($oldLinkString, $newLinkString, $pageHtml);
53 + }
54 + }
55 + }
56 +
57 + // Replace any relative links with system domain
58 + return $pageHtml;
59 + }
60 +
61 +}
...\ No newline at end of file ...\ No newline at end of file
...@@ -9,16 +9,16 @@ ...@@ -9,16 +9,16 @@
9 "packages": [ 9 "packages": [
10 { 10 {
11 "name": "aws/aws-sdk-php", 11 "name": "aws/aws-sdk-php",
12 - "version": "3.12.1", 12 + "version": "3.13.1",
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": "5ee0f33fafe47740c03ff38ddb73ae4f52b4da5b" 16 + "reference": "cc1796d1c21146cdcbfb7628aee816acb7b85e09"
17 }, 17 },
18 "dist": { 18 "dist": {
19 "type": "zip", 19 "type": "zip",
20 - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/5ee0f33fafe47740c03ff38ddb73ae4f52b4da5b", 20 + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/cc1796d1c21146cdcbfb7628aee816acb7b85e09",
21 - "reference": "5ee0f33fafe47740c03ff38ddb73ae4f52b4da5b", 21 + "reference": "cc1796d1c21146cdcbfb7628aee816acb7b85e09",
22 "shasum": "" 22 "shasum": ""
23 }, 23 },
24 "require": { 24 "require": {
...@@ -40,7 +40,7 @@ ...@@ -40,7 +40,7 @@
40 "ext-simplexml": "*", 40 "ext-simplexml": "*",
41 "ext-spl": "*", 41 "ext-spl": "*",
42 "nette/neon": "^2.3", 42 "nette/neon": "^2.3",
43 - "phpunit/phpunit": "~4.0" 43 + "phpunit/phpunit": "~4.0|~5.0"
44 }, 44 },
45 "suggest": { 45 "suggest": {
46 "aws/aws-php-sns-message-validator": "To validate incoming SNS notifications", 46 "aws/aws-php-sns-message-validator": "To validate incoming SNS notifications",
...@@ -84,7 +84,7 @@ ...@@ -84,7 +84,7 @@
84 "s3", 84 "s3",
85 "sdk" 85 "sdk"
86 ], 86 ],
87 - "time": "2016-01-06 22:50:48" 87 + "time": "2016-01-19 22:46:22"
88 }, 88 },
89 { 89 {
90 "name": "barryvdh/laravel-debugbar", 90 "name": "barryvdh/laravel-debugbar",
...@@ -829,16 +829,16 @@ ...@@ -829,16 +829,16 @@
829 }, 829 },
830 { 830 {
831 "name": "laravel/framework", 831 "name": "laravel/framework",
832 - "version": "v5.2.7", 832 + "version": "v5.2.10",
833 "source": { 833 "source": {
834 "type": "git", 834 "type": "git",
835 "url": "https://github.com/laravel/framework.git", 835 "url": "https://github.com/laravel/framework.git",
836 - "reference": "26cd65eaa4bcc0fb0be381cfb7cfdcda06a3c2b4" 836 + "reference": "93dc5b0089eef468157fd7200e575c3861ec59a5"
837 }, 837 },
838 "dist": { 838 "dist": {
839 "type": "zip", 839 "type": "zip",
840 - "url": "https://api.github.com/repos/laravel/framework/zipball/26cd65eaa4bcc0fb0be381cfb7cfdcda06a3c2b4", 840 + "url": "https://api.github.com/repos/laravel/framework/zipball/93dc5b0089eef468157fd7200e575c3861ec59a5",
841 - "reference": "26cd65eaa4bcc0fb0be381cfb7cfdcda06a3c2b4", 841 + "reference": "93dc5b0089eef468157fd7200e575c3861ec59a5",
842 "shasum": "" 842 "shasum": ""
843 }, 843 },
844 "require": { 844 "require": {
...@@ -953,7 +953,7 @@ ...@@ -953,7 +953,7 @@
953 "framework", 953 "framework",
954 "laravel" 954 "laravel"
955 ], 955 ],
956 - "time": "2016-01-07 13:54:34" 956 + "time": "2016-01-13 20:29:10"
957 }, 957 },
958 { 958 {
959 "name": "laravel/socialite", 959 "name": "laravel/socialite",
...@@ -1849,16 +1849,16 @@ ...@@ -1849,16 +1849,16 @@
1849 }, 1849 },
1850 { 1850 {
1851 "name": "symfony/class-loader", 1851 "name": "symfony/class-loader",
1852 - "version": "v2.8.1", 1852 + "version": "v2.8.2",
1853 "source": { 1853 "source": {
1854 "type": "git", 1854 "type": "git",
1855 "url": "https://github.com/symfony/class-loader.git", 1855 "url": "https://github.com/symfony/class-loader.git",
1856 - "reference": "ec74b0a279cf3a9bd36172b3e3061591d380ce6c" 1856 + "reference": "98e9089a428ed0e39423b67352c57ef5910a3269"
1857 }, 1857 },
1858 "dist": { 1858 "dist": {
1859 "type": "zip", 1859 "type": "zip",
1860 - "url": "https://api.github.com/repos/symfony/class-loader/zipball/ec74b0a279cf3a9bd36172b3e3061591d380ce6c", 1860 + "url": "https://api.github.com/repos/symfony/class-loader/zipball/98e9089a428ed0e39423b67352c57ef5910a3269",
1861 - "reference": "ec74b0a279cf3a9bd36172b3e3061591d380ce6c", 1861 + "reference": "98e9089a428ed0e39423b67352c57ef5910a3269",
1862 "shasum": "" 1862 "shasum": ""
1863 }, 1863 },
1864 "require": { 1864 "require": {
...@@ -1897,7 +1897,7 @@ ...@@ -1897,7 +1897,7 @@
1897 ], 1897 ],
1898 "description": "Symfony ClassLoader Component", 1898 "description": "Symfony ClassLoader Component",
1899 "homepage": "https://symfony.com", 1899 "homepage": "https://symfony.com",
1900 - "time": "2015-12-05 17:37:59" 1900 + "time": "2016-01-03 15:33:41"
1901 }, 1901 },
1902 { 1902 {
1903 "name": "symfony/console", 1903 "name": "symfony/console",
......
...@@ -21,6 +21,7 @@ elixir.extend('queryVersion', function(inputFiles) { ...@@ -21,6 +21,7 @@ elixir.extend('queryVersion', function(inputFiles) {
21 elixir(function(mix) { 21 elixir(function(mix) {
22 mix.sass('styles.scss') 22 mix.sass('styles.scss')
23 .sass('print-styles.scss') 23 .sass('print-styles.scss')
24 + .sass('export-styles.scss')
24 .browserify('global.js', 'public/js/common.js') 25 .browserify('global.js', 'public/js/common.js')
25 .queryVersion(['css/styles.css', 'css/print-styles.css', 'js/common.js']); 26 .queryVersion(['css/styles.css', 'css/print-styles.css', 'js/common.js']);
26 }); 27 });
......
1 +/* Generated by Font Squirrel (http://www.fontsquirrel.com) on December 30, 2015 */
2 +@font-face {
3 + font-family: 'Roboto';
4 + src: url('/fonts/roboto-bold-webfont.eot');
5 + src: url('/fonts/roboto-bold-webfont.eot?#iefix') format('embedded-opentype'),
6 + url('/fonts/roboto-bold-webfont.woff2') format('woff2'),
7 + url('/fonts/roboto-bold-webfont.woff') format('woff'),
8 + url('/fonts/roboto-bold-webfont.ttf') format('truetype'),
9 + url('/fonts/roboto-bold-webfont.svg#robotobold') format('svg');
10 + font-weight: bold;
11 + font-style: normal;
12 +}
13 +
14 +@font-face {
15 + font-family: 'Roboto';
16 + src: url('/fonts/roboto-bolditalic-webfont.eot');
17 + src: url('/fonts/roboto-bolditalic-webfont.eot?#iefix') format('embedded-opentype'),
18 + url('/fonts/roboto-bolditalic-webfont.woff2') format('woff2'),
19 + url('/fonts/roboto-bolditalic-webfont.woff') format('woff'),
20 + url('/fonts/roboto-bolditalic-webfont.ttf') format('truetype'),
21 + url('/fonts/roboto-bolditalic-webfont.svg#robotobold_italic') format('svg');
22 + font-weight: bold;
23 + font-style: italic;
24 +}
25 +
26 +@font-face {
27 + font-family: 'Roboto';
28 + src: url('/fonts/roboto-italic-webfont.eot');
29 + src: url('/fonts/roboto-italic-webfont.eot?#iefix') format('embedded-opentype'),
30 + url('/fonts/roboto-italic-webfont.woff2') format('woff2'),
31 + url('/fonts/roboto-italic-webfont.woff') format('woff'),
32 + url('/fonts/roboto-italic-webfont.ttf') format('truetype'),
33 + url('/fonts/roboto-italic-webfont.svg#robotoitalic') format('svg');
34 + font-weight: normal;
35 + font-style: italic;
36 +}
37 +
38 +@font-face {
39 + font-family: 'Roboto';
40 + src: url('/fonts/roboto-light-webfont.eot');
41 + src: url('/fonts/roboto-light-webfont.eot?#iefix') format('embedded-opentype'),
42 + url('/fonts/roboto-light-webfont.woff2') format('woff2'),
43 + url('/fonts/roboto-light-webfont.woff') format('woff'),
44 + url('/fonts/roboto-light-webfont.ttf') format('truetype'),
45 + url('/fonts/roboto-light-webfont.svg#robotolight') format('svg');
46 + font-weight: 300;
47 + font-style: normal;
48 +}
49 +
50 +@font-face {
51 + font-family: 'Roboto';
52 + src: url('/fonts/roboto-lightitalic-webfont.eot');
53 + src: url('/fonts/roboto-lightitalic-webfont.eot?#iefix') format('embedded-opentype'),
54 + url('/fonts/roboto-lightitalic-webfont.woff2') format('woff2'),
55 + url('/fonts/roboto-lightitalic-webfont.woff') format('woff'),
56 + url('/fonts/roboto-lightitalic-webfont.ttf') format('truetype'),
57 + url('/fonts/roboto-lightitalic-webfont.svg#robotolight_italic') format('svg');
58 + font-weight: 300;
59 + font-style: italic;
60 +}
61 +
62 +@font-face {
63 + font-family: 'Roboto';
64 + src: url('/fonts/roboto-medium-webfont.eot');
65 + src: url('/fonts/roboto-medium-webfont.eot?#iefix') format('embedded-opentype'),
66 + url('/fonts/roboto-medium-webfont.woff2') format('woff2'),
67 + url('/fonts/roboto-medium-webfont.woff') format('woff'),
68 + url('/fonts/roboto-medium-webfont.ttf') format('truetype'),
69 + url('/fonts/roboto-medium-webfont.svg#robotomedium') format('svg');
70 + font-weight: 500;
71 + font-style: normal;
72 +}
73 +
74 +@font-face {
75 + font-family: 'Roboto';
76 + src: url('/fonts/roboto-mediumitalic-webfont.eot');
77 + src: url('/fonts/roboto-mediumitalic-webfont.eot?#iefix') format('embedded-opentype'),
78 + url('/fonts/roboto-mediumitalic-webfont.woff2') format('woff2'),
79 + url('/fonts/roboto-mediumitalic-webfont.woff') format('woff'),
80 + url('/fonts/roboto-mediumitalic-webfont.ttf') format('truetype'),
81 + url('/fonts/roboto-mediumitalic-webfont.svg#robotomedium_italic') format('svg');
82 + font-weight: 500;
83 + font-style: italic;
84 +}
85 +
86 +@font-face {
87 + font-family: 'Roboto';
88 + src: url('/fonts/roboto-regular-webfont.eot');
89 + src: url('/fonts/roboto-regular-webfont.eot?#iefix') format('embedded-opentype'),
90 + url('/fonts/roboto-regular-webfont.woff2') format('woff2'),
91 + url('/fonts/roboto-regular-webfont.woff') format('woff'),
92 + url('/fonts/roboto-regular-webfont.ttf') format('truetype'),
93 + url('/fonts/roboto-regular-webfont.svg#robotoregular') format('svg');
94 + font-weight: normal;
95 + font-style: normal;
96 +}
...\ No newline at end of file ...\ No newline at end of file
...@@ -187,7 +187,7 @@ form.search-box { ...@@ -187,7 +187,7 @@ form.search-box {
187 } 187 }
188 188
189 .faded { 189 .faded {
190 - a, button, span { 190 + a, button, span, span > div {
191 color: #666; 191 color: #666;
192 } 192 }
193 .text-button { 193 .text-button {
......
...@@ -52,101 +52,3 @@ $text-light: #EEE; ...@@ -52,101 +52,3 @@ $text-light: #EEE;
52 $bs-light: 0 0 4px 1px #CCC; 52 $bs-light: 0 0 4px 1px #CCC;
53 $bs-med: 0 1px 3px 1px rgba(76, 76, 76, 0.26); 53 $bs-med: 0 1px 3px 1px rgba(76, 76, 76, 0.26);
54 $bs-hover: 0 2px 2px 1px rgba(0,0,0,.13); 54 $bs-hover: 0 2px 2px 1px rgba(0,0,0,.13);
55 -
56 -
57 -/* Generated by Font Squirrel (http://www.fontsquirrel.com) on December 30, 2015 */
58 -@font-face {
59 - font-family: 'Roboto';
60 - src: url('/fonts/roboto-bold-webfont.eot');
61 - src: url('/fonts/roboto-bold-webfont.eot?#iefix') format('embedded-opentype'),
62 - url('/fonts/roboto-bold-webfont.woff2') format('woff2'),
63 - url('/fonts/roboto-bold-webfont.woff') format('woff'),
64 - url('/fonts/roboto-bold-webfont.ttf') format('truetype'),
65 - url('/fonts/roboto-bold-webfont.svg#robotobold') format('svg');
66 - font-weight: bold;
67 - font-style: normal;
68 -}
69 -
70 -@font-face {
71 - font-family: 'Roboto';
72 - src: url('/fonts/roboto-bolditalic-webfont.eot');
73 - src: url('/fonts/roboto-bolditalic-webfont.eot?#iefix') format('embedded-opentype'),
74 - url('/fonts/roboto-bolditalic-webfont.woff2') format('woff2'),
75 - url('/fonts/roboto-bolditalic-webfont.woff') format('woff'),
76 - url('/fonts/roboto-bolditalic-webfont.ttf') format('truetype'),
77 - url('/fonts/roboto-bolditalic-webfont.svg#robotobold_italic') format('svg');
78 - font-weight: bold;
79 - font-style: italic;
80 -}
81 -
82 -@font-face {
83 - font-family: 'Roboto';
84 - src: url('/fonts/roboto-italic-webfont.eot');
85 - src: url('/fonts/roboto-italic-webfont.eot?#iefix') format('embedded-opentype'),
86 - url('/fonts/roboto-italic-webfont.woff2') format('woff2'),
87 - url('/fonts/roboto-italic-webfont.woff') format('woff'),
88 - url('/fonts/roboto-italic-webfont.ttf') format('truetype'),
89 - url('/fonts/roboto-italic-webfont.svg#robotoitalic') format('svg');
90 - font-weight: normal;
91 - font-style: italic;
92 -}
93 -
94 -@font-face {
95 - font-family: 'Roboto';
96 - src: url('/fonts/roboto-light-webfont.eot');
97 - src: url('/fonts/roboto-light-webfont.eot?#iefix') format('embedded-opentype'),
98 - url('/fonts/roboto-light-webfont.woff2') format('woff2'),
99 - url('/fonts/roboto-light-webfont.woff') format('woff'),
100 - url('/fonts/roboto-light-webfont.ttf') format('truetype'),
101 - url('/fonts/roboto-light-webfont.svg#robotolight') format('svg');
102 - font-weight: 300;
103 - font-style: normal;
104 -}
105 -
106 -@font-face {
107 - font-family: 'Roboto';
108 - src: url('/fonts/roboto-lightitalic-webfont.eot');
109 - src: url('/fonts/roboto-lightitalic-webfont.eot?#iefix') format('embedded-opentype'),
110 - url('/fonts/roboto-lightitalic-webfont.woff2') format('woff2'),
111 - url('/fonts/roboto-lightitalic-webfont.woff') format('woff'),
112 - url('/fonts/roboto-lightitalic-webfont.ttf') format('truetype'),
113 - url('/fonts/roboto-lightitalic-webfont.svg#robotolight_italic') format('svg');
114 - font-weight: 300;
115 - font-style: italic;
116 -}
117 -
118 -@font-face {
119 - font-family: 'Roboto';
120 - src: url('/fonts/roboto-medium-webfont.eot');
121 - src: url('/fonts/roboto-medium-webfont.eot?#iefix') format('embedded-opentype'),
122 - url('/fonts/roboto-medium-webfont.woff2') format('woff2'),
123 - url('/fonts/roboto-medium-webfont.woff') format('woff'),
124 - url('/fonts/roboto-medium-webfont.ttf') format('truetype'),
125 - url('/fonts/roboto-medium-webfont.svg#robotomedium') format('svg');
126 - font-weight: 500;
127 - font-style: normal;
128 -}
129 -
130 -@font-face {
131 - font-family: 'Roboto';
132 - src: url('/fonts/roboto-mediumitalic-webfont.eot');
133 - src: url('/fonts/roboto-mediumitalic-webfont.eot?#iefix') format('embedded-opentype'),
134 - url('/fonts/roboto-mediumitalic-webfont.woff2') format('woff2'),
135 - url('/fonts/roboto-mediumitalic-webfont.woff') format('woff'),
136 - url('/fonts/roboto-mediumitalic-webfont.ttf') format('truetype'),
137 - url('/fonts/roboto-mediumitalic-webfont.svg#robotomedium_italic') format('svg');
138 - font-weight: 500;
139 - font-style: italic;
140 -}
141 -
142 -@font-face {
143 - font-family: 'Roboto';
144 - src: url('/fonts/roboto-regular-webfont.eot');
145 - src: url('/fonts/roboto-regular-webfont.eot?#iefix') format('embedded-opentype'),
146 - url('/fonts/roboto-regular-webfont.woff2') format('woff2'),
147 - url('/fonts/roboto-regular-webfont.woff') format('woff'),
148 - url('/fonts/roboto-regular-webfont.ttf') format('truetype'),
149 - url('/fonts/roboto-regular-webfont.svg#robotoregular') format('svg');
150 - font-weight: normal;
151 - font-style: normal;
152 -}
......
1 +@import "reset";
2 +@import "variables";
3 +@import "mixins";
4 +@import "html";
5 +@import "text";
6 +@import "grid";
7 +@import "blocks";
8 +@import "forms";
9 +@import "tables";
10 +@import "header";
11 +@import "lists";
12 +@import "pages";
...\ No newline at end of file ...\ No newline at end of file
1 @import "reset"; 1 @import "reset";
2 @import "variables"; 2 @import "variables";
3 +@import "fonts";
3 @import "mixins"; 4 @import "mixins";
4 @import "html"; 5 @import "html";
5 @import "text"; 6 @import "text";
......
1 +<!doctype html>
2 +<html lang="en">
3 +<head>
4 + <meta charset="UTF-8">
5 + <title>{{ $page->name }}</title>
6 +
7 + <style>
8 + {!! $css !!}
9 + </style>
10 +</head>
11 +<body>
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 +
19 + <hr>
20 +
21 + <p class="text-muted small">
22 + Created {{$page->created_at->diffForHumans()}} @if($page->createdBy) by {{$page->createdBy->name}} @endif
23 + <br>
24 + Last Updated {{$page->updated_at->diffForHumans()}} @if($page->updatedBy) by {{$page->updatedBy->name}} @endif
25 + </p>
26 +
27 + </div>
28 + </div>
29 + </div>
30 +</div>
31 +</body>
32 +</html>
...@@ -19,6 +19,12 @@ ...@@ -19,6 +19,12 @@
19 </div> 19 </div>
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">
23 + <div dropdown-toggle class="text-button text-primary"><i class="zmdi zmdi-open-in-new"></i>Export Page</div>
24 + <ul>
25 + <li><a href="{{$page->getUrl() . '/export/html'}}" target="_blank">Contained HTML File</a></li>
26 + </ul>
27 + </span>
22 @if($currentUser->can('page-update')) 28 @if($currentUser->can('page-update'))
23 <a href="{{$page->getUrl() . '/revisions'}}" class="text-primary text-button"><i class="zmdi zmdi-replay"></i>Revisions</a> 29 <a href="{{$page->getUrl() . '/revisions'}}" class="text-primary text-button"><i class="zmdi zmdi-replay"></i>Revisions</a>
24 <a href="{{$page->getUrl() . '/edit'}}" class="text-primary text-button" ><i class="zmdi zmdi-edit"></i>Edit</a> 30 <a href="{{$page->getUrl() . '/edit'}}" class="text-primary text-button" ><i class="zmdi zmdi-edit"></i>Edit</a>
......