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
ChromeLayoutshells (auth, bootstrap config, initial/normalize payloads). Same role asEditorGatebut for chrome layouts instead ofSitePage.
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:
- Skip Tailwind JIT — too expensive on a timer
- Skip publishing normalizers — draft must round-trip to the canvas identical; publish rewrites would look like constant “changes”
- Keep security:
EditorHtmlSanitizer→EditorCustomCodeSanitizer→EditorHtmlSecuritySanitizer; CSSneutralizeStyleBreakout; JS viaAuthorScriptPolicy+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.