2017 © Pedro Peláez
 

library staticka

A simple and extensible static site generator.

image

staticka/staticka

A simple and extensible static site generator.

  • Friday, April 6, 2018
  • by rougin
  • Repository
  • 1 Watchers
  • 1 Stars
  • 193 Installations
  • PHP
  • 1 Dependents
  • 0 Suggesters
  • 1 Forks
  • 0 Open issues
  • 4 Versions
  • 0 % Grown

The README.md

Staticka

Latest Version on Packagist ![Software License][ico-license] Build Status ![Coverage Status][ico-coverage] Total Downloads, (*1)

A yet-another PHP-based static site generator. This converts Markdown content and PHP files into static HTML. It is inspired by popular static site generators like Hugo and Jekyll., (*2)

Installation

Installing Staticka is possible via Composer:, (*3)

``` bash $ composer require staticka/staticka, (*4)


## Basic Usage The following guides below showcase the functionalities of `Staticka`. If a specified requirement wants to create a static blog site using a terminal or wants to create pages with a web-based user interface, kindly check [Console](https://github.com/staticka/console) or [Expresso](https://github.com/staticka/expresso) respectively. ### Simple HTML from string `Staticka` can convert simple Markdown content from string into HTML: ``` php // index.php use Staticka\Page; use Staticka\Parser; // Creates a new page with the specified body ----- $page = (new Page)->setName('Hello world!'); $page->setBody("# {NAME}\nThis is a sample page."); // ------------------------------------------------ // Converts the page into an HTML --- echo (new Parser)->parsePage($page); // ----------------------------------

``` bash $ php index.php, (*5)

Hello world!

This is a sample template., (*6)


In the example above, the `{NAME}` is a placeholder to insert the `name` value from the `Page` class to the body. ### Using `.md` files `Staticka` also supports converting the Markdown-based files (`.md`files) by adding the path of the `.md` file to the `Page` class: ``` md # Hello World! This is a sample **Markdown** file!

``` php // index.php, (*7)

// ..., (*8)

// Specify the path of the Markdown file ----- $file = DIR . '/app/pages/hello-world.md';, (*9)

$page = new Page($file); // -------------------------------------------, (*10)

// ..., (*11)


``` bash $ php index.php

Hello World!

This is a sample Markdown file!, (*12)

Adding Front Matter, additional data

Staticka supports Front Matter in which can add predefined variables in a specific content., (*13)

``` md , (*14)


link: hello-world

Hello World!

The link is {LINK}., (*15)


``` bash $ php index.php

Hello World!

The link is hello-world., (*16)

To use the variable inside a content, use the curly brackets ({}) format (e.g., {NAME})., (*17)

Building HTML pages

Multiple Page classes can be converted into .html files with their respective directory names using the Site class:, (*18)

``` php // index.php, (*19)

// ..., (*20)

use Staticka\Site;, (*21)

// ..., (*22)

// Builds the site with its pages ------------ $site = new Site($parser);, (*23)

$file = DIR . '/app/pages/hello-world.md'; $site->addPage(new Page($file));, (*24)

$site->build(DIR . '/app/web'); // -------------------------------------------, (*25)


``` bash $ php index.php

``` html , (*26)

Hello World!

The link is hello-world., (*27)


The `Site` class can also empty a specified directory or copy a directory with its files. This is usable if the output directory needs CSS and JS files:

app/ ├─ web/ │ ├─ index.html styles/ ├─ index.css, (*28)


``` php // ... // Empty the "output" directory --- $output = __DIR__ . '/app/web'; $site->emptyDir($output); // -------------------------------- // Copy the "styles" directory to "output" --- $styles = __DIR__ . '/styles'; $site->copyDir($styles, $output); // ------------------------------------------- // ...

Adding data that can be applied to all pages is also possible in the same Site class:, (*29)

``` php // ..., (*30)

$data = array('ga_code' => '12345678'); $data['website'] = 'https://roug.in';, (*31)

$site->setData($data);, (*32)

// ..., (*33)


> [!NOTE] > The data provided in the `Site` class can also be accessed inside a content by using the curly braces format (`{}`). ### Adding template engines Building HTML pages from Markdown files only returns the content itself. By adding a third-party template engine, it makes it easier to add partials (e.g., layouts) or provide additional styling to each page. To add a template engine, a `Render` class must be used inside the `Parser` class: ``` md --- name: Hello world! link: hello-world plate: main.php --- # This is a hello world! The link is **{LINK}**. And this is to get started...

The plate property specifies the layout file to be used when parsing the page. In this example, the main.php is the layout to be used in the hello-world.md file:, (*34)

``` html , (*35)

, (*36)

<?php echo $name; ?>

> [!NOTE] > The `$html` variable from the example above is a predefined variable for returning the content from the page that is parsed. The additional data from the `Page` class are also predefined as a variable (e.g., `$link` from `link`, `$name` from `name`). After creating the template file (e.g., `main.php`), specify the `Parser` class to render templates using the `Render` class: ``` php // index.php // ... use Staticka\Parser; use Staticka\Render; // ... // Path where the "main.php" can be located --- $path = __DIR__ . '/app/plates'; // -------------------------------------------- // Sets the Render and Parser --- $render = new Render($path); $parser = new Parser($render); // ------------------------------ // Render may be added to Parser after --- $parser->setRender($render); // --------------------------------------- // ...

Then running the script will convert the .md file to a compiled .html with the defined template:, (*37)

``` bash $ php index.php, (*38)


``` html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Hello world!</title> </head> <body>

This is a hello world!

The link is hello-world. And this is to get started..., (*39)

</body> </html>

To implement a custom template engine to Staticka, implement the said engine to the RenderInterface:, (*40)

``` php namespace Staticka\Render;, (*41)

interface RenderInterface { /** * Renders a file from a specified template. * * @param string $name * @param array<string, mixed> $data * * @return string * @throws \InvalidArgumentException */ public function render($name, $data = array()); }, (*42)


### Setting layouts A `Layout` class allows a `Page` class to use various filters and helpers. It can also be passed as a `class-string` in the `.md` file: ``` php // index.php use Staticka\Layout; // ... $pages = __DIR__ . '/app/pages'; // Define the layout with the name "main.php" --- $layout = (new Layout)->setName('main.php'); // ---------------------------------------------- // ... // Set the layout into the page ------------- $page = new Page($pages . '/hello-world.md'); $site->addPage($page->setLayout($layout)); // ------------------------------------------

[!NOTE] If a name is specified from the Layout, there is no need to specify the plate property from the .md file., (*43)

It is also possible to specify a Layout class in the .md file by specifying it to the plate property. Using this approach requires a RenderInterface attached to the Parser class:, (*44)

``` php namespace App\Layouts;, (*45)

use Staticka\Layout;, (*46)

class HomeLayout extends Layout { /** * Specifies the plate to be used as the layout. * * @var string */ protected $name = 'home.php'; }, (*47)


``` md --- name: Hello world! link: hello-world plate: App\Layouts\HomeLayout --- # This is a hello world! The link is **{LINK}**. And this is to get started...

If the Layout class requires complex dependencies, the Parser class must specify a container to easily identify the specified layout instance:, (*48)

``` php namespace App\Layouts;, (*49)

use App\Complex; use Staticka\Layout;, (*50)

class ComplexLayout extends Layout { protected $complex;, (*51)

public function (Complex $complex)
{
    $this->complex = $complex;
}

// ...

}, (*52)


``` php // index.php use App\Layouts\ComplexLayout; use Rougin\Slytherin\Container\Container; use App\Complex; // ... // Define the complex layout... --------- $layout = new ComplexLayout(new Complex); // -------------------------------------- // ...then add it to the container... --- $container = new Container; $name = ComplexLayout::class; $container->set($name, $layout); // -------------------------------------- // ... // ...and set the container to the parser --- $parser->setContainer($container); // ------------------------------------------ // ...

[!NOTE] If the container is not specified, the ReflectionContainer from Slytherin is initialized by default., (*53)

Extending and customization

With the philosophy of Staticka to be an extensible and scalable static site generator, the following guides below are use-cases for Staticka turning it into a content management system (CMS) or a fully functional static blog website:, (*54)

Modifying with filters

A Filter allows a page to be modified after being parsed:, (*55)

``` php // index.php, (*56)

use Staticka\Filter\HtmlMinifier;, (*57)

// ..., (*58)

// Set the layout class for "main.php" --- $layout = new Layout;, (*59)

$layout->setName('main.php'); // ---------------------------------------, (*60)

// Minifies the HTML after parsing the page --- $layout->addFilter(new HtmlMinifier); // --------------------------------------------, (*61)

// ..., (*62)


``` bash $ php index.php

``` html , (*63)

, (*64)

Hello world!

This is a hello world!

The link is hello-world. And this is to get started..., (*65)

, (*66)


To create a custom filter, implement it using the `FilterInterface`: ``` php namespace Staticka\Filter; interface FilterInterface { /** * Filters the specified code. * * @param string $code * * @return string */ public function filter($code); }

[!TIP] Please see FILTERS page for showcasing the list of available filters., (*67)

Custom methods using helpers

A Helper provides additional methods inside template files:, (*68)

``` php // index.php, (*69)

use Staticka\Helper\LinkHelper;, (*70)

// ..., (*71)

// Set the layout class for "main.php" --- $layout = new Layout;, (*72)

$layout->setName('main.php'); // ---------------------------------------, (*73)

// Add a "$url" variable in templates --- $url = new LinkHelper('https://roug.in');, (*74)

$layout->addHelper($url); // --------------------------------------, (*75)

// ..., (*76)


``` html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> </head> <body> <a href="<?php echo $url->set($link); ?>"></a> </body> </html>

``` bash $ php index.php, (*77)


``` html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Hello world!</title> </head> <body>

This is a hello world!

The link is hello-world. And this is to get started..., (*78)

<a href="https://roug.in/hello-world">Hello world!</a> </body> </html>

To create a template helper, implement the said code in HelperInterface:, (*79)

``` php namespace Staticka\Helper;, (*80)

interface HelperInterface { /** * Returns the name of the helper. * * @return string */ public function name(); }, (*81)


> [!TIP] > Check the [HELPERS][link-helpers] page for a list of available helpers. ### Adding filters to Parser By design, the filters under `FilterInterface` should be executed after parsing is completed by Parser. However, there may be scenarios that the body of a page must undergo a filter prior to its parsing process: ``` php namespace App\Filters; use Staticka\Filter\FilterInterface; class WorldFilter implements FilterInterface { public function filter($code) { return str_replace('Hello', 'World', $code); } }

``` php // index.php, (*82)

use App\Filters\WorldFilter;, (*83)

// ..., (*84)

// Replaces "Hello" string to "World" --- $parser->addFilter(new WorldFilter); // --------------------------------------, (*85)

// ..., (*86)


### Using the `Package` class There may be a requirement wherein `Staticka` must be built to any PHP application such as a static blog platform or a hybrid content management system. To achieve this, the `Package` and `System` classes may be used for the specified requirement: ``` php // index.php use Rougin\Slytherin\Container\Container; use Rougin\Slytherin\Integration\Configuration; use Staticka\Package; // Create paths such as "pages", "plates", and --- // "build" from "__DIR__ . '/app'" directory ----- $root = __DIR__ . '/app'; $app = new Package($root); $app->setPathsFromRooth(); // ----------------------------------------------- // Return the "System" instance from "Package" --- $container = new Container; $config = new Configuration; $result = $app->define($container, $config); /** @var \Staticka\System */ $app = $result->get(System::class); // -----------------------------------------------

For more information on how to implement this for new ideas and projects, kindly see the codebase of Console and Expresso respectively for their implementations., (*87)

Using the PageDepot class

Staticka also contains a PageDepot class for providing CRUD operations for pages:, (*88)

``` php // index.php, (*89)

use Staticka\Depots\PageDepot;, (*90)

// ..., (*91)

/** @var \Staticka\System $app */ $depot = new PageDepot($app);, (*92)


The specified depot has a functionality to create a new page based on provided payload: ``` php // index.php // ... $data = array('name' => 'Hello!'); $data['link'] = '/hello'; /** @var \Staticka\Page */ $page = $depot->create($data); // Return the unix timestamp as its identifier --- $id = $page->getId(); // -----------------------------------------------

[!NOTE] A page's identifier is specified by its timestamp (e.g., 20240101000000_hello.md returns a 1704067200 as its identifier)., (*93)

After the new page is created successfully, it can now be updated its details using update:, (*94)

``` php // index.php, (*95)

// ..., (*96)

// Return the "/hello" link --- echo $page->getLink(); // ----------------------------, (*97)

$data = array('link' => '/hello-world');, (*98)

/** @var \Staticka\Page */ $page = $depot->update($id, $data);, (*99)

// Return the "/hello-world" link --- echo $page->getLink(); // ----------------------------------, (*100)


To delete a specified page, the `delete` method can be used: ``` php // index.php // Will delete the file specified in the page --- $depot->delete($id); // ----------------------------------------------

Finding a specified page is also possible by its identifier, by link, or by name:, (*101)

``` php // index.php, (*102)

// The page can be found using its ID... --- $page = $depot->find(1704067200); // -----------------------------------------, (*103)

// ...or by the page's link... ------ $page = $depot->findByLink('/hello'); // ----------------------------------, (*104)

// ...or by its page name ----------- $page = $depot->findByName('Hello!'); // ----------------------------------, (*105)


`PageDepot` can also return the available pages from its source directory: ``` php // index.php /** @var \Staticka\Page[] */ $pages = $depot->get(); // Can also return pages as data --- $items = $depot->getAsData(); // ---------------------------------

[!NOTE] The word Depot is only a preference and it is best known as the Repository pattern., (*106)

Migrating to the v0.4.0 release

The new release for v0.4.0 will be having a backward compatibility break (BC break). With this, some functionalities from the earlier versions might not be working after upgrading. This was done to increase extensibility, simplicity and maintainbility. Staticka is also mentioned in my blog post:, (*107)

I also want to extend this plan to my personal packages as well like Staticka and Transcribe. With this, I will introduce backward compatibility breaks to them initially as it is hard to migrate their codebase due to minimal to no documentation being provided in its basic usage and its internals. As I checked their code, I realized that they are also over engineered, which is a mistake that I needed to atone for when updating my packages in the future., (*108)

Please see Pull Request #5 for the files that were removed or updated in this release and the UPGRADING page for the specified breaking changes., (*109)

Changelog

Please see CHANGELOG for more information what has changed recently., (*110)

Testing

The unit tests of Staticka can be run using the test command:, (*111)

bash $ composer test, (*112)

Credits

License

The MIT License (MIT). Please see LICENSE for more information., (*113)

The Versions

06/04 2018

dev-master

9999999-dev https://staticka.github.io

A simple and extensible static site generator.

  Sources   Download

MIT

The Requires

 

The Development Requires

generator simple static site php library static cms staticka

06/04 2018

v0.2.0

0.2.0.0 https://staticka.github.io

A simple and extensible static site generator.

  Sources   Download

MIT

The Requires

 

The Development Requires

generator simple static site php library staticka

04/04 2018

v0.1.0

0.1.0.0 https://staticka.github.io

A simple and extensible static site generator.

  Sources   Download

MIT

The Requires

 

The Development Requires

generator simple static site php library staticka