clarkwinkelmann / flarum-mithril2html
将 Mithril 组件渲染为 HTML,以便在 blade 模板中使用
Requires
- php: ^7.4|^8.0
- ext-json: *
- flarum/core: ^1.2
- spatie/browsershot: ^3.0
- symfony/css-selector: ^5.0
- symfony/dom-crawler: ^5.0
Requires (Dev)
- flarum/testing: ^1.0
This package is auto-updated.
Last update: 2024-08-29 06:07:41 UTC
README
使用 Chrome Puppeteer 通过 Spatie Browsershot 将 Mithril 组件渲染为静态 HTML。
按照 Browsershot 指示设置 Node 和无头 Chrome。
此功能旨在与电子邮件或其他离线内容生成一起使用。
由于引入了延迟,因此不建议在队列之外使用此功能。
用法
在你的扩展的 extend.php
中,在注册任何资产之前调用设置扩展器
扩展器可以被多个扩展调用而不会出现问题。一旦已注册,它将不会做任何事情。
return [ new \ClarkWinkelmann\Mithril2Html\Extend\Setup(), // Your other extenders ];
创建一个新页面,就像创建一个普通的 Flarum 页面一样
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, }; });
为了节省空间在 forum
包中或为了避免冲突,你可以将你的页面仅添加到 mithril2html
前端。你需要更新你的 webpack 配置以添加一个额外的入口文件,请参阅此包的 webpack.config.js
以获取示例。
如果你创建了一个单独的包(不是 forum
),请使用 Flarum 的 Frontend
扩展器进行注册
(new Frontend('mithril2html')) ->js(__DIR__ . '/js/dist/mithril2html.js'),
如果你已经有一个带有导出的论坛包,不幸的是,Flarum 将会覆盖所有 forum
导出以 mithril2html
导出(即使你没有) 。为了解决这个问题,有一个仅针对 JavaScript 的不同扩展器可用
(new \ClarkWinkelmann\Mithril2Html\Extend\FrontendNoConflict('mithril2html')) ->js(__DIR__ . '/js/dist/mithril2html.js'),
然后你可以使用 Renderer
类来渲染组件
$component = new ClarkWinkelmann\Mithril2Html\AnonymousComponent('hello-world'); echo resolve(ClarkWinkelmann\Mithril2Html\Renderer::class)->render($component); // <p>Hello World</p>
或者,你可以直接使用 blade 指令
@mithril2html(new ClarkWinkelmann\Mithril2Html\AnonymousComponent('hello-world'))
你可以使用组件类来配置额外的选项。该类必须实现 ClarkWinkelmann\Mithril2Html\ComponentInterface
。 AnonymousComponent
是一个简单的类,允许自定义所有参数而不创建额外的类。
可以通过组件类自定义的参数有
route
:不带前导斜杠的 Mithril 路由名称。preload
:通过 API 客户端预加载的 API 路由。带有前导斜杠。actor
:用于请求的演员。默认为访客。selector
:指向要返回的 HTML 的 CSS 选择器。该元素的 innerHTML 将被返回。如果选择器找不到,将抛出异常。
使用自定义组件类有助于在需要预加载时保持事物的整洁
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'; } }
<p>Below is a summary of your invoice:</p>
@mithril2html(new InvoiceComponent($invoice))
PDF 和截图
虽然这不是此扩展的主要用例,但 Renderer
类还公开了一个 browsershot
方法,它提供了对预配置但未使用的 Browsershot 实例的访问。
在使用该方法时,将忽略 selector
属性,并使用整个页面/视口。必须使用 Browsershot 方法来配置输出。
示例
$component = new ClarkWinkelmann\Mithril2Html\AnonymousComponent('hello-world'); echo resolve(ClarkWinkelmann\Mithril2Html\Renderer::class)->browsershot($component)->landscape()->pdf();
当调用 Renderer::render
时,页面 CSS 不会被加载,但在调用 Renderer::browsershot
时默认加载。可以通过将 false
作为第二个参数传递来禁用此操作,如 $renderer->browsershot($component, false)
。
已知问题
目前,传递演员将验证基础请求和预加载的 apiDocument
,但不会验证组件在页面加载后所做的任何其他 API 请求。
如果您渲染包含用户生成内容的页面且存在跨站脚本攻击(XSS)的风险,攻击者可能通过首先窃取 mithril2html 内部令牌,然后使用该令牌预加载任意的 GET 端点,以管理员身份读取任何 API GET 端点。
测试
集成测试有一些特殊之处,因为它们需要一个可以被 Chrome 访问的运行中的 web 服务器。
在运行测试之前,请先运行 composer test:server
以在端口 8080
上启动 PHP 开发服务器。服务器配置了一个路由脚本,该脚本负责将路由回集成临时文件夹。