emsifa/power-stub

Stub engine that support control statements and looping without breaking your indentations.

dev-master 2019-05-14 02:40 UTC

This package is auto-updated.

Last update: 2024-12-14 15:50:07 UTC


README

Build Status License: MIT

Power Stub is a stub engine that support control statements, looping and several other features that make it easier for you to generate code from stub file.

Stub file is a file that contains raw code with several parameters that will be replaced with certain text.

We use term stub engine because Power Stub not only able to replace parameter with given text, but also support control statement (if-elseif-else-endif), looping (foreach-endforeach, while-endwhile), etc. It is like template engine who also keep your indentation in the right place, so your generated code will stay neat.

Understanding The Problem

In common template engine such as Blade, Twig, etc. They will render your view file into PHP code below:

<div>
    <?php foreach($a as $b): ?>
    <p>
        lorem ipsum <?= $b ?>
    </p>
    <?php endforeach; ?>
</div>

When we render that file with $a = [1,2,3], the result will be messy like this:

<div>
        <p>
        lorem ipsum 1
    </p>
        <p>
        lorem ipsum 2
    </p>
        <p>
        lorem ipsum 3
    </p>
    </div>

It is OK, because template engine results are intended for browsers who don't care about indentation.

But this is not acceptable if we want to make code generator.

So with Power Stub, our stub file would looks like this:

<div>
    |# foreach($a as $b) #|
    <p>
        lorem ipsum [# $b #]
    </p>
    |# endforeach #|
</div>

When we render that stub with $a = [1,2,3], the result would looks like this:

<div>
    <p>
        lorem ipsum 1
    </p>
    <p>
        lorem ipsum 2
    </p>
    <p>
        lorem ipsum 3
    </p>
</div>

Now everybody happy :D

Other Features

Include

We also handle include function to keep indentation relative to the definition. For example you have 2 stub files like below:

main.js.stub

import something from 'something';

[# include("timeout.js", ['message' => 'first', 'delay' => 1000]) #]

something.on('event', () => {
    something.asyncStuff(() => {
        // timeout 2 seconds
        [# include("timeout.js", ['message' => 'second', 'delay' => 2000]) #]
    });
});

timeout.js.stub

setTimeout(() => {
    console.log("[# $message #]");
}, [# $delay #]);

If we render main.js.stub, the result would looks like this:

import something from 'something';

setTimeout(() => {
    console.log("first");
}, 1000);

something.on('event', () => {
    something.asyncStuff(() => {
        // timeout 2 seconds
        setTimeout(() => {
            console.log("second");
        }, 2000);
    });
});

GETTING STARTED

Power Stub still experimental. We have done some simple tests. You can use it, but there will may be some breaking changes.

Requirements

  • PHP >= 7.1

Installation

Make directory where you want to place your code.

Go to that directory using your cmd/terminal, and run composer command below:

composer require emsifa/power-stub:dev-master

Preparation

Before we start using Power Stub, we need to make 2 directories.

You can use commands below:

  • mkdir stubs
  • mkdir compiled

Render

First let's make our first stub. Create file app.js.stub inside our stubs directory.

In this example we will create an express app stub containing dynamic routes.

const express = require('express');
const app = express();

|# foreach($routes as $r) #|
app.[# strtolower($r['method']) #]('[# $r['path'] #]', function (req, res) {
    return res.send('OK');
});
|# endforeach #|

app.listen(3000);

Now let's create PHP script to render that stub. Create file named render.php.

<?php

require("vendor/autoload.php");

$powerStub = new Factory(
    __DIR__.'/stubs',       // our stubs directory
    __DIR__.'/compiled',    // compiled directory
    'stub'                  // extension (optional, default 'stub')
);

// Render app.js.stub
$rendered = $powerStub->render("app.js", [
    'routes' => [
        [
            'path' => '/',
            'method' => 'GET',
        ],
        [
            'path' => '/login',
            'method' => 'POST',
        ],
        [
            'path' => '/register',
            'method' => 'POST',
        ]
    ]
]);

echo $rendered;

Now when you call php render.php, the output will looks like this:

const express = require('express');
const app = express();

app.get('/', function (req, res) {
    return res.send('OK');
});
app.post('/login', function (req, res) {
    return res.send('OK');
});
app.register('/register', function (req, res) {
    return res.send('OK');
});

app.listen(3000);