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

Theme export: convert uploaded URLs to relative path assets #66407

Draft
wants to merge 12 commits into
base: trunk
Choose a base branch
from

Conversation

ramonjd
Copy link
Member

@ramonjd ramonjd commented Oct 24, 2024

🚧

Warning

Experimental code - please don't treat it as ready yet. Thank you!

What? How?

This is a first pass, so it's pretty rough and tumble. No tests or defensive coding yet.

This PR checks a theme tree for URIs containing the current site's upload path. If found:

  • it replaces the paths with a relative equivalent: 'http://domain/wp-content/uploads/1/2/test.gif' >' file:./uploads/test.gif'
  • fetches the file and adds it to the zip in /uploads

The outcome is that the uploaded files become part of the new theme's asset library, and can therefore be installed anywhere.

Why?

A theme can use uploaded files for:

  • fonts
  • background images

The paths to these assets are absolute URIs to the uploaded files.

Currently, when exporting themes these URIs are preserved in the theme.json, which means that the theme isn't "portable" in that relies on those hosted assets.

Testing Instructions

  1. In the site editor, go to global styles and upload a font or two.
  2. Upload some images and use them as background images for the site or for quote/pullquote/group blocks.
  3. Save the styles.
  4. Now export the theme and open the zip.
  5. In theme.json, the absolute paths to uploaded files should be converted to relative file:./ paths
  6. The uploaded files themselves should be available in /uploads in the zip.
  7. Now upload the exported theme and activate it in your site. Check that it all works as expected.

Exported theme.json [BEFORE]

					"fontFace": [
						{
							"fontFamily": "\"Star Jedi\"",
							"fontStyle": "normal",
							"fontWeight": "400",
							"src": "http://localhost:8888/wp-content/uploads/fonts/Starjedi.ttf"
						}
					],

Exported theme.json [AFTER]

					"fontFace": [
						{
							"fontFamily": "\"Star Jedi\"",
							"fontStyle": "normal",
							"fontWeight": "400",
							"src": "file:./uploads/Starjedi.ttf"
						}
					],

Screenshots or screencast

Screenshot 2024-10-25 at 7 20 17 am

@ramonjd ramonjd self-assigned this Oct 24, 2024
@ramonjd ramonjd added [Feature] Themes Questions or issues with incorporating or styling blocks in a theme. [Type] Experimental Experimental feature or API. labels Oct 24, 2024
lib/block-template-utils.php Outdated Show resolved Hide resolved
lib/block-template-utils.php Outdated Show resolved Hide resolved
lib/block-template-utils.php Outdated Show resolved Hide resolved
lib/block-template-utils.php Show resolved Hide resolved
@ramonjd ramonjd changed the title First try at converting all uploaded URLs to relative path assets Theme export: convert uploaded URLs to relative path assets Oct 24, 2024
@ramonjd ramonjd added the [Status] In Progress Tracking issues with work in progress label Oct 24, 2024
Copy link

github-actions bot commented Oct 24, 2024

Flaky tests detected in 8646cce.
Some tests passed with failed attempts. The failures may not be related to this commit but are still reported for visibility. See the documentation for more information.

🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/11512116126
📝 Reported issues:

@@ -30,6 +30,8 @@ function gutenberg_get_global_stylesheet( $types = array() ) {
$tree = WP_Theme_JSON_Resolver_Gutenberg::get_merged_data();
$tree = WP_Theme_JSON_Resolver_Gutenberg::resolve_theme_file_uris( $tree );

var_dump( WP_Theme_JSON_Resolver_Gutenberg::get_migrated_relative_theme_uris( $tree ) );
Copy link
Member Author

Choose a reason for hiding this comment

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

Just to test the output

*/
public static function get_resolved_theme_uris( $theme_json ) {
$resolved_theme_uris = array();
private static function process_theme_uris( $theme_json, $options = array() ) {
Copy link
Member Author

Choose a reason for hiding this comment

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

Everything here and below is a major refactor. Just testing things out for now.

Basically so we have a single source of truth about where these types of URIs live.

Copy link
Contributor

@andrewserong andrewserong left a comment

Choose a reason for hiding this comment

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

Just a drive-by comment to say I love this idea, feels like a quality of life improvement that'll make exporting feel that much smoother 👍

In terms of the directory where we save the file, at first I saw "uploads" as a directory and wondered if "assets" would be better. Now that I see it's been updated to "assets", I'm wondering if that could conflict with how a theme has structured its other... assets?

Naming and defaults are tricky to figure out, but I was wondering what the trade-offs might be between storing the uploaded files somewhere explicit so that they don't conflict (or aren't mixed up with) files that live with the theme (uploads) OR attempting to place them somewhere that makes sense as a permanent home for the files (assets) 🤔

I was half wondering if we might need an export modal at some point for configuration of the output zip — with this PR there'd only be a single field, though, so maybe not very useful just yet 😄

Anyway, mostly just wanted to say thanks for working on this!

@ramonjd
Copy link
Member Author

ramonjd commented Oct 25, 2024

Thank you @andrewserong!

I'm a bit obsessed with it now - I want to get it working 🤣 With fonts working, it's a pretty good quality of life upgrade!

Now that I see it's been updated to "assets", I'm wondering if that could conflict with how a theme has structured its other... assets?

I'm dumping the files under assets in the zip, but I guess there could be a slight risk of overwriting existing files where assets already exists. Then again, there's that risk with any name we choose.

Maybe /assets/_external or /assets/_custom would mitigate it? I don't know. This PR is now so messy, I'm sure we'll think of something by the time I clean it up and write tests. 😄

I was half wondering if we might need an export modal at some point for configuration of the output zip

Good idea for down the road!

@youknowriad
Copy link
Contributor

I like "assets", I think it's good to set a convention there.

I don't understand much how we'll be overwriting anything though? We're exporting a new theme right and we control all its content no?

@ramonjd
Copy link
Member Author

ramonjd commented Oct 25, 2024

I don't understand much how we'll be overwriting anything though? We're exporting a new theme right and we control all its content no?

Might have been paranoia. Just in case an uploaded file has the same name as a theme file already under /assets, if that's even likely.

@carolinan
Copy link
Contributor

carolinan commented Oct 25, 2024

Thank you for working on this.
I assume you have already compared with how it is solved in Create Block Theme?

I don't understand much how we'll be overwriting anything though? We're exporting a new theme right and we control all its content no?

I am not sure I understood the question correctly.
The Export from the Site Editor includes all the existing folders and files in the active theme. Plus the user's changes.

@youknowriad
Copy link
Contributor

The Export from the Site Editor includes all the existing folders and files in the active theme.

I see I didn't know about this. Personally, I'm not entirely sure this is a good idea. I'd rather "compute" the full theme.

@ramonjd
Copy link
Member Author

ramonjd commented Oct 25, 2024

Thanks for the feedback!

I assume you have already compared with how it is solved in Create Block Theme?

For fonts, this PR does something very similar to CBT_Theme_Zip::add_activated_fonts_to_zip() (src), however Create Block Theme doesn't handle the migration of background urls, so it will export theme.json like this:

	"styles": {
		"background": {
			"backgroundImage": {
				"id": 7,
				"source": "file",
				"title": "default_man_sitting_alone_eating_lunch_thinking_about_WordPressXRhXpu",
				"url": "http://localhost:8888/wp-content/uploads/2024/10/default_man_sitting_alone_eating_lunch_thinking_about_WordPressXRhXpu.png"
			}
		},

The goal of this PR is for the exported theme.json to look more like this:

	"styles": {
		"background": {
			"backgroundImage": {
				"url": "file:./assets/default_man_sitting_alone_eating_lunch_thinking_about_WordPressXRhXpu.png"
			}
		},

The image file is fetched and dumped in /assets/ in the zip.

I'd rather "compute" the full theme.

What would that look like do you think?

In this PR, I don't think it's much of a stretch to check for duplicate names in the destination directory via locateName() and then do some renaming faffery. 🤷🏻

lib/block-template-utils.php Outdated Show resolved Hide resolved
Ensure to strip background image properties before setting relative path
$href = array(
'url' => $href,
);
}
Copy link
Member Author

Choose a reason for hiding this comment

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

@carolinan
Copy link
Contributor

The issue for this PR is: #41798

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Feature] Themes Questions or issues with incorporating or styling blocks in a theme. [Status] In Progress Tracking issues with work in progress [Type] Experimental Experimental feature or API.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants