Minn\Theme
The block-theme reader, templates, global styles and the page renderer. 41 classes, 165 public methods and 90 internals. This page is the public surface; each class name opens the whole class.
ArchiveTitle final class
public/minn/src/Minn/Theme/ArchiveTitle.php · 55 lines · Open the class →
The label and name an archive titles itself with: `Category:` around the term, `Author:` around the display name, the date formatted for its granularity. One source of truth for the block path's query-title and the classic path's get_the_archive_title(), which used to compute the same labels separately. Search and post-type archives stay with their callers: their captured shapes differ between the two paths.
| static | parts(Minn\Front\Resolution $resolution, ?string $dateFormat): array | The archive title's prefix and title for a resolution. @return array{string, string} the prefix (its colon included, in the site's language) and the escaped bare name; both empty when the view has none |
| static | compose(string $prefix, string $name): string | The reference's prefixed shape, `Category: <span>Uncategorized</span>`, through the language's own order. |
| inside | dateParts(), taxonomyLabel() |
BodyClasses final class
public/minn/src/Minn/Theme/BodyClasses.php · 86 lines · Open the class →
The body-class list a classic theme's body_class() starts from, in the reference's order: the query tokens (with the singular and template tokens spliced in front of the type token), logged-in, the embed and theme tokens, with the numbered paging tokens re-seated after the embed token. The body_class filter runs over this list in the facade.
| static | classic(Minn\Front\Resolution $resolution, array $coreClasses, ?string $customTemplate, string $themeSlug, ?string $parentSlug, Minn\Theme\BodyFacts $facts): array | The body classes a classic theme's page carries. @param list<string> $coreClasses@return list<string> |
| static | forView(?string $singular, array $coreClasses, ?string $customTemplate, string $themeSlug, ?string $parentSlug, Minn\Theme\BodyFacts $facts): array | The same list for a view named by the post type it shows alone (null when it shows no single post), as get_body_class needs off the front (probe post-template-remaining). @param list<string> $coreClasses@return list<string> |
| inside | withSingularTokens() |
BodyFacts final readonly class
public/minn/src/Minn/Theme/BodyFacts.php · 10 lines · Open the class →
The facts about a page that decide the body classes a classic theme's page carries beyond the view tokens: a signed-in reader, a custom logo, responsive embeds, and the Minn bar.
| new | __construct(bool $loggedIn = false, bool $customLogo = false, bool $embedResponsive = true, bool $bar = false) | |
| prop | readonly bool $loggedIn | |
| prop | readonly bool $customLogo | |
| prop | readonly bool $embedResponsive | |
| prop | readonly bool $bar |
ClassicContent final class
public/minn/src/Minn/Theme/ClassicContent.php · 39 lines · Open the class →
What a classic theme's the_content() prints: the engine's block pipeline (render, password gate, the more-tag teaser in listings), the cached embeds, then the runtime's shortcodes and the_content filters so plugin code sees the same hook order the reference runs.
| static | render(Minn\Content\PostRecord $post, ?string $moreLinkText): string | A post's content as the classic loop prints it, with the more link. |
ClassicRenderer final readonly class
public/minn/src/Minn/Theme/ClassicRenderer.php · 125 lines · Open the class →
A whole page from the active classic theme: the reference's PHP template loader. The main query stands, template_redirect fires, the hierarchy picks a PHP file, template_include filters it, and load_template() runs it as the response body. The theme prints its own document; the engine contributes the reference's wp_head defaults (title tag, robots, feed links, REST and oEmbed discovery, canonical, site icon) as hooks the theme's wp_head() call fires.
| new | __construct(Minn\Content\Site $site, Minn\Content\Posts $posts, Minn\Front\Permalinks $permalinks, Minn\Theme\ClassicTheme $theme, ?Minn\Theme\Theme $styleTheme, Minn\Theme\MainQueryBridge $bridge, ?Minn\Front\AdminBar $bar = NULL) | |
| static | create(Minn\Db $db, Minn\Theme\ClassicTheme $theme, ?Minn\Theme\Theme $styleTheme, Minn\Front\Permalinks $permalinks, int $perPage, ?Minn\Front\AdminBar $bar = NULL): self | A classic renderer over the database door. |
| method | render(Minn\Front\Resolution $resolution, array $coreClasses): ?string | The page for a resolution through the theme's PHP templates. |
| method | themeClasses(Minn\Front\Resolution $resolution, array $coreClasses): array | The body-class tokens before plugins filter them (get_body_class filters them). @return list<string> @return list<string> |
| inside | template(), bodyClasses(), registerHead(), registerStyles() |
ClassicTheme final readonly class
public/minn/src/Minn/Theme/ClassicTheme.php · 31 lines · Open the class →
The active classic (PHP-template) theme on disk. A theme is classic when it ships no block template index; its templates are PHP files the engine dispatches through the reference's hierarchy and runs via load_template(). The theme's own functions.php loads through the runtime's symbol gate.
| prop | readonly string $stylesheet | |
| prop | readonly string $template | |
| prop | readonly string $stylesheetDir | |
| prop | readonly string $templateDir | |
| static | active(Minn\Content\Site $site, string $themesDir): ?self | The active classic theme, or null under a block theme. |
CustomCss final class
public/minn/src/Minn/Theme/CustomCss.php · 69 lines · Open the class →
Custom CSS as theme.json and blocks write it (a styles node's "css", a block's style.css): nested rules under "&" unfolded beneath the selector they belong to, each wrapped in :root :where() as the reference prints them. Pure: CSS and selectors in, rules out.
| static | scoped(string $css, string $selector): string | A block's own CSS under its selector (probe editor-styles; a block's style.css too, probe block-supports), split at each ampersand: a part with no rule applies to the block itself; a nested selector that starts with a space is scoped, every comma part after the block's selector; any other is appended to it; a pseudo element moves to the end, outside :where(). |
| static | ofStyles(array $styles): string | The styles' own CSS (WP_Theme_JSON::get_custom_css): the top-level css, then each block's under its root selector. @param array<string, mixed> $styles |
| inside | scope(), append() |
EmbedRenderer final readonly class
public/minn/src/Minn/Theme/EmbedRenderer.php · 33 lines · Open the class →
A post's embed page (its /embed/ address, or ?embed= on it), the card another site's iframe shows, as the reference prints it: the main query stood with the embed asked for, then the embed template (the theme's own embed-{type}.php or embed.php, else the engine's theme-compat one) through template_include, with embed_head, embed_content, embed_content_meta and embed_footer. An address that embeds nothing gets the 404 card.
| new | __construct(Minn\Theme\MainQueryBridge $bridge) | |
| static | asked(Minn\Http\Request $request, Minn\Front\Resolution $resolution): bool | Whether a request for this resolution asks for its embed page. |
| method | render(Minn\Front\Resolution $resolution, Closure $bodyClasses): Minn\Http\Response | The embed page, under the status the request's main query settled on; the body classes the theme's page would carry (the Minn bar's aside), read once its main query stands. @param Closure(): list<string> $bodyClasses |
FeatureSelectors final class
public/minn/src/Minn/Theme/FeatureSelectors.php · 33 lines · Open the class →
A block's styles split between the selectors its metadata gives its features (probe theme-json-css), in the metadata's order: a property with a selector of its own first, then what is left of its feature under the feature's selector. What is taken leaves the node.
| static | split(array $selectors, array $node): array | The styles each feature selector takes, and the node left over. @param array<string, mixed> $selectors the block's metadata selectors@param array<string, mixed> $node the block's styles@return array{0: list<array{0: string, 1: array<string, mixed>}>, 1: array<string, mixed>} the styles each selector takes, in order, and what stays |
FeedHeaders final class
public/minn/src/Minn/Theme/FeedHeaders.php · 50 lines · Open the class →
The headers a feed is sent with, as the reference's send_headers sends them (suite feed-hooks): the feed type's content type, and when the site last changed (its posts, and its comments too for a comments feed) as Last-Modified with an ETag over it; a reader whose copy carries that date or tag is told the copy is current.
| static | for(array $vars, ?Minn\Http\Request $request): array | The headers, and whether the reader's copy is current. @param array<string, mixed> $vars the request's query variables@return array{0: array<string, string>, 1: bool} |
| inside | carriesComments() |
Folder final readonly class
public/minn/src/Minn/Theme/Folder.php · 77 lines · Open the class →
A theme folder read from disk: its style.css headers, which folder its templates come from, its screenshot, whether it is a block theme.
| prop | readonly string $root | |
| prop | readonly string $slug | |
| prop | readonly bool $exists | |
| prop | readonly array $headers | |
| prop | readonly string $template | |
| static | read(string $root, string $slug, array $labels, ?Closure $reader = NULL): self | A theme folder with its style.css headers. @param array<string, string> $labels key => the style.css header label@param Closure(string, array<string, string>): array<string, string>|null $reader the header reader (the facade's, so header filters apply); the engine's own by default |
| method | dir(): string | The folder's path. |
| method | screenshot(): ?string | The screenshot file name, or null when the theme has none. |
| static | isBlockTheme(array $dirs): bool | Whether any of the folders ships a block template index. @param list<string> $dirs the stylesheet and template directories |
| static | filePath(string $stylesheetDir, string $templateDir, string $file): string | The first of the stylesheet and template directories that holds the file, or the template directory's path. |
FontFaces final class
public/minn/src/Minn/Theme/FontFaces.php · 119 lines · Open the class →
fonts a theme.json declares in the shape they are printed from.
A face needs a family and at least one source it can name a format for. Its rule lists family (quoted unless it is one word or already carries quotes), style (normal), weight (400), display (fallback unless it is one the reference knows), the sources, then any other face property in the order given. Sources go data URIs first, then woff2, woff, truetype, embedded-opentype and opentype; anything else is dropped.
| static | css(array $fonts): string | The rules for fonts given as families of faces, one rule a line; '' when no face can be printed. @param array<array-key, mixed> $fonts |
| static | fromSettings(array $settings, Closure $fileUri): array | The fonts a theme.json's settings declare, one list of faces per family that has any: each face's sources first (file:./ ones through $fileUri), then its family (the first name of its own, or of the family's, unquoted), then its other properties in kebab case. @param Closure(string): string $fileUri a theme-relative path to its URL@return list<list<array<string, mixed>>> |
| inside | rule(), sources(), family(), variations(), firstName() |
FrontLifecycle final class
public/minn/src/Minn/Theme/FrontLifecycle.php · 110 lines · Open the class →
WordPress's front-end request steps around the main query, as WP::main runs them (front lifecycle trace): parse the request (do_parse_request may take it over; query_vars names the public variables, a plugin's own read from the query string; request filters the result; parse_request follows), the main query, the 404 decision (pre_handle_404 first), the globals, and the headers (wp_headers, the status, send_headers). The engine has already resolved the URL; these steps tell plugins about it in the reference's order and let them change what the query asks.
| static | parseRequest(WP $wp, array $vars, array $given, ?Closure $parse = NULL): bool | Parses the request: false when a plugin's do_parse_request took the parse over (the main query then does not run). The query string is the main query's to build, after. @param array<string, mixed> $vars the variables the engine resolved@param array<string, mixed> $given the query string and form, where a plugin's own variables are read@param (\Closure(list<string>): array<string, mixed>)|null $parse the reference's parse vars for the public vars, when the request is known |
| static | handle404(WP_Query $query, bool $notFound): void | The 404 decision, the one place it is made: a plugin's pre_handle_404 may make it; otherwise a request for something the site does not have is a 404, as is an empty page past the first of any listing and an empty date archive that names nothing else (an existing term, author or type with no posts, a date inside one of those or inside a search, an empty search, the front: a 200); the status and no-cache headers follow. A feed is never a 404: one of nothing is an empty feed. |
| static | sendHeaders(WP $wp): void | The headers the reference sends for the request: no caching for a signed-in reader or a 404, the content type, a pingback address for a single post that takes pings; then wp_headers, the status an error variable names, and send_headers. |
GlobalStyles final readonly class
public/minn/src/Minn/Theme/GlobalStyles.php · 547 lines · Open the class →
theme.json to CSS. Presets become custom properties on :root and their has-* utility classes; settings.layout sizes, root styles, elements, and per-block styles become rules; the containers, galleries, and style variations the page actually rendered get their own stylesheets. The layout rules themselves (flow, constrained, flex, grid, alignments) are the engine's own, written to the same class hooks.
| const | ELEMENT_SELECTORS = array ( 'link' => 'a:where(:not(.wp-element-button))', 'heading' => 'h1, h2, h3, h4, h5, h6', 'h1' => 'h1', 'h2' => 'h2', 'h3' => 'h3', 'h4' => 'h4', 'h5' => 'h5', 'h6' => 'h6', 'button' => '.wp-element-button, .wp-block-button__link', 'caption' => '.wp-element-caption, .wp-block-audio figcaption, .wp-block-embed figcaption, .wp-block-gallery figcaption, .wp-block-image figcaption, .wp-block-table figcaption, .wp-block-video figcaption', 'cite' => 'cite', ) | Element selectors in the order the reference prints them, whatever order theme.json or the saved styles list them in: the heading group lands before the individual levels, so an h1 line-height beats the group's. Themes list h1..h6 before heading and would otherwise win. |
| new | __construct(Minn\Theme\Theme $theme, ?array $user = NULL) | |
| method | styles(): array | The theme.json (plus site-editor) styles node, under the engine's own defaults. |
| method | resolvedStyles(): array | The same node with every `var:preset|…` token resolved to the custom property it names, which is the shape a caller reading the styles as data expects (the CSS writer resolves them on the way out instead). |
| method | css(): string | The global stylesheet from theme.json and the user's styles, as a page prints it: only the core blocks it rendered. |
| method | stylesheet(array $types): string | The stylesheet wp_get_global_stylesheet answers (probe editor-styles), by type: the custom properties, the styles (every block's, rendered or not), the preset classes; in that order. @param list<string> $types |
| method | fontFaces(): string | The @font-face rules for every family that declares font files (Theme\FontFaces), with file:./ resolved against the theme that carries the file. The page prints them through wp_print_font_faces on wp_head; the editor's styles read them here. |
| static | rootRules(bool $aware): string | The body's margin, the global padding rules under root-padding-aware alignments, and the site's alignments. |
| static | blockGapRules(string $gap): string | The block gap between the site's blocks and inside every layout. |
| static | layoutRules(): string | The layouts' own rules: alignments inside flow and constrained layouts, the content and wide sizes, flex and grid. |
| static | gapRules(string $prefix, string $gap): string | The block-gap rules for a layout scope: "" for the root, or a block's -is-layout- prefix. |
| static | elementStyles(array $elements, string $scope): string | The element rules (links, headings, buttons, captions, citations), each state after it; under a block's selector when one is given. |
| static | blockStyles(string $name, array $blockStyles, string $scope = ''): string | A block's rules: its root rule, its layout gap rules, then a rule for each feature its metadata gives a selector of its own (the avatar's border on its image), its own CSS and its elements (probe editor-styles). |
| static | scoped(string $selector, string $scope): string | Each selector in a list under the scope ("" for none). |
| static | rootSelector(string $name): string | A block's root selector: its metadata's, the reference's own for a few core blocks, else .wp-block-{slug}. |
| static | selectorsOf(string $name): array | A core block's selectors from its metadata. @return array<string, mixed> @return array<string, mixed> |
| static | byFeature(array $styles, array $selectors): array | A block's styles split between its root selector and the features (or a feature's single properties) its metadata selects elsewhere. @param array<string, mixed> $styles@param array<string, mixed> $selectors@return array{0: array<string, mixed>, 1: array<string, array<string, mixed>>} |
| static | variationCss(string $name, string $style, int $instance, array $variation): string | A numbered style variation's CSS (probe block-supports): its element rules scoped by the numbered class alone, then the variation on the block's root selector (the class riding on the block's own class: .wp-block-button.is-style-outline--3 .wp-block-button__link), its own CSS, and the blocks styled inside it. |
| static | declarations(array $styles, array $skip): array | theme.json style properties to declarations: color, typography, spacing, border, shadow, dimensions, outline. @return list<string> |
| inside | json(), parts(), fontUrl(), rootStyles(), blockCustomProperties(), withoutEmpty(), containerStyles(), ordered() |
HeadLinks final readonly class
public/minn/src/Minn/Theme/HeadLinks.php · 51 lines · Open the class →
The engine's own pieces of a page's head: its block stylesheet link, and for rest_output_link_wp_head the REST discovery link and the JSON alternate for the queried object; the site's feed links as feed_links prints them. Every theme's head prints them from the reference's wp_head hooks.
| new | __construct(Minn\Front\Permalinks $permalinks) | |
| method | engineStylesheet(): string | The link to the engine's own block stylesheet. |
| static | siteFeeds(array $args): string | The site's two feed links as feed_links prints them: the posts feed and the comments feed (each unless its feed_links_show_* filter says no), titled with the caller's separator and words, through feed_links_args. @param array<string, mixed> $args |
| method | restLink(): string | No trailing newline: the reference prints the JSON alternate and the RSD link on the same physical line. |
| method | jsonAlternate(Minn\Front\Resolution $resolution): string | The wp/v2 alternate link for the resolution. |
Hierarchy final class
public/minn/src/Minn/Theme/Hierarchy.php · 148 lines · Open the class →
The classic template hierarchy: the candidate file names each template type tries, most specific first, as the reference resolves them. The facade's get_{type}_template() functions feed these to get_query_template(), which locates the first candidate the theme (child, then parent) ships.
| static | frontPage(): array | The front page templates. @return list<string> |
| static | home(): array | The home templates. @return list<string> |
| static | privacyPolicy(): array | The privacy policy templates. @return list<string> |
| static | page(string $custom, string $slug, int $id): array | The page templates, custom first. @return list<string> |
| static | single(string $type, string $slug, string $custom): array | The single templates, custom first. @return list<string> |
| static | attachment(string $mimeType): array | The attachment templates by mime type: type-subtype, subtype, type (probe template-getters). @return list<string> |
| static | term(string $taxonomy, string $slug, int $id): array | The term archive templates. @return list<string> |
| static | author(string $nicename, int $id): array | The author archive templates. @return list<string> |
| static | archive(array $postTypes): array | The post type archive templates. @param list<string> $postTypes @return list<string> |
MainQueryBridge final readonly class
public/minn/src/Minn/Theme/MainQueryBridge.php · 136 lines · Open the class →
Stands the main query for a themed page and runs the front-end steps around it as WP::main does (FrontLifecycle): the request parsed, the main query through WP_Query (so pre_get_posts and every posts_* filter shape it), the 404 decision, the globals, the headers, then "wp" and template_redirect. A listing's posts are the query's, and so is the 404 for an empty page past the first or an empty date; a single post the query does not find (a preview, a draft its author reads) is the one the engine resolved. When a plugin takes the parse over no query runs, as on the reference, and the page stands empty.
| new | __construct(int $perPage) | |
| method | stand(Minn\Front\Resolution $resolution, array $extra = array ( )): Minn\Content\Page | The page of posts a resolution shows, through the runtime's main query; the variables a request adds of its own (a feed's) win. @param array<string, mixed> $extra |
| static | verdict(Minn\Front\Resolution $resolution): Minn\Front\Resolution | The resolution as the main query left it: a 404 when the query decided one (an empty page past the first, an empty date), with the vars it was asked under. |
| method | perPage(): int | Posts per page. |
| inside | vars(), postVars(), queried(), seeded() |
NotModified final class
public/minn/src/Minn/Theme/NotModified.php · 3 lines · implements Throwable, Stringable · extends Exception · Open the class →
Raised once a reader's copy of a feed has been found current and the headers that say so are sent: the reference stops the request there, so the engine answers with nothing more.
PageRenderer final readonly class
public/minn/src/Minn/Theme/PageRenderer.php · 185 lines · Open the class →
A whole page from the active block theme: the template the resolution maps to, rendered against the main query, inside the document shell the reference emits (skip link, wp-site-blocks, the skip-link target on the first main element).
PatternHeaders final class
public/minn/src/Minn/Theme/PatternHeaders.php · 78 lines · Open the class →
A theme's pattern files read by their headers, as WP_Theme::get_block_patterns lists them (probe wp-theme). Each one gives title, slug and description (empty when the header has none), then whatever of viewportWidth (a number), inserter (false for "no"), and the lists categories, keywords, blockTypes, postTypes and templateTypes it declares, split on commas and whitespace. A file without a title and a slug is not a pattern.
| static | all(string $themeDir): array | The patterns directory's files by file name, in name order. @return array<string, array<string, mixed>> |
| static | files(string $themeDir): array | The pattern files a theme ships, file name => path, in name order. @return array<string, string> |
| static | of(array $files): array | The records of a list of pattern files, file name => path (a list a plugin may have changed); a file that is not a pattern is left out. @param array<string, string> $files@return array<string, array<string, mixed>> |
| static | read(string $head): ?array | One file's record from the start of its text, or null when it names no title or slug. @return array<string, mixed>|null |
PatternText final class
public/minn/src/Minn/Theme/PatternText.php · 234 lines · Open the class →
Block-theme patterns are PHP files whose only code is a handful of echo-and-escape calls around literal strings. The engine never executes them: it interprets that small text grammar (string literals, "." concatenation, the i18n and escaping wrappers, the theme URI helper, and printf with %s) and leaves anything else out. A translated string is looked up in its domain (the theme's own), with its context where it gives one, as the reference's patterns ask for theirs. The header comment block is dropped, and every byte outside the PHP tags is kept as-is.
| static | render(string $file, string $themeUri): string | A pattern file's HTML with its PHP interpreted, never executed. |
| inside | statements(), printf(), expression(), term(), translated(), escape(), arguments(), stringLiteral(), identifier(), skipSpace() |
Printed final class
public/minn/src/Minn/Theme/Printed.php · 3 lines · implements Throwable, Stringable · extends Exception · Open the class →
Raised once a WordPress handler has printed a whole response (a sitemap, a stylesheet) or sent a redirect, where the reference exits: the request ends there and the engine answers with what was printed.
QueryClasses final readonly class
public/minn/src/Minn/Theme/QueryClasses.php · 128 lines · Open the class →
The body-class tokens the main query stands for, in the reference's order (captured from the oracles): the view tokens (home, blog, privacy-policy, archive, date, search with its results token, paged, attachment, error404), then the singular's or the archive's own, then the numbered paging tokens. Flags combine as the query's do: a search inside a category carries both sets. The bare paged token follows the listing's page; the numbered ones follow a single's page too, and take the view's prefix in one precedence (single, page, category, tag, date, author, search, post type; the front and a plain taxonomy have none). A 404 carries no paging tokens. The theme renderers seat the numbered tokens after the embed token and add the template and theme tokens.
| new | __construct(Minn\Db $db) | |
| method | of(WP_Query $query): array | The tokens for a main query. @return list<string> |
| inside | format(), singular(), archive(), paging(), named() |
SpacingScale final class
public/minn/src/Minn/Theme/SpacingScale.php · 48 lines · Open the class →
The spacing sizes a theme.json spacing scale makes (probe theme-json-css): Medium (slug 50) at the medium step; below it, half the other steps rounded down, each divided by (or less) the increment, named Small, X-Small, 2X-Small; above it the rest, multiplied by (or plus) it, named Large, X-Large, 2X-Large; slugs ten apart, values rounded to two places. An invalid scale makes none.
| static | sizes(array $scale): array | The sizes the scale makes, smallest first. @param array<string, mixed> $scale operator, increment, steps, mediumStep, unit@return list<array{name: string, slug: string, size: string}> |
| inside | name(), format() |
StyleLayers final class
public/minn/src/Minn/Theme/StyleLayers.php · 67 lines · Open the class →
What plugins change about the global stylesheet's layers and nodes, for GlobalStyles: core's preset lists when wp_theme_json_data_default changed core's layer, and the style nodes wp_theme_json_get_style_nodes keeps (probe hook-inputs-2). Without those filters the stylesheet is the engine's own, byte for byte.
| static | corePresets(): array | Core's preset lists: as stored, unless a plugin changed core's layer (wp_theme_json_data_default), whose lists then stand in for them. @return array<string, list<array{slug: string, value: string}>> |
| static | keptBlocks(array $blocks, array $kept): array | The blocks' styles as far as the kept nodes reach: a block's own declarations with its node, each of its elements with that element's node (the reference lists them apart); a block with neither goes. @param array<string, mixed> $blocks@param list<string> $kept@return array<string, mixed> |
| static | keptNodes(array $styles): ?array | The style nodes a plugin keeps (wp_theme_json_get_style_nodes) as their paths, the root, element and block nodes printed only when kept; null when no plugin filters them. @return list<string>|null |
StylePresets final class
public/minn/src/Minn/Theme/StylePresets.php · 148 lines · Open the class →
The preset side of theme.json: the colour, gradient, font-size, font-family, spacing, and shadow lists a theme declares over core's own, as the custom properties on :root and the has-* utility classes the reference prints for them. Pure: settings in, CSS fragments out.
| static | presets(array $settings, ?array $core = NULL): array | Every preset list the theme declares, over core's own (as given, else data/presets.json), keyed by kind. |
| static | presetList(mixed $presets): array | A preset list as theme.json writes it is a plain list; as the site editor saves it, it is keyed by origin (default, theme, custom). The reference prints the origins in that order, so the two shapes flatten to one list here. @return list<array> |
| static | fontFamilies(array $settings): array | The font family presets in the settings. @return list<array> |
| static | presetProperties(array $presets): string | The presets as custom properties for :root. |
| static | customProperties(array $custom, string $prefix = '--wp--custom--'): string | A settings.custom tree as custom properties: --wp--custom-- and the path to each value, every key in kebab case, lists by index; empty values are left out. @param array<array-key, mixed> $custom |
| static | presetClasses(array $presets, string $prefix = ''): string | The has-* utility classes the presets give every colour, gradient, font size, and font family; each under the prefix given (a block's :where(selector)). |
| static | defaultSlugsFirst(array $presets, array $defaults): array | A theme size that reuses one of core's slugs prints in core's position; the theme's own slugs follow. @param list<array> $presets@param list<string> $defaults@return list<array> |
| static | spacingPresets(array $defaults, array $own): array | The default spacing scale (20 to 80) is always present, whatever defaultSpacingSizes says; a theme size with the same slug replaces the default in place, and the theme's other sizes follow the scale. @return list<array{slug: string, value: string}> |
| static | fluidFontSize(array $preset, array $settings): string | A font size preset as the global stylesheet writes it: fluid by the theme's settings (Typography::fontSize). |
StyleSettings final class
public/minn/src/Minn/Theme/StyleSettings.php · 88 lines · Open the class →
The settings and styles nodes as wp/v2/global-styles reports them: preset lists keyed by the origin that declared them, appearanceTools spelled out as the flags it stands for, and var:preset tokens resolved to the custom properties they name. Pure: a node in, a node out.
| static | normalize(array $settings, string $origin): array | A settings node as written (theme.json, a variation, or the site editor's post) with its presets keyed by origin and appearanceTools expanded. |
| static | presetsByOrigin(array $settings, string $origin): array | The preset lists, at the root and under each block, keyed by the origin given; nothing else changed. |
| static | resolved(array $node): array | Every var:preset|kind|slug token replaced by the custom property it names. |
| inside | presetsUnder(), withAppearanceTools() |
TemplateBuffer final class
public/minn/src/Minn/Theme/TemplateBuffer.php · 31 lines · Open the class →
The reference includes a front-end template inside the template-enhancement buffer: wp_before_include_template fires with the template's file, its default callback opens the buffer when a plugin filters wp_template_enhancement_output_buffer, and that filter is handed the whole page. The engine builds the page as a string, so the string is passed through the same buffer: every buffer the action opened is closed in turn, its handler writing into the capture the page is read from.
| static | around(string $template, callable $render): ?string | The page a render gives, as the buffers opened before it leave it; null when the render gives none. A render that fails leaves nothing behind. @param callable(): ?string $render |
TemplateHierarchy final class
public/minn/src/Minn/Theme/TemplateHierarchy.php · 75 lines · Open the class →
The templates a block theme falls back through for a template slug, as get_template_hierarchy builds them (probe rest-templates-lookup): the slug itself, then its family's chain to index. A single entry's slug reaches single-{type} and single only when the type is registered (and goes straight to singular when not); a taxonomy's reaches taxonomy-{tax} and taxonomy only when the taxonomy is; pages, categories, tags and authors step through their bare name when the slug has more to it. A prefix names the next step outright. A custom template is a page's.
| static | for(string $slug, bool $custom, string $prefix, array $types, array $taxonomies): array | A slug's fallback chain, most specific first, ending at index. @param list<string> $types the registered post types@param list<string> $taxonomies the registered taxonomies@return list<string> |
| inside | chain(), single(), taxonomy(), registered() |
TemplateIndex final class
public/minn/src/Minn/Theme/TemplateIndex.php · 304 lines · Open the class →
Every block template and template part the site offers, in the order the reference lists them: the rows the site editor saved first (newest post date first), then the theme's own files in the order the directory hands them back, then whatever a plugin registered. A saved row shadows the theme file of the same slug and reports has_theme_file so the file can be restored by deleting the row.
| const | TEMPLATE = 'wp_template' | |
| const | PART = 'wp_template_part' | |
| new | __construct(Minn\Db $db, Minn\Theme\Theme $theme, Minn\Content\Site $site, ?Minn\Runtime\BlockTemplates $registered = NULL) | |
| method | all(string $type): array | Every template of a type: the theme's files with the saved rows over them. @return list<TemplateRecord> |
| method | find(string $type, string $id): ?Minn\Theme\TemplateRecord | Null when the id names another theme, or a slug nothing provides. |
| method | postRecord(array $row): Minn\Theme\TemplateRecord | A saved wp_template or wp_template_part row as a template. @param array<string, mixed> $row @param array<string, mixed> $row |
| method | files(string $type): array | The theme's files of a type, in the directory's order, each as _get_block_templates_files describes it (fileInfo). @return list<array<string, mixed>> |
| method | fileInfo(string $type, string $slug): ?array | One theme file: its slug, path, theme (the parent's for a file the child does not have) and type; a part's title (when theme.json gives one) and area; a custom template's title and post types. Null when the theme has no such file. @return array<string, mixed>|null |
| method | postTypes(string $slug): array | The post types a custom template declares; none for any other template. @return list<string> |
| method | themeSlug(): string | The theme the index reads. |
| method | hasFile(string $type, string $slug): bool | Whether the theme ships a file for a slug. |
| method | authorText(Minn\Theme\TemplateRecord $record): string | Who the caller is told made this: the theme's own name for anything that has a file behind it, the plugin for a registered one, the author's display name for a row a person saved, and the site's name when nobody is recorded. |
| method | originalSource(Minn\Theme\TemplateRecord $record): string | theme when a file backs it, plugin when one registered it, user when someone saved it, else site. |
| static | isCustom(string $slug): bool | A slug the reference does not name in its default template types is a custom template. |
| static | defaults(): array | The default template types. @return array<string, array{title: string, description: string}> |
| method | markup(string $content): string | Markup as a caller of the REST route sees it: patterns spliced in where the template only named them, then every template-part block told which theme it belongs to. A record carries the markup as stored, because that is what get_block_templates() hands a plugin. |
| inside | savedRows(), pluginRows(), fromRow(), fromFile(), fromPlugin(), fileTitle(), savedArea() |
TemplatePartTheme final readonly class
public/minn/src/Minn/Theme/TemplatePartTheme.php · 45 lines · Open the class →
A template-part block inside a template says which theme's part it means. The theme's own files usually leave that out, and the reference fills the active theme in on the way out, for saved rows as much as for files. It appends the attribute and leaves every other byte of the markup alone.
| static | apply(string $markup, string $theme): string | Template part blocks with the theme attribute set. |
| inside | withTheme(), encode(), pair() |
TemplatePatterns final readonly class
public/minn/src/Minn/Theme/TemplatePatterns.php · 88 lines · Open the class →
A template can name a pattern instead of carrying its blocks, and the reference hands the caller the blocks: every "wp:pattern" delimiter is replaced by the pattern's own markup before a template or part is served. A slug the theme does not know stays exactly as it is, which is what tells an editor the pattern went missing rather than the block.
| static | expand(string $markup, Minn\Theme\Theme $theme, int $depth = 0): string | Markup with its pattern blocks replaced by the patterns' content. |
| inside | closerAt(), pattern(), stamped(), isOneBlock() |
TemplateRecord final readonly class
public/minn/src/Minn/Theme/TemplateRecord.php · 34 lines · Open the class →
One block template or template part, whatever it came from: a theme file, a row the site editor saved, or a template a plugin registered. The id every caller uses is "<theme>//<slug>" in all three cases.
| new | __construct(string $theme, string $slug, string $type, string $content, string $title, string $description, string $source, ?string $origin, bool $hasThemeFile, int $author, ?string $modified, ?string $date, int $wpId, string $status = 'publish', ?string $area = NULL, ?string $plugin = NULL) | |
| prop | readonly string $theme | |
| prop | readonly string $slug | |
| prop | readonly string $type | |
| prop | readonly string $content | |
| prop | readonly string $title | |
| prop | readonly string $description | |
| prop | readonly string $source | |
| prop | readonly ?string $origin | |
| prop | readonly bool $hasThemeFile | |
| prop | readonly int $author | |
| prop | readonly ?string $modified | |
| prop | readonly ?string $date | |
| prop | readonly int $wpId | |
| prop | readonly string $status | |
| prop | readonly ?string $area | |
| prop | readonly ?string $plugin | |
| method | id(): string | The reference's template id: theme//slug. |
| method | isPart(): bool | Whether this is a template part. |
TemplateWriter final readonly class
public/minn/src/Minn/Theme/TemplateWriter.php · 116 lines · Open the class →
Saving and removing block templates. A template the theme ships is never touched on disk: editing one writes a wp_template row that shadows the file, and deleting that row is what "reset to the theme version" means.
| new | __construct(Minn\Db $db, Minn\Content\PostWriter $writer, Minn\Content\Terms $terms, Minn\Content\Site $site, Minn\Theme\TemplateIndex $index) | |
| method | save(Minn\Theme\TemplateRecord $record, array $fields, int $authorId): int | Writes the site's own copy of a template, creating the row the first time. Returns the post id. @param array{title?: string, content?: string, description?: string, area?: string} $fields |
| method | create(Minn\Theme\TemplateRecord $record, array $fields, int $authorId): int | A new site copy from the collection's create: as a save inserts one, but recording no origin, even over a theme file (probe rest-template-create). @param array<string, string> $fields |
| method | trash(Minn\Theme\TemplateRecord $record): void | Moves a site copy to the trash, which hands the theme's file back. |
| method | destroy(Minn\Theme\TemplateRecord $record): void | Deletes a saved template row. |
| inside | insert(), setArea(), themeTermId() |
Templates final readonly class
public/minn/src/Minn/Theme/Templates.php · 204 lines · Open the class →
Which template renders a resolution, and where its markup comes from: a wp_template post saved from the site editor (matched by slug and the theme term) wins over the theme's file. Parts resolve the same way through wp_template_part.
| new | __construct(Minn\Db $db, Minn\Content\Posts $posts, Minn\Theme\Theme $theme, ?Minn\Runtime\BlockTemplates $registered = NULL) | |
| method | forResolution(Minn\Front\Resolution $resolution): ?array | The template that renders a resolution, or null. @return array{slug: string, markup: string}|null |
| method | template(string $slug): ?string | A template's markup by slug, saved first. |
| method | part(string $slug): ?string | A template part's markup by slug, saved first. |
| method | partSource(string $slug): array | Where a template part comes from: a part saved for the theme (its post id), the theme's file (its path), or nowhere; with its markup. @return array{0: 'post'|'file'|'none', 1: int|string, 2: ?string} |
| method | candidates(Minn\Front\Resolution $resolution): array | The block-theme template hierarchy for each kind of resolution. @return list<string> |
| method | userStyles(): ?array | The site editor's saved global styles for the active theme, when any. An emptied node is stored as [] and reads as nothing, the way the reference reads it; a list where a map belongs is dropped the same way. |
| method | customTemplate(int $pageId): ?string | A page's chosen custom template, from _wp_page_template meta. |
| inside | filtered(), hierarchy(), savedOfTheme(), saved(), savedRow() |
Theme final class
public/minn/src/Minn/Theme/Theme.php · 347 lines · Open the class →
The active block theme on disk, read as data: theme.json, the templates and parts directories, and the patterns index. A child theme's files win and its parent fills in what the child does not define; theme.json merges the same way, with the child's preset lists replacing the parent's whole. The engine reads the site's installed theme the way it reads the site's database; it never runs the theme's PHP.
| new | __construct(string $slug, string $dir, string $uri, ?Minn\Theme\Theme $parent = NULL) | |
| prop | readonly string $slug | |
| prop | readonly string $dir | |
| prop | readonly string $uri | |
| prop | readonly ?Minn\Theme\Theme $parent | |
| static | active(Minn\Content\Site $site, Minn\Front\Permalinks $permalinks, string $themesDir): ?self | The active block theme, or null under a classic one. |
| static | forStyles(Minn\Content\Site $site, Minn\Front\Permalinks $permalinks, string $themesDir): ?self | The active theme as styling data (theme.json present), whether or not it is a block theme; the classic renderer prints its presets where the reference prints a classic theme's global styles. |
| method | parentSlug(): ?string | The theme's own name, and the parent's, for body classes. |
| method | json(): array | The theme.json with the parent's merged in; with plugins loaded, through wp_theme_json_data_theme. |
| method | styleFiles(): array | Every JSON file under styles/, the parent theme's first and each theme's in path order: block style partials and style variations alike. @return list<string> |
| static | merge(array $base, array $over): array | Layered theme.json: maps merge key by key, lists (palettes, font sizes, template parts) replace as a whole. |
| method | templateFile(string $slug): ?string | A template file's markup, or null. |
| method | templatePath(string $slug): ?string | The file a template is read from: this theme's, else its parent's; null when neither has one. |
| method | partFile(string $slug): ?string | A template part file's markup, or null. |
| method | partPath(string $slug): ?string | The file a template part is read from: this theme's, else its parent's; null when neither has one. |
| method | name(): string | The theme's display name, as the stylesheet header states it; a child theme answers with its own. Falls back to theme.json's title, then the folder name. |
| method | fileSlugs(string $folder): array | Every template (or part) slug the theme offers, the child's files first and the parent's after, each in the order the directory hands them back: the reference walks these directories unsorted and its template list carries that order through. @return list<string> |
| method | customTemplate(string $slug): ?array | A template title and description the theme declares for a custom template slug. |
| method | partTitle(string $slug): ?string | The title theme.json gives a template part, when it names one. |
| method | partArea(string $slug): string | The template-part area declared in theme.json (header, footer, or uncategorized). |
| method | pattern(string $slug): ?string | A pattern's markup, with its PHP text subset interpreted; null when unknown. |
| method | patternMeta(string $slug): array | A pattern's declared Block Types and Categories, the header fields a plugin reads to tell (say) a header pattern from any other. @return array{blockTypes: list<string>, categories: list<string>} |
| method | patternHeader(string $slug): ?array | The header fields a pattern declares, as the metadata attribute the reference writes onto the pattern's first block when it splices the pattern into a template. A field the header omits is omitted here. @return array{patternName: string, name: string, description?: string, categories?: list<string>}|null |
| method | styleUri(): ?string | The theme's stylesheet URL when it ships one; a child's own, else nothing (the parent's is not enqueued for it). |
| inside | at(), rawJson(), withStylePartials(), partialFiles(), safe(), htmlFiles(), patternIndex() |
ThemeJsonData final class
public/minn/src/Minn/Theme/ThemeJsonData.php · 82 lines · Open the class →
The theme's theme.json as plugins and the theme's own functions may change it (wp_theme_json_data_theme, a WP_Theme_JSON_Data they update with presets and settings of their own), as the reference's resolver hands it to them, and the core and site editor layers likewise (wp_theme_json_data_default, wp_theme_json_data_user). Worked out once a request for each set of callbacks, so a filter added late still counts.
| static | theme(array $json, string $dir): array | The theme layer through wp_theme_json_data_theme; as written when nothing filters it. @param array<string, mixed> $json @param array<string, mixed> $json |
| static | layer(string $origin, array $json): array | The core layer (wp_theme_json_data_default, origin default) or the site editor's (wp_theme_json_data_user, origin custom) as plugins leave it, each a WP_Theme_JSON_Data they update; as given when nothing filters it. Worked out once a request for each set of callbacks and layer. @param array<string, mixed> $json@return array<string, mixed> |
| inside | asWritten() |
ThemeStyles final readonly class
public/minn/src/Minn/Theme/ThemeStyles.php · 142 lines · Open the class →
The active theme's global styles as wp/v2/global-styles/themes/{stylesheet} reports them: the engine's defaults (captured from the reference under a theme with no theme.json) with the theme's own settings and styles over them, and the style variations the theme ships.
| new | __construct(?Minn\Theme\Theme $theme, string $stylesheet, ?array $core = NULL) | @param array{settings?: array, styles?: array}|null $core core's layer when not the stored one (a plugin changed it) |
| prop | readonly string $stylesheet | |
| method | withFilteredCore(): self | The same styling data over core's layer as wp_theme_json_data_default leaves it, for the places the reference reads core's layer through that filter (its resolver's core and merged data). |
| static | forSite(Minn\Content\Site $site, Minn\Front\Permalinks $permalinks, string $themesDir): self | The site's active theme as styling data, whether or not it is a block theme. |
| method | settings(): array | Settings: presets by origin, appearanceTools expanded, the defaults underneath. |
| method | patterns(): array | The pattern directory slugs the theme.json lists (its patterns), as given; [] when it lists none. @return array<mixed> @return array<mixed> |
| method | styles(): array | Styles: the theme's over the defaults, block style partials and section styles in, every var:preset token resolved. |
| method | variations(): array | The style variations under styles/: every JSON file there that names no blockTypes (those are block style partials), the parent theme's first, in path order, $schema dropped and the nodes normalized the way the theme's own are. @return list<array> |
| inside | withSectionStyles(), partials(), defaults(), storedCore() |
TreeStyles final readonly class
public/minn/src/Minn/Theme/TreeStyles.php · 259 lines · Open the class →
The CSS one theme.json tree writes, as WP_Theme_JSON keeps the tree (presets keyed by origin): its custom properties, its preset classes, its styles (the root layout, the root, elements, blocks) and its own CSS, by type, origin and option (probe theme-json-css). The rules are GlobalStyles'; what the page's writer takes for granted is read from the tree instead: block gaps only when the tree turns them on, the root padding only on the sides it gives, and none of the engine's own defaults.
| new | __construct(array $tree) | @param array<string, mixed> $tree |
| method | stylesheet(array $types, array $origins, array $options): string | The stylesheet for the types asked for, in the order variables, styles, presets, the tree's own CSS; origins narrow the presets. @param list<string> $types@param list<string> $origins@param array<string, mixed> $options root_selector, scope, skip_root_layout_styles |
| method | variables(array $origins, string $scope): string | The presets and settings.custom as custom properties: on :root, then on each block's settings selector that has its own. @param list<string> $origins |
| method | variablesOf(array $settings, array $origins, string $selector): string | One settings node's custom properties under its selector; nothing when it has none. @param array<string, mixed> $settings@param list<string> $origins |
| method | presetClasses(array $origins, string $scope): string | The has-* classes: the root's bare, each block's under :where(its settings selector). @param list<string> $origins |
| method | classesOf(array $settings, array $origins, string $selector): string | One settings node's has-* classes, under :where(selector) unless it is the bare :root. @param array<string, mixed> $settings@param list<string> $origins |
| method | styles(array $options): string | The styles: the root layout (unless skip_root_layout_styles), the root's own rule, its CSS when the root is not body, the elements, then each block; under the root_selector and scope options. @param array<string, mixed> $options |
| method | rootLayoutRules(string $selector): string | The root layout: the content and wide sizes, the body's margin, the global padding rules, the alignments; for body, the block gap (or the fallback gap of flex and grid) and the layouts' own rules. |
| method | layoutStyles(): string | The block gap and the layouts' own rules; flex and grid fall back to a 0.5em gap when the tree has no block gap. |
| method | rootStyles(string $selector): string | The root's own rule: body as it is, any other root under :root :where(). |
| method | blockStyles(string $name, string $scope = ''): string | One block's rules; its own block gap only when the tree turns block gaps on. |
| method | blockOwnStyles(string $name): string | One block's own rules, its elements left out: each element is a style node of its own. |
| method | blockElements(string $name): array | The elements a block styles, in the order they print. @return list<string> |
| method | elementStyles(string $element, string $block = ''): string | One element's rules, under a block's selector when it belongs to one. |
| method | customCss(): string | The tree's own top-level CSS, as written. |
| static | settingsSelector(string $name): string | A block's settings selector: its experimental selector when it has one, else .wp-block-{slug}. |
| inside | blockGap(), presets() |
Typography final class
public/minn/src/Minn/Theme/Typography.php · 105 lines · Open the class →
Font sizes as the reference writes them (probe plugin-queue3): a size in px, rem or em, and, with fluid typography on, a clamp() that grows linearly from a minimum at a small viewport to the size (or the preset's own maximum) at the wide one.
| static | valueAndUnit(mixed $raw, array $options = array ( )): ?array | A CSS length split into its number and unit (px, rem or em, or the units given), converted to another unit on request at a 16px root (or the one given); a bare number is px. Null for anything else. @param array{coerce_to?: string, root_size_value?: int|float, acceptable_units?: list<string>} $options@return array{value: float, unit: string}|null |
| static | fontSize(array $preset, array $settings): mixed | A font size preset as CSS (wp_get_typography_font_size_value). It stays as written unless fluid typography is on and the size is in a known unit and above the floor (14px, or the settings' minFontSize); then it grows from a minimum (the preset's own, else the size scaled by 1 - 0.075 log2 of its px, held between 0.25 and 0.75, never under the floor) to a maximum (the preset's own, else the size). @param array<string, mixed> $preset@param array<string, mixed> $settings typography and layout, merged over the global settings |
| static | clamp(?string $minViewport, ?string $maxViewport, ?string $minSize, ?string $maxSize, int|float|null $scale): ?string | The clamp() between two sizes over two viewport widths (wp_get_computed_fluid_typography_value): the slope in the minimum's unit, the base in rem. Null when a size or a width is missing or in an unknown unit, or the widths are equal. |
| inside | number() |
UserStyles final readonly class
public/minn/src/Minn/Theme/UserStyles.php · 111 lines · Open the class →
The site editor's saved global styles: one wp_global_styles post per theme, tied to it by the wp_theme term, holding a versioned JSON body of the settings and styles the editor wrote. Every changed save leaves a revision behind, as a post's does.
| new | __construct(Minn\Db $db, Minn\Content\Posts $posts, Minn\Content\PostWriter $writer, Minn\Content\Terms $terms, Minn\Content\Site $site) | |
| method | idFor(string $stylesheet): ?int | The newest published global-styles post carrying the theme's term, or null. |
| method | ensure(string $stylesheet, int $userId): int | The theme's post, made the way the reference makes it when there is none yet. |
| method | find(int $id): ?Minn\Content\PostRecord | The post when it is a global-styles post, else null. |
| static | decode(string $json): array | What a global-styles body holds; a missing, malformed, or list-shaped node is empty, as the reference reads it. @return array{settings: array, styles: array} |
| static | isBlank(string $json): bool | True when the body carries nothing at all under settings or styles, malformed or not. |
| method | save(int $id, int $userId, ?string $title, ?array $settings, ?array $styles, ?Closure $filter = NULL): void | Replaces what the caller names (null keeps the stored value), stamps the modified time, and snapshots a revision when anything changed. A filter, when given, has the last word on the content and title written (the save filters a REST save runs them through). @param null|Closure(array<string, string>): array<string, string> $filter |
Nothing matches.