Browse Source

it's there!

master
Tsia 3 years ago
commit
5032fa8154
  1. 7
      .gitignore
  2. 21
      LICENSE
  3. 102
      README.md
  4. 18
      composer.json
  5. 350
      composer.lock
  6. 363
      index.php
  7. 4
      settings.php.dist
  8. 0
      static/.gitkeep
  9. 13
      static/example/css/fonts.css
  10. 51
      static/example/css/ie.css
  11. 30
      static/example/css/style.css
  12. BIN
      static/example/favicon.ico
  13. BIN
      static/example/fonts/FiraMono-Regular.woff2
  14. BIN
      static/example/fonts/FiraSans-Regular.woff2
  15. 2
      static/example/js/notjquery.js
  16. 0
      templates/.gitkeep
  17. 21
      templates/example/layout.twig
  18. 16
      templates/example/pages/index.twig
  19. 10
      templates/example/pages/posts/post1.ini
  20. 10
      templates/example/pages/posts/post1.twig
  21. 6
      templates/example/pages/posts/post2.ini
  22. 10
      templates/example/pages/posts/post2.twig
  23. 3
      templates/example/pages/posts/post3.ini
  24. 8
      templates/example/pages/posts/post3.twig
  25. 7
      templates/example/post.twig

7
.gitignore

@ -0,0 +1,7 @@
/vendor/
/current
/previous
/next
/versions/
!/versions/.gitkeep
/settings.php

21
LICENSE

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2018 tsia
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

102
README.md

@ -0,0 +1,102 @@
This is a Static Site Generator.
In many cases a CMS doesn't need to generate each page again and again for each request.
This is an attempt to generate Static HTML from Twig Templates.
# Setup
* `git clone`
* `composer install`
* `cp settings.php.dist settings.php`
# Config
Edit `settings.php` and change `BASE_PATH` accordingly.
Depending on your webserver, you can change `$redirectMethod` to one of the following:
* `REDIRECT_METHOD_NONE`
* `REDIRECT_METHOD_HTACCESS`
* `REDIRECT_METHOD_PHP`
* `REDIRECT_METHOD_HTML`
* `REDIRECT_METHOD_SYMLINK`
This will change the way, the user is redirected from `altSlugs` (see section "Advanced page features") to the primary URL of a page.
`REDIRECT_METHOD_HTACCESS` obviously will only work with Apache. `REDIRECT_METHOD_PHP` obviously will only work with a PHP-capable webserver.
`REDIRECT_METHOD_HTML` will generate HTML files that redirect the user via `<meta>` tags and JS. `REDIRECT_METHOD_SYMLINK` will just symlink the file so basically no redirect will happen.
Depending on your webserver, you can change `*contenttypeOverrideMethod` to one of the following:
* `CONTENTTYPE_OVERRIDE_METHOD_NONE`
* `CONTENTTYPE_OVERRIDE_METHOD_HTACCESS`
* `CONTENTTYPE_OVERRIDE_METHOD_PHP`
This will change the way, the content-type of pages is overridden. This is only required for example for RSS Feeds etc. where you want a different content-type than the one guessed by the webserver.
again: `CONTENTTYPE_OVERRIDE_METHOD_HTACCESS` obviously will only work with Apache. `CONTENTTYPE_OVERRIDE_METHOD_PHP` obviously will only work with a PHP-capable webserver.
there are some more constants that can be set but usually this is not required.
# Usage
!(https://dev.tsia.de/htmlengine/example.png)
run `./index.php --help` for a brief list of commands:
```
Usage:
--run render and switch to new version
--no-switch render and don't switch to new version
--switchonly don't render and only switch to new version (use after --no-switch)
--rollback switch to previous version
--switch-to VER switch to version VER
--list-versions list available versions
```
`./index.php --run` will generate a folder structure, render all templates and place the HTML into the appropriate folder.
by default the latest generated files will be accessible via the symlink `versions/current`. Your webserver should use that symlink as webroot.
# Versions
every time you run `./index.php --run`, a new version will be created in the `versions`-folder. you can list them with `./index.php --list-versions` to see what version is currently active.
you can switch versions with `./index.php --switch-to` or `./index.php --switchonly`.
You can use `./index.php --no-switch` to generate the new templates but not switch them to `current`. Instead a symlink `next` will be created. use this to preview the new site for example at a different subdomain before switching it to production.
In case something goes wrong, you can use `./index.php --rollback` to switch to the previous version. Note: only one rollback at a time is supported. to switch further, use `./index.php --switch-to ...`
# Creating pages
rendering is done by just parsing all files under `templates/THEME/pages/*.twig` with twig. the url is inferred from the file name of the template.
`templates/THEME/pages/post1.twig` will be available at the URL `/post`.
you can use sub-folders inside of `templates/THEME/pages/` if you like. they don't change the behaviour in any way.
# Advanced page features
if a ini-file with the same name as the template exists, it is read. example file:
```
[settings]
slug = "faq"
enabled = 1
[altSlugs]
0 = "help"
[variables]
headline = "FAQ & Help"
```
* `slug`: this will be the URL
* `enabled`: if not true, the page won't be rendered
* `[altSlugs]`: list of alternative URLs. Users will be redirected to the primary `slug`
* `[variables]`: those variables will be available in the template
see example templates for more details how to use twig template extension, blocks and variables to re-use templates.
# special twig functions
use the special twig function `getPageContent($slug, $block = 'entry')` to get rendered page contents. This can be used to embed single blocks of a page somewhere else.
use the special twig function `getPageMeta($path, $sort, $limit, $desc)` to get a list of page metadata from their ini files. This can be used to create a listing of pages for example with title, link etc.
use `$path` to limit the list to only those templates inside a specific template folder.
use `$sort` to sort the pages by a specific item in their ini files.
use `$limit` to limit the amount of pages to fetch.
use `$desc = false` to sort them ascending instead of decending.
# advanced settings
`define('DIR_MODE', 0755)` permissions of newly created folders.
`define('OUTPUT_DIR', __DIR__ . '/versions')` the folder where to put the rendered pages. no trailing slash.
`define('BASE_PATH', 'http://localhost/')` the base path used to generate absolute URLs in templates and redirects. don't forget the trailing slash.
`define('THEME', 'example')` the name of the theme to use.
`define('STATIC_FOLDER', 'static')` the name of the folder where static files like css are copied to.

18
composer.json

@ -0,0 +1,18 @@
{
"name": "tsia/htmlengine",
"type": "project",
"require-dev": {
"kint-php/kint": "^2.2"
},
"authors": [
{
"name": "Thomas Tsiakalakis",
"email": "mail@tsia.de"
}
],
"require": {
"twig/twig": "^2.4",
"aptoma/twig-markdown": "^3.0",
"michelf/php-markdown": "~1.3"
}
}

350
composer.lock

@ -0,0 +1,350 @@
{
"_readme": [
"This file locks the dependencies of your project to a known state",
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
"content-hash": "1151dbf084092da68d7cf267bc8b3d50",
"packages": [
{
"name": "aptoma/twig-markdown",
"version": "3.0.0",
"source": {
"type": "git",
"url": "https://github.com/aptoma/twig-markdown.git",
"reference": "624ccf53002e6786a17789a98d08e3d5e662517d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/aptoma/twig-markdown/zipball/624ccf53002e6786a17789a98d08e3d5e662517d",
"reference": "624ccf53002e6786a17789a98d08e3d5e662517d",
"shasum": ""
},
"require": {
"php": "^7.0",
"twig/twig": "^2.0"
},
"require-dev": {
"codeclimate/php-test-reporter": "dev-master",
"erusev/parsedown": "^1.6",
"knplabs/github-api": "~1.4",
"league/commonmark": "~0.5",
"michelf/php-markdown": "~1",
"phpunit/phpunit": "~6.0||~5.0"
},
"suggest": {
"knplabs/github-api": "Needed for using GitHub's Markdown engine provided through their API.",
"michelf/php-markdown": "Original Markdown engine with MarkdownExtra."
},
"type": "library",
"autoload": {
"psr-0": {
"Aptoma": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Joris Berthelot",
"email": "joris@berthelot.tel"
},
{
"name": "Gunnar Lium",
"email": "gunnar@aptoma.com"
}
],
"description": "Twig extension to work with Markdown content",
"keywords": [
"markdown",
"twig"
],
"time": "2017-06-23T14:35:41+00:00"
},
{
"name": "michelf/php-markdown",
"version": "1.8.0",
"source": {
"type": "git",
"url": "https://github.com/michelf/php-markdown.git",
"reference": "01ab082b355bf188d907b9929cd99b2923053495"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/michelf/php-markdown/zipball/01ab082b355bf188d907b9929cd99b2923053495",
"reference": "01ab082b355bf188d907b9929cd99b2923053495",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Michelf\\": "Michelf/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Michel Fortin",
"email": "michel.fortin@michelf.ca",
"homepage": "https://michelf.ca/",
"role": "Developer"
},
{
"name": "John Gruber",
"homepage": "https://daringfireball.net/"
}
],
"description": "PHP Markdown",
"homepage": "https://michelf.ca/projects/php-markdown/",
"keywords": [
"markdown"
],
"time": "2018-01-15T00:49:33+00:00"
},
{
"name": "symfony/polyfill-mbstring",
"version": "v1.7.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "78be803ce01e55d3491c1397cf1c64beb9c1b63b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/78be803ce01e55d3491c1397cf1c64beb9c1b63b",
"reference": "78be803ce01e55d3491c1397cf1c64beb9c1b63b",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"suggest": {
"ext-mbstring": "For best performance"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.7-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Polyfill\\Mbstring\\": ""
},
"files": [
"bootstrap.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for the Mbstring extension",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"mbstring",
"polyfill",
"portable",
"shim"
],
"time": "2018-01-30T19:27:44+00:00"
},
{
"name": "twig/twig",
"version": "v2.4.6",
"source": {
"type": "git",
"url": "https://github.com/twigphp/Twig.git",
"reference": "d2117ec118c1ff3d28ccddca8212d82787a4809f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/twigphp/Twig/zipball/d2117ec118c1ff3d28ccddca8212d82787a4809f",
"reference": "d2117ec118c1ff3d28ccddca8212d82787a4809f",
"shasum": ""
},
"require": {
"php": "^7.0",
"symfony/polyfill-mbstring": "~1.0"
},
"require-dev": {
"psr/container": "^1.0",
"symfony/debug": "~2.7",
"symfony/phpunit-bridge": "~3.3@dev"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.4-dev"
}
},
"autoload": {
"psr-0": {
"Twig_": "lib/"
},
"psr-4": {
"Twig\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com",
"homepage": "http://fabien.potencier.org",
"role": "Lead Developer"
},
{
"name": "Armin Ronacher",
"email": "armin.ronacher@active-4.com",
"role": "Project Founder"
},
{
"name": "Twig Team",
"homepage": "http://twig.sensiolabs.org/contributors",
"role": "Contributors"
}
],
"description": "Twig, the flexible, fast, and secure template language for PHP",
"homepage": "http://twig.sensiolabs.org",
"keywords": [
"templating"
],
"time": "2018-03-03T16:23:01+00:00"
}
],
"packages-dev": [
{
"name": "erusev/parsedown",
"version": "1.7.0",
"source": {
"type": "git",
"url": "https://github.com/erusev/parsedown.git",
"reference": "6678d59be48c4be64eaca6ce70bea48a09488cc2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/erusev/parsedown/zipball/6678d59be48c4be64eaca6ce70bea48a09488cc2",
"reference": "6678d59be48c4be64eaca6ce70bea48a09488cc2",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"require-dev": {
"phpunit/phpunit": "^4.8.35"
},
"type": "library",
"autoload": {
"psr-0": {
"Parsedown": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Emanuil Rusev",
"email": "hello@erusev.com",
"homepage": "http://erusev.com"
}
],
"description": "Parser for Markdown.",
"homepage": "http://parsedown.org",
"keywords": [
"markdown",
"parser"
],
"time": "2018-02-28T11:41:37+00:00"
},
{
"name": "kint-php/kint",
"version": "2.2",
"source": {
"type": "git",
"url": "https://github.com/kint-php/kint.git",
"reference": "b091715eadaf6e1a7ef927f3e81d1004611d2aea"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/kint-php/kint/zipball/b091715eadaf6e1a7ef927f3e81d1004611d2aea",
"reference": "b091715eadaf6e1a7ef927f3e81d1004611d2aea",
"shasum": ""
},
"require": {
"php": ">=5.1.2"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^2.0",
"phpunit/phpunit": "^4.0",
"symfony/finder": "^2.6"
},
"type": "library",
"autoload": {
"files": [
"init.php"
],
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Rokas Šleinius",
"homepage": "https://github.com/raveren"
},
{
"name": "Jonathan Vollebregt",
"homepage": "https://github.com/jnvsor"
},
{
"name": "Contributors",
"homepage": "https://github.com/kint-php/kint/graphs/contributors"
}
],
"description": "Kint - debugging tool for PHP developers",
"homepage": "https://kint-php.github.io/kint/",
"keywords": [
"debug",
"kint",
"php"
],
"time": "2017-09-06T17:46:03+00:00"
}
],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
"prefer-stable": false,
"prefer-lowest": false,
"platform": [],
"platform-dev": []
}

363
index.php

@ -0,0 +1,363 @@
#!/usr/bin/env php
<?php
use Aptoma\Twig\Extension\MarkdownExtension;
use Aptoma\Twig\Extension\MarkdownEngine;
if (PHP_SAPI !== 'cli') {
die();
}
require __DIR__ . '/vendor/autoload.php';
if(in_array('--help', $argv) || in_array('-h', $argv) || !in_array('--run', $argv)){
echo 'Usage:' . PHP_EOL;
echo ' --run render and switch to new version' . PHP_EOL;
echo ' --no-switch render and don\'t switch to new version' . PHP_EOL;
echo ' --switchonly don\'t render and only switch to new version (use after --no-switch)' . PHP_EOL;
echo ' --rollback switch to previous version' . PHP_EOL;
echo ' --switch-to VER switch to version VER' . PHP_EOL;
echo ' --list-versions list available versions' . PHP_EOL;
die();
}
define('REDIRECT_METHOD_NONE', 0);
define('REDIRECT_METHOD_HTACCESS', 1);
define('REDIRECT_METHOD_PHP', 2);
define('REDIRECT_METHOD_HTML', 3);
define('REDIRECT_METHOD_SYMLINK', 4);
define('CONTENTTYPE_OVERRIDE_METHOD_NONE', 0);
define('CONTENTTYPE_OVERRIDE_METHOD_HTACCESS', 1);
define('CONTENTTYPE_OVERRIDE_METHOD_PHP', 2);
$redirectMethod = REDIRECT_METHOD_PHP;
$contenttypeOverrideMethod = CONTENTTYPE_OVERRIDE_METHOD_PHP;
require __DIR__ . '/settings.php';
if(! defined('DIR_MODE')){
define('DIR_MODE', 0755);
}
if(! defined('OUTPUT_DIR')){
define('OUTPUT_DIR', __DIR__ . '/versions');
}
define('VERSION_DIR', OUTPUT_DIR . '/' . date('Y-m-d_H-i-s'));
if(! defined('BASE_PATH')){
define('BASE_PATH', 'http://localhost/');
}
if(! defined('THEME')){
define('THEME', 'example');
}
if(! defined('STATIC_FOLDER')){
define('STATIC_FOLDER', 'static');
}
if(!file_exists(__DIR__ . '/templates/' . THEME)){
throw new Exception('Templates folder not found.');
}
if(!file_exists(__DIR__ . '/static/' . THEME)){
throw new Exception('Static folder not found.');
}
$defaultParams = [
'settings' => ['enabled' => true, 'markdown' => false],
'altSlugs' => [],
'variables' => [],
];
if(in_array('--switchonly', $argv)){
if(!file_exists('next')){
throw new Exception('could not switch version. no previous version found.');
}
echo 'switching version' . PHP_EOL;
if(is_link('current')){
rename('current', 'previous');
}
if(!file_exists('current')) {
rename('next', 'current');
}else{
throw new Exceptio('could not switch version. file exists.');
}
die('done.');
}
if(in_array('--rollback', $argv)){
if(!file_exists('previous')){
throw new Exception('could not roll back. no previous version found.');
}
if(is_link('current')){
unlink('current');
}
if(!file_exists('current')){
rename('previous', 'current');
}else{
throw new Exception('could not roll back. file exists.');
}
die('done.');
}
if(in_array('--switch-to', $argv)){
$targetVersion = array_pop($argv);
if(!is_dir(OUTPUT_DIR . '/' . $targetVersion)){
throw new Exception('could not switch version. version ' . $targetVersion . ' not found.');
}
if(is_link('current')){
unlink('current');
}
if(!file_exists('current')){
symlink(OUTPUT_DIR . '/' . $targetVersion, 'current');
copyr(__DIR__ . '/static/' . THEME, 'current/' . STATIC_FOLDER);
}else{
throw new Exception('could not switch version. file exists.');
}
die('done.');
}
if(in_array('--list-versions', $argv)){
$versions = glob(OUTPUT_DIR . '/*');
foreach($versions as $version){
if(is_dir($version)){
echo basename($version);
if(realpath('current') == $version) {
echo ' (current)';
} else if (realpath('previous') == $version) {
echo ' (previous)';
} else if (realpath('next') == $version) {
echo ' (next)';
}
echo PHP_EOL;
}
}
die('done.');
}
if($argc > 2 || ($argc > 1 && $argv[1] !== '--no-switch' && $argv[1] !== '--run')){
throw new Exception('Invalid Argument');
}
$loader = new Twig_Loader_Filesystem(__DIR__ . '/templates/' . THEME);
$twig = new Twig_Environment($loader, ['debug' => true]);
$markdownengine = new MarkdownEngine\MichelfMarkdownEngine();
$twig->addExtension(new MarkdownExtension($markdownengine));
$function = new Twig_Function('getPageMeta', function ($path = '/', $sort = null, $limit = 0, $desc = true) use ($defaultParams) {
$tplpath = __DIR__ . '/templates/' . THEME . '/pages' . $path;
if(!file_exists($tplpath)){ throw new Exception('Page ' . $path . ' not found.'); }
$dir_iterator = new RecursiveDirectoryIterator($tplpath);
$iterator = new RecursiveIteratorIterator($dir_iterator);
$sortedresult = [];
foreach($iterator as $file){
if(!$file->isFile() || $file->getExtension() !== 'twig'){
continue;
}
$settingsfile = preg_replace('/\\.twig$/', '.ini', $file->getRealPath());
if(file_exists($settingsfile)){
$data = parse_ini_file($settingsfile, true);
}else{
$data = $defaultParams;
}
if(empty($data['settings']['slug'])){
$defaultslug = getDefaultSlug($file);
$data['settings']['slug'] = $defaultslug;
}
$keyparts = explode('.', $sort);
$subdata = $keyparts[0];
$key = $keyparts[1];
if(! array_key_exists($key, $data[$subdata])){
$sortedresult[] = $data;
}else{
$sortedresult[$data[$subdata][$key]] = $data;
}
}
if($desc){
$sortedresult = array_reverse($sortedresult);
}
$result = [];
$counter = 0;
foreach($sortedresult as $item){
if($limit == 0 || $counter < $limit){
$result[$counter] = $item;
}
$counter++;
}
return $result;
});
$twig->addFunction($function);
$function = new Twig_Function('dump', function ($input) {
Kint::$enabled_mode = Kint::MODE_RICH;
return d($input);
});
$twig->addFunction($function);
$function = new Twig_Function('getPageContent', function ($slug, $block = 'entry') use ($twig, $defaultParams) {
$dir_iterator = new RecursiveDirectoryIterator(__DIR__ . '/templates/' . THEME . '/pages/');
$iterator = new RecursiveIteratorIterator($dir_iterator);
foreach($iterator as $templatefile){
if(!$templatefile->isFile() || $templatefile->getExtension() !== 'twig'){
continue;
}
$params = readParams($templatefile, $defaultParams);
$defaultslug = getDefaultSlug($templatefile);
$currentslug = empty($params['settings']['slug']) ? $defaultslug : $params['settings']['slug'];
if($currentslug !== $slug || $params['settings']['enabled'] != true){
continue;
}
$params['settings']['slug'] = $currentslug;
$params['basepath'] = BASE_PATH;
$template = file_get_contents($templatefile->getRealPath());
return $twig->createTemplate($template)->renderBlock($block, $params);
}
throw new Exception('Page ' . $slug . ' not found.');
});
$twig->addFunction($function);
echo 'creating version folder ' . VERSION_DIR . PHP_EOL;
mkdir(VERSION_DIR);
$dir_iterator = new RecursiveDirectoryIterator(__DIR__ . '/templates/' . THEME . '/pages/');
$iterator = new RecursiveIteratorIterator($dir_iterator);
foreach ($iterator as $templatefile) {
if(!$templatefile->isFile() || $templatefile->getExtension() !== 'twig'){
continue;
}
echo 'rendering ' . $templatefile->getRealPath() . PHP_EOL;
$template = file_get_contents($templatefile->getRealPath());
$params = readParams($templatefile, $defaultParams);
if($params['settings']['enabled'] != true){
continue;
}
$defaultslug = getDefaultSlug($templatefile);
$slug = empty($params['settings']['slug']) ? $defaultslug : $params['settings']['slug'];
handleAltSlugs($params['altSlugs'], $slug, $redirectMethod);
$params['settings']['slug'] = $slug;
$params['basepath'] = BASE_PATH;
$twigTemplate = $twig->createTemplate($template);
$output = $twigTemplate->render($params);
if($slug === 'index'){
$outputpath = VERSION_DIR;
}else{
$outputpath = VERSION_DIR . '/' . $slug;
}
mkdirIfNotExists($outputpath);
if(array_key_exists('contenttype', $params['settings'])){
handleContentTypeOverride($slug, $params['settings']['contenttype'], $contenttypeOverrideMethod);
}
file_put_contents($outputpath . '/index.html', $output);
}
if(in_array('--no-switch', $argv)){
echo 'not switching version.' . PHP_EOL;
if(is_link('next')){
unlink('next');
}
if(!file_exists('next')) {
symlink(VERSION_DIR, 'next');
copyr(__DIR__ . '/static/' . THEME, 'next/' . STATIC_FOLDER);
}else{
throw new Exception('could not create next version. file exists.');
}
}else{
echo 'switching version' . PHP_EOL;
if(is_link('current')){
rename('current', 'previous');
}
if(!file_exists('current')) {
symlink(VERSION_DIR, 'current');
copyr(__DIR__ . '/static/' . THEME, 'current/' . STATIC_FOLDER);
}else{
throw new Exception('could not switch version. file exists.');
}
}
echo 'done.' . PHP_EOL;
function readParams($templatefile, $defaultParams){
$settingsfile = preg_replace('/\\.twig$/', '.ini', $templatefile->getRealPath());
$params = [];
if(file_exists($settingsfile)){
$params = parse_ini_file($settingsfile, true);
}
$params = array_merge($defaultParams, $params);
$params['settings'] = array_merge($defaultParams['settings'], $params['settings']);
return $params;
}
function getDefaultSlug($templatefile){
if(is_object($templatefile)){
$tempaltefile = $templatefile->getRealPath();
}
$regex = '/^' . preg_quote(__DIR__ . '/templates/' . THEME . '/pages/', '/') . '(.*)\\.twig$/';
$result = preg_replace($regex, '$1', $templatefile);
return $result;
}
function handleAltSlugs($slugs, $target, $method) {
foreach($slugs as $slug) {
echo " " . $slug . PHP_EOL;
$output = VERSION_DIR . '/' . $slug;
switch($method){
case REDIRECT_METHOD_HTACCESS:
file_put_contents(VERSION_DIR . '/.htaccess', 'Redirect 301 ' . BASE_PATH . $slug . ' ' . BASE_PATH . $target . PHP_EOL, FILE_APPEND);
break;
case REDIRECT_METHOD_PHP:
mkdirIfNotExists($output);
file_put_contents($output . '/index.php', '<?php header("HTTP/1.1 301 Moved Permanently"); header("Location: ' . BASE_PATH . $target . '"); ?>');
break;
case REDIRECT_METHOD_HTML:
mkdirIfNotExists($output);
file_put_contents($output . '/index.html', '<html><head><meta http-equiv="refresh" content="0; url=' . BASE_PATH . $target . '">
<script>window.location.href="' . BASE_PATH . $target . '"</script></head>
<body>Redirecting to <a href="' . BASE_PATH . $target . '">' . htmlentities(BASE_PATH . $target) . '</a>...</body></html>');
break;
case REDIRECT_METHOD_SYMLINK:
mkdirIfNotExists(dirname($output));
link($output . '/index.html', VERSION_DIR . '/' . $target);
break;
}
}
}
function handleContentTypeOverride($slug, $contenttype, $method) {
$output = VERSION_DIR . '/' . $slug;
switch($method){
case CONTENTTYPE_OVERRIDE_METHOD_HTACCESS:
$output .= '/.htaccess';
file_put_contents($output, 'AddType text/xml .html' . PHP_EOL);
break;
case CONTENTTYPE_OVERRIDE_METHOD_PHP:
$output .= '/index.php';
file_put_contents($output, '<?php header("Content-Type: ' . $contenttype . '"); readfile("index.html"); ?>');
break;
}
}
function mkdirIfNotExists($path) {
if(!file_exists($path)){
mkdir($path, DIR_MODE, true);
}
}
function copyr($source, $destination) {
mkdirIfNotExists($destination);
$dir_iterator = new RecursiveDirectoryIterator($source, RecursiveDirectoryIterator::SKIP_DOTS);
$iterator = new RecursiveIteratorIterator($dir_iterator, RecursiveIteratorIterator::SELF_FIRST);
foreach($iterator as $item) {
if ($item->isDir()){
mkdirIfNotExists($destination . '/' . $iterator->getSubPathName());
} else {
copy($item, $destination . '/' . $iterator->getSubPathName());
}
}
}

4
settings.php.dist

@ -0,0 +1,4 @@
<?php
$redirectMethod = REDIRECT_METHOD_HTML;
define('BASE_PATH', 'http://localhost/');
define('THEME', 'example');

0
static/.gitkeep

13
static/example/css/fonts.css

@ -0,0 +1,13 @@
@font-face {
font-family: 'Fira Sans';
font-style: normal;
font-weight: 400;
src: local('Fira Sans Regular'), local('FiraSans-Regular'), url(../fonts/FiraSans-Regular.woff2) format('woff2');
}
@font-face {
font-family: 'Fira Mono';
font-style: normal;
font-weight: 400;
src: local('Fira Mono Regular'), local('FiraMono-Regular'), url(../fonts/FiraMono-Regular.woff2) format('woff2');
}

51
static/example/css/ie.css

@ -0,0 +1,51 @@
@charset 'utf-8';
/* These rules apply to Internet Explorer 7 and lower */
#header,
#footer {
zoom: 1;
}
#header .hr {
position: absolute;
top: 130px;
left: 53px;
}
#main {
margin-top: -75px;
}
#main .content ol.commentlist li {
margin-left: -16px;
list-style: none;
}
/* These rules apply to Internet Explorer 6 and lower */
* html .content .menu li a {
float: left;
}
* html #col2-right {
margin-right: -20px;
overflow: hidden;
}
* html #footer {
border-bottom: 80px solid #fff;
}
* html #col3-middle {
margin-right: -20px;
overflow: hidden;
}
* html #col3-right {
width: 160px;
float: right;
display: inline;
margin-right: -10px;
}

30
static/example/css/style.css

@ -0,0 +1,30 @@
body {
font-family: 'Fira Sans', 'sans-serif';
}
pre, code {
font-family: 'Fira Mono', 'monospace';
}
pre {
border: 1px solid gray;
border-radius: 3px;
background-color: lightgray;
padding: 5px;
}
blockquote {
margin: 16px 40px 16px 5px;
padding-left: 35px;
border-left: 20px solid lightgrey;
}
.wrapper {
max-width: 1000px;
margin: auto;
}
a:link, a:active, a:hover, a:visited {
color: black;
text-decoration: underline;
}

BIN
static/example/favicon.ico

BIN
static/example/fonts/FiraMono-Regular.woff2

BIN
static/example/fonts/FiraSans-Regular.woff2

2
static/example/js/notjquery.js

@ -0,0 +1,2 @@
'use strict';
console.log('this is definitely not jQuery.');

0
templates/.gitkeep

21
templates/example/layout.twig

@ -0,0 +1,21 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="de" lang="de">
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>HTMLEngine</title>
<link href="{{ basepath }}static/css/style.css" rel="stylesheet" media="screen" type="text/css">
<link rel="shortcut icon" href="{{ basepath }}static/favicon.ico" type="image/x-icon">
<script src="{{ basepath }}static/js/notjquery.js"></script>
<!--[if lte IE 7]>
<link href="{{ basepath }}static/css/ie.css" rel="stylesheet" media="screen" type="text/css" />
<![endif]-->
<link rel="index" title="HTMLEngine" href="{{ basepath }}">
</head>
<body>
<div class="wrapper">
<h1><a href="{{ basepath }}">My Blog or something</a></h1>
{% block content %}
{% endblock %}
</div>
</body>
</html>

16
templates/example/pages/index.twig

@ -0,0 +1,16 @@
{% extends 'layout.twig' %}
{% block content %}
<div id="listing">
{% set pages = getPageMeta('/posts', 'settings.slug') %}
{% for page in pages %}
<div class="post">
<small>{{ page.variables.date }}</small>
<h2><a href="{{ basepath }}{{ page.settings.slug }}">{{ page.variables.title }}</a></h2>
<p>{{ getPageContent(page.settings.slug)|striptags|slice(0, 120) }}
{%- if getPageContent(page.settings.slug)|striptags|length > 120 %}&hellip;{% endif %}</p>
<hr>
</div>
{% endfor %}
</div>
{% endblock %}

10
templates/example/pages/posts/post1.ini

@ -0,0 +1,10 @@
[settings]
slug = "the-first-post"
enabled = 1
[altSlugs]
0 = "post-1"
[variables]
title = "First Post"
date = "21.10.2015"

10
templates/example/pages/posts/post1.twig

@ -0,0 +1,10 @@
{% extends 'post.twig' %}
{% block entry %}
{% markdown %}
this is the first post.
* it can
* have bullet
* points
{% endmarkdown %}
{% endblock %}

6
templates/example/pages/posts/post2.ini

@ -0,0 +1,6 @@
[settings]
enabled = 1
[variables]
title = "Post No. 2"
date = "22.10.2015"

10
templates/example/pages/posts/post2.twig

@ -0,0 +1,10 @@
{% extends 'post.twig' %}
{% block entry %}
{% markdown %}
this is the second post.
```
it can have code blocks and stuff.
```
{% endmarkdown %}
{% endblock %}

3
templates/example/pages/posts/post3.ini

@ -0,0 +1,3 @@
[variables]
title = "3rd Post"
date = "23.10.2015"

8
templates/example/pages/posts/post3.twig

@ -0,0 +1,8 @@
{% extends 'post.twig' %}
{% block entry %}
{% markdown %}
this is the third post.
> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec interdum feugiat nunc ac fringilla. Praesent consequat nec velit a finibus. Nulla placerat nibh ac orci blandit lacinia. Donec pellentesque sed lectus et posuere. Aenean sit amet fringilla libero. Phasellus volutpat fringilla scelerisque. Vivamus id dolor ullamcorper libero malesuada condimentum. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Proin at tempus neque.
{% endmarkdown %}
{% endblock %}

7
templates/example/post.twig

@ -0,0 +1,7 @@
{% extends 'layout.twig' %}
{% block content %}
<small>{{ variables.date }}</small>
<h2>{{ variables.title }}</h2>
{% block entry %}
{% endblock %}
{% endblock %}
Loading…
Cancel
Save