-
Notifications
You must be signed in to change notification settings - Fork 257
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
Remove DOMParser from Blueprints: installPlugin and installTheme #427
Remove DOMParser from Blueprints: installPlugin and installTheme #427
Conversation
@adamziel Thank you for reviewing this rough draft. I didn't know about the I started the PR by writing an automated test, but realized that the Playground on Node.js side, So, for now, the test will be bare bones with PHP WASM, only to confirm that the plugin was extracted to the expected location. I'll do some manual tests on the browser side for plugin activation, which requires WordPress. In the CI logs, you can see that the call to
Apparently it's because the variable Working on this PR is turning out to be a good excursion through the codebase, learning about various new aspects of the project. |
Still trying to figure this out. It's definitely an instance of return new File([buffer], this.name); The buffer is const file = new File([buffer], this.name);
console.log(await file.arrayBuffer());
return file; And get the same error:
Weird. I'm going to try using EDIT: Same error with literal resource passing raw buffer as Looks like the It extends the |
On the browser side, it's getting close. At the last step of the install process, this line: await playground.mv(tmpPluginPath, pluginPath); Throws:
EDIT: The FS method is called |
Yes, that’s definitely something to improve. Perhaps it will make sense to put parts of wp-now there.
A-ha! That’s an interesting idea!
That’s a challenging one. Perhaps building wp-now to a single bundle and then using that to run Blueprints tests would solve it here. This is the second time this comes up today- the first time was in #434 |
Co-authored-by: Adam Zielinski <[email protected]>
…to provide missing method File.arrayBuffer()
…as been fixed upstream
OK, the server-side test is now passing. I had to patch On the browser side, it looks like I've prepared a separate little PR for |
packages/playground/blueprints/src/lib/steps/activate-plugin.ts
Outdated
Show resolved
Hide resolved
…e or relative path)
* Import the polyfilled File class below to ensure its buffer is available to | ||
* functions like writeFile (./client-methods.ts) and fileToUint8Array (above). | ||
*/ | ||
class FilePolyfill extends File { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ideally this would live in tests, but that makes importing Blueprints in other packages tricky as every package would have to polyfill it. I think this is a neat solution, thank you for taking the time to explore this 👍
/** | ||
* Install asset: Extract folder from zip file and move it to target | ||
*/ | ||
export async function installAsset( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I initially had this in mind as an internal utility to aid other steps, I wonder whether this makes sense as its own step 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The term "asset" seems ambiguous as part of a public API. Internally it means:
- a zip package
- with a single folder of files in it
- to be extracted to a target path
Technically it's generic, not limited to plugins and themes - but I can't imagine what else would be considered "assets" that has the above characteristics.
There could be an installMuPlugin
blueprint step, same as for plugins but with target mu-plugins
.
Media files could be another kind of asset. Maybe an installMedia
step that uses installAssets
. Unlike plugins/themes, it would not require a single container folder. And the step will need to run additional PHP to upload the files into the media library.
So I think installAsset
by itself may not be useful to expose as a blueprint step, and can probably stay an internal helper function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh sorry I got confused. It is in the steps directory and kind of looks like a step declaration, but it actually is an internal helper. My bad!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be nice to put each step in a separate file and move helpers somewhere distinct, maybe a subdirectory? Let's figure this out separately
packages/playground/blueprints/src/lib/steps/activate-plugin.ts
Outdated
Show resolved
Hide resolved
This is looking great @eliot-akira! Two more comments from me, otherwise it looks ready. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Really great work here @eliot-akira ! Now these can be used outside of the browser and power the CLI tools!
Thank you for a thorough review of the PR. That was good exercise and satisfying to see the code get refined through discussion. I discovered there's another significant use of |
## What? Add `prependPath` option to `PHP.listFiles` method, which will prepend given folder path to every file found in it. ## Why? It's a common need to iterate over a list of files with each file path being an accessible path instead of only the file name. Idea mentioned in: - #427 (comment) For example, this is a common pattern: ```ts const files = await playground.listFiles( folderPath ) for (const file of files) { const filePath = `${folderPath}/${file}`; ... } ``` Also expressed as: ```ts const filePaths = (await playground.listFiles( folderPath )).map( (name: string) => `${folderPath}/${name}`) ) ``` With the new option, the above can be simplified as: ```ts const filePaths = await playground.listFiles(folderPath, { prependPath: true }) ``` ## How? - [x] Add `prependPath` option to `BasePHP.listFiles` method - [x] Document the option and what it does - [x] Add test ## Testing Instructions <!-- Please include step by step instructions on how to test this PR. --> 1. Check out the branch. 2. Run `nx test playground-blueprints`
Installing a plugin where the plugin files are directly at the top level does not work. This PR assumes that, unless the zip file contains only a single directory, the plugin files start at the top level. Related: #427 Unit tests included. Run `npm run dev` and confirm that adding ?gutenberg-pr=47739 to the URL installs the PR.
Installing a plugin where the plugin files are directly at the top level does not work. This PR assumes that, unless the zip file contains only a single directory, the plugin files start at the top level. Related: #427 Unit tests included. Run `npm run dev` and confirm that adding ?gutenberg-pr=47739 to the URL installs the PR.
Installing a plugin where the plugin files are directly at the top level does not work. This PR assumes that, unless the zip file contains only a single directory, the plugin files start at the top level. Related: #427 Unit tests included. Run `npm run dev` and confirm that adding ?gutenberg-pr=47739 to the URL installs the PR.
## What? Add `prependPath` option to `PHP.listFiles` method, which will prepend given folder path to every file found in it. ## Why? It's a common need to iterate over a list of files with each file path being an accessible path instead of only the file name. Idea mentioned in: - WordPress/wordpress-playground#427 (comment) For example, this is a common pattern: ```ts const files = await playground.listFiles( folderPath ) for (const file of files) { const filePath = `${folderPath}/${file}`; ... } ``` Also expressed as: ```ts const filePaths = (await playground.listFiles( folderPath )).map( (name: string) => `${folderPath}/${name}`) ) ``` With the new option, the above can be simplified as: ```ts const filePaths = await playground.listFiles(folderPath, { prependPath: true }) ``` ## How? - [x] Add `prependPath` option to `BasePHP.listFiles` method - [x] Document the option and what it does - [x] Add test ## Testing Instructions <!-- Please include step by step instructions on how to test this PR. --> 1. Check out the branch. 2. Run `nx test playground-blueprints`
What?
The goal of this pull request is to remove the use of any browser-specific API such as
DOMParser
from the Blueprints package. This allows all Blueprint steps to run on the browser and server side.Why?
Currently, the steps
installPlugin
andinstallTheme
can only be run with the Playground in the browser, not on server side withwp-now
and Node.js, because they use theasDOM
helper function which depends on theDOMParser
class only available in the browser.Related discussion:
The initial idea was to introduce an "isomorphic DOM" library that exports native DOM API for the browser and jsdom for Node.js. That would have allowed the existing implementation of
installPlugin
andinstallTheme
to work as is on server side.However, after weighing the pros and cons, it was decided that it's simpler to maintain if we rewrite these steps to perform their actions without using any DOM operations.
How?
installPlugin
andinstallTheme
to use Playground and PHP WASM API.asDOM
helper function.Testing Instructions
npx nx test playground-blueprints