1
0
mirror of https://github.com/typemill/typemill.git synced 2025-08-06 06:07:31 +02:00

finished TOC feature

This commit is contained in:
Sebastian
2017-11-29 21:51:47 +01:00
parent 4bea02cb16
commit 7da2060cae
30 changed files with 605 additions and 276 deletions

14
composer.lock generated
View File

@@ -422,16 +422,16 @@
},
{
"name": "slim/slim",
"version": "3.9.0",
"version": "3.9.2",
"source": {
"type": "git",
"url": "https://github.com/slimphp/Slim.git",
"reference": "575a8b53a0a489447915029c69680156cd355304"
"reference": "4086d0106cf5a7135c69fce4161fe355a8feb118"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/slimphp/Slim/zipball/575a8b53a0a489447915029c69680156cd355304",
"reference": "575a8b53a0a489447915029c69680156cd355304",
"url": "https://api.github.com/repos/slimphp/Slim/zipball/4086d0106cf5a7135c69fce4161fe355a8feb118",
"reference": "4086d0106cf5a7135c69fce4161fe355a8feb118",
"shasum": ""
},
"require": {
@@ -489,7 +489,7 @@
"micro",
"router"
],
"time": "2017-11-04T08:46:46+00:00"
"time": "2017-11-26T19:13:09+00:00"
},
{
"name": "slim/twig-view",
@@ -543,7 +543,7 @@
},
{
"name": "symfony/event-dispatcher",
"version": "v3.3.12",
"version": "v3.3.13",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher.git",
@@ -606,7 +606,7 @@
},
{
"name": "symfony/yaml",
"version": "v2.8.30",
"version": "v2.8.31",
"source": {
"type": "git",
"url": "https://github.com/symfony/yaml.git",

View File

@@ -11,7 +11,7 @@ You will find all themes in the `theme` folder of TYPEMILL. Change the theme in
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.
- `404.twig`: This is the template for a not found message.
There is another optional template:

View File

@@ -2,6 +2,12 @@
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.
## Table of Contents
You can create a table of contents with the [TOC] tag written in a separate line. The TOC-Tag will be replaced with a link-list to all headlines of the page.
[TOC]
## Inline Elements
This is an ordinary paragraph containing only simple text.

View File

@@ -0,0 +1,5 @@
# Übermaß: A simple encoding test
This is just a test for character encoding. If you see the correct german word "Übermaß" in the left navigation, and if you can click the navigation point to get to this page, then everything works fine.
I still encourage you to use only english characters to name your content files, because many special characters and many languages won't work. I even doubt, that german or european characters will work in special server environments. So you can try it, but if it does not work, you only option is to avoid special characters in your file-names.

59
system/Assets.php Normal file
View File

@@ -0,0 +1,59 @@
<?php
namespace Typemill;
class Assets
{
protected $baseUrl;
public function __construct($baseUrl)
{
$this->baseUrl = $baseUrl;
$this->JS = array();
$this->CSS = array();
$this->inlineJS = array();
$this->inlineCSS = array();
}
public function addCSS(string $CSS)
{
$CSSpath = __DIR__ . '/../plugins' . $CSS;
if(file_exists($CSSfile))
{
$CSSfile = $this->baseUrl . '/plugins' . $CSS;
$this->CSS[] = '<link rel="stylesheet" href="' . $CSSfile . '" />';
}
}
public function addInlineCSS($CSS)
{
$this->inlineCSS[] = '<style>' . $CSS . '</style>';
}
public function addJS(string $JS)
{
$JSpath = __DIR__ . '/../plugins' . $JS;
if(file_exists($JSpath))
{
$JSfile = $this->baseUrl . '/plugins' . $JS;
$this->JS[] = '<script src="' . $JSfile . '"></script>';
}
}
public function addInlineJS($JS)
{
$this->inlineJS[] = '<script>' . $JS . '</script>';
}
public function renderCSS()
{
return implode('<br/>', $this->CSS) . implode('<br/>', $this->inlineCSS);
}
public function renderJS()
{
return implode('<br/>', $this->JS) . implode('<br/>', $this->inlineJS);
}
}

View File

@@ -4,7 +4,7 @@ namespace Typemill\Controllers;
/* Use the slim-container */
use Interop\Container\ContainerInterface;
use Typemill\Events\RenderSiteEvent;
use Typemill\Events\RenderPageEvent;
abstract class Controller
{
@@ -17,7 +17,7 @@ abstract class Controller
protected function render($response, $route, $data)
{
$data = $this->c->dispatcher->dispatch('beforeRenderSite', new RenderSiteEvent($data))->getData();
$data = $this->c->dispatcher->dispatch('onPageRendered', new RenderPageEvent($data))->getData();
return $this->c->view->render($response, $route, $data);
}

View File

@@ -9,9 +9,10 @@ use Typemill\Models\WriteYaml;
use \Symfony\Component\Yaml\Yaml;
use Typemill\Models\VersionCheck;
use Typemill\Models\Helpers;
use Typemill\Events\LoadStructureEvent;
use Typemill\Events\LoadPagetreeEvent;
use Typemill\Events\LoadMarkdownEvent;
use Typemill\Events\ParseHtmlEvent;
use Typemill\Extensions\ParsedownExtension;
class PageController extends Controller
{
@@ -63,7 +64,7 @@ class PageController extends Controller
}
/* dispatch event and let others manipulate the structure */
$structure = $this->c->dispatcher->dispatch('onStructureLoaded', new LoadStructureEvent($structure))->getData();
$structure = $this->c->dispatcher->dispatch('onPagetreeLoaded', new LoadPagetreeEvent($structure))->getData();
}
catch (Exception $e)
{
@@ -122,7 +123,8 @@ class PageController extends Controller
$contentMD = $this->c->dispatcher->dispatch('onMarkdownLoaded', new LoadMarkdownEvent($contentMD))->getData();
/* initialize parsedown */
$Parsedown = new \ParsedownExtra();
// $Parsedown = new \ParsedownExtra();
$Parsedown = new ParsedownExtension();
/* parse markdown-file to html-string */
$contentHTML = $Parsedown->text($contentMD);
@@ -141,7 +143,7 @@ class PageController extends Controller
*/
$route = empty($args) && $settings['startpage'] ? '/cover.twig' : '/index.twig';
$this->render($response, $route, array('navigation' => $structure, 'content' => $contentHTML, 'item' => $item, 'breadcrumb' => $breadcrumb, 'settings' => $settings, 'title' => $title, 'description' => $description, 'base_url' => $base_url ));
}

View File

@@ -8,7 +8,7 @@ use Symfony\Component\EventDispatcher\Event;
* Event for the folder structure.
*/
class LoadStructureEvent extends Event
class LoadPagetreeEvent extends Event
{
protected $data;

View File

@@ -8,7 +8,7 @@ use Symfony\Component\EventDispatcher\Event;
* Event for the pure content.
*/
class RenderSiteEvent extends Event
class RenderPageEvent extends Event
{
protected $data;

View File

@@ -0,0 +1,149 @@
<?php
namespace Typemill\Extensions;
class ParsedownExtension extends \ParsedownExtra
{
function __construct()
{
parent::__construct();
array_unshift($this->BlockTypes['['], 'TableOfContents');
}
function text($text)
{
# make sure no definitions are set
$this->DefinitionData = array();
# standardize line breaks
$text = str_replace(array("\r\n", "\r"), "\n", $text);
# remove surrounding line breaks
$text = trim($text, "\n");
# split text into lines
$lines = explode("\n", $text);
# iterate through lines to identify blocks
$markup = $this->lines($lines);
# trim line breaks
$markup = trim($markup, "\n");
if (isset($this->DefinitionData['TableOfContents']))
{
$TOC = $this->buildTOC($this->headlines);
$markup = preg_replace('%(<p[^>]*>\[TOC\]</p>)%i', $TOC, $markup);
}
# merge consecutive dl elements
$markup = preg_replace('/<\/dl>\s+<dl>\s+/', '', $markup);
# add footnotes
if (isset($this->DefinitionData['Footnote']))
{
$Element = $this->buildFootnoteElement();
$markup .= "\n" . $this->element($Element);
}
return $markup;
}
# TableOfContents
protected function blockTableOfContents($line, $block)
{
if ($line['text'] == '[TOC]')
{
$this->DefinitionData['TableOfContents'] = true;
}
}
#
# Header
private $headlines = array();
private $headlinesCount = 0;
protected function blockHeader($Line)
{
if (isset($Line['text'][1]))
{
$level = 1;
while (isset($Line['text'][$level]) and $Line['text'][$level] === '#')
{
$level ++;
}
if ($level > 6)
{
return;
}
$text = trim($Line['text'], '# ');
$this->headlinesCount++;
$Block = array(
'element' => array(
'name' => 'h' . min(6, $level),
'text' => $text,
'handler' => 'line',
'attributes' => array(
'id' => "headline-$this->headlinesCount"
)
)
);
$this->headlines[] = array('level' => $level, 'name' => $Block['element']['name'], 'attribute' => $Block['element']['attributes']['id'], 'text' => $text);
return $Block;
}
}
# build the markup for table of contents
protected function buildTOC($headlines)
{
$markup = '<ul class="TOC">';
foreach($headlines as $key => $headline)
{
$thisLevel = $headline['level'];
$prevLevel = $key > 0 ? $headlines[$key-1]['level'] : 1;
$nextLevel = isset($headlines[$key+1]) ? $headlines[$key+1]['level'] : 0;
if($thisLevel > $prevLevel)
{
$markup .= '<ul>';
}
$markup .= '<li class="' . $headline['name'] . '"><a href="#' . $headline['attribute'] . '">' . $headline['text'] . '</a>';
if($thisLevel == $nextLevel)
{
$markup .= '</li>';
}
elseif($thisLevel > $nextLevel)
{
while($thisLevel > $nextLevel)
{
$markup .= '</li></ul>';
$thisLevel--;
}
}
}
$markup .= '</ul>';
return $markup;
}
}

View File

@@ -59,9 +59,9 @@ class 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->name = iconv(mb_detect_encoding($item->name, mb_detect_order(), true), "UTF-8", $item->name);
$item->slug = implode("-",$nameParts);
$item->slug = URLify::filter(iconv('ISO-8859-15', 'UTF-8', $item->slug));
$item->slug = URLify::filter(iconv(mb_detect_encoding($item->slug, mb_detect_order(), true), "UTF-8", $item->slug));
$item->path = $fullPath . DIRECTORY_SEPARATOR . $key;
$item->urlRelWoF = $fullSlugWithoutFolder . '/' . $item->slug;
$item->urlRel = $fullSlugWithFolder . '/' . $item->slug;
@@ -85,9 +85,9 @@ class Folder
$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->name = iconv(mb_detect_encoding($item->name, mb_detect_order(), true), "UTF-8", $item->name);
$item->slug = implode("-",$nameParts);
$item->slug = URLify::filter(iconv('ISO-8859-15', 'UTF-8', $item->slug));
$item->slug = URLify::filter(iconv(mb_detect_encoding($item->slug, mb_detect_order(), true), "UTF-8", $item->slug));
$item->path = $fullPath . DIRECTORY_SEPARATOR . $name;
$item->key = $iteration;
$item->keyPath = $keyPath . '.' . $iteration;

View File

@@ -7,9 +7,9 @@ use \Symfony\Component\EventDispatcher\EventSubscriberInterface;
abstract class Plugin implements EventSubscriberInterface
{
protected $app;
private $app;
protected $container;
private $container;
/**
* Constructor.
@@ -28,16 +28,51 @@ abstract class Plugin implements EventSubscriberInterface
{
return $this->container['request']->getUri();
}
protected function getPath()
{
$route = $this->container['request']->getUri();
return $route->getPath();
return $this->container['request']->getUri()->getPath();
}
protected function getDispatcher($dispatcher)
protected function getDispatcher()
{
return $dispatcher;
return $this->$dispatcher;
}
}
protected function addTwigGlobal($name, $class)
{
$this->container->view->getEnvironment()->addGlobal($name, $class);
}
protected function addTwigFilter($name, $filter)
{
$filter = new \Twig_SimpleFilter($name, $filter);
$this->container->view->getEnvironment()->addFilter($filter);
}
protected function addTwigFunction($name, $function)
{
$function = new \Twig_SimpleFunction($name, $function);
$this->container->view->getEnvironment()->addFunction($function);
}
protected function addJS($JS)
{
$this->container->assets->addJS($JS);
}
protected function addInlineJS($JS)
{
$this->container->assets->addInlineJS($JS);
}
protected function addCSS($CSS)
{
$this->container->assets->addCSS($CSS);
}
protected function addInlineCSS($CSS)
{
$this->container->assets->addInlineCSS($CSS);
}
}

View File

@@ -39,16 +39,18 @@ class Plugins
/* if they are properly formatted, add them to routes array */
foreach($pluginRoutes as $pluginRoute)
{
if($this->checkRouteArray($pluginRoute))
if($this->checkRouteArray($routes,$pluginRoute))
{
$pluginRoute['route'] = strtolower($pluginRoute['route']);
$routes[] = $pluginRoute;
}
}
}
elseif(is_array($routes))
{
if($this->checkRouteArray($pluginRoutes))
if($this->checkRouteArray($routes,$pluginRoutes))
{
$pluginRoutes['route'] = strtolower($pluginRoutes['route']);
$routes[] = $pluginRoutes;
}
}
@@ -66,18 +68,31 @@ class Plugins
}
}
private function checkRouteArray($route)
private function checkRouteArray($routes,$route)
{
if(
isset($route['httpMethod']) AND in_array($route['httpMethod'], array('get','post','put','delete','head','patch','options'))
AND isset($route['route']) AND is_string($route['route'])
AND isset($route['class']) AND is_string($route['class']))
AND isset($route['class']) AND is_string($route['class'])
AND !$this->in_array_r(strtolower($route['route']),$routes))
{
return true;
}
return false;
}
private function in_array_r($needle, $haystack, $strict = false)
{
foreach ($haystack as $item)
{
if (($strict ? $item === $needle : $item == $needle) || (is_array($item) && $this->in_array_r($needle, $item, $strict)))
{
return true;
}
}
return false;
}
private function scanPluginFolder()
{
$pluginsDir = __DIR__ . '/../plugins';

View File

@@ -27,33 +27,6 @@ $app = new \Slim\App($settings);
$container = $app->getContainer();
/************************
* LOAD TWIG VIEW *
************************/
$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();
};
/****************************
* CREATE EVENT DISPATCHER *
****************************/
@@ -71,18 +44,69 @@ $routes = $middleware = array();
foreach($pluginClassNames as $pluginClassName)
{
$routes = $plugins->getNewRoutes($pluginClassName, $routes);
$middleware[] = $plugins->getNewMiddleware($pluginClassName);
$middleware = $plugins->getNewMiddleware($pluginClassName, $middleware);
$dispatcher->addSubscriber(new $pluginClassName($container, $app));
}
$dispatcher->dispatch('onPluginsInitialized');
/******************************
* ADD DISPATCHER TO CONTAINER *
******************************/
$container['dispatcher'] = function($container) use ($dispatcher)
{
return $dispatcher;
};
/******************************
* ADD FLASH MESSAGES FOR TIWG *
******************************/
$container['flash'] = function ()
{
return new \Slim\Flash\Messages();
};
/********************************
* ADD ASSET-FUNCTION FOR TWIG *
********************************/
$container['assets'] = function($c)
{
return new \Typemill\Assets($c['request']->getUri()->getBaseUrl());
};
/************************
* LOAD TWIG VIEW *
************************/
$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));
$view['baseUrl'] = $container['request']->getUri()->getBaseUrl();
/* add flash messages to all views */
$view->getEnvironment()->addGlobal('flash', $container->flash);
/* add asset-function to all views */
$view->getEnvironment()->addGlobal('assets', $container->assets);
return $view;
};
$container->dispatcher->dispatch('onTwigLoaded');
/************************
* ADD MIDDLEWARE *
************************/
@@ -96,7 +120,5 @@ $container['notFoundHandler'] = function($c)
* ADD ROUTES *
************************/
$timer['before router']=microtime(true);
require __DIR__ . '/Routes/api.php';
require __DIR__ . '/Routes/web.php';
require __DIR__ . '/Routes/web.php';

View File

@@ -232,79 +232,6 @@
"dependency injection"
]
},
{
"name": "slim/slim",
"version": "3.9.0",
"version_normalized": "3.9.0.0",
"source": {
"type": "git",
"url": "https://github.com/slimphp/Slim.git",
"reference": "575a8b53a0a489447915029c69680156cd355304"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/slimphp/Slim/zipball/575a8b53a0a489447915029c69680156cd355304",
"reference": "575a8b53a0a489447915029c69680156cd355304",
"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-11-04T08:46:46+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": "twig/twig",
"version": "v1.35.0",
@@ -372,57 +299,6 @@
"templating"
]
},
{
"name": "symfony/yaml",
"version": "v2.8.30",
"version_normalized": "2.8.30.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/yaml.git",
"reference": "d819bf267e901727141fe828ae888486fd21236e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/yaml/zipball/d819bf267e901727141fe828ae888486fd21236e",
"reference": "d819bf267e901727141fe828ae888486fd21236e",
"shasum": ""
},
"require": {
"php": ">=5.3.9"
},
"time": "2017-11-05T15:25:56+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"
},
{
"name": "slim/twig-view",
"version": "2.3.0",
@@ -674,10 +550,134 @@
"parser"
]
},
{
"name": "slim/slim",
"version": "3.9.2",
"version_normalized": "3.9.2.0",
"source": {
"type": "git",
"url": "https://github.com/slimphp/Slim.git",
"reference": "4086d0106cf5a7135c69fce4161fe355a8feb118"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/slimphp/Slim/zipball/4086d0106cf5a7135c69fce4161fe355a8feb118",
"reference": "4086d0106cf5a7135c69fce4161fe355a8feb118",
"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-11-26T19:13:09+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": "symfony/yaml",
"version": "v2.8.31",
"version_normalized": "2.8.31.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/yaml.git",
"reference": "d819bf267e901727141fe828ae888486fd21236e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/yaml/zipball/d819bf267e901727141fe828ae888486fd21236e",
"reference": "d819bf267e901727141fe828ae888486fd21236e",
"shasum": ""
},
"require": {
"php": ">=5.3.9"
},
"time": "2017-11-05T15:25:56+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"
},
{
"name": "symfony/event-dispatcher",
"version": "v3.3.12",
"version_normalized": "3.3.12.0",
"version": "v3.3.13",
"version_normalized": "3.3.13.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher.git",

View File

@@ -52,7 +52,7 @@ class App
*
* @var string
*/
const VERSION = '3.9.0';
const VERSION = '3.9.2';
/**
* Container
@@ -292,11 +292,29 @@ class App
$response = $this->container->get('response');
try {
ob_start();
$response = $this->process($this->container->get('request'), $response);
} catch (InvalidMethodException $e) {
$response = $this->processInvalidMethod($e->getRequest(), $response);
} finally {
$output = ob_get_clean();
}
if (!empty($output) && $response->getBody()->isWritable()) {
$outputBuffering = $this->container->get('settings')['outputBuffering'];
if ($outputBuffering === 'prepend') {
// prepend output buffer content
$body = new Http\Body(fopen('php://temp', 'r+'));
$body->write($output . $response->getBody());
$response = $response->withBody($body);
} elseif ($outputBuffering === 'append') {
// append output buffer content
$response->getBody()->write($output);
}
}
$response = $this->finalize($response);
if (!$silent) {
$this->respond($response);
}
@@ -374,13 +392,11 @@ class App
$response = $this->handlePhpError($e, $request, $response);
}
$response = $this->finalize($response);
return $response;
}
/**
* Send the response the client
* Send the response to the client
*
* @param ResponseInterface $response
*/

View File

@@ -153,8 +153,7 @@ class DefaultServicesProvider
*/
$container['errorHandler'] = function ($container) {
return new Error(
$container->get('settings')['displayErrorDetails'],
$container->get('settings')['outputBuffering']
$container->get('settings')['displayErrorDetails']
);
};
}

View File

@@ -4,7 +4,7 @@
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2017 Josh Lockhart
* @license https://github.com/slimphp/Slim/blob/3.x/LICENSE (MIT License)
* @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
*/
namespace Slim\Exception;

View File

@@ -4,7 +4,7 @@
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2017 Josh Lockhart
* @license https://github.com/slimphp/Slim/blob/3.x/LICENSE (MIT License)
* @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
*/
namespace Slim\Exception;

View File

@@ -1,5 +1,11 @@
<?php
/**
* Slim Framework (https://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2017 Josh Lockhart
* @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
*/
namespace Slim\Exception;
use Psr\Http\Message\ServerRequestInterface;

View File

@@ -4,7 +4,7 @@
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2017 Josh Lockhart
* @license https://github.com/slimphp/Slim/blob/3.x/LICENSE (MIT License)
* @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
*/
namespace Slim\Exception;

View File

@@ -4,7 +4,7 @@
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2017 Josh Lockhart
* @license https://github.com/slimphp/Slim/blob/3.x/LICENSE (MIT License)
* @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
*/
namespace Slim\Exception;

View File

@@ -18,20 +18,14 @@ abstract class AbstractError extends AbstractHandler
*/
protected $displayErrorDetails;
/**
* @var bool|string
*/
protected $outputBuffering;
/**
* Constructor
*
* @param bool $displayErrorDetails Set to true to display full details
*/
public function __construct($displayErrorDetails = false, $outputBuffering = false)
public function __construct($displayErrorDetails = false)
{
$this->displayErrorDetails = (bool) $displayErrorDetails;
$this->outputBuffering = $outputBuffering;
}
/**

View File

@@ -55,19 +55,7 @@ class Error extends AbstractError
$this->writeToErrorLog($exception);
$body = new Body(fopen('php://temp', 'r+'));
if ($this->outputBuffering === 'prepend') {
// prepend output buffer content
$body->write(ob_get_clean() . $output);
} elseif ($this->outputBuffering === 'append') {
// append output buffer content
$body->write($output . ob_get_clean());
} else {
// outputBuffering is false or some other unknown setting
// delete anything in the output buffer.
ob_get_clean();
$body->write($output);
}
$body->write($output);
return $response
->withStatus(500)

View File

@@ -249,6 +249,34 @@ class Response extends Message implements ResponseInterface
return '';
}
/*******************************************************************************
* Headers
******************************************************************************/
/**
* Return an instance with the provided value replacing the specified header.
*
* If a Location header is set and the status code is 200, then set the status
* code to 302 to mimic what PHP does. See https://github.com/slimphp/Slim/issues/1730
*
* @param string $name Case-insensitive header field name.
* @param string|string[] $value Header value(s).
* @return static
* @throws \InvalidArgumentException for invalid header names or values.
*/
public function withHeader($name, $value)
{
$clone = clone $this;
$clone->headers->set($name, $value);
if ($clone->getStatusCode() === 200 && strtolower($name) === 'location') {
$clone = $clone->withStatus(302);
}
return $clone;
}
/*******************************************************************************
* Body
******************************************************************************/

View File

@@ -381,6 +381,8 @@ class Uri implements UriInterface
$clone->user = $this->filterUserInfo($user);
if ($clone->user) {
$clone->password = $password ? $this->filterUserInfo($password) : '';
} else {
$clone->password = '';
}
return $clone;

View File

@@ -8,12 +8,9 @@
*/
namespace Slim;
use Exception;
use Throwable;
use InvalidArgumentException;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\ResponseInterface;
use Slim\Exception\SlimException;
use Slim\Handlers\Strategies\RequestResponse;
use Slim\Interfaces\InvocationStrategyInterface;
use Slim\Interfaces\RouteInterface;
@@ -335,22 +332,7 @@ class Route extends Routable implements RouteInterface
/** @var InvocationStrategyInterface $handler */
$handler = isset($this->container) ? $this->container->get('foundHandler') : new RequestResponse();
// invoke route callable
if ($this->outputBuffering === false) {
$newResponse = $handler($this->callable, $request, $response, $this->arguments);
} else {
try {
ob_start();
$newResponse = $handler($this->callable, $request, $response, $this->arguments);
$output = ob_get_clean();
// @codeCoverageIgnoreStart
} catch (Throwable $e) {
throw $e;
// @codeCoverageIgnoreEnd
} catch (Exception $e) {
throw $e;
}
}
$newResponse = $handler($this->callable, $request, $response, $this->arguments);
if ($newResponse instanceof ResponseInterface) {
// if route callback returns a ResponseInterface, then use it
@@ -362,18 +344,6 @@ class Route extends Routable implements RouteInterface
}
}
if (!empty($output) && $response->getBody()->isWritable()) {
if ($this->outputBuffering === 'prepend') {
// prepend output buffer content
$body = new Http\Body(fopen('php://temp', 'r+'));
$body->write($output . $response->getBody());
$response = $response->withBody($body);
} elseif ($this->outputBuffering === 'append') {
// append output buffer content
$response->getBody()->write($output);
}
}
return $response;
}
}

View File

@@ -426,6 +426,26 @@ cite{}
abbr{}
hr{}
ul.TOC,.TOC ul{
list-style: none;
padding-left: 0px;
margin-left: 0px;
}
ul.TOC{
background: #f9f8f6;
width: 100%;
padding: 20px;
box-sizing:border-box;
}
li.h1{
font-weight: 700;
}
li.h2, li.h3, li.h4, li.h5, li.h6
{
font-weight: 400;
padding-left: 25px;
}
/************************
* GitHub Ribbon *
************************/

View File

@@ -17,10 +17,15 @@
<link rel="icon" type="image/png" href="{{ base_url }}/themes/typemill/img/favicon-32x32.png" sizes="32x32" />
<link rel="icon" type="image/png" href="{{ base_url }}/themes/typemill/img/favicon-16x16.png" sizes="16x16" />
<link rel="stylesheet" href="{{ base_url }}/themes/typemill/css/fontello/css/fontello.css" />
<link rel="stylesheet" href="{{ base_url }}/themes/typemill/css/normalize.css" />
<link rel="stylesheet" href="{{ base_url }}/themes/typemill/js/highlight/styles/default.css" />
<link rel="stylesheet" href="{{ base_url }}/themes/typemill/css/style.css" />
{% block stylesheets %}
<link rel="stylesheet" href="{{ base_url }}/themes/typemill/css/fontello/css/fontello.css" />
<link rel="stylesheet" href="{{ base_url }}/themes/typemill/css/normalize.css" />
<link rel="stylesheet" href="{{ base_url }}/themes/typemill/js/highlight/styles/default.css" />
<link rel="stylesheet" href="{{ base_url }}/themes/typemill/css/style.css" />
{{ assets.renderCSS() }}
{% endblock %}
</head>
<body>
<div class="main">
@@ -29,6 +34,7 @@
</header>
<article>
{% block content %}{% endblock %}
<small>{{content|rot13}}</small>
</article>
<aside id="navigation" class="close">
<nav>
@@ -36,30 +42,37 @@
</nav>
</aside>
<footer>
<p>hello {{ myName() }}</p>
{% include 'partials/footer.twig' %}
</footer>
</div>
<script src="{{ base_url }}/themes/typemill/js/highlight/highlight.pack.js"></script>
<script>hljs.initHighlightingOnLoad();</script>
<script>
var menu = document.getElementById("menu"),
navi = document.getElementById("navigation");
{% block javascripts %}
<script src="{{ base_url }}/themes/typemill/js/highlight/highlight.pack.js"></script>
<script>hljs.initHighlightingOnLoad();</script>
<script>
var menu = document.getElementById("menu"),
navi = document.getElementById("navigation");
if(menu)
{
menu.addEventListener("click", function(){
if(navi.className == "close")
{
navi.className = "open";
menu.className = "active";
}
else
{
navi.className = "close";
menu.className = "";
}
});
}
</script>
if(menu)
{
menu.addEventListener("click", function(){
if(navi.className == "close")
{
navi.className = "open";
menu.className = "active";
}
else
{
navi.className = "close";
menu.className = "";
}
});
}
</script>
{{ assets.renderJS() }}
{% endblock %}
</body>
</html>

Binary file not shown.