use DomPDF;
use Exception;
use SnappyPDF;
+use League\HTMLToMarkdown\HtmlConverter;
use Throwable;
+use ZipArchive;
class ExportFormatter
{
}
return $text;
}
+
+ /**
+ * Convert a page to a Markdown file.
+ * @throws Throwable
+ */
+ public function pageToMarkdown(Page $page)
+ {
+ if (property_exists($page, 'markdown') && $page->markdown != '') {
+ return "# " . $page->name . "\n\n" . $page->markdown;
+ } else {
+ $converter = new HtmlConverter();
+ return "# " . $page->name . "\n\n" . $converter->convert($page->html);
+ }
+ }
+
+ /**
+ * Convert a chapter to a Markdown file.
+ * @throws Throwable
+ */
+ public function chapterToMarkdown(Chapter $chapter)
+ {
+ $text = "# " . $chapter->name . "\n\n";
+ $text .= $chapter->description . "\n\n";
+ foreach ($chapter->pages as $page) {
+ $text .= $this->pageToMarkdown($page);
+ }
+ return $text;
+ }
+
+ /**
+ * Convert a book into a plain text string.
+ */
+ public function bookToMarkdown(Book $book): string
+ {
+ $bookTree = (new BookContents($book))->getTree(false, true);
+ $text = "# " . $book->name . "\n\n";
+ foreach ($bookTree as $bookChild) {
+ if ($bookChild->isA('chapter')) {
+ $text .= $this->chapterToMarkdown($bookChild);
+ } else {
+ $text .= $this->pageToMarkdown($bookChild);
+ }
+ }
+ return $text;
+ }
+
+ /**
+ * Convert a book into a zip file.
+ */
+ public function bookToZip(Book $book): string
+ {
+ // TODO: Is not unlinking the file a security risk?
+ $z = new ZipArchive();
+ $z->open("book.zip", \ZipArchive::CREATE | \ZipArchive::OVERWRITE);
+ $bookTree = (new BookContents($book))->getTree(false, true);
+ foreach ($bookTree as $bookChild) {
+ if ($bookChild->isA('chapter')) {
+ $z->addEmptyDir($bookChild->name);
+ foreach ($bookChild->pages as $page) {
+ $filename = $bookChild->name . "/" . $page->name . ".md";
+ $z->addFromString($filename, $this->pageToMarkdown($page));
+ }
+ } else {
+ $z->addFromString($bookChild->name . ".md", $this->pageToMarkdown($bookChild));
+ }
+ }
+ return "book.zip";
+ }
}
$textContent = $this->exportFormatter->bookToPlainText($book);
return $this->downloadResponse($textContent, $bookSlug . '.txt');
}
+
+ /**
+ * Export a book as a markdown file.
+ */
+ public function markdown(string $bookSlug)
+ {
+ $book = $this->bookRepo->getBySlug($bookSlug);
+ $textContent = $this->exportService->bookToMarkdown($book);
+ return $this->downloadResponse($textContent, $bookSlug . '.md');
+ }
+
+ /**
+ * Export a book as a zip file, made of markdown files.
+ */
+ public function zip(string $bookSlug)
+ {
+ $book = $this->bookRepo->getBySlug($bookSlug);
+ $filename = $this->exportService->bookToZip($book);
+ return response()->download($filename);
+ }
}
$chapterText = $this->exportFormatter->chapterToPlainText($chapter);
return $this->downloadResponse($chapterText, $chapterSlug . '.txt');
}
+
+ /**
+ * Export a chapter to a simple markdown file.
+ * @throws NotFoundException
+ */
+ public function markdown(string $bookSlug, string $chapterSlug)
+ {
+ // TODO: This should probably export to a zip file.
+ $chapter = $this->chapterRepo->getBySlug($bookSlug, $chapterSlug);
+ $chapterText = $this->exportService->chapterToMarkdown($chapter);
+ return $this->downloadResponse($chapterText, $chapterSlug . '.md');
+ }
}
$pageText = $this->exportFormatter->pageToPlainText($page);
return $this->downloadResponse($pageText, $pageSlug . '.txt');
}
+
+ /**
+ * Export a page to a simple markdown .md file.
+ * @throws NotFoundException
+ */
+ public function markdown(string $bookSlug, string $pageSlug)
+ {
+ $page = $this->pageRepo->getBySlug($bookSlug, $pageSlug);
+ $pageText = $this->exportService->pageToMarkdown($page);
+ return $this->downloadResponse($pageText, $pageSlug . '.md');
+ }
}
"laravel/socialite": "^5.1",
"league/commonmark": "^1.5",
"league/flysystem-aws-s3-v3": "^1.0.29",
+ "league/html-to-markdown": "^4.9",
"nunomaduro/collision": "^3.1",
"onelogin/php-saml": "^4.0",
"predis/predis": "^1.1.6",
# Install additional dependacnies and configure apache
RUN apt-get update -y \
- && apt-get install -y git zip unzip libpng-dev libldap2-dev wait-for-it \
+ && apt-get install -y git zip unzip libpng-dev libldap2-dev libzip-dev wait-for-it \
&& docker-php-ext-configure ldap --with-libdir=lib/x86_64-linux-gnu \
- && docker-php-ext-install pdo_mysql gd ldap \
+ && docker-php-ext-install pdo_mysql gd ldap zip \
&& a2enmod rewrite \
&& sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf \
&& sed -ri -e 's!/var/www/!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf
# Use the default production configuration and update it as required
RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini" \
- && sed -i 's/memory_limit = 128M/memory_limit = 512M/g' "$PHP_INI_DIR/php.ini"
\ No newline at end of file
+ && sed -i 's/memory_limit = 128M/memory_limit = 512M/g' "$PHP_INI_DIR/php.ini"
'export_html' => 'Contained Web File',
'export_pdf' => 'PDF File',
'export_text' => 'Plain Text File',
+ 'export_md' => 'Markdown File',
// Permissions and restrictions
'permissions' => 'Permissions',
<li><a href="{{ $entity->getUrl('/export/html') }}" target="_blank" rel="noopener">{{ trans('entities.export_html') }} <span class="text-muted float right">.html</span></a></li>
<li><a href="{{ $entity->getUrl('/export/pdf') }}" target="_blank" rel="noopener">{{ trans('entities.export_pdf') }} <span class="text-muted float right">.pdf</span></a></li>
<li><a href="{{ $entity->getUrl('/export/plaintext') }}" target="_blank" rel="noopener">{{ trans('entities.export_text') }} <span class="text-muted float right">.txt</span></a></li>
+ <li><a href="{{ $entity->getUrl('/export/markdown') }}" target="_blank" rel="noopener">{{ trans('entities.export_md') }} <span class="text-muted float right">.md</span></a></li>
</ul>
-</div>
\ No newline at end of file
+</div>
Route::put('/{bookSlug}/sort', 'BookSortController@update');
Route::get('/{bookSlug}/export/html', 'BookExportController@html');
Route::get('/{bookSlug}/export/pdf', 'BookExportController@pdf');
+ Route::get('/{bookSlug}/export/markdown', 'BookExportController@markdown');
+ Route::get('/{bookSlug}/export/zip', 'BookExportController@zip');
Route::get('/{bookSlug}/export/plaintext', 'BookExportController@plainText');
// Pages
Route::get('/{bookSlug}/page/{pageSlug}', 'PageController@show');
Route::get('/{bookSlug}/page/{pageSlug}/export/pdf', 'PageExportController@pdf');
Route::get('/{bookSlug}/page/{pageSlug}/export/html', 'PageExportController@html');
+ Route::get('/{bookSlug}/page/{pageSlug}/export/markdown', 'PageExportController@markdown');
Route::get('/{bookSlug}/page/{pageSlug}/export/plaintext', 'PageExportController@plainText');
Route::get('/{bookSlug}/page/{pageSlug}/edit', 'PageController@edit');
Route::get('/{bookSlug}/page/{pageSlug}/move', 'PageController@showMove');
Route::get('/{bookSlug}/chapter/{chapterSlug}/permissions', 'ChapterController@showPermissions');
Route::get('/{bookSlug}/chapter/{chapterSlug}/export/pdf', 'ChapterExportController@pdf');
Route::get('/{bookSlug}/chapter/{chapterSlug}/export/html', 'ChapterExportController@html');
+ Route::get('/{bookSlug}/chapter/{chapterSlug}/export/markdown', 'ChapterExportController@markdown');
Route::get('/{bookSlug}/chapter/{chapterSlug}/export/plaintext', 'ChapterExportController@plainText');
Route::put('/{bookSlug}/chapter/{chapterSlug}/permissions', 'ChapterController@permissions');
Route::get('/{bookSlug}/chapter/{chapterSlug}/delete', 'ChapterController@showDelete');