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

Extract common layout styles #35867

Closed
wants to merge 4 commits into from
Closed

Conversation

youknowriad
Copy link
Contributor

Right now Gutenberg supports two layout types "flow" (or default) and "flex" (row block). Blocks using these layouts generate inline <style> tags because each block can have a different layout configuration.

Things that make the layout styles dynamic:

  • Whether the theme supports block gap or not
  • Widths (content and wide widths)
  • Justification (left, right, space between...)

That said, there are things that are common across layout types, this PR extracts these common styles to the common.css stylesheet that is loaded for all themes.

Conceptually speaking, I still have a preference for the "all dynamic" approach we have in trunk but in terms of "purity" of the output, this is probably a bit better so I'm personally hesitant.

@youknowriad youknowriad added the [Type] Code Quality Issues or PRs that relate to code quality label Oct 22, 2021
@youknowriad youknowriad self-assigned this Oct 22, 2021
}

$style .= "$selector .alignleft { float: left; margin-right: 2em; }";
$style .= "$selector .alignright { float: right; margin-left: 2em; }";
if ( $has_block_gap_support ) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This dynamic part can potentially be transformed to a static style if we introduce some kind of global .has-block-gap-support classname to the root of the block editor and the frontend. Thoughts?

Copy link
Member

Choose a reason for hiding this comment

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

Extracting these sort of styles to its own file (also from lib/class-wp-theme-json-gutenberg.php) will help with #35736 (comment)

@@ -89,3 +89,40 @@
width: auto;
z-index: 100000;
}

// Default Flow Layout
.wp-site-blocks > *,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

wp-site-blocks is the root of all block templates, potentially we could add the wp-layout-default classname to the template output instead of duplicating these selectors.

@github-actions
Copy link

github-actions bot commented Oct 22, 2021

Size Change: +1.58 kB (0%)

Total Size: 1.07 MB

Filename Size Change
build/block-editor/index.min.js 135 kB -419 B (0%)
build/block-editor/style-rtl.css 13.9 kB -1 B (0%)
build/block-editor/style.css 13.9 kB -2 B (0%)
build/block-library/blocks/navigation-link/editor-rtl.css 488 B -80 B (-14%) 👏
build/block-library/blocks/navigation-link/editor.css 489 B -81 B (-14%) 👏
build/block-library/blocks/navigation/editor-rtl.css 1.71 kB -8 B (0%)
build/block-library/blocks/navigation/editor.css 1.71 kB -6 B (0%)
build/block-library/blocks/navigation/style-rtl.css 1.7 kB +10 B (+1%)
build/block-library/blocks/navigation/style.css 1.69 kB +14 B (+1%)
build/block-library/blocks/post-comments-form/style-rtl.css 347 B +207 B (+148%) 🆘
build/block-library/blocks/post-comments-form/style.css 347 B +207 B (+148%) 🆘
build/block-library/blocks/post-comments/style-rtl.css 475 B +115 B (+32%) 🚨
build/block-library/blocks/post-comments/style.css 475 B +116 B (+32%) 🚨
build/block-library/common-rtl.css 935 B +120 B (+15%) ⚠️
build/block-library/common.css 932 B +120 B (+15%) ⚠️
build/block-library/editor-rtl.css 9.67 kB +14 B (0%)
build/block-library/editor.css 9.67 kB +15 B (0%)
build/block-library/index.min.js 149 kB +8 B (0%)
build/block-library/style-rtl.css 10.6 kB +243 B (+2%)
build/block-library/style.css 10.6 kB +243 B (+2%)
build/components/index.min.js 212 kB +7 B (0%)
build/dom/index.min.js 4.44 kB -15 B (0%)
build/edit-post/index.min.js 29.4 kB +56 B (0%)
build/edit-widgets/index.min.js 16.3 kB +592 B (+4%)
build/edit-widgets/style-rtl.css 4.17 kB +51 B (+1%)
build/edit-widgets/style.css 4.18 kB +50 B (+1%)
ℹ️ View Unchanged
Filename Size
build/a11y/index.min.js 931 B
build/admin-manifest/index.min.js 1.09 kB
build/annotations/index.min.js 2.7 kB
build/api-fetch/index.min.js 2.21 kB
build/autop/index.min.js 2.08 kB
build/blob/index.min.js 459 B
build/block-directory/index.min.js 6.2 kB
build/block-directory/style-rtl.css 1.01 kB
build/block-directory/style.css 1.01 kB
build/block-editor/default-editor-styles-rtl.css 378 B
build/block-editor/default-editor-styles.css 378 B
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 65 B
build/block-library/blocks/archives/style.css 65 B
build/block-library/blocks/audio/editor-rtl.css 58 B
build/block-library/blocks/audio/editor.css 58 B
build/block-library/blocks/audio/style-rtl.css 111 B
build/block-library/blocks/audio/style.css 111 B
build/block-library/blocks/audio/theme-rtl.css 125 B
build/block-library/blocks/audio/theme.css 125 B
build/block-library/blocks/block/editor-rtl.css 161 B
build/block-library/blocks/block/editor.css 161 B
build/block-library/blocks/button/editor-rtl.css 470 B
build/block-library/blocks/button/editor.css 470 B
build/block-library/blocks/button/style-rtl.css 549 B
build/block-library/blocks/button/style.css 549 B
build/block-library/blocks/buttons/editor-rtl.css 309 B
build/block-library/blocks/buttons/editor.css 309 B
build/block-library/blocks/buttons/style-rtl.css 317 B
build/block-library/blocks/buttons/style.css 317 B
build/block-library/blocks/calendar/style-rtl.css 207 B
build/block-library/blocks/calendar/style.css 207 B
build/block-library/blocks/categories/editor-rtl.css 84 B
build/block-library/blocks/categories/editor.css 83 B
build/block-library/blocks/categories/style-rtl.css 79 B
build/block-library/blocks/categories/style.css 79 B
build/block-library/blocks/code/style-rtl.css 90 B
build/block-library/blocks/code/style.css 90 B
build/block-library/blocks/code/theme-rtl.css 131 B
build/block-library/blocks/code/theme.css 131 B
build/block-library/blocks/columns/editor-rtl.css 206 B
build/block-library/blocks/columns/editor.css 205 B
build/block-library/blocks/columns/style-rtl.css 497 B
build/block-library/blocks/columns/style.css 496 B
build/block-library/blocks/cover/editor-rtl.css 546 B
build/block-library/blocks/cover/editor.css 547 B
build/block-library/blocks/cover/style-rtl.css 1.17 kB
build/block-library/blocks/cover/style.css 1.17 kB
build/block-library/blocks/embed/editor-rtl.css 488 B
build/block-library/blocks/embed/editor.css 488 B
build/block-library/blocks/embed/style-rtl.css 417 B
build/block-library/blocks/embed/style.css 417 B
build/block-library/blocks/embed/theme-rtl.css 124 B
build/block-library/blocks/embed/theme.css 124 B
build/block-library/blocks/file/editor-rtl.css 300 B
build/block-library/blocks/file/editor.css 300 B
build/block-library/blocks/file/style-rtl.css 255 B
build/block-library/blocks/file/style.css 255 B
build/block-library/blocks/file/view.min.js 322 B
build/block-library/blocks/freeform/editor-rtl.css 2.44 kB
build/block-library/blocks/freeform/editor.css 2.44 kB
build/block-library/blocks/gallery/editor-rtl.css 977 B
build/block-library/blocks/gallery/editor.css 982 B
build/block-library/blocks/gallery/style-rtl.css 1.6 kB
build/block-library/blocks/gallery/style.css 1.59 kB
build/block-library/blocks/gallery/theme-rtl.css 122 B
build/block-library/blocks/gallery/theme.css 122 B
build/block-library/blocks/group/editor-rtl.css 159 B
build/block-library/blocks/group/editor.css 159 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 114 B
build/block-library/blocks/heading/style.css 114 B
build/block-library/blocks/home-link/style-rtl.css 247 B
build/block-library/blocks/home-link/style.css 247 B
build/block-library/blocks/html/editor-rtl.css 332 B
build/block-library/blocks/html/editor.css 333 B
build/block-library/blocks/image/editor-rtl.css 731 B
build/block-library/blocks/image/editor.css 730 B
build/block-library/blocks/image/style-rtl.css 502 B
build/block-library/blocks/image/style.css 505 B
build/block-library/blocks/image/theme-rtl.css 124 B
build/block-library/blocks/image/theme.css 124 B
build/block-library/blocks/latest-comments/style-rtl.css 284 B
build/block-library/blocks/latest-comments/style.css 284 B
build/block-library/blocks/latest-posts/editor-rtl.css 137 B
build/block-library/blocks/latest-posts/editor.css 137 B
build/block-library/blocks/latest-posts/style-rtl.css 528 B
build/block-library/blocks/latest-posts/style.css 527 B
build/block-library/blocks/list/style-rtl.css 94 B
build/block-library/blocks/list/style.css 94 B
build/block-library/blocks/media-text/editor-rtl.css 266 B
build/block-library/blocks/media-text/editor.css 263 B
build/block-library/blocks/media-text/style-rtl.css 493 B
build/block-library/blocks/media-text/style.css 490 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/style-rtl.css 94 B
build/block-library/blocks/navigation-link/style.css 94 B
build/block-library/blocks/navigation-submenu/editor-rtl.css 299 B
build/block-library/blocks/navigation-submenu/editor.css 299 B
build/block-library/blocks/navigation-submenu/style-rtl.css 195 B
build/block-library/blocks/navigation-submenu/style.css 195 B
build/block-library/blocks/navigation-submenu/view.min.js 343 B
build/block-library/blocks/navigation/view.min.js 2.74 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 198 B
build/block-library/blocks/page-list/style.css 198 B
build/block-library/blocks/paragraph/editor-rtl.css 157 B
build/block-library/blocks/paragraph/editor.css 157 B
build/block-library/blocks/paragraph/style-rtl.css 273 B
build/block-library/blocks/paragraph/style.css 273 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-excerpt/editor-rtl.css 73 B
build/block-library/blocks/post-excerpt/editor.css 73 B
build/block-library/blocks/post-excerpt/style-rtl.css 69 B
build/block-library/blocks/post-excerpt/style.css 69 B
build/block-library/blocks/post-featured-image/editor-rtl.css 396 B
build/block-library/blocks/post-featured-image/editor.css 397 B
build/block-library/blocks/post-featured-image/style-rtl.css 156 B
build/block-library/blocks/post-featured-image/style.css 156 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 391 B
build/block-library/blocks/post-template/style.css 392 B
build/block-library/blocks/post-terms/style-rtl.css 73 B
build/block-library/blocks/post-terms/style.css 73 B
build/block-library/blocks/post-title/style-rtl.css 60 B
build/block-library/blocks/post-title/style.css 60 B
build/block-library/blocks/preformatted/style-rtl.css 103 B
build/block-library/blocks/preformatted/style.css 103 B
build/block-library/blocks/pullquote/editor-rtl.css 198 B
build/block-library/blocks/pullquote/editor.css 198 B
build/block-library/blocks/pullquote/style-rtl.css 378 B
build/block-library/blocks/pullquote/style.css 378 B
build/block-library/blocks/pullquote/theme-rtl.css 167 B
build/block-library/blocks/pullquote/theme.css 167 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 262 B
build/block-library/blocks/query-pagination/editor.css 255 B
build/block-library/blocks/query-pagination/style-rtl.css 234 B
build/block-library/blocks/query-pagination/style.css 231 B
build/block-library/blocks/query/editor-rtl.css 131 B
build/block-library/blocks/query/editor.css 132 B
build/block-library/blocks/quote/style-rtl.css 187 B
build/block-library/blocks/quote/style.css 187 B
build/block-library/blocks/quote/theme-rtl.css 223 B
build/block-library/blocks/quote/theme.css 226 B
build/block-library/blocks/rss/editor-rtl.css 202 B
build/block-library/blocks/rss/editor.css 204 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 165 B
build/block-library/blocks/search/editor.css 165 B
build/block-library/blocks/search/style-rtl.css 397 B
build/block-library/blocks/search/style.css 398 B
build/block-library/blocks/search/theme-rtl.css 64 B
build/block-library/blocks/search/theme.css 64 B
build/block-library/blocks/separator/editor-rtl.css 99 B
build/block-library/blocks/separator/editor.css 99 B
build/block-library/blocks/separator/style-rtl.css 250 B
build/block-library/blocks/separator/style.css 250 B
build/block-library/blocks/separator/theme-rtl.css 172 B
build/block-library/blocks/separator/theme.css 172 B
build/block-library/blocks/shortcode/editor-rtl.css 474 B
build/block-library/blocks/shortcode/editor.css 474 B
build/block-library/blocks/site-logo/editor-rtl.css 770 B
build/block-library/blocks/site-logo/editor.css 770 B
build/block-library/blocks/site-logo/style-rtl.css 165 B
build/block-library/blocks/site-logo/style.css 165 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 84 B
build/block-library/blocks/site-title/editor.css 84 B
build/block-library/blocks/social-link/editor-rtl.css 177 B
build/block-library/blocks/social-link/editor.css 177 B
build/block-library/blocks/social-links/editor-rtl.css 824 B
build/block-library/blocks/social-links/editor.css 823 B
build/block-library/blocks/social-links/style-rtl.css 1.32 kB
build/block-library/blocks/social-links/style.css 1.32 kB
build/block-library/blocks/spacer/editor-rtl.css 307 B
build/block-library/blocks/spacer/editor.css 307 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 471 B
build/block-library/blocks/table/editor.css 472 B
build/block-library/blocks/table/style-rtl.css 481 B
build/block-library/blocks/table/style.css 481 B
build/block-library/blocks/table/theme-rtl.css 188 B
build/block-library/blocks/table/theme.css 188 B
build/block-library/blocks/tag-cloud/style-rtl.css 146 B
build/block-library/blocks/tag-cloud/style.css 146 B
build/block-library/blocks/template-part/editor-rtl.css 560 B
build/block-library/blocks/template-part/editor.css 559 B
build/block-library/blocks/template-part/theme-rtl.css 101 B
build/block-library/blocks/template-part/theme.css 101 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 87 B
build/block-library/blocks/verse/style.css 87 B
build/block-library/blocks/video/editor-rtl.css 571 B
build/block-library/blocks/video/editor.css 572 B
build/block-library/blocks/video/style-rtl.css 173 B
build/block-library/blocks/video/style.css 173 B
build/block-library/blocks/video/theme-rtl.css 124 B
build/block-library/blocks/video/theme.css 124 B
build/block-library/reset-rtl.css 474 B
build/block-library/reset.css 474 B
build/block-library/theme-rtl.css 668 B
build/block-library/theme.css 673 B
build/block-serialization-default-parser/index.min.js 1.09 kB
build/block-serialization-spec-parser/index.min.js 2.79 kB
build/blocks/index.min.js 46 kB
build/components/style-rtl.css 15.3 kB
build/components/style.css 15.3 kB
build/compose/index.min.js 10.4 kB
build/core-data/index.min.js 12.4 kB
build/customize-widgets/index.min.js 11.2 kB
build/customize-widgets/style-rtl.css 1.5 kB
build/customize-widgets/style.css 1.49 kB
build/data-controls/index.min.js 614 B
build/data/index.min.js 7.1 kB
build/date/index.min.js 31.5 kB
build/deprecated/index.min.js 428 B
build/dom-ready/index.min.js 304 B
build/edit-navigation/index.min.js 15.8 kB
build/edit-navigation/style-rtl.css 3.76 kB
build/edit-navigation/style.css 3.76 kB
build/edit-post/classic-rtl.css 492 B
build/edit-post/classic.css 494 B
build/edit-post/style-rtl.css 7.12 kB
build/edit-post/style.css 7.12 kB
build/edit-site/index.min.js 30.7 kB
build/edit-site/style-rtl.css 5.71 kB
build/edit-site/style.css 5.71 kB
build/editor/index.min.js 37.6 kB
build/editor/style-rtl.css 3.78 kB
build/editor/style.css 3.77 kB
build/element/index.min.js 3.21 kB
build/escape-html/index.min.js 517 B
build/format-library/index.min.js 5.99 kB
build/format-library/style-rtl.css 571 B
build/format-library/style.css 571 B
build/hooks/index.min.js 1.55 kB
build/html-entities/index.min.js 424 B
build/i18n/index.min.js 3.6 kB
build/is-shallow-equal/index.min.js 501 B
build/keyboard-shortcuts/index.min.js 1.72 kB
build/keycodes/index.min.js 1.3 kB
build/list-reusable-blocks/index.min.js 1.85 kB
build/list-reusable-blocks/style-rtl.css 838 B
build/list-reusable-blocks/style.css 838 B
build/media-utils/index.min.js 2.92 kB
build/notices/index.min.js 845 B
build/nux/index.min.js 2.03 kB
build/nux/style-rtl.css 747 B
build/nux/style.css 743 B
build/plugins/index.min.js 1.83 kB
build/primitives/index.min.js 921 B
build/priority-queue/index.min.js 582 B
build/react-i18n/index.min.js 671 B
build/redux-routine/index.min.js 2.63 kB
build/reusable-blocks/index.min.js 2.19 kB
build/reusable-blocks/style-rtl.css 256 B
build/reusable-blocks/style.css 256 B
build/rich-text/index.min.js 10.7 kB
build/server-side-render/index.min.js 1.52 kB
build/shortcode/index.min.js 1.48 kB
build/token-list/index.min.js 562 B
build/url/index.min.js 1.74 kB
build/viewport/index.min.js 1.02 kB
build/warning/index.min.js 248 B
build/widgets/index.min.js 7.11 kB
build/widgets/style-rtl.css 1.16 kB
build/widgets/style.css 1.16 kB
build/wordcount/index.min.js 1.04 kB

compressed-size-action

@jasmussen
Copy link
Contributor

I'm seeing some auto margins wreaking some havoc in my theme. Before:
Screenshot 2021-10-22 at 10 41 34

After:

Screenshot 2021-10-22 at 10 40 03

It's this rule, applying now:
Screenshot 2021-10-22 at 10 39 48

In my structure, I have .is-root-container > [header template part] > [navigation block], but it appears that the navigation block is now receiving the wp-layout-default classname, and therefore the subsequent forced left/right auto-margins for child blocks. That doesn't seem right? Shouldn't only top level blocks get those auto-margin rules?

@youknowriad
Copy link
Contributor Author

the navigation block is now receiving the wp-layout-default classname, and therefore the subsequent forced left/right auto-margins for child blocks. That doesn't seem right?

Well in my mental modal, it seems right :) I need to understand why in trunk it was not already receiving these styles dynamically (generated classname + style)

@jasmussen
Copy link
Contributor

Which blocks would receive the wp-layout-default class?

The reason I'm asking is that the auto margins applied to direct descendants of thoes blocks is quite high (!important), and we want to be sure centering the children of said blocks is actually what we want. In the case of the navigation block, I don't understand why we'd ever center descendant children — that could be because it isn't using the new flex system quite yet, but I imagine the vertical one wouldn't either.

@youknowriad
Copy link
Contributor Author

Which blocks would receive the wp-layout-default class?

I guess all blocks that have the "default layout" meaning all blocks that use "inner blocks" that didn't specify an alternative layout (like flex).

Maybe we had a mechanism in place to avoid that in trunk but I can't find it.

@youknowriad
Copy link
Contributor Author

@jasmussen Found it nevermind, I'll push a fix.

@jasmussen
Copy link
Contributor

Thanks, I'll take a look when I can. I'm still curious though, and I feel like we've already discussed this — the centered column which is the purpose of the auto margins feels most useful for top level blocks to create the initial main column, or for full-wide top level blocks. Centering every child for nested flow content makes less sense for me. 🤔

@youknowriad
Copy link
Contributor Author

@jasmussen For me, every container block should have a layout. That said, it's not the case anymore anyway with my last commit (for backward compatibility reasons). For me the navigation block should have a "flex layout" which doesn't have the centering.

@jasmussen
Copy link
Contributor

I agree with both the layout and proper flex for navigation. My only challenge here is that I'm not sure centering child blocks of any flow content layout should be the default behavior. But it may be a non-issue in practice, per your last comment.

@youknowriad
Copy link
Contributor Author

My only challenge here is that I'm not sure centering child blocks of any flow content layout should be the default behavior.

It doesn't matter since by default there's no max width defined. so it doesn't have any impact. It's how it works now, if we want to remove these styles from the default flow layout, we can make them part of the "dynamic" styles (only included if widths are defined)

@youknowriad
Copy link
Contributor Author

Oh I just noticed that these margins are actually only applied when widths are defined on trunk (my bad), I'll restore that behavior.

@jasmussen
Copy link
Contributor

Just took it for a spin again this morning, and I'm seeing no difference between trunk and this branch in my testing. Which I suppose is good? Let me know if there's anything specific I can help with from this point on, or if I should be looking at something else.

@MaggieCabrera
Copy link
Contributor

I just tested this with emptytheme and our markup to test alignments and it looks like full width alignments are broken. Seems like we have lost the

.wp-container-61765cea1bf58 .alignfull {
    max-width: none;
}

kind of rule.

The markup I used is here. This is what I see:

Trunk This PR
Screenshot 2021-10-25 at 09-30-11 Alignments – Skatepark Screenshot 2021-10-25 at 09-30-25 Alignments – Skatepark

@youknowriad
Copy link
Contributor Author

I've pushed a fix here for @MaggieCabrera's bug. That said, I feel like I'm not satisfied with this PR. While in principle extracting these common styles can be good, It creates a lot of subtle issues:

  • Specificity battles between dynamic and static styles for these layouts.
  • Styles that work together split between two different code bases (CSS styles for the static ones and JS for the dynamic ones)

I'd be personally in favor of keeping things as they are in trunk. This means more inline <style> tags for sure, but it's simpler to guarantee that things are correct.

@MaggieCabrera
Copy link
Contributor

I've pushed a fix here for @MaggieCabrera's bug.

Thank you! that looks like it fixes it!

@youknowriad youknowriad deleted the add/extract-common-layout-styles branch November 29, 2021 07:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Type] Code Quality Issues or PRs that relate to code quality
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants