Make WordPress Core

Opened 20 hours ago

Last modified 19 hours ago

#65907 new enhancement

Restore the revisions easter egg

Reported by: adamsilverstein Owned by:
Priority: normal Milestone: Awaiting Review
Component: Editor Version:
Severity: normal Keywords: has-patch
Cc: Focuses:

Description

This PR restores the admin easter egg WordPress used to trigger by comparing a revision to itself. It shipped for about a decade until it came out in [24820] (see #24852) when the revisions UI was rewritten and the "compare a revision to itself" state stopped existing and it became impossible to trigger.

This PR restores the easter egg behind the command palette, so it can be triggered by typing a phrase into the palette. The phrase is a well known WordPress phrase which I won't divuldge here in order to not ruin the surprise for anyone who wants to find it themselves.

The phrase is compared through the a Dvorak/QWERTY substitution cipher so it is possible to deduce it from the source code with a little bit of work.

Notes on the code

The JavaScript here is a rewrite of the original which no longer depends on jQuery.

A few other things needed updating after twelve years:

  • <blink> and text-decoration: blink are replaced with a CSS @keyframes blink, plus a prefers-reduced-motion guard.
  • The original took over the document, rewriting html/body CSS and stripping nodes out of the page's first <p>. The scene now renders into its own overlay and touches nothing on the admin page.
  • The overlay is marked aria-hidden. Without it, text typed one character at a time lands in the accessibility tree one node at a time.

Note: only a small loader is added to admin pages. The scene itself is fetched at the moment it is invoked, so a normal admin load carries nothing else.

Change History (3)

This ticket was mentioned in PR #13152 on WordPress/wordpress-develop by @adamsilverstein.


20 hours ago
#1

  • Keywords has-patch added

## Description

Restores the admin easter egg WordPress used to trigger by comparing a revision to itself. It shipped for about a decade and came out in [24820] (see #24852) when the revisions UI was rewritten and the "compare a revision to itself" state stopped existing. It was not removed because anyone objected to it, only because its doorway disappeared.

The command palette is the new doorway. No command is registered: a registered command shows up in the results the moment its phrase matches, which hands the egg to anyone who happens to type near it. Instead a keydown handler watches for Enter while the palette is open and acts on the phrase itself. The palette shows its ordinary "No results found." state throughout, so typing the phrase looks exactly like a search that missed.

The phrase is compared through the same Dvorak/QWERTY substitution cipher the original used, so it is not a readable string in the admin bundle. It can be worked out from the source with a little effort, which seems like about the right amount.

## Notes on the payload

The 2013 original shipped as a Dean Edwards packed blob, which is what #15262 was about. Rather than reship that, it is unpacked here into readable source and no longer depends on jQuery - the original only used $.each, $.inArray, .hide(), .show(), .animate(), and some manual child removal. Shipped output is minified by the normal build, so nothing changes visually.

Timings, dialogue, and staging are faithful to the original. A few things needed updating after twelve years:

  • <blink> and text-decoration: blink are both gone from browsers. Replaced with a CSS @keyframes blink, plus a prefers-reduced-motion guard.
  • The original took over the document, rewriting html/body CSS and stripping nodes out of the page's first <p>. The scene now renders into its own overlay and touches nothing on the admin page.
  • The overlay is marked aria-hidden. Without it, text typed one character at a time lands in the accessibility tree one node at a time.
  • Scrolling is locked while the scene plays. Otherwise the page behind it stays scrollable and leaves a scrollbar strip down the side.

Only a small loader is added to admin pages. The scene itself is fetched at the moment it is invoked, so a normal admin load carries nothing else.

## How has this been tested

  1. Open any admin screen and press Cmd/Ctrl+K.
  2. Type the phrase. The palette will say "No results found." the whole time, which is expected. Press Enter anyway.
  3. The scene runs for about 30 seconds. ESC or a click dismisses it at any point.

Also verified:

  • Ordinary palette commands still run. The handler is capture phase, so this one is worth a reviewer's eye.
  • Enter on a genuinely empty search does nothing.
  • The payload is not requested until the egg is invoked.
  • No console errors on normal admin screens.
  • grunt jshint:core and grunt typecheck:js pass, phpcs is clean.

## Types of changes

  • Add the scene as src/js/_enqueues/admin/easter-egg.js, fetched on demand.
  • Add the loader as src/js/_enqueues/admin/easter-egg-loader.js, enqueued with the command palette.
  • Register and enqueue the loader in wp_enqueue_command_palette_assets().
  • Add both files to the Gruntfile admin-js build map.

## Open questions

  • The loader reads a small config global that is printed on every admin page, so page source reveals that an egg exists, though not the phrase. Worth leaving as is, or better to derive those values at runtime so nothing is printed?
  • Is a capture-phase keydown handler the right approach here, or is there a cleaner hook for "Enter was pressed and nothing matched"?

## AI Use

Both the code and this description came out of a back and forth with 🤖 Claude Code. I will review and test.

@adamsilverstein commented on PR #13152:


20 hours ago
#2

Calling the files easter-egg-* is probably a bit too obvious, maybe we can come up with something a bit less so.

@adamsilverstein commented on PR #13152:


19 hours ago
#3

Agreed. Renamed to teletype.js and teletype-loader.js in b2150a3 - named for what they do rather than for what they are, since the loader's src shows up in the markup of every admin page that loads the palette. The script handle, config global and overlay class follow. Docblocks still say plainly what this is, and minification strips those so they never reach a production page.

Note: See TracTickets for help on using tickets.