- Added tests to cover.
- Added slight extra spaces at content joins.
$text = "# " . $chapter->name . "\n\n";
$text .= $chapter->description . "\n\n";
foreach ($chapter->pages as $page) {
- $text .= $this->pageToMarkdown($page);
+ $text .= $this->pageToMarkdown($page) . "\n\n";
}
return $text;
}
*/
protected function getConverterEnvironment(): Environment
{
- $environment = new Environment(['header_style' => 'atx']);
+ $environment = new Environment([
+ 'header_style' => 'atx', // Set to 'atx' to output H1 and H2 headers as # Header1 and ## Header2
+ 'suppress_errors' => true, // Set to false to show warnings when loading malformed HTML
+ 'strip_tags' => false, // Set to true to strip tags that don't have markdown equivalents. N.B. Strips tags, not their content. Useful to clean MS Word HTML output.
+ 'strip_placeholder_links' => false, // Set to true to remove <a> that doesn't have href.
+ 'bold_style' => '**', // DEPRECATED: Set to '__' if you prefer the underlined style
+ 'italic_style' => '*', // DEPRECATED: Set to '_' if you prefer the underlined style
+ 'remove_nodes' => '', // space-separated list of dom nodes that should be removed. example: 'meta style script'
+ 'hard_break' => false, // Set to true to turn <br> into `\n` instead of ` \n`
+ 'list_item_style' => '-', // Set the default character for each <li> in a <ul>. Can be '-', '*', or '+'
+ 'preserve_comments' => false, // Set to true to preserve comments, or set to an array of strings to preserve specific comments
+ 'use_autolinks' => false, // Set to true to use simple link syntax if possible. Will always use []() if set to false
+ 'table_pipe_escape' => '\|', // Replacement string for pipe characters inside markdown table cells
+ 'table_caption_side' => 'top', // Set to 'top' or 'bottom' to show <caption> content before or after table, null to suppress
+ ]);
$environment->addConverter(new BlockquoteConverter());
$environment->addConverter(new CodeConverter());
$textContent = $this->exportFormatter->bookToPlainText($book);
return $this->downloadResponse($textContent, $book->slug . '.txt');
}
+
+ /**
+ * Export a book as a markdown file.
+ */
+ public function exportMarkdown(int $id)
+ {
+ $book = Book::visible()->findOrFail($id);
+ $markdown = $this->exportFormatter->bookToMarkdown($book);
+ return $this->downloadResponse($markdown, $book->slug . '.md');
+ }
}
use BookStack\Entities\Models\Chapter;
use BookStack\Entities\Tools\ExportFormatter;
-use BookStack\Entities\Repos\BookRepo;
use Throwable;
class ChapterExportApiController extends ApiController
$textContent = $this->exportFormatter->chapterToPlainText($chapter);
return $this->downloadResponse($textContent, $chapter->slug . '.txt');
}
+
+ /**
+ * Export a chapter as a markdown file.
+ */
+ public function exportMarkdown(int $id)
+ {
+ $chapter = Chapter::visible()->findOrFail($id);
+ $markdown = $this->exportFormatter->chapterToMarkdown($chapter);
+ return $this->downloadResponse($markdown, $chapter->slug . '.md');
+ }
}
$textContent = $this->exportFormatter->pageToPlainText($page);
return $this->downloadResponse($textContent, $page->slug . '.txt');
}
+
+ /**
+ * Export a page as a markdown file.
+ */
+ public function exportMarkdown(int $id)
+ {
+ $page = Page::visible()->findOrFail($id);
+ $markdown = $this->exportFormatter->pageToMarkdown($page);
+ return $this->downloadResponse($markdown, $page->slug . '.md');
+ }
}
Route::get('books/{id}/export/html', 'BookExportApiController@exportHtml');
Route::get('books/{id}/export/pdf', 'BookExportApiController@exportPdf');
Route::get('books/{id}/export/plaintext', 'BookExportApiController@exportPlainText');
+Route::get('books/{id}/export/markdown', 'BookExportApiController@exportMarkdown');
Route::get('chapters', 'ChapterApiController@list');
Route::post('chapters', 'ChapterApiController@create');
Route::get('chapters/{id}/export/html', 'ChapterExportApiController@exportHtml');
Route::get('chapters/{id}/export/pdf', 'ChapterExportApiController@exportPdf');
Route::get('chapters/{id}/export/plaintext', 'ChapterExportApiController@exportPlainText');
+Route::get('chapters/{id}/export/markdown', 'ChapterExportApiController@exportMarkdown');
Route::get('pages', 'PageApiController@list');
Route::post('pages', 'PageApiController@create');
Route::get('pages/{id}/export/html', 'PageExportApiController@exportHtml');
Route::get('pages/{id}/export/pdf', 'PageExportApiController@exportPdf');
Route::get('pages/{id}/export/plaintext', 'PageExportApiController@exportPlainText');
+Route::get('pages/{id}/export/markdown', 'PageExportApiController@exportMarkDown');
Route::get('shelves', 'BookshelfApiController@list');
Route::post('shelves', 'BookshelfApiController@create');
$resp->assertStatus(200);
$resp->assertHeader('Content-Disposition', 'attachment; filename="' . $book->slug . '.pdf"');
}
+
+ public function test_export_markdown_endpoint()
+ {
+ $this->actingAsApiEditor();
+ $book = Book::visible()->has('pages')->has('chapters')->first();
+
+ $resp = $this->get($this->baseEndpoint . "/{$book->id}/export/markdown");
+ $resp->assertStatus(200);
+ $resp->assertHeader('Content-Disposition', 'attachment; filename="' . $book->slug . '.md"');
+ $resp->assertSee('# ' . $book->name);
+ $resp->assertSee('# ' . $book->pages()->first()->name);
+ $resp->assertSee('# ' . $book->chapters()->first()->name);
+ }
}
\ No newline at end of file
$resp->assertStatus(200);
$resp->assertHeader('Content-Disposition', 'attachment; filename="' . $chapter->slug . '.pdf"');
}
+
+ public function test_export_markdown_endpoint()
+ {
+ $this->actingAsApiEditor();
+ $chapter = Chapter::visible()->has('pages')->first();
+
+ $resp = $this->get($this->baseEndpoint . "/{$chapter->id}/export/markdown");
+ $resp->assertStatus(200);
+ $resp->assertHeader('Content-Disposition', 'attachment; filename="' . $chapter->slug . '.md"');
+ $resp->assertSee('# ' . $chapter->name);
+ $resp->assertSee('# ' . $chapter->pages()->first()->name);
+ }
}
\ No newline at end of file
$resp->assertStatus(200);
$resp->assertHeader('Content-Disposition', 'attachment; filename="' . $page->slug . '.pdf"');
}
+
+ public function test_export_markdown_endpoint()
+ {
+ $this->actingAsApiEditor();
+ $page = Page::visible()->first();
+
+ $resp = $this->get($this->baseEndpoint . "/{$page->id}/export/markdown");
+ $resp->assertStatus(200);
+ $resp->assertSee('# ' . $page->name);
+ $resp->assertHeader('Content-Disposition', 'attachment; filename="' . $page->slug . '.md"');
+ }
}
\ No newline at end of file