5am-code / laravel-notion-api

Effortless Notion integrations with Laravel
https://notionforlaravel.com
MIT License
408 stars 49 forks source link

Blocks to markdown/html renderer #163

Open Gummibeer opened 1 year ago

Gummibeer commented 1 year ago

Is your feature request related to a problem? Please describe. Right now you can retrieve the content of a page (child blocks) with all the notion raw data, like annotations and so on. But In case you want to render it somewhere you will have manually go through all the blocks, apply the annotations and concatenate all blocks rendered output together.

Describe the solution you'd like I've started to create a collection of renderer classes transforming the different blocks and sub-entities to markdown. Markdown as it's short and easy to store in a database or file and can be used in different languages and has no definitions of how it's rendered, with which tags, classes or could even be used in non-HTML renderers.

Describe alternatives you've considered Markdown is probably not the best/most feature-complete option as Notion allows to colorize or underline text, both aren't possible with markdown. So HTML could be a better option - even if I would like to have the choice if HTML should be implemented. So a driver-based renderer and not forcing the user to use the one we picked.

Additional context Here's for example the RichTextRenderer which is one of the most common ones and would do the most work:

<?php

namespace App\Renderers;

use FiveamCode\LaravelNotionApi\Entities\PropertyItems\RichText;
use Illuminate\Support\Str;
use Illuminate\Support\Stringable;

class RichTextRenderer extends Renderer
{
    public function __construct(protected RichText $richText)
    {
    }

    public function render(): ?string
    {
        return collect($this->richText->getRawResponse())
            ->map(static function (array $data): string {
                return Str::of($data['plain_text'])
                    ->when(
                        $data['annotations']['italic'],
                        fn (Stringable $s) => $s->prepend('_')->append('_')
                    )
                    ->when(
                        $data['annotations']['bold'],
                        fn (Stringable $s) => $s->prepend('**')->append('**')
                    )
                    ->when(
                        $data['annotations']['strikethrough'],
                        fn (Stringable $s) => $s->prepend('~')->append('~')
                    )
                    ->when(
                        $data['annotations']['code'],
                        fn (Stringable $s) => $s->prepend('`')->append('`')
                    )
                    ->when(
                        $data['type'] === 'mention' && $data['mention']['type'] === 'page',
                        fn (Stringable $s) => $s->prepend('@[')->append("]({$data['mention']['page']['id']})")
                    );
            })
            ->implode('');
    }
}
johguentner commented 1 year ago

That is an amazing idea! Thank you very much for sharing @Gummibeer ! We thought about accurate access to rich-text entities a lot and put it on pause for other priority stuff. Really like the concept of having different drivers for rendering rich-text. As other things (like updating the version etc.) still have higher priority, I'll mark this as feature for the (hopefully) near future.

Gummibeer commented 1 year ago

As I already have some code here - if you would point me to the API you would want to provide I could potentially work on that one. Probably something like the PHP League commonmark. So a super simple entry point where you only pass in one block or a list of blocks and as a result receive HTML/Markdown/... Internally it could use a register of renderers that can even be overridden to handle all the different blocks. For example the link block could be very likely to be customized as I think that most people with the need to render the notion page would want a custom link instead of the notion page link.

CeriseGoutPelican commented 2 weeks ago

This would actually be an amazing update that I am really looking forward to. If I can help in any way, please do not hesitate to tag me.

I do like the approach of zusamarehan/laravel-notion-renderer