EditorGate & bootstrap

Sample documentation (demo only)
This is an incomplete, outdated docs snapshot shipped with the playground — screenshots were removed on purpose.
For the full, current manuals go to voodflow.com/docs.

Voodflow\Voodbuilder\Support\Editor\EditorChromeLayoutEditorGate

  • File: Support/Editor/EditorChromeLayoutEditorGate.php
  • Kind: final class
  • Responsibility: Parallel gate for ChromeLayout shells (auth, bootstrap config, initial/normalize payloads). Same role as EditorGate but for chrome layouts instead of SitePage.

Methods

Signature Behaviour
canEdit(ChromeLayout $layout): bool Chrome layouts enabled ∧ LayoutsModule ∧ page-builder access
isEditing(ChromeLayout $layout): bool canEdit ∧ request edit=1
config(ChromeLayout $layout): array Bootstrap JSON for chrome canvas (save URLs, reading typography, entitlements, allowlists)
initialPayload(ChromeLayout $layout): array Initial html/css/js loaded into the chrome canvas
normalizePayload(array $payload): array Sanitize/normalize chrome save payload (no SitePage context)

Voodflow\Voodbuilder\Support\Editor\EditorGate

  • File: Support/Editor/EditorGate.php
  • Kind: final class
  • Responsibility: Central visual-editor gate for SitePage: authorization, GrapesJS bootstrap config, initial canvas payload, publish normalize, draft sanitize.

Called by: page Blade when ?edit=1, EditorPageController on save, History autosave path, chrome/page shared entitlement helpers.

Providers & authorization

Signature Behaviour
registerLabelProvider(callable(): array): void Companion i18n labels merged into bootstrap
registerConfigProvider(callable(): array): void Companion keys merged into bootstrap (URLs, feature flags)
flushLabelProviders(): void Clear label providers (tests)
flushConfigProviders(): void Clear config providers (tests)
authorizeUsing(?callable): void Override canEdit; null restores default
canEdit(SitePage $page): bool Custom authorizer or userCanEdit
userCanEdit(SitePage $page): bool editor.enabled ∧ PagesModule ∧ usesEditorBuilder() ∧ PageBuilderAccess
isEditing(SitePage $page): bool canEdit ∧ query edit=1

Bootstrap config & catalogs

Signature Behaviour
config(SitePage $page): array Full GrapesJS bootstrap: save/revision URLs, chrome shell mode, entitlements, labels, catalogs, compile-css URL, companion config
mergedCompanionConfig(): array (protected) Merges all registerConfigProvider callables
sharedEntitlements(): array Capability flags shared by page / chrome / popup bootstraps
sharedElementsCatalogOptions(bool $includeTemplates = true): array Elements (+ optional Templates) library modal bundles; user components excluded
sharedEditorLabels(): array Core labels + all label providers

Payload I/O

initialPayload(SitePage $page): array

Builds the html/css/js (+ metadata) first loaded into the canvas. Applies chrome strip / binding preview when editing so the author sees resolved data without publishing.

normalizePayload(array $payload, bool $recompilePageCss = false, ?string $previousFullCss = null, ?string $previousClassFingerprint = null, ?string $liveUtilitiesCss = null): array

Publish/save path. Called from EditorPageController with $recompilePageCss = true. Returns normalized html, css, js, fonts, optional project, optional css_class_fingerprint.

Ordered steps (do not reorder without tests):

# Call Why
1 EditorHtmlSanitizer::sanitize Allowlisted tags/attrs
2 stripOrphanPageContentText Text outside content slots corrupts layout
3 stripEditorOnlyAttributes Stale data-gjs-* (e.g. corrupted droppable) blank CTAs
4 restoreEmptyCtaLabels Repair CTA labels after aggressive strip
5 EditorDynamicBlockAttributeNormalizer::normalize Stable dynamic-block attrs
6 EditorConditionsAttributeNormalizer::normalize Stable condition attrs
7 EditorCustomCodeSanitizer::sanitize Embedded custom-code nodes
8 EditorHtmlSecuritySanitizer::sanitize Real DOM parse: unquoted handlers, svg/onload, encoded schemes (regex cannot see these)
9 EditorCodeBlockNormalizer::normalize Code-block markup
10 AuthorScriptPolicy::keepOrDiscard($js) Do not store author JS when edition lacks pages.custom-js
11 ThemeToken → LibraryLayout → Placeholder → EditorBindingNormalizer → Tailwind SVG paint bake/strip Structural migrations + binding storage form
12 EditorPastedComponentNormalizer::resolvePublishedPageCss* Publish CSS; JIT path when $recompilePageCss
13 ThemePalette::stripEmbeddedPaletteOverrides Stale --vx-* in page CSS must not override admin palette
14 FontStylesheets::withDetectedFonts + EditorJsSanitizer + optional project migrate Fonts list + JS sanitize
15 css_class_fingerprint if recompile Detect utility-class drift on next save

sanitizeDraftPayload(array $payload): array

Autosave/draft path. Returns {html, css, js} only.

Narrower than normalizePayload on purpose:

  1. Skip Tailwind JIT — too expensive on a timer
  2. Skip publishing normalizers — draft must round-trip to the canvas identical; publish rewrites would look like constant “changes”
  3. Keep security: EditorHtmlSanitizer → EditorCustomCodeSanitizer → EditorHtmlSecuritySanitizer; CSS neutralizeStyleBreakout; JS via AuthorScriptPolicy + EditorJsSanitizer

Helpers

Signature Behaviour
chromeShellPreviewSubTheme(): string Sub-theme id when previewing chrome shell inside page editor
hasPersistedProject(mixed $project): bool True if Grapes project looks non-empty (has pages)

Private helpers in the same class (editorRoute, optionalEditorRoute, elementsCatalogOptions, newsletter list options, …) are not part of the public extension surface.

Demo resets in 00:29:41