diff --git a/CHANGELOG.md b/CHANGELOG.md index 75389d8..ddeabee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## 1.0.9 - 23th January 2024 +- Adding Aside block rendering +- Updating rector 0.19 + ## 1.0.8 - 2nd January 2024 - Fixing and updating the Sample PDF generation diff --git a/art/aside-examples.png b/art/aside-examples.png new file mode 100644 index 0000000..34095e0 Binary files /dev/null and b/art/aside-examples.png differ diff --git a/composer.lock b/composer.lock index d9efa80..e5c496e 100644 --- a/composer.lock +++ b/composer.lock @@ -526,16 +526,16 @@ }, { "name": "illuminate/collections", - "version": "v10.41.0", + "version": "v10.42.0", "source": { "type": "git", "url": "https://github.com/illuminate/collections.git", - "reference": "82025fd7ac761cc50d5dbd9f9532ebf066821858" + "reference": "221c1ee944cb20ed807a8a5e8668552d6ca736ff" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/collections/zipball/82025fd7ac761cc50d5dbd9f9532ebf066821858", - "reference": "82025fd7ac761cc50d5dbd9f9532ebf066821858", + "url": "https://api.github.com/repos/illuminate/collections/zipball/221c1ee944cb20ed807a8a5e8668552d6ca736ff", + "reference": "221c1ee944cb20ed807a8a5e8668552d6ca736ff", "shasum": "" }, "require": { @@ -577,11 +577,11 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2024-01-01T15:17:18+00:00" + "time": "2024-01-22T13:55:20+00:00" }, { "name": "illuminate/conditionable", - "version": "v10.41.0", + "version": "v10.42.0", "source": { "type": "git", "url": "https://github.com/illuminate/conditionable.git", @@ -627,7 +627,7 @@ }, { "name": "illuminate/contracts", - "version": "v10.41.0", + "version": "v10.42.0", "source": { "type": "git", "url": "https://github.com/illuminate/contracts.git", @@ -675,16 +675,16 @@ }, { "name": "illuminate/filesystem", - "version": "v10.41.0", + "version": "v10.42.0", "source": { "type": "git", "url": "https://github.com/illuminate/filesystem.git", - "reference": "c765c61cf1308d4f5f3dc3c03ed5f920953b795c" + "reference": "782e0bf05709f8b0395f54174ce0b66334324eea" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/filesystem/zipball/c765c61cf1308d4f5f3dc3c03ed5f920953b795c", - "reference": "c765c61cf1308d4f5f3dc3c03ed5f920953b795c", + "url": "https://api.github.com/repos/illuminate/filesystem/zipball/782e0bf05709f8b0395f54174ce0b66334324eea", + "reference": "782e0bf05709f8b0395f54174ce0b66334324eea", "shasum": "" }, "require": { @@ -738,11 +738,11 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2023-12-21T15:30:21+00:00" + "time": "2024-01-17T15:07:27+00:00" }, { "name": "illuminate/macroable", - "version": "v10.41.0", + "version": "v10.42.0", "source": { "type": "git", "url": "https://github.com/illuminate/macroable.git", @@ -788,16 +788,16 @@ }, { "name": "illuminate/support", - "version": "v10.41.0", + "version": "v10.42.0", "source": { "type": "git", "url": "https://github.com/illuminate/support.git", - "reference": "1355b7d28ebb802e95bffcb27417862961382c52" + "reference": "11a87daf9c4bef3d654c853161b34e11a6ca0618" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/support/zipball/1355b7d28ebb802e95bffcb27417862961382c52", - "reference": "1355b7d28ebb802e95bffcb27417862961382c52", + "url": "https://api.github.com/repos/illuminate/support/zipball/11a87daf9c4bef3d654c853161b34e11a6ca0618", + "reference": "11a87daf9c4bef3d654c853161b34e11a6ca0618", "shasum": "" }, "require": { @@ -855,7 +855,7 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2024-01-15T18:53:10+00:00" + "time": "2024-01-22T18:45:06+00:00" }, { "name": "league/commonmark", @@ -1346,16 +1346,16 @@ }, { "name": "nesbot/carbon", - "version": "2.72.1", + "version": "2.72.2", "source": { "type": "git", "url": "https://github.com/briannesbitt/Carbon.git", - "reference": "2b3b3db0a2d0556a177392ff1a3bf5608fa09f78" + "reference": "3e7edc41b58d65509baeb0d4a14c8fa41d627130" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/2b3b3db0a2d0556a177392ff1a3bf5608fa09f78", - "reference": "2b3b3db0a2d0556a177392ff1a3bf5608fa09f78", + "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/3e7edc41b58d65509baeb0d4a14c8fa41d627130", + "reference": "3e7edc41b58d65509baeb0d4a14c8fa41d627130", "shasum": "" }, "require": { @@ -1449,35 +1449,35 @@ "type": "tidelift" } ], - "time": "2023-12-08T23:47:49+00:00" + "time": "2024-01-19T00:21:53+00:00" }, { "name": "nette/schema", - "version": "v1.2.5", + "version": "v1.3.0", "source": { "type": "git", "url": "https://github.com/nette/schema.git", - "reference": "0462f0166e823aad657c9224d0f849ecac1ba10a" + "reference": "a6d3a6d1f545f01ef38e60f375d1cf1f4de98188" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nette/schema/zipball/0462f0166e823aad657c9224d0f849ecac1ba10a", - "reference": "0462f0166e823aad657c9224d0f849ecac1ba10a", + "url": "https://api.github.com/repos/nette/schema/zipball/a6d3a6d1f545f01ef38e60f375d1cf1f4de98188", + "reference": "a6d3a6d1f545f01ef38e60f375d1cf1f4de98188", "shasum": "" }, "require": { - "nette/utils": "^2.5.7 || ^3.1.5 || ^4.0", - "php": "7.1 - 8.3" + "nette/utils": "^4.0", + "php": "8.1 - 8.3" }, "require-dev": { - "nette/tester": "^2.3 || ^2.4", + "nette/tester": "^2.4", "phpstan/phpstan-nette": "^1.0", - "tracy/tracy": "^2.7" + "tracy/tracy": "^2.8" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.2-dev" + "dev-master": "1.3-dev" } }, "autoload": { @@ -1509,9 +1509,9 @@ ], "support": { "issues": "https://github.com/nette/schema/issues", - "source": "https://github.com/nette/schema/tree/v1.2.5" + "source": "https://github.com/nette/schema/tree/v1.3.0" }, - "time": "2023-10-05T20:37:59+00:00" + "time": "2023-12-11T11:54:22+00:00" }, { "name": "nette/utils", @@ -3350,16 +3350,16 @@ "packages-dev": [ { "name": "laravel/pint", - "version": "v1.13.9", + "version": "v1.13.10", "source": { "type": "git", "url": "https://github.com/laravel/pint.git", - "reference": "e3e269cc5d874c8efd2dc7962b1c7ff2585fe525" + "reference": "e2b5060885694ca30ac008c05dc9d47f10ed1abf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/pint/zipball/e3e269cc5d874c8efd2dc7962b1c7ff2585fe525", - "reference": "e3e269cc5d874c8efd2dc7962b1c7ff2585fe525", + "url": "https://api.github.com/repos/laravel/pint/zipball/e2b5060885694ca30ac008c05dc9d47f10ed1abf", + "reference": "e2b5060885694ca30ac008c05dc9d47f10ed1abf", "shasum": "" }, "require": { @@ -3370,8 +3370,8 @@ "php": "^8.1.0" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^3.47.0", - "illuminate/view": "^10.40.0", + "friendsofphp/php-cs-fixer": "^3.47.1", + "illuminate/view": "^10.41.0", "larastan/larastan": "^2.8.1", "laravel-zero/framework": "^10.3.0", "mockery/mockery": "^1.6.7", @@ -3412,7 +3412,7 @@ "issues": "https://github.com/laravel/pint/issues", "source": "https://github.com/laravel/pint" }, - "time": "2024-01-16T17:39:29+00:00" + "time": "2024-01-22T09:04:15+00:00" }, { "name": "phpstan/phpstan", diff --git a/readme.md b/readme.md index 4722949..217819e 100644 --- a/readme.md +++ b/readme.md @@ -6,9 +6,8 @@ ## Create eBooks with Markdown -Are you a content creator looking to streamline your eBook creation process? -Look no further. -Ibis Next is your all-in-one solution, meticulously crafted to empower you in transforming your ideas into polished eBooks with unparalleled ease. +Ibis Next is an open source tool developed for ebook creators who want to focus on content creation. +Ibis Next supports writing in Markdown format and offers the capability to generate ebooks in PDF or EPUB format. The tool aims to simplify the ebook creation process, allowing the writers to concentrate on their content while providing functionality for converting it into polished ebooks efficiently. ### What is Ibis Next? @@ -16,16 +15,16 @@ Ibis Next is a PHP-based tool specifically designed to simplify the entire eBook ### Key features -- **Markdown Magic**: Write your content using the simplicity and versatility of Markdown. +- **Markdown**: Write your content using the simplicity and versatility of Markdown. - **Automatic Generation**: Effortlessly create PDF or EPUB files with a single command using the `ibis-next pdf` command or `ibis-next epub`. -- **Aesthetic Appeal**: Elevate your eBooks with a professionally designed cover photo, a clickable auto-generated table of contents, and code syntax highlighting. +- **Aesthetic Appeal**: create your eBooks with a custom cover photo, a clickable auto-generated table of contents, and code syntax highlighting. - **Theme Options**: Choose between two visually appealing themes - Light and Dark (theme support available for PDFs). ### Why Choose Ibis Next? -Ibis Next eliminates the complexities of manual formatting, allowing you to concentrate on what matters most - your content. With Ibis Next, the once-daunting process of eBook creation becomes a smooth and enjoyable experience. +Ibis Next is a powerful tool for effortlessly creating digital books (e-books) in EPUB and PDF formats. With Ibis Next, writers can concentrate on crafting content without worrying about formatting. The content is authored in Markdown format, allowing for simplicity and flexibility. -This documentation serves as your guide to unlocking the full potential of Ibis Next. Whether you are a seasoned developer integrating Ibis Next into your workflow or a content creator exploring the possibilities, each section will provide insights, instructions, and best practices to ensure a seamless experience. +Ibis Next seamlessly handles the conversion process, ensuring a hassle-free transition from Markdown to the correct EPUB and PDF formats. Embracing markdown streamlines the writing process and enhances collaboration and ease of editing, making it an ideal choice for authors seeking efficiency and a focus on content creation. Get ready to revolutionize your eBook creation process with Ibis Next! @@ -147,8 +146,50 @@ Inside the `content` directory, you can write multiple `.md` files. Ibis uses th `

` tags define different titles inside a chapter. ~~~ -### Adding different quotes +### Adding Aside +Inspired by the great Astro Starlight tool for creating technical documentation we support aside block. +Taking the definition from Astro Starlight documentation: +Asides (also known as “admonitions” or “callouts”) are useful for displaying secondary information alongside a page’s main content. + +

+ Aside block examples +

+ + +Ibis Next offers a tailored Markdown syntax designed for presenting asides. To demarcate aside blocks, use a set of triple colons `:::` to enclose your content, specifying the type as `note`, `tip`, `caution`, or `danger`. + +While you have the flexibility to nest various other Markdown content types within an aside, it is recommended to use asides for brief and succinct portions of content. + +~~~markdown +:::note +**Ibis Next** is an open-source tool, and you can contribute to the project by joining the [Ibis Next GitHub repository](https://github.com/Hi-Folks/ibis-next). +::: + +:::warning +**Ibis Next** is an open-source tool, and you can contribute to the project by joining the [Ibis Next GitHub repository](https://github.com/Hi-Folks/ibis-next). +::: +:::tip +**Ibis Next** is an open-source tool, and you can contribute to the project by joining the [Ibis Next GitHub repository](https://github.com/Hi-Folks/ibis-next). +::: + +:::danger +**Ibis Next** is an open-source tool, and you can contribute to the project by joining the [Ibis Next GitHub repository](https://github.com/Hi-Folks/ibis-next). +::: +~~~ + +You can also customize the title od the aside block using the square brackets `[your title]` in this way: + +~~~markdown +:::tip[My two cents] +I want to give you a piece of advice: use **Ibis Next** to create your e-books. +::: +~~~ + +In the example above, the aside type "tip" was used (`:::tip`), with a custom title "My two cents" (`[My two cents]`) and the content of the block can contain text formatted with classic Markdown markers. + +### Adding different quotes +For historical reason Ibis Next supports also another syntax for the quoutes. The suggestion is to use the Aside instead of these (deprecated) quotes. Three different types of quotes can be added: `quote`, `warning`, and `notice`. ~~~markdown diff --git a/src/Commands/BaseBuildCommand.php b/src/Commands/BaseBuildCommand.php index 6955c42..d3d76e3 100644 --- a/src/Commands/BaseBuildCommand.php +++ b/src/Commands/BaseBuildCommand.php @@ -3,6 +3,7 @@ namespace Ibis\Commands; use Ibis\Config; +use Ibis\Markdown\Extensions\AsideExtension; use SplFileInfo; use Illuminate\Filesystem\Filesystem; @@ -71,6 +72,7 @@ protected function buildHtml(string $path, array $config): Collection $environment->addExtension(new GithubFlavoredMarkdownExtension()); $environment->addExtension(new TableExtension()); $environment->addExtension(new FrontMatterExtension()); + $environment->addExtension(new AsideExtension()); $environment->addRenderer(FencedCode::class, new FencedCodeRenderer([ 'html', 'php', 'js', 'bash', 'json' diff --git a/src/Markdown/Extensions/Aside.php b/src/Markdown/Extensions/Aside.php new file mode 100644 index 0000000..8c990c1 --- /dev/null +++ b/src/Markdown/Extensions/Aside.php @@ -0,0 +1,36 @@ +title = $title === "" ? ucwords((string) $this->type) : $title; + + parent::__construct(); + } + + public function getType() + { + return $this->type; + } + + public function getTitle(): string + { + return $this->title; + } + +} diff --git a/src/Markdown/Extensions/AsideBlockParser.php b/src/Markdown/Extensions/AsideBlockParser.php new file mode 100644 index 0000000..5e9469a --- /dev/null +++ b/src/Markdown/Extensions/AsideBlockParser.php @@ -0,0 +1,52 @@ +aside = new Aside($type, $title); + } + + public function getBlock(): AbstractBlock + { + return $this->aside; + } + + public function isContainer(): bool + { + return true; + } + + public function canHaveLazyContinuationLines(): bool + { + return false; + } + + public function canContain(AbstractBlock $childBlock): bool + { + return true; + } + + public function tryContinue(Cursor $cursor, BlockContinueParserInterface $activeBlockParser): ?BlockContinue + { + if ($cursor->getLine() === ":::") { + return BlockContinue::finished(); + } + + return BlockContinue::at($cursor); + } + + public function addLine(string $line): void {} + + public function closeBlock(): void {} + +} diff --git a/src/Markdown/Extensions/AsideExtension.php b/src/Markdown/Extensions/AsideExtension.php new file mode 100644 index 0000000..e2d6486 --- /dev/null +++ b/src/Markdown/Extensions/AsideExtension.php @@ -0,0 +1,15 @@ +addBlockStartParser(new AsideParser()) + ->addRenderer(Aside::class, new AsideRenderer()); + } +} diff --git a/src/Markdown/Extensions/AsideParser.php b/src/Markdown/Extensions/AsideParser.php new file mode 100644 index 0000000..36d863a --- /dev/null +++ b/src/Markdown/Extensions/AsideParser.php @@ -0,0 +1,60 @@ +getRemainder(), ':::note') + || str_starts_with($cursor->getRemainder(), ':::notice')) { + $type = Aside::TYPE_NOTE; + $title = "Note"; + $isAside = true; + } + + if (str_starts_with($cursor->getRemainder(), ':::warning') || + str_starts_with($cursor->getRemainder(), ':::caution')) { + $type = Aside::TYPE_CAUTION; + $title = "Caution"; + $isAside = true; + } + + if (str_starts_with($cursor->getRemainder(), ':::tip')) { + $type = Aside::TYPE_TIP; + $title = "Tip"; + $isAside = true; + } + + if (str_starts_with($cursor->getRemainder(), ':::danger')) { + $type = Aside::TYPE_DANGER; + $title = "Danger"; + $isAside = true; + } + + if ($isAside) { + $pattern = '/\[([^]]+)\]/'; + if (preg_match($pattern, $cursor->getRemainder(), $matches)) { + $title = $matches[1]; + } + + $cursor->advanceToNextNonSpaceOrTab(); + $cursor->advanceToEnd(); + + return BlockStart::of(new AsideBlockParser($type, $title))->at($cursor); + } + + return BlockStart::none(); + + + + } +} diff --git a/src/Markdown/Extensions/AsideRenderer.php b/src/Markdown/Extensions/AsideRenderer.php new file mode 100644 index 0000000..0f40cef --- /dev/null +++ b/src/Markdown/Extensions/AsideRenderer.php @@ -0,0 +1,30 @@ +data->getData('attributes'); + $contents = $childRenderer->renderNodes($node->children()); + $blockQuoteContent = new HtmlElement('div', $attrs->export(), $contents); + $blockQuoteTitle = ""; + if ($node->getTitle() !== "") { + $blockQuoteTitle = new HtmlElement('div', ["class" => "title"], $node->getTitle()); + } + + return new HtmlElement( + 'blockquote', + ['class' => $node->getType()], + $blockQuoteTitle . $blockQuoteContent + ); + } +}