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

Symfony Djot Laravel Package

php-collective/symfony-djot

Symfony integration for Djot, the lightweight markup language. Provides bundle configuration, service wiring, and Twig rendering so you can parse and display Djot content in Symfony applications with minimal setup.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit

  • symfony-djot is a thin Symfony bundle around a Djot parser; the value for a Laravel codebase lives in the framework-agnostic converter, not the bundle's DI wiring. Treat it as a library-layer dependency inside our rendering pipeline, not as a framework integration.
  • Djot is a plausible successor format to Markdown for user-authored and CMS content. Adopting it is a content-pipeline decision (storage format, authoring UX, render path), not just a Composer require — the package is the smallest part of that decision.
  • Fits cleanly behind a single DjotRenderer seam: source text in, HTML out. That keeps the parser swappable if the 0.x line stalls.

Integration feasibility

  • Composer-installable and PHP-native; the core converter can be bound in an app service provider. The bundle's Symfony container config will not be auto-discovered by Laravel, so expect to instantiate the converter and options manually — budget a small adapter, not a zero-config install.
  • The new converter options (significant_newlines, soft_break_mode, xhtml) and six extensions are all constructor/config-level, which maps well to a Laravel config file with per-context profiles (e.g. comments, docs, cms).
  • Verify Symfony component constraints against our Laravel version's transitive Symfony pins before committing; that is the most likely install-time blocker.

Technical risk

  • Highest risk: the safe_mode default flip. It is a silent output change, not a loud failure. Any content that previously rendered raw HTML will now be escaped, producing visibly mangled pages on upgrade rather than an error.
  • Second risk: the escape hatch. |djot_raw / djot_raw() is the obvious "fix" a developer will reach for when rendering breaks, which reintroduces the XSS exposure the default just closed. This needs an explicit policy before rollout, not after.
  • 0.x versioning means the safe-mode flip is a preview of the release cadence: breaking changes can land in any minor. Six new extensions in one minor also means six new surfaces whose edge cases are largely untested by us.
  • Single-maintainer/collective-project risk; no commercial support path.

Key questions

  • Is the underlying parser usable standalone without Symfony HttpKernel/DependencyInjection, or does the bundle drag framework weight into a Laravel app?
  • Does safe_mode: true escape raw HTML, strip it, or render it inertly? The answer determines whether upgrade breakage is cosmetic or content-destructive.
  • Are the six new extensions opt-in and independently scoped, or do any alter default parsing behavior?
  • What are the PHP and Symfony constraint ranges, and do they conflict with our Laravel version?
  • Is djot_raw output sanitized in any way, or fully trusted-input-only?
  • What is the compatibility story between Djot and our existing Markdown corpus — is there a conversion tool, and is round-tripping lossless?

Integration Approach

Stack fit

  • Bind the converter as a singleton in a service provider, expose a Blade directive/component and a Djot::toHtml() facade, and drive configuration from config/djot.php with named profiles. This isolates the package behind our own interface so a future swap (or a fork) is a one-file change.
  • Prefer render-at-write with cached HTML for anything on a hot path; keep render-at-read for low-volume or draft content.

Migration path

  • Do not adopt 0.2.0 defaults blindly. Land 0.2.0 with safe_mode: false set explicitly to preserve current output, ship the upgrade with zero user-visible change, then flip to the secure default as a deliberate, separately-tested step.
  • Content audit before the flip: run the full corpus through both configurations and diff rendered HTML. Every diff is either "this content was relying on raw HTML" (needs a decision) or "this content was already being escaped" (no-op).
  • Reserve djot_raw for a named allowlist of trusted, admin-only fields. Enforce it in the renderer profile, not in templates, so it cannot be reached ad hoc.

Compatibility

  • Pin exactly (0.2.0, not ^0.2) given the 0.x cadence, and treat every minor as a potential breaking change requiring the golden-file diff.
  • Confirm PHP version and Symfony constraint compatibility during the spike, before any content migration work is scheduled.

Sequencing

  1. Spike: core parser in a branch, no framework glue, confirm install and basic render.
  2. Build the DjotRenderer seam plus a golden-file test suite over a representative content corpus.
  3. Upgrade to 0.2.0 with explicit safe_mode: false; diff against baseline; expect zero deltas.
  4. Flip to safe_mode: true; triage every delta; add djot_raw only where an owner signs off.
  5. Adopt extensions one at a time, each with its own fixture set — start with admonition and tabs (high author value, low blast radius), defer inline_footnotes and heading_reference until authoring docs exist.
  6. Evaluate xhtml and soft_break_mode only if a concrete consumer (email rendering, feed output) requires them; otherwise leave defaults.

Operational Impact

Maintenance

  • The package is a moving target at 0.x. Budget recurring review time per release and assume at least one breaking change per quarter. The safe-mode flip is the template: security-motivated default changes that require content-side action.
  • Maintain the golden-file corpus as a first-class asset. It is the only reliable detector for silent rendering changes and it makes each future upgrade a diff review rather than a manual QA pass.

Support

  • Community-only support via GitHub issues; no SLA. Escalation path is "we patch our fork" — which means someone on the team must be able to read the parser, or we accept being blocked on upstream.
  • Document the djot_raw policy and the profile-to-use-case mapping internally; otherwise support requests will resolve to "turn off safe mode," which is the wrong answer.

Scaling

  • Parsing is CPU-bound pure PHP. At current volumes this is negligible; at high volume, move rendering off the request path (queue-based pre-render on save) rather than trying to optimize the parser.
  • Cached HTML scales linearly and cheaply; the practical ceiling is cache invalidation on content edits, not parse throughput.
  • The new extensions add parse work but nothing that changes the scaling shape.

Failure modes

  • Silent content regression on safe-mode flip — previously-raw HTML now escaped; pages render with visible tags or broken layout. Detect via corpus diff; mitigate by staging the flip behind a config flag.
  • XSS regression via djot_raw — a developer "fixes" a rendering break by reaching for the raw filter on user content. Mitigate by scoping djot_raw to renderer profiles, not templates, and by reviewing any PR that adds it.
  • Dependency resolution failure — Symfony constraint conflict with the Laravel version at install or upgrade time. Mitigate by pinning and testing in CI against the target Laravel matrix.
  • Double-escaping in Blade — using {{ }} around already-rendered HTML, or {!! !!} around unrendered Djot. Mitigate with a single blessed directive and a lint rule.
  • Extension interaction bugs — six new extensions, all early. Mitigate by enabling one at a time with fixtures.

Ramp-up

  • Two separate ramps: engineers (small — one adapter class, one config file, one test harness) and content authors (larger — Djot syntax diverges from Markdown, and six new extensions each add syntax to learn).
  • Author-facing cost is the under-estimated one. Do not enable extensions before publishing syntax docs and examples; an extension authors don't know about is pure parser overhead.
  • Plan roughly a sprint for the technical integration and a parallel content-audit track; the audit, not the code, is the critical path to the safe-mode default.
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.
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums
rlacerda83/query-parser
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings