PHPackages                             timnarr/kirby-helpers - 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. timnarr/kirby-helpers

ActiveKirby-plugin[Utility &amp; Helpers](/categories/utility)

timnarr/kirby-helpers
=====================

This plugin provides a collection of helper functions for Kirby

v1.6.0(2mo ago)2268MITPHPPHP ^8.2

Since Aug 1Pushed 1mo ago2 watchersCompare

[ Source](https://github.com/timnarr/kirby-helpers)[ Packagist](https://packagist.org/packages/timnarr/kirby-helpers)[ Docs](https://github.com/timnarr/kirby-helpers)[ RSS](/packages/timnarr-kirby-helpers/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (10)Dependencies (6)Versions (19)Used By (0)

Kirby Helpers
=============

[](#kirby-helpers)

Kirby Helpers is a collection of useful helper functions for Kirby CMS.

Features
--------

[](#features)

- 🎨 **CSS Helpers** - Lazy loading, conditional loading by template or block type
- 🔗 **Link Helpers** - Automatic link labels, external link detection, mailto builders
- 📝 **String Helpers** - Prefix/suffix utilities for consistent formatting
- 🌐 **Translation Helpers** - Translation status checking, filtering, and badges
- ♿️ **Accessibility** - SVG accessibility attributes, automatic link titles
- 🎯 **Block Helpers** - Extract and analyze block types for conditional styling
- ⚡️ **Vite Integration** - Dev mode detection, asset inlining
- 🏗️ **HTML Utilities** - Heading level validation and manipulation

Installation via Composer
-------------------------

[](#installation-via-composer)

To install Kirby Helpers via Composer, run the following command:

```
composer require timnarr/kirby-helpers
```

Available Functions
-------------------

[](#available-functions)

### CSS Helpers

[](#css-helpers)

#### `cssLazy(string $file, bool $omitNoscript = false): void`

[](#csslazystring-file-bool-omitnoscript--false-void)

Load a CSS file lazily using preload with low priority.

```
cssLazy('assets/css/carousel.css');
cssLazy(vite()->asset('styles/carousel.scss'), true);
```

#### `cssIfBlock(string $file, string $blockType, array $usedBlockTypes, bool $lazy = false): void`

[](#cssifblockstring-file-string-blocktype-array-usedblocktypes-bool-lazy--false-void)

Load CSS only if a specific block type is used on the page.

```
$pageBlocks = getUsedBlockTypes($page->text()->toBlocks());
cssIfBlock('assets/css/carousel.css', 'carousel', $pageBlocks);
cssIfBlock(vite()->asset('styles/carousel.scss'), 'carousel', $pageBlocks, true);
```

#### `cssIfTemplate(string $file, string|array $template, bool $lazy = false): void`

[](#cssiftemplatestring-file-stringarray-template-bool-lazy--false-void)

Load CSS only for specific page template(s).

```
cssIfTemplate('assets/css/contact.css', 'contact');
cssIfTemplate('assets/css/forms.css', ['contact', 'signup']);
```

---

### String Helpers

[](#string-helpers)

#### `ensureLeft(string $string, string $prefix): string`

[](#ensureleftstring-string-string-prefix-string)

Ensure a string starts with a specific prefix.

```
ensureLeft('example.com', 'https://'); // 'https://example.com'
ensureLeft('https://example.com', 'https://'); // 'https://example.com'
```

#### `ensureRight(string $string, string $suffix): string`

[](#ensurerightstring-string-string-suffix-string)

Ensure a string ends with a specific suffix.

```
ensureRight('example', '.com'); // 'example.com'
ensureRight('example.com', '.com'); // 'example.com'
```

#### `ensureHashed(string $string): string`

[](#ensurehashedstring-string-string)

Ensure a string starts with a hash character (#). Useful for anchor links.

```
ensureHashed('section-1'); // '#section-1'
ensureHashed('#section-1'); // '#section-1'
```

---

### HTML/Heading Helpers

[](#htmlheading-helpers)

#### `heading(string $level, string $text, array $attrs = []): string`

[](#headingstring-level-string-text-array-attrs---string)

Generate an HTML heading element with specified level, text, and attributes.

```
heading('h2', 'Welcome', ['class' => 'title']);
// Welcome
```

#### `incrementHeadingLevel(string $level, int $steps = 1): string`

[](#incrementheadinglevelstring-level-int-steps--1-string)

Increment or decrement a heading level, clamped between h1 and h6.

```
incrementHeadingLevel('h2', 1);  // 'h3'
incrementHeadingLevel('h2', -1); // 'h1'
incrementHeadingLevel('h6', 1);  // 'h6' (clamped)
```

#### `validateHeadingLevel(string $level): void`

[](#validateheadinglevelstring-level-void)

Validate a heading level string. Throws exception if invalid.

```
validateHeadingLevel('h2'); // OK
validateHeadingLevel('h7'); // Throws InvalidArgumentException
```

---

### Block Helpers

[](#block-helpers)

#### `getUsedBlockTypes(Blocks|array $blocks): array`

[](#getusedblocktypesblocksarray-blocks-array)

Extract all used block types from a Blocks object or array. Useful for conditional CSS loading.

```
$pageBlocks = getUsedBlockTypes($page->text()->toBlocks());
// ['heading', 'text', 'image', 'gallery']

// Use with cssIfBlock
cssIfBlock('assets/css/gallery.css', 'gallery', $pageBlocks);
```

---

### Link Helpers

[](#link-helpers)

#### `setBlankIfExternal(string $link, bool $dontReturnHref = false): array`

[](#setblankifexternalstring-link-bool-dontreturnhref--false-array)

Determine if a link is external and return appropriate attributes (target="\_blank" for external links).

```
setBlankIfExternal('https://example.com');
// ['href' => 'https://example.com', 'target' => '_blank']

setBlankIfExternal('mailto:test@example.com');
// ['href' => 'mailto:test@example.com']
```

#### `linkLabel(string $type, string|Page|File $data): string`

[](#linklabelstring-type-stringpagefile-data-string)

Generate accessible link labels for different link types.

```
linkLabel('internal', $page);   // "Link to page: {title}"
linkLabel('external', 'https://example.com'); // "External link: https://example.com (Opens new tab)"
linkLabel('document', $file);   // "Download file: document.pdf (2.5 MB)"
linkLabel('mail', 'test@example.com'); // "Send email to: test@example.com"
linkLabel('tel', '+1234567890'); // "Call phone number: +1234567890"
```

#### `buildMailtoLink(string $email, string|null $subject = null, string|null $body = null): string`

[](#buildmailtolinkstring-email-stringnull-subject--null-stringnull-body--null-string)

Build a mailto link with optional subject and body parameters.

```
buildMailtoLink('test@example.com', 'Hello', 'This is a test');
// 'mailto:obfuscated@email.com?subject=Hello&body=This%20is%20a%20test'

buildMailtoLink('test@example.com', 'Hello', 'Line 1\nLine 2');
// Line breaks are properly encoded
```

---

### Page/Cache Helpers

[](#pagecache-helpers)

#### `shouldIgnorePageFromCache(Page $page, Pages|null $ignoredPages, array $ignoredSlugs = [], array $ignoredTemplates = []): bool`

[](#shouldignorepagefromcachepage-page-pagesnull-ignoredpages-array-ignoredslugs---array-ignoredtemplates---bool)

Determine if a page should be excluded from caching.

```
shouldIgnorePageFromCache($page, site()->notCachedPages()->toPages(), ['my-slug'], ['contact']);
```

#### `getAvailableTranslations(Page $page): array`

[](#getavailabletranslationspage-page-array)

Get available translation language codes for a page (excluding current language).

```
getAvailableTranslations($page); // ['de', 'fr']
```

#### `getMissingTranslations(Page $page): array`

[](#getmissingtranslationspage-page-array)

Get an array of language codes for which the page translation does not exist.

```
getMissingTranslations($page); // ['de', 'fr']
```

---

### File Helpers

[](#file-helpers)

#### `readAccessible(File $file, string $title = '', string $description = '', bool $isDecorative = false): string`

[](#readaccessiblefile-file-string-title---string-description---bool-isdecorative--false-string)

Read and enhance SVG files with accessibility attributes (title, description, ARIA attributes).

```
readAccessible($file, 'Icon description', 'Detailed description');
readAccessible($file, '', '', true); // Decorative SVG with aria-hidden
```

---

### Vite Helpers

[](#vite-helpers)

#### `isViteDevMode(): bool`

[](#isvitedevmode-bool)

Check if Vite is in development mode by verifying manifest file presence.

```
if (isViteDevMode()) {
    // Development-specific code
}
```

#### `inlineViteAsset(string|array $files, string $type): void`

[](#inlineviteassetstringarray-files-string-type-void)

Inline Vite assets (stylesheet or script) based on environment.

```
inlineViteAsset('main.css', 'stylesheet');
inlineViteAsset(['app.js', 'vendor.js'], 'script');
```

---

Field Methods
-------------

[](#field-methods)

### `ensureLeft(string $prefix): string`

[](#ensureleftstring-prefix-string)

Ensure a field value starts with a specific prefix. Returns the field for chaining.

```
$page->url()->ensureLeft('https://')->value();
```

### `ensureRight(string $suffix): string`

[](#ensurerightstring-suffix-string)

Ensure a field value ends with a specific suffix. Returns the field for chaining.

```
$page->path()->ensureRight('/')->value();
```

### `ensureHashed(): string`

[](#ensurehashed-string)

Ensure a field value starts with a hash character (#). Useful for anchor links. Returns the field for chaining.

```
$page->anchor()->ensureHashed()->value();
// 'section-1' becomes '#section-1'
```

### `autoLinkTitles(): string`

[](#autolinktitles-string)

Automatically add accessible title attributes to all links in HTML content. Detects internal pages, files, email, phone, and external links. Returns the field for chaining.

```
$page->text()->kirbytext()->autoLinkTitles();
// Adds appropriate title attributes to all  tags
```

---

File Methods
------------

[](#file-methods)

### `readAccessible(string $title = '', string $description = '', bool $isDecorative = false): string`

[](#readaccessiblestring-title---string-description---bool-isdecorative--false-string)

```
$file->readAccessible('Icon title', 'Icon description');
```

---

Page Methods
------------

[](#page-methods)

### `hasTranslations(): bool`

[](#hastranslations-bool)

```
if ($page->hasTranslations()) {
    // Page has translations
}
```

### `getTranslations(): array`

[](#gettranslations-array)

```
$translations = $page->getTranslations(); // ['de', 'fr']
```

### `missingTranslationCodes(): array`

[](#missingtranslationcodes-array)

Get an array of language codes for which the page translation does not exist.

```
$missing = $page->missingTranslationCodes(); // ['de', 'fr']
```

### `missingTranslationsBadge(): string`

[](#missingtranslationsbadge-string)

Generate a Kirby Panel info badge showing translation status. Returns a green badge if all translations exist, or a red badge with missing language codes.

```
echo $page->missingTranslationsBadge();
// All translated
// or
// Missing: DE, FR
```

---

Options
-------

[](#options)

The following options are available for customization:

OptionDefaultTypeDescription`vite.manifestPath``kirby()->root() . '/build/manifest.json'`stringPath to vites manifest file to determine dev mode. Used by `isViteDevMode()`Translations
------------

[](#translations)

Translations are required for the labels returned by the `linkLabel()` function. This plugin provides translations for English and German. The following translation keys are available for customization:

KeyDefault`link_label_internal_home``Link to homepage: { title }``link_label_internal``Link to page: { title }` `link_label_document``Download file: { filename }` `link_label_external``External link: { url } (Opens new tab)` `link_label_mail``Send email to: { mail } (Opens new window of your email program)` `link_label_tel``Call phone number: { tel } (Opens new window/program)`License
-------

[](#license)

Kirby Helpers is licensed under the [MIT License](./LICENSE). © 2024-present Tim Narr

###  Health Score

46

—

FairBetter than 93% of packages

Maintenance88

Actively maintained with recent releases

Popularity16

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity61

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 ~35 days

Recently: every ~26 days

Total

17

Last Release

79d ago

Major Versions

0.5.0 → 1.0.02025-10-24

### Community

Maintainers

![](https://www.gravatar.com/avatar/75cefc2df4ef7934de03eae279eadce11b87ebf6252019a643a626327e887ef5?d=identicon)[TimNarr](/maintainers/TimNarr)

---

Top Contributors

[![timnarr](https://avatars.githubusercontent.com/u/3532570?v=4)](https://github.com/timnarr "timnarr (54 commits)")

---

Tags

kirby-cmskirby-pluginhelpertranslationshelpersviteaccessibilityutilitieskirbykirby-pluginkirby-cms

###  Code Quality

Code StylePHP CS Fixer

### Embed Badge

![Health badge](/badges/timnarr-kirby-helpers/health.svg)

```
[![Health](https://phpackages.com/badges/timnarr-kirby-helpers/health.svg)](https://phpackages.com/packages/timnarr-kirby-helpers)
```

###  Alternatives

[belugadigital/kirby-navigation

Kirby 5 field for hierarchical menus with drag &amp; drop level indentation.

8713.4k](/packages/belugadigital-kirby-navigation)[bnomei/kirby3-dotenv

Kirby Plugin for environment variables from .env

4144.1k1](/packages/bnomei-kirby3-dotenv)[bnomei/kirby3-recently-modified

Kirby Section to display recently modified content pages

309.3k](/packages/bnomei-kirby3-recently-modified)[johannschopplich/kirby-helpers

Environment, SEO, and build utilities for Kirby CMS

277.4k](/packages/johannschopplich-kirby-helpers)[moritzebeling/kirby-favicon

Kirby plugin to meet all favicon needs

144.8k](/packages/moritzebeling-kirby-favicon)[tobimori/kirby-tailwind-merge

Tailwind Merge for Kirby CMS

276.3k](/packages/tobimori-kirby-tailwind-merge)

PHPackages © 2026

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