Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add CodeMirror to Additional CSS / Custom HTML block #60155

Open
wants to merge 23 commits into
base: trunk
Choose a base branch
from

Conversation

okmttdhr
Copy link
Contributor

@okmttdhr okmttdhr commented Mar 25, 2024

What?

This PR introduces inline code completion and linting into Global Style's Additional CSS and Custom HTML block by using CodeMirror.

Additional CSS

before

Screen.Recording.2024-03-26.at.14.30.24.mov

after

Screen.Recording.2024-03-27.at.15.16.21.mov
previous commits

Screen.Recording.2024-03-26.at.14.29.24.mov

Custom HTML

before

Screen.Recording.2024-03-26.at.14.39.08.mov

after

Screen.Recording.2024-03-26.at.14.38.12.mov

Chunks are loaded on demand and reused

Screen.Recording.2024-03-26.at.14.41.57.mov

Why?

CodeMirror is first introduced to Gutenberg in this PR: #4348 but removed in this PR: #10396. The follow-up issue: #10423 was created, but there haven't been any further updates.

This PR addresses #10423 and #47945.

How?

Branched from PR #53380, this update utilizes Webpack’s dynamic import() as a temporary measure to lazy-load CodeMirror, as I agree with this comment.

This code should work even when we adopt importmap later. Once we turn all @wordpress/* packages (specifically block-editor in this case) into modules by using output.module=true, we can externalize codemirror by using defaultRequestToExternalModule in DependencyExtractionWebpackPlugin and register the script as a module by wp_register_script_module('@wordpress/block-editor') setting codemirror as a dependency module.

Testing Instructions

Additional CSS

  • Select the global styles panel on the right
  • Make sure the dev tool network tab is open
  • In the overflow menu top right, select Additional CSS
  • Make sure the chunks get loaded on demand
  • Add some CSS to the editor box and make sure line numbers appear, CSS autocompletion appears
  • Make sure custom CSS is applied

Custom HTML

  • Make sure the dev tool network tab is open
  • Add a Custom HTML block
  • Make sure the chunks get loaded on demand
  • Add some HTML to the editor and make sure line numbers appear, HTML autocompletion appears

Copy link

github-actions bot commented Mar 25, 2024

Size Change: +2.03 kB (0%)

Total Size: 1.92 MB

Filename Size Change
build/block-editor/index.min.js 256 kB +1.95 kB (+1%)
build/block-library/index.min.js 218 kB +38 B (0%)
build/edit-site/style-rtl.css 15.1 kB +22 B (0%)
build/edit-site/style.css 15.1 kB +23 B (0%)
ℹ️ View Unchanged
Filename Size
build/1518/1518-9a6e12da98e0667d8b52.min.js 57.6 kB
build/3795/3795-cf80ea501ea833cde319.min.js 10.5 kB
build/565/565-27575c366ef06214b764.min.js 18.3 kB
build/5987/5987-72a613d4af2982aa4fa6.min.js 11.9 kB
build/6075/6075-3a7d6f93eab9b9c244fe.min.js 41.6 kB
build/7104/7104-f7d0eb673aa0f622205f.min.js 20 kB
build/7339/7339-e6efd18bff3a3551e35d.min.js 8.84 kB
build/7447/7447-a2773faa13cb45dbcc3b.min.js 16.1 kB
build/a11y/index.min.js 955 B
build/annotations/index.min.js 2.27 kB
build/api-fetch/index.min.js 2.32 kB
build/autop/index.min.js 2.1 kB
build/blob/index.min.js 578 B
build/block-directory/index.min.js 7.26 kB
build/block-directory/style-rtl.css 1.03 kB
build/block-directory/style.css 1.03 kB
build/block-editor/content-rtl.css 4.46 kB
build/block-editor/content.css 4.46 kB
build/block-editor/default-editor-styles-rtl.css 394 B
build/block-editor/default-editor-styles.css 394 B
build/block-editor/style-rtl.css 15.6 kB
build/block-editor/style.css 15.6 kB
build/block-library/blocks/archives/editor-rtl.css 61 B
build/block-library/blocks/archives/editor.css 60 B
build/block-library/blocks/archives/style-rtl.css 90 B
build/block-library/blocks/archives/style.css 90 B
build/block-library/blocks/audio/editor-rtl.css 150 B
build/block-library/blocks/audio/editor.css 150 B
build/block-library/blocks/audio/style-rtl.css 122 B
build/block-library/blocks/audio/style.css 122 B
build/block-library/blocks/audio/theme-rtl.css 133 B
build/block-library/blocks/audio/theme.css 133 B
build/block-library/blocks/avatar/editor-rtl.css 116 B
build/block-library/blocks/avatar/editor.css 116 B
build/block-library/blocks/avatar/style-rtl.css 104 B
build/block-library/blocks/avatar/style.css 104 B
build/block-library/blocks/block/editor-rtl.css 305 B
build/block-library/blocks/block/editor.css 305 B
build/block-library/blocks/button/editor-rtl.css 415 B
build/block-library/blocks/button/editor.css 414 B
build/block-library/blocks/button/style-rtl.css 627 B
build/block-library/blocks/button/style.css 626 B
build/block-library/blocks/buttons/editor-rtl.css 337 B
build/block-library/blocks/buttons/editor.css 337 B
build/block-library/blocks/buttons/style-rtl.css 332 B
build/block-library/blocks/buttons/style.css 332 B
build/block-library/blocks/calendar/style-rtl.css 239 B
build/block-library/blocks/calendar/style.css 239 B
build/block-library/blocks/categories/editor-rtl.css 113 B
build/block-library/blocks/categories/editor.css 112 B
build/block-library/blocks/categories/style-rtl.css 124 B
build/block-library/blocks/categories/style.css 124 B
build/block-library/blocks/code/editor-rtl.css 53 B
build/block-library/blocks/code/editor.css 53 B
build/block-library/blocks/code/style-rtl.css 121 B
build/block-library/blocks/code/style.css 121 B
build/block-library/blocks/code/theme-rtl.css 124 B
build/block-library/blocks/code/theme.css 124 B
build/block-library/blocks/columns/editor-rtl.css 108 B
build/block-library/blocks/columns/editor.css 108 B
build/block-library/blocks/columns/style-rtl.css 421 B
build/block-library/blocks/columns/style.css 421 B
build/block-library/blocks/comment-author-avatar/editor-rtl.css 125 B
build/block-library/blocks/comment-author-avatar/editor.css 125 B
build/block-library/blocks/comment-content/style-rtl.css 92 B
build/block-library/blocks/comment-content/style.css 92 B
build/block-library/blocks/comment-template/style-rtl.css 199 B
build/block-library/blocks/comment-template/style.css 198 B
build/block-library/blocks/comments-pagination-numbers/editor-rtl.css 123 B
build/block-library/blocks/comments-pagination-numbers/editor.css 121 B
build/block-library/blocks/comments-pagination/editor-rtl.css 222 B
build/block-library/blocks/comments-pagination/editor.css 209 B
build/block-library/blocks/comments-pagination/style-rtl.css 235 B
build/block-library/blocks/comments-pagination/style.css 231 B
build/block-library/blocks/comments-title/editor-rtl.css 75 B
build/block-library/blocks/comments-title/editor.css 75 B
build/block-library/blocks/comments/editor-rtl.css 840 B
build/block-library/blocks/comments/editor.css 839 B
build/block-library/blocks/comments/style-rtl.css 637 B
build/block-library/blocks/comments/style.css 636 B
build/block-library/blocks/cover/editor-rtl.css 647 B
build/block-library/blocks/cover/editor.css 650 B
build/block-library/blocks/cover/style-rtl.css 1.7 kB
build/block-library/blocks/cover/style.css 1.69 kB
build/block-library/blocks/details/editor-rtl.css 65 B
build/block-library/blocks/details/editor.css 65 B
build/block-library/blocks/details/style-rtl.css 86 B
build/block-library/blocks/details/style.css 86 B
build/block-library/blocks/embed/editor-rtl.css 322 B
build/block-library/blocks/embed/editor.css 322 B
build/block-library/blocks/embed/style-rtl.css 410 B
build/block-library/blocks/embed/style.css 410 B
build/block-library/blocks/embed/theme-rtl.css 133 B
build/block-library/blocks/embed/theme.css 133 B
build/block-library/blocks/file/editor-rtl.css 326 B
build/block-library/blocks/file/editor.css 327 B
build/block-library/blocks/file/style-rtl.css 280 B
build/block-library/blocks/file/style.css 281 B
build/block-library/blocks/file/view.min.js 324 B
build/block-library/blocks/footnotes/style-rtl.css 201 B
build/block-library/blocks/footnotes/style.css 199 B
build/block-library/blocks/form-input/editor-rtl.css 227 B
build/block-library/blocks/form-input/editor.css 227 B
build/block-library/blocks/form-input/style-rtl.css 343 B
build/block-library/blocks/form-input/style.css 343 B
build/block-library/blocks/form-submission-notification/editor-rtl.css 340 B
build/block-library/blocks/form-submission-notification/editor.css 340 B
build/block-library/blocks/form-submit-button/style-rtl.css 69 B
build/block-library/blocks/form-submit-button/style.css 69 B
build/block-library/blocks/form/view.min.js 471 B
build/block-library/blocks/freeform/editor-rtl.css 2.61 kB
build/block-library/blocks/freeform/editor.css 2.61 kB
build/block-library/blocks/gallery/editor-rtl.css 947 B
build/block-library/blocks/gallery/editor.css 952 B
build/block-library/blocks/gallery/style-rtl.css 1.72 kB
build/block-library/blocks/gallery/style.css 1.72 kB
build/block-library/blocks/gallery/theme-rtl.css 108 B
build/block-library/blocks/gallery/theme.css 108 B
build/block-library/blocks/group/editor-rtl.css 647 B
build/block-library/blocks/group/editor.css 647 B
build/block-library/blocks/group/style-rtl.css 57 B
build/block-library/blocks/group/style.css 57 B
build/block-library/blocks/group/theme-rtl.css 78 B
build/block-library/blocks/group/theme.css 78 B
build/block-library/blocks/heading/style-rtl.css 189 B
build/block-library/blocks/heading/style.css 189 B
build/block-library/blocks/html/editor-rtl.css 336 B
build/block-library/blocks/html/editor.css 337 B
build/block-library/blocks/image/editor-rtl.css 878 B
build/block-library/blocks/image/editor.css 878 B
build/block-library/blocks/image/style-rtl.css 1.6 kB
build/block-library/blocks/image/style.css 1.59 kB
build/block-library/blocks/image/theme-rtl.css 133 B
build/block-library/blocks/image/theme.css 133 B
build/block-library/blocks/image/view.min.js 1.54 kB
build/block-library/blocks/latest-comments/style-rtl.css 357 B
build/block-library/blocks/latest-comments/style.css 357 B
build/block-library/blocks/latest-posts/editor-rtl.css 213 B
build/block-library/blocks/latest-posts/editor.css 212 B
build/block-library/blocks/latest-posts/style-rtl.css 478 B
build/block-library/blocks/latest-posts/style.css 478 B
build/block-library/blocks/list/style-rtl.css 88 B
build/block-library/blocks/list/style.css 88 B
build/block-library/blocks/media-text/editor-rtl.css 306 B
build/block-library/blocks/media-text/editor.css 305 B
build/block-library/blocks/media-text/style-rtl.css 505 B
build/block-library/blocks/media-text/style.css 503 B
build/block-library/blocks/more/editor-rtl.css 431 B
build/block-library/blocks/more/editor.css 431 B
build/block-library/blocks/navigation-link/editor-rtl.css 668 B
build/block-library/blocks/navigation-link/editor.css 669 B
build/block-library/blocks/navigation-link/style-rtl.css 259 B
build/block-library/blocks/navigation-link/style.css 257 B
build/block-library/blocks/navigation-submenu/editor-rtl.css 296 B
build/block-library/blocks/navigation-submenu/editor.css 295 B
build/block-library/blocks/navigation/editor-rtl.css 2.26 kB
build/block-library/blocks/navigation/editor.css 2.26 kB
build/block-library/blocks/navigation/style-rtl.css 2.26 kB
build/block-library/blocks/navigation/style.css 2.25 kB
build/block-library/blocks/navigation/view.min.js 1.03 kB
build/block-library/blocks/nextpage/editor-rtl.css 395 B
build/block-library/blocks/nextpage/editor.css 395 B
build/block-library/blocks/page-list/editor-rtl.css 377 B
build/block-library/blocks/page-list/editor.css 377 B
build/block-library/blocks/page-list/style-rtl.css 175 B
build/block-library/blocks/page-list/style.css 175 B
build/block-library/blocks/paragraph/editor-rtl.css 235 B
build/block-library/blocks/paragraph/editor.css 235 B
build/block-library/blocks/paragraph/style-rtl.css 335 B
build/block-library/blocks/paragraph/style.css 335 B
build/block-library/blocks/post-author/style-rtl.css 175 B
build/block-library/blocks/post-author/style.css 176 B
build/block-library/blocks/post-comments-form/editor-rtl.css 96 B
build/block-library/blocks/post-comments-form/editor.css 96 B
build/block-library/blocks/post-comments-form/style-rtl.css 508 B
build/block-library/blocks/post-comments-form/style.css 508 B
build/block-library/blocks/post-content/editor-rtl.css 74 B
build/block-library/blocks/post-content/editor.css 74 B
build/block-library/blocks/post-date/style-rtl.css 61 B
build/block-library/blocks/post-date/style.css 61 B
build/block-library/blocks/post-excerpt/editor-rtl.css 71 B
build/block-library/blocks/post-excerpt/editor.css 71 B
build/block-library/blocks/post-excerpt/style-rtl.css 141 B
build/block-library/blocks/post-excerpt/style.css 141 B
build/block-library/blocks/post-featured-image/editor-rtl.css 666 B
build/block-library/blocks/post-featured-image/editor.css 662 B
build/block-library/blocks/post-featured-image/style-rtl.css 342 B
build/block-library/blocks/post-featured-image/style.css 342 B
build/block-library/blocks/post-navigation-link/style-rtl.css 215 B
build/block-library/blocks/post-navigation-link/style.css 214 B
build/block-library/blocks/post-template/editor-rtl.css 99 B
build/block-library/blocks/post-template/editor.css 98 B
build/block-library/blocks/post-template/style-rtl.css 409 B
build/block-library/blocks/post-template/style.css 408 B
build/block-library/blocks/post-terms/style-rtl.css 96 B
build/block-library/blocks/post-terms/style.css 96 B
build/block-library/blocks/post-time-to-read/style-rtl.css 69 B
build/block-library/blocks/post-time-to-read/style.css 69 B
build/block-library/blocks/post-title/style-rtl.css 100 B
build/block-library/blocks/post-title/style.css 100 B
build/block-library/blocks/preformatted/style-rtl.css 125 B
build/block-library/blocks/preformatted/style.css 125 B
build/block-library/blocks/pullquote/editor-rtl.css 135 B
build/block-library/blocks/pullquote/editor.css 135 B
build/block-library/blocks/pullquote/style-rtl.css 354 B
build/block-library/blocks/pullquote/style.css 354 B
build/block-library/blocks/pullquote/theme-rtl.css 174 B
build/block-library/blocks/pullquote/theme.css 174 B
build/block-library/blocks/query-pagination-numbers/editor-rtl.css 122 B
build/block-library/blocks/query-pagination-numbers/editor.css 121 B
build/block-library/blocks/query-pagination/editor-rtl.css 221 B
build/block-library/blocks/query-pagination/editor.css 211 B
build/block-library/blocks/query-pagination/style-rtl.css 288 B
build/block-library/blocks/query-pagination/style.css 284 B
build/block-library/blocks/query-title/style-rtl.css 63 B
build/block-library/blocks/query-title/style.css 63 B
build/block-library/blocks/query/editor-rtl.css 486 B
build/block-library/blocks/query/editor.css 486 B
build/block-library/blocks/query/view.min.js 958 B
build/block-library/blocks/quote/style-rtl.css 237 B
build/block-library/blocks/quote/style.css 237 B
build/block-library/blocks/quote/theme-rtl.css 233 B
build/block-library/blocks/quote/theme.css 235 B
build/block-library/blocks/read-more/style-rtl.css 140 B
build/block-library/blocks/read-more/style.css 140 B
build/block-library/blocks/rss/editor-rtl.css 149 B
build/block-library/blocks/rss/editor.css 149 B
build/block-library/blocks/rss/style-rtl.css 289 B
build/block-library/blocks/rss/style.css 288 B
build/block-library/blocks/search/editor-rtl.css 184 B
build/block-library/blocks/search/editor.css 184 B
build/block-library/blocks/search/style-rtl.css 690 B
build/block-library/blocks/search/style.css 689 B
build/block-library/blocks/search/theme-rtl.css 114 B
build/block-library/blocks/search/theme.css 114 B
build/block-library/blocks/search/view.min.js 478 B
build/block-library/blocks/separator/editor-rtl.css 146 B
build/block-library/blocks/separator/editor.css 146 B
build/block-library/blocks/separator/style-rtl.css 229 B
build/block-library/blocks/separator/style.css 229 B
build/block-library/blocks/separator/theme-rtl.css 194 B
build/block-library/blocks/separator/theme.css 194 B
build/block-library/blocks/shortcode/editor-rtl.css 323 B
build/block-library/blocks/shortcode/editor.css 323 B
build/block-library/blocks/site-logo/editor-rtl.css 754 B
build/block-library/blocks/site-logo/editor.css 754 B
build/block-library/blocks/site-logo/style-rtl.css 204 B
build/block-library/blocks/site-logo/style.css 204 B
build/block-library/blocks/site-tagline/editor-rtl.css 86 B
build/block-library/blocks/site-tagline/editor.css 86 B
build/block-library/blocks/site-title/editor-rtl.css 116 B
build/block-library/blocks/site-title/editor.css 116 B
build/block-library/blocks/site-title/style-rtl.css 57 B
build/block-library/blocks/site-title/style.css 57 B
build/block-library/blocks/social-link/editor-rtl.css 184 B
build/block-library/blocks/social-link/editor.css 184 B
build/block-library/blocks/social-links/editor-rtl.css 676 B
build/block-library/blocks/social-links/editor.css 675 B
build/block-library/blocks/social-links/style-rtl.css 1.48 kB
build/block-library/blocks/social-links/style.css 1.48 kB
build/block-library/blocks/spacer/editor-rtl.css 350 B
build/block-library/blocks/spacer/editor.css 350 B
build/block-library/blocks/spacer/style-rtl.css 48 B
build/block-library/blocks/spacer/style.css 48 B
build/block-library/blocks/table/editor-rtl.css 395 B
build/block-library/blocks/table/editor.css 395 B
build/block-library/blocks/table/style-rtl.css 639 B
build/block-library/blocks/table/style.css 639 B
build/block-library/blocks/table/theme-rtl.css 152 B
build/block-library/blocks/table/theme.css 152 B
build/block-library/blocks/tag-cloud/style-rtl.css 251 B
build/block-library/blocks/tag-cloud/style.css 253 B
build/block-library/blocks/template-part/editor-rtl.css 431 B
build/block-library/blocks/template-part/editor.css 431 B
build/block-library/blocks/template-part/theme-rtl.css 107 B
build/block-library/blocks/template-part/theme.css 107 B
build/block-library/blocks/term-description/style-rtl.css 111 B
build/block-library/blocks/term-description/style.css 111 B
build/block-library/blocks/text-columns/editor-rtl.css 95 B
build/block-library/blocks/text-columns/editor.css 95 B
build/block-library/blocks/text-columns/style-rtl.css 166 B
build/block-library/blocks/text-columns/style.css 166 B
build/block-library/blocks/verse/style-rtl.css 99 B
build/block-library/blocks/verse/style.css 99 B
build/block-library/blocks/video/editor-rtl.css 552 B
build/block-library/blocks/video/editor.css 555 B
build/block-library/blocks/video/style-rtl.css 185 B
build/block-library/blocks/video/style.css 185 B
build/block-library/blocks/video/theme-rtl.css 133 B
build/block-library/blocks/video/theme.css 133 B
build/block-library/classic-rtl.css 179 B
build/block-library/classic.css 179 B
build/block-library/common-rtl.css 1.11 kB
build/block-library/common.css 1.11 kB
build/block-library/editor-elements-rtl.css 75 B
build/block-library/editor-elements.css 75 B
build/block-library/editor-rtl.css 12.4 kB
build/block-library/editor.css 12.4 kB
build/block-library/elements-rtl.css 54 B
build/block-library/elements.css 54 B
build/block-library/reset-rtl.css 472 B
build/block-library/reset.css 472 B
build/block-library/style-rtl.css 14.8 kB
build/block-library/style.css 14.8 kB
build/block-library/theme-rtl.css 707 B
build/block-library/theme.css 713 B
build/block-serialization-default-parser/index.min.js 1.12 kB
build/block-serialization-spec-parser/index.min.js 2.87 kB
build/blocks/index.min.js 51.5 kB
build/commands/index.min.js 15.2 kB
build/commands/style-rtl.css 956 B
build/commands/style.css 953 B
build/components/index.min.js 222 kB
build/components/style-rtl.css 11.9 kB
build/components/style.css 11.9 kB
build/compose/index.min.js 12.6 kB
build/core-commands/index.min.js 2.77 kB
build/core-data/index.min.js 72.5 kB
build/customize-widgets/index.min.js 11.2 kB
build/customize-widgets/style-rtl.css 1.36 kB
build/customize-widgets/style.css 1.36 kB
build/data-controls/index.min.js 640 B
build/data/index.min.js 9 kB
build/date/index.min.js 17.9 kB
build/deprecated/index.min.js 451 B
build/dom-ready/index.min.js 324 B
build/dom/index.min.js 4.65 kB
build/edit-post/classic-rtl.css 578 B
build/edit-post/classic.css 579 B
build/edit-post/index.min.js 23.2 kB
build/edit-post/style-rtl.css 5.5 kB
build/edit-post/style.css 5.5 kB
build/edit-site/index.min.js 232 kB
build/edit-widgets/index.min.js 17.4 kB
build/edit-widgets/style-rtl.css 4.15 kB
build/edit-widgets/style.css 4.15 kB
build/editor/index.min.js 67.4 kB
build/editor/style-rtl.css 5.46 kB
build/editor/style.css 5.46 kB
build/element/index.min.js 4.83 kB
build/escape-html/index.min.js 537 B
build/format-library/index.min.js 8.11 kB
build/format-library/style-rtl.css 492 B
build/format-library/style.css 490 B
build/hooks/index.min.js 1.55 kB
build/html-entities/index.min.js 448 B
build/i18n/index.min.js 3.58 kB
build/interactivity/file.min.js 447 B
build/interactivity/image.min.js 1.67 kB
build/interactivity/index.min.js 13 kB
build/interactivity/navigation.min.js 1.17 kB
build/interactivity/query.min.js 740 B
build/interactivity/router.min.js 1.36 kB
build/interactivity/search.min.js 618 B
build/is-shallow-equal/index.min.js 527 B
build/keyboard-shortcuts/index.min.js 1.3 kB
build/keycodes/index.min.js 1.46 kB
build/list-reusable-blocks/index.min.js 2.11 kB
build/list-reusable-blocks/style-rtl.css 851 B
build/list-reusable-blocks/style.css 849 B
build/media-utils/index.min.js 2.92 kB
build/modules/importmap-polyfill.min.js 12.2 kB
build/notices/index.min.js 948 B
build/nux/index.min.js 1.57 kB
build/nux/style-rtl.css 747 B
build/nux/style.css 742 B
build/patterns/index.min.js 5.91 kB
build/patterns/style-rtl.css 553 B
build/patterns/style.css 552 B
build/plugins/index.min.js 1.8 kB
build/preferences-persistence/index.min.js 2.06 kB
build/preferences/index.min.js 2.83 kB
build/preferences/style-rtl.css 710 B
build/preferences/style.css 712 B
build/primitives/index.min.js 975 B
build/priority-queue/index.min.js 1.52 kB
build/private-apis/index.min.js 1 kB
build/react-i18n/index.min.js 623 B
build/react-refresh-entry/index.min.js 9.47 kB
build/react-refresh-runtime/index.min.js 6.78 kB
build/redux-routine/index.min.js 2.7 kB
build/reusable-blocks/index.min.js 2.73 kB
build/reusable-blocks/style-rtl.css 256 B
build/reusable-blocks/style.css 256 B
build/rich-text/index.min.js 10 kB
build/router/index.min.js 1.88 kB
build/server-side-render/index.min.js 1.96 kB
build/shortcode/index.min.js 1.39 kB
build/style-engine/index.min.js 2.03 kB
build/token-list/index.min.js 582 B
build/url/index.min.js 3.74 kB
build/vendors/inert-polyfill.min.js 2.48 kB
build/vendors/react-dom.min.js 41.7 kB
build/vendors/react.min.js 4.02 kB
build/viewport/index.min.js 957 B
build/warning/index.min.js 249 B
build/widgets/index.min.js 7.23 kB
build/widgets/style-rtl.css 1.17 kB
build/widgets/style.css 1.17 kB
build/wordcount/index.min.js 1.02 kB

compressed-size-action

@okmttdhr okmttdhr changed the title Add codemirror to Additional CSS / Custom HTML block Add CodeMirror to Additional CSS / Custom HTML block Mar 25, 2024
Copy link

github-actions bot commented Mar 26, 2024

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: okmttdhr <[email protected]>
Co-authored-by: talldan <[email protected]>
Co-authored-by: jsnajdr <[email protected]>
Co-authored-by: mirka <[email protected]>
Co-authored-by: ellatrix <[email protected]>
Co-authored-by: tyxla <[email protected]>
Co-authored-by: jasmussen <[email protected]>
Co-authored-by: youknowriad <[email protected]>
Co-authored-by: afercia <[email protected]>
Co-authored-by: sirreal <[email protected]>
Co-authored-by: annezazu <[email protected]>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@talldan talldan added [Type] Enhancement A suggestion for improvement. [Block] HTML Affects the the HTML Block Global Styles Anything related to the broader Global Styles efforts, including Styles Engine and theme.json labels Mar 26, 2024
@jasmussen
Copy link
Contributor

Thanks for the contribution. It may be good to search the archive for "codemirror" as well, there have been past conversations exploring adding it to the code editor section, which ultimately failed. It would be good to see what lessons could potentially be learned adding it here. I'd like to see this land, but there are some checks and balances that need to be considered. Perhaps an option even is to turn it on or off. This could be in preferences and/or onboarding, that might even let it be available for the code editor too.

A few notes from a superficial review, here's a GIF showing some light CSS editing and tabbing:

tabbing into code mirror

  • The input field needs a border in its resting state. Essentially it should look the same as before, a $gray-600 border with its corners set to $radius-block-ui
  • The focus style should also be the same as before, a 1.5px thick spot color blue.
  • Can the input field be full-height, same as before?
  • Do we actually need to show the line-numbers? In this particular narrow context, they take up quite a bit of horizontal space. If not, we'd probably want to do some light visul changes to reduce the footprint.
  • How hard would it be to change the syntax highlighting colors? It would be good to get closer to the core UI colors we have available, make it feel more at home and ensure good contrast.
  • Can we use the same code font-stack for the field? It's $editor-html-font.

Probably related to the past conversations on codemirror, IMO the biggest potential benefit of using codemirror is tabbing to indent/outdent code. Yet that's also one of the main challenges, as we still need a way for keyboard users to enter and exit this field. That's something to consider the best practices for.

@tyxla tyxla requested a review from jsnajdr March 26, 2024 17:12
@okmttdhr
Copy link
Contributor Author

okmttdhr commented Mar 27, 2024

Thank you for your review, @jasmussen!

The input field needs a border in its resting state. Essentially it should look the same as before, a $gray-600 border with its corners set to $radius-block-ui
The focus style should also be the same as before, a 1.5px thick spot color blue.
Can the input field be full-height, same as before?
Can we use the same code font-stack for the field? It's $editor-html-font.

I have addressed these points and updated the video in the PR description accordingly 🙂

Do we actually need to show the line-numbers? In this particular narrow context, they take up quite a bit of horizontal space. If not, we'd probably want to do some light visul changes to reduce the footprint.

I think line numbers serve as a clear & common indicator for developers that "Oh, this is the place I can write code". However, I agree that the space is limited in terms of the Additional CSS input, so I've removed it, while retaining it for a Custom HTML block.

the biggest potential benefit of using codemirror is tabbing to indent/outdent code. Yet that's also one of the main challenges, as we still need a way for keyboard users to enter and exit this field. That's something to consider the best practices for.

I implemented tab-based indentation following the documentation: CodeMirror Language Config Example. It mentions that using Tab for indentation is not enabled by default because it could conflict with Success Criterion 2.1.2 No Keyboard Trap. I attempted to address this by implementing Esc & Tab to focus out (which is the same behavior as focusing on/out blocks in the editor) and by adding instructions using aria-describedby (9394fc9) what are your thoughts on this?

How hard would it be to change the syntax highlighting colors? It would be good to get closer to the core UI colors we have available, make it feel more at home and ensure good contrast.

Technically, altering the syntax highlighting colors is straightforward — it's about overriding the original CSS. However, it's tricky to select the appropriate colors, IMO. For instance, the following CSS already contains some colors, necessitating consideration in determining which colors should be defined and used in which state (like when highlighting the text).

Screenshot 2024-03-27 at 15 55 15 when highlighting 'o'

It may be good to search the archive for "codemirror" as well, there have been past conversations exploring adding it to the code editor section, which ultimately failed. It would be good to see what lessons could potentially be learned adding it here.

As far as I know, CodeMirror was first introduced to Gutenberg in this PR: #4348 but removed later in this PR: #10396. It was mainly due to the difficulty of lazy loading at that time. Now, importmap is coming soon in WP 6.5, and it's ready to get prepared by using import().

I'm aware there have been several UX discussions, but I may need more time to find/review them thoroughly. 🙂 Please let me know if anything can be improved.

@okmttdhr okmttdhr requested a review from talldan March 27, 2024 07:14
@okmttdhr okmttdhr requested a review from jsnajdr March 28, 2024 09:07
Copy link
Member

@mirka mirka left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work, it would be really nice to have this feature!

I commented on things I noticed on the first pass, but before code specifics, we need to make sure there are no accessibility blockers. If we can make it work for everyone, great. If not, that might mean making it a toggleable option.

I think the accessibility-related notes I made are addressable, but I don't have enough familiarity with the text editing mechanics inside the editor itself. The code completion popover works as expected for me in VoiceOver, so that's good.

cc @andrewhayward @afercia @alexstine

packages/block-editor/package.json Outdated Show resolved Hide resolved
packages/edit-site/src/components/global-styles/style.scss Outdated Show resolved Hide resolved
packages/block-library/src/html/edit.js Outdated Show resolved Hide resolved
Comment on lines 73 to 75
// We only want to run this once, so we can ignore the dependency array.
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [] );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure this is tenable in a React context. I'm assuming from this code that the content, onChange, onBlur, and mode props are all basically initial config and cannot be dynamically updated. As a component consumer, that is unexpected to me. We could for example tweak the component API to make it clearer that they're initial config (like have consumers pass in the config through the output of a useEditorView( config ) hook or something).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your comment!

I'm assuming from this code that the content, onChange, onBlur, and mode props are all basically initial config and cannot be dynamically updated

Yes, the approach was chosen to initialize new CmEditorView just once, allowing CodeMirror to handle subsequent updates, as I was to minimize complexity.

As a component consumer, that is unexpected to me.

It makes sense to me! I have just updated the component API to use the term initialConfig to clarify that these properties are intended for initial setup only, but WDYT?

spellCheck={ false }
/>
<label
htmlFor={ EDITOR_ID }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apparently a generic div is not labelable. (Confirmed not labeled in the accessibility tree.)

packages/edit-site/src/components/global-styles/style.scss Outdated Show resolved Hide resolved
>
{ editorInstructionsText }
{ __(
`Press Escape then Tab to move focus out of the editor.`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we actually make the editor field blur on Escape? Currently, it just maintains the focus outline and I can still type in the field. At the very least I think we need some visual feedback for the Escape.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've taken a look at the current implementation, and it seems to work as intended on my end. Here's what it looks like:

Screen.Recording.2024-04-02.at.15.38.15.mov

I'm wondering if there might be specific conditions or environments where this behavior isn't consistent. Could you share more details about the issue you're encountering?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the editor in the Custom HTML block, we'll need to style it in a way that works across different color schemes. This is how it currently looks in a dark color scheme:

Code completion popover has an illegible color combination

@mirka mirka added the Needs Accessibility Feedback Need input from accessibility label Mar 28, 2024
@youknowriad
Copy link
Contributor

This code should work even when we adopt importmap later. Once we turn all @wordpress/* packages (specifically block-editor in this case) into modules by using output.module=true, we can externalize codemirror by using defaultRequestToExternalModule in DependencyExtractionWebpackPlugin and register the script as a module by WordPress/wordpress-develop#5818 setting codemirror as a dependency module.

Thanks for starting this work, I don't think we need to wait for all the packages to be modules to be able to use import maps. Import maps is already supported in Core today and scripts can load modules so I think by making code mirror a module, we can start using it today.

@afercia
Copy link
Contributor

afercia commented Apr 2, 2024

I think the accessibility-related notes I made are addressable, but I don't have enough familiarity with the text editing mechanics inside the editor itself. The code completion popover works as expected for me in VoiceOver, so that's good.

From an accessibility perspective, I'd like to avoid to repeat all the concerns that were originally raised for the core implementation in https://core.trac.wordpress.org/ticket/12423. Basically, Codemirror drastically alters the DOM making it hardly readable with assistive technology. Also, the Codemirror UI isn't greatly accessible.

That's the reason why in https://core.trac.wordpress.org/ticket/12423 the final decision was that codemirror can be entirely disabled by users. This whole feature must honor the user preference syntax_highlighting in wp-admin/profile.php.

Comment on lines +79 to +103
{
name: 'codemirror',
message:
'Please use dynamic import (`import()`) instead since it is a large dependency.',
},
{
name: '@codemirror/commands',
message:
'Please use dynamic import (`import()`) instead since it is a large dependency.',
},
{
name: '@codemirror/lang-css',
message:
'Please use dynamic import (`import()`) instead since it is a large dependency.',
},
{
name: '@codemirror/lang-html',
message:
'Please use dynamic import (`import()`) instead since it is a large dependency.',
},
{
name: '@codemirror/view',
message:
'Please use dynamic import (`import()`) instead since it is a large dependency.',
},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a bit repetitive. Does it make sense to use the patterns option to combine them into a single restricted import?

* (height of all the elements in the sidebar except the editor) + (height of the header) + (height of the footer)
* Currently, it's desktop-optimized.
*/
const MARGIN = 234 + 60 + 25;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we're going to keep these static, can we move them up there in the module, right below the module imports?

I'd also suggest splitting each into a separate constant, which will allow separate comments for each value, perhaps making it all a bit more readable.

*/
function ensureMinLines( content ) {
const MIN_LINES = 10;
const LINE_HEIGHT = 18.2; // Height of one line in the editor
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above in terms of where the constants live.

initialConfig={
{
callback: () => ensureMaxHeight(instanceId),
content: ensureMinLines( inheritedValue?.css ),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The optional chaining here hints that we could have an undefined passed to ensureMinLines(). But ensureMinLines() expects content to be defined as it does content.split(). Should we add some checks or coalesce to a default value?

@include input-style__focus();
}
}
.cm-editor {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we can make things less specific here. Right now we have 4 levels:

  1. .edit-site-global-styles-screen-css
  2. .components-v-stack
  3. .cm-editor
  4. .cm-line

Do we need all of that nesting?

placeholder={ __( 'Write HTML…' ) }
aria-label={ __( 'HTML' ) }
<EditorView
editorId={'block-library-html__editor'}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
editorId={'block-library-html__editor'}
editorId="block-library-html__editor"

aria-label={ __( 'HTML' ) }
<EditorView
editorId={'block-library-html__editor'}
editorInstructionsText={__(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spacing seems to be a bit off here. Linter didn't run for some reason.

<EditorView
editorId={'block-library-html__editor'}
editorInstructionsText={__(
`This editor allows you to input your custom HTML.`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems to be no need for a template literal, it can be a quoted string.

Suggested change
`This editor allows you to input your custom HTML.`
"This editor allows you to input your custom HTML."

onChange={ ( content ) => setAttributes( { content } ) }
placeholder={ __( 'Write HTML…' ) }
aria-label={ __( 'HTML' ) }
<EditorView
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a big change to the html block and may need a CHANGELOG mention.

@jsnajdr
Copy link
Member

jsnajdr commented Apr 2, 2024

I created #60362 to explore reorganizing the @codemirror/* imports so that the webpack chunk layout is simpler.

When we import the CodeMirror modules with individual dynamic imports, like:

await import( 'codemirror' )
await import( '@codemirror/commands' )
await import( '@codemirror/view' )
await import( '@codemirror/lang-css' )

then webpack assumes that the imports are independent, i.e., any of the modules can be imported at any time, without importing the others. That's why it creates 7 independent chunks for CodeMirror modules:

Screenshot 2024-04-02 at 13 38 47

For example, @codemirror/commands and @codemirror/autocomplete are dependencies of codemirror, they have been loaded already by import( 'codemirror' ), but because they are also parts of other imports (i.e., @codemirror/autocomplete is a dependency of @codemirror/lang-css and others), they have their own chunks, to support independent loading and also to avoid duplication.

But when I move the imports to be synchronous in a separate ./code-mirror.js file:

import 'codemirror'
import '@codemirror/commands'
import '@codemirror/view'

async function importLanguage() {
  await import( '@codemirror/lang-css' )
}

and import the file dynamically with import( './code-mirror' ), then webpack is able to infer two things:

  1. @codemirror/commands and @codemirror/view are always imported together with codemirror, they can be all bundled together.
  2. @codemirror/lang-css is loaded only in a situation where codemirror is already loaded. So, if lang-css depends on autocomplete, it doesn't need to worry about it because it's been already loaded and webpack knows it. The chunk needs to contain only the minimal code to load lang-css on top of codemirror.

The result is that there are only three chunks, with minimal size and no code duplication:

Screenshot 2024-04-02 at 12 43 12

Much better layout. I'm also specifying a webpackChunkName on each import, because otherwise the chunk file names will be numeric. This is how the production build of the current PR looks like:

Screenshot 2024-04-02 at 12 53 45

@okmttdhr
Copy link
Contributor Author

okmttdhr commented Apr 3, 2024

I think the accessibility-related notes I made are addressable, but I don't have enough familiarity with the text editing mechanics inside the editor itself. The code completion popover works as expected for me in VoiceOver, so that's good.

From an accessibility perspective, I'd like to avoid to repeat all the concerns that were originally raised for the core implementation in core.trac.wordpress.org/ticket/12423. Basically, Codemirror drastically alters the DOM making it hardly readable with assistive technology. Also, the Codemirror UI isn't greatly accessible.

That's the reason why in core.trac.wordpress.org/ticket/12423 the final decision was that codemirror can be entirely disabled by users. This whole feature must honor the user preference syntax_highlighting in wp-admin/profile.php.
#60155 (comment)

Thank you for the valuable resources, @afercia!
I have reviewed the previous discussions. It appears that many of the accessibility issues have been addressed in this version in the CodeMirror 6 released in 2022.
Nevertheless, to get aligned with it, it'd be nice to make syntax highlighting opt-out to respect the user preference, as it does for the Customizer.

@okmttdhr
Copy link
Contributor Author

okmttdhr commented Apr 3, 2024

This code should work even when we adopt importmap later. Once we turn all @wordpress/* packages (specifically block-editor in this case) into modules by using output.module=true, we can externalize codemirror by using defaultRequestToExternalModule in DependencyExtractionWebpackPlugin and register the script as a module by WordPress/wordpress-develop#5818 setting codemirror as a dependency module.

Thanks for starting this work, I don't think we need to wait for all the packages to be modules to be able to use import maps. Import maps is already supported in Core today and scripts can load modules so I think by making code mirror a module, we can start using it today.
#60155 (comment)

Thanks for your suggestion, @youknowriad! In reference to Script Modules in 6.5, my understanding is that for utilization of a module (in this PR use case), it must be declared as a dependent of the consumer to be added into the importmap. In the following example, @my-plugin/shared module will be available to the @my-plugin/entry module:

wp_register_script_module(
	'@my-plugin/shared',
	plugin_dir_url( __FILE__ ) . 'shared.js'
);

wp_enqueue_script_module(
	'@my-plugin/entry',
	plugin_dir_url( __FILE__ ) . 'entry.js',
	array( '@my-plugin/shared' )
);

Thus, @wordpress/block-editor should act as a module and an entry module in this scenario. Also, currently, it seems that modules cannot depend on scripts, and scripts cannot depend on modules.
Please feel free to offer corrections if my understanding is inaccurate.

@youknowriad
Copy link
Contributor

youknowriad commented Apr 3, 2024

my understanding is that for utilization of a module (in this PR use case), it must be declared as a dependent of the consumer to be added into the importmap.

Oh It's unfortunate that this slipped through the cracks, I wasn't aware of it. I think we should have a way to add a module to the import map without it being a dependency of another module that gets loaded manually in order to be used by scripts. @sirreal how do we solve this, it feels like a small thing to allow without necessarily making all scripts modules.

@afercia
Copy link
Contributor

afercia commented Apr 3, 2024

it'd be nice to make syntax highlighting opt-out to respect the user preference, as it does for the Customizer.

Just for compelteness, it does it also for the Theme File Editor and for the Plugin File Editor.

@sirreal
Copy link
Member

sirreal commented Apr 3, 2024

@sirreal how do we solve this, it feels like a small thing to allow without necessarily making all scripts modules.

Scripts and modules are completely separate right now, there's no interoperability or interdependence right now. I hope to have a good solution for WordPress 6.6. Work is happening in this Trac Ticket.

@okmttdhr
Copy link
Contributor Author

📝 I plan to revisit this PR again in a while, as I currently don't have much time. But feel free to take this over if anyone is interested.

@annezazu
Copy link
Contributor

Tagging in a few folks who might be interested in taking this across the line for 6.7 cc @carolinan @Mamaduka @aristath @t-hamano. It would be awesome to see this finally added in.

@sirreal
Copy link
Member

sirreal commented Jun 25, 2024

Scripts and modules are completely separate right now, there's no interoperability or interdependence right now. I hope to have a good solution for WordPress 6.6. Work is happening in this Trac Ticket.

I've created this "Script Modules: Allow scripts to depend on modules" ticket for efforts to allow Scripts to depend on Script Modules.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Block] HTML Affects the the HTML Block Global Styles Anything related to the broader Global Styles efforts, including Styles Engine and theme.json Needs Accessibility Feedback Need input from accessibility [Type] Enhancement A suggestion for improvement.
Projects
None yet
Development

Successfully merging this pull request may close these issues.