diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index f4abc88..cb9cf95 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -116,6 +116,12 @@ jobs:
- uses: actions/checkout@v4
with:
fetch-depth: 0
+
+ - name: Fetch and checkout the latest commit
+ run: |
+ git fetch origin main
+ git checkout origin/main
+
- uses: pnpm/action-setup@v2
with:
version: 9
diff --git a/README.md b/README.md
index 696a99f..87785fa 100644
--- a/README.md
+++ b/README.md
@@ -94,43 +94,43 @@ Once your theme has been created, it will not be changed again by the Inertia Wo
If you ran the theme bootstrapper command above, you should have something like the above.
-### app.php
+> ### app.php
See [InertiaJS.com > Server-Side Setup > Root Template](https://inertiajs.com/server-side-setup#root-template)
-### controllers
+> ### controllers
These files will be the bridge between Wordpress and Inertia for serving GET requests. Each file should contain a single class that extends the `EvoMark\InertiaWordpress\InertiaController` class and provides a `handle` method. The handle method must return a call to `$this->render()`.
The files in this directory are loaded in accordance with [Wordpress' template hierarchy rules](https://developer.wordpress.org/themes/basics/template-hierarchy/), albeit moved from the root of your theme to this `controllers` directory.
-### ecosystem.config.cjs
+> ### ecosystem.config.cjs
This is an optional file provided to make running your InertiaJS SSR process easier. It is read by the PM2 process manager and keeps your process running reliably.
For more information see the page on [PM2 Ecosystem Files](https://pm2.keymetrics.io/docs/usage/application-declaration/)
-### functions.php
+> ### functions.php
-The standard entry point for your theme. The bootstrapper will populate this with a call to REST API.
+The standard entry point for your theme. The bootstrapper will populate this with a small amount of code.
-The REST API is a call to [WP Rest Registration](https://evomark.co.uk/open-source-software/wp-rest-registration/) which allows you to easily register REST endpoints that can validated input.
+The code `new RestApi` is a call to [WP Rest Registration](https://evomark.co.uk/open-source-software/wp-rest-registration/) which allows you to easily register REST API endpoints that can validate input.
-We'll be using these to process information submitted by our InertiaJS frontend. See `rest-api` below for more details.
+We'll be using these endpoints to process information submitted by our InertiaJS frontend. See `rest-api` below for more details.
-### index.php
+> ### index.php
Intentionally left empty to prevent directory indexing
-### package.json
+> ### package.json
A file used by NodeJS package managers to install dependencies required by your theme. Common package managers are `NPM`, `PNPM`, and `Yarn`.
-### resources
+> ### resources
This is where the majority of your themes frontend will live. It's no different from a standard InertiaJS project setup, so we won't go into much detail on the file structure.
-### rest-api
+> ### rest-api
Since InertiaJS sends its data via AJAX requests, we can't use our `controllers` classes to process it. Instead, we must use special REST API controllers.
@@ -138,11 +138,11 @@ All classes in this directory are automatically registered by the call the `new
See the [WP REST Registration documentation](https://evomark.co.uk/open-source-software/wp-rest-registration/) for more details.
-### style.css
+> ### style.css
Required by Wordpress.
-### vite.config.js
+> ### vite.config.js
Used by Vite to bundle/build your theme's JavaScript and CSS files. You shouldn't need to change anything here to get Vite working, but feel free to add more plugins.
@@ -202,7 +202,7 @@ createInertiaApp({
The `resolveInertiaPage` accepts two arguments, the first is your pages glob. With `eager: true` the pages will all be bundled into a single file, whereas with `eager: false` Vite will use code-splitting when bundling your app.
-The second argument the `resolveInertiaPage` accepts is your [Default Layout](https://inertiajs.com/pages#default-layouts). This can either be a standard layout/layout-array:
+The second argument the `resolveInertiaPage` accepts is your [Default Layout](https://inertiajs.com/pages#default-layouts).
```js
import Layout from './Layout'
@@ -213,7 +213,7 @@ resolve: resolveInertiaPage(
),
```
-or you can pass a function that should return a layout or layout-array:
+A third argument can be an optional callback that receives the page name and page object and should return a valid Layout.
```js
import Layout1 from './Layout';
@@ -222,6 +222,7 @@ import Layout2 from './Layout2';
// ...
resolve: resolveInertiaPage(
import.meta.glob("./pages/**/*.vue", { eager: false }),
+ null, // Notice that the 2nd argument is null
/**
* @param { string } name The page name that is being loaded
* @param { VNode } resolvedPage The resolved page vNode
@@ -237,10 +238,14 @@ resolve: resolveInertiaPage(
If you check your Inertia page props, you'll see a few provided objects pre-loaded:
-- **$page.props.wp.adminBar**: _Coming Soon_
+- **$page.props.wp.name**: The name of your site
+- **$page.props.wp.homeUrl**: The URL of your site's homepage
- **$page.props.wp.restUrl**: The base URL for making REST API requests
- **$page.props.wp.user**: The user object for the currently logged in user
- **$page.props.wp.userCapabilities**: An object of the current users capabilities/permission
+- **$page.props.wp.logo**: An image resource containing your site logo as set in Wordpress' Appearance->Customise menu
+- **$page.props.wp.menus**: A nested object containing your registered menus, keyed by location
+- **$page.props.wp.adminBar**: _Coming Soon_
## Wordpress Settings
diff --git a/changelog/next.md b/changelog/next.md
index e69de29..b91a352 100644
--- a/changelog/next.md
+++ b/changelog/next.md
@@ -0,0 +1,7 @@
+- **Feature**: Svelte template now available via `wp inertia:create-theme` command
+- **Feature**: React template now available via `wp inertia:create-theme` command
+- **Feature**: Edit and Comment nodes returned via `wp.adminBar` on Inertia requests
+
+- **Improvement**: Included more detailed templates/layouts for theme bootstrapper
+
+- **BugFix**: Duplicated inertia instances when using code-splitting on pages
diff --git a/composer.json b/composer.json
index ec794e4..4a105f7 100644
--- a/composer.json
+++ b/composer.json
@@ -25,7 +25,7 @@
"require": {
"php": ">=8.2",
"evo-mark/evo-wp-rest-registration": "^4.1",
- "evo-mark/wp-vite": "^1.1",
+ "evo-mark/wp-vite": "^1.2",
"guzzlehttp/guzzle": "^7.9",
"illuminate/collections": "^11.35",
"nesbot/carbon": "^3.8",
@@ -58,4 +58,4 @@
},
"minimum-stability": "dev",
"prefer-stable": true
-}
+}
\ No newline at end of file
diff --git a/composer.lock b/composer.lock
index 074502d..ac57fac 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "395eb20e0a536260c917661856afe4db",
+ "content-hash": "e8564996de0d9f760fa9f6d0dea02d5d",
"packages": [
{
"name": "carbonphp/carbon-doctrine-types",
@@ -126,16 +126,16 @@
},
{
"name": "evo-mark/wp-vite",
- "version": "v1.1.1",
+ "version": "v1.2.1",
"source": {
"type": "git",
"url": "https://github.com/evo-mark/wp-vite.git",
- "reference": "852fa07ae207366fb3d5d643230a48cf3292312b"
+ "reference": "25e5ed52b433ec7f7da0a6ad9d7172bf1abfc818"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/evo-mark/wp-vite/zipball/852fa07ae207366fb3d5d643230a48cf3292312b",
- "reference": "852fa07ae207366fb3d5d643230a48cf3292312b",
+ "url": "https://api.github.com/repos/evo-mark/wp-vite/zipball/25e5ed52b433ec7f7da0a6ad9d7172bf1abfc818",
+ "reference": "25e5ed52b433ec7f7da0a6ad9d7172bf1abfc818",
"shasum": ""
},
"require": {
@@ -161,9 +161,9 @@
],
"support": {
"issues": "https://github.com/evo-mark/wp-vite/issues",
- "source": "https://github.com/evo-mark/wp-vite/tree/v1.1.1"
+ "source": "https://github.com/evo-mark/wp-vite/tree/v1.2.1"
},
- "time": "2024-11-17T13:30:37+00:00"
+ "time": "2024-12-21T12:17:50+00:00"
},
{
"name": "guzzlehttp/guzzle",
@@ -492,16 +492,16 @@
},
{
"name": "illuminate/collections",
- "version": "v11.35.1",
+ "version": "v11.36.1",
"source": {
"type": "git",
"url": "https://github.com/illuminate/collections.git",
- "reference": "b8be9c0fedfc5be1524b290fed640d4b7d42c813"
+ "reference": "21868f9ac221a42d4346dc56495d11ab7e0d339a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/illuminate/collections/zipball/b8be9c0fedfc5be1524b290fed640d4b7d42c813",
- "reference": "b8be9c0fedfc5be1524b290fed640d4b7d42c813",
+ "url": "https://api.github.com/repos/illuminate/collections/zipball/21868f9ac221a42d4346dc56495d11ab7e0d339a",
+ "reference": "21868f9ac221a42d4346dc56495d11ab7e0d339a",
"shasum": ""
},
"require": {
@@ -544,11 +544,11 @@
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
- "time": "2024-12-10T14:54:28+00:00"
+ "time": "2024-12-13T13:58:10+00:00"
},
{
"name": "illuminate/conditionable",
- "version": "v11.35.1",
+ "version": "v11.36.1",
"source": {
"type": "git",
"url": "https://github.com/illuminate/conditionable.git",
@@ -594,7 +594,7 @@
},
{
"name": "illuminate/contracts",
- "version": "v11.35.1",
+ "version": "v11.36.1",
"source": {
"type": "git",
"url": "https://github.com/illuminate/contracts.git",
@@ -642,7 +642,7 @@
},
{
"name": "illuminate/macroable",
- "version": "v11.35.1",
+ "version": "v11.36.1",
"source": {
"type": "git",
"url": "https://github.com/illuminate/macroable.git",
@@ -790,10 +790,6 @@
],
"type": "library",
"extra": {
- "branch-alias": {
- "dev-master": "3.x-dev",
- "dev-2.x": "2.x-dev"
- },
"laravel": {
"providers": [
"Carbon\\Laravel\\ServiceProvider"
@@ -803,6 +799,10 @@
"includes": [
"extension.neon"
]
+ },
+ "branch-alias": {
+ "dev-2.x": "2.x-dev",
+ "dev-master": "3.x-dev"
}
},
"autoload": {
@@ -2512,13 +2512,13 @@
},
"type": "library",
"extra": {
- "branch-alias": {
- "dev-main": "3.x-dev"
- },
"phpstan": {
"includes": [
"extension.neon"
]
+ },
+ "branch-alias": {
+ "dev-main": "3.x-dev"
}
},
"autoload": {
diff --git a/resources/plugins/index.js b/resources/plugins/index.js
index ada1477..8f2bbec 100644
--- a/resources/plugins/index.js
+++ b/resources/plugins/index.js
@@ -1,21 +1,25 @@
-export const resolveInertiaPage = (glob, layout = null) => {
- return async function (name) {
- let resolvedPage = glob[`./pages/${name}.vue`];
- if (!resolvedPage) {
- console.error(`[Inertia] Couldn't find page matching "${name}"`);
- return null;
- }
+export const resolveInertiaPage = (
+ glob,
+ layout = null,
+ layoutCallback = null
+) => {
+ return async function (name) {
+ let resolvedPage = glob[`./pages/${name}.vue`];
+ if (!resolvedPage) {
+ console.error(`[Inertia] Couldn't find page matching "${name}"`);
+ return null;
+ }
- if (typeof resolvedPage === "function") {
- resolvedPage = await resolvedPage();
- }
+ if (typeof resolvedPage === "function") {
+ resolvedPage = await resolvedPage();
+ }
- if (typeof layout === "function") {
- resolvedPage.default.layout = layout(name, resolvedPage);
- } else if (layout) {
- resolvedPage.default.layout = layout;
- }
+ if (layoutCallback) {
+ resolvedPage.default.layout = layoutCallback(name, resolvedPage);
+ } else if (layout) {
+ resolvedPage.default.layout = resolvedPage.default.layout || layout;
+ }
- return resolvedPage;
- };
+ return resolvedPage;
+ };
};
diff --git a/resources/plugins/package.json b/resources/plugins/package.json
index 4533c68..042ed7f 100644
--- a/resources/plugins/package.json
+++ b/resources/plugins/package.json
@@ -8,6 +8,14 @@
".": {
"import": "./index.js",
"require": "./index.js"
+ },
+ "./react": {
+ "import": "./react.jsx",
+ "require": "./react.jsx"
+ },
+ "./svelte": {
+ "import": "./svelte.js",
+ "require": "./svelte.js"
}
},
"scripts": {
diff --git a/resources/plugins/react.jsx b/resources/plugins/react.jsx
new file mode 100644
index 0000000..f715195
--- /dev/null
+++ b/resources/plugins/react.jsx
@@ -0,0 +1,26 @@
+export const resolveInertiaPage = (
+ glob,
+ Layout = null,
+ layoutCallback = null
+) => {
+ return async function (name) {
+ let resolvedPage = glob[`./pages/${name}.jsx`];
+ if (!resolvedPage) {
+ console.error(`[Inertia] Couldn't find page matching "${name}"`);
+ return null;
+ }
+
+ if (typeof resolvedPage === "function") {
+ resolvedPage = await resolvedPage();
+ }
+
+ if (layoutCallback) {
+ resolvedPage.default.layout = layoutCallback(name, resolvedPage);
+ } else if (Layout) {
+ resolvedPage.default.layout =
+ resolvedPage.default.layout || ((page) => {name}
+
+ > + ); +}; + +export default Archive; diff --git a/stubs/theme/resources/js/pages/Error.react.stub b/stubs/theme/resources/js/pages/Error.react.stub new file mode 100644 index 0000000..3e38b7f --- /dev/null +++ b/stubs/theme/resources/js/pages/Error.react.stub @@ -0,0 +1,15 @@ +import { usePage, Link } from "@inertiajs/react"; + +const Error = () => { + const { error, wp } = usePage().props; + return ( + <> +
+ >
+ );
+};
+
+export default Error;
diff --git a/stubs/theme/resources/js/pages/Error.svelte.stub b/stubs/theme/resources/js/pages/Error.svelte.stub
new file mode 100644
index 0000000..fce5c71
--- /dev/null
+++ b/stubs/theme/resources/js/pages/Error.svelte.stub
@@ -0,0 +1,11 @@
+
+
+Error: {error}
+
+
+ >
+ );
+};
+
+export default Home;
diff --git a/stubs/theme/resources/js/pages/Home.svelte.stub b/stubs/theme/resources/js/pages/Home.svelte.stub
new file mode 100644
index 0000000..f17d479
--- /dev/null
+++ b/stubs/theme/resources/js/pages/Home.svelte.stub
@@ -0,0 +1,11 @@
+
+ + diff --git a/stubs/theme/resources/js/pages/Post.react.stub b/stubs/theme/resources/js/pages/Post.react.stub new file mode 100644 index 0000000..80f73e0 --- /dev/null +++ b/stubs/theme/resources/js/pages/Post.react.stub @@ -0,0 +1,34 @@ +import { Head, usePage } from "@inertiajs/react"; +import { useMemo } from "react"; + +const Post = () => { + const { post } = usePage().props; + const publishedDate = useMemo(() => { + const d = new Date(post.createdAt); + return d.toLocaleString(undefined, { + dateStyle: "long", + timeStyle: "medium", + }); + }, [post]); + + return ( + <> +
+
+ >
+ );
+};
+
+export default Post;
diff --git a/stubs/theme/resources/js/pages/Post.vue.stub b/stubs/theme/resources/js/pages/Post.vue.stub
index a340592..a888fbd 100644
--- a/stubs/theme/resources/js/pages/Post.vue.stub
+++ b/stubs/theme/resources/js/pages/Post.vue.stub
@@ -1,5 +1,36 @@
- {{ post.title }}
+
+
+
+