소스 검색

Version 1.0.0

Sebastian 8 년 전
커밋
f39d60b60b
100개의 변경된 파일6834개의 추가작업 그리고 0개의 파일을 삭제
  1. 26 0
      .htaccess
  2. 26 0
      composer.json
  3. 662 0
      composer.lock
  4. 20 0
      content/0_typemill/01-use-cases.md
  5. 22 0
      content/0_typemill/03-features.md
  6. 13 0
      content/0_typemill/09-roadmap.md
  7. BIN
      content/0_typemill/bnmc-bolachas-02.png
  8. 3 0
      content/0_typemill/index.md
  9. 15 0
      content/1_getting-started/00-system-requirements.md
  10. 68 0
      content/1_getting-started/01-installation.md
  11. 44 0
      content/1_getting-started/02-settings.md
  12. 3 0
      content/1_getting-started/index.md
  13. 11 0
      content/2_for-writers/00-quick-start.md
  14. 156 0
      content/2_for-writers/02-mardown.md
  15. 19 0
      content/2_for-writers/10-naming-files-and-folders.md
  16. 5 0
      content/2_for-writers/30-folder-structure.md
  17. 3 0
      content/2_for-writers/index.md
  18. 40 0
      content/3_for-developers/01-quick-start.md
  19. 208 0
      content/3_for-developers/03-twig.md
  20. 38 0
      content/3_for-developers/04-theme-structure.md
  21. 7 0
      content/3_for-developers/05-theme-variables/05-content.md
  22. 9 0
      content/3_for-developers/05-theme-variables/08-description.md
  23. 302 0
      content/3_for-developers/05-theme-variables/10-item.md
  24. 11 0
      content/3_for-developers/05-theme-variables/15-breadcrumb.md
  25. 102 0
      content/3_for-developers/05-theme-variables/25-navigation.md
  26. 62 0
      content/3_for-developers/05-theme-variables/30-settings.md
  27. 3 0
      content/3_for-developers/05-theme-variables/index.md
  28. 3 0
      content/3_for-developers/index.md
  29. 16 0
      content/4_info/01-release-notes.md
  30. 16 0
      content/4_info/05-usage-and-licence.md
  31. 12 0
      content/4_info/10-Imprint-and-privacy.md
  32. 100 0
      content/4_info/15_markdown-test.md
  33. 3 0
      content/4_info/index.md
  34. 2 0
      content/index.md
  35. 9 0
      index.php
  36. 7 0
      licence.md
  37. 50 0
      readme.md
  38. 6 0
      settings/settings.yaml.example
  39. 23 0
      system/Controllers/Controller.php
  40. 132 0
      system/Controllers/PageController.php
  41. 138 0
      system/Controllers/SetupController.php
  42. 81 0
      system/Models/Cache.php
  43. 274 0
      system/Models/Folder.php
  44. 28 0
      system/Models/Helpers.php
  45. 7 0
      system/Routes/api.php
  46. 13 0
      system/Routes/web.php
  47. 461 0
      system/author/css/normalize.css
  48. 231 0
      system/author/css/style.css
  49. 18 0
      system/author/layout.twig
  50. 74 0
      system/author/setup.twig
  51. 17 0
      system/author/welcome.twig
  52. 7 0
      system/autoload.php
  53. 23 0
      system/settings.php
  54. 77 0
      system/system.php
  55. 7 0
      system/vendor/autoload.php
  56. 445 0
      system/vendor/composer/ClassLoader.php
  57. 21 0
      system/vendor/composer/LICENSE
  58. 9 0
      system/vendor/composer/autoload_classmap.php
  59. 10 0
      system/vendor/composer/autoload_files.php
  60. 14 0
      system/vendor/composer/autoload_namespaces.php
  61. 18 0
      system/vendor/composer/autoload_psr4.php
  62. 70 0
      system/vendor/composer/autoload_real.php
  63. 117 0
      system/vendor/composer/autoload_static.php
  64. 667 0
      system/vendor/composer/installed.json
  65. 3 0
      system/vendor/container-interop/container-interop/.gitignore
  66. 20 0
      system/vendor/container-interop/container-interop/LICENSE
  67. 148 0
      system/vendor/container-interop/container-interop/README.md
  68. 15 0
      system/vendor/container-interop/container-interop/composer.json
  69. 114 0
      system/vendor/container-interop/container-interop/docs/ContainerInterface-meta.md
  70. 158 0
      system/vendor/container-interop/container-interop/docs/ContainerInterface.md
  71. 259 0
      system/vendor/container-interop/container-interop/docs/Delegate-lookup-meta.md
  72. 60 0
      system/vendor/container-interop/container-interop/docs/Delegate-lookup.md
  73. BIN
      system/vendor/container-interop/container-interop/docs/images/interoperating_containers.png
  74. BIN
      system/vendor/container-interop/container-interop/docs/images/priority.png
  75. BIN
      system/vendor/container-interop/container-interop/docs/images/side_by_side_containers.png
  76. 15 0
      system/vendor/container-interop/container-interop/src/Interop/Container/ContainerInterface.php
  77. 15 0
      system/vendor/container-interop/container-interop/src/Interop/Container/Exception/ContainerException.php
  78. 15 0
      system/vendor/container-interop/container-interop/src/Interop/Container/Exception/NotFoundException.php
  79. 1 0
      system/vendor/erusev/parsedown
  80. 1 0
      system/vendor/erusev/parsedown-extra
  81. 1 0
      system/vendor/jbroadway/urlify
  82. 5 0
      system/vendor/nikic/fast-route/.gitignore
  83. 1 0
      system/vendor/nikic/fast-route/.hhconfig
  84. 12 0
      system/vendor/nikic/fast-route/.travis.yml
  85. 126 0
      system/vendor/nikic/fast-route/FastRoute.hhi
  86. 31 0
      system/vendor/nikic/fast-route/LICENSE
  87. 313 0
      system/vendor/nikic/fast-route/README.md
  88. 21 0
      system/vendor/nikic/fast-route/composer.json
  89. 24 0
      system/vendor/nikic/fast-route/phpunit.xml
  90. 6 0
      system/vendor/nikic/fast-route/src/BadRouteException.php
  91. 25 0
      system/vendor/nikic/fast-route/src/DataGenerator.php
  92. 28 0
      system/vendor/nikic/fast-route/src/DataGenerator/CharCountBased.php
  93. 28 0
      system/vendor/nikic/fast-route/src/DataGenerator/GroupCountBased.php
  94. 25 0
      system/vendor/nikic/fast-route/src/DataGenerator/GroupPosBased.php
  95. 25 0
      system/vendor/nikic/fast-route/src/DataGenerator/MarkBased.php
  96. 144 0
      system/vendor/nikic/fast-route/src/DataGenerator/RegexBasedAbstract.php
  97. 25 0
      system/vendor/nikic/fast-route/src/Dispatcher.php
  98. 28 0
      system/vendor/nikic/fast-route/src/Dispatcher/CharCountBased.php
  99. 28 0
      system/vendor/nikic/fast-route/src/Dispatcher/GroupCountBased.php
  100. 30 0
      system/vendor/nikic/fast-route/src/Dispatcher/GroupPosBased.php

+ 26 - 0
.htaccess

@@ -0,0 +1,26 @@
+RewriteEngine On
+
+# If your homepage is http://yourdomain.com/yoursite
+# Set the RewriteBase to:
+# RewriteBase /yoursite
+
+# In some environements, an empty RewriteBase is required:
+# RewriteBase /
+
+# Protect your system files from prying eyes
+RewriteRule ^(system\/author\/) - [L]
+RewriteRule ^(system) - [F,L]
+RewriteRule ^(content) - [F,L]
+RewriteRule ^(.*)?\.yml$ - [F,L]
+Rewriterule ^(.*)?\.yaml$ - [F,L]
+RewriteRule ^(.*/)?\.git+ - [F,L]
+
+# Use this to redirect www to non-wwww on apache servers
+RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
+RewriteRule ^(.*)$ http://%1/$1 [R=301,L]
+
+# Remove the index.php
+RewriteCond %{REQUEST_URI} !^/index\.php
+RewriteCond %{REQUEST_FILENAME} !-f
+RewriteCond %{REQUEST_FILENAME} !-d
+RewriteRule ^ index.php [QSA,L]

+ 26 - 0
composer.json

@@ -0,0 +1,26 @@
+{
+    "name": "trendschau/writeitdown",
+    "type": "project",
+    "description": "A crazy simple tool to create web-documentations and online manuals with markdown files.",
+    "keywords": ["documentations","manuals","flat-file","Markdown","php"],
+    "homepage": "http://writeitdown.net",
+    "license": "MIT",
+    "config": {
+        "vendor-dir": "system/vendor"
+    },
+    "require": {
+        "slim/slim": "^3.7",
+		"twig/twig": "^1.18",		
+		"slim/twig-view": "dev-master",
+		"slim/flash": "dev-master",
+        "symfony/yaml": "~2.8",
+		"erusev/parsedown": "~1.4",
+		"erusev/parsedown-extra": "dev-master",
+		"jbroadway/urlify": "dev-master"
+    },
+	"autoload": {
+		"psr-4": {
+			"System\\": "system"
+		}
+	}
+}

+ 662 - 0
composer.lock

@@ -0,0 +1,662 @@
+{
+    "_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": "f62200a42c7079d79121ddda255fa670",
+    "packages": [
+        {
+            "name": "container-interop/container-interop",
+            "version": "1.2.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/container-interop/container-interop.git",
+                "reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/container-interop/container-interop/zipball/79cbf1341c22ec75643d841642dd5d6acd83bdb8",
+                "reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8",
+                "shasum": ""
+            },
+            "require": {
+                "psr/container": "^1.0"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Interop\\Container\\": "src/Interop/Container/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "description": "Promoting the interoperability of container objects (DIC, SL, etc.)",
+            "homepage": "https://github.com/container-interop/container-interop",
+            "time": "2017-02-14T19:40:03+00:00"
+        },
+        {
+            "name": "erusev/parsedown",
+            "version": "1.6.2",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/erusev/parsedown.git",
+                "reference": "1bf24f7334fe16c88bf9d467863309ceaf285b01"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/erusev/parsedown/zipball/1bf24f7334fe16c88bf9d467863309ceaf285b01",
+                "reference": "1bf24f7334fe16c88bf9d467863309ceaf285b01",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.0"
+            },
+            "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": "2017-03-29T16:04:15+00:00"
+        },
+        {
+            "name": "erusev/parsedown-extra",
+            "version": "dev-master",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/erusev/parsedown-extra.git",
+                "reference": "0db5cce7354e4b76f155d092ab5eb3981c21258c"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/erusev/parsedown-extra/zipball/0db5cce7354e4b76f155d092ab5eb3981c21258c",
+                "reference": "0db5cce7354e4b76f155d092ab5eb3981c21258c",
+                "shasum": ""
+            },
+            "require": {
+                "erusev/parsedown": "~1.4"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-0": {
+                    "ParsedownExtra": ""
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Emanuil Rusev",
+                    "email": "hello@erusev.com",
+                    "homepage": "http://erusev.com"
+                }
+            ],
+            "description": "An extension of Parsedown that adds support for Markdown Extra.",
+            "homepage": "https://github.com/erusev/parsedown-extra",
+            "keywords": [
+                "markdown",
+                "markdown extra",
+                "parsedown",
+                "parser"
+            ],
+            "time": "2015-11-01 10:19:22"
+        },
+        {
+            "name": "jbroadway/urlify",
+            "version": "dev-master",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/jbroadway/urlify.git",
+                "reference": "99bb78cd9002d0e9ce479bb81635eb665e37e981"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/jbroadway/urlify/zipball/99bb78cd9002d0e9ce479bb81635eb665e37e981",
+                "reference": "99bb78cd9002d0e9ce479bb81635eb665e37e981",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.0-dev"
+                }
+            },
+            "autoload": {
+                "psr-0": {
+                    "URLify": ""
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD"
+            ],
+            "authors": [
+                {
+                    "name": "Johnny Broadway",
+                    "email": "johnny@johnnybroadway.com",
+                    "homepage": "http://www.johnnybroadway.com/"
+                }
+            ],
+            "description": "PHP port of URLify.js from the Django project. Transliterates non-ascii characters for use in URLs.",
+            "homepage": "https://github.com/jbroadway/urlify",
+            "keywords": [
+                "encode",
+                "iconv",
+                "link",
+                "slug",
+                "translit",
+                "transliterate",
+                "transliteration",
+                "url",
+                "urlify"
+            ],
+            "time": "2017-01-03 20:12:54"
+        },
+        {
+            "name": "nikic/fast-route",
+            "version": "v1.2.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/nikic/FastRoute.git",
+                "reference": "b5f95749071c82a8e0f58586987627054400cdf6"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/nikic/FastRoute/zipball/b5f95749071c82a8e0f58586987627054400cdf6",
+                "reference": "b5f95749071c82a8e0f58586987627054400cdf6",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.4.0"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "FastRoute\\": "src/"
+                },
+                "files": [
+                    "src/functions.php"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Nikita Popov",
+                    "email": "nikic@php.net"
+                }
+            ],
+            "description": "Fast request router for PHP",
+            "keywords": [
+                "router",
+                "routing"
+            ],
+            "time": "2017-01-19T11:35:12+00:00"
+        },
+        {
+            "name": "pimple/pimple",
+            "version": "v3.0.2",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/silexphp/Pimple.git",
+                "reference": "a30f7d6e57565a2e1a316e1baf2a483f788b258a"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/silexphp/Pimple/zipball/a30f7d6e57565a2e1a316e1baf2a483f788b258a",
+                "reference": "a30f7d6e57565a2e1a316e1baf2a483f788b258a",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "3.0.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-0": {
+                    "Pimple": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Fabien Potencier",
+                    "email": "fabien@symfony.com"
+                }
+            ],
+            "description": "Pimple, a simple Dependency Injection Container",
+            "homepage": "http://pimple.sensiolabs.org",
+            "keywords": [
+                "container",
+                "dependency injection"
+            ],
+            "time": "2015-09-11T15:10:35+00:00"
+        },
+        {
+            "name": "psr/container",
+            "version": "1.0.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/php-fig/container.git",
+                "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f",
+                "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.0.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Psr\\Container\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "PHP-FIG",
+                    "homepage": "http://www.php-fig.org/"
+                }
+            ],
+            "description": "Common Container Interface (PHP FIG PSR-11)",
+            "homepage": "https://github.com/php-fig/container",
+            "keywords": [
+                "PSR-11",
+                "container",
+                "container-interface",
+                "container-interop",
+                "psr"
+            ],
+            "time": "2017-02-14T16:28:37+00:00"
+        },
+        {
+            "name": "psr/http-message",
+            "version": "1.0.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/php-fig/http-message.git",
+                "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363",
+                "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.0.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Psr\\Http\\Message\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "PHP-FIG",
+                    "homepage": "http://www.php-fig.org/"
+                }
+            ],
+            "description": "Common interface for HTTP messages",
+            "homepage": "https://github.com/php-fig/http-message",
+            "keywords": [
+                "http",
+                "http-message",
+                "psr",
+                "psr-7",
+                "request",
+                "response"
+            ],
+            "time": "2016-08-06T14:39:51+00:00"
+        },
+        {
+            "name": "slim/flash",
+            "version": "dev-master",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/slimphp/Slim-Flash.git",
+                "reference": "3c9a26b3163820acc48080336c504d0a3cac6f30"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/slimphp/Slim-Flash/zipball/3c9a26b3163820acc48080336c504d0a3cac6f30",
+                "reference": "3c9a26b3163820acc48080336c504d0a3cac6f30",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.5.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^4.0"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Slim\\Flash\\": "src"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Josh Lockhart",
+                    "email": "hello@joshlockhart.com",
+                    "homepage": "http://joshlockhart.com"
+                }
+            ],
+            "description": "Slim Framework Flash message service provider",
+            "homepage": "http://slimframework.com",
+            "keywords": [
+                "flash",
+                "framework",
+                "message",
+                "provider",
+                "slim"
+            ],
+            "time": "2016-11-11 16:29:19"
+        },
+        {
+            "name": "slim/slim",
+            "version": "3.8.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/slimphp/Slim.git",
+                "reference": "5385302707530b2bccee1769613ad769859b826d"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/slimphp/Slim/zipball/5385302707530b2bccee1769613ad769859b826d",
+                "reference": "5385302707530b2bccee1769613ad769859b826d",
+                "shasum": ""
+            },
+            "require": {
+                "container-interop/container-interop": "^1.2",
+                "nikic/fast-route": "^1.0",
+                "php": ">=5.5.0",
+                "pimple/pimple": "^3.0",
+                "psr/container": "^1.0",
+                "psr/http-message": "^1.0"
+            },
+            "provide": {
+                "psr/http-message-implementation": "1.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^4.0",
+                "squizlabs/php_codesniffer": "^2.5"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Slim\\": "Slim"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Rob Allen",
+                    "email": "rob@akrabat.com",
+                    "homepage": "http://akrabat.com"
+                },
+                {
+                    "name": "Josh Lockhart",
+                    "email": "hello@joshlockhart.com",
+                    "homepage": "https://joshlockhart.com"
+                },
+                {
+                    "name": "Gabriel Manricks",
+                    "email": "gmanricks@me.com",
+                    "homepage": "http://gabrielmanricks.com"
+                },
+                {
+                    "name": "Andrew Smith",
+                    "email": "a.smith@silentworks.co.uk",
+                    "homepage": "http://silentworks.co.uk"
+                }
+            ],
+            "description": "Slim is a PHP micro framework that helps you quickly write simple yet powerful web applications and APIs",
+            "homepage": "https://slimframework.com",
+            "keywords": [
+                "api",
+                "framework",
+                "micro",
+                "router"
+            ],
+            "time": "2017-03-19T17:55:20+00:00"
+        },
+        {
+            "name": "slim/twig-view",
+            "version": "dev-master",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/slimphp/Twig-View.git",
+                "reference": "a743ac45e2a089942159dda499c5ef5bc5f6bfa6"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/slimphp/Twig-View/zipball/a743ac45e2a089942159dda499c5ef5bc5f6bfa6",
+                "reference": "a743ac45e2a089942159dda499c5ef5bc5f6bfa6",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.5.0",
+                "psr/http-message": "^1.0",
+                "twig/twig": "^1.18|^2.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^4.8|^5.7"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Slim\\Views\\": "src"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Josh Lockhart",
+                    "email": "hello@joshlockhart.com",
+                    "homepage": "http://joshlockhart.com"
+                }
+            ],
+            "description": "Slim Framework 3 view helper built on top of the Twig 2 templating component",
+            "homepage": "http://slimframework.com",
+            "keywords": [
+                "framework",
+                "slim",
+                "template",
+                "twig",
+                "view"
+            ],
+            "time": "2017-01-25 20:38:39"
+        },
+        {
+            "name": "symfony/yaml",
+            "version": "v2.8.19",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/yaml.git",
+                "reference": "286d84891690b0e2515874717e49360d1c98a703"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/yaml/zipball/286d84891690b0e2515874717e49360d1c98a703",
+                "reference": "286d84891690b0e2515874717e49360d1c98a703",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.9"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.8-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Symfony\\Component\\Yaml\\": ""
+                },
+                "exclude-from-classmap": [
+                    "/Tests/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Fabien Potencier",
+                    "email": "fabien@symfony.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Symfony Yaml Component",
+            "homepage": "https://symfony.com",
+            "time": "2017-03-20T09:41:44+00:00"
+        },
+        {
+            "name": "twig/twig",
+            "version": "v1.33.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/twigphp/Twig.git",
+                "reference": "05cf49921b13f6f01d3cfdf9018cfa7a8086fd5a"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/twigphp/Twig/zipball/05cf49921b13f6f01d3cfdf9018cfa7a8086fd5a",
+                "reference": "05cf49921b13f6f01d3cfdf9018cfa7a8086fd5a",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.2.7"
+            },
+            "require-dev": {
+                "psr/container": "^1.0",
+                "symfony/debug": "~2.7",
+                "symfony/phpunit-bridge": "~3.3@dev"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.33-dev"
+                }
+            },
+            "autoload": {
+                "psr-0": {
+                    "Twig_": "lib/"
+                }
+            },
+            "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": "2017-03-22T15:40:09+00:00"
+        }
+    ],
+    "packages-dev": [],
+    "aliases": [],
+    "minimum-stability": "stable",
+    "stability-flags": {
+        "slim/twig-view": 20,
+        "slim/flash": 20,
+        "erusev/parsedown-extra": 20,
+        "jbroadway/urlify": 20
+    },
+    "prefer-stable": false,
+    "prefer-lowest": false,
+    "platform": [],
+    "platform-dev": []
+}

+ 20 - 0
content/0_typemill/01-use-cases.md

@@ -0,0 +1,20 @@
+# Use Cases
+
+Whenever you want to publish a finished text work as a website, then TYPEMILL is a smart and lightweight solution. Possible use cases are ...
+
+- a book
+- a drama
+- a lyric collection
+- a whitepaper
+- a documentation
+- a manual or user guide
+- a handbook
+- a tutorial
+- a study
+- a collection of articles
+
+TYPEMILL is not a full blown Content Management System (CMS). It has no admin panel and it does not support any content creation right now. Instead, it takes some existing markdown files and generates a beautiful website. 
+
+Use your favourite text or markdown editor (e.g. Typora) to create markdown files and upload them with a FTP software (e.g. FileZilla) to your server.
+
+TYPEMILL is not the right solution, if you want to create a blog, a wiki or any website with an author interface. But it is a smart solution to publish any text work based on markdown files.

+ 22 - 0
content/0_typemill/03-features.md

@@ -0,0 +1,22 @@
+# Features
+
+TYPEMILL has a limited set of features right now. It transforms a bunch of **markdown files** into a **website** and generates a list of contents for **navigation**. 
+
+This is what you can **do with TYPEMILL**:
+
+- Setup your website with an easy setup form.
+- Create your website content with simple folders and files (markdown).
+- Choose a static startpage for your website (optional).
+- Change the theme (design).
+- Create your own theme with HTML, CSS and Twig (a template language for PHP).
+
+This is, what **TYPEMILL does** for you:
+
+- It creates a website based on your folders and files.
+- It generates a navigation according to the structure of your folders and files.
+- It adds a paging.
+- It adds a breadcrumb.
+- It adds hierarchic numbers to your chapters and pages.
+- It makes everything responsive for mobile devices.
+
+There is a roadmap for TYPEMILL, so there will be a lot more useful features in near future.

+ 13 - 0
content/0_typemill/09-roadmap.md

@@ -0,0 +1,13 @@
+# Roadmap
+
+There are a lot of plans for future releases of TYPEMILL, but it also follows the concept of simplicity. To prevent TYPEMILL from becomming a feature soup, it will strictly focus on the writers needs. These are some ideas:  
+
+- Image and media support.
+- A dashboard for authors to create and edit content online.
+- More themes for special publications like documentations, books or lyrics.
+- Additional navigation based on the headlines of a content page.
+- Extensibility (Plugins) and API design.
+- Version controll and updates.
+- Additional output format like mobi, epub, static html and more.
+
+If you miss a feature or if you found a bug, please report it on GitHub.

BIN
content/0_typemill/bnmc-bolachas-02.png


+ 3 - 0
content/0_typemill/index.md

@@ -0,0 +1,3 @@
+#About TYPEMILL
+
+TYPEMILL is a simple tool to create a website like this. It transforms a bunch of **text files** (Markdown) into a **website** and generates a **navigation**. TYPEMILL is a perfect tool for web books, documentations or manuals.

+ 15 - 0
content/1_getting-started/00-system-requirements.md

@@ -0,0 +1,15 @@
+# System Requirements
+
+TYPEMILL is a modern and lightweight software with nearly no requirements. All you need is:
+
+- **A webserver** (to host TYPEMILL)
+- **PHP 5.6+** (to run TYPEMILL)
+- **FTP** (to upload your content files)
+
+What you don't need:
+
+- **A lot of space** (TYPEMILL is  lightweight with less than 5MBs)
+- **A database** (TYPEMILL uses files, not a database)
+- **Technical skills** (TYPEMILL is easy to use for non-technical people)
+
+Almost any hosting package provides a webserver with php. If you ever hosted a website with WordPress, then chances are high, that you can run TYPEMILL there without any problems.

+ 68 - 0
content/1_getting-started/01-installation.md

@@ -0,0 +1,68 @@
+# Installation
+
+The installation of TYPEMILL is as simple as that: 
+
+- Go to [typemill.net](http://www.typemill.net) and download the TYPEMILL files.
+- Upload the files to your server.
+- Go to `www.your-typemill-website.com/setup` and fill out the form. 
+
+You can also setup TYPEMILL manually with the `settings.yaml.example` file, that you can find in the root folder of TYPEMILL.
+
+Don't forget to make some folders and files writable (set permission to `774`):
+
+- `\cache` folder and files
+- `\settings` folder and files
+- `\content` folder and files
+
+If you have any trouble to understand the instructions above, read the following detailed description.
+
+## Download
+
+There are two ways to copy TYPEMILL to your local computer:
+
+1. Go to [typemill.net](http://www.typemill.net), download the zip-archive and unzip it.
+2. **Or** use GitHub and Composer.
+
+If you use GitHub, then you can find the repository of TYPEMILL on [github/trendschau/typemill](https://github/trendschau/typemill). Just open the command line (git-CLI) and type
+
+````
+git clone "https://github.com/trendschau/typemill.git"
+````
+
+TYPEMILL uses some nice frameworks and libraries, which can be found in the folder `\system\vendor`. Make sure, that all these libraries are completely downloaded. Run composer to update all libraries. If you don't have composer installed yet, head over to the [composer website](https://getcomposer.org/) and install it. After that, open your command line, go to your TYPEMILL folder and type:
+
+````
+composer update
+````
+
+The exact command might vary depending on your composer installation. If you face any problems, please check the documentation of composer.
+
+That's it!
+
+## Setup
+
+There are three ways to setup your TYPEMILL website:
+
+- **Recommended**: Copy the file `settings.yaml.example` in the root folder of TYPEMILL and rename it to `settings.yaml`. Fill out the settings directly in the file. It is human readable, so no problem for you!
+- **Recommended**: If you run you website on your local machine, you can also go to `your-local-adress/setup` and fill out the setup form.
+- **Be careful**: You can also upload TYPEMILL to a live server and fill out the form live. Just visit `your-website.com/setup`. But be aware, that everybody can visit this adress and setup your website easily. It is not a big deal, because you can always upload your own `settings.yaml` file with your ftp program.
+
+If there is a valid `settings.yaml` file in your root folder, then the adress `your-website.com/setup` is not active anymore.
+
+Read all details about the settings in the next chapter.
+
+## Upload
+
+To run a live website, simply upload TYPEMILL to your webserver (e.g. with ftp). You have to make some folders and files writable:
+
+- `\cache`
+- `\content`
+
+To make the folders and files writable, use your ftp programm, click on the folder, choose `permissions` and change the permission to `744`. Use the recursive permission for all containing files and folders. If `744` does not work, try `774`.
+
+To fill the website with your own content, just upload your folders and markdown files to the `content` folder of TYPEMILL (with ftp again). Visit your website and press `F5` to actualize the cache.
+
+## Run Locally
+
+If you are a developer and if you want to run TYPEMILL locally, then simply download TYPEMILL (zip or git) and visit your local folder like `localhost/typemill`. No additional work is required.
+

+ 44 - 0
content/1_getting-started/02-settings.md

@@ -0,0 +1,44 @@
+# Settings
+
+TYPEMILL offers some settings for customization. There are two ways to add settings:
+
+1. Visit `your-website.com/setup` and use the setup form to customize the settings or
+2. Rename the file `settings.yaml.example` to `settings.yaml` and edit the file manually. You will find the file in the settings folder of TYPEMILL.
+
+More details are described in the previous chapter about the installation of TYPEMILL.
+
+## Standard Settings
+
+You will find six standard settings in the file `settings.yaml.example`:
+
+````
+title: MyWebsite
+author: 'Your Name'
+copyright: ©
+year: '2017'
+theme: typemill
+startpage: true
+````
+
+The settings are written in YAML, a simple and human readable format. Simply add 
+
+- A title for your website. Keep it short, or it will destroy the design.
+- An author name (or several author names)
+- A licence or copyright like `©`, `cc-by` or whatever you want. 
+- A year. This should be the starting year. The theme will add a range to the present like 2015 - 2017.
+- A theme. Add the name of the theme folder here. 
+- A startpage. Add `false` or `true`.
+
+## Advanced settings
+
+You can also add some advanced settings, if you really want. 
+
+````
+themeFolder: themes
+contentFolder: content
+displayErrorDetails: false
+````
+
+It probably does not make much sence to change the theme folder or the content folder, but you can do so if you want.
+
+If you are a developer and if you run TYPEMILL on your local machine, you can set `displayErrorDetails` to `true` for a detailed error reporting. Don't forget to set it back to `false` before you deploy the website live. It is not secure to show the world your internal errors and many hosters will turn off all public error reports by default.

+ 3 - 0
content/1_getting-started/index.md

@@ -0,0 +1,3 @@
+# Getting Started
+
+Simply download TYPEMILL and immediately start publishing. TYPEMILL runs with **php5.6+** on most webservers. **No database** or any other additional technology is required.

+ 11 - 0
content/2_for-writers/00-quick-start.md

@@ -0,0 +1,11 @@
+# Quick Start for Writers
+
+You are a pro and don't want to read the whole manual? No problem, this is a quick overview:
+
+- **Folders and files**: Organize your content in folders and markdown files and put them in the `\content` folder of TYPEMILL. 
+- **Naming conventions**: Use prefixes like `01-` or `aa_` to sort your folders and files.
+- **Markdown**: Use the Markdown syntax for your content files. Markdown Extra (e.g. tables, footnotes) is supported, too.
+- **Index files**: Add an `index.md` file to a folder to create content for the folder itself.
+- **F5**: After some changes, use the `F5` key to refresh the navigation manually.
+- **Settings**: Use the file `settings.yaml` in the root folder to change the theme or other settings.
+- **Lean back** and let TYPEMILL create a nice website for you.

+ 156 - 0
content/2_for-writers/02-mardown.md

@@ -0,0 +1,156 @@
+# Markdown
+
+Never heard of Markdown? Markdown is  very similar to the markup used by Wikipedia. It is a simple syntax to format headlines, lists or paragraphs in a text file. Markdown files end with `.md`.
+
+Today, Markdown is a standard formatting language used by a lot of technology platforms like GitHub or StackOverflow. And Markdown is also entering the non technical mainstream. The press releases of dpa are written in Markdown, for example.
+
+Markdown uses some special chars like `#` or `-` to format a text. A short example: 
+
+````
+# My first level headline
+
+This is a paragraph and now we create an unordered list:
+
+- Item
+- Another item
+- A last item
+````
+
+## Advantages of Markdown
+
+There are some good reasons for the rise of Markdown:
+
+- Different to proprietary formats like word.docx, the Markdown syntax is universal and not bound to a special text software.
+- You can use the most simple text editor (e.g. the "editor" of microsoft office) or a special Markdown editor like Typora to create Markdown files.
+- Markdown can be transformed into a valid HTML document easily.
+- Compared to the well known WISYWIG HTML editors (e.g. used by WordPress), Markdown is less hacky and the content is more reusable.
+
+There are also some disadvantages:
+
+- You cannot use a text program like Microsoft Word to create Markdown files.
+- Markdown is usually not WYSIWYG and the writing experience is a bit different from Word or WordPress. However, there are a lot of Markdown editors which provide a preview window. Some editors even provide a full WYSIWYG modus (e.g. Typora).
+- Markdown is not totally unified and the rendering of Markdown files can be ambiguous. There are some variations and enhancements like CommonMark or Markdown Extra.
+
+With the following basic Markdown reference, you can learn to write Markdown in less than 10 minutes!
+
+## Basic Markdown Reference
+
+You can read the full specification of Markdown at [Mark Guber](http://daringfireball.net/projects/markdown/syntax), the inventor of Markdown.
+
+### Paragraph
+
+Just write down some text and use the return key two times for a new paragraph:
+
+````
+To create a new paragraph, just press the return button two times.
+
+Then proceed writing. It is really as simple as that!
+````
+
+### Emphasis and Strong
+
+Embed text in a `_` or `*` to create an _emphasis_ or use a `__` or `**` to create **strong** text element:
+
+````
+This is an _emphasis_ and this is a __strong__ text. 
+
+You can use asterix for an *emphasis* or a **strong** text, too.
+````
+
+### Headlines
+
+Just use the character `#` for headlines like this:
+
+````
+# Headline (1. level)
+## Headline (2. level)
+### Headline (3. level)
+#### Headline (4. level)
+##### Headline (5. level)
+###### Headline (6. level)
+````
+
+### Lists
+
+To create an unordered `-` or ordered `1.` list, just follow your intuition:
+
+````
+This is an unordered list: 
+
+- Item
+- Another item
+- Last item
+
+And this is an ordred list: 
+
+1. Item 1
+2. Item 2
+3. Item 3
+````
+
+ ### Blockquote
+
+Just use the `>` to create a blockquote:
+
+````
+This is a quote by a famous woman:
+
+> If I stop to kick every barking dog I am not going to get where I’m going.
+````
+
+### Horizontal Rule
+
+To create a horizontal line, use `---`
+
+````
+This is a text followed by a horizontal line
+---
+And this is another text.
+````
+
+### Links
+
+Use square brackets for the linked text followed by round clips for the url.
+
+````
+[Linked Text](http://url-to-a-website.com)
+````
+
+You can also use a shortcut for links `<http://www.yourlink.de>` and emails `<my@emailadress.net>`, but you cannot add a text for the links or emails with these shortcuts.
+
+When rendered, Markdown will automatically obfuscate email adresses to help obscure your address from spambots. 
+
+### Images
+
+Images look similar to links, simply add an ! like this:
+
+````
+![image alt text](/path/to/image.jpg)
+````
+
+### Code (inline)
+
+To create a inline code, just use the ` sign like this:
+
+````
+Inline code `<?php echo 'hello world!'; ?>` within a sentence.
+````
+
+### Code (block)
+
+To create a code block, just indent your text with four spaces or use four ```` like this:
+
+````
+This text is followed by a code-block:
+
+​````
+<?php
+	$string = 'hello ';
+ 	$string .= 'world!';
+	echo $string;
+?>
+````
+
+### Advanced Formats
+
+With enhancements like Markdown Extra you can also create more complex formats like tables, abbreviations, footnotes and special attributes. TYPEMILL supports Markdown Extra, so just check the [specification of Markdown Extra](https://michelf.ca/projects/php-markdown/extra/) if you want to use these kind of formats.

+ 19 - 0
content/2_for-writers/10-naming-files-and-folders.md

@@ -0,0 +1,19 @@
+# Naming your Files and Folders
+
+To create a clean website with TYPEMILL, you have to follow some naming conventions for your files and folders. A typcial structure for folders and file looks like this:
+
+- 01_content_folder
+  - 01_markdown_file.md
+  - 02_another_markdown_file.md
+  - index.md
+
+The rules are simple: 
+
+- **Keep it short**: The names of the files and folders are used to create the navigation, so it is essential to keep them really short!!
+- **Use prefixes**: Please use some kind of sorting-prefix for your files and folders. You can use numbers `01-` or letters `aa-`. The part before the first separator (the prefix) is striped out by TYPEMILL.
+- **Use Separators**: Please use separators like dashes `-` or underscores `_` to separate words or prefixes in your file names and folder names. Do not use space!!!
+- **Use index.md**: You can use a file named `index.md` to create content for the folder itself. This is optional.
+- **Avoid Language Specific Characters**: Use the english character set to name your files and folders. French, German, Russian or Turkish are beautiful languages, but right now it is not guarantied, that these characters are interpreted correctly. But you can use all character sets to write the content in your files of course.
+
+When you name your files and folders, then always keep in mind, that the names are used to generate the navigation and the table of contents. So keep it short to keep the layout and design healthy.
+

+ 5 - 0
content/2_for-writers/30-folder-structure.md

@@ -0,0 +1,5 @@
+# Folder Structure
+
+You can create any kind of folder structer with TYPEMILL. As long as you follow the naming conventions for folders and files, it will work.
+
+However, if you create a very deep structure, then it might result in an odd design or even in usability errors. Similar to real live, it is always a good idea to keep the hierarchy as flat as possible.

+ 3 - 0
content/2_for-writers/index.md

@@ -0,0 +1,3 @@
+# Hello Writers!
+
+If you love **simple text files** (Markdown) and if you like **distraction free websites** without fiddly technology, then TYPEMILL is for you!

+ 40 - 0
content/3_for-developers/01-quick-start.md

@@ -0,0 +1,40 @@
+# Quick Start for Developers
+
+So you are a pro and don't want to read the whole documentation? No problem, this is all you need to know to create your own theme for TYPEMILL.
+
+## Theme Folder
+
+You will find all themes in the `theme` folder of TYPEMILL. Change the  theme in the `settings.yaml`.
+
+## Theme Structure
+
+There is no theme structure. There are only two files that are required: 
+
+- `index.twig`: All content files will be rendered with this template. 
+- `404.twig`: This is the template for a not found message.  
+
+There is another optional template:
+
+- `cover.twig`: Use this name to create a template for a static startpage.
+
+It is always a good idea to structure your files a bit more. For example, you can create a folder called `partials` with separate files for different layouts (maybe a folder and file layout?), a navigation, a header, a footer or whatever you want. But this decision is completely up to you. The same with css, JavaScript and other ressources: It is a good practice to create separate folders for that, but it is up to you.
+
+## Twig
+
+The template language for TYPEMILL is Twig. You are probably familiar with it. If not: Twig is a widespread template language, that is very easy to learn. It is shorter and safer to use than pure PHP.
+
+## Template Variables
+
+There are exactly six template variables to fill your templates with dynamic content. Just print the variables out to get some insights.
+
+- `navigation`: This variable is a multidimensional array of objects. Each object represents a file or a folder. You can use a Twig-macro to create a navigation with this variable in your template. A macro in TWIG is the same as a recursive function in PHP. 
+- `content`: This variable holds the HTML content of the markdown file for a specific page.
+- `breadcrumb`: This variable is an one dimensional array. It contains the breadcrumb of the page. Just use a loop like  `{% for element in breadcrumb %}` to print it out.
+- `item`: This variable is an object of the actual page. It contains all the details like name, url, path, chapter as well as the next and previous items for a pagination. And guess what? The `navigation` variable is just an array of these item-objects (with a bit less information).
+- `settings`: You will find all the settings in this variable (like the navigation-title, the author, the theme and the copyright information).
+- `description`: This are the first 150 characters of the content of a page. You can use this for the meta description.
+
+If you did not understand everything, then please read the full developer manual. In less than one hour you can develop with TYPEMILL like a pro.
+
+Happy coding!
+

+ 208 - 0
content/3_for-developers/03-twig.md

@@ -0,0 +1,208 @@
+# Templates with Twig
+
+Twig is a flexible, fast and secure template engine for PHP. If you have never used a template language before, then there are some good reasons to start with it today:
+
+- The Twig syntax is **much shorter**, so your templates look cleaner and are easier to maintain.
+- Twig produces **less errors**. An unknown variable produces an error in PHP, but it does not in Twig. Twig handles most of these cases, so you don't have to care about it.
+- Twig is very **widespread**. Even Drupal switched to Twig in version 8.
+
+The full Twig documentation for template designers is just one page long, so just head [over to Twig](http://twig.sensiolabs.org/doc/2.x/templates.html) and read it. You can learn the most important essentials for TYPEMILL in the following list.
+
+## Basic Twig Syntax
+
+In a Twig template, you can use ordinary HTML markup. Statements and expressions are written in curly brackets.
+
+Twig uses two curly brackets **to print out** a variable or expression: 
+
+````
+<p>{{ variable }}</p>
+````
+
+Twig uses one curly bracket with a procent sign **to execute** statements such as loops:
+
+````
+<ul>
+    {% for element in breadcrumb %}
+      <li> {{ element.output|e }} </li>
+    {% endfor %}
+</ul>
+````
+
+As you can see, the Twig syntax is a cleaner and easier than pure PHP:
+
+- You don't need the long `<?php echo something; ?>` introduction.
+- You don't need the `$` to mark a variable.
+- You don't need the `;` to finish a statement.
+- You don't need the `->` or `['foo']` notation for objects and arrays, just use a dot-notation like `element.name` for everything.
+- You don't need a lot of `()` like `foreach(a as b)`.
+- You don't need a syntax like `<?php echo htmlspecialchars($element->output, ENT_QUOTES, 'UTF-8') ?>` for escaping, just use a filter with a pipe notation like this `{{ element.output|e }}`.
+
+## References
+
+These are some useful examples and snippets, that you can use for your templates. 
+
+### Simple Variable
+
+Set a simple variable and print it out:
+
+````
+{% set content = "my content" %}
+{{ content }}
+````
+
+### Array
+
+Set an array and print out a value:
+
+````
+{% set content = ['first' => 'one value', 'second' => 'another value'] %}
+{{ content.first }}
+````
+
+### Object
+
+Set an object and print out a value:
+
+````
+{% set content = {'first' : 'first value', 'second' : 'another value'} %}
+{{ content.first }}
+````
+
+### Loop
+
+Loop over an object or array and print out the values:
+
+````
+{% for value in content %}
+   {{ value }}
+{% endfor %}
+````
+
+Outputs:
+
+- first value
+- another value
+
+### Filters
+
+Set the first character of the words to uppercase:
+
+````
+<ul>
+{% for value in content %}
+   <li>{{ value|title }}</li>
+{% endfor %}
+</ul>
+````
+
+Output:
+
+- First Value
+- Another Value
+
+You can manipulate variables with filters. Fiters are used after a pipe notation. See a list of all filters in the [Twig documentation](http://twig.sensiolabs.org/doc/2.x/filters/index.html).
+
+### Functions
+
+Print out content that was created in the last 30 days: 
+
+```
+{% if date(content.created_at) > date('-30days') %}
+    {{ content.title }}
+{% endif %}
+```
+
+'created_at' could be a timestamp of the content file. See a list of all functions in the [Twig documentation](https://twig.sensiolabs.org/doc/2.x/functions/index.html).
+
+### Include Template
+
+To include a template, just write:
+
+````
+{{ include(sidebar.twig) }}
+````
+
+**Example usage**: Your layout-template includes other templates like header.twig, footer.twig or sidebar.twig.
+
+### Extend Template
+
+To extend a template, just write:
+
+````
+{% extends "partials/layout.twig" %}
+````
+
+**Example usage:** Your content template (e.g. index.twig) extends your layout template. This means, index.twig is rendered within the layout.twig, and the layout.twig includes a header.twig, a footer.twig and a sidebar.twig.
+
+### Example: Include and Extend
+
+If you extend a template with another template (e.g. if you extend `layout.twig` with `index.twig`), then you have to define some content areas in the "parent" template that get overwritten with the content of the "child" template. You can use the "block" statement to define such areas. 
+
+Your layout.twig looks like this:
+
+````
+<!DOCTYPE html>
+<html>
+  <head>
+    ...
+  </head>
+  <body>
+    <article>{% block content %}{% endblock %}</article>
+    <nav>
+      {{ inlude 'navigation.twig' }}
+    </nav>
+    <footer>
+      {{ include 'footer.twig' }}
+    </footer>
+  </body>
+</html>
+````
+
+Your index.twig looks like this:
+
+````
+{% extends "layout.twig" %}
+
+{% block content %}
+  
+  <ul>
+    {% for value in content%}
+      <li>{{ value }}</li>
+    {% endfor }
+  </ul>
+  
+{% endblock %}
+````
+
+Now, your template `index.twig` extends your template `layout.twig` and the `block content` in your layout template gets replaced by the `block content` defined in your index template. At the same time the layout template includes the navigation and the footer.
+
+### Macros
+
+Macros in Twig are like functions in PHP: You can use them for repeating tasks. A typical example is a navigation, where you loop over a complex array recursively. But you can also use macros to render forms and input fields.
+
+This is an example for a navigation:
+
+    {% macro loop_over(navigation) %}
+    
+      {% import _self as macros %}
+    
+      {% for element in navigation %} 
+        <li>
+          {% if element.elementType == 'folder' %}
+    	    <a href="{{ element.url }}">{{ element.name|title }}</a>		
+            <ul>
+              {{ macros.loop_over(element.folderContent) }}
+            </ul>
+          {% else %}
+    		<a href="{{ element.url }}">{{ element.name|title }}</a>
+          {% endif %}
+        </li>
+       {% endfor %}
+    {% endmacro %}
+    
+    {% import _self as macros %}
+    
+    <ul class="main-menu">
+      {{ macros.loop_over(navigation) }}
+    </ul>
+These are only some small examples, how you can use Twig to create templates and themes for TYPEMILL. In fact, you can do a lot more complex stuff with Twig. Just read the [official documentation](https://twig.sensiolabs.org/doc).

+ 38 - 0
content/3_for-developers/04-theme-structure.md

@@ -0,0 +1,38 @@
+# Theme Structure
+
+TYPEMILL requires a minimal structure and a small set of mandatory files:
+
+- **/myThemeFolder**: A theme folder. The name of the folder is the name of the theme.
+  - **404.twig**: The template for a not found page. It is mandatory.
+  - **index.twig**: The template for all other pages. It is mandatory.
+  - **cover.twig**: The template for a static startpage. It is optional.
+  - **myThemeFolder.jpg**: A preview picture of your theme. It is mandatory. The file must be named exactly like the theme folder. Minimum width is 400px.
+
+That's it.
+
+## Recommendation
+
+If you want to create a more complex structure, then you can do whatever you want, as long as you follow the basic structure and conventions described above.
+
+However, if you don't have an idea how to start, then you can follow this example:
+
+- css
+    - style.css
+    - another.css
+- js
+    - javascript.js
+- img
+    - icon.png
+    - favicon.ico
+    - themeLogo.jpg
+- partials
+    - layoutStart.twig // layout for the static startpage.
+    - layout.twig  // layout for all other pages, includes navigation, header and footer
+    - navigation.twig
+    - header.twig
+    - footer.twig
+- cover.twig // template for the static startpage. Extends the layoutStart.twig.
+- index.twig // template for all other pages. Extends the layout.twig
+- 404.twig // template for not found page. Extends the layout.twig.
+
+If you have not read the chapter about Twig templates yet, please read it now. It does not only describe the template language Twig, but also the template hierarchy (how templates can be included and extended).

+ 7 - 0
content/3_for-developers/05-theme-variables/05-content.md

@@ -0,0 +1,7 @@
+# Content
+
+The content-variable holds the whole content of your Markdown file in HTML. To print out the content of the Markdown file, simply write:
+
+    {{ content }}
+You can only use Twig filters to manipulate the content, but the possibilities are limited.
+

+ 9 - 0
content/3_for-developers/05-theme-variables/08-description.md

@@ -0,0 +1,9 @@
+# Description
+
+The description variable extracts the first 150 characters of the content. You can print the description out with:
+
+    {{ description }}
+
+You can use the description for the meta-tag in your HTML head, for example.
+
+

+ 302 - 0
content/3_for-developers/05-theme-variables/10-item.md

@@ -0,0 +1,302 @@
+# Item
+
+The item variable is an object. It provides informations about the actual page, like the page title,  the url, the slug or the next and the previous page. 
+
+Some informations are only available for the type `folder` while some other informations are specific to the type `file`. But most informations are shared by both.
+
+## Example of the {{ item }} variable
+
+This is an example of an item variable:
+
+````
+stdClass Object
+(
+    [originalName] => 25-navigation.md
+    [elementType] => file
+    [fileType] => md
+    [order] => 25
+    [name] => navigation
+    [slug] => navigation
+    [path] => \3_for-developers\05-theme-variables\25-navigation.md
+    [key] => 4
+    [keyPath] => 3.3.4
+    [keyPathArray] => Array
+        (
+            [0] => 3
+            [1] => 3
+            [2] => 4
+        )
+    [chapter] => 4.4.5
+    [urlRel] => /typemill/developers/theme-variables/navigation
+    [urlAbs] => http://localhost/typemill/developers/theme-variables/navigation
+    [active] => 1
+    [thisChapter] => stdClass Object
+        (
+            [originalName] => 05-theme-variables
+            [elementType] => folder
+            [index] => 1
+            [order] => 05
+            [name] => theme variables
+            [slug] => theme-variables
+            [path] => \3_for-developers\05-theme-variables
+            [urlRel] => /typemill/developers/theme-variables
+            [urlAbs] => http://localhost/typemill/developers/theme-variables
+            [key] => 3
+            [keyPath] => 3.3
+            [keyPathArray] => Array
+                (
+                    [0] => 3
+                    [1] => 3
+                )
+
+            [chapter] => 4.4
+            [active] => 1
+            [activeParent] => 1
+        )
+
+    [prevItem] => stdClass Object
+        (
+            [originalName] => 15-breadcrumb.md
+            [elementType] => file
+            [fileType] => md
+            [order] => 15
+            [name] => breadcrumb
+            [slug] => breadcrumb
+            [path] => \3_for-developers\05-theme-variables\15-breadcrumb.md
+            [key] => 3
+            [keyPath] => 3.3.3
+            [keyPathArray] => Array
+                (
+                    [0] => 3
+                    [1] => 3
+                    [2] => 3
+                )
+
+            [chapter] => 4.4.4
+            [urlRel] => /typemill/developers/theme-variables/breadcrumb
+            [urlAbs] => http://localhost/typemill/developers/theme-variables/breadcrumb
+        )
+
+    [nextItem] => stdClass Object
+        (
+            [originalName] => 30-settings.md
+            [elementType] => file
+            [fileType] => md
+            [order] => 30
+            [name] => settings
+            [slug] => settings
+            [path] => \3_for-developers\05-theme-variables\30-settings.md
+            [key] => 5
+            [keyPath] => 3.3.5
+            [keyPathArray] => Array
+                (
+                    [0] => 3
+                    [1] => 3
+                    [2] => 5
+                )
+
+            [chapter] => 4.4.6
+            [urlRel] => /typemill/developers/theme-variables/settings
+            [urlAbs] => http://localhost/typemill/developers/theme-variables/settings
+        )
+
+)
+````
+
+## Shared properties
+
+The following informations (properties) are shared by folders and files. The examples are based on a simple file and folder structure like this: 
+
+- content
+  - 1.my-folder
+    - index.md
+    - 04.my-content-file.md
+
+### {{ item.elementType }}
+
+The type of the item. Possible values are:
+
+- "file"
+- "folder"
+
+You can check the elementType and display a folder in a different way than a content file.
+
+Example: `{% if item.elementType == 'folder' %}`
+
+### {{ item.urlRel }}
+
+The relative url of the item without the base url. This is useful if you want to set a link to another internal page.
+
+Example:  `/my-folder/my-content-file`
+
+### {{ item.urlAbs }}
+
+The absolute url of the item. This is useful for cannonical links, social media links or permalinks.
+
+Example: `http://mydomain.com/my-folder/my-content-file`
+
+### {{ item.slug }}
+
+The slug of the file or folder. This is the last part of the url. 
+
+Example:  `/my-content-file` in the url `www.mywebsite.com/my-folder/my-content-file`.
+
+### {{ item.name }}
+
+The human readable name of the file or folder.
+
+Example:  `my content file` for a Mardown file with a name like `01.my-content-file.md`.
+
+### {{ item.originalName }}
+
+The original name of the file or folder. You probably don't need it for your theme.
+
+Example: `04.my-content-file.md` or `1.my-folder`. 
+
+### {{ item.path }}
+
+The physical path to the item on your server. You probably don't need that, but TYPEMILL uses this information to map the urls with the content files and folders.
+
+Example: `\1.my-folder\04.my-content-file.md`.
+
+### {{ item.order }}
+
+The prefix of the item for ordering. You probably don't need it for your theme.
+
+Example:  `1` for the folder and `04` for the file.
+
+### {{ item.active }}
+
+The item.active indicates, if the item is active or not. You probably don't need it in a page content, because the current page is always an active page, too. But you will need this in another context, for example, if you create a navigation.
+
+### {{ item.key }}
+
+The key of the item within the navigation array. You probably don't need that.
+
+Example: `2`.
+
+### {{ item.keyPath }}
+
+The full key path of the item within the navigation array. You probably don't need that.
+
+Example: `1.3.2`
+
+### {{ item.keyPathArray }}
+
+The full key path of the item within the navigation array as an array instead of a string.
+
+Example: `array(0 => 1, 1 => 3, 2 => 2 )`
+
+This might be useful if you want to determine the depth of the item within the content structure.
+
+Example: `item.keyPathArray|length` returns `3`, so you know that the page exists in third level of the content structure.
+
+### {{ item.chapter }}
+
+The human readable key path of the item as a string. Different to the key path, it starts with `1` instead of `0`. You can use it to print out a chapter number.
+
+Example: `2.4.3`
+
+### {{ item.thisChapter }}
+
+The parent chapter of the current item. If the current item is 1.3.2, then the parent chapter is 1.3. 
+
+The variable `item.thisChapter` is an item object again, so you have access to all the above informations. This way, you can display the parent chapter's name or create a link to the parent chapter on the page.
+
+Example: `<a href="{{ item.thisChapter.urlRel }}">{{ item.thisChapter.name}}</a>`
+
+### {{ item.nextItem}}
+
+The next item. If the current item is 1.3.2, then the next item might be 1.3.3 or 1.4. 
+
+The `item.nextItem` is an item object again, so you have access to all the informations explained above. You can use the nextItem to create a pagination.
+
+Example: `<a href="{{ item.nextItem.urlRel }}">{{ item.nextItem.name }}</a>`
+
+### {{ item.prevItem}}
+
+The previous item. If the current item is 1.3.2, then the previous item is 1.3.1. If the current item is 1.3, then the previous item might be 1.2.8.
+
+The `item.prevItem` is an item object again, so you have access to all the informations explained above. You can use the prevItem to create a pagination.
+
+Example: `<a href="{{ item.prevItem.urlRel }}">{{ item.prevItem.name }}</a>`
+
+## Specific to Folders or Files
+
+The following informations are specific to files or folders
+
+### {{ item.fileType }}
+
+This information is only available for **files**. The fileType is `md` for Markdown. You will probably not need it for your theme.
+
+Example: `{% if item.elementType == 'file' %} {{ item.fileType}} {% endif %}`
+
+### {{ item.index }}
+
+This information is only available for **folders**. It indicates, if there exits an `index.md` file in the folder or not. If there is no index file with content for the folder, then you can display an alternative content.
+
+The whole usecase might look like this:
+
+```
+{% if item.elementType == 'folder' %}
+   {% if item.index %}
+     {{ content }}
+   {% else %}
+       <h1>{{ item.name }}</h1>
+       <p>Your alternative static content for a folder.</p>
+   {% endif %}
+{% endif %}
+```
+
+### {{ item.folderContent }}
+
+This information is only available for **folders**. It contains the whole content of that folder, again as an multidimensional array of item objects. You can use it to list the content of a folder.
+
+To do so, you have two options:
+
+1. Display only the first level items in the current folder. This can be done with a simple for loop.
+2. Display all nested items and folders within the current folder recursively. You have to write a Twig macro for that.
+
+The simple solution with all first level items of the current folder looks like this:
+
+````
+{% if item.elementType == 'folder' %}
+  <ul>
+    {% for sub in item.folderContent %}
+      <li>{{ sub.itemName }}</li>
+    {% endfor %}
+  </ul>
+{% endif %}
+````
+
+To display all items within the current folder you have to create a macro in a separate file like this first:
+
+````
+{% macro loop_over(folder) %}
+    {% for element in folder %}
+        {% if element.elementType == 'folder' %}
+		    <a href="{{ element.urlRel }}">{{ element.name }}</a>		
+             <ul>
+                 {{ macros.loop_over(element.folderContent) }}
+             </ul>
+            {% else %}
+				<a href="{{ element.urlRel }}">{{ element.name }}</a>
+            {% endif %}
+        </li>
+    {% endfor %}
+{% endmacro %}
+````
+
+Then you have to import the macro into your template and call it like this:
+
+```
+{% import 'folderMacro.twig' as macros %}
+{% if item.elementType == 'folder' %}
+    <ul>
+       {{ macros.loop_over(item.folderContent) }}
+    </ul>
+{% endif %}
+```
+
+You will learn more about macros in the chapter about the navigation variable.
+

+ 11 - 0
content/3_for-developers/05-theme-variables/15-breadcrumb.md

@@ -0,0 +1,11 @@
+# Breadcrumb
+
+The `{{ breadcrumb }}` variable contains the breadcrumb for the page as an one dimensional array. The array contains item objects. You can loop over the breadcrumb and print the elements out like this: 
+
+    <ul class="breadcrumb">
+    {% for element in breadcrumb %}
+        <li><a href="{{ element.urlRel }}">{{ element.name }}</a></li>
+    {% endfor %}
+    </ul>
+
+All informations of the items are available, so check the chapter about the item variable for more details.

+ 102 - 0
content/3_for-developers/05-theme-variables/25-navigation.md

@@ -0,0 +1,102 @@
+# Navigation
+
+The variable `{{ navigation }}` represents the structure of the whole content folder and can be used to create a navigation. 
+
+The `{{ navigation }}` variable is a multidimensional array of item objects. So you have access to nearly all informations, that an item object provides. Only the following informations for the paging is not part of the item objects within the navigation variable:
+
+- thisChapter
+- nextItem
+- prevItem
+
+The chapter about the `{{ item }}` variable lists all informations, that are provided by the item object. Read it, if you haven't done it yet.
+
+## Example of the {{ navigation }} variable 
+
+This is an example of the `{{ navigation }}`  variable containing just one folder and a file:
+
+    Array(
+       [0] => stdClass Object(
+           [originalName] => 0_about-typemill
+           [elementType] => folder
+           [index] => 1
+           [order] => 0
+           [name] => about typemill
+           [slug] => about-typemill
+           [path] => \0_about-typemill
+           [urlRel] => /about-typemill
+           [urlAbs] => http://localhost/about-typemill
+           [key] => 0
+           [keyPath] => 0
+           [keyPathArray] => Array
+           (
+               [0] => 0
+           )
+           [chapter] => 1
+           [folderContent] => Array
+           (
+               [0] => stdClass Object(
+                    [originalName] => 02-what-is-mardown.md
+                    [elementType] => file
+                    [fileType] => md
+                    [order] => 02
+                    [name] => what is mardown
+                    [slug] => what-is-mardown
+                    [path] => \0_about-robodoc\02-what-is-mardown.md
+                    [key] => 0
+                    [keyPath] => 0.0
+                    [keyPathArray] => Array
+                    (
+                        [0] => 0
+                        [1] => 0
+                    )
+                    [chapter] => 1.1
+                    [urlRel] => /about-robodoc/what-is-mardown
+                    [urlAbs] => http://localhost/about-robodoc/what-is-mardown
+                )
+            )
+        )
+    )
+
+## Create a Navigation for Your Theme
+
+To print out the navigation or a table of contents, you have to loop over  `{{ navigation }}` recursively. In Twig, you can do this with a macro. 
+
+In the following example, the macro is integrated in a separate template called "navigation.twig". You can also create a separate file with the macro (e.g. "navMacro.twig") and import it into your navigation template.
+
+The whole usecase with the macro and the navigation in one template looks like this:
+
+    {# define the macro #}
+    {% macro loop_over(navigation) %}
+    {% import _self as macros %}
+    {% for item in navigation %}
+        <li>
+            {% if item.elementType == 'folder' %}
+    			{% if item.index %}
+    				<a href="{{ item.urlRel }}">{{ item.name }}</a>
+    			{% else %}
+    				{{ item.name }}
+    			{% endif %}				
+                <ul>
+                    {{ macros.loop_over(item.folderContent) }}
+                </ul>
+            {% else %}
+    			<a href="{{ item.urlRel }}">{{ item.name }}</a>
+            {% endif %}
+        </li>
+    {% endfor %}
+    {% endmacro %}
+    
+    {# import the macro and use it to create the navigation #}
+    {% import _self as macros %}
+    <nav>
+        <ul class="main-menu">
+            {{ macros.loop_over(navigation) }}
+        </ul>
+    </nav>
+Just as a recommendation for your theme-structure: Typically you create a separate file like `navigation.twig`  with all the code above. Then you place this template in a folder like `partials`. You can include this navigation.twig-file in a `layout.twig` file, so that the navigation is included in all websites of your theme. So the structure might look like this:
+
+- theme
+  - partials
+    - layout.twig // includes navigation
+    - navigation.twig
+  - index.twig // extends layout.twig

+ 62 - 0
content/3_for-developers/05-theme-variables/30-settings.md

@@ -0,0 +1,62 @@
+# Settings
+
+The `{{ settings }}` variable is a simple array. It combines the default settings and the user specific settings of the `settings.yaml` file.
+
+## Useful Settings
+
+The following settings might be useful for your theme:
+
+### {{ settings.title }}
+
+The title of the website. The default value is `TYPEMILL`.
+
+### {{ settings.author }}
+
+Thee author of the website. The default value is `unknown`.
+
+### {{ settings.copyright }}
+
+The copyright of the website. The default value is `copyright`.
+
+### {{ settings.startpage }}
+
+Has a separate startpage or not. Default value is `true`.
+
+### {{ settings.theme }}
+
+The name of the theme that is in use. Default value is `typemill`.
+
+### {{ settings.version }}
+
+The version of TYPEMILL that is in use. A value of the format `0.0.1`.
+
+## Additional Settings
+
+There a some more settings that are probably not very useful for your theme:
+
+### {{ settings.themeFolder }}
+
+The folder of the theme. The default value is `theme`.
+
+### {{ settings.contentFolder }}
+
+The folder of the content. The default value is `content`. 
+
+### {{ settings.rootPath }}
+
+The full path to the root of the website. 
+
+### {{ settings.themePath }}
+
+The full path to the theme of the website.
+
+### {{ settings.authorPath }}
+
+The full path to the author theme. This theme is actually only in use for the setup path, but might hold an admin dashboard in future.
+
+### {{ settings.displayErrorDetails }}
+
+If the error display is off or on. Default value is `false`.
+
+Some more informations are provided by the Slim framework, that runs under the hood of TYPEMILL. You will probably never use them.
+

+ 3 - 0
content/3_for-developers/05-theme-variables/index.md

@@ -0,0 +1,3 @@
+# Theme Variables
+
+TYPEMILL provides **six variables** for your theme. They are easy to understand and simple to use.  

+ 3 - 0
content/3_for-developers/index.md

@@ -0,0 +1,3 @@
+# Hello Developers!
+
+If you love **lightweight systems**, stupid **simple theming** and the template language **Twig**, then TYPEMILL is for you!

+ 16 - 0
content/4_info/01-release-notes.md

@@ -0,0 +1,16 @@
+#Release Notes
+
+This is the version history with some release notes.
+
+## Version 1.0.0 (13.04.2017)
+The first alpha version of typemill with all basic features for a simple website:
+
+- **Content** with Markdown files and folders
+- **Settings** with YAML and a setup page
+- **Themes** with Twig and six theme variables
+  - {{ content }}
+  - {{ description }}
+  - {{ item }}
+  - {{ breadcrumb }}
+  - {{ navigation }}
+  - {{ settings }}

+ 16 - 0
content/4_info/05-usage-and-licence.md

@@ -0,0 +1,16 @@
+# Usage and Licence
+
+TYPEMILL is published under the MIT licence. This means, that you can do with it whatever you want. 
+
+You are always welcome to reference or link to TYPEMILL, to report bugs and to contribute to this project (e.g. share fixes, enhancements or ideas). If this software safed you a lot of time and money, then you are invited to donate some bucks, so I can save some money, too :-)
+
+---
+
+Copyright (c) 2017 Sebastian Schürmanns
+
+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.
+

+ 12 - 0
content/4_info/10-Imprint-and-privacy.md

@@ -0,0 +1,12 @@
+# Imprint
+
+The owner of this website is
+
+Sebastian Schürmanns
+
+Stendaler Str. 15
+
+10559 Berlin
+
+<trendschau@gmail.com>
+

+ 100 - 0
content/4_info/15_markdown-test.md

@@ -0,0 +1,100 @@
+# Test the Markdown-Styling
+
+This is just a test file to check, if all the html elements created by the markdown syntax are styled correctly. If you create a new template, please use this page to check your css styling.
+
+## Inline Elements
+
+This is an ordinary paragraph containing only simple text. 
+
+This is an _emphasis_ and this is a **bold** text. You can use asterixes to create an *emphasis* or an **bold** text, too. You can _emphasis more than one word_, but if you use it in_the_middle_of_the_word, then no emphasis will appear.
+
+This is a footnote [^1]. Please check at the end of this file, if two footnotes[^2] appear. 
+
+This is a [Link](http://writedown.net), you can also use a shortcut to create a <http://writedown.net> without a link text.
+
+## Headlines
+
+We already used some first and second level headlines, but check them in combination of other headlines. Now let us use a 
+
+### Third Level Headline
+
+This headline is ligthly more decent and should be visibly lower prioritized than a second level headline.
+
+#### Fourth Level Headline
+
+The fourth level headline will probably not used too often in usual text works, but you should still provide a design for it.
+
+##### Fifth Level Headline
+
+Yes, this is a really low level headline, probably only used by very scientific works or studies with a deep logical structure.
+
+###### Sixth Level Headline
+
+Finally a sixth level headline, and yes: This is really really low. But get your brain around it and provide some nice style!
+
+## Lists
+
+This is an unordered List: 
+
+- One Item
+- Another Item
+- An Item again
+
+This is an ordered List: 
+
+1. First Item
+2. Second Item
+3. Third Item
+
+And this is a definition List:
+
+Apple
+:   Pomaceous fruit of plants of the genus Malus in 
+the family Rosaceae.
+
+Orange
+:   The fruit of an evergreen tree of the genus Citrus.
+
+## Blockquote
+
+There always some women and men with wise words
+
+> But I usually don't read them, to be honest.
+
+## Tables
+
+Tables are a feature of Markdown Extra. Tables are not mentioned in the original Markdown specification.
+
+| Name      | Usage   |
+| --------- | ------- |
+| My Name   | For Me  |
+| Your Name | For You |
+
+## Abbreviations
+
+This is part of Markdown Extra, too.
+
+*[HTML]: Hyper Text Markup Language
+
+*[W3C]: World Wide Web Consortium
+
+The HTML specification is maintained by the W3C.
+
+## Code
+
+Let us create some `<?php inlineCode(); ?>` and now let us check, if a codeblock works:
+
+````
+<?php
+	$welcome = 'Hello World!';
+	echo $welcome;
+?>
+````
+
+
+
+
+
+[^1]: This is the first footnote
+[^2]: This is the second footnote
+

+ 3 - 0
content/4_info/index.md

@@ -0,0 +1,3 @@
+# Info
+
+Some informations like version history, copyright, licence and imprint.

+ 2 - 0
content/index.md

@@ -0,0 +1,2 @@
+TYPEMILL is a simple system to **publish** your **text-work** (markdown) as a **website**. Nearly no technical skills are required. Just download, learn and start.
+

+ 9 - 0
index.php

@@ -0,0 +1,9 @@
+<?php
+
+require __DIR__  . '/system/vendor/autoload.php';
+
+require __DIR__  . '/system/system.php';
+
+$app->run();
+
+?>

+ 7 - 0
licence.md

@@ -0,0 +1,7 @@
+Copyright (c) 2017 Sebastian Schürmanns
+
+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.

+ 50 - 0
readme.md

@@ -0,0 +1,50 @@
+# About TYPEMILL
+
+TYPEMILL is a small system to create a website based on Markdown files. It is perfect for web books, online manuals or documentations.
+
+To create a website, simply add your Markdown files to the content folder of TYPEMILL. TYPEMILL will take your files and folders and create a website with a corresponding navigation.
+
+TYPEMILL is a lightweight tool for writers, who do not want to fiddle around with complicated technology. If you are a developer, you can easily craft your own theme based on the template language Twig.
+
+![TYPEMILL Screenshot](/themes/typemill/typemill-large.jpg)
+
+## Documentation
+
+You can read the full documentation for writers and developers on the [TYPEMILL website](http://typemill.net).
+
+## Installation
+
+Download TYPEMILL from the [TYPEMILL website](http://typemill.net) or clone this repository with git. Open your git command line (e.g. gitbash), go to your project folder (e.g. htdocs) and type:
+
+    git clone git://github.com/trendschau/typemill.git
+
+Then open your command line, go to your fresh TYPEMILL folder and update the libraries with composer:
+
+    composer update
+If you did not use composer before, please go to the [composer website](http://getcomposer.org) and start to learn.
+
+To run TYPEMILL **live**, simply upload the files to your server.
+
+## Requirements
+
+Your server should run with PHP 5.6 or newer. No database is required.
+
+## Setup
+
+To setup TYPEMILL, please visit yourdomain.com/setup and fill out the forms.  
+
+You can also setup TYPEMILL manually: Go to the settings folder, copy the file `settings.yaml.example` and rename it to `settings.yaml`. Then open the file and edit the settings manually.
+
+It is recommended to setup your TYPEMILL website before you push it live, because the setup url is open to everybody. After the first setup, the setup url is not active anymore.
+
+Please read the full documentation on the [TYPEMILL website](http://typemill.net).
+
+## Contribute
+
+If you want to contribute to TYPEMILL, please fork this GitHub repository first. Then make your changes and create a pull request. I will review all request as soon as possible.
+
+For hints, questions, problems and support, please open up a new issue on GitHub.
+
+## Licence
+
+TYPEMILL is published under MIT licence.

+ 6 - 0
settings/settings.yaml.example

@@ -0,0 +1,6 @@
+title: MyWebsite
+author: 'Your Name'
+copyright: ©
+year: '2017'
+theme: robodoc
+startpage: true

+ 23 - 0
system/Controllers/Controller.php

@@ -0,0 +1,23 @@
+<?php
+
+namespace System\Controllers;
+
+/* Use the slim-container */
+use Interop\Container\ContainerInterface;
+
+abstract class Controller
+{
+	protected $c;
+
+	public function __construct(ContainerInterface $c)
+	{
+		$this->c = $c;
+	}
+	
+	protected function render404($response, $content = NULL)
+	{
+		return $this->c->view->render($response->withStatus(404), '/404.twig', $content);
+	}
+}
+
+?>

+ 132 - 0
system/Controllers/PageController.php

@@ -0,0 +1,132 @@
+<?php
+
+namespace System\Controllers;
+
+use System\Models\Folder;
+use System\Models\Cache;
+use System\Models\Helpers;
+
+class PageController extends Controller
+{
+	
+	public function index($request, $response, $args)
+	{
+		
+		/* Initiate Variables */
+		$structure		= false;
+		$contentHTML	= false;
+		$item			= false;
+		$breadcrumb 	= false;
+		$description	= '';
+		$settings		= $this->c->get('settings');
+		$pathToContent	= $settings['rootPath'] . $settings['contentFolder'];
+		$cache 			= new Cache();
+		$uri 			= $request->getUri();
+		$base_url		= $uri->getBaseUrl();
+		
+		if($cache->validate())
+		{
+			$structure	= $this->getCachedStructure($cache);
+			$cached 	= true;
+		}
+		else
+		{
+			$structure 	= $this->getFreshStructure($pathToContent, $cache, $uri);
+			$cached		= false;
+			
+			if(!$structure)
+			{ 
+				$content = '<h1>No Content</h1><p>Your content folder is empty.</p>'; 
+				$this->c->view->render($response, '/index.twig', [ 'content' => $content ]);
+			}
+		}
+
+		/* if the user is on startpage */
+		if(empty($args))
+		{
+			/* check, if there is an index-file in the root of the content folder */
+			$contentMD = file_exists($pathToContent . DIRECTORY_SEPARATOR . 'index.md') ? file_get_contents($pathToContent . DIRECTORY_SEPARATOR . 'index.md') : NULL;
+		}
+		else
+		{
+			/* get the request url */
+			$urlRel = $uri->getBasePath() . '/' . $args['params'];			
+			
+			/* find the url in the content-item-tree and return the item-object for the file */
+			$item = Folder::getItemForUrl($structure, $urlRel);
+
+			if(!$item && $cached)
+			{
+				$structure = $this->getFreshStructure($pathToContent, $cache, $uri); 
+				$item = Folder::getItemForUrl($structure, $urlRel);
+			}
+			if(!$item){	return $this->render404($response, array( 'navigation' => $structure, 'settings' => $settings,  'base_url' => $base_url )); }
+			
+			/* get breadcrumb for page */
+			$breadcrumb = Folder::getBreadcrumb($structure, $item->keyPathArray);
+
+			/* add the paging to the item */
+			$item = Folder::getPagingForItem($structure, $item);
+
+			/* check if url is a folder. If so, check if there is an index-file for the folder */
+			if($item->elementType == 'folder' && $item->index)
+			{
+				$filePath = $pathToContent . $item->path . DIRECTORY_SEPARATOR . 'index.md';
+			}
+			elseif($item->elementType == 'file')
+			{
+				$filePath = $pathToContent . $item->path;
+			}
+
+			/* read the content of the file */
+			$contentMD = isset($filePath) ? file_get_contents($filePath) : false;
+		}
+		
+		/* initialize parsedown */
+		$Parsedown = new \ParsedownExtra();
+
+		/* parse markdown-file to html-string */
+		$contentHTML = $Parsedown->text($contentMD);
+		$description = substr(strip_tags($contentHTML),0,150);
+		$description = trim(preg_replace('/\s+/', ' ', $description));
+		
+		/* 
+			$timer['topiccontroller']=microtime(true);
+			$timer['end topiccontroller']=microtime(true);
+			Helpers::printTimer($timer);
+		*/
+		
+		$route = empty($args) && $settings['startpage'] ? '/cover.twig' : '/index.twig';
+
+		$this->c->view->render($response, $route, array('navigation' => $structure, 'content' => $contentHTML, 'item' => $item, 'breadcrumb' => $breadcrumb, 'settings' => $settings, 'description' => $description, 'base_url' => $base_url ));
+	}
+
+	
+	protected function getCachedStructure($cache)
+	{
+		return $cache->getData('structure');
+	}
+
+	
+	protected function getFreshStructure($pathToContent, $cache, $uri)
+	{
+		/* scan the content of the folder */
+		$structure = Folder::scanFolder($pathToContent);
+
+		/* if there is no content, render an empty page */
+		if(count($structure) == 0)
+		{
+			return false;
+		}
+
+		/* create an array of object with the whole content of the folder */
+		$structure = Folder::getFolderContentDetails($structure, $uri->getBaseUrl(), $uri->getBasePath());
+		
+		/* cache navigation */
+		$cache->refresh($structure, 'structure');
+		
+		return $structure;
+	}	
+}
+
+?>

+ 138 - 0
system/Controllers/SetupController.php

@@ -0,0 +1,138 @@
+<?php
+
+namespace System\Controllers;
+
+use \Symfony\Component\Yaml\Yaml;
+
+class SetupController extends Controller
+{
+	public function setup($request, $response, $args)
+	{				
+		$themes 		= $this->getThemes();
+		$copyright 		= $this->getCopyright();
+		$uri 			= $request->getUri();
+		$base_url		= $uri->getBaseUrl();
+		$errors 		= false;
+		
+		/* Check, if setting folder is */
+		if(!is_writable($this->c->get('settings')['settingsPath'])){ $errors['folder'] = 'Your settings folder is not writable.'; }
+				
+		$data = array(
+			'themes' 	=> $themes,
+			'copyright'	=> $copyright,
+			'inputs'	=> false,
+			'errors'	=> $errors,
+			'base_url'	=> $base_url
+		);
+		$this->c->view->render($response, '/setup.twig', $data);
+	}
+	
+	public function save($request, $response, $args)
+	{
+		if($request->isPost())
+		{
+			$params 	= $request->getParams();
+			
+			$copyright	= $this->getCopyright();
+			$themes		= $this->getThemes();
+			$errors 	= array();
+			$uri 		= $request->getUri();
+			$base_url	= $uri->getBaseUrl();
+
+			/* Validate Title */
+			if(!isset($params['title'])){ $errors['title'] = 'Please add a title. '; }
+			if(strlen($params['title']) < 2){ $errors['title'] = 'Title is too short (< 2). '; }
+			if(strlen($params['title']) > 20){ $errors['title'] = 'Title is too long (> 20). '; }			
+			
+			/* Validate Author */
+			if(isset($params['author']) && !empty($params['author']))
+			{
+				if(strlen($params['author']) < 2){ $errors['author'] = 'Text is too short (< 2). '; }
+				if(strlen($params['author']) > 40){ $errors['author'] .= 'Text is too long (> 40). '; } 
+				if(preg_match('/[\(\)\[\]\{\}\?\*\$\"\'\|<>=!;@#%§]/', $params['author'])){ $errors['author'] .= 'Only special chars like a,b a-b a_b a&b are allowed.'; }
+			}
+			
+			/* Validate Year */
+			if(!isset($params['year'])){ $errors['year'] = 'Please add a year, e.g. 2017.'; }
+			if(!preg_match('/^(\d{4})$/', $params['year'])){ $errors['year'] = 'Use four digits for the year like 2017.'; }
+			
+			/* Validate Copyright */
+			if(isset($params['copyright']) AND !in_array($params['copyright'], $copyright )){ $errors['copyright'] = 'Please select a valid copyright.'; }
+			
+			/* Validate Theme */
+			if(!isset($params['theme']) AND !in_array($params['theme'], $themes)){ $errors['theme'] = 'Please select a valid theme.'; }
+			
+			/* Validate Startpage */
+			if(isset($params['startpage'])){ $params['startpage'] = true; }else{ $params['startpage'] = false; }
+			
+			/* Validate Folder Writable */
+			if(!is_writable($this->c->get('settings')['settingsPath'])){ $errors['folder'] = 'Your settings folder is not writable.'; }
+			
+			/* Prevent Title From Hacking */
+			$params['title'] = htmlentities(stripslashes($params['title']));
+			
+			if(!empty($errors))
+			{
+				$data = array(
+					'themes' 	=> $themes,
+					'copyright' => $copyright,
+					'errors'	=> $errors,
+					'inputs'	=> $params,
+					'base_url'	=> $base_url
+					
+				);
+				$this->c->view->render($response, '/setup.twig', $data);
+			}
+			else
+			{
+				$file 			= $this->c->get('settings')['settingsPath'] . DIRECTORY_SEPARATOR . 'settings.yaml';
+				$fh 			= fopen($file, 'w');
+				$yaml 			= Yaml::dump($params);
+				
+				file_put_contents($file, $yaml);
+
+				$data = array(
+					'inputs'	=> $params,
+					'base_url'	=> $base_url
+					
+				);
+				
+				$this->c->view->render($response, '/welcome.twig', $data);
+			}
+		}
+	}
+	
+	private function getCopyright()
+	{
+		return array(
+			"©",
+			"CC-BY",
+			"CC-BY-NC",
+			"CC-BY-NC-ND",
+			"CC-BY-NC-SA",
+			"CC-BY-ND",
+			"CC-BY-SA",
+			"None"
+		);
+	}
+	
+	private function getThemes()
+	{
+		$themeFolder 	= $this->c->get('settings')['rootPath'] . $this->c->get('settings')['themeFolder'];
+		$themeFolderC 	= scandir($themeFolder);
+		$themes 		= array();
+		foreach ($themeFolderC as $key => $theme)
+		{
+			if (!in_array($theme, array(".","..")))
+			{
+				if (is_dir($themeFolder . DIRECTORY_SEPARATOR . $theme))
+				{
+					$themes[] = $theme;
+				}
+			}
+		}
+		return $themes;
+	}
+}
+
+?>

+ 81 - 0
system/Models/Cache.php

@@ -0,0 +1,81 @@
+<?php
+
+namespace System\Models;
+
+class Cache
+{
+	private $cachePath;
+
+	public function __construct()
+	{
+		$cachePath = getcwd() . DIRECTORY_SEPARATOR . 'cache' . DIRECTORY_SEPARATOR;
+		if(!is_dir($cachePath)){ 
+			mkdir($cachePath, 0774, true) or die('Please create a cache folder in your root and make it writable.');
+		}
+		is_writable($cachePath) or die('Your cache folder is not writable.');
+		$this->cachePath = $cachePath;
+	}
+	
+	public function validate()
+	{
+		if(isset($_SERVER['HTTP_CACHE_CONTROL']) && $_SERVER['HTTP_CACHE_CONTROL'] == 'max-age=0')
+		{
+			return false;
+		}
+		
+		$requestFile = $this->cachePath.'request.txt';
+		if(!file_exists($requestFile))
+		{
+			$this->writeFile($requestFile, time());
+			return false;
+		}
+		
+		$lastRequest = file_get_contents($requestFile);
+		if(time() - $lastRequest > 600)
+		{
+			return false;
+		}
+
+		return true;
+	}
+	
+	public function refresh($data, $name)
+	{
+		$sData 			= serialize($data);
+		$dataFile 		= $this->cachePath.$name.'.txt';
+		$requestFile	= $this->cachePath.'request.txt';
+		
+		$this->writeFile($dataFile, $sData);
+		$this->writeFile($requestFile, time());		
+	}
+		
+	public function getData($name)
+	{
+		if (file_exists($this->cachePath.$name.'.txt'))
+		{
+			$data = file_get_contents($this->cachePath.$name.'.txt');
+			$data = unserialize($data);
+			return $data;
+		}
+		return false;
+	}
+	
+	public function clearData($name)
+	{
+		/* todo */
+	}
+	
+	public function clearAll()
+	{
+		/* todo */
+	}
+	
+	public function writeFile($file, $data)
+	{
+		$fp = fopen($file, "w");
+		fwrite($fp, $data);
+		fclose($fp);
+	}
+}
+
+?>

+ 274 - 0
system/Models/Folder.php

@@ -0,0 +1,274 @@
+<?php
+
+namespace System\Models;
+
+use \URLify;
+
+class Folder
+{	
+	/*
+	* scans content of a folder recursively
+	* vars: folder path as string
+	* returns: multi-dimensional array with names of folders and files
+	*/
+	public static function scanFolder($folderPath)
+	{
+		$folderItems 	= scandir($folderPath);
+		$folderContent 	= array();
+		
+		foreach ($folderItems as $key => $item)
+		{
+			if (!in_array($item, array(".","..")))
+			{
+				if (is_dir($folderPath . DIRECTORY_SEPARATOR . $item))
+				{
+					$subFolder 					= $item;
+					$folderContent[$subFolder] 	= self::scanFolder($folderPath . DIRECTORY_SEPARATOR . $subFolder);					
+				}
+				else
+				{
+					$file						= $item;
+					$folderContent[] 			= $file;
+				}
+			}
+		}
+		return $folderContent;
+	}
+	
+	/*
+	* Transforms array of folder item into an array of item-objects with additional information for each item
+	* vars: multidimensional array with folder- and file-names
+	* returns: array of objects. Each object contains information about an item (file or folder).
+	*/	
+	public static function getFolderContentDetails(array $folderContent, $baseUrl, $fullSlug = NULL, $fullPath = NULL, $keyPath = NULL, $chapter = NULL)
+	{
+		$contentDetails 	= [];
+		$iteration 			= 0;
+		$chapternr 			= 1;
+
+		foreach($folderContent as $key => $name)
+		{
+			$item = new \stdClass();
+						
+			if(is_array($name))
+			{
+				$nameParts = self::getStringParts($key);
+				
+				$item->originalName 	= $key;
+				$item->elementType		= 'folder';
+				$item->index			= array_search('index.md', $name) === false ? false : true;
+				$item->order 			= count($nameParts) > 1 ? array_shift($nameParts) : NULL;
+				$item->name 			= implode(" ",$nameParts);
+				$item->name				= iconv('ISO-8859-15', 'UTF-8', $item->name);
+				$item->slug				= implode("-",$nameParts);
+				$item->slug				= URLify::filter(iconv('ISO-8859-15', 'UTF-8', $item->slug));
+				$item->path				= $fullPath . DIRECTORY_SEPARATOR . $key;
+				$item->urlRel			= $fullSlug . '/' . $item->slug;
+				$item->urlAbs			= $baseUrl . $fullSlug . '/' . $item->slug;
+				$item->key				= $iteration;
+				$item->keyPath			= $keyPath ? $keyPath . '.' . $iteration : $iteration;
+				$item->keyPathArray		= explode('.', $item->keyPath);
+				$item->chapter			= $chapter ? $chapter . '.' . $chapternr : $chapternr;
+				
+				$item->folderContent 	= self::getFolderContentDetails($name, $baseUrl, $item->urlRel, $item->path, $item->keyPath, $item->chapter);
+			}
+			else
+			{
+				$nameParts 				= self::getStringParts($name);
+				$fileType 				= array_pop($nameParts);
+				
+				if($name == 'index.md' || $fileType !== 'md' ) break;
+												
+				$item->originalName 	= $name;
+				$item->elementType		= 'file';
+				$item->fileType			= $fileType;
+				$item->order 			= count($nameParts) > 1 ? array_shift($nameParts) : NULL;
+				$item->name 			= implode(" ",$nameParts);
+				$item->name				= iconv('ISO-8859-15', 'UTF-8', $item->name);
+				$item->slug				= implode("-",$nameParts);
+				$item->slug				= URLify::filter(iconv('ISO-8859-15', 'UTF-8', $item->slug));
+				$item->path				= $fullPath . DIRECTORY_SEPARATOR . $name;
+				$item->key				= $iteration;
+				$item->keyPath			= $keyPath . '.' . $iteration;
+				$item->keyPathArray		= explode('.',$item->keyPath);
+				$item->chapter			= $chapter . '.' . $chapternr;
+				$item->urlRel			= $fullSlug . '/' . $item->slug;
+				$item->urlAbs			= $baseUrl . $fullSlug . '/' . $item->slug;
+			}
+			$iteration++;
+			$chapternr++;
+			$contentDetails[]		= $item;
+		}
+		return $contentDetails;	
+	}
+
+	public static function getItemForUrl($folderContentDetails, $url, $result = NULL)
+	{
+		foreach($folderContentDetails as $key => $item)
+		{
+			if($item->urlRel === $url)
+			{
+				$item->active = true;
+				$result = $item;
+			}
+			elseif($item->elementType === "folder")
+			{
+				$result = self::getItemForUrl($item->folderContent, $url, $result);
+			}
+		}
+		return $result;
+	}	
+
+	public static function getPagingForItem($content, $item)
+	{
+		$keyPos 			= count($item->keyPathArray)-1;
+		$thisChapArray		= $item->keyPathArray;
+		$nextItemArray 		= $item->keyPathArray;
+		$prevItemArray 		= $item->keyPathArray;
+		
+		$item->thisChapter 	= false;
+		$item->prevItem 	= false;
+		$item->nextItem 	= false;
+		
+		
+		/************************
+		* 	ADD THIS CHAPTER 	*
+		************************/
+
+		if($keyPos > 0)
+		{
+			array_pop($thisChapArray);
+			$item->thisChapter = self::getItemWithKeyPath($content, $thisChapArray);
+		}
+		
+		/************************
+		* 	ADD NEXT ITEM	 	*
+		************************/
+				
+		if($item->elementType == 'folder')
+		{
+			/* get the first element in the folder */
+			$item->nextItem = isset($item->folderContent[0]) ? $item->folderContent[0] : false;
+		}
+		
+		if(!$item->nextItem)
+		{
+			$nextItemArray[$keyPos]++;
+			$item->nextItem = self::getItemWithKeyPath($content, $nextItemArray);
+		}
+		
+		while(!$item->nextItem)
+		{
+			array_pop($nextItemArray);
+			if(empty($nextItemArray)) break; 
+			$newKeyPos = count($nextItemArray)-1;
+			$nextItemArray[$newKeyPos]++;
+			$item->nextItem = self::getItemWithKeyPath($content, $nextItemArray);
+		}
+
+		/************************
+		* 	ADD PREVIOUS ITEM	*
+		************************/
+		
+		if($prevItemArray[$keyPos] > 0)
+		{
+			$prevItemArray[$keyPos]--;
+			$item->prevItem = self::getItemWithKeyPath($content, $prevItemArray);
+			
+			if($item->prevItem && $item->prevItem->elementType == 'folder' && !empty($item->prevItem->folderContent))
+			{
+				/* get last item in folder */
+				$item->prevItem = self::getLastItemOfFolder($item->prevItem);
+			}
+		}
+		else
+		{
+			$item->prevItem = $item->thisChapter;
+		}
+		
+		if($item->prevItem && $item->prevItem->elementType == 'folder'){ unset($item->prevItem->folderContent); }
+		if($item->nextItem && $item->nextItem->elementType == 'folder'){ unset($item->nextItem->folderContent); }
+		if($item->thisChapter){unset($item->thisChapter->folderContent); }
+		
+		return $item;
+	}
+		
+	public static function getItemWithKeyPath($content, array $searchArray)
+	{
+		$item = false;
+
+		foreach($searchArray as $key => $itemKey)
+		{
+			$item = isset($content[$itemKey]) ? clone($content[$itemKey]) : false;
+			
+			unset($searchArray[$key]);
+			if(!empty($searchArray) && $item)
+			{
+				return self::getItemWithKeyPath($item->folderContent, $searchArray);
+			}
+		}
+		return $item;
+	}
+
+	/* get breadcrumb as copied array, set elements active in original and mark parent element in original */
+	public static function getBreadcrumb($content, $searchArray, $i = NULL, $breadcrumb = NULL)
+	{
+		if(!$i){ $i = 0; $breadcrumb = array();}
+		
+		while($i < count($searchArray))
+		{
+			$item = $content[$searchArray[$i]];
+			$item->active = true;
+			if($i == count($searchArray)-2)
+			{
+				$item->activeParent = true; 
+			}
+
+			$copy = clone($item);
+			if($copy->elementType == 'folder')
+			{
+				unset($copy->folderContent);
+				$content = $item->folderContent;
+			}
+			$breadcrumb[] = $copy;
+			
+			$i++;
+			return self::getBreadcrumb($content, $searchArray, $i++, $breadcrumb);
+		}
+		return $breadcrumb;
+	}
+	
+	public static function getParentItem($content, $searchArray, $iteration = NULL)
+	{
+		if(!$iteration){ $iteration = 0; }
+		while($iteration < count($searchArray)-2)
+		{
+			$content = $content[$searchArray[$iteration]]->folderContent;
+			$iteration++;
+			return self::getParentItem($content, $searchArray, $iteration);
+		}
+		return $content[$searchArray[$iteration]];
+	}
+	
+	private static function getLastItemOfFolder($folder)
+	{	
+		$lastItem = end($folder->folderContent);
+		if(is_object($lastItem) && $lastItem->elementType == 'folder' && !empty($lastItem->folderContent))
+		{
+			return self::getLastItemOfFolder($lastItem);
+		}
+		return $lastItem;
+	}
+
+	public static function getStringParts($name)
+	{
+		return preg_split('/[\-\.\_\=\+\?\!\*\#\(\)\/ ]/',$name);
+	}
+	
+	public static function getFileType($fileName)
+	{
+		$parts = preg_split('/\./',$fileName);
+		return end($parts);
+	}	
+}
+?>

+ 28 - 0
system/Models/Helpers.php

@@ -0,0 +1,28 @@
+<?php
+
+namespace System\Models;
+
+class Helpers{
+
+	public static function printTimer($timer)
+	{
+		$lastTime = NULL;
+		$table = '<html><body><table>';
+		$table .= '<tr><th>Breakpoint</th><th>Time</th><th>Duration</th></tr>';
+		foreach($timer as $breakpoint => $time)
+		{
+			$duration = $time - $lastTime;
+			
+			$table .= '<tr>';
+			$table .= '<td>' . $breakpoint . '</td>';
+			$table .= '<td>' . $time . '</td>';
+			$table .= '<td>' . $duration . '</td>';
+			$table .= '</tr>';
+			
+			$lastTime = $time;
+		}
+		$table .= '</table></body></html>';
+		echo $table;
+		exit;
+	}
+}

+ 7 - 0
system/Routes/api.php

@@ -0,0 +1,7 @@
+<?php
+/*
+use App\Controllers\ApiController;
+
+$app->get('/api', ApiController::class . ':index' )->setName('api.index');
+*/
+?>

+ 13 - 0
system/Routes/web.php

@@ -0,0 +1,13 @@
+<?php
+
+use System\Controllers\PageController;
+use System\Controllers\SetupController;
+
+if(!isset($userSettings))
+{
+	$app->get('/setup', SetupController::class . ':setup')->setName('setup');
+	$app->post('/setup', SetupController::class . ':save')->setName('save');
+}
+
+$app->get('/[{params:.*}]', PageController::class . ':index');
+?>

+ 461 - 0
system/author/css/normalize.css

@@ -0,0 +1,461 @@
+/*! normalize.css v5.0.0 | MIT License | github.com/necolas/normalize.css */
+
+/**
+ * 1. Change the default font family in all browsers (opinionated).
+ * 2. Correct the line height in all browsers.
+ * 3. Prevent adjustments of font size after orientation changes in
+ *    IE on Windows Phone and in iOS.
+ */
+
+/* Document
+   ========================================================================== */
+
+html {
+  font-family: sans-serif; /* 1 */
+  line-height: 1.15; /* 2 */
+  -ms-text-size-adjust: 100%; /* 3 */
+  -webkit-text-size-adjust: 100%; /* 3 */
+}
+
+/* Sections
+   ========================================================================== */
+
+/**
+ * Remove the margin in all browsers (opinionated).
+ */
+
+body {
+  margin: 0;
+}
+
+/**
+ * Add the correct display in IE 9-.
+ */
+
+article,
+aside,
+footer,
+header,
+nav,
+section {
+  display: block;
+}
+
+/**
+ * Correct the font size and margin on `h1` elements within `section` and
+ * `article` contexts in Chrome, Firefox, and Safari.
+ */
+
+h1 {
+  font-size: 2em;
+  margin: 0.67em 0;
+}
+
+/* Grouping content
+   ========================================================================== */
+
+/**
+ * Add the correct display in IE 9-.
+ * 1. Add the correct display in IE.
+ */
+
+figcaption,
+figure,
+main { /* 1 */
+  display: block;
+}
+
+/**
+ * Add the correct margin in IE 8.
+ */
+
+figure {
+  margin: 1em 40px;
+}
+
+/**
+ * 1. Add the correct box sizing in Firefox.
+ * 2. Show the overflow in Edge and IE.
+ */
+
+hr {
+  box-sizing: content-box; /* 1 */
+  height: 0; /* 1 */
+  overflow: visible; /* 2 */
+}
+
+/**
+ * 1. Correct the inheritance and scaling of font size in all browsers.
+ * 2. Correct the odd `em` font sizing in all browsers.
+ */
+
+pre {
+  font-family: monospace, monospace; /* 1 */
+  font-size: 1em; /* 2 */
+}
+
+/* Text-level semantics
+   ========================================================================== */
+
+/**
+ * 1. Remove the gray background on active links in IE 10.
+ * 2. Remove gaps in links underline in iOS 8+ and Safari 8+.
+ */
+
+a {
+  background-color: transparent; /* 1 */
+  -webkit-text-decoration-skip: objects; /* 2 */
+}
+
+/**
+ * Remove the outline on focused links when they are also active or hovered
+ * in all browsers (opinionated).
+ */
+
+a:active,
+a:hover {
+  outline-width: 0;
+}
+
+/**
+ * 1. Remove the bottom border in Firefox 39-.
+ * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
+ */
+
+abbr[title] {
+  border-bottom: none; /* 1 */
+  text-decoration: underline; /* 2 */
+  text-decoration: underline dotted; /* 2 */
+}
+
+/**
+ * Prevent the duplicate application of `bolder` by the next rule in Safari 6.
+ */
+
+b,
+strong {
+  font-weight: inherit;
+}
+
+/**
+ * Add the correct font weight in Chrome, Edge, and Safari.
+ */
+
+b,
+strong {
+  font-weight: bolder;
+}
+
+/**
+ * 1. Correct the inheritance and scaling of font size in all browsers.
+ * 2. Correct the odd `em` font sizing in all browsers.
+ */
+
+code,
+kbd,
+samp {
+  font-family: monospace, monospace; /* 1 */
+  font-size: 1em; /* 2 */
+}
+
+/**
+ * Add the correct font style in Android 4.3-.
+ */
+
+dfn {
+  font-style: italic;
+}
+
+/**
+ * Add the correct background and color in IE 9-.
+ */
+
+mark {
+  background-color: #ff0;
+  color: #000;
+}
+
+/**
+ * Add the correct font size in all browsers.
+ */
+
+small {
+  font-size: 80%;
+}
+
+/**
+ * Prevent `sub` and `sup` elements from affecting the line height in
+ * all browsers.
+ */
+
+sub,
+sup {
+  font-size: 75%;
+  line-height: 0;
+  position: relative;
+  vertical-align: baseline;
+}
+
+sub {
+  bottom: -0.25em;
+}
+
+sup {
+  top: -0.5em;
+}
+
+/* Embedded content
+   ========================================================================== */
+
+/**
+ * Add the correct display in IE 9-.
+ */
+
+audio,
+video {
+  display: inline-block;
+}
+
+/**
+ * Add the correct display in iOS 4-7.
+ */
+
+audio:not([controls]) {
+  display: none;
+  height: 0;
+}
+
+/**
+ * Remove the border on images inside links in IE 10-.
+ */
+
+img {
+  border-style: none;
+}
+
+/**
+ * Hide the overflow in IE.
+ */
+
+svg:not(:root) {
+  overflow: hidden;
+}
+
+/* Forms
+   ========================================================================== */
+
+/**
+ * 1. Change the font styles in all browsers (opinionated).
+ * 2. Remove the margin in Firefox and Safari.
+ */
+
+button,
+input,
+optgroup,
+select,
+textarea {
+  font-family: sans-serif; /* 1 */
+  font-size: 100%; /* 1 */
+  line-height: 1.15; /* 1 */
+  margin: 0; /* 2 */
+}
+
+/**
+ * Show the overflow in IE.
+ * 1. Show the overflow in Edge.
+ */
+
+button,
+input { /* 1 */
+  overflow: visible;
+}
+
+/**
+ * Remove the inheritance of text transform in Edge, Firefox, and IE.
+ * 1. Remove the inheritance of text transform in Firefox.
+ */
+
+button,
+select { /* 1 */
+  text-transform: none;
+}
+
+/**
+ * 1. Prevent a WebKit bug where (2) destroys native `audio` and `video`
+ *    controls in Android 4.
+ * 2. Correct the inability to style clickable types in iOS and Safari.
+ */
+
+button,
+html [type="button"], /* 1 */
+[type="reset"],
+[type="submit"] {
+  -webkit-appearance: button; /* 2 */
+}
+
+/**
+ * Remove the inner border and padding in Firefox.
+ */
+
+button::-moz-focus-inner,
+[type="button"]::-moz-focus-inner,
+[type="reset"]::-moz-focus-inner,
+[type="submit"]::-moz-focus-inner {
+  border-style: none;
+  padding: 0;
+}
+
+/**
+ * Restore the focus styles unset by the previous rule.
+ */
+
+button:-moz-focusring,
+[type="button"]:-moz-focusring,
+[type="reset"]:-moz-focusring,
+[type="submit"]:-moz-focusring {
+  outline: 1px dotted ButtonText;
+}
+
+/**
+ * Change the border, margin, and padding in all browsers (opinionated).
+ */
+
+fieldset {
+  border: 1px solid #c0c0c0;
+  margin: 0 2px;
+  padding: 0.35em 0.625em 0.75em;
+}
+
+/**
+ * 1. Correct the text wrapping in Edge and IE.
+ * 2. Correct the color inheritance from `fieldset` elements in IE.
+ * 3. Remove the padding so developers are not caught out when they zero out
+ *    `fieldset` elements in all browsers.
+ */
+
+legend {
+  box-sizing: border-box; /* 1 */
+  color: inherit; /* 2 */
+  display: table; /* 1 */
+  max-width: 100%; /* 1 */
+  padding: 0; /* 3 */
+  white-space: normal; /* 1 */
+}
+
+/**
+ * 1. Add the correct display in IE 9-.
+ * 2. Add the correct vertical alignment in Chrome, Firefox, and Opera.
+ */
+
+progress {
+  display: inline-block; /* 1 */
+  vertical-align: baseline; /* 2 */
+}
+
+/**
+ * Remove the default vertical scrollbar in IE.
+ */
+
+textarea {
+  overflow: auto;
+}
+
+/**
+ * 1. Add the correct box sizing in IE 10-.
+ * 2. Remove the padding in IE 10-.
+ */
+
+[type="checkbox"],
+[type="radio"] {
+  box-sizing: border-box; /* 1 */
+  padding: 0; /* 2 */
+}
+
+/**
+ * Correct the cursor style of increment and decrement buttons in Chrome.
+ */
+
+[type="number"]::-webkit-inner-spin-button,
+[type="number"]::-webkit-outer-spin-button {
+  height: auto;
+}
+
+/**
+ * 1. Correct the odd appearance in Chrome and Safari.
+ * 2. Correct the outline style in Safari.
+ */
+
+[type="search"] {
+  -webkit-appearance: textfield; /* 1 */
+  outline-offset: -2px; /* 2 */
+}
+
+/**
+ * Remove the inner padding and cancel buttons in Chrome and Safari on macOS.
+ */
+
+[type="search"]::-webkit-search-cancel-button,
+[type="search"]::-webkit-search-decoration {
+  -webkit-appearance: none;
+}
+
+/**
+ * 1. Correct the inability to style clickable types in iOS and Safari.
+ * 2. Change font properties to `inherit` in Safari.
+ */
+
+::-webkit-file-upload-button {
+  -webkit-appearance: button; /* 1 */
+  font: inherit; /* 2 */
+}
+
+/* Interactive
+   ========================================================================== */
+
+/*
+ * Add the correct display in IE 9-.
+ * 1. Add the correct display in Edge, IE, and Firefox.
+ */
+
+details, /* 1 */
+menu {
+  display: block;
+}
+
+/*
+ * Add the correct display in all browsers.
+ */
+
+summary {
+  display: list-item;
+}
+
+/* Scripting
+   ========================================================================== */
+
+/**
+ * Add the correct display in IE 9-.
+ */
+
+canvas {
+  display: inline-block;
+}
+
+/**
+ * Add the correct display in IE.
+ */
+
+template {
+  display: none;
+}
+
+/* Hidden
+   ========================================================================== */
+
+/**
+ * Add the correct display in IE 10-.
+ */
+
+[hidden] {
+  display: none;
+}

+ 231 - 0
system/author/css/style.css

@@ -0,0 +1,231 @@
+/**********************
+*  		HELPERS		  *
+**********************/
+
+a, a:link, a:visited, a:focus, a:hover, a:active, button, .button, input{
+	-webkit-transition: all 0.2s ease;
+	-moz-transition: all 0.2s ease;
+	-o-transition: all 0.2s ease;
+	-ms-transition: all 0.2s ease;
+	transition: all 0.2s ease;
+}
+
+/**********************
+*    	 COLORS 	  *
+**********************/
+
+body{ 								background: #f9f8f6; color: #444; }
+.card{ 								background: #FFF; }
+.card header{						background: #e0494c; color: #f9f8f6; }
+.onoffswitch-label {				border: 0px solid #DDD; }
+.onoffswitch-inner:before {			background: #8ce196; color: #f9f8f6; }
+.onoffswitch-inner:after {			background: #e0474c; color: #f9f8f6; }
+.onoffswitch-switch {				background: #f9f8f6; border: 1px solid #999; }
+input, select{ 						border: 1px solid #ddd;	background: #fff; }
+select:focus, input:focus{			border: 1px solid #FFF; outline: none; box-shadow: 0 0 2px #e0474c; }
+input[type="submit"]{				border: 2px solid #FFF; background: #e0474c; color: #f9f8f6; }
+input[type="submit"]:hover{			background: #FFF; color: #444; }
+a.button{							border: 2px solid #e0474c; background: #e0474c; color: #f9f8f6; }
+a.button:hover{						border: 2px solid #e0474c; background: #FFF; color: #444; }
+.error label{						color: #e0474c; }
+.error input, .error select{		border: 1px solid #e0474c; }
+.error small, .error p{				color: #e0474c; }
+
+/********************
+*  		FONTS 	    *
+********************/
+
+header, nav, h1, h2, h3, h4, h5, h6{
+	font-family: arial, sans-serif;
+}
+
+/********************
+*  	   HEADLINES    *
+********************/
+
+h1, h2, h3, h4, h5, h6{ font-weight: 700; }
+h1{ font-size: 1em; margin: 0.6em 0 0.6em; }
+h2{ font-size: 1em; margin: 0.6em 0 0.6em; }
+h3{	font-size: 1em; margin: 0.6em 0 0.6em; }
+
+html,body{
+	padding: 0;
+	margin:0;
+}
+body{
+	padding: 20px;
+	font-size: 18px;
+}
+.card{
+	display: block;
+	margin: auto;
+	max-width: 400px;
+	box-shadow: 0 2px 5px 0 rgba(0,0,0,0.16),0 2px 10px 0 rgba(0,0,0,0.12);
+}
+.card img{
+	width: 100%;
+}
+.card header{
+	display: inlin-block;
+	width: 100%;
+	padding: 20px;
+	box-sizing: border-box;
+}
+.card header h1{
+	display: inline-block;
+}
+form{}
+fieldset{
+	padding: 30px 20px;
+	margin: 0;
+	box-sizing: border-box;
+	border: none;
+}
+label,.label{
+	display: block;
+	font-size: 0.65em;
+	font-weight: 300;
+	padding: 15px 0 0;
+	line-height: 1.5em;
+	text-transform: uppercase;
+}
+.field{
+	margin: 5px 0;
+	box-sizing: border-box;
+}
+.size100{
+	width: 100%;
+}
+.size25, .size50, .size75{
+	display: inline-block;
+	vertical-align: top;	
+}
+.size75{ width: 74%; }
+.size50{ width: 49%; }
+.size25{ width: 24%; }
+input, select{
+	display: inline-block;
+	margin-top: 5px;
+	box-shadow: none;
+	width: 100%;
+	font-size: 0.8em;
+	box-sizing: border-box;
+	min-height: 42px;
+}
+input{
+	padding: 10px;
+}
+select{
+	padding: 8px;
+}
+input[type="submit"]{
+	border-radius: 3px;
+	float: right;
+	margin-top: 0px;
+	width: 150px;
+}
+input[type="submit"]:hover{
+	cursor: pointer;
+}
+
+/* Select Button, see https://codepen.io/vkjgr/pen/VYMeXp */
+select {
+	/* reset */
+	-webkit-appearance: none;
+	-moz-appearance: none;
+	
+	/* style */
+	background-image:
+		linear-gradient(45deg, transparent 50%, #444 50%),
+		linear-gradient(135deg, #444 50%, transparent 50%),
+		linear-gradient(to right, #f9f8f6, #f9f8f6);
+	background-position:
+		calc(100% - 20px) calc(1em + 2px),
+		calc(100% - 15px) calc(1em + 2px),
+		100% 0;
+	background-size: 
+		5px 5px,
+		5px 5px,
+		2.8em 2.8em;
+	background-repeat: no-repeat;	
+}
+
+/* On Off Switch */
+.onoffswitch {
+	margin-top: 5px;
+	display: inline-block;
+	position: relative;
+	width: 100%;
+    -webkit-user-select:none; 
+	-moz-user-select:none; 
+	-ms-user-select:none;
+}
+.onoffswitch label{
+	padding: 0;
+}
+.onoffswitch-checkbox {
+	display: none;
+}
+.onoffswitch-label {
+	display: block; 
+	overflow: hidden; 
+	cursor: pointer;
+}
+.onoffswitch-inner {
+	display: block; 
+	width: 200%;
+	margin-left: -100%;
+	transition: margin 0.3s ease-in 0s;
+}
+.onoffswitch-inner:before, .onoffswitch-inner:after {
+	display: block; 
+	float: left; 
+	width: 50%;
+	padding: 10px 0; 
+	font-size: 1.5em;
+	line-height: 1.9em;
+	font-family: Trebuchet, Arial, sans-serif; 
+	font-weight: bold;
+	box-sizing: border-box;
+	min-height: 42px;
+}
+.onoffswitch-inner:before {
+	content: "ON";
+	padding-left: 20px;
+}
+.onoffswitch-inner:after {
+	content: "OFF";
+	padding-right: 20px;
+	text-align: right;
+}
+.onoffswitch-switch {
+	display: block; 
+	width: 18px; 
+	margin: 6px;
+	position: absolute; 
+	top: 0; 
+	bottom: 0;
+	right: 60%;
+	border-radius: 20px;
+	transition: all 0.3s ease-in 0s; 
+}
+.onoffswitch-checkbox:checked + .onoffswitch-label .onoffswitch-inner {
+	margin-left: 0;
+}
+.onoffswitch-checkbox:checked + .onoffswitch-label .onoffswitch-switch {
+	right: 0px; 
+}
+.welcome{
+	padding: 20px;
+	font-size: 0.9em;
+}
+a.button{
+	display: block;
+	width: 100%;
+	padding: 10px;
+	text-align: center;
+	margin: 20px 0;
+	border-radius: 3px;
+	box-sizing: border-box;
+	text-decoration: none;
+}

+ 18 - 0
system/author/layout.twig

@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<meta charset="UTF-8">
+		<title>{% block title %}{% endblock %}</title>
+		<meta name="viewport" content="width=device-width, initial-scale=1.0" />
+
+		<meta name="description" content="Setup your TYPEMILL website">
+		
+		<link rel="stylesheet" href="{{ base_url }}/system/author/css/normalize.css" />
+		<link rel="stylesheet" href="{{ base_url }}/system/author/css/style.css" />
+	</head>
+	<body>
+		<div class="main">
+			{% block content %}{% endblock %}
+		</div>
+	</body>
+</html>

+ 74 - 0
system/author/setup.twig

@@ -0,0 +1,74 @@
+{% extends '/layout.twig' %}
+
+{% block title %}Setup{% endblock %}
+
+{% block content %}
+	<div class="card">
+		<form method="POST" action="{{ base_url() }}/setup">
+			<header>
+				<h1>Setup</h1>
+				<input type="submit" value="save" />
+			</header>
+			<fieldset>
+				{% if errors.folder %}
+					<div class="field error">
+						<p>{{ errors.folder }}</p>
+					</div>
+				{% endif %}
+				<div class="field size100{% if errors.title %} error{% endif %}">
+					<label for="title">Website Title *</label>
+					<input type="text" name="title" id="title" pattern=".{2,20}" required title="Use 2 to 20 characters." value="{{ inputs.title }}" />
+					{% if errors.title %}<small>{{ errors.title }}</small>{% endif %}
+				</div>
+				<div class="field size100{% if errors.author %} error{% endif %}">
+					<label for="author">Author</label>
+					<input type="text" name="author" id="author" value="{{ inputs.author }}" pattern="[^()/><\]\{\}\?\$@#!*%§=[\\\x22;:|]{2,40}" title="Use 2 to 40 characters. Only the following special characters are allowed: a,b a.b a-b a_b a&b a+b" />
+					{% if errors.author %}<small>{{ errors.author }}</small>{% endif %}				
+				</div>
+				<div class="field size75{% if errors.copyright %} error{% endif %}">
+					<label for="copyright">Copyright/Licence</label>
+					<select name="copyright" id="copyright">
+					{% for copy in copyright %}
+						<option value="{{ copy }}">{{ copy }}</option>
+					{% endfor %}
+					</select>
+					{% if errors.copyright %}<small>{{ errors.copyright }}</small>{% endif %}					
+				</div>
+				<div class="field size25{% if errors.year %} error{% endif %}">
+					<label for="year">Year *</label>
+					<input type="text" name="year" id="year" value="{{ "now"|date("Y") }}" pattern="[0-9]{4}" required title="Use a valid year, e.g. 2017" />
+					{% if errors.year %}<small>{{ errors.year }}</small>{% endif %}
+				</div>
+				<div class="field size75{% if errors.theme %} error{% endif %}">
+					<label for="theme">Theme</label>
+					<select name="theme" id="themeSwitch">
+					{% for theme in themes %}
+						<option value="{{ theme }}">{{ theme }}</option>
+					{% endfor %}
+					</select>
+					{% if errors.theme %}<small>{{ errors.theme }}</small>{% endif %}
+				</div>
+				<div class="field size25"><span class="label">Startpage</label>
+					<div class="onoffswitch">
+						<input type="checkbox" name="startpage" class="onoffswitch-checkbox" id="startpage" checked >
+						<label class="onoffswitch-label" for="startpage">
+							<span class="onoffswitch-inner"></span>
+							<span class="onoffswitch-switch"></span>
+						</label>
+					</div>
+				</div>
+			</fieldset>
+		</form>
+		<img id="themePrev" src="{{ base_url() }}/themes/typemill/typemill.jpg">
+	</div>
+	<script>
+		var themeSwitch	= document.getElementById("themeSwitch"),
+			themePrev	= document.getElementById("themePrev"),
+			themePath	= themePrev.src.split("themes")[0];
+		themeSwitch.addEventListener('change', function()
+		{
+			themePrev.src = themePath + 'themes/' + themeSwitch.value + '/' + themeSwitch.value + '.jpg';
+		});
+		
+	</script>
+{% endblock %}

+ 17 - 0
system/author/welcome.twig

@@ -0,0 +1,17 @@
+{% extends '/layout.twig' %}
+
+{% block title %}Setup Welcome{% endblock %}
+
+{% block content %}
+	<div class="card">
+		<header>
+			<h1>Congratulations!</h1>
+		</header>
+		<div class="welcome">
+			<p>Hello {{ author }}!</p>
+			<p>Your settings are stored in your settings folder now. If you want to change the settings, simply open the file "settings.yaml" and edit them.</p>
+			<p>Not sure how to start? Simply create some content for your new website or visit the homepage and read the documentation... </p>
+			<a class="button" href="{{ base_url }}">Homepage</a>
+		</div>
+	</div>
+{% endblock %}

+ 7 - 0
system/autoload.php

@@ -0,0 +1,7 @@
+<?php
+
+// autoload.php @generated by Composer
+
+require_once __DIR__ . '/composer/autoload_real.php';
+
+return ComposerAutoloaderInit7102ebcc2359dc2658965039bfa4c68f::getLoader();

+ 23 - 0
system/settings.php

@@ -0,0 +1,23 @@
+<?php 
+
+DEFINE('DS', DIRECTORY_SEPARATOR);
+
+return [
+    'settings' => [
+		'title'					=> 'TYPEMILL',
+		'author'				=> 'unknown',
+		'copyright'				=> 'copyright',
+		'startpage'				=> true,
+		'rootPath'				=> __DIR__ . DS .  '..' . DS,
+		'theme'					=> ($theme = 'typemill'),
+		'themeFolder'			=> ($themeFolder = 'themes'),
+		'themePath'				=> __DIR__ . DS . '..' . DS . $themeFolder . DS . $theme,
+		'settingsPath'			=> __DIR__ . DS . '..' . DS . 'settings',
+		'authorPath'			=> __DIR__ . DS . 'author' . DS,
+		'contentFolder'			=> 'content',
+        'displayErrorDetails' 	=> false,
+		'version'				=> '1.0.0'
+    ],
+];
+
+?>

+ 77 - 0
system/system.php

@@ -0,0 +1,77 @@
+<?php
+
+/************************
+* START SESSION			*
+************************/
+
+session_start();
+
+/************************
+* LOAD SETTINGS			*
+************************/
+
+$settings 		= require_once( __DIR__ . '/settings.php');
+
+if(file_exists($settings['settings']['settingsPath'] . DIRECTORY_SEPARATOR . 'settings.yaml'))
+{
+	$yaml 			= new \Symfony\Component\Yaml\Parser();
+
+	try {
+		$userSettings 	= $yaml->parse( file_get_contents($settings['settings']['settingsPath'] . DIRECTORY_SEPARATOR . 'settings.yaml' ) );
+	} catch (ParseException $e) {
+		printf("Unable to parse the YAML string: %s", $e->getMessage());
+	}
+	
+	$settings 		= array('settings' => array_merge($settings['settings'], $userSettings));
+}
+
+/************************
+* INITIATE SLIM 		*
+************************/
+
+$app 			= new \Slim\App($settings);
+
+/************************
+* 	SLIM CONTAINER		*
+************************/
+
+$container 		= $app->getContainer();
+
+/************************
+* 		LOAD TWIG		*
+************************/
+$container['view'] = function ($container) use ($settings){
+	$path = array($settings['settings']['themePath'], $settings['settings']['authorPath']);
+    $view = new \Slim\Views\Twig( $path, [
+        'cache' => false,
+		'autoescape' => false
+    ]);
+    
+    // Instantiate and add Slim specific extension
+    $basePath = rtrim(str_ireplace('index.php', '', $container['request']->getUri()->getBasePath()), '/');
+    $view->addExtension(new Slim\Views\TwigExtension($container['router'], $basePath));
+
+	return $view;
+};
+
+/************************
+* 	LOAD FLASH MESSAGES	*
+************************/
+
+$container['flash'] = function () {
+    return new \Slim\Flash\Messages();
+};
+
+/************************
+* 	NOT FOUND HANDLER	*
+************************/
+
+$container['notFoundHandler'] = function($c)
+{
+	return new \System\Handlers\NotFoundHandler($c['view']);
+};
+
+require __DIR__ . '/Routes/web.php';
+require __DIR__ . '/Routes/api.php';
+
+?>

+ 7 - 0
system/vendor/autoload.php

@@ -0,0 +1,7 @@
+<?php
+
+// autoload.php @generated by Composer
+
+require_once __DIR__ . '/composer/autoload_real.php';
+
+return ComposerAutoloaderInit836351be733ecbf4741aea17e1973480::getLoader();

+ 445 - 0
system/vendor/composer/ClassLoader.php

@@ -0,0 +1,445 @@
+<?php
+
+/*
+ * This file is part of Composer.
+ *
+ * (c) Nils Adermann <naderman@naderman.de>
+ *     Jordi Boggiano <j.boggiano@seld.be>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Composer\Autoload;
+
+/**
+ * ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
+ *
+ *     $loader = new \Composer\Autoload\ClassLoader();
+ *
+ *     // register classes with namespaces
+ *     $loader->add('Symfony\Component', __DIR__.'/component');
+ *     $loader->add('Symfony',           __DIR__.'/framework');
+ *
+ *     // activate the autoloader
+ *     $loader->register();
+ *
+ *     // to enable searching the include path (eg. for PEAR packages)
+ *     $loader->setUseIncludePath(true);
+ *
+ * In this example, if you try to use a class in the Symfony\Component
+ * namespace or one of its children (Symfony\Component\Console for instance),
+ * the autoloader will first look for the class under the component/
+ * directory, and it will then fallback to the framework/ directory if not
+ * found before giving up.
+ *
+ * This class is loosely based on the Symfony UniversalClassLoader.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ * @author Jordi Boggiano <j.boggiano@seld.be>
+ * @see    http://www.php-fig.org/psr/psr-0/
+ * @see    http://www.php-fig.org/psr/psr-4/
+ */
+class ClassLoader
+{
+    // PSR-4
+    private $prefixLengthsPsr4 = array();
+    private $prefixDirsPsr4 = array();
+    private $fallbackDirsPsr4 = array();
+
+    // PSR-0
+    private $prefixesPsr0 = array();
+    private $fallbackDirsPsr0 = array();
+
+    private $useIncludePath = false;
+    private $classMap = array();
+    private $classMapAuthoritative = false;
+    private $missingClasses = array();
+    private $apcuPrefix;
+
+    public function getPrefixes()
+    {
+        if (!empty($this->prefixesPsr0)) {
+            return call_user_func_array('array_merge', $this->prefixesPsr0);
+        }
+
+        return array();
+    }
+
+    public function getPrefixesPsr4()
+    {
+        return $this->prefixDirsPsr4;
+    }
+
+    public function getFallbackDirs()
+    {
+        return $this->fallbackDirsPsr0;
+    }
+
+    public function getFallbackDirsPsr4()
+    {
+        return $this->fallbackDirsPsr4;
+    }
+
+    public function getClassMap()
+    {
+        return $this->classMap;
+    }
+
+    /**
+     * @param array $classMap Class to filename map
+     */
+    public function addClassMap(array $classMap)
+    {
+        if ($this->classMap) {
+            $this->classMap = array_merge($this->classMap, $classMap);
+        } else {
+            $this->classMap = $classMap;
+        }
+    }
+
+    /**
+     * Registers a set of PSR-0 directories for a given prefix, either
+     * appending or prepending to the ones previously set for this prefix.
+     *
+     * @param string       $prefix  The prefix
+     * @param array|string $paths   The PSR-0 root directories
+     * @param bool         $prepend Whether to prepend the directories
+     */
+    public function add($prefix, $paths, $prepend = false)
+    {
+        if (!$prefix) {
+            if ($prepend) {
+                $this->fallbackDirsPsr0 = array_merge(
+                    (array) $paths,
+                    $this->fallbackDirsPsr0
+                );
+            } else {
+                $this->fallbackDirsPsr0 = array_merge(
+                    $this->fallbackDirsPsr0,
+                    (array) $paths
+                );
+            }
+
+            return;
+        }
+
+        $first = $prefix[0];
+        if (!isset($this->prefixesPsr0[$first][$prefix])) {
+            $this->prefixesPsr0[$first][$prefix] = (array) $paths;
+
+            return;
+        }
+        if ($prepend) {
+            $this->prefixesPsr0[$first][$prefix] = array_merge(
+                (array) $paths,
+                $this->prefixesPsr0[$first][$prefix]
+            );
+        } else {
+            $this->prefixesPsr0[$first][$prefix] = array_merge(
+                $this->prefixesPsr0[$first][$prefix],
+                (array) $paths
+            );
+        }
+    }
+
+    /**
+     * Registers a set of PSR-4 directories for a given namespace, either
+     * appending or prepending to the ones previously set for this namespace.
+     *
+     * @param string       $prefix  The prefix/namespace, with trailing '\\'
+     * @param array|string $paths   The PSR-4 base directories
+     * @param bool         $prepend Whether to prepend the directories
+     *
+     * @throws \InvalidArgumentException
+     */
+    public function addPsr4($prefix, $paths, $prepend = false)
+    {
+        if (!$prefix) {
+            // Register directories for the root namespace.
+            if ($prepend) {
+                $this->fallbackDirsPsr4 = array_merge(
+                    (array) $paths,
+                    $this->fallbackDirsPsr4
+                );
+            } else {
+                $this->fallbackDirsPsr4 = array_merge(
+                    $this->fallbackDirsPsr4,
+                    (array) $paths
+                );
+            }
+        } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
+            // Register directories for a new namespace.
+            $length = strlen($prefix);
+            if ('\\' !== $prefix[$length - 1]) {
+                throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
+            }
+            $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
+            $this->prefixDirsPsr4[$prefix] = (array) $paths;
+        } elseif ($prepend) {
+            // Prepend directories for an already registered namespace.
+            $this->prefixDirsPsr4[$prefix] = array_merge(
+                (array) $paths,
+                $this->prefixDirsPsr4[$prefix]
+            );
+        } else {
+            // Append directories for an already registered namespace.
+            $this->prefixDirsPsr4[$prefix] = array_merge(
+                $this->prefixDirsPsr4[$prefix],
+                (array) $paths
+            );
+        }
+    }
+
+    /**
+     * Registers a set of PSR-0 directories for a given prefix,
+     * replacing any others previously set for this prefix.
+     *
+     * @param string       $prefix The prefix
+     * @param array|string $paths  The PSR-0 base directories
+     */
+    public function set($prefix, $paths)
+    {
+        if (!$prefix) {
+            $this->fallbackDirsPsr0 = (array) $paths;
+        } else {
+            $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
+        }
+    }
+
+    /**
+     * Registers a set of PSR-4 directories for a given namespace,
+     * replacing any others previously set for this namespace.
+     *
+     * @param string       $prefix The prefix/namespace, with trailing '\\'
+     * @param array|string $paths  The PSR-4 base directories
+     *
+     * @throws \InvalidArgumentException
+     */
+    public function setPsr4($prefix, $paths)
+    {
+        if (!$prefix) {
+            $this->fallbackDirsPsr4 = (array) $paths;
+        } else {
+            $length = strlen($prefix);
+            if ('\\' !== $prefix[$length - 1]) {
+                throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
+            }
+            $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
+            $this->prefixDirsPsr4[$prefix] = (array) $paths;
+        }
+    }
+
+    /**
+     * Turns on searching the include path for class files.
+     *
+     * @param bool $useIncludePath
+     */
+    public function setUseIncludePath($useIncludePath)
+    {
+        $this->useIncludePath = $useIncludePath;
+    }
+
+    /**
+     * Can be used to check if the autoloader uses the include path to check
+     * for classes.
+     *
+     * @return bool
+     */
+    public function getUseIncludePath()
+    {
+        return $this->useIncludePath;
+    }
+
+    /**
+     * Turns off searching the prefix and fallback directories for classes
+     * that have not been registered with the class map.
+     *
+     * @param bool $classMapAuthoritative
+     */
+    public function setClassMapAuthoritative($classMapAuthoritative)
+    {
+        $this->classMapAuthoritative = $classMapAuthoritative;
+    }
+
+    /**
+     * Should class lookup fail if not found in the current class map?
+     *
+     * @return bool
+     */
+    public function isClassMapAuthoritative()
+    {
+        return $this->classMapAuthoritative;
+    }
+
+    /**
+     * APCu prefix to use to cache found/not-found classes, if the extension is enabled.
+     *
+     * @param string|null $apcuPrefix
+     */
+    public function setApcuPrefix($apcuPrefix)
+    {
+        $this->apcuPrefix = function_exists('apcu_fetch') && ini_get('apc.enabled') ? $apcuPrefix : null;
+    }
+
+    /**
+     * The APCu prefix in use, or null if APCu caching is not enabled.
+     *
+     * @return string|null
+     */
+    public function getApcuPrefix()
+    {
+        return $this->apcuPrefix;
+    }
+
+    /**
+     * Registers this instance as an autoloader.
+     *
+     * @param bool $prepend Whether to prepend the autoloader or not
+     */
+    public function register($prepend = false)
+    {
+        spl_autoload_register(array($this, 'loadClass'), true, $prepend);
+    }
+
+    /**
+     * Unregisters this instance as an autoloader.
+     */
+    public function unregister()
+    {
+        spl_autoload_unregister(array($this, 'loadClass'));
+    }
+
+    /**
+     * Loads the given class or interface.
+     *
+     * @param  string    $class The name of the class
+     * @return bool|null True if loaded, null otherwise
+     */
+    public function loadClass($class)
+    {
+        if ($file = $this->findFile($class)) {
+            includeFile($file);
+
+            return true;
+        }
+    }
+
+    /**
+     * Finds the path to the file where the class is defined.
+     *
+     * @param string $class The name of the class
+     *
+     * @return string|false The path if found, false otherwise
+     */
+    public function findFile($class)
+    {
+        // class map lookup
+        if (isset($this->classMap[$class])) {
+            return $this->classMap[$class];
+        }
+        if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
+            return false;
+        }
+        if (null !== $this->apcuPrefix) {
+            $file = apcu_fetch($this->apcuPrefix.$class, $hit);
+            if ($hit) {
+                return $file;
+            }
+        }
+
+        $file = $this->findFileWithExtension($class, '.php');
+
+        // Search for Hack files if we are running on HHVM
+        if (false === $file && defined('HHVM_VERSION')) {
+            $file = $this->findFileWithExtension($class, '.hh');
+        }
+
+        if (null !== $this->apcuPrefix) {
+            apcu_add($this->apcuPrefix.$class, $file);
+        }
+
+        if (false === $file) {
+            // Remember that this class does not exist.
+            $this->missingClasses[$class] = true;
+        }
+
+        return $file;
+    }
+
+    private function findFileWithExtension($class, $ext)
+    {
+        // PSR-4 lookup
+        $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
+
+        $first = $class[0];
+        if (isset($this->prefixLengthsPsr4[$first])) {
+            $subPath = $class;
+            while (false !== $lastPos = strrpos($subPath, '\\')) {
+                $subPath = substr($subPath, 0, $lastPos);
+                $search = $subPath.'\\';
+                if (isset($this->prefixDirsPsr4[$search])) {
+                    foreach ($this->prefixDirsPsr4[$search] as $dir) {
+                        $length = $this->prefixLengthsPsr4[$first][$search];
+                        if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) {
+                            return $file;
+                        }
+                    }
+                }
+            }
+        }
+
+        // PSR-4 fallback dirs
+        foreach ($this->fallbackDirsPsr4 as $dir) {
+            if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
+                return $file;
+            }
+        }
+
+        // PSR-0 lookup
+        if (false !== $pos = strrpos($class, '\\')) {
+            // namespaced class name
+            $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
+                . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
+        } else {
+            // PEAR-like class name
+            $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
+        }
+
+        if (isset($this->prefixesPsr0[$first])) {
+            foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
+                if (0 === strpos($class, $prefix)) {
+                    foreach ($dirs as $dir) {
+                        if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
+                            return $file;
+                        }
+                    }
+                }
+            }
+        }
+
+        // PSR-0 fallback dirs
+        foreach ($this->fallbackDirsPsr0 as $dir) {
+            if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
+                return $file;
+            }
+        }
+
+        // PSR-0 include paths.
+        if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
+            return $file;
+        }
+
+        return false;
+    }
+}
+
+/**
+ * Scope isolated include.
+ *
+ * Prevents access to $this/self from included files.
+ */
+function includeFile($file)
+{
+    include $file;
+}

+ 21 - 0
system/vendor/composer/LICENSE

@@ -0,0 +1,21 @@
+
+Copyright (c) Nils Adermann, Jordi Boggiano
+
+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.
+

+ 9 - 0
system/vendor/composer/autoload_classmap.php

@@ -0,0 +1,9 @@
+<?php
+
+// autoload_classmap.php @generated by Composer
+
+$vendorDir = dirname(dirname(__FILE__));
+$baseDir = dirname(dirname($vendorDir));
+
+return array(
+);

+ 10 - 0
system/vendor/composer/autoload_files.php

@@ -0,0 +1,10 @@
+<?php
+
+// autoload_files.php @generated by Composer
+
+$vendorDir = dirname(dirname(__FILE__));
+$baseDir = dirname(dirname($vendorDir));
+
+return array(
+    '253c157292f75eb38082b5acb06f3f01' => $vendorDir . '/nikic/fast-route/src/functions.php',
+);

+ 14 - 0
system/vendor/composer/autoload_namespaces.php

@@ -0,0 +1,14 @@
+<?php
+
+// autoload_namespaces.php @generated by Composer
+
+$vendorDir = dirname(dirname(__FILE__));
+$baseDir = dirname(dirname($vendorDir));
+
+return array(
+    'URLify' => array($vendorDir . '/jbroadway/urlify'),
+    'Twig_' => array($vendorDir . '/twig/twig/lib'),
+    'Pimple' => array($vendorDir . '/pimple/pimple/src'),
+    'ParsedownExtra' => array($vendorDir . '/erusev/parsedown-extra'),
+    'Parsedown' => array($vendorDir . '/erusev/parsedown'),
+);

+ 18 - 0
system/vendor/composer/autoload_psr4.php

@@ -0,0 +1,18 @@
+<?php
+
+// autoload_psr4.php @generated by Composer
+
+$vendorDir = dirname(dirname(__FILE__));
+$baseDir = dirname(dirname($vendorDir));
+
+return array(
+    'System\\' => array($baseDir . '/system'),
+    'Symfony\\Component\\Yaml\\' => array($vendorDir . '/symfony/yaml'),
+    'Slim\\Views\\' => array($vendorDir . '/slim/twig-view/src'),
+    'Slim\\Flash\\' => array($vendorDir . '/slim/flash/src'),
+    'Slim\\' => array($vendorDir . '/slim/slim/Slim'),
+    'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-message/src'),
+    'Psr\\Container\\' => array($vendorDir . '/psr/container/src'),
+    'Interop\\Container\\' => array($vendorDir . '/container-interop/container-interop/src/Interop/Container'),
+    'FastRoute\\' => array($vendorDir . '/nikic/fast-route/src'),
+);

+ 70 - 0
system/vendor/composer/autoload_real.php

@@ -0,0 +1,70 @@
+<?php
+
+// autoload_real.php @generated by Composer
+
+class ComposerAutoloaderInit836351be733ecbf4741aea17e1973480
+{
+    private static $loader;
+
+    public static function loadClassLoader($class)
+    {
+        if ('Composer\Autoload\ClassLoader' === $class) {
+            require __DIR__ . '/ClassLoader.php';
+        }
+    }
+
+    public static function getLoader()
+    {
+        if (null !== self::$loader) {
+            return self::$loader;
+        }
+
+        spl_autoload_register(array('ComposerAutoloaderInit836351be733ecbf4741aea17e1973480', 'loadClassLoader'), true, true);
+        self::$loader = $loader = new \Composer\Autoload\ClassLoader();
+        spl_autoload_unregister(array('ComposerAutoloaderInit836351be733ecbf4741aea17e1973480', 'loadClassLoader'));
+
+        $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
+        if ($useStaticLoader) {
+            require_once __DIR__ . '/autoload_static.php';
+
+            call_user_func(\Composer\Autoload\ComposerStaticInit836351be733ecbf4741aea17e1973480::getInitializer($loader));
+        } else {
+            $map = require __DIR__ . '/autoload_namespaces.php';
+            foreach ($map as $namespace => $path) {
+                $loader->set($namespace, $path);
+            }
+
+            $map = require __DIR__ . '/autoload_psr4.php';
+            foreach ($map as $namespace => $path) {
+                $loader->setPsr4($namespace, $path);
+            }
+
+            $classMap = require __DIR__ . '/autoload_classmap.php';
+            if ($classMap) {
+                $loader->addClassMap($classMap);
+            }
+        }
+
+        $loader->register(true);
+
+        if ($useStaticLoader) {
+            $includeFiles = Composer\Autoload\ComposerStaticInit836351be733ecbf4741aea17e1973480::$files;
+        } else {
+            $includeFiles = require __DIR__ . '/autoload_files.php';
+        }
+        foreach ($includeFiles as $fileIdentifier => $file) {
+            composerRequire836351be733ecbf4741aea17e1973480($fileIdentifier, $file);
+        }
+
+        return $loader;
+    }
+}
+
+function composerRequire836351be733ecbf4741aea17e1973480($fileIdentifier, $file)
+{
+    if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
+        require $file;
+
+        $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
+    }
+}

+ 117 - 0
system/vendor/composer/autoload_static.php

@@ -0,0 +1,117 @@
+<?php
+
+// autoload_static.php @generated by Composer
+
+namespace Composer\Autoload;
+
+class ComposerStaticInit836351be733ecbf4741aea17e1973480
+{
+    public static $files = array (
+        '253c157292f75eb38082b5acb06f3f01' => __DIR__ . '/..' . '/nikic/fast-route/src/functions.php',
+    );
+
+    public static $prefixLengthsPsr4 = array (
+        'S' => 
+        array (
+            'System\\' => 7,
+            'Symfony\\Component\\Yaml\\' => 23,
+            'Slim\\Views\\' => 11,
+            'Slim\\Flash\\' => 11,
+            'Slim\\' => 5,
+        ),
+        'P' => 
+        array (
+            'Psr\\Http\\Message\\' => 17,
+            'Psr\\Container\\' => 14,
+        ),
+        'I' => 
+        array (
+            'Interop\\Container\\' => 18,
+        ),
+        'F' => 
+        array (
+            'FastRoute\\' => 10,
+        ),
+    );
+
+    public static $prefixDirsPsr4 = array (
+        'System\\' => 
+        array (
+            0 => __DIR__ . '/../../..' . '/system',
+        ),
+        'Symfony\\Component\\Yaml\\' => 
+        array (
+            0 => __DIR__ . '/..' . '/symfony/yaml',
+        ),
+        'Slim\\Views\\' => 
+        array (
+            0 => __DIR__ . '/..' . '/slim/twig-view/src',
+        ),
+        'Slim\\Flash\\' => 
+        array (
+            0 => __DIR__ . '/..' . '/slim/flash/src',
+        ),
+        'Slim\\' => 
+        array (
+            0 => __DIR__ . '/..' . '/slim/slim/Slim',
+        ),
+        'Psr\\Http\\Message\\' => 
+        array (
+            0 => __DIR__ . '/..' . '/psr/http-message/src',
+        ),
+        'Psr\\Container\\' => 
+        array (
+            0 => __DIR__ . '/..' . '/psr/container/src',
+        ),
+        'Interop\\Container\\' => 
+        array (
+            0 => __DIR__ . '/..' . '/container-interop/container-interop/src/Interop/Container',
+        ),
+        'FastRoute\\' => 
+        array (
+            0 => __DIR__ . '/..' . '/nikic/fast-route/src',
+        ),
+    );
+
+    public static $prefixesPsr0 = array (
+        'U' => 
+        array (
+            'URLify' => 
+            array (
+                0 => __DIR__ . '/..' . '/jbroadway/urlify',
+            ),
+        ),
+        'T' => 
+        array (
+            'Twig_' => 
+            array (
+                0 => __DIR__ . '/..' . '/twig/twig/lib',
+            ),
+        ),
+        'P' => 
+        array (
+            'Pimple' => 
+            array (
+                0 => __DIR__ . '/..' . '/pimple/pimple/src',
+            ),
+            'ParsedownExtra' => 
+            array (
+                0 => __DIR__ . '/..' . '/erusev/parsedown-extra',
+            ),
+            'Parsedown' => 
+            array (
+                0 => __DIR__ . '/..' . '/erusev/parsedown',
+            ),
+        ),
+    );
+
+    public static function getInitializer(ClassLoader $loader)
+    {
+        return \Closure::bind(function () use ($loader) {
+            $loader->prefixLengthsPsr4 = ComposerStaticInit836351be733ecbf4741aea17e1973480::$prefixLengthsPsr4;
+            $loader->prefixDirsPsr4 = ComposerStaticInit836351be733ecbf4741aea17e1973480::$prefixDirsPsr4;
+            $loader->prefixesPsr0 = ComposerStaticInit836351be733ecbf4741aea17e1973480::$prefixesPsr0;
+
+        }, null, ClassLoader::class);
+    }
+}

+ 667 - 0
system/vendor/composer/installed.json

@@ -0,0 +1,667 @@
+[
+    {
+        "name": "nikic/fast-route",
+        "version": "v1.2.0",
+        "version_normalized": "1.2.0.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/nikic/FastRoute.git",
+            "reference": "b5f95749071c82a8e0f58586987627054400cdf6"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/nikic/FastRoute/zipball/b5f95749071c82a8e0f58586987627054400cdf6",
+            "reference": "b5f95749071c82a8e0f58586987627054400cdf6",
+            "shasum": ""
+        },
+        "require": {
+            "php": ">=5.4.0"
+        },
+        "time": "2017-01-19T11:35:12+00:00",
+        "type": "library",
+        "installation-source": "dist",
+        "autoload": {
+            "psr-4": {
+                "FastRoute\\": "src/"
+            },
+            "files": [
+                "src/functions.php"
+            ]
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "BSD-3-Clause"
+        ],
+        "authors": [
+            {
+                "name": "Nikita Popov",
+                "email": "nikic@php.net"
+            }
+        ],
+        "description": "Fast request router for PHP",
+        "keywords": [
+            "router",
+            "routing"
+        ]
+    },
+    {
+        "name": "psr/http-message",
+        "version": "1.0.1",
+        "version_normalized": "1.0.1.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/php-fig/http-message.git",
+            "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363",
+            "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363",
+            "shasum": ""
+        },
+        "require": {
+            "php": ">=5.3.0"
+        },
+        "time": "2016-08-06T14:39:51+00:00",
+        "type": "library",
+        "extra": {
+            "branch-alias": {
+                "dev-master": "1.0.x-dev"
+            }
+        },
+        "installation-source": "dist",
+        "autoload": {
+            "psr-4": {
+                "Psr\\Http\\Message\\": "src/"
+            }
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "MIT"
+        ],
+        "authors": [
+            {
+                "name": "PHP-FIG",
+                "homepage": "http://www.php-fig.org/"
+            }
+        ],
+        "description": "Common interface for HTTP messages",
+        "homepage": "https://github.com/php-fig/http-message",
+        "keywords": [
+            "http",
+            "http-message",
+            "psr",
+            "psr-7",
+            "request",
+            "response"
+        ]
+    },
+    {
+        "name": "pimple/pimple",
+        "version": "v3.0.2",
+        "version_normalized": "3.0.2.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/silexphp/Pimple.git",
+            "reference": "a30f7d6e57565a2e1a316e1baf2a483f788b258a"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/silexphp/Pimple/zipball/a30f7d6e57565a2e1a316e1baf2a483f788b258a",
+            "reference": "a30f7d6e57565a2e1a316e1baf2a483f788b258a",
+            "shasum": ""
+        },
+        "require": {
+            "php": ">=5.3.0"
+        },
+        "time": "2015-09-11T15:10:35+00:00",
+        "type": "library",
+        "extra": {
+            "branch-alias": {
+                "dev-master": "3.0.x-dev"
+            }
+        },
+        "installation-source": "dist",
+        "autoload": {
+            "psr-0": {
+                "Pimple": "src/"
+            }
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "MIT"
+        ],
+        "authors": [
+            {
+                "name": "Fabien Potencier",
+                "email": "fabien@symfony.com"
+            }
+        ],
+        "description": "Pimple, a simple Dependency Injection Container",
+        "homepage": "http://pimple.sensiolabs.org",
+        "keywords": [
+            "container",
+            "dependency injection"
+        ]
+    },
+    {
+        "name": "slim/twig-view",
+        "version": "dev-master",
+        "version_normalized": "9999999-dev",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/slimphp/Twig-View.git",
+            "reference": "a743ac45e2a089942159dda499c5ef5bc5f6bfa6"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/slimphp/Twig-View/zipball/a743ac45e2a089942159dda499c5ef5bc5f6bfa6",
+            "reference": "a743ac45e2a089942159dda499c5ef5bc5f6bfa6",
+            "shasum": ""
+        },
+        "require": {
+            "php": ">=5.5.0",
+            "psr/http-message": "^1.0",
+            "twig/twig": "^1.18|^2.0"
+        },
+        "require-dev": {
+            "phpunit/phpunit": "^4.8|^5.7"
+        },
+        "time": "2017-01-25T20:38:39+00:00",
+        "type": "library",
+        "installation-source": "source",
+        "autoload": {
+            "psr-4": {
+                "Slim\\Views\\": "src"
+            }
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "MIT"
+        ],
+        "authors": [
+            {
+                "name": "Josh Lockhart",
+                "email": "hello@joshlockhart.com",
+                "homepage": "http://joshlockhart.com"
+            }
+        ],
+        "description": "Slim Framework 3 view helper built on top of the Twig 2 templating component",
+        "homepage": "http://slimframework.com",
+        "keywords": [
+            "framework",
+            "slim",
+            "template",
+            "twig",
+            "view"
+        ]
+    },
+    {
+        "name": "psr/container",
+        "version": "1.0.0",
+        "version_normalized": "1.0.0.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/php-fig/container.git",
+            "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f",
+            "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f",
+            "shasum": ""
+        },
+        "require": {
+            "php": ">=5.3.0"
+        },
+        "time": "2017-02-14T16:28:37+00:00",
+        "type": "library",
+        "extra": {
+            "branch-alias": {
+                "dev-master": "1.0.x-dev"
+            }
+        },
+        "installation-source": "dist",
+        "autoload": {
+            "psr-4": {
+                "Psr\\Container\\": "src/"
+            }
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "MIT"
+        ],
+        "authors": [
+            {
+                "name": "PHP-FIG",
+                "homepage": "http://www.php-fig.org/"
+            }
+        ],
+        "description": "Common Container Interface (PHP FIG PSR-11)",
+        "homepage": "https://github.com/php-fig/container",
+        "keywords": [
+            "PSR-11",
+            "container",
+            "container-interface",
+            "container-interop",
+            "psr"
+        ]
+    },
+    {
+        "name": "container-interop/container-interop",
+        "version": "1.2.0",
+        "version_normalized": "1.2.0.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/container-interop/container-interop.git",
+            "reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/container-interop/container-interop/zipball/79cbf1341c22ec75643d841642dd5d6acd83bdb8",
+            "reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8",
+            "shasum": ""
+        },
+        "require": {
+            "psr/container": "^1.0"
+        },
+        "time": "2017-02-14T19:40:03+00:00",
+        "type": "library",
+        "installation-source": "dist",
+        "autoload": {
+            "psr-4": {
+                "Interop\\Container\\": "src/Interop/Container/"
+            }
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "MIT"
+        ],
+        "description": "Promoting the interoperability of container objects (DIC, SL, etc.)",
+        "homepage": "https://github.com/container-interop/container-interop"
+    },
+    {
+        "name": "jbroadway/urlify",
+        "version": "dev-master",
+        "version_normalized": "9999999-dev",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/jbroadway/urlify.git",
+            "reference": "99bb78cd9002d0e9ce479bb81635eb665e37e981"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/jbroadway/urlify/zipball/99bb78cd9002d0e9ce479bb81635eb665e37e981",
+            "reference": "99bb78cd9002d0e9ce479bb81635eb665e37e981",
+            "shasum": ""
+        },
+        "require": {
+            "php": ">=5.3.0"
+        },
+        "time": "2017-01-03T20:12:54+00:00",
+        "type": "library",
+        "extra": {
+            "branch-alias": {
+                "dev-master": "1.0-dev"
+            }
+        },
+        "installation-source": "source",
+        "autoload": {
+            "psr-0": {
+                "URLify": ""
+            }
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "BSD"
+        ],
+        "authors": [
+            {
+                "name": "Johnny Broadway",
+                "email": "johnny@johnnybroadway.com",
+                "homepage": "http://www.johnnybroadway.com/"
+            }
+        ],
+        "description": "PHP port of URLify.js from the Django project. Transliterates non-ascii characters for use in URLs.",
+        "homepage": "https://github.com/jbroadway/urlify",
+        "keywords": [
+            "encode",
+            "iconv",
+            "link",
+            "slug",
+            "translit",
+            "transliterate",
+            "transliteration",
+            "url",
+            "urlify"
+        ]
+    },
+    {
+        "name": "slim/slim",
+        "version": "3.8.1",
+        "version_normalized": "3.8.1.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/slimphp/Slim.git",
+            "reference": "5385302707530b2bccee1769613ad769859b826d"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/slimphp/Slim/zipball/5385302707530b2bccee1769613ad769859b826d",
+            "reference": "5385302707530b2bccee1769613ad769859b826d",
+            "shasum": ""
+        },
+        "require": {
+            "container-interop/container-interop": "^1.2",
+            "nikic/fast-route": "^1.0",
+            "php": ">=5.5.0",
+            "pimple/pimple": "^3.0",
+            "psr/container": "^1.0",
+            "psr/http-message": "^1.0"
+        },
+        "provide": {
+            "psr/http-message-implementation": "1.0"
+        },
+        "require-dev": {
+            "phpunit/phpunit": "^4.0",
+            "squizlabs/php_codesniffer": "^2.5"
+        },
+        "time": "2017-03-19T17:55:20+00:00",
+        "type": "library",
+        "installation-source": "dist",
+        "autoload": {
+            "psr-4": {
+                "Slim\\": "Slim"
+            }
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "MIT"
+        ],
+        "authors": [
+            {
+                "name": "Rob Allen",
+                "email": "rob@akrabat.com",
+                "homepage": "http://akrabat.com"
+            },
+            {
+                "name": "Josh Lockhart",
+                "email": "hello@joshlockhart.com",
+                "homepage": "https://joshlockhart.com"
+            },
+            {
+                "name": "Gabriel Manricks",
+                "email": "gmanricks@me.com",
+                "homepage": "http://gabrielmanricks.com"
+            },
+            {
+                "name": "Andrew Smith",
+                "email": "a.smith@silentworks.co.uk",
+                "homepage": "http://silentworks.co.uk"
+            }
+        ],
+        "description": "Slim is a PHP micro framework that helps you quickly write simple yet powerful web applications and APIs",
+        "homepage": "https://slimframework.com",
+        "keywords": [
+            "api",
+            "framework",
+            "micro",
+            "router"
+        ]
+    },
+    {
+        "name": "erusev/parsedown-extra",
+        "version": "dev-master",
+        "version_normalized": "9999999-dev",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/erusev/parsedown-extra.git",
+            "reference": "0db5cce7354e4b76f155d092ab5eb3981c21258c"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/erusev/parsedown-extra/zipball/0db5cce7354e4b76f155d092ab5eb3981c21258c",
+            "reference": "0db5cce7354e4b76f155d092ab5eb3981c21258c",
+            "shasum": ""
+        },
+        "require": {
+            "erusev/parsedown": "~1.4"
+        },
+        "time": "2015-11-01T10:19:22+00:00",
+        "type": "library",
+        "installation-source": "source",
+        "autoload": {
+            "psr-0": {
+                "ParsedownExtra": ""
+            }
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "MIT"
+        ],
+        "authors": [
+            {
+                "name": "Emanuil Rusev",
+                "email": "hello@erusev.com",
+                "homepage": "http://erusev.com"
+            }
+        ],
+        "description": "An extension of Parsedown that adds support for Markdown Extra.",
+        "homepage": "https://github.com/erusev/parsedown-extra",
+        "keywords": [
+            "markdown",
+            "markdown extra",
+            "parsedown",
+            "parser"
+        ]
+    },
+    {
+        "name": "erusev/parsedown",
+        "version": "1.6.2",
+        "version_normalized": "1.6.2.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/erusev/parsedown.git",
+            "reference": "1bf24f7334fe16c88bf9d467863309ceaf285b01"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/erusev/parsedown/zipball/1bf24f7334fe16c88bf9d467863309ceaf285b01",
+            "reference": "1bf24f7334fe16c88bf9d467863309ceaf285b01",
+            "shasum": ""
+        },
+        "require": {
+            "php": ">=5.3.0"
+        },
+        "time": "2017-03-29T16:04:15+00:00",
+        "type": "library",
+        "installation-source": "source",
+        "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"
+        ]
+    },
+    {
+        "name": "slim/flash",
+        "version": "dev-master",
+        "version_normalized": "9999999-dev",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/slimphp/Slim-Flash.git",
+            "reference": "3c9a26b3163820acc48080336c504d0a3cac6f30"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/slimphp/Slim-Flash/zipball/3c9a26b3163820acc48080336c504d0a3cac6f30",
+            "reference": "3c9a26b3163820acc48080336c504d0a3cac6f30",
+            "shasum": ""
+        },
+        "require": {
+            "php": ">=5.5.0"
+        },
+        "require-dev": {
+            "phpunit/phpunit": "^4.0"
+        },
+        "time": "2016-11-11T16:29:19+00:00",
+        "type": "library",
+        "installation-source": "source",
+        "autoload": {
+            "psr-4": {
+                "Slim\\Flash\\": "src"
+            }
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "MIT"
+        ],
+        "authors": [
+            {
+                "name": "Josh Lockhart",
+                "email": "hello@joshlockhart.com",
+                "homepage": "http://joshlockhart.com"
+            }
+        ],
+        "description": "Slim Framework Flash message service provider",
+        "homepage": "http://slimframework.com",
+        "keywords": [
+            "flash",
+            "framework",
+            "message",
+            "provider",
+            "slim"
+        ]
+    },
+    {
+        "name": "twig/twig",
+        "version": "v1.33.0",
+        "version_normalized": "1.33.0.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/twigphp/Twig.git",
+            "reference": "05cf49921b13f6f01d3cfdf9018cfa7a8086fd5a"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/twigphp/Twig/zipball/05cf49921b13f6f01d3cfdf9018cfa7a8086fd5a",
+            "reference": "05cf49921b13f6f01d3cfdf9018cfa7a8086fd5a",
+            "shasum": ""
+        },
+        "require": {
+            "php": ">=5.2.7"
+        },
+        "require-dev": {
+            "psr/container": "^1.0",
+            "symfony/debug": "~2.7",
+            "symfony/phpunit-bridge": "~3.3@dev"
+        },
+        "time": "2017-03-22T15:40:09+00:00",
+        "type": "library",
+        "extra": {
+            "branch-alias": {
+                "dev-master": "1.33-dev"
+            }
+        },
+        "installation-source": "dist",
+        "autoload": {
+            "psr-0": {
+                "Twig_": "lib/"
+            }
+        },
+        "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"
+        ]
+    },
+    {
+        "name": "symfony/yaml",
+        "version": "v2.8.19",
+        "version_normalized": "2.8.19.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/symfony/yaml.git",
+            "reference": "286d84891690b0e2515874717e49360d1c98a703"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/symfony/yaml/zipball/286d84891690b0e2515874717e49360d1c98a703",
+            "reference": "286d84891690b0e2515874717e49360d1c98a703",
+            "shasum": ""
+        },
+        "require": {
+            "php": ">=5.3.9"
+        },
+        "time": "2017-03-20T09:41:44+00:00",
+        "type": "library",
+        "extra": {
+            "branch-alias": {
+                "dev-master": "2.8-dev"
+            }
+        },
+        "installation-source": "dist",
+        "autoload": {
+            "psr-4": {
+                "Symfony\\Component\\Yaml\\": ""
+            },
+            "exclude-from-classmap": [
+                "/Tests/"
+            ]
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "MIT"
+        ],
+        "authors": [
+            {
+                "name": "Fabien Potencier",
+                "email": "fabien@symfony.com"
+            },
+            {
+                "name": "Symfony Community",
+                "homepage": "https://symfony.com/contributors"
+            }
+        ],
+        "description": "Symfony Yaml Component",
+        "homepage": "https://symfony.com"
+    }
+]

+ 3 - 0
system/vendor/container-interop/container-interop/.gitignore

@@ -0,0 +1,3 @@
+composer.lock
+composer.phar
+/vendor/

+ 20 - 0
system/vendor/container-interop/container-interop/LICENSE

@@ -0,0 +1,20 @@
+The MIT License (MIT)
+
+Copyright (c) 2013 container-interop
+
+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.

+ 148 - 0
system/vendor/container-interop/container-interop/README.md

@@ -0,0 +1,148 @@
+# Container Interoperability
+
+[![Latest Stable Version](https://poser.pugx.org/container-interop/container-interop/v/stable.png)](https://packagist.org/packages/container-interop/container-interop)
+[![Total Downloads](https://poser.pugx.org/container-interop/container-interop/downloads.svg)](https://packagist.org/packages/container-interop/container-interop)
+
+## Deprecation warning!
+
+Starting Feb. 13th 2017, container-interop is officially deprecated in favor of [PSR-11](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-11-container.md).
+Container-interop has been the test-bed of PSR-11. From v1.2, container-interop directly extends PSR-11 interfaces.
+Therefore, all containers implementing container-interop are now *de-facto* compatible with PSR-11.
+
+- Projects implementing container-interop interfaces are encouraged to directly implement PSR-11 interfaces instead.
+- Projects consuming container-interop interfaces are very strongly encouraged to directly type-hint on PSR-11 interfaces, in order to be compatible with PSR-11 containers that are not compatible with container-interop.
+
+Regarding the delegate lookup feature, that is present in container-interop and not in PSR-11, the feature is actually a design pattern. It is therefore not deprecated. Documentation regarding this design pattern will be migrated from this repository into a separate website in the future.
+
+## About
+
+*container-interop* tries to identify and standardize features in *container* objects (service locators,
+dependency injection containers, etc.) to achieve interoperability.
+
+Through discussions and trials, we try to create a standard, made of common interfaces but also recommendations.
+
+If PHP projects that provide container implementations begin to adopt these common standards, then PHP
+applications and projects that use containers can depend on the common interfaces instead of specific
+implementations. This facilitates a high-level of interoperability and flexibility that allows users to consume
+*any* container implementation that can be adapted to these interfaces.
+
+The work done in this project is not officially endorsed by the [PHP-FIG](http://www.php-fig.org/), but it is being
+worked on by members of PHP-FIG and other good developers. We adhere to the spirit and ideals of PHP-FIG, and hope
+this project will pave the way for one or more future PSRs.
+
+
+## Installation
+
+You can install this package through Composer:
+
+```json
+composer require container-interop/container-interop
+```
+
+The packages adheres to the [SemVer](http://semver.org/) specification, and there will be full backward compatibility
+between minor versions.
+
+## Standards
+
+### Available
+
+- [`ContainerInterface`](src/Interop/Container/ContainerInterface.php).
+[Description](docs/ContainerInterface.md) [Meta Document](docs/ContainerInterface-meta.md).
+Describes the interface of a container that exposes methods to read its entries.
+- [*Delegate lookup feature*](docs/Delegate-lookup.md).
+[Meta Document](docs/Delegate-lookup-meta.md).
+Describes the ability for a container to delegate the lookup of its dependencies to a third-party container. This
+feature lets several containers work together in a single application.
+
+### Proposed
+
+View open [request for comments](https://github.com/container-interop/container-interop/labels/RFC)
+
+## Compatible projects
+
+### Projects implementing `ContainerInterface`
+
+- [Acclimate](https://github.com/jeremeamia/acclimate-container): Adapters for
+  Aura.Di, Laravel, Nette DI, Pimple, Symfony DI, ZF2 Service manager, ZF2
+  Dependency injection and any container using `ArrayAccess`
+- [Aura.Di](https://github.com/auraphp/Aura.Di)
+- [auryn-container-interop](https://github.com/elazar/auryn-container-interop)
+- [Burlap](https://github.com/codeeverything/burlap)
+- [Chernozem](https://github.com/pyrsmk/Chernozem)
+- [Data Manager](https://github.com/chrismichaels84/data-manager)
+- [Disco](https://github.com/bitexpert/disco)
+- [InDI](https://github.com/idealogica/indi)
+- [League/Container](http://container.thephpleague.com/)
+- [Mouf](http://mouf-php.com)
+- [Njasm Container](https://github.com/njasm/container)
+- [PHP-DI](http://php-di.org)
+- [Picotainer](https://github.com/thecodingmachine/picotainer)
+- [PimpleInterop](https://github.com/moufmouf/pimple-interop)
+- [Pimple3-ContainerInterop](https://github.com/Sam-Burns/pimple3-containerinterop) (using Pimple v3)
+- [SitePoint Container](https://github.com/sitepoint/Container)
+- [Thruster Container](https://github.com/ThrusterIO/container) (PHP7 only)
+- [Ultra-Lite Container](https://github.com/ultra-lite/container)
+- [Unbox](https://github.com/mindplay-dk/unbox)
+- [XStatic](https://github.com/jeremeamia/xstatic)
+- [Zend\ServiceManager](https://github.com/zendframework/zend-servicemanager)
+- [Zit](https://github.com/inxilpro/Zit)
+
+### Projects implementing the *delegate lookup* feature
+
+- [Aura.Di](https://github.com/auraphp/Aura.Di)
+- [Burlap](https://github.com/codeeverything/burlap)
+- [Chernozem](https://github.com/pyrsmk/Chernozem)
+- [InDI](https://github.com/idealogica/indi)
+- [League/Container](http://container.thephpleague.com/)
+- [Mouf](http://mouf-php.com)
+- [Picotainer](https://github.com/thecodingmachine/picotainer)
+- [PHP-DI](http://php-di.org)
+- [PimpleInterop](https://github.com/moufmouf/pimple-interop)
+- [Ultra-Lite Container](https://github.com/ultra-lite/container)
+
+### Middlewares implementing `ContainerInterface`
+
+- [Alias-Container](https://github.com/thecodingmachine/alias-container): add
+  aliases support to any container
+- [Prefixer-Container](https://github.com/thecodingmachine/prefixer-container):
+  dynamically prefix identifiers
+- [Lazy-Container](https://github.com/snapshotpl/lazy-container): lazy services
+
+### Projects using `ContainerInterface`
+
+The list below contains only a sample of all the projects consuming `ContainerInterface`. For a more complete list have a look [here](http://packanalyst.com/class?q=Interop%5CContainer%5CContainerInterface).
+
+| | Downloads |
+| --- | --- |
+| [Adroit](https://github.com/bitexpert/adroit) | ![](https://img.shields.io/packagist/dt/bitexpert/adroit.svg) |
+| [Behat](https://github.com/Behat/Behat/pull/974) | ![](https://img.shields.io/packagist/dt/behat/behat.svg) |
+| [blast-facades](https://github.com/phpthinktank/blast-facades): Minimize complexity and represent dependencies as facades. | ![](https://img.shields.io/packagist/dt/blast/facades.svg) |
+| [interop.silex.di](https://github.com/thecodingmachine/interop.silex.di): an extension to [Silex](http://silex.sensiolabs.org/) that adds support for any *container-interop* compatible container | ![](https://img.shields.io/packagist/dt/mouf/interop.silex.di.svg) |
+| [mindplay/walkway](https://github.com/mindplay-dk/walkway): a modular request router | ![](https://img.shields.io/packagist/dt/mindplay/walkway.svg) |
+| [mindplay/middleman](https://github.com/mindplay-dk/middleman): minimalist PSR-7 middleware dispatcher | ![](https://img.shields.io/packagist/dt/mindplay/middleman.svg) |
+| [PHP-DI/Invoker](https://github.com/PHP-DI/Invoker): extensible and configurable invoker/dispatcher | ![](https://img.shields.io/packagist/dt/php-di/invoker.svg) |
+| [Prophiler](https://github.com/fabfuel/prophiler) | ![](https://img.shields.io/packagist/dt/fabfuel/prophiler.svg) |
+| [Silly](https://github.com/mnapoli/silly): CLI micro-framework | ![](https://img.shields.io/packagist/dt/mnapoli/silly.svg) |
+| [Slim v3](https://github.com/slimphp/Slim) | ![](https://img.shields.io/packagist/dt/slim/slim.svg) |
+| [Splash](http://mouf-php.com/packages/mouf/mvc.splash-common/version/8.0-dev/README.md) | ![](https://img.shields.io/packagist/dt/mouf/mvc.splash-common.svg) |
+| [Woohoo Labs. Harmony](https://github.com/woohoolabs/harmony): a flexible micro-framework | ![](https://img.shields.io/packagist/dt/woohoolabs/harmony.svg) |
+| [zend-expressive](https://github.com/zendframework/zend-expressive) | ![](https://img.shields.io/packagist/dt/zendframework/zend-expressive.svg) |
+
+
+## Workflow
+
+Everyone is welcome to join and contribute.
+
+The general workflow looks like this:
+
+1. Someone opens a discussion (GitHub issue) to suggest an interface
+1. Feedback is gathered
+1. The interface is added to a development branch
+1. We release alpha versions so that the interface can be experimented with
+1. Discussions and edits ensue until the interface is deemed stable by a general consensus
+1. A new minor version of the package is released
+
+We try to not break BC by creating new interfaces instead of editing existing ones.
+
+While we currently work on interfaces, we are open to anything that might help towards interoperability, may that
+be code, best practices, etc.

+ 15 - 0
system/vendor/container-interop/container-interop/composer.json

@@ -0,0 +1,15 @@
+{
+    "name": "container-interop/container-interop",
+    "type": "library",
+    "description": "Promoting the interoperability of container objects (DIC, SL, etc.)",
+    "homepage": "https://github.com/container-interop/container-interop",
+    "license": "MIT",
+    "autoload": {
+        "psr-4": {
+            "Interop\\Container\\": "src/Interop/Container/"
+        }
+    },
+    "require": {
+        "psr/container": "^1.0"
+    }
+}

+ 114 - 0
system/vendor/container-interop/container-interop/docs/ContainerInterface-meta.md

@@ -0,0 +1,114 @@
+# ContainerInterface Meta Document
+
+## Introduction
+
+This document describes the process and discussions that lead to the `ContainerInterface`.
+Its goal is to explain the reasons behind each decision.
+
+## Goal
+
+The goal set by `ContainerInterface` is to standardize how frameworks and libraries make use of a
+container to obtain objects and parameters.
+
+By standardizing such a behavior, frameworks and libraries using the `ContainerInterface`
+could work with any compatible container.
+That would allow end users to choose their own container based on their own preferences.
+
+It is important to distinguish the two usages of a container:
+
+- configuring entries
+- fetching entries
+
+Most of the time, those two sides are not used by the same party.
+While it is often end users who tend to configure entries, it is generally the framework that fetch
+entries to build the application.
+
+This is why this interface focuses only on how entries can be fetched from a container.
+
+## Interface name
+
+The interface name has been thoroughly discussed and was decided by a vote.
+
+The list of options considered with their respective votes are:
+
+- `ContainerInterface`: +8
+- `ProviderInterface`: +2
+- `LocatorInterface`: 0
+- `ReadableContainerInterface`: -5
+- `ServiceLocatorInterface`: -6
+- `ObjectFactory`: -6
+- `ObjectStore`: -8
+- `ConsumerInterface`: -9
+
+[Full results of the vote](https://github.com/container-interop/container-interop/wiki/%231-interface-name:-Vote)
+
+The complete discussion can be read in [the issue #1](https://github.com/container-interop/container-interop/issues/1).
+
+## Interface methods
+
+The choice of which methods the interface would contain was made after a statistical analysis of existing containers.
+The results of this analysis are available [in this document](https://gist.github.com/mnapoli/6159681).
+
+The summary of the analysis showed that:
+
+- all containers offer a method to get an entry by its id
+- a large majority name such method `get()`
+- for all containers, the `get()` method has 1 mandatory parameter of type string
+- some containers have an optional additional argument for `get()`, but it doesn't have the same purpose between containers
+- a large majority of the containers offer a method to test if it can return an entry by its id
+- a majority name such method `has()`
+- for all containers offering `has()`, the method has exactly 1 parameter of type string
+- a large majority of the containers throw an exception rather than returning null when an entry is not found in `get()`
+- a large majority of the containers don't implement `ArrayAccess`
+
+The question of whether to include methods to define entries has been discussed in
+[issue #1](https://github.com/container-interop/container-interop/issues/1).
+It has been judged that such methods do not belong in the interface described here because it is out of its scope
+(see the "Goal" section).
+
+As a result, the `ContainerInterface` contains two methods:
+
+- `get()`, returning anything, with one mandatory string parameter. Should throw an exception if the entry is not found.
+- `has()`, returning a boolean, with one mandatory string parameter.
+
+### Number of parameters in `get()` method
+
+While `ContainerInterface` only defines one mandatory parameter in `get()`, it is not incompatible with
+existing containers that have additional optional parameters. PHP allows an implementation to offer more parameters
+as long as they are optional, because the implementation *does* satisfy the interface.
+
+This issue has been discussed in [issue #6](https://github.com/container-interop/container-interop/issues/6).
+
+### Type of the `$id` parameter
+
+The type of the `$id` parameter in `get()` and `has()` has been discussed in
+[issue #6](https://github.com/container-interop/container-interop/issues/6).
+While `string` is used in all the containers that were analyzed, it was suggested that allowing
+anything (such as objects) could allow containers to offer a more advanced query API.
+
+An example given was to use the container as an object builder. The `$id` parameter would then be an
+object that would describe how to create an instance.
+
+The conclusion of the discussion was that this was beyond the scope of getting entries from a container without
+knowing how the container provided them, and it was more fit for a factory.
+
+## Contributors
+
+Are listed here all people that contributed in the discussions or votes, by alphabetical order:
+
+- [Amy Stephen](https://github.com/AmyStephen)
+- [David Négrier](https://github.com/moufmouf)
+- [Don Gilbert](https://github.com/dongilbert)
+- [Jason Judge](https://github.com/judgej)
+- [Jeremy Lindblom](https://github.com/jeremeamia)
+- [Marco Pivetta](https://github.com/Ocramius)
+- [Matthieu Napoli](https://github.com/mnapoli)
+- [Paul M. Jones](https://github.com/pmjones)
+- [Stephan Hochdörfer](https://github.com/shochdoerfer)
+- [Taylor Otwell](https://github.com/taylorotwell)
+
+## Relevant links
+
+- [`ContainerInterface.php`](https://github.com/container-interop/container-interop/blob/master/src/Interop/Container/ContainerInterface.php)
+- [List of all issues](https://github.com/container-interop/container-interop/issues?labels=ContainerInterface&milestone=&page=1&state=closed)
+- [Vote for the interface name](https://github.com/container-interop/container-interop/wiki/%231-interface-name:-Vote)

+ 158 - 0
system/vendor/container-interop/container-interop/docs/ContainerInterface.md

@@ -0,0 +1,158 @@
+Container interface
+===================
+
+This document describes a common interface for dependency injection containers.
+
+The goal set by `ContainerInterface` is to standardize how frameworks and libraries make use of a
+container to obtain objects and parameters (called *entries* in the rest of this document).
+
+The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD",
+"SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be
+interpreted as described in [RFC 2119][].
+
+The word `implementor` in this document is to be interpreted as someone
+implementing the `ContainerInterface` in a dependency injection-related library or framework.
+Users of dependency injections containers (DIC) are referred to as `user`.
+
+[RFC 2119]: http://tools.ietf.org/html/rfc2119
+
+1. Specification
+-----------------
+
+### 1.1 Basics
+
+- The `Interop\Container\ContainerInterface` exposes two methods : `get` and `has`.
+
+- `get` takes one mandatory parameter: an entry identifier. It MUST be a string.
+  A call to `get` can return anything (a *mixed* value), or throws an exception if the identifier
+  is not known to the container. Two successive calls to `get` with the same
+  identifier SHOULD return the same value. However, depending on the `implementor`
+  design and/or `user` configuration, different values might be returned, so
+  `user` SHOULD NOT rely on getting the same value on 2 successive calls.
+  While `ContainerInterface` only defines one mandatory parameter in `get()`, implementations
+  MAY accept additional optional parameters.
+
+- `has` takes one unique parameter: an entry identifier. It MUST return `true`
+  if an entry identifier is known to the container and `false` if it is not.
+  `has($id)` returning true does not mean that `get($id)` will not throw an exception.
+  It does however mean that `get($id)` will not throw a `NotFoundException`.
+
+### 1.2 Exceptions
+
+Exceptions directly thrown by the container MUST implement the
+[`Interop\Container\Exception\ContainerException`](../src/Interop/Container/Exception/ContainerException.php).
+
+A call to the `get` method with a non-existing id SHOULD throw a
+[`Interop\Container\Exception\NotFoundException`](../src/Interop/Container/Exception/NotFoundException.php).
+
+### 1.3 Additional features
+
+This section describes additional features that MAY be added to a container. Containers are not
+required to implement these features to respect the ContainerInterface.
+
+#### 1.3.1 Delegate lookup feature
+
+The goal of the *delegate lookup* feature is to allow several containers to share entries.
+Containers implementing this feature can perform dependency lookups in other containers.
+
+Containers implementing this feature will offer a greater lever of interoperability
+with other containers. Implementation of this feature is therefore RECOMMENDED.
+
+A container implementing this feature:
+
+- MUST implement the `ContainerInterface`
+- MUST provide a way to register a delegate container (using a constructor parameter, or a setter,
+  or any possible way). The delegate container MUST implement the `ContainerInterface`.
+
+When a container is configured to use a delegate container for dependencies:
+
+- Calls to the `get` method should only return an entry if the entry is part of the container.
+  If the entry is not part of the container, an exception should be thrown
+  (as requested by the `ContainerInterface`).
+- Calls to the `has` method should only return `true` if the entry is part of the container.
+  If the entry is not part of the container, `false` should be returned.
+- If the fetched entry has dependencies, **instead** of performing
+  the dependency lookup in the container, the lookup is performed on the *delegate container*.
+
+Important! By default, the lookup SHOULD be performed on the delegate container **only**, not on the container itself.
+
+It is however allowed for containers to provide exception cases for special entries, and a way to lookup
+into the same container (or another container) instead of the delegate container.
+
+2. Package
+----------
+
+The interfaces and classes described as well as relevant exception are provided as part of the
+[container-interop/container-interop](https://packagist.org/packages/container-interop/container-interop) package.
+
+3. `Interop\Container\ContainerInterface`
+-----------------------------------------
+
+```php
+<?php
+namespace Interop\Container;
+
+use Interop\Container\Exception\ContainerException;
+use Interop\Container\Exception\NotFoundException;
+
+/**
+ * Describes the interface of a container that exposes methods to read its entries.
+ */
+interface ContainerInterface
+{
+    /**
+     * Finds an entry of the container by its identifier and returns it.
+     *
+     * @param string $id Identifier of the entry to look for.
+     *
+     * @throws NotFoundException  No entry was found for this identifier.
+     * @throws ContainerException Error while retrieving the entry.
+     *
+     * @return mixed Entry.
+     */
+    public function get($id);
+
+    /**
+     * Returns true if the container can return an entry for the given identifier.
+     * Returns false otherwise.
+     *
+     * `has($id)` returning true does not mean that `get($id)` will not throw an exception.
+     * It does however mean that `get($id)` will not throw a `NotFoundException`.
+     *
+     * @param string $id Identifier of the entry to look for.
+     *
+     * @return boolean
+     */
+    public function has($id);
+}
+```
+
+4. `Interop\Container\Exception\ContainerException`
+---------------------------------------------------
+
+```php
+<?php
+namespace Interop\Container\Exception;
+
+/**
+ * Base interface representing a generic exception in a container.
+ */
+interface ContainerException
+{
+}
+```
+
+5. `Interop\Container\Exception\NotFoundException`
+---------------------------------------------------
+
+```php
+<?php
+namespace Interop\Container\Exception;
+
+/**
+ * No entry was found in the container.
+ */
+interface NotFoundException extends ContainerException
+{
+}
+```

+ 259 - 0
system/vendor/container-interop/container-interop/docs/Delegate-lookup-meta.md

@@ -0,0 +1,259 @@
+Delegate lookup feature Meta Document
+=====================================
+
+1. Summary
+----------
+
+This document describes the *delegate lookup feature*.
+Containers are not required to implement this feature to respect the `ContainerInterface`.
+However, containers implementing this feature will offer a greater lever of interoperability
+with other containers, allowing multiple containers to share entries in the same application.
+Implementation of this feature is therefore recommanded.
+
+2. Why Bother?
+--------------
+
+The [`ContainerInterface`](../src/Interop/Container/ContainerInterface.php) ([meta doc](ContainerInterface.md))
+standardizes how frameworks and libraries make use of a container to obtain objects and parameters.
+
+By standardizing such a behavior, frameworks and libraries relying on the `ContainerInterface`
+could work with any compatible container.
+That would allow end users to choose their own container based on their own preferences.
+
+The `ContainerInterface` is also enough if we want to have several containers side-by-side in the same
+application. For instance, this is what the [CompositeContainer](https://github.com/jeremeamia/acclimate-container/blob/master/src/CompositeContainer.php) 
+class of [Acclimate](https://github.com/jeremeamia/acclimate-container) is designed for:
+
+![Side by side containers](images/side_by_side_containers.png)
+
+However, an instance in container 1 cannot reference an instance in container 2.
+
+It would be better if an instance of container 1 could reference an instance in container 2,
+and the opposite should be true. 
+
+![Interoperating containers](images/interoperating_containers.png)
+
+In the sample above, entry 1 in container 1 is referencing entry 3 in container 2.
+
+3. Scope
+--------
+
+### 3.1 Goals
+
+The goal of the *delegate lookup* feature is to allow several containers to share entries.
+
+4. Approaches
+-------------
+
+### 4.1 Chosen Approach
+
+Containers implementing this feature can perform dependency lookups in other containers.
+
+A container implementing this feature:
+
+- must implement the `ContainerInterface`
+- must provide a way to register a *delegate container* (using a constructor parameter, or a setter, or any
+possible way). The *delegate container* must implement the `ContainerInterface`.
+
+When a *delegate container* is configured on a container:
+
+- Calls to the `get` method should only return an entry if the entry is part of the container.
+If the entry is not part of the container, an exception should be thrown (as required in the `ContainerInterface`).
+- Calls to the `has` method should only return *true* if the entry is part of the container.
+If the entry is not part of the container, *false* should be returned.
+ - Finally, the important part: if the entry we are fetching has dependencies,
+**instead** of perfoming the dependency lookup in the container, the lookup is performed on the *delegate container*.
+
+Important! By default, the lookup should be performed on the delegate container **only**, not on the container itself.
+
+It is however allowed for containers to provide exception cases for special entries, and a way to lookup into 
+the same container (or another container) instead of the delegate container.
+
+### 4.2 Typical usage
+
+The *delegate container* will usually be a composite container. A composite container is a container that
+contains several other containers. When performing a lookup on a composite container, the inner containers are 
+queried until one container returns an entry.
+An inner container implementing the *delegate lookup feature* will return entries it contains, but if these
+entries have dependencies, the dependencies lookup calls will be performed on the composite container, giving
+a chance to all containers to answer.
+
+Interestingly enough, the order in which containers are added in the composite container matters. Indeed,
+the first containers to be added in the composite container can "override" the entries of containers with
+lower priority.
+
+![Containers priority](images/priority.png)
+
+In the example above, "container 2" contains a controller "myController" and the controller is referencing an 
+"entityManager" entry. "Container 1" contains also an entry named "entityManager".
+Without the *delegate lookup* feature, when requesting the "myController" instance to container 2, it would take 
+in charge the instanciation of both entries.
+
+However, using the *delegate lookup* feature, here is what happens when we ask the composite container for the 
+"myController" instance:
+
+- The composite container asks container 1 if if contains the "myController" instance. The answer is no.
+- The composite container asks container 2 if if contains the "myController" instance. The answer is yes.
+- The composite container performs a `get` call on container 2 for the "myController" instance.
+- Container 2 sees that "myController" has a dependency on "entityManager".
+- Container 2 delegates the lookup of "entityManager" to the composite container.
+- The composite container asks container 1 if if contains the "entityManager" instance. The answer is yes.
+- The composite container performs a `get` call on container 1 for the "entityManager" instance.
+
+In the end, we get a controller instanciated by container 2 that references an entityManager instanciated
+by container 1.
+
+### 4.3 Alternative: the fallback strategy
+
+The first proposed approach we tried was to perform all the lookups in the "local" container,
+and if a lookup fails in the container, to use the delegate container. In this scenario, the
+delegate container is used in "fallback" mode.
+
+This strategy has been described in @moufmouf blog post: http://mouf-php.com/container-interop-whats-next (solution 1).
+It was also discussed [here](https://github.com/container-interop/container-interop/pull/8#issuecomment-33570697) and
+[here](https://github.com/container-interop/container-interop/pull/20#issuecomment-56599631).
+
+Problems with this strategy:
+
+- Heavy problem regarding infinite loops
+- Unable to overload a container entry with the delegate container entry
+
+### 4.4 Alternative: force implementing an interface
+
+The first proposed approach was to develop a `ParentAwareContainerInterface` interface.
+It was proposed here: https://github.com/container-interop/container-interop/pull/8
+
+The interface would have had the behaviour of the delegate lookup feature but would have forced the addition of
+a `setParentContainter` method:
+
+```php
+interface ParentAwareContainerInterface extends ReadableContainerInterface {
+    /**
+     * Sets the parent container associated to that container. This container will call
+     * the parent container to fetch dependencies.
+     *
+     * @param ContainerInterface $container
+     */
+    public function setParentContainer(ContainerInterface $container);
+}
+```
+
+The interface idea was first questioned by @Ocramius [here](https://github.com/container-interop/container-interop/pull/8#issuecomment-51721777).
+@Ocramius expressed the idea that an interface should not contain setters, otherwise, it is forcing implementation
+details on the class implementing the interface. 
+Then @mnapoli made a proposal for a "convention" [here](https://github.com/container-interop/container-interop/pull/8#issuecomment-51841079),
+this idea was further discussed until all participants in the discussion agreed to remove the interface idea
+and replace it with a "standard" feature.
+
+**Pros:**
+
+If we had had an interface, we could have delegated the registration of the delegate/composite container to the
+the delegate/composite container itself.
+For instance:
+
+```php
+$containerA = new ContainerA();
+$containerB = new ContainerB();
+
+$compositeContainer = new CompositeContainer([$containerA, $containerB]);
+
+// The call to 'setParentContainer' is delegated to the CompositeContainer
+// It is not the responsibility of the user anymore.
+class CompositeContainer {
+	...
+	
+	public function __construct($containers) {
+		foreach ($containers as $container) {
+			if ($container instanceof ParentAwareContainerInterface) {
+				$container->setParentContainer($this);
+			}
+		}
+		...
+	}
+}
+
+``` 
+
+**Cons:**
+
+Cons have been extensively discussed [here](https://github.com/container-interop/container-interop/pull/8#issuecomment-51721777).
+Basically, forcing a setter into an interface is a bad idea. Setters are similar to constructor arguments,
+and it's a bad idea to standardize a constructor: how the delegate container is configured into a container is an implementation detail. This outweights the benefits of the interface.
+
+### 4.4 Alternative: no exception case for delegate lookups
+
+Originally, the proposed wording for delegate lookup calls was:
+
+> Important! The lookup MUST be performed on the delegate container **only**, not on the container itself.
+
+This was later replaced by:
+
+> Important! By default, the lookup SHOULD be performed on the delegate container **only**, not on the container itself.
+>
+> It is however allowed for containers to provide exception cases for special entries, and a way to lookup 
+> into the same container (or another container) instead of the delegate container.
+
+Exception cases have been allowed to avoid breaking dependencies with some services that must be provided
+by the container (on @njasm proposal). This was proposed here: https://github.com/container-interop/container-interop/pull/20#issuecomment-56597235
+
+### 4.5 Alternative: having one of the containers act as the composite container
+
+In real-life scenarios, we usually have a big framework (Symfony 2, Zend Framework 2, etc...) and we want to
+add another DI container to this container. Most of the time, the "big" framework will be responsible for
+creating the controller's instances, using it's own DI container. Until *container-interop* is fully adopted,
+the "big" framework will not be aware of the existence of a composite container that it should use instead
+of its own container.
+
+For this real-life use cases, @mnapoli and @moufmouf proposed to extend the "big" framework's DI container
+to make it act as a composite container.
+
+This has been discussed [here](https://github.com/container-interop/container-interop/pull/8#issuecomment-40367194) 
+and [here](http://mouf-php.com/container-interop-whats-next#solution4).
+
+This was implemented in Symfony 2 using:
+
+- [interop.symfony.di](https://github.com/thecodingmachine/interop.symfony.di/tree/v0.1.0)
+- [framework interop](https://github.com/mnapoli/framework-interop/)
+
+This was implemented in Silex using:
+
+- [interop.silex.di](https://github.com/thecodingmachine/interop.silex.di)
+
+Having a container act as the composite container is not part of the delegate lookup standard because it is
+simply a temporary design pattern used to make existing frameworks that do not support yet ContainerInterop
+play nice with other DI containers.
+
+
+5. Implementations
+------------------
+
+The following projects already implement the delegate lookup feature:
+
+- [Mouf](http://mouf-php.com), through the [`setDelegateLookupContainer` method](https://github.com/thecodingmachine/mouf/blob/2.0/src/Mouf/MoufManager.php#L2120)
+- [PHP-DI](http://php-di.org/), through the [`$wrapperContainer` parameter of the constructor](https://github.com/mnapoli/PHP-DI/blob/master/src/DI/Container.php#L72)
+- [pimple-interop](https://github.com/moufmouf/pimple-interop), through the [`$container` parameter of the constructor](https://github.com/moufmouf/pimple-interop/blob/master/src/Interop/Container/Pimple/PimpleInterop.php#L62)
+
+6. People
+---------
+
+Are listed here all people that contributed in the discussions, by alphabetical order:
+
+- [Alexandru Pătrănescu](https://github.com/drealecs)
+- [Ben Peachey](https://github.com/potherca)
+- [David Négrier](https://github.com/moufmouf)
+- [Jeremy Lindblom](https://github.com/jeremeamia)
+- [Marco Pivetta](https://github.com/Ocramius)
+- [Matthieu Napoli](https://github.com/mnapoli)
+- [Nelson J Morais](https://github.com/njasm)
+- [Phil Sturgeon](https://github.com/philsturgeon)
+- [Stephan Hochdörfer](https://github.com/shochdoerfer)
+
+7. Relevant Links
+-----------------
+
+_**Note:** Order descending chronologically._
+
+- [Pull request on the delegate lookup feature](https://github.com/container-interop/container-interop/pull/20)
+- [Pull request on the interface idea](https://github.com/container-interop/container-interop/pull/8)
+- [Original article exposing the delegate lookup idea along many others](http://mouf-php.com/container-interop-whats-next)
+

+ 60 - 0
system/vendor/container-interop/container-interop/docs/Delegate-lookup.md

@@ -0,0 +1,60 @@
+Delegate lookup feature
+=======================
+
+This document describes a standard for dependency injection containers.
+
+The goal set by the *delegate lookup* feature is to allow several containers to share entries.
+Containers implementing this feature can perform dependency lookups in other containers.
+
+Containers implementing this feature will offer a greater lever of interoperability
+with other containers. Implementation of this feature is therefore RECOMMENDED.
+
+The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD",
+"SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be
+interpreted as described in [RFC 2119][].
+
+The word `implementor` in this document is to be interpreted as someone
+implementing the delegate lookup feature in a dependency injection-related library or framework.
+Users of dependency injections containers (DIC) are referred to as `user`.
+
+[RFC 2119]: http://tools.ietf.org/html/rfc2119
+
+1. Vocabulary
+-------------
+
+In a dependency injection container, the container is used to fetch entries.
+Entries can have dependencies on other entries. Usually, these other entries are fetched by the container.
+
+The *delegate lookup* feature is the ability for a container to fetch dependencies in
+another container. In the rest of the document, the word "container" will reference the container
+implemented by the implementor. The word "delegate container" will reference the container we are
+fetching the dependencies from.
+
+2. Specification
+----------------
+
+A container implementing the *delegate lookup* feature:
+
+- MUST implement the [`ContainerInterface`](ContainerInterface.md)
+- MUST provide a way to register a delegate container (using a constructor parameter, or a setter,
+  or any possible way). The delegate container MUST implement the [`ContainerInterface`](ContainerInterface.md).
+
+When a container is configured to use a delegate container for dependencies:
+
+- Calls to the `get` method should only return an entry if the entry is part of the container.
+  If the entry is not part of the container, an exception should be thrown
+  (as requested by the [`ContainerInterface`](ContainerInterface.md)).
+- Calls to the `has` method should only return `true` if the entry is part of the container.
+  If the entry is not part of the container, `false` should be returned.
+- If the fetched entry has dependencies, **instead** of performing
+  the dependency lookup in the container, the lookup is performed on the *delegate container*.
+
+Important: By default, the dependency lookups SHOULD be performed on the delegate container **only**, not on the container itself.
+
+It is however allowed for containers to provide exception cases for special entries, and a way to lookup
+into the same container (or another container) instead of the delegate container.
+
+3. Package / Interface
+----------------------
+
+This feature is not tied to any code, interface or package.

BIN
system/vendor/container-interop/container-interop/docs/images/interoperating_containers.png


BIN
system/vendor/container-interop/container-interop/docs/images/priority.png


BIN
system/vendor/container-interop/container-interop/docs/images/side_by_side_containers.png


+ 15 - 0
system/vendor/container-interop/container-interop/src/Interop/Container/ContainerInterface.php

@@ -0,0 +1,15 @@
+<?php
+/**
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
+ */
+
+namespace Interop\Container;
+
+use Psr\Container\ContainerInterface as PsrContainerInterface;
+
+/**
+ * Describes the interface of a container that exposes methods to read its entries.
+ */
+interface ContainerInterface extends PsrContainerInterface
+{
+}

+ 15 - 0
system/vendor/container-interop/container-interop/src/Interop/Container/Exception/ContainerException.php

@@ -0,0 +1,15 @@
+<?php
+/**
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
+ */
+
+namespace Interop\Container\Exception;
+
+use Psr\Container\ContainerExceptionInterface as PsrContainerException;
+
+/**
+ * Base interface representing a generic exception in a container.
+ */
+interface ContainerException extends PsrContainerException
+{
+}

+ 15 - 0
system/vendor/container-interop/container-interop/src/Interop/Container/Exception/NotFoundException.php

@@ -0,0 +1,15 @@
+<?php
+/**
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
+ */
+
+namespace Interop\Container\Exception;
+
+use Psr\Container\NotFoundExceptionInterface as PsrNotFoundException;
+
+/**
+ * No entry was found in the container.
+ */
+interface NotFoundException extends ContainerException, PsrNotFoundException
+{
+}

+ 1 - 0
system/vendor/erusev/parsedown

@@ -0,0 +1 @@
+Subproject commit 1bf24f7334fe16c88bf9d467863309ceaf285b01

+ 1 - 0
system/vendor/erusev/parsedown-extra

@@ -0,0 +1 @@
+Subproject commit 0db5cce7354e4b76f155d092ab5eb3981c21258c

+ 1 - 0
system/vendor/jbroadway/urlify

@@ -0,0 +1 @@
+Subproject commit 99bb78cd9002d0e9ce479bb81635eb665e37e981

+ 5 - 0
system/vendor/nikic/fast-route/.gitignore

@@ -0,0 +1,5 @@
+/vendor/
+.idea/
+
+# ignore lock file since we have no extra dependencies
+composer.lock

+ 1 - 0
system/vendor/nikic/fast-route/.hhconfig

@@ -0,0 +1 @@
+assume_php=false

+ 12 - 0
system/vendor/nikic/fast-route/.travis.yml

@@ -0,0 +1,12 @@
+language: php
+
+php:
+  - 5.4
+  - 5.5
+  - 5.6
+  - 7.0
+  - hhvm
+
+matrix:
+  allow_failures:
+    - php: 7.0

+ 126 - 0
system/vendor/nikic/fast-route/FastRoute.hhi

@@ -0,0 +1,126 @@
+<?hh // decl
+
+namespace FastRoute {
+    class BadRouteException extends \LogicException {
+    }
+
+    interface RouteParser {
+        public function parse(string $route): array<array>;
+    }
+
+    class RouteCollector {
+        public function __construct(RouteParser $routeParser, DataGenerator $dataGenerator);
+        public function addRoute(mixed $httpMethod, string $route, mixed $handler): void;
+        public function getData(): array;
+    }
+
+    class Route {
+        public function __construct(string $httpMethod, mixed $handler, string $regex, array $variables);
+        public function matches(string $str): bool;
+    }
+
+    interface DataGenerator {
+        public function addRoute(string $httpMethod, array $routeData, mixed $handler);
+        public function getData(): array;
+    }
+
+    interface Dispatcher {
+        const int NOT_FOUND = 0;
+        const int FOUND = 1;
+        const int METHOD_NOT_ALLOWED = 2;
+        public function dispatch(string $httpMethod, string $uri): array;
+    }
+
+    function simpleDispatcher(
+        (function(RouteCollector): void) $routeDefinitionCallback,
+        shape(
+          'routeParser' => ?classname<RouteParser>,
+          'dataGenerator' => ?classname<DataGenerator>,
+          'dispatcher' => ?classname<Dispatcher>,
+          'routeCollector' => ?classname<RouteCollector>,
+        ) $options = shape()): Dispatcher;
+
+    function cachedDispatcher(
+        (function(RouteCollector): void) $routeDefinitionCallback,
+        shape(
+          'routeParser' => ?classname<RouteParser>,
+          'dataGenerator' => ?classname<DataGenerator>,
+          'dispatcher' => ?classname<Dispatcher>,
+          'routeCollector' => ?classname<RouteCollector>,
+          'cacheDisabled' => ?bool,
+          'cacheFile' => ?string,
+        ) $options = shape()): Dispatcher;
+}
+
+namespace FastRoute\DataGenerator {
+    abstract class RegexBasedAbstract implements \FastRoute\DataGenerator {
+        protected abstract function getApproxChunkSize();
+        protected abstract function processChunk($regexToRoutesMap);
+
+        public function addRoute(string $httpMethod, array $routeData, mixed $handler): void;
+        public function getData(): array;
+    }
+
+    class CharCountBased extends RegexBasedAbstract {
+        protected function getApproxChunkSize(): int;
+        protected function processChunk(array<string, string> $regexToRoutesMap): array<string, mixed>;
+    }
+
+    class GroupCountBased extends RegexBasedAbstract {
+        protected function getApproxChunkSize(): int;
+        protected function processChunk(array<string, string> $regexToRoutesMap): array<string, mixed>;
+    }
+
+    class GroupPosBased extends RegexBasedAbstract {
+        protected function getApproxChunkSize(): int;
+        protected function processChunk(array<string, string> $regexToRoutesMap): array<string, mixed>;
+    }
+
+    class MarkBased extends RegexBasedAbstract {
+        protected function getApproxChunkSize(): int;
+        protected function processChunk(array<string, string> $regexToRoutesMap): array<string, mixed>;
+    }
+}
+
+namespace FastRoute\Dispatcher {
+    abstract class RegexBasedAbstract implements \FastRoute\Dispatcher {
+        protected abstract function dispatchVariableRoute(array<array> $routeData, string $uri): array;
+
+        public function dispatch(string $httpMethod, string $uri): array;
+    }
+
+    class GroupPosBased extends RegexBasedAbstract {
+        public function __construct(array $data);
+        protected function dispatchVariableRoute(array<array> $routeData, string $uri): array;
+    }
+
+    class GroupCountBased extends RegexBasedAbstract {
+        public function __construct(array $data);
+        protected function dispatchVariableRoute(array<array> $routeData, string $uri): array;
+    }
+
+    class CharCountBased extends RegexBasedAbstract {
+        public function __construct(array $data);
+        protected function dispatchVariableRoute(array<array> $routeData, string $uri): array;
+    }
+
+    class MarkBased extends RegexBasedAbstract {
+        public function __construct(array $data);
+        protected function dispatchVariableRoute(array<array> $routeData, string $uri): array;
+    }
+}
+
+namespace FastRoute\RouteParser {
+    class Std implements \FastRoute\RouteParser {
+        const string VARIABLE_REGEX = <<<'REGEX'
+\{
+    \s* ([a-zA-Z][a-zA-Z0-9_]*) \s*
+    (?:
+        : \s* ([^{}]*(?:\{(?-1)\}[^{}]*)*)
+    )?
+\}
+REGEX;
+        const string DEFAULT_DISPATCH_REGEX = '[^/]+';
+        public function parse(string $route): array<array>;
+    }
+}

+ 31 - 0
system/vendor/nikic/fast-route/LICENSE

@@ -0,0 +1,31 @@
+Copyright (c) 2013 by Nikita Popov.
+
+Some rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * The names of the contributors may not be used to endorse or
+      promote products derived from this software without specific
+      prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ 313 - 0
system/vendor/nikic/fast-route/README.md

@@ -0,0 +1,313 @@
+FastRoute - Fast request router for PHP
+=======================================
+
+This library provides a fast implementation of a regular expression based router. [Blog post explaining how the
+implementation works and why it is fast.][blog_post]
+
+Install
+-------
+
+To install with composer:
+
+```sh
+composer require nikic/fast-route
+```
+
+Requires PHP 5.4 or newer.
+
+Usage
+-----
+
+Here's a basic usage example:
+
+```php
+<?php
+
+require '/path/to/vendor/autoload.php';
+
+$dispatcher = FastRoute\simpleDispatcher(function(FastRoute\RouteCollector $r) {
+    $r->addRoute('GET', '/users', 'get_all_users_handler');
+    // {id} must be a number (\d+)
+    $r->addRoute('GET', '/user/{id:\d+}', 'get_user_handler');
+    // The /{title} suffix is optional
+    $r->addRoute('GET', '/articles/{id:\d+}[/{title}]', 'get_article_handler');
+});
+
+// Fetch method and URI from somewhere
+$httpMethod = $_SERVER['REQUEST_METHOD'];
+$uri = $_SERVER['REQUEST_URI'];
+
+// Strip query string (?foo=bar) and decode URI
+if (false !== $pos = strpos($uri, '?')) {
+    $uri = substr($uri, 0, $pos);
+}
+$uri = rawurldecode($uri);
+
+$routeInfo = $dispatcher->dispatch($httpMethod, $uri);
+switch ($routeInfo[0]) {
+    case FastRoute\Dispatcher::NOT_FOUND:
+        // ... 404 Not Found
+        break;
+    case FastRoute\Dispatcher::METHOD_NOT_ALLOWED:
+        $allowedMethods = $routeInfo[1];
+        // ... 405 Method Not Allowed
+        break;
+    case FastRoute\Dispatcher::FOUND:
+        $handler = $routeInfo[1];
+        $vars = $routeInfo[2];
+        // ... call $handler with $vars
+        break;
+}
+```
+
+### Defining routes
+
+The routes are defined by calling the `FastRoute\simpleDispatcher()` function, which accepts
+a callable taking a `FastRoute\RouteCollector` instance. The routes are added by calling
+`addRoute()` on the collector instance:
+
+```php
+$r->addRoute($method, $routePattern, $handler);
+```
+
+The `$method` is an uppercase HTTP method string for which a certain route should match. It
+is possible to specify multiple valid methods using an array:
+
+```php
+// These two calls
+$r->addRoute('GET', '/test', 'handler');
+$r->addRoute('POST', '/test', 'handler');
+// Are equivalent to this one call
+$r->addRoute(['GET', 'POST'], '/test', 'handler');
+```
+
+By default the `$routePattern` uses a syntax where `{foo}` specifies a placeholder with name `foo`
+and matching the regex `[^/]+`. To adjust the pattern the placeholder matches, you can specify
+a custom pattern by writing `{bar:[0-9]+}`. Some examples:
+
+```php
+// Matches /user/42, but not /user/xyz
+$r->addRoute('GET', '/user/{id:\d+}', 'handler');
+
+// Matches /user/foobar, but not /user/foo/bar
+$r->addRoute('GET', '/user/{name}', 'handler');
+
+// Matches /user/foo/bar as well
+$r->addRoute('GET', '/user/{name:.+}', 'handler');
+```
+
+Custom patterns for route placeholders cannot use capturing groups. For example `{lang:(en|de)}`
+is not a valid placeholder, because `()` is a capturing group. Instead you can use either
+`{lang:en|de}` or `{lang:(?:en|de)}`.
+
+Furthermore parts of the route enclosed in `[...]` are considered optional, so that `/foo[bar]`
+will match both `/foo` and `/foobar`. Optional parts are only supported in a trailing position,
+not in the middle of a route.
+
+```php
+// This route
+$r->addRoute('GET', '/user/{id:\d+}[/{name}]', 'handler');
+// Is equivalent to these two routes
+$r->addRoute('GET', '/user/{id:\d+}', 'handler');
+$r->addRoute('GET', '/user/{id:\d+}/{name}', 'handler');
+
+// Multiple nested optional parts are possible as well
+$r->addRoute('GET', '/user[/{id:\d+}[/{name}]]', 'handler');
+
+// This route is NOT valid, because optional parts can only occur at the end
+$r->addRoute('GET', '/user[/{id:\d+}]/{name}', 'handler');
+```
+
+The `$handler` parameter does not necessarily have to be a callback, it could also be a controller
+class name or any other kind of data you wish to associate with the route. FastRoute only tells you
+which handler corresponds to your URI, how you interpret it is up to you.
+
+#### Shorcut methods for common request methods
+
+For the `GET`, `POST`, `PUT`, `PATCH`, `DELETE` and `HEAD` request methods shortcut methods are available. For example:
+
+```php
+$r->get('/get-route', 'get_handler');
+$r->post('/post-route', 'post_handler');
+```
+
+Is equivalent to:
+
+```php
+$r->addRoute('GET', '/get-route', 'get_handler');
+$r->addRoute('POST', '/post-route', 'post_handler');
+```
+
+#### Route Groups
+
+Additionally, you can specify routes inside of a group. All routes defined inside a group will have a common prefix.
+
+For example, defining your routes as:
+
+```php
+$r->addGroup('/admin', function (RouteCollector $r) {
+    $r->addRoute('GET', '/do-something', 'handler');
+    $r->addRoute('GET', '/do-another-thing', 'handler');
+    $r->addRoute('GET', '/do-something-else', 'handler');
+});
+```
+
+Will have the same result as:
+
+ ```php
+$r->addRoute('GET', '/admin/do-something', 'handler');
+$r->addRoute('GET', '/admin/do-another-thing', 'handler');
+$r->addRoute('GET', '/admin/do-something-else', 'handler');
+ ```
+
+Nested groups are also supported, in which case the prefixes of all the nested groups are combined.
+
+### Caching
+
+The reason `simpleDispatcher` accepts a callback for defining the routes is to allow seamless
+caching. By using `cachedDispatcher` instead of `simpleDispatcher` you can cache the generated
+routing data and construct the dispatcher from the cached information:
+
+```php
+<?php
+
+$dispatcher = FastRoute\cachedDispatcher(function(FastRoute\RouteCollector $r) {
+    $r->addRoute('GET', '/user/{name}/{id:[0-9]+}', 'handler0');
+    $r->addRoute('GET', '/user/{id:[0-9]+}', 'handler1');
+    $r->addRoute('GET', '/user/{name}', 'handler2');
+}, [
+    'cacheFile' => __DIR__ . '/route.cache', /* required */
+    'cacheDisabled' => IS_DEBUG_ENABLED,     /* optional, enabled by default */
+]);
+```
+
+The second parameter to the function is an options array, which can be used to specify the cache
+file location, among other things.
+
+### Dispatching a URI
+
+A URI is dispatched by calling the `dispatch()` method of the created dispatcher. This method
+accepts the HTTP method and a URI. Getting those two bits of information (and normalizing them
+appropriately) is your job - this library is not bound to the PHP web SAPIs.
+
+The `dispatch()` method returns an array whose first element contains a status code. It is one
+of `Dispatcher::NOT_FOUND`, `Dispatcher::METHOD_NOT_ALLOWED` and `Dispatcher::FOUND`. For the
+method not allowed status the second array element contains a list of HTTP methods allowed for
+the supplied URI. For example:
+
+    [FastRoute\Dispatcher::METHOD_NOT_ALLOWED, ['GET', 'POST']]
+
+> **NOTE:** The HTTP specification requires that a `405 Method Not Allowed` response include the
+`Allow:` header to detail available methods for the requested resource. Applications using FastRoute
+should use the second array element to add this header when relaying a 405 response.
+
+For the found status the second array element is the handler that was associated with the route
+and the third array element is a dictionary of placeholder names to their values. For example:
+
+    /* Routing against GET /user/nikic/42 */
+
+    [FastRoute\Dispatcher::FOUND, 'handler0', ['name' => 'nikic', 'id' => '42']]
+
+### Overriding the route parser and dispatcher
+
+The routing process makes use of three components: A route parser, a data generator and a
+dispatcher. The three components adhere to the following interfaces:
+
+```php
+<?php
+
+namespace FastRoute;
+
+interface RouteParser {
+    public function parse($route);
+}
+
+interface DataGenerator {
+    public function addRoute($httpMethod, $routeData, $handler);
+    public function getData();
+}
+
+interface Dispatcher {
+    const NOT_FOUND = 0, FOUND = 1, METHOD_NOT_ALLOWED = 2;
+
+    public function dispatch($httpMethod, $uri);
+}
+```
+
+The route parser takes a route pattern string and converts it into an array of route infos, where
+each route info is again an array of it's parts. The structure is best understood using an example:
+
+    /* The route /user/{id:\d+}[/{name}] converts to the following array: */
+    [
+        [
+            '/user/',
+            ['id', '\d+'],
+        ],
+        [
+            '/user/',
+            ['id', '\d+'],
+            '/',
+            ['name', '[^/]+'],
+        ],
+    ]
+
+This array can then be passed to the `addRoute()` method of a data generator. After all routes have
+been added the `getData()` of the generator is invoked, which returns all the routing data required
+by the dispatcher. The format of this data is not further specified - it is tightly coupled to
+the corresponding dispatcher.
+
+The dispatcher accepts the routing data via a constructor and provides a `dispatch()` method, which
+you're already familiar with.
+
+The route parser can be overwritten individually (to make use of some different pattern syntax),
+however the data generator and dispatcher should always be changed as a pair, as the output from
+the former is tightly coupled to the input of the latter. The reason the generator and the
+dispatcher are separate is that only the latter is needed when using caching (as the output of
+the former is what is being cached.)
+
+When using the `simpleDispatcher` / `cachedDispatcher` functions from above the override happens
+through the options array:
+
+```php
+<?php
+
+$dispatcher = FastRoute\simpleDispatcher(function(FastRoute\RouteCollector $r) {
+    /* ... */
+}, [
+    'routeParser' => 'FastRoute\\RouteParser\\Std',
+    'dataGenerator' => 'FastRoute\\DataGenerator\\GroupCountBased',
+    'dispatcher' => 'FastRoute\\Dispatcher\\GroupCountBased',
+]);
+```
+
+The above options array corresponds to the defaults. By replacing `GroupCountBased` by
+`GroupPosBased` you could switch to a different dispatching strategy.
+
+### A Note on HEAD Requests
+
+The HTTP spec requires servers to [support both GET and HEAD methods][2616-511]:
+
+> The methods GET and HEAD MUST be supported by all general-purpose servers
+
+To avoid forcing users to manually register HEAD routes for each resource we fallback to matching an
+available GET route for a given resource. The PHP web SAPI transparently removes the entity body
+from HEAD responses so this behavior has no effect on the vast majority of users.
+
+However, implementers using FastRoute outside the web SAPI environment (e.g. a custom server) MUST
+NOT send entity bodies generated in response to HEAD requests. If you are a non-SAPI user this is
+*your responsibility*; FastRoute has no purview to prevent you from breaking HTTP in such cases.
+
+Finally, note that applications MAY always specify their own HEAD method route for a given
+resource to bypass this behavior entirely.
+
+### Credits
+
+This library is based on a router that [Levi Morrison][levi] implemented for the Aerys server.
+
+A large number of tests, as well as HTTP compliance considerations, were provided by [Daniel Lowrey][rdlowrey].
+
+
+[2616-511]: http://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html#sec5.1.1 "RFC 2616 Section 5.1.1"
+[blog_post]: http://nikic.github.io/2014/02/18/Fast-request-routing-using-regular-expressions.html
+[levi]: https://github.com/morrisonlevi
+[rdlowrey]: https://github.com/rdlowrey

+ 21 - 0
system/vendor/nikic/fast-route/composer.json

@@ -0,0 +1,21 @@
+{
+  "name": "nikic/fast-route",
+  "description": "Fast request router for PHP",
+  "keywords": ["routing", "router"],
+  "license": "BSD-3-Clause",
+  "authors": [
+    {
+      "name": "Nikita Popov",
+      "email": "nikic@php.net"
+    }
+  ],
+  "require": {
+    "php": ">=5.4.0"
+  },
+  "autoload": {
+    "psr-4": {
+      "FastRoute\\": "src/"
+    },
+    "files": ["src/functions.php"]
+  }
+}

+ 24 - 0
system/vendor/nikic/fast-route/phpunit.xml

@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<phpunit backupGlobals="false"
+         backupStaticAttributes="false"
+         colors="true"
+         convertErrorsToExceptions="true"
+         convertNoticesToExceptions="true"
+         convertWarningsToExceptions="true"
+         processIsolation="false"
+         syntaxCheck="false"
+         bootstrap="test/bootstrap.php"
+        >
+    <testsuites>
+        <testsuite name="FastRoute Tests">
+            <directory>./test/</directory>
+        </testsuite>
+    </testsuites>
+
+    <filter>
+        <whitelist>
+            <directory>./src/</directory>
+        </whitelist>
+    </filter>
+</phpunit>

+ 6 - 0
system/vendor/nikic/fast-route/src/BadRouteException.php

@@ -0,0 +1,6 @@
+<?php
+
+namespace FastRoute;
+
+class BadRouteException extends \LogicException {
+}

+ 25 - 0
system/vendor/nikic/fast-route/src/DataGenerator.php

@@ -0,0 +1,25 @@
+<?php
+
+namespace FastRoute;
+
+interface DataGenerator {
+    /**
+     * Adds a route to the data generator. The route data uses the
+     * same format that is returned by RouterParser::parser().
+     *
+     * The handler doesn't necessarily need to be a callable, it
+     * can be arbitrary data that will be returned when the route
+     * matches.
+     *
+     * @param string $httpMethod
+     * @param array $routeData
+     * @param mixed $handler
+     */
+    public function addRoute($httpMethod, $routeData, $handler);
+
+    /**
+     * Returns dispatcher data in some unspecified format, which
+     * depends on the used method of dispatch.
+     */
+    public function getData();
+}

+ 28 - 0
system/vendor/nikic/fast-route/src/DataGenerator/CharCountBased.php

@@ -0,0 +1,28 @@
+<?php
+
+namespace FastRoute\DataGenerator;
+
+class CharCountBased extends RegexBasedAbstract {
+    protected function getApproxChunkSize() {
+        return 30;
+    }
+
+    protected function processChunk($regexToRoutesMap) {
+        $routeMap = [];
+        $regexes = [];
+
+        $suffixLen = 0;
+        $suffix = '';
+        $count = count($regexToRoutesMap);
+        foreach ($regexToRoutesMap as $regex => $route) {
+            $suffixLen++;
+            $suffix .= "\t";
+
+            $regexes[] = '(?:' . $regex . '/(\t{' . $suffixLen . '})\t{' . ($count - $suffixLen) . '})';
+            $routeMap[$suffix] = [$route->handler, $route->variables];
+        }
+
+        $regex = '~^(?|' . implode('|', $regexes) . ')$~';
+        return ['regex' => $regex, 'suffix' => '/' . $suffix, 'routeMap' => $routeMap];
+    }
+}

+ 28 - 0
system/vendor/nikic/fast-route/src/DataGenerator/GroupCountBased.php

@@ -0,0 +1,28 @@
+<?php
+
+namespace FastRoute\DataGenerator;
+
+class GroupCountBased extends RegexBasedAbstract {
+    protected function getApproxChunkSize() {
+        return 10;
+    }
+
+    protected function processChunk($regexToRoutesMap) {
+        $routeMap = [];
+        $regexes = [];
+        $numGroups = 0;
+        foreach ($regexToRoutesMap as $regex => $route) {
+            $numVariables = count($route->variables);
+            $numGroups = max($numGroups, $numVariables);
+
+            $regexes[] = $regex . str_repeat('()', $numGroups - $numVariables);
+            $routeMap[$numGroups + 1] = [$route->handler, $route->variables];
+
+            ++$numGroups;
+        }
+
+        $regex = '~^(?|' . implode('|', $regexes) . ')$~';
+        return ['regex' => $regex, 'routeMap' => $routeMap];
+    }
+}
+

+ 25 - 0
system/vendor/nikic/fast-route/src/DataGenerator/GroupPosBased.php

@@ -0,0 +1,25 @@
+<?php
+
+namespace FastRoute\DataGenerator;
+
+class GroupPosBased extends RegexBasedAbstract {
+    protected function getApproxChunkSize() {
+        return 10;
+    }
+
+    protected function processChunk($regexToRoutesMap) {
+        $routeMap = [];
+        $regexes = [];
+        $offset = 1;
+        foreach ($regexToRoutesMap as $regex => $route) {
+            $regexes[] = $regex;
+            $routeMap[$offset] = [$route->handler, $route->variables];
+
+            $offset += count($route->variables);
+        }
+
+        $regex = '~^(?:' . implode('|', $regexes) . ')$~';
+        return ['regex' => $regex, 'routeMap' => $routeMap];
+    }
+}
+

+ 25 - 0
system/vendor/nikic/fast-route/src/DataGenerator/MarkBased.php

@@ -0,0 +1,25 @@
+<?php
+
+namespace FastRoute\DataGenerator;
+
+class MarkBased extends RegexBasedAbstract {
+    protected function getApproxChunkSize() {
+        return 30;
+    }
+
+    protected function processChunk($regexToRoutesMap) {
+        $routeMap = [];
+        $regexes = [];
+        $markName = 'a';
+        foreach ($regexToRoutesMap as $regex => $route) {
+            $regexes[] = $regex . '(*MARK:' . $markName . ')';
+            $routeMap[$markName] = [$route->handler, $route->variables];
+
+            ++$markName;
+        }
+
+        $regex = '~^(?|' . implode('|', $regexes) . ')$~';
+        return ['regex' => $regex, 'routeMap' => $routeMap];
+    }
+}
+

+ 144 - 0
system/vendor/nikic/fast-route/src/DataGenerator/RegexBasedAbstract.php

@@ -0,0 +1,144 @@
+<?php
+
+namespace FastRoute\DataGenerator;
+
+use FastRoute\DataGenerator;
+use FastRoute\BadRouteException;
+use FastRoute\Route;
+
+abstract class RegexBasedAbstract implements DataGenerator {
+    protected $staticRoutes = [];
+    protected $methodToRegexToRoutesMap = [];
+
+    protected abstract function getApproxChunkSize();
+    protected abstract function processChunk($regexToRoutesMap);
+
+    public function addRoute($httpMethod, $routeData, $handler) {
+        if ($this->isStaticRoute($routeData)) {
+            $this->addStaticRoute($httpMethod, $routeData, $handler);
+        } else {
+            $this->addVariableRoute($httpMethod, $routeData, $handler);
+        }
+    }
+
+    public function getData() {
+        if (empty($this->methodToRegexToRoutesMap)) {
+            return [$this->staticRoutes, []];
+        }
+
+        return [$this->staticRoutes, $this->generateVariableRouteData()];
+    }
+
+    private function generateVariableRouteData() {
+        $data = [];
+        foreach ($this->methodToRegexToRoutesMap as $method => $regexToRoutesMap) {
+            $chunkSize = $this->computeChunkSize(count($regexToRoutesMap));
+            $chunks = array_chunk($regexToRoutesMap, $chunkSize, true);
+            $data[$method] =  array_map([$this, 'processChunk'], $chunks);
+        }
+        return $data;
+    }
+
+    private function computeChunkSize($count) {
+        $numParts = max(1, round($count / $this->getApproxChunkSize()));
+        return ceil($count / $numParts);
+    }
+
+    private function isStaticRoute($routeData) {
+        return count($routeData) === 1 && is_string($routeData[0]);
+    }
+
+    private function addStaticRoute($httpMethod, $routeData, $handler) {
+        $routeStr = $routeData[0];
+
+        if (isset($this->staticRoutes[$httpMethod][$routeStr])) {
+            throw new BadRouteException(sprintf(
+                'Cannot register two routes matching "%s" for method "%s"',
+                $routeStr, $httpMethod
+            ));
+        }
+
+        if (isset($this->methodToRegexToRoutesMap[$httpMethod])) {
+            foreach ($this->methodToRegexToRoutesMap[$httpMethod] as $route) {
+                if ($route->matches($routeStr)) {
+                    throw new BadRouteException(sprintf(
+                        'Static route "%s" is shadowed by previously defined variable route "%s" for method "%s"',
+                        $routeStr, $route->regex, $httpMethod
+                    ));
+                }
+            }
+        }
+
+        $this->staticRoutes[$httpMethod][$routeStr] = $handler;
+    }
+
+    private function addVariableRoute($httpMethod, $routeData, $handler) {
+        list($regex, $variables) = $this->buildRegexForRoute($routeData);
+
+        if (isset($this->methodToRegexToRoutesMap[$httpMethod][$regex])) {
+            throw new BadRouteException(sprintf(
+                'Cannot register two routes matching "%s" for method "%s"',
+                $regex, $httpMethod
+            ));
+        }
+
+        $this->methodToRegexToRoutesMap[$httpMethod][$regex] = new Route(
+            $httpMethod, $handler, $regex, $variables
+        );
+    }
+
+    private function buildRegexForRoute($routeData) {
+        $regex = '';
+        $variables = [];
+        foreach ($routeData as $part) {
+            if (is_string($part)) {
+                $regex .= preg_quote($part, '~');
+                continue;
+            }
+
+            list($varName, $regexPart) = $part;
+
+            if (isset($variables[$varName])) {
+                throw new BadRouteException(sprintf(
+                    'Cannot use the same placeholder "%s" twice', $varName
+                ));
+            }
+
+            if ($this->regexHasCapturingGroups($regexPart)) {
+                throw new BadRouteException(sprintf(
+                    'Regex "%s" for parameter "%s" contains a capturing group',
+                    $regexPart, $varName
+                ));
+            }
+
+            $variables[$varName] = $varName;
+            $regex .= '(' . $regexPart . ')';
+        }
+
+        return [$regex, $variables];
+    }
+
+    private function regexHasCapturingGroups($regex) {
+        if (false === strpos($regex, '(')) {
+            // Needs to have at least a ( to contain a capturing group
+            return false;
+        }
+
+        // Semi-accurate detection for capturing groups
+        return preg_match(
+            '~
+                (?:
+                    \(\?\(
+                  | \[ [^\]\\\\]* (?: \\\\ . [^\]\\\\]* )* \]
+                  | \\\\ .
+                ) (*SKIP)(*FAIL) |
+                \(
+                (?!
+                    \? (?! <(?![!=]) | P< | \' )
+                  | \*
+                )
+            ~x',
+            $regex
+        );
+    }
+}

+ 25 - 0
system/vendor/nikic/fast-route/src/Dispatcher.php

@@ -0,0 +1,25 @@
+<?php
+
+namespace FastRoute;
+
+interface Dispatcher {
+    const NOT_FOUND = 0;
+    const FOUND = 1;
+    const METHOD_NOT_ALLOWED = 2;
+
+    /**
+     * Dispatches against the provided HTTP method verb and URI.
+     *
+     * Returns array with one of the following formats:
+     *
+     *     [self::NOT_FOUND]
+     *     [self::METHOD_NOT_ALLOWED, ['GET', 'OTHER_ALLOWED_METHODS']]
+     *     [self::FOUND, $handler, ['varName' => 'value', ...]]
+     *
+     * @param string $httpMethod
+     * @param string $uri
+     *
+     * @return array
+     */
+    public function dispatch($httpMethod, $uri);
+}

+ 28 - 0
system/vendor/nikic/fast-route/src/Dispatcher/CharCountBased.php

@@ -0,0 +1,28 @@
+<?php
+
+namespace FastRoute\Dispatcher;
+
+class CharCountBased extends RegexBasedAbstract {
+    public function __construct($data) {
+        list($this->staticRouteMap, $this->variableRouteData) = $data;
+    }
+
+    protected function dispatchVariableRoute($routeData, $uri) {
+        foreach ($routeData as $data) {
+            if (!preg_match($data['regex'], $uri . $data['suffix'], $matches)) {
+                continue;
+            }
+
+            list($handler, $varNames) = $data['routeMap'][end($matches)];
+
+            $vars = [];
+            $i = 0;
+            foreach ($varNames as $varName) {
+                $vars[$varName] = $matches[++$i];
+            }
+            return [self::FOUND, $handler, $vars];
+        }
+
+        return [self::NOT_FOUND];
+    }
+}

+ 28 - 0
system/vendor/nikic/fast-route/src/Dispatcher/GroupCountBased.php

@@ -0,0 +1,28 @@
+<?php
+
+namespace FastRoute\Dispatcher;
+
+class GroupCountBased extends RegexBasedAbstract {
+    public function __construct($data) {
+        list($this->staticRouteMap, $this->variableRouteData) = $data;
+    }
+
+    protected function dispatchVariableRoute($routeData, $uri) {
+        foreach ($routeData as $data) {
+            if (!preg_match($data['regex'], $uri, $matches)) {
+                continue;
+            }
+
+            list($handler, $varNames) = $data['routeMap'][count($matches)];
+
+            $vars = [];
+            $i = 0;
+            foreach ($varNames as $varName) {
+                $vars[$varName] = $matches[++$i];
+            }
+            return [self::FOUND, $handler, $vars];
+        }
+
+        return [self::NOT_FOUND];
+    }
+}

+ 30 - 0
system/vendor/nikic/fast-route/src/Dispatcher/GroupPosBased.php

@@ -0,0 +1,30 @@
+<?php
+
+namespace FastRoute\Dispatcher;
+
+class GroupPosBased extends RegexBasedAbstract {
+    public function __construct($data) {
+        list($this->staticRouteMap, $this->variableRouteData) = $data;
+    }
+
+    protected function dispatchVariableRoute($routeData, $uri) {
+        foreach ($routeData as $data) {
+            if (!preg_match($data['regex'], $uri, $matches)) {
+                continue;
+            }
+
+            // find first non-empty match
+            for ($i = 1; '' === $matches[$i]; ++$i);
+
+            list($handler, $varNames) = $data['routeMap'][$i];
+
+            $vars = [];
+            foreach ($varNames as $varName) {
+                $vars[$varName] = $matches[$i++];
+            }
+            return [self::FOUND, $handler, $vars];
+        }
+
+        return [self::NOT_FOUND];
+    }
+}

이 변경점에서 너무 많은 파일들이 변경되어 몇몇 파일들은 표시되지 않았습니다.