PHPackages                             gebruederheitz/wp-theme-docs - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. gebruederheitz/wp-theme-docs

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

gebruederheitz/wp-theme-docs
============================

Add simple admin pages or a Wordpress theme documentation page to the editor.

v3.1.0(3mo ago)01.1k↓50%1GPL-3.0-onlyPHPPHP &gt;=8.0

Since Nov 3Pushed 3mo ago2 watchersCompare

[ Source](https://github.com/gebruederheitz/wp-theme-docs)[ Packagist](https://packagist.org/packages/gebruederheitz/wp-theme-docs)[ RSS](/packages/gebruederheitz-wp-theme-docs/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (10)Dependencies (6)Versions (16)Used By (1)

Wordpress Theme Admin Page and Documentation Maker
==================================================

[](#wordpress-theme-admin-page-and-documentation-maker)

*Add simply admin pages or a Wordpress theme documentation page to the editor.*

---

Installation
------------

[](#installation)

via composer:

```
> composer require gebruederheitz/wp-theme-docs
```

Make sure you have Composer autoload or an alternative class loader present.

Usage
-----

[](#usage)

```
# functions.php (or controller class)
use Gebruederheitz\Wordpress\Documentation\AdminPage;

new AdminPage('my-extra-admin-page', 'Extra Tools', 'tools.php');
// or use the factory method
AdminPage::factory('my-extra-admin-page', 'Extra Tools', 'tools.php');
```

This will set up a basic admin page under the "Tools" tab in the Wordpress backend with the translated title `__('Extra Tools', 'ghwp')`(`/wordpress/wp-admin/tools.php?page=my-extra-admin-page`).

In its most basic state, this renders a page empty except for the title. You will need to [register sections](#adding-sections) to add some content.

### Constructor (and factory) arguments

[](#constructor-and-factory-arguments)

```
AdminPage::__construct(
     string $menuSlug,
     ?string $title = null,
     ?string $menuLocation = 'themes.php',
     ?string $menuTitle = null,
     ?string $overridePath = null,
     ?string $i18nNamespace = 'ghwp'
 ): AdminPage
```

argumentdescriptionmenuSlugWhere the menu will be available under $menuLocation (`?page={{this}}`)titleA title displayed as `` at the top of the page, will be run through `__()`.menuLocationWhere to append the new submenu. Popular places are `themes.php` or `tools.php`.menuTitleAn alternative text for the menu entry. Defaults to `$title`.overridePathAn alternative path where consumers can put overrides templates to use instead of `template-parts/meta/docs/documentation-page.php`.i18nNamespaceThe namespace used for translations for menu titles, titles and within the default templates (`__(somestring, 'ghwp')`)### Adding sections

[](#adding-sections)

#### Section registration &amp; custom sections

[](#section-registration--custom-sections)

Any section you add must implement the `AdminPageSectionInterface`. You can use the method `addSection()` or the filter hook to add your section to a page:

##### using `addSection()`

[](#using-addsection)

```
use Gebruederheitz\Wordpress\Documentation\AdminPage ;
$page = new AdminPage('extras');
$page->addSection(new MySection());

// Using AdminPage's factory method:
AdminPage::factory('extras')->addSection($mySection);

// Adding multiple sections with addSection() or addSections()
AdminPage::factory('extras')
    ->addSection($mySection)
    ->addSection($otherSection);
AdminPage::factory('extras')
    ->addSections([
        new MySection(),
        new OtherSection(),
    ]);
```

##### using the hook

[](#using-the-hook)

```
use Gebruederheitz\Wordpress\Documentation\AdminPage ;
$page = new AdminPage('extras');

function ghwp_add_doc_section(array $sections) {
    $sections[] = new MyDocSection();

    return $sections;
}

add_filter($page->getSectionsHook(), 'ghwp_add_doc_section');
// OR, using 'ghwp_filter_sections_' and the page's slug:
add_filter('ghwp_filter_sections_extras', 'ghwp_add_doc_section');
```

For convenience, you can extend the `AbstractAdminPageSection`, which already has the interface implemented, only requiring you to implement three abstract getters to get it to run.

```
use Gebruederheitz\Wordpress\AdminPage\AbstractAdminPageSection;

class MyDocsSection extends AbstractAdminPageSection {
    public function getTitle() : string{
        return 'Documentation for my amazing feature';
    }

    protected function getDefaultPartial() : string{
        return __DIR__. '/../template-parts/meta/docs/feature.php';
    }
    /* Optional: Define an override path that can be used instead of your default */
    protected function getOverridePath() : string{
        return get_theme_file_path('template-parts/meta/overrides/feature.php');
    }

    /* Optional: Expose public methods for your template to use */
    public function getSomeData() {
        return [/* ... */];
    }
}
```

The above example sets up a section with the title `Documentation for my amazing feature`rendering from the template partial at the given path. The template is passed the instance of `AdminPage` and the current section:

```

```

Instead of setting the `$partial` property (or even extending the abstract class), you can also implement a custom rendering method:

```
use Gebruederheitz\Wordpress\AdminPage\AdminPageSectionInterface
use Gebruederheitz\Wordpress\AdminPage\AbstractAdminPageSection;

class MySecondDocsSection extends AbstractAdminPageSection {
    /* ... */

    /**
     * @override
     */
    public function render(AdminPage $docs)
    {
        get_template_part('template-parts/meta/docs/documentation', 'page', [$docs, $this]);
    }
}

/** Example of a section not extending the abstract base implementation */
class MyThirdDocsSection implements AdminPageSectionInterface {
    public function onPageSections(array $sections): array
    {
        $sections[] = $this;
        return $sections;
    }

    public function getTitle(): string
    {
        return 'My Third Docs Section is the best to date!';
    }

    public function render(DocumentationMenu $docs)
    {
        get_template_part('template-parts/meta/docs/documentation', 'page', [$docs, $this]);
    }

}
```

### The theme documentation page

[](#the-theme-documentation-page)

```
# functions.php (or controller class)
use Gebruederheitz\Wordpress\AdminPage\Documentation\DocumentationMenu;

new DocumentationMenu();
```

This will set up the basic documentation page under the "Appearance" tab in the Wordpress backend with the translated title `__('Theme-Help', 'ghwp')`(`/wordpress/wp-admin/themes.php?page=ghwp-help`).

It's simply a preconfigured `AdminPage`, so you will need to add sections. In this case, you can add them right through the constructor by passing an array as the first argument:

```
new DocumentationMenu([$sectionOne, $sectionTwo]);
```

> **Warning**
>
> Due to how PHP inheritance works, AdminPage's static `::factory()` method is available on DocumentationMenu, but it should not be used, as it will return a simple AdminPage object, not a DocumentationMenu instance.

#### DocumentationMenu: Changing the title and the template used

[](#documentationmenu-changing-the-title-and-the-template-used)

You can change the title displayed on the documentation page by passing a string as the constructor's second argument:

```
new \Gebruederheitz\Wordpress\Documentation\DocumentationMenu(null, 'Theme Docs!');
```

You can override the default template by creating a file in your theme's root directory under `template-parts/meta/docs/documentation-page.php`.

Alternatively you may override this default path by supplying a second argument to the constructor:

```
new DocumentationMenu(null, null, 'template-parts/special/docs.php');
```

#### Included sections

[](#included-sections)

The sections included in this package all extend `AbstractAdminPageSection`.

```
use Gebruederheitz\Wordpress\AdminPage\Documentation\DocumentationMenu;
use Gebruederheitz\Wordpress\AdminPage\Documentation\Section\Shortcodes;
use Gebruederheitz\Wordpress\AdminPage\Documentation\Section\Icons;

new DocumentationMenu(
    'My Theme',
    [
        new Shortcodes(),
        new Icons(),
    ]
);
// or
$docs = new DocumentationMenu();
$docs->addSection(new Shortcodes())->addSection(new Icons());
// or
$docs->addSections([new Shortcodes(), new Icons()]);
// or
add_filter($docs->getSectionsHook(), function(array $sections): array {
    $sections[] = new Shortcodes();

    return $sections;
});
```

This will register the sections and add them to the help page.

#### Generic Documentation Sections

[](#generic-documentation-sections)

This module will create a documentation section for users based on the attribute class `DocumentationSection`.

```
use Gebruederheitz\Wordpress\AdminPage\Documentation\Attributes\DocumentationSection;

#[DocumentationSection(
    title: "My Feature",
    description: "This is some content for my feature documentation."
)]
class MyDocumentedFeature {
    public function __construct()
    {
        DocumentationSection::register($this);
        // or: DocumentationSection::register(self::class);
    }
}
```

You will need to initialize the processing of these generic section in your AdminPage or DocumentationMenu instance you want them rendered in:

```
// Using a regular AdminPage
\Gebruederheitz\Wordpress\AdminPage\AdminPage::factory('docs')
->processGenericSections();

// Using the DocumentationMenu constructor
new \Gebruederheitz\Wordpress\AdminPage\Documentation\DocumentationMenu(
    sections: [/* ... */],
    processGenericSections: true // processGenericSections();
```

The generic sections can render Markdown content if the third-party package `fastvolt/markdown` is installed and the `markdown` property is set to `true`:

```
use Gebruederheitz\Wordpress\AdminPage\Documentation\Attributes\DocumentationSection;
#[DocumentationSection(
    title: "My Markdown Feature",
    description:
```

###### Using a different template partial location

[](#using-a-different-template-partial-location)

You'll need to extend the `Shortcodes` class and provide an alternative getter:

```
class MyShortcodes extends Shortcodes {
    // skip this if you want to keep the default partial and only
    // change the override location
    protected function getDefaultPartial(): string
    {
        return __DIR__ . '/../../templates/shortcodes.php';
    }

    protected function getOverridePath(): string
    {
        return 'template-parts/meta/docs/shortcodes.php';
    }
}
```

#### List of SVG icon partials

[](#list-of-svg-icon-partials)

This module will render a list of all icons that can be used by editors (for instance via shortcodes). By default it searches `template-parts/svg/` in your theme's root directory recursively for `.php` files, assuming they are templates containing SVG markup.

This is most useful in conjunction with a shortcode that can render these SVG partials, for instance into button blocks.

##### Setting a different path for SVG partials

[](#setting-a-different-path-for-svg-partials)

Same as [with the Shortcodes section](#using-a-different-template-partial-location).

Development
-----------

[](#development)

### Dependencies

[](#dependencies)

- PHP &gt;= 8.0
- optional: DDEV
- [Composer 2.x](https://getcomposer.org)
- [asdf tool version manager](https://asdf-vm.com) with nodeJS LTS (v24.x)
- [go-task / Taskfiles](https://taskfile.dev)

Migration
---------

[](#migration)

### v2 to v3

[](#v2-to-v3)

We've removed the deprecated Doctrine\\Annotations and replaced them with native PHP attributes. If you were using the ShortcodeDocumentation annotation, you'll need to change your code to use the attribute instead. We've also added a new method for registering shortcode documentation that does not require importing the trait.

```
- use Gebruederheitz\Wordpress\AdminPage\Documentation\Annotations\ShortcodeDocumentation;
+ use Gebruederheitz\Wordpress\AdminPage\Documentation\Attributes\ShortcodeDocumentation;
- use Gebruederheitz\Wordpress\AdminPage\Documentation\Traits\withShortcodeDocumentation;

- /**
-  * @ShortcodeDocumentation(
-  *   shortcode="ghwp-my-shortcode",
-  *   description="Renders a thing.",
-  *   parameters={
-  *       "id": "The post ID you wish to display."
-  *   },
-  *   examples={
-  *     "[ghwp-my-shortcode id=123 /]"
-  *   }
-  * )
-  */
+ #[ShortcodeDocumentation(
+   shortcode: "ghwp-my-shortcode",
+   description: "Renders a thing.",
+   parameters: [
+       "id" => "The post ID you wish to display."
+   ],
+   examples: [
+       "[ghwp-my-shortcode id=123 /]"
+   ]
+ )]
+
class MyShortcode {
-    use withShortcodeDocumentation;

    public function __construct()
    {
-        $this->addDocumentation();
+        ShortcodeDocumentation::register($this);
        add_shortcode('ghwp-my-shortcode', [$this, 'renderShortcode'));
    }
```

If you wish to continue using the traits, they now use the more conventional PascalCase naming, so `withShortcodeDocumentation` is now `WithShortcodeDocumentation`:

```
use Gebruederheitz\Wordpress\AdminPage\Documentation\Attributes\ShortcodeDocumentation;
- use Gebruederheitz\Wordpress\AdminPage\Documentation\Traits\withShortcodeDocumentation;
+ use Gebruederheitz\Wordpress\AdminPage\Documentation\Traits\WithShortcodeDocumentation;

#[ShortcodeDocumentation(
  shortcode: "ghwp-my-shortcode",
  description: "Renders a thing.",
  parameters: [
      "id" => "The post ID you wish to display."
  ],
  examples: [
      "[ghwp-my-shortcode id=123 /]"
  ]
)]
class MyShortcode {
-    use withShortcodeDocumentation;
+    use WithShortcodeDocumentation;

    public function __construct()
    {
        $this->addDocumentation();
        add_shortcode('ghwp-my-shortcode', [$this, 'renderShortcode'));
    }
```

### v1 to v2

[](#v1-to-v2)

- The PSR-4 namespaces changed; so instead of using `Gebruederheitz\Wordpress\Documentation\DocumentationPage`you will need to use `Gebruederheitz\Wordpress\AdminPage\Documentation\DocumentationPage` etc.
- `AdminPageSectionInterface` replaces `DocumentationSectionInterface`, `AbstractAdminPageSections`replaces `AbstractDocumentationSection`.
- For a complete list of namespace and class name changes refer to the table below.
- Sections do not extend `Singleton` anymore, so you will have to construct them like any regular class instead of calling `::getInstance()`.
- The filter hook for documentation sections has changed from `ghwp_filter_documentation_sections`to `ghwp_filter_sections_ghwp-help`. You can not use `DocumentationPage::HOOK_SECTIONS`anymore; either use the literal hook name, get the name via `$documentationPageInstance->getSectionsHook()`, or (preferred) use `$documentationPageInstance->addSection(AdminPageSectionInterface`

changedv1v2movedGebruederheitz\\Wordpress\\Documentation\\DocumentationPageGebruederheitz\\Wordpress\\AdminPage\\Documentation\\DocumentationPagerenamedGebruederheitz\\Wordpress\\Documentation\\DocumentationSectionInterfaceGebruederheitz\\Wordpress\\AdminPage\\AdminPageSectionInterfacerenamed, movedGebruederheitz\\Wordpress\\Documentation\\Sections\\AbstractDocumentationSectionGebruederheitz\\Wordpress\\AdminPage\\AbstractAdminPageSectionmovedGebruederheitz\\Wordpress\\Documentation\\Sections\\ShortcodeGebruederheitz\\Wordpress\\AdminPage\\Documentation\\Section\\ShortcodemovedGebruederheitz\\Wordpress\\Documentation\\Sections\\IconsGebruederheitz\\Wordpress\\AdminPage\\Documentation\\Section\\IconsmovedGebruederheitz\\Wordpress\\Documentation\\Annotations\\ShortcodeDocumentationGebruederheitz\\Wordpress\\AdminPage\\Documentation\\Annotations\\ShortcodeDocumentationmovedGebruederheitz\\Wordpress\\Documentation\\Traits\\withShortcodeDocumentationGebruederheitz\\Wordpress\\AdminPage\\Documentation\\Traits\\withShortcodeDocumentation--&gt;Gebruederheitz\\Wordpress\\Documentation\\Helper\\AnnotationReaderGebruederheitz\\Wordpress\\AdminPage\\Helper\\AnnotationReadernew--Gebruederheitz\\Wordpress\\AdminPage\\AdminPage

###  Health Score

46

—

FairBetter than 93% of packages

Maintenance81

Actively maintained with recent releases

Popularity17

Limited adoption so far

Community10

Small or concentrated contributor base

Maturity63

Established project with proven stability

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~111 days

Recently: every ~1 days

Total

15

Last Release

100d ago

Major Versions

v1.0.5 → v2.0.02023-07-06

v2.0.2 → v3.x-dev2026-01-29

PHP version history (3 changes)v1.0.0PHP ^7.3

v1.0.5PHP &gt;=7.3

v3.x-devPHP &gt;=8.0

### Community

Maintainers

![](https://www.gravatar.com/avatar/d2a201d58341e3ed71321bcb66cb375a8c6efffce7d8fe33244e821afc087c78?d=identicon)[mediocrity](/maintainers/mediocrity)

---

Top Contributors

[![AndreasMaros](https://avatars.githubusercontent.com/u/25008845?v=4)](https://github.com/AndreasMaros "AndreasMaros (39 commits)")

###  Code Quality

Static AnalysisPHPStan

Type Coverage Yes

### Embed Badge

![Health badge](/badges/gebruederheitz-wp-theme-docs/health.svg)

```
[![Health](https://phpackages.com/badges/gebruederheitz-wp-theme-docs/health.svg)](https://phpackages.com/packages/gebruederheitz-wp-theme-docs)
```

###  Alternatives

[clawrock/magento2-sass-preprocessor

Module for Sass processing during static content deployment

1012.1k](/packages/clawrock-magento2-sass-preprocessor)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
