Skip to content

Instantly share code, notes, and snippets.

@bgrgicak
Created July 22, 2026 10:20
Show Gist options
  • Select an option

  • Save bgrgicak/0cdb0637bc50476daed943ed1b0b22a5 to your computer and use it in GitHub Desktop.

Select an option

Save bgrgicak/0cdb0637bc50476daed943ed1b0b22a5 to your computer and use it in GitHub Desktop.
WP Doom Block repo-hosted blueprint mirror for Playground testing
{
"$schema": "https://playground.wordpress.net/blueprint-schema.json",
"preferredVersions": {
"php": "8.3",
"wp": "latest"
},
"features": {
"networking": true
},
"landingPage": "/doom-block/",
"meta": {
"title": "Try WP Doom Block in Playground",
"author": "Bero / Gil",
"description": "Installs WP Doom Block and loads a page with the block already inserted."
},
"steps": [
{
"step": "installPlugin",
"pluginData": {
"resource": "literal:directory",
"name": "wp-doom-block",
"files": {
"wp-doom-block.php": "<?php\n/**\n * Plugin Name: WP Doom Block\n * Description: Adds a Gutenberg block that embeds playable Doom in a post or page.\n * Version: 0.1.0\n * Requires at least: 6.5\n * Requires PHP: 8.0\n * Author: Gil / Hermes\n * License: GPL-2.0-or-later\n * License URI: https://www.gnu.org/licenses/gpl-2.0.html\n * Text Domain: wp-doom-block\n *\n * @package WPDoomBlock\n */\n\ndeclare(strict_types=1);\n\nif (! defined('ABSPATH')) {\n exit;\n}\n\nrequire_once __DIR__ . '/includes/render.php';\n\nfunction wp_doom_block_register(): void {\n $dir = __DIR__ . '/build';\n\n register_block_type(\n $dir,\n [\n 'render_callback' => 'wp_doom_block_render',\n ]\n );\n}\nadd_action('init', 'wp_doom_block_register');\n",
"README.md": "# WP Doom Block\n\nA WordPress plugin that adds a Gutenberg block for embedding playable DOOM in a post or page.\n\n## Inspiration\n\nThis block was inspired by Rhys Wynne\u2019s work on bringing DOOM into WordPress and WordPress Playground.\n\n- Author: Rhys Wynne\n- Blog post: [Can WordPress run Doom? (of course it can, here's how)](https://dwinrhys.com/2024/05/08/can-wordpress-run-doom-of-course-it-can-heres-how/)\n- Related original plugin/repo: [rhyswynne/wpdoom](https://github.com/rhyswynne/wpdoom)\n\nThis plugin is a separate Gutenberg block implementation and does not reuse the original shortcode-based plugin architecture.\n\n## What this plugin does\n\n- Registers a Gutenberg block named `create-block/wp-doom-block`\n- Renders a start button that lazy-loads a DOOM iframe on the front end\n- Lets the editor configure the game URL, frame height, and button text\n\n## Local structure\n\n- `wp-doom-block.php` \u2014 plugin bootstrap and block registration\n- `includes/render.php` \u2014 server-side render helpers\n- `build/` \u2014 block metadata and compiled assets\n- `tests/run.php` \u2014 lightweight verification script\n\n## Verification\n\nRun:\n\n```bash\nphp tests/run.php\n```\n\nExpected output:\n\n```text\nAll tests passed\n```\n",
"includes": {
"render.php": "<?php\n\ndeclare(strict_types=1);\n\nfunction wp_doom_block_escape_url(string $value): string {\n return function_exists('esc_url') ? esc_url($value) : htmlspecialchars($value, ENT_QUOTES, 'UTF-8');\n}\n\nfunction wp_doom_block_escape_attr(string $value): string {\n return function_exists('esc_attr') ? esc_attr($value) : htmlspecialchars($value, ENT_QUOTES, 'UTF-8');\n}\n\nfunction wp_doom_block_escape_html(string $value): string {\n return function_exists('esc_html') ? esc_html($value) : htmlspecialchars($value, ENT_QUOTES, 'UTF-8');\n}\n\nfunction wp_doom_block_render_markup(array $attributes, string $wrapperAttributes = ''): string {\n $defaults = [\n 'gameUrl' => 'https://js-dos.com/games/doom.exe.html',\n 'height' => 600,\n 'startButtonText' => 'Click to play DOOM',\n ];\n\n $attributes = array_merge($defaults, $attributes);\n\n $height = is_numeric($attributes['height']) ? max(240, (int) $attributes['height']) : 600;\n $gameUrl = wp_doom_block_escape_url((string) $attributes['gameUrl']);\n $buttonText = wp_doom_block_escape_html((string) $attributes['startButtonText']);\n\n $wrapperAttributes = trim($wrapperAttributes);\n if ($wrapperAttributes === '') {\n $wrapperAttributes = 'class=\"wp-block-create-block-wp-doom-block wp-doom-block\"';\n }\n\n return sprintf(\n '<div %1$s data-game-url=\"%2$s\">'\n . '<div class=\"wp-doom-block__shell\" style=\"min-height:%3$dpx\">'\n . '<button type=\"button\" class=\"wp-doom-block__start-button\" data-doom-start>%4$s</button>'\n . '<iframe class=\"wp-doom-block__iframe\" title=\"DOOM\" loading=\"lazy\" allowfullscreen data-doom-frame data-src=\"%2$s\" style=\"height:%3$dpx\" hidden></iframe>'\n . '</div>'\n . '</div>',\n $wrapperAttributes,\n $gameUrl,\n $height,\n $buttonText\n );\n}\n\nfunction wp_doom_block_render(array $attributes, string $content = '', $block = null): string {\n $wrapperAttributes = function_exists('get_block_wrapper_attributes')\n ? get_block_wrapper_attributes([\n 'class' => 'wp-doom-block',\n ])\n : 'class=\"wp-block-create-block-wp-doom-block wp-doom-block\"';\n\n return wp_doom_block_render_markup($attributes, $wrapperAttributes);\n}\n"
},
"build": {
"block.json": "{\n \"$schema\": \"https://schemas.wp.org/trunk/block.json\",\n \"apiVersion\": 3,\n \"name\": \"create-block/wp-doom-block\",\n \"version\": \"0.1.0\",\n \"title\": \"DOOM\",\n \"category\": \"widgets\",\n \"icon\": \"games\",\n \"description\": \"Embed playable DOOM in a post or page.\",\n \"keywords\": [\"doom\", \"game\", \"retro\", \"embed\"],\n \"textdomain\": \"wp-doom-block\",\n \"attributes\": {\n \"gameUrl\": {\n \"type\": \"string\",\n \"default\": \"https://js-dos.com/games/doom.exe.html\"\n },\n \"height\": {\n \"type\": \"number\",\n \"default\": 600\n },\n \"startButtonText\": {\n \"type\": \"string\",\n \"default\": \"Click to play DOOM\"\n }\n },\n \"editorScript\": \"file:./index.js\",\n \"viewScript\": \"file:./view.js\",\n \"style\": \"file:./style.css\"\n}\n",
"index.asset.php": "<?php\nreturn [\n 'dependencies' => [\n 'wp-blocks',\n 'wp-block-editor',\n 'wp-components',\n 'wp-element',\n 'wp-i18n',\n ],\n 'version' => '0.1.0',\n];\n",
"index.js": "( function ( blocks, blockEditor, components, element, i18n ) {\n var el = element.createElement;\n var useBlockProps = blockEditor.useBlockProps;\n var InspectorControls = blockEditor.InspectorControls;\n var PanelBody = components.PanelBody;\n var RangeControl = components.RangeControl;\n var TextControl = components.TextControl;\n var __ = i18n.__;\n\n blocks.registerBlockType( 'create-block/wp-doom-block', {\n edit: function ( props ) {\n var attributes = props.attributes;\n var setAttributes = props.setAttributes;\n var blockProps = useBlockProps( {\n className: 'wp-doom-block-editor',\n } );\n\n return [\n el(\n InspectorControls,\n { key: 'inspector' },\n el(\n PanelBody,\n { title: __( 'DOOM settings', 'wp-doom-block' ), initialOpen: true },\n el( TextControl, {\n label: __( 'Game URL', 'wp-doom-block' ),\n value: attributes.gameUrl || 'https://js-dos.com/games/doom.exe.html',\n onChange: function ( value ) {\n setAttributes( { gameUrl: value } );\n },\n help: __( 'Swap in another js-dos compatible page if you want a different build.', 'wp-doom-block' ),\n } ),\n el( RangeControl, {\n label: __( 'Frame height', 'wp-doom-block' ),\n value: attributes.height || 600,\n onChange: function ( value ) {\n setAttributes( { height: value } );\n },\n min: 240,\n max: 1000,\n } ),\n el( TextControl, {\n label: __( 'Start button text', 'wp-doom-block' ),\n value: attributes.startButtonText || 'Click to play DOOM',\n onChange: function ( value ) {\n setAttributes( { startButtonText: value } );\n },\n } )\n )\n ),\n el(\n 'div',\n Object.assign( { key: 'preview' }, blockProps ),\n el( 'div', { className: 'wp-doom-block__shell', style: { minHeight: ( attributes.height || 600 ) + 'px' } },\n el( 'p', { className: 'wp-doom-block__eyebrow' }, __( 'Playable DOOM block', 'wp-doom-block' ) ),\n el( 'h3', null, 'DOOM' ),\n el( 'p', null, __( 'The front end renders a start button that lazy-loads the game iframe.', 'wp-doom-block' ) ),\n el( 'p', null, __( 'Source:', 'wp-doom-block' ) + ' ' + ( attributes.gameUrl || 'https://js-dos.com/games/doom.exe.html' ) ),\n el( 'button', { type: 'button', className: 'wp-doom-block__start-button', disabled: true }, attributes.startButtonText || 'Click to play DOOM' )\n )\n )\n ];\n },\n save: function () {\n return null;\n },\n } );\n} )( window.wp.blocks, window.wp.blockEditor, window.wp.components, window.wp.element, window.wp.i18n );\n",
"style.css": ".wp-block-create-block-wp-doom-block,\n.wp-doom-block-editor {\n width: 100%;\n}\n\n.wp-doom-block__shell {\n display: flex;\n min-height: 600px;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 1rem;\n padding: 1.5rem;\n border-radius: 16px;\n background: radial-gradient(circle at top, #2f2f2f 0%, #111 58%, #000 100%);\n color: #f7f0d0;\n box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.08);\n}\n\n.wp-doom-block__eyebrow {\n margin: 0;\n font-size: 0.8rem;\n letter-spacing: 0.08em;\n text-transform: uppercase;\n color: #ffcc66;\n}\n\n.wp-doom-block__start-button {\n border: 0;\n border-radius: 999px;\n padding: 0.9rem 1.35rem;\n font-weight: 700;\n cursor: pointer;\n background: linear-gradient(180deg, #ff7b2f 0%, #c93c00 100%);\n color: #fff;\n}\n\n.wp-doom-block__start-button[disabled] {\n cursor: default;\n opacity: 1;\n}\n\n.wp-doom-block__iframe {\n width: 100%;\n min-height: 600px;\n border: 0;\n border-radius: 12px;\n background: #000;\n}\n",
"view.asset.php": "<?php\nreturn [\n 'dependencies' => [],\n 'version' => '0.1.0',\n];\n",
"view.js": "document.addEventListener('click', function (event) {\n var button = event.target.closest('[data-doom-start]');\n if (!button) {\n return;\n }\n\n var shell = button.closest('.wp-doom-block__shell');\n if (!shell) {\n return;\n }\n\n var iframe = shell.querySelector('[data-doom-frame]');\n if (!iframe) {\n return;\n }\n\n if (!iframe.getAttribute('src')) {\n iframe.setAttribute('src', iframe.dataset.src || 'https://js-dos.com/games/doom.exe.html');\n }\n\n iframe.hidden = false;\n button.hidden = true;\n} );\n"
}
}
},
"options": {
"activate": true
},
"ifAlreadyInstalled": "overwrite"
},
{
"step": "runPHP",
"code": "<?php\nrequire '/wordpress/wp-load.php';\nupdate_option( 'blogname', 'WP Doom Block Demo' );\nupdate_option( 'blogdescription', 'Playable DOOM inside a Gutenberg block' );\nupdate_option( 'permalink_structure', '/%postname%/' );\n$page_id = wp_insert_post( [\n 'post_title' => 'DOOM Block Demo',\n 'post_name' => 'doom-block',\n 'post_status' => 'publish',\n 'post_type' => 'page',\n 'post_content' => '<!-- wp:create-block/wp-doom-block {\\\"height\\\":600,\\\"startButtonText\\\":\\\"Click to play DOOM\\\"} /-->'\n] );\nif ( is_wp_error( $page_id ) ) {\n throw new Exception( $page_id->get_error_message() );\n}\nupdate_option( 'show_on_front', 'page' );\nupdate_option( 'page_on_front', (int) $page_id );\nflush_rewrite_rules();"
}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment