Skip to content

[#311] Fixed the console errors raised while editing content. - #314

Merged
AlexSkrypnyk merged 5 commits into
developfrom
feature/311-js-errors-edit
Aug 13, 2026
Merged

[#311] Fixed the console errors raised while editing content.#314
AlexSkrypnyk merged 5 commits into
developfrom
feature/311-js-errors-edit

Conversation

@AlexSkrypnyk

@AlexSkrypnyk AlexSkrypnyk commented Aug 13, 2026

Copy link
Copy Markdown
Member

Closes #311

Checklist before requesting a review

  • Subject includes ticket number as [#123] Verb in past tense.
  • Ticket number #123 added to description
  • Added context in Changed section
  • Self-reviewed code and commented in commented complex areas.
  • Added tests for fix/feature.
  • Relevant tests run and passed locally.

Changed

  1. Excluded the base theme's files from CKEditor 5's merged internal.drupal.ckeditor5.stylesheets library in LibraryInfoAlterHook. civictheme/dist/civictheme.editor.css opens with two @import url("https://fonts.googleapis.com/...") statements, which the content security policy blocks because this site self-hosts Lexend and Rubik. The sub-theme's dist/styles.editor.css is its own build of the same partials, carrying self-hosted @font-face rules instead, and contributes every selector the base theme's copy did: comparing the two built files gives 115 selectors in the base theme's, all present among the sub-theme's 117. civictheme.variables.css goes with it for the same reason the theme already redirects the other three CivicTheme stylesheets through libraries-override: the sub-theme ships the replacement. The hook runs with OrderAfter(modules: ['ckeditor5']), since CKEditor 5 assembles that library in its own hook_library_info_alter() and would otherwise overwrite the filtered list.
  2. Added NavigationScriptHash, which derives the policy hash for the inline script core's navigation toolbar renders. That script carries no nonce, and the policy carries a nonce and no unsafe-inline, so it was blocked and editors saw the sidebar flash from collapsed to expanded on every admin page. The service reads core/modules/navigation/layouts/navigation.html.twig, hashes each inline script it holds and caches the result, so no digest is recorded in this repository and a core release that edits the script cannot leave a stale value behind.
  3. Made that derivation report rather than fail quietly. When the template cannot be read, holds no script the extraction can read, or holds a script built by Twig, whose rendered bytes cannot be known from the template, it logs a warning on the do_base channel naming the path and the consequence, and returns no hash. The empty result is cached too, so an unreadable template logs once per cache lifetime instead of on every request.
  4. Moved hook_page_attachments() out of do_base.module into PageAttachmentsHook, alongside the four concerns it already carried. The hook now takes the route match, entity type manager, module handler and hash service by injection, which replaces the \Drupal::routeMatch() and ImageStyle::load() static calls, and swaps the class_exists(Csp::class) guard for moduleExists('csp').
  5. Limited the banner background preload to routes that actually render a node's banner: the route name against BANNER_ROUTES, plus any route carrying the _preview_link_route option, which is how the neighbouring preview-link tag already recognises a preview page. The edit form, the delete confirmation and the revision list all carry a node parameter and resolve the same background without ever drawing it, so each was fetching a full-width derivative and discarding it.
  6. Added NavigationScriptHashTest (11 cases) over the derivation, running against fixture templates under tests/fixtures/ so every shape core could ship is reachable: one script, several scripts, no script, a Twig-built script, an unreadable template, an absent module, and the caching behaviour in both directions. Added LibraryInfoAlterHookTest (13 cases) over the stylesheet filtering, including the leading-slash path shape CKEditor 5 actually produces and paths outside the base theme's own files.
  7. Added PageAttachmentsTest (14 cases), which resolves the hook from the container so its wiring is asserted alongside its behaviour, and drives it with the route match set per case: the nonce, the hash, the preload on each route that draws a banner and each route that does not, and a site without the policy module. testAllowedHashMatchesTheTemplate() compares the attached hash against one it computes from the template core currently ships, so a core release that restructures that file fails continuous integration rather than only logging a warning.
  8. Documented the policy in docs/csp.md, including what each warning means and what to do about it, and the editor stylesheet exclusion and the preload's route gate in docs/performance.md, next to the existing claim that nothing is fetched from fonts.googleapis.com, which the editing area did not hold to until now.

Screenshots

CKEditor editing area still styled by the sub-theme build after the base theme's stylesheets were dropped from the library

Before / After

The issue reports five console messages from one page. They come from three causes, and the two font messages plus the Ajax failure are all one of them: both @import statements live in the same file, and a stylesheet whose @import is blocked fires error rather than load, so core's add_css command reports the whole aggregate as unloadable, rejects, and abandons every command queued behind it.

┌───┬──────────────────────────────────────────────┬───────────────────────────┬──────────────────────────┐
│ # │ Console message (before)                     │ Cause                     │ After                    │
├───┼──────────────────────────────────────────────┼───────────────────────────┼──────────────────────────┤
│ 1 │ Inline script violates script-src-elem       │ Toolbar script, no nonce  │ Allowed by sha256 hash   │
│ 2 │ banner_background webp preloaded, not used   │ Preload on any node route │ View routes only         │
│ 3 │ Stylesheet Lexend violates style-src         │ @import in editor CSS     │ File no longer loaded    │
│ 4 │ Stylesheet Public Sans violates style-src    │ @import in editor CSS     │ File no longer loaded    │
│ 5 │ Error executing the Ajax response            │ Blocked @import above     │ Commands all run         │
└───┴──────────────────────────────────────────────┴───────────────────────────┴──────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ BEFORE  internal.drupal.ckeditor5.stylesheets                   │
├─────────────────────────────────────────────────────────────────┤
│ civictheme/dist/civictheme.editor.css      (blocked @import x2) │
│ civictheme/dist/civictheme.variables.css                        │
│ drevops/dist/styles.editor.css                                  │
│ drevops/dist/styles.variables.css                               │
└─────────────────────────────────────────────────────────────────┘

┌───────────────────────────────────────────────────────────────┐
│ AFTER  internal.drupal.ckeditor5.stylesheets                  │
├───────────────────────────────────────────────────────────────┤
│ drevops/dist/styles.editor.css       (self-hosted @font-face) │
│ drevops/dist/styles.variables.css                             │
└───────────────────────────────────────────────────────────────┘

Where the hash comes from. Nothing digest-like is committed, and a template this cannot account for says so in the log instead of silently dropping the source:

                    ┌──────────────────────────────────────────────┐
                    │ core/modules/navigation/layouts/             │
                    │   navigation.html.twig   <script> … </script>│
                    └───────────────────┬──────────────────────────┘
                                        │ read once, then cached
                                        ▼
┌───────────────────────┐   ┌───────────────────────┐   ┌──────────────────────────┐
│ PageAttachmentsHook   │◄──│ NavigationScriptHash  │──►│ watchdog: do_base        │
│ csp_hash              │   │ sha256 per script     │   │ warning when it cannot   │
│   script-src-elem     │   └───────────────────────┘   │ account for a script     │
└──────────┬────────────┘                               └──────────────────────────┘
           ▼
  script-src 'self' … 'nonce-<per-response>' 'sha256-<derived>'
  script-src-attr 'self'   ← pinned by the csp module, so the hash cannot
                             widen inline event handlers

@coderabbitai

coderabbitai Bot commented Aug 13, 2026

Copy link
Copy Markdown

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 24 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: b725a7c3-e23e-46e9-ac99-819f79f54241

📥 Commits

Reviewing files that changed from the base of the PR and between 9286c60 and 86b6f19.

📒 Files selected for processing (15)
  • AGENTS.md
  • docs/csp.md
  • docs/performance.md
  • web/modules/custom/do_base/do_base.module
  • web/modules/custom/do_base/do_base.services.yml
  • web/modules/custom/do_base/src/Hook/LibraryInfoAlterHook.php
  • web/modules/custom/do_base/src/Hook/PageAttachmentsHook.php
  • web/modules/custom/do_base/src/NavigationScriptHash.php
  • web/modules/custom/do_base/tests/fixtures/nav_no_script/layouts/navigation.html.twig
  • web/modules/custom/do_base/tests/fixtures/nav_one_script/layouts/navigation.html.twig
  • web/modules/custom/do_base/tests/fixtures/nav_twig_script/layouts/navigation.html.twig
  • web/modules/custom/do_base/tests/fixtures/nav_two_scripts/layouts/navigation.html.twig
  • web/modules/custom/do_base/tests/src/Kernel/PageAttachmentsTest.php
  • web/modules/custom/do_base/tests/src/Unit/LibraryInfoAlterHookTest.php
  • web/modules/custom/do_base/tests/src/Unit/NavigationScriptHashTest.php

Comment @coderabbitai help to get the list of available commands.

@AlexSkrypnyk AlexSkrypnyk added A1 Board worker 1 AUTOMERGE Pull request has been approved and set to automerge labels Aug 13, 2026
@github-actions

This comment has been minimized.

@codecov-commenter

codecov-commenter commented Aug 13, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 96.77419% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 86.56%. Comparing base (9286c60) to head (86b6f19).

Files with missing lines Patch % Lines
...es/custom/do_base/src/Hook/PageAttachmentsHook.php 94.91% 3 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##           develop     #314      +/-   ##
===========================================
+ Coverage    84.51%   86.56%   +2.04%     
===========================================
  Files           26       28       +2     
  Lines          562      655      +93     
===========================================
+ Hits           475      567      +92     
- Misses          87       88       +1     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@AlexSkrypnyk AlexSkrypnyk added the Needs review Pull request needs a review from assigned developers label Aug 13, 2026
@AlexSkrypnyk
AlexSkrypnyk temporarily deployed to PR-314 August 13, 2026 04:00 Inactive
@github-actions

Copy link
Copy Markdown

Code coverage (threshold: 80%)

  Classes: 51.85% (14/27)
  Methods: 77.17% (71/92)
  Lines:   89.01% (745/837)
Per-class coverage
Drupal\do_ai_alt_text\AltTextGenerator
  Methods:  85.71% ( 6/ 7)   Lines:  98.72% ( 77/ 78)
Drupal\do_ai_alt_text\Plugin\Action\RegenerateImageAltText
  Methods: 100.00% ( 8/ 8)   Lines: 100.00% ( 63/ 63)
Drupal\do_base\EventSubscriber\PreviewLinkCacheSubscriber
  Methods:  33.33% ( 1/ 3)   Lines:  11.11% (  1/  9)
Drupal\do_base\EventSubscriber\ThemeColorSubscriber
  Methods:  66.67% ( 2/ 3)   Lines:  40.00% (  4/ 10)
Drupal\do_base\Hook\AutomatedListPagerHook
  Methods: 100.00% ( 5/ 5)   Lines: 100.00% ( 31/ 31)
Drupal\do_base\Hook\LibraryInfoAlterHook
  Methods: 100.00% ( 3/ 3)   Lines: 100.00% (  9/  9)
Drupal\do_base\Hook\MetatagsAlterHook
  Methods: 100.00% ( 7/ 7)   Lines: 100.00% ( 58/ 58)
Drupal\do_base\Hook\PageAttachmentsHook
  Methods:  87.50% ( 7/ 8)   Lines:  94.92% ( 56/ 59)
Drupal\do_base\NavigationScriptHash
  Methods: 100.00% ( 3/ 3)   Lines: 100.00% ( 27/ 27)
Drupal\do_base\Twig\ImageDimensionsExtension
  Methods:  40.00% ( 2/ 5)   Lines:  81.48% ( 44/ 54)
Drupal\do_content_api\EventSubscriber\JsonApiWriteGateSubscriber
  Methods:  66.67% ( 2/ 3)   Lines:  88.89% (  8/  9)
Drupal\do_content_api\Hook\EntityCreateAccessHook
  Methods: 100.00% ( 2/ 2)   Lines: 100.00% ( 12/ 12)
Drupal\do_content_api\Hook\ModerationPolicyHook
  Methods:  50.00% ( 1/ 2)   Lines:  93.75% ( 15/ 16)
Drupal\do_content_api\Routing\RouteSubscriber
  Methods: 100.00% ( 1/ 1)   Lines: 100.00% (  6/  6)
Drupal\do_feed\FeedUrlBuilder
  Methods: 100.00% ( 4/ 4)   Lines: 100.00% ( 18/ 18)
Drupal\do_feed\Form\FeedSettingsForm
  Methods: 100.00% ( 4/ 4)   Lines: 100.00% ( 15/ 15)
Drupal\do_feed\Hook\EntityDeleteHook
  Methods:  50.00% ( 1/ 2)   Lines:  92.31% ( 12/ 13)
Drupal\do_feed\Hook\EntityPresaveHook
  Methods: 100.00% ( 4/ 4)   Lines: 100.00% ( 54/ 54)
Drupal\do_feed\Hook\PreprocessParagraphHook
  Methods: 100.00% ( 2/ 2)   Lines: 100.00% ( 14/ 14)
Drupal\do_feed\Hook\PreprocessViewsViewRowRssHook
  Methods: 100.00% ( 1/ 1)   Lines: 100.00% (  3/  3)
Drupal\do_feed\Hook\ViewsPreViewHook
  Methods:  50.00% ( 1/ 2)   Lines:  96.43% ( 27/ 28)
Drupal\do_generated_content\Generator\CaseMatrix
  Methods: 100.00% ( 3/ 3)   Lines: 100.00% ( 12/ 12)
Drupal\do_generated_content\Generator\RelativeDate
  Methods: 100.00% ( 1/ 1)   Lines: 100.00% (  1/  1)

@AlexSkrypnyk
AlexSkrypnyk merged commit 5d0c005 into develop Aug 13, 2026
10 checks passed
@AlexSkrypnyk
AlexSkrypnyk deleted the feature/311-js-errors-edit branch August 13, 2026 05:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A1 Board worker 1 AUTOMERGE Pull request has been approved and set to automerge Needs review Pull request needs a review from assigned developers

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Fix JS errors in PROD when editing content

2 participants