Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Prosemirror To Html Laravel Package

ueberdosis/prosemirror-to-html

Convert ProseMirror and TipTap JSON documents into clean HTML with this Laravel/PHP package. Render rich text content from your editor reliably, handling nodes, marks, and nested structures through a simple, straightforward API.

Deep Wiki
Context7

Technical Evaluation

Architecture fit

  • Single-responsibility library: consumes a ProseMirror document (JSON) plus a schema definition and emits an HTML string. That maps cleanly onto a Laravel app where the front end (Tiptap/ProseMirror) persists JSON in a json/longtext column and the back end needs HTML for emails, PDFs, RSS, search indexing, or server-rendered pages.
  • It is a server-side re-implementation of the client renderer, not a bridge to the JS library. That means two renderers (JS in the editor, PHP on the server) must be kept behaviourally identical — a permanent correctness obligation, not a one-off integration.
  • Package comes from the same organisation as Tiptap, so the modelling conventions (nodes, marks, toDOM-style attribute mapping) should be familiar, but the PHP port is structurally independent of the JS source of truth.

Integration feasibility

  • Composer-installable, MIT-licensed, small dependency surface. Expect a service provider/facade registration and a config file describing the schema — a few hours to a working prototype.
  • Blocking concerns are lifecycle, not effort: archived since 2021-08-18. No PHP 8.2/8.3 hardening, no Laravel 10/11 compatibility work, no security releases. Composer constraints in composer.json will likely need overriding or a fork to install on a current stack.
  • Repository: unknown in the package metadata is a supply-chain red flag. Before adoption, verify the Packagist source/dist URLs, tag-to-commit integrity, and that the published tarball matches the tagged source.

Technical risk

  • XSS surface (high). The package's job is to turn stored JSON into HTML. Unless every attribute and text node is escaped by the schema callbacks you write, you are one custom node away from stored XSS. Sanitisation (ezyang/htmlpurifier or mews/purifier) must sit downstream, not be assumed.
  • Schema drift (high). ProseMirror documents evolve. Any node or mark type not registered in your PHP schema will either throw or be silently dropped — silent content loss on export is worse than a 500. Needs an explicit unknown-node policy and alerting.
  • Output parity (medium). Divergence between Tiptap's generateHTML and this renderer shows up as subtly different markup in emails versus the editor preview, which is hard to test for and easy to ship.
  • Abandonment (certain). Archived means zero upstream fixes. Treat this as vendored source you own, not a dependency you consume.
  • Score 0.5175 / 75 stars is consistent with a narrow, useful, low-adoption utility — not a signal of quality either way, but it does mean a thin community for triage.

Key questions

  1. Which ProseMirror/Tiptap schema version does the renderer target, and how far has our editor schema diverged?
  2. Does it support nested nodes, marks with attributes, and custom nodes via an extension point — or only the starter-kit set?
  3. What is the behaviour on an unregistered node type: exception, skip, or passthrough?
  4. Are text and attribute values escaped by default, or is that the caller's responsibility?
  5. What PHP and Laravel versions are actually exercised by the (presumably minimal) test suite?
  6. Will we fork, vendor, or wrap — and who owns the fork?

Integration Approach

Stack fit

  • Natural fit: Laravel 8–10 era application, Tiptap editor, JSON content column, server-side rendering into mailables, PDF generation (DomPDF/Snappy), sitemap/RSS, or a search index.
  • Poor fit if content is rendered only in the browser — the client renderer is maintained, this is not, and adding a second renderer buys nothing.

Migration path

  1. Isolate behind an interface. Define ContentRendererContract::toHtml(array $doc): string in the application and bind the package behind it. Nothing else in the codebase imports the package namespace. This is the single decision that makes the eventual replace-or-fork cheap.
  2. Vendor or fork. Either "repositories" fork with a maintained branch, or copy the source in-tree under app/Support/ProseMirror. Forking preserves MIT attribution and gives a place to patch PHP-version and escaping issues.
  3. Golden-file corpus. Capture 30–50 real production documents (the ugly ones: tables, nested lists, mentions, code blocks, images with attributes). Snapshot expected HTML. Run both the JS renderer and the PHP renderer over the corpus and diff. This is the acceptance gate, not a nice-to-have.
  4. Sanitise downstream. Pipe renderer output through an allowlist sanitiser with a policy per output channel (email is stricter than web).

Compatibility

  • Pin the dependency exactly; do not allow transitive drift. Check composer.json for php and illuminate/support constraints and add platform overrides only where you have tested.
  • Confirm the package's attribute-mapping model matches how our editor serialises marks; a mismatch here is the most common source of parity bugs.

Sequencing

  1. Spike: install on a branch, render the golden corpus, measure parity gap. Timebox to ~3 days.
  2. Decide: fork-and-patch vs. build a ~300-line in-house renderer vs. offload to a headless Node service using the maintained JS renderer.
  3. Ship behind the interface with the sanitiser, plus a metric on render failures and unknown-node events.
  4. Only then expose to user-facing surfaces (email, exports); keep it off the critical read path until parity is proven.

Recommendation: adopt conditionally, wrapped and forked, for non-critical rendering paths. If server-side rendering becomes a core product surface, the headless-Node option using the maintained JS renderer is the lower long-term risk.

Operational Impact

Maintenance

  • Ownership transfers to us on day one. Budget a small recurring allowance for schema additions (every new editor node is a PHP change), PHP/Laravel upgrades, and escaping review.
  • Track upstream changes in Tiptap's JS renderer manually; there is no upstream to follow.

Support

  • No upstream maintainer, no issue triage, no CVE response. Internal escalation only. Document the fork's provenance and patch history so a future maintainer can reason about it.
  • Low bus factor risk if the wrapper interface is honoured — the fallback is to swap the implementation, not rewrite call sites.

Scaling

  • Pure PHP string assembly; CPU-bound and linear in document size. Negligible for typical article-length content.
  • Watch the pathological cases: very large documents (long-form docs, imported content), and rendering in a loop (bulk export, backfill). Move bulk jobs to the queue rather than rendering inline in a request.
  • No caching built in — cache rendered HTML by content hash and schema version, and invalidate on either change.

Failure modes

Failure Symptom Mitigation
Unknown node/mark Exception or silent content loss Explicit policy + counter metric + alert
Unescaped attribute Stored XSS Downstream allowlist sanitiser, non-negotiable
Malformed JSON 500 on render Validate against schema on write, not on read
Composer conflict Install/upgrade blocked Exact pin + fork with widened constraints
Renderer divergence Email ≠ editor preview Golden-file parity suite in CI
Abandonment No fix for PHP/Laravel upgrade Fork we control; interface boundary

Ramp-up

  • Engineer ramp-up is low: small API, a few hours to first render. The real cost is ProseMirror schema fluency — understanding node/mark/attribute structure well enough to write correct renderers. Assume 1–2 days of learning per engineer, and require review from whoever owns the editor schema.
  • Operational ramp-up is the bigger ask: runbooks for the unknown-node alert, the sanitiser policy, and the fork's release process. Without these the package quietly becomes unowned infrastructure.

Verdict: acceptable as an internal, forked, wrapped utility for secondary rendering paths; not acceptable as an unexamined Composer dependency on the critical path. The archived status and missing repository provenance push this from "convenient" to "you are now the maintainer."

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox