PHPackages                             off-by-n/shortcode-templates - 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. off-by-n/shortcode-templates

ActiveLibrary

off-by-n/shortcode-templates
============================

 A simple and fast parser for text with BBCode-style shortcodes

1.0.2(2y ago)022MITPHPPHP &gt;=7.0.0

Since Nov 13Pushed 2y ago1 watchersCompare

[ Source](https://github.com/off-by-n/ShortcodeTemplates)[ Packagist](https://packagist.org/packages/off-by-n/shortcode-templates)[ RSS](/packages/off-by-n-shortcode-templates/feed)WikiDiscussions main Synced 1mo ago

READMEChangelogDependenciesVersions (4)Used By (0)

Shortcode Templates
===================

[](#shortcode-templates)

This library offers a simple parser for text containing "shortcodes", the underlying format of [BBCode](https://en.wikipedia.org/wiki/BBCode).

The scope of this project is to turn plain text containing generic shortcodes into a corresponding data structure. This should be as fast and efficient as possible, even for large amounts of text and deeply nested structures. It is not within the scope of this project to support any processing beyond that. For a more flexible solution that is optimized for smaller amounts of text, see [Shortcode](https://github.com/thunderer/Shortcode).

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

[](#installation)

```
composer require off-by-n/shortcode-templates

```

Usage
-----

[](#usage)

```
(new ShortcodeParser)->parse($inputString);
```

Example input string:

```
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, [hr bold][color=red]sed diam nonumy eirmod [color="green"]tempor invidunt ut labore et[/color] dolore [url="https://example.org" alt="Magna"]magna[/url] aliquyam [/color] erat, [b]sed[/b] diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.

```

This would produce the equivalent of the following data structure. As you can see, both closed and unclosed shortcodes are allowed. The plain text inbetween shortcodes is part of the output:

```
[
    "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, ",
    {
        "name": "hr",
        "value": null,
        "attributes": {
            "bold": true
        },
        "children": null
    },
    {
        "name": "color",
        "value": "red",
        "attributes": {},
        "children": [
            "sed diam nonumy eirmod ",
            {
                "name": "color",
                "value": "green",
                "attributes": {},
                "children": [
                    "tempor invidunt ut labore et"
                ]
            },
            " dolore ",
            {
                "name": "url",
                "value": "https:\/\/example.org",
                "attributes": {
                    "alt": "Magna"
                },
                "children": [
                    "magna"
                ]
            },
            " aliquyam "
        ]
    },
    " erat, ",
    {
        "name": "b",
        "value": null,
        "attributes": {},
        "children": [
            "sed"
        ]
    },
    " diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet."
]
```

You can then roll your own logic to proceed. Basic example:

```
function process($chunks = [])
{
    $output = '';
    foreach ($chunks as $chunk) {
        if ($chunk->isShortcode()) {
            $shortcode = $chunk->asShortcode();
            if ($shortcode->getName() == 'raw') {
                $output .= $shortcode->getInnerSource();
            } else {
                $output .= process($shortcode->getChildren());
            }
        } else {
            $output .= $chunk;
        }
    }

    return $output;
}
```

Properties
----------

[](#properties)

The anatomy of a shortcode is assumed to be:

`[= = =][/]`

All parts but the opening name and brackets are optional. The following methods are available for each shortcode:

- `getName()` - retrieves the shortcode's name
- `getValue()` - retrieves the shortcode's value, or `null` if none provided
- `getAttributes()` - retrieves all attributes as an associative array
- `getAttribute($name)` - retrieves a single attribute, by name, or `null` if not defined
- `getChildren()` - retrieves an array of all child chunks, or `null` for unclosed shortcodes
- `getInnerSource()` - retrieves the unparsed source text between the shortcode's opening and closing tag or `null` for unclosed shortcodes
- `getOuterSource()` - retrieves the unparsed source text of the shortcode, including opening and closing tag

All chunks, including text chunks, have a method `isShortcode()` to differentiate between types of chunk: `shortcode` or `text`.

Why RegEx
---------

[](#why-regex)

By default, this library uses PHP's own [RegEx](https://en.wikipedia.org/wiki/Regular_expression) extension to search the source text for control structures. The reasons for that are performance and easy setup: The Shortcodes format is made up of large amounts of literal text containing few relatively short control structures of a known format. The RegEx extension is optimized to find exactly that. Since it is a native implementation, it will usually have a better performance than any solution built in PHP code. Because the extension is already present in most installations, no additional extensions are required to install this parser. If another implementation is needed, it should be relatively easy to add.

###  Health Score

20

—

LowBetter than 14% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity6

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity39

Early-stage or recently created project

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

Total

3

Last Release

910d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/eab132f9f1076a13ff8eb11679aebe58dbe4282467903064f1ec9b5288f2cefe?d=identicon)[off-by-n](/maintainers/off-by-n)

---

Top Contributors

[![off-by-n](https://avatars.githubusercontent.com/u/63042351?v=4)](https://github.com/off-by-n "off-by-n (1 commits)")

### Embed Badge

![Health badge](/badges/off-by-n-shortcode-templates/health.svg)

```
[![Health](https://phpackages.com/badges/off-by-n-shortcode-templates/health.svg)](https://phpackages.com/packages/off-by-n-shortcode-templates)
```

PHPackages © 2026

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