Renders Mithril components to HTML for use in blade templates

Overview

Flarum Mithril2Html

Uses Chrome Puppeteer via Spatie Browsershot to render Mithril components as static HTML.

Follow Browsershot instructions to setup Node and Headless Chrome.

This is intended for use with emails or other offline content generation.

It's probably not a good idea to use this outside of a queue because of the delays it introduces.

Usage

In your extension's extend.php, call the setup extender before registering any asset:

The extender can be called by multiple extensions without issues. It won't do anything once already registered.

return [
    new \ClarkWinkelmann\Mithril2Html\Extend\Setup(),
    
    // Your other extenders
];

Create a new page just like you would a normal Flarum page:

import Page from 'flarum/common/components/Page';

class HelloWorld extends Page {
    view() {
        return <p>Hello World</p>;
    }
}

app.initializers.add('demo', function () {
    app.routes.helloWorld = {
        path: '/hello-world',
        component: HelloWorld,
    };
});

To save up space in the forum bundle or to prevent conflicts, you can add your page only to the mithril2html frontend. You will need to update your webpack config to add an additional entry file, see this package's webpack.config.js for an example.

If you created a separate bundle (not forum), register it using Flarum's Frontend extender:

    (new Frontend('mithril2html'))
        ->js(__DIR__ . '/js/dist/mithril2html.js'),

If you already have a forum bundle with exports, Flarum will unfortunately override all forum exports with mithril2html exports (even if you have none). To work around this, a different extender is available just for javascript:

    (new \ClarkWinkelmann\Mithril2Html\Extend\FrontendNoConflict('mithril2html'))
        ->js(__DIR__ . '/js/dist/mithril2html.js'),

You can then use the Renderer class to render the component:

$component = new ClarkWinkelmann\Mithril2Html\AnonymousComponent('hello-world');
echo resolve(ClarkWinkelmann\Mithril2Html\Renderer::class)->render($component);
// 

Hello World

Alternatively, you can use the blade directive directly:

@mithril2html(new ClarkWinkelmann\Mithril2Html\AnonymousComponent('hello-world'))

You can configure additional options using a component class. The class must implement ClarkWinkelmann\Mithril2Html\ComponentInterface. AnonymousComponent is a simple class that allows customizing all parameters without creating additional classes.

The parameters customizable through a component class are:

  • route: The Mithril route name without leading slash.
  • preload: An API route to preload through the API Client. With leading slash.
  • actor: An actor to use for the request. Defaults to guest.
  • selector: A CSS selector targeting the HTML to return. That element's innerHTML will be returned. If the selector can't be found, an exception will be thrown.

Using a custom component class helps keep things clean when preloading is necessary:

class InvoiceComponent implements ComponentInterface {
    protected $invoice;

    public function __construct(Invoice $invoice)
    {
        $this->invoice = $invoice;
    }

    public function route(): string
    {
        return 'invoice';
    }

    public function preload(): ?string
    {
        return '/invoices/' . $this->invoice->id;
    }

    public function actor(): ?User
    {
        return $this->invoice->user;
    }

    public function selector(): ?string
    {
        return '#content';
    }
}

Below is a summary of your invoice:

@mithril2html(new InvoiceComponent($invoice))

Known issues

At the moment, passing an actor will authenticate the base request and preloaded apiDocument, but not any additional API request the component will make after page load.

If you render a page with user-generated content and an XSS is possible, the attacker might be able to read any API GET endpoint as administrator by first stealing the mithril2html internal token and then using that token to preload arbitrary GET endpoints.

Tests

The integration tests are a bit special because they require a working webserver that can be accessed by Chrome.

Run composer test:server before running the tests to start the PHP development server on port 8080. The server is configured with a router script that takes care of routing back to the integration tmp folder.

You might also like...
SwitchBlade: Custom Directives for the Laravel Blade templating engine

SwitchBlade: Custom Directives for the Laravel Blade templating engine

Smarty is a template engine for PHP, facilitating the separation of presentation (HTML/CSS) from application logic.

Smarty 3 template engine smarty.net Documentation For documentation see www.smarty.net/docs/en/ Requirements Smarty can be run with PHP 5.2 to PHP 7.4

A ready-to-use Model View Controller template in PHP

PHP-MVC-Template A ready-to-use Model View Controller template in PHP Use this repo as a template! (Or clone it) Start to configure your MVC file Afte

A SilverStripe Module with template methods to quickly make use of FocusPoint, LazySizes, and Object-fit

LazyFocusFit A SilverStripe module with template methods to quickly make use of FocusPoint, LazySizes and object-fit. Requirements PHP FocusPoint JS/C

YCOM Impersonate. Login as selected YCOM user 🧙‍♂️in frontend.

YCOM Impersonate Login as selected YCOM user in frontend. Features: Backend users with admin rights or YCOM[] rights, can be automatically logged in v

Blade UI Kit is a set of renderless components to utilise in your Laravel Blade views
Blade UI Kit is a set of renderless components to utilise in your Laravel Blade views

Blade UI Kit is a set of renderless components to utilise in your Laravel Blade views. In all essence, it's a collection of useful utilities, connecting the dots between different parts of the TALL stack. It was made for Blade, Laravel's powerful templating engine.

SPA Skeleton with Mithril.js and Slim Framework

A single-page application (SPA) skeleton based on Mithril.js and Slim Framework 4 trying to use good practices

A package that uses blade templates to control how markdown is converted to HTML inside Laravel, as well as providing support for markdown files to Laravel views.
A package that uses blade templates to control how markdown is converted to HTML inside Laravel, as well as providing support for markdown files to Laravel views.

Install Install via composer. $ composer require olliecodes/laravel-etched-blade Once installed you'll want to publish the config. $ php artisan vendo

Custom Blade components to add sortable/drag-and-drop HTML elements in your apps.
Custom Blade components to add sortable/drag-and-drop HTML elements in your apps.

Laravel Blade Sortable Demo Repo Installation You can install the package via composer: composer require asantibanez/laravel-blade-sortable After the

Plastic is an Elasticsearch ODM and mapper for Laravel. It renders the developer experience more enjoyable while using Elasticsearch, by providing a fluent syntax for mapping, querying, and storing eloquent models.
Plastic is an Elasticsearch ODM and mapper for Laravel. It renders the developer experience more enjoyable while using Elasticsearch, by providing a fluent syntax for mapping, querying, and storing eloquent models.

Plastic is an Elasticsearch ODM and mapper for Laravel. It renders the developer experience more enjoyable while using Elasticsearch, by providing a f

Renders consistent HTTP JSON responses for API-based projects
Renders consistent HTTP JSON responses for API-based projects

Laravel API Response is a package that helps to provide and render a consistent HTTP JSON responses to API calls as well as converting and formatting

Cagilo - a set of simple components for use in your views Laravel Blade.

Cagilo - a set of simple components for use in your views Laravel Blade. Official Documentation Documentation for Cagilo can be found on its we

Use Blade templates without the full Laravel framework

blade Use Laravel Blade templates as a standalone component without the full Laravel framework Full documentation is available at http://duncan3dc.git

Blade Snip allows you to use parts of a blade template multiple times. Basically partials, but inline.

Blade Snip Blade Snip allows you to use parts of a blade template multiple times. Basically partials, but inline: div class="products" @snip('pr

This package adds artisan commands to create VueJS components and InertiaJS components.
This package adds artisan commands to create VueJS components and InertiaJS components.

Laravel Vue Commands This package adds artisan commands to create VueJS components and InertiaJS components. Installation You can install the package

SilverStripe live templates - Speed up development with SilverStripe live templates for PhpStorm and WebStorm

SilverStripe live templates My collection of live templates for WebStorm and PhpStorm, following PSR-2, using PHPDoc, and utilizing PHP 5.4 array shor

Useful blade components and functionality for most Laravel projects.

laravel-base Note: Package is still in early stages of development, so functionality is subject to change. LaravelBase is a package I've created to pr

Laravel Livewire (TALL-stack) form generator with realtime validation, file uploads, array fields, blade form input components and more.
Laravel Livewire (TALL-stack) form generator with realtime validation, file uploads, array fields, blade form input components and more.

TALL-stack form generator Laravel Livewire, Tailwind forms with auto-generated views. Support Contributions Features This is not an admin panel genera

Vim syntax highlighting for Blade templates.

vim-blade Vim syntax highlighting for Blade templates (Laravel 4+). This plugin contributes to vim-polyglot language pack. Installation Using vim-plug

Comments
  • Constrain token to specified actor and preload to reduce XSS vector

    Constrain token to specified actor and preload to reduce XSS vector

    This is currently a low priority issue but should be addressed at some point.

    It might be possible for an attacker who finds an XSS to steal and/or reuse the internal token, which can then be used to leak other private information by accessing GET API endpoints as an administrator.

    Most importantly because the internal token never changes, it should not be exposed directly to the Headless Chrome instance. Instead a short-lived token should be passed, like a value signed from the internal token. This will then negate most of the attack vectors.

    Since the token is passed through a header, it can't be read from the page with javascript. I'm not sure whether Chrome will re-send that token in other circumstances or not. If the headers are only sent with the initial page request and never again, the attack vector might be non-existent.

    The following situations need testing:

    • Can you perform an extra API request and read the header from the request/response?
    • Can you force a page reload with partially overridden headers?

    The Puppeteer documentation suggests the order of the headers is not guaranteed https://pptr.dev/api/puppeteer.page.setextrahttpheaders/ so I think that this suggests that in the event an attacker tries to provide alternate values for X-Browsershot-User or X-Browsershot-Preload, they will also have to try until their own header gets in front of the original one, otherwise the backend would never read it. Maybe the backend could throw an error if there is more than one value per header.

    opened by clarkwinkelmann 0
Releases(1.3.0)
  • 1.3.0(Dec 30, 2022)

    • Added Renderer::browsershot() method to allow more advanced usage of browsershot like PDF or screenshot rendering.
    • Added CSS support in Mithril2Html frontend to be used with the new feature.
    • Now requires PHP 7.4 or higher.
    Source code(tar.gz)
    Source code(zip)
  • 1.2.0(Dec 20, 2022)

    • Add /test endpoint as an always-available route inside the Mithril2Html frontend
    • Make test the default route for mithril2html:troubleshoot if not provided
    • Fix error when calling mithril2html:troubleshoot command without --actor=
    Source code(tar.gz)
    Source code(zip)
  • 1.1.0(Nov 13, 2022)

    • Updated code to use Webpack 5.
    • Fixed compatibility with extensions that provide their bundles compiled with Webpack 5.
    • Added different default content for single page app 404 page.
    • Added mithril2html:troubleshoot command to manually render a given URL, and obtain console output and request log from Chrome.
    • A 500 error in the preload call now makes Chrome fail with a 500 error rather than boot into the single page app which then breaks on invalid payload.
    • A 404 error in the preload now makes the rendering fail with a 500 error rather than a 404 error which wouldn't be logged anywhere.
    • The PHP renderer now throws custom exception classes, but the error text is unchanged.
    Source code(tar.gz)
    Source code(zip)
  • 1.0.0(Aug 26, 2021)

Owner
Clark Winkelmann
Webdesign, open source and electric car enthusiast
Clark Winkelmann
The free-to-use template for your Imagehost-website made with PHP, HTML and CSS!

The free-to-use template for your Imagehost-website made with PHP, HTML and CSS! Some information before we start This repo is only code related, to a

Ilian 6 Jul 22, 2022
The free-to-use template for your Imagehost-website made with PHP, HTML and CSS!

The free-to-use template for your Imagehost-website made with PHP, HTML and CSS! Some information before we start This repo is only code related, to a

Ilian 6 Jul 22, 2022
PHP template engine for native PHP templates

FOIL PHP template engine, for PHP templates. Foil brings all the flexibility and power of modern template engines to native PHP templates. Write simpl

Foil PHP 167 Dec 3, 2022
Contao extension to provide content templates for pages.

Contao Content Templates In Contao, the regular content of a page can be made up of different articles, each assigned to different sections of a page

inspiredminds 7 Oct 11, 2022
Document templates Laravel package is intended for creating/managing user editable document template

Document Templates Introduction Document templates Laravel package is intended for creating/managing user editable document templates, with ability to

42coders 139 Dec 15, 2022
Laravel Live Templates for PhpStorm

Laravel Live Templates for PhpStorm How to: Go to Preferences | Tools | Settings Repository Add Read-only Source https://github.com/koomai/phpstorm-la

Sid 1.2k Dec 22, 2022
Qiq templates for PHP 8.

Qiq Templates for PHP 8 This package provides a PHP 8.0 implementation of the TemplateView and TwoStepView patterns using PHP itself as the templating

null 18 Nov 24, 2022
Simple PHP templating system for user editable templates.

Simple template Simple PHP templating system for user editable templates. Idea Most applications need to render templates that insert safely treated v

Baraja packages 1 Jan 23, 2022
Foil brings all the flexibility and power of modern template engines to native PHP templates

Foil brings all the flexibility and power of modern template engines to native PHP templates. Write simple, clean and concise templates with nothing more than PHP.

Foil PHP 167 Dec 3, 2022
Yii2 Gii Extended templates and generators

model template with TimestampBehavior and BlameableBehavior according to columns

潘文斌 1 Feb 12, 2020