Mecha CMS

Updates.

Opinionated Layout Hook System

Mecha introduces an opinionated layout hook system in the form of array to help you shape complex HTML markup without the need for dependencies like DOM parser and such.

In the future, it is possible to accept content data in the form of array as the second array data for the HTML class. This feature improvement allows us to create more complex and unlimited nesting level of HTML markup initiation data. A second argument named $deep is available with its default value set to false for backward compatibility, in which if it has the value set to true, then it will allow you to continue parsing the HTML content into list of tokens.

Formal syntax:

new HTML(array|string $value = [], bool $deep = false);

Given this input:

$div = new HTML(
<<<HTML
<ul class="list" id="list">
  <li>List item 1</li>
  <li>List item 2</li>
  <li>List item 3
    <ul>
      <li>List item 3.1</li>
      <li>List item 3.2</li>
      <li>List item 3.3</li>
    </ul>
  </li>
</ul>
HTML
);

The following is how a HTML string will be parsed before Mecha version 3.0.0:

$div = ['ul', '
  <li>List item 1</li>
  <li>List item 2</li>
  <li>List item 3
    <ul>
      <li>List item 3.1</li>
      <li>List item 3.2</li>
      <li>List item 3.3</li>
    </ul>
  </li>
', [
    'class' => 'list',
    'id' => 'list'
]];

Given this input:

$div = new HTML(
<<<HTML
<ul class="list" id="list">
  <li>List item 1</li>
  <li>List item 2</li>
  <li>List item 3
    <ul>
      <li>List item 3.1</li>
      <li>List item 3.2</li>
      <li>List item 3.3</li>
    </ul>
  </li>
</ul>
HTML
, true); // ← see the `true` value here?

The following is how a HTML string will be parsed in Mecha version 3.0.0:

$div = ['ul', [
    ['li', 'List item 1', []],
    ['li', 'List item 2', []],
    ['li', [
        'List item 3',
        ['ul', [
            ['li', 'List item 3.1', []],
            ['li', 'List item 3.2', []],
            ['li', 'List item 3.3', []]
        ], []]
    ], []]
], [
    'class' => 'list',
    'id' => 'list'
]];

It’s possible to parse HTML string into array without the DOM extension, although I haven’t really checked it strictly. Especially if there are some void elements in the container elements. But, converting array into HTML string tends to be easy to do and bug-free. This gave me a fresh idea to improve extensions that would add layout components like Alert and Comment, by initializing the HTML output for the layout components as a list of tokens:

echo new HTML(['section', [ /* … */ ], [
    'class' => 'comments'
]]);

Tokens can then be connected to a hook, so that developers can change the component’s HTML output according to their layout specification without the need to touch and modify the Comment extension directly:

echo new HTML(Hook::fire('y.comments', [['section', [ /* … */ ], [
    'class' => 'comments'
]]], $page));

For example, from another extension, a developer can change the comments block class name this way:

Hook::set('y.comments', function($y) {
    $y[2]['class'] = 'custom-comments';
    return $y;
});

I’ve been thinking about updating the Poll extension for a long time, but couldn’t find the right solution until this idea popped up. Previously, the extension relied heavily on HTML markup and I found the practice to be less flexible as it could prevent developers from changing the visual appearance of the poll component to suit the layout they developed.