Skip to content

Commit

Permalink
Merge branch 'trunk' into add/wp-static-asset-zip
Browse files Browse the repository at this point in the history
  • Loading branch information
bgrgicak authored Jul 4, 2024
2 parents 1feb41a + abf5a41 commit f3fe08d
Show file tree
Hide file tree
Showing 181 changed files with 4,619 additions and 2,553 deletions.
2 changes: 1 addition & 1 deletion lerna.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"$schema": "node_modules/lerna/schemas/lerna-schema.json",
"version": "0.9.8",
"useWorkspaces": true,
"version": "0.9.2",
"useNx": true
}
1,927 changes: 1,091 additions & 836 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"format:uncommitted": "nx format --fix --parallel --uncommitted",
"lint": "nx run-many --all --target=lint",
"prepublishOnly": "npm run build",
"mindmap": "cd packages/meta/src/mindmap/v2 && php -S 127.0.0.1:5269",
"preview": "nx preview playground-website",
"recompile:php:web": "nx recompile-php:light:all php-wasm-web && nx recompile-php:kitchen-sink:all php-wasm-web ",
"recompile:php:web:light": "nx recompile-php:light:all php-wasm-web ",
Expand Down
92 changes: 72 additions & 20 deletions packages/docs/site/docs/09-blueprints-api/03-data-format.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,11 @@ sidebar_position: 1
title: Blueprint data Format
---

# Blueprint data Format
# Blueprint data format

A Blueprint can contain the following properties:
A Blueprint JSON file can have many different properties that will be used to define your Playground instance. The most important properties are detailed below.

- landingPage (string): The URL to navigate to after the Blueprint has been run.
- [preferredVersions](#preferred-versions): The preferred PHP and WordPress versions to use.
- [steps](./05-steps.md): The steps to run.

Here's a Blueprint that uses all of them:
Here's an example that uses many of them:

import BlueprintExample from '@site/src/components/Blueprints/BlueprintExample.mdx';

Expand All @@ -34,34 +30,90 @@ import BlueprintExample from '@site/src/components/Blueprints/BlueprintExample.m
]
}} />

## JSON Schema
## JSON schema

JSON files can be tedious to write and easy to get wrong. To help with that, Playground provides a [JSON schema](https://playground.wordpress.net/blueprint-schema.json) file that you can use to get autocompletion and validation in your editor:
JSON files can be tedious to write and easy to get wrong. To help with that, Playground provides a [JSON schema](https://playground.wordpress.net/blueprint-schema.json) file that you can use to get auto-completion and validation in your editor. Just set the `$schema` property to the following:

```js
{
"$schema": "https://playground.wordpress.net/blueprint-schema.json",
"landingPage": "/wp-admin/",
// ...
}
```

## Preferred Versions
## Landing page

The `preferredVersions` property, unsurprisingly, declares the preferred of PHP and WordPress versions to use. It can contain the following properties:
The `landingPage` property tells Playground which URL to navigate to after the Blueprint has been run. This is a great tool, especially when creating theme or plugin demos. Often, you will want to start Playground in the Site Editor or have a specific post open in the Post Editor. Make sure you use a relative path.

- `php` (string): The preferred PHP version to use. Defaults to "latest". Only accepts major versions, like "7.4" or "8.0". Minor versions like "7.4.1" are not supported.
- `wp` (string): Loads the specified WordPress version. Supported values: The last three major WordPress versions—minor versions, like `6.5.1`, are not supported. As of April 4, 2024, that's `6.3`, `6.4`, `6.5`. You can also use these values: `latest` (default), `nightly`, or `beta`.
```js
{
"landingPage": "/wp-admin/site-editor.php",
}
```

## Preferred versions

The `preferredVersions` property declares your preferred PHP and WordPress versions. It can contain the following properties:

- `php` (string): Loads the specified PHP version. Accepts `7.0`, `7.1`, `7.2`, `7.3`, `7.4`, `8.0`, `8.1`, `8.2`, `8.3`, or `latest`. Minor versions like `7.4.1` are not supported.
- `wp` (string): Loads the specified WordPress version. Accepts the last four major WordPress versions. As of June 1, 2024, that's `6.2`, `6.3`, `6.4`, or `6.5`. You can also use the generic values `latest`, `nightly`, or `beta`.

```js
{
"preferredVersions": {
"php": "8.0",
"wp": "6.5"
},
}
```

## PHP extensions

The `phpExtensionBundles` property is an array of PHP extension bundles to load. The following bundles are supported:
The `phpExtensionBundles` property is an array of PHP extension bundles that should be loaded. The following bundles are supported:

- `light`: Default choice. Saves 6MB of downloads, loads none of the extensions below.
- `kitchen-sink`: Installs [`gd`](https://www.php.net/manual/en/book.image.php), [`mbstring`](https://www.php.net/manual/en/mbstring.installation.php), [`iconv`](https://www.php.net/manual/en/function.iconv.php), [`openssl`](https://www.php.net/manual/en/book.openssl.php), [`libxml`](https://www.php.net/manual/en/book.libxml.php), [`xml`](https://www.php.net/manual/en/xml.installation.php), [`dom`](https://www.php.net/manual/en/intro.dom.php), [`simplexml`](https://www.php.net/manual/en/book.simplexml.php), [`xmlreader`](https://www.php.net/manual/en/book.xmlreader.php), [`xmlwriter`](https://www.php.net/manual/en/book.xmlwriter.php)
- `kitchen-sink`: Default choice. Installs [`gd`](https://www.php.net/manual/en/book.image.php), [`mbstring`](https://www.php.net/manual/en/mbstring.installation.php), [`iconv`](https://www.php.net/manual/en/function.iconv.php), [`openssl`](https://www.php.net/manual/en/book.openssl.php), [`libxml`](https://www.php.net/manual/en/book.libxml.php), [`xml`](https://www.php.net/manual/en/xml.installation.php), [`dom`](https://www.php.net/manual/en/intro.dom.php), [`simplexml`](https://www.php.net/manual/en/book.simplexml.php), [`xmlreader`](https://www.php.net/manual/en/book.xmlreader.php), and [`xmlwriter`](https://www.php.net/manual/en/book.xmlwriter.php)
- `light`: It saves 6MB of downloads and loads none of the extensions above.

```js
{
"phpExtensionBundles": [
"kitchen-sink"
],
}
```

## Features

The `features` property is used to enable or disable certain features of the Playground. It can contain the following properties:
You can use the `features` property to turn on or off certain features of the Playground instance. It can contain the following properties:

- `networking`: Defaults to `false`. Enables or disables the networking support for Playground. If enabled, [`wp_safe_remote_get`](https://developer.wordpress.org/reference/functions/wp_safe_remote_get/) and similar WordPress functions will actually use `fetch()` to make HTTP requests. If disabled, they will immediately fail instead.
- `networking`: Defaults to `false`. Enables or disables the networking support for Playground. If enabled, [`wp_safe_remote_get`](https://developer.wordpress.org/reference/functions/wp_safe_remote_get/) and similar WordPress functions will actually use `fetch()` to make HTTP requests. If disabled, they will immediately fail instead. You will need this property enabled if you want the user to be able to install plugins or themes.

```js
{
"features": {
"networking": true
},
}
```

## Steps

Arguably the most powerful property, `steps` allows you to configure the Playground instance with preinstalled themes, plugins, demo content, and more. The following example logs the user in with a dedicated username and password. It then installs and activates the Gutenberg plugin. [Learn more about steps](./05-steps.md).

```js
{
"steps": [
{
"step": "login",
"username": "admin",
"password": "password"
},
{
"step": "installPlugin",
"pluginZipFile": {
"resource": "wordpress.org/plugins",
"slug": "gutenberg"
}
},
]
}
```
229 changes: 229 additions & 0 deletions packages/meta/src/mindmap/v1/fetch-mindmap-data.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
const shouldRebuild =
new URLSearchParams(window.location.search).get('rebuild') === 'true';

let __moduleGithubToken = localStorage.getItem('GITHUB_TOKEN');
const repos = [
'wordpress/wordpress-playground',
'wordpress/playground-tools',
'wordpress/blueprints',
'wordpress/blueprints-library',
'adamziel/playground-docs-workflow',
'adamziel/site-transfer-protocol',
];

const comparableKey = (str) => str.toLowerCase();

const graphqlQuery = async (query, variables) => {
const headers = {
'Content-Type': 'application/json',
};
if (__moduleGithubToken) {
headers['Authorization'] = `Bearer ${__moduleGithubToken}`;
}
const response = await fetch('https://api.github.com/graphql', {
method: 'POST',
headers,
body: JSON.stringify({ query, variables }),
});
return response.json();
};

async function* iterateIssuesPRs(repo, labels = []) {
const query = `
query GetProjects($cursor: String!, $query: String!) {
search(query: $query, first: 100, type: ISSUE, after: $cursor) {
pageInfo {
hasNextPage
endCursor
}
edges {
node {
... on Issue {
number
title
url
body
state
repository {
nameWithOwner
}
labels(first: 10) {
nodes {
name
}
}
}
... on PullRequest {
number
title
url
body
state
repository {
nameWithOwner
}
labels(first: 10) {
nodes {
name
}
}
}
}
}
}
}
`;

let cursor = '';
do {
const labelQuery = labels.map((label) => `"${label}"`).join(',');
const variables = {
cursor,
query:
`repo:${repo}` + (labels.length ? ` label:${labelQuery}` : ''),
};

const response = await graphqlQuery(query, variables);
const edges = response.data.search.edges;
for (const edge of edges) {
if (edge.node) {
const item = edge.node;
const key = comparableKey(
`${item.repository.nameWithOwner}#${item.number}`
);
item.key = key;
item.title = item.title.trim().replace(/^Tracking: /, '');
yield edge.node;
}
}
if (!response.data.search.pageInfo.hasNextPage) {
break;
}
cursor = response.data.search.pageInfo.endCursor;
} while (true);
}

const nodesCacheKey = 'nodes_cache';

const fetchData = async () => {
let allNodes = {};
const allNodesArray = [];
for (const repo of repos) {
for await (const item of iterateIssuesPRs(repo)) {
allNodes[item.key] = item;
}
for await (const item of iterateIssuesPRs(repo, [
'[Type] Mindmap Node',
'[Type] Mindmap Tree',
])) {
allNodes[item.key] = item;
}
}
return allNodes;
};

const getConnectedNodes = (issue) => {
const currentRepo = issue.repository.nameWithOwner;
let connections = [];

const regex1 =
/\bhttps:\/\/github.com\/([^\/]+)\/([^\/]+)\/(?:issues|pull)\/(\d+)\b/g;
const regex2 = /\b#(\d+)\b/g;
let match;

while ((match = regex1.exec(issue.body)) !== null) {
connections.push(`${match[1]}/${match[2]}#${match[3]}`);
}

while ((match = regex2.exec(issue.body)) !== null) {
connections.push(`${currentRepo}#${match[1]}`);
}

return connections.map(comparableKey);
};

const buildEdges = ({ allNodes, rootKey, isEdge }) => {
const seen = {};
const allEdges = {};

const preorderTraversal = (currentNode) => {
const relatedIssueKeys = getConnectedNodes(currentNode).filter(
(edgeKey) => isEdge(currentNode.key, edgeKey)
);

for (const relatedKey of relatedIssueKeys) {
if (!allNodes[relatedKey]) continue;
if (seen[relatedKey]) continue;
seen[relatedKey] = true;

if (!allEdges[currentNode.key]) {
allEdges[currentNode.key] = [];
}

allEdges[currentNode.key].push(relatedKey);
preorderTraversal(allNodes[relatedKey]);
}
};

preorderTraversal(allNodes[rootKey]);
return allEdges;
};

const buildTree = (allNodes, allEdges, rootKey) => {
const node = { ...allNodes[rootKey] };
const childrenKeys = allEdges[rootKey] || [];
node.children = childrenKeys.map((childKey) =>
buildTree(allNodes, allEdges, childKey)
);
return node;
};

export const fetchMindmapData = async ({ githubToken } = {}) => {
if (githubToken) {
__moduleGithubToken = githubToken;
}

const allNodes = await fetchData();
const isEdge = (fromKey, toKey) => {
if (mindmapTrees[fromKey]) {
return true;
}
if (mindmapNodes[fromKey] && mindmapNodes[toKey]) {
return true;
}
return false;
};

const mindmapTrees = {};
const mindmapNodes = {};
for (const key in allNodes) {
if (
allNodes[key].labels.nodes.some(
(label) => label.name === '[Type] Mindmap Tree'
)
) {
mindmapTrees[key] = allNodes[key];
mindmapNodes[key] = allNodes[key];
} else if (
allNodes[key].labels.nodes.some(
(label) => label.name === '[Type] Mindmap Node'
)
) {
mindmapNodes[key] = allNodes[key];
}
}

const rootKey = 'wordpress/wordpress-playground#525';
const allEdges = buildEdges({
allNodes,
rootKey,
isEdge,
});
const tree = buildTree(allNodes, allEdges, rootKey);
console.log({
allNodes,
tree,
});

return tree;
};
13 changes: 13 additions & 0 deletions packages/meta/src/mindmap/v1/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Mind Map</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div id="mindmap"></div>
<script src="https://d3js.org/d3.v6.min.js"></script>
<script src="script.js"></script>
</body>
</html>
Loading

0 comments on commit f3fe08d

Please sign in to comment.