GKD Post Include
WordPress Gutenberg block that embeds another post's content, picked via taxonomy → term → post
by AlwaysRichard · github.com/alwaysrichard/gkd-post-include
Install
No release zip yet. The repository archive installs, but the folder name will carry the branch suffix and updates will not flow:
wp plugin install https://github.com/alwaysrichard/gkd-post-include/archive/refs/heads/master.zipA WordPress Gutenberg block that embeds the full content of another post into the current post/page, picked via a taxonomy → term → post flow. It's a dynamic block — the included content is rendered on every page load, so edits to the source post stay in sync automatically.
Features
- Taxonomy → Term → Post picker: pick any public, REST-exposed taxonomy, a term within it, and a post carrying that term — across every post type the taxonomy applies to.
- Live sync: content is pulled from the source post at render time via
the_content, not baked into the block on save. - Recursion guard: refuses to render if the source post is the current post, or if the source post (directly or transitively, up to 5 levels deep) includes the current post — skips with an HTML comment instead of looping.
- Draft-friendly: source posts don't need to be published themselves — the page containing the block is what actually gates visibility. An "Include Drafts" switch controls whether draft posts show up in the picker.
- Optional section heading: show the source post's title above the included content, in your choice of format (H1, H2, H3, Bold, Underline, Italic).
- Optional featured image: show the source post's featured image, positioned above or below the title.
Requirements
- WordPress 6.0+
- PHP 8.0+
- Node.js 18+ (for building — see Build)
Installation
- Clone/copy this plugin into
wp-content/plugins/gkd-post-include - Build it (see below)
- Activate GKD Post Include in WordPress Admin → Plugins
Build
This plugin uses @wordpress/scripts with a custom webpack.config.js (single-block entry, avoids the block.json auto-discovery filename collision documented in gkd_gallery/tools/WEBPACK_FIX.md).
npm install
npm run build # Production build → blocks/PostInclude/build/
npm run start # Development mode with live reloading
If your local machine's Node/npm is too old for @wordpress/scripts (this plugin was originally built against a dev box running Node 7 — a full generation behind), build on a server instead:
tools/push-to-server.sh # rsyncs source to alwaysvw.net
ssh root@alwaysvw.net
cd /home/alwaysvw.net/public_html/wp-content/plugins/gkd-post-include
npm install && npm run build
tools/ is git-ignored — it's deploy tooling for this specific setup, not part of the plugin.
Block Usage
- Add the Post Include block to any post or page.
- Pick a Taxonomy, then a Term, then a Post — the post list is scoped to whatever post type(s) the taxonomy applies to, and excludes the post you're currently editing.
- Once a post is selected, the block shows a preview (title, status, excerpt) and a Change selection button to redo the picker.
- Three switches sit in the top-right of the block, next to the "Post Include" title:
- Display Title — toggles whether the source post's title renders as a heading above the included content, and lets you pick its format (as dropdown: H1 / H2 / H3 / Bold / Underline / Italic).
- Display Featured Image — toggles whether the source post's featured image renders, and lets you pick whether it goes Above or Below the title.
- Include Drafts — widens the post picker to include draft posts (pending/private/future posts are always included; only
draftis gated by this switch).
Block Attributes
| Attribute | Type | Default | Purpose |
|---|---|---|---|
taxonomy |
string | "" |
Taxonomy slug — retained so the editor can restore picker state. |
termId |
integer | 0 |
Selected term ID — same purpose. |
postId |
integer | 0 |
Selected post ID — the only attribute required at render time. |
includeDrafts |
boolean | false |
Whether the editor's post picker lists draft posts. |
includeTitle |
boolean | true |
Whether to render the source post's title as a heading. |
titleFormat |
string | "h2" |
h1 | h2 | h3 | bold | underline | italic. |
displayFeaturedImage |
boolean | false |
Whether to render the source post's featured image. |
featuredImagePosition |
string | "above" |
above | below (relative to the title). |
taxonomy/termId aren't used at render time — they just let the editor UI restore the picker's "Selected post: Taxonomy → Term" context without re-deriving it.
Rendering Behavior
- If
postIdis unset, or the source post can't be found, istrash, or isauto-draft, the block renders nothing but a discreet `` comment — never an error. - Otherwise: fetch the post, run
post_contentthroughapply_filters( 'the_content', ... ), and wrap it:<div class="gkd-post-include" data-gkd-post-include-source="123"> <div class="gkd-post-include__featured-image">...</div> <h2 class="gkd-post-include__title">Source Post Title</h2> ...filtered content... </div>(the featured image only renders if the source post has one; its position swaps with the title's per
featuredImagePosition) - Recursion guard: before rendering, the block checks whether the source post is the current post, and whether including the source post would create a cycle — i.e. whether the source post, directly or transitively (up to 5 levels of nested
gkd/post-includeblocks), includes the current post back. Either case skips rendering with an HTML comment rather than infinite-looping.
Architecture
gkd-post-include.php # Plugin entry point — dynamic block registration via glob()
blocks/PostInclude/
├── block.json # Block metadata (Gutenberg Block API v3)
├── block_init.php # PHP class autoloader
├── index.jsx # Block editor UI (React)
├── style.scss # Frontend styles
├── editor.scss # Editor-only styles
├── Renderer.php # WordPress render_callback interface
├── Engine.php # Thin adapter
└── src/
├── main/Main.php # Normalization, recursion guard, orchestration
└── impl/
├── Queries.php # Walks post content for nested gkd/post-include blocks
└── HtmlBuilder.php # Wrapper div + optional title heading + optional featured image
Rendering Flow
WordPress → Renderer::render()
→ Engine::run()
→ Main::run()
→ normalize attributes
→ self-reference / recursion checks
→ fetch + validate source post
→ apply_filters( 'the_content', ... )
→ HtmlBuilder::build()
Namespace
Everything lives under gkd_pi\ (gkd_pi\WP_Interface for Renderer/Engine, gkd_pi\Impl for Main/Queries/HtmlBuilder) — namespaced separately from gkd_gallery's gkd\ and gkd_tagcloud's gkd_tc\ so all three plugins can coexist on the same site without collisions.
License
GPL-2.0-or-later