mirror of
https://github.com/typemill/typemill.git
synced 2025-08-04 13:17:29 +02:00
Version 1.0.1
This commit is contained in:
7
.gitignore
vendored
7
.gitignore
vendored
@@ -1,4 +1,7 @@
|
||||
cache/structure.txt
|
||||
cache/request.txt
|
||||
cache/sitemap.txt
|
||||
cache/lastCache.txt
|
||||
cache/lastSitemap.txt
|
||||
settings/settings.yaml
|
||||
typemill.zip
|
||||
typemill.zip
|
||||
typemill-1.0.1.zip
|
@@ -13,6 +13,8 @@ RewriteRule ^(system) - [F,L]
|
||||
RewriteRule ^(content) - [F,L]
|
||||
RewriteRule ^(.*)?\.yml$ - [F,L]
|
||||
Rewriterule ^(.*)?\.yaml$ - [F,L]
|
||||
RewriteRule ^(.*)?\.txt$ - [F,L]
|
||||
RewriteRule ^(.*)?\.example$ - [F,L]
|
||||
RewriteRule ^(.*/)?\.git+ - [F,L]
|
||||
|
||||
# Use this to redirect www to non-wwww on apache servers
|
||||
|
5
content/1_getting-started/03-update.md
Normal file
5
content/1_getting-started/03-update.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# Update
|
||||
|
||||
If your version of TYPEMILL is not up to date, you will find an update notice in your footer.
|
||||
|
||||
To update your TYPEMILL version, simply download the latest version of TYPEMILL on . Then delete the old `system` folder on your server and upload the new system folder. Sometimes it is a good idea to delete the content in the cache folder too.
|
3
content/2_for-writers/20-google-sitemap.md
Normal file
3
content/2_for-writers/20-google-sitemap.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Google Sitemap
|
||||
|
||||
As of version 1.0.1, TYPEMILL creates a google sitemap in the cache folder. You can reach the sitemap with the url `http:yourwebsite.net/cache/sitemap.xml` and add the sitemap to the google search console. The sitemap will update once a day. You can also trigger a manual update with a refresh of your browser (F5).
|
@@ -2,6 +2,12 @@
|
||||
|
||||
This is the version history with some release notes.
|
||||
|
||||
## Version 1.0.1 (01.05.2017)
|
||||
|
||||
- Bugfix: Index file in the content folder won't break the building of the navigation tree anymore.
|
||||
- New Feature: Added a google sitemap.xml in the cache folder.
|
||||
- New Feature: Added a version check, an update message can be displayed in theme now.
|
||||
|
||||
## Version 1.0.0 (13.04.2017)
|
||||
The first alpha version of typemill with all basic features for a simple website:
|
||||
|
||||
|
@@ -2,5 +2,5 @@ title: MyWebsite
|
||||
author: 'Your Name'
|
||||
copyright: ©
|
||||
year: '2017'
|
||||
theme: robodoc
|
||||
theme: typemill
|
||||
startpage: true
|
@@ -3,12 +3,15 @@
|
||||
namespace System\Controllers;
|
||||
|
||||
use System\Models\Folder;
|
||||
use System\Models\Cache;
|
||||
use System\Models\WriteCache;
|
||||
use System\Models\WriteSitemap;
|
||||
use System\Models\WriteYaml;
|
||||
use \Symfony\Component\Yaml\Yaml;
|
||||
use System\Models\VersionCheck;
|
||||
use System\Models\Helpers;
|
||||
|
||||
class PageController extends Controller
|
||||
{
|
||||
|
||||
public function index($request, $response, $args)
|
||||
{
|
||||
|
||||
@@ -20,30 +23,54 @@ class PageController extends Controller
|
||||
$description = '';
|
||||
$settings = $this->c->get('settings');
|
||||
$pathToContent = $settings['rootPath'] . $settings['contentFolder'];
|
||||
$cache = new Cache();
|
||||
$cache = new WriteCache();
|
||||
$uri = $request->getUri();
|
||||
$base_url = $uri->getBaseUrl();
|
||||
|
||||
if($cache->validate())
|
||||
|
||||
try
|
||||
{
|
||||
$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($cache->validate('cache', 'lastCache.txt',600))
|
||||
{
|
||||
$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 ]);
|
||||
}
|
||||
elseif(!$cache->validate('cache', 'lastSitemap.txt', 86400))
|
||||
{
|
||||
/* update sitemap */
|
||||
$sitemap = new WriteSitemap();
|
||||
$sitemap->updateSitemap('cache', 'sitemap.xml', 'lastSitemap.txt', $structure, $uri->getBaseUrl());
|
||||
|
||||
$version = new VersionCheck();
|
||||
$latestVersion = $version->checkVersion($uri->getBaseUrl());
|
||||
if($latestVersion)
|
||||
{
|
||||
$yaml = new WriteYaml();
|
||||
$yamlContent = $yaml->getYaml('settings', 'settings.yaml');
|
||||
$yamlContent['latestVersion'] = $latestVersion;
|
||||
$yaml->updateYaml('settings', 'settings.yaml', $yamlContent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
catch (Exception $e)
|
||||
{
|
||||
echo $e->getMessage();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
@@ -100,13 +127,11 @@ class PageController extends Controller
|
||||
|
||||
$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');
|
||||
return $cache->getCache('cache', 'structure.txt');
|
||||
}
|
||||
|
||||
|
||||
protected function getFreshStructure($pathToContent, $cache, $uri)
|
||||
{
|
||||
@@ -120,13 +145,13 @@ class PageController extends Controller
|
||||
}
|
||||
|
||||
/* create an array of object with the whole content of the folder */
|
||||
$structure = Folder::getFolderContentDetails($structure, $uri->getBaseUrl(), $uri->getBasePath());
|
||||
|
||||
$structure = Folder::getFolderContentDetails($structure, $uri->getBaseUrl(), $uri->getBasePath());
|
||||
|
||||
/* cache navigation */
|
||||
$cache->refresh($structure, 'structure');
|
||||
$cache->updateCache('cache', 'structure.txt', 'lastCache.txt', $structure);
|
||||
|
||||
return $structure;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
@@ -1,81 +0,0 @@
|
||||
<?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);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
@@ -40,16 +40,16 @@ class Folder
|
||||
* 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)
|
||||
{
|
||||
public static function getFolderContentDetails(array $folderContent, $baseUrl, $fullSlugWithFolder = NULL, $fullSlugWithoutFolder = 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);
|
||||
@@ -63,21 +63,22 @@ class Folder
|
||||
$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->urlRelWoF = $fullSlugWithoutFolder . '/' . $item->slug;
|
||||
$item->urlRel = $fullSlugWithFolder . '/' . $item->slug;
|
||||
$item->urlAbs = $baseUrl . $fullSlugWithoutFolder . '/' . $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);
|
||||
$item->folderContent = self::getFolderContentDetails($name, $baseUrl, $item->urlRel, $item->urlRelWoF, $item->path, $item->keyPath, $item->chapter);
|
||||
}
|
||||
else
|
||||
{
|
||||
$nameParts = self::getStringParts($name);
|
||||
$fileType = array_pop($nameParts);
|
||||
|
||||
if($name == 'index.md' || $fileType !== 'md' ) break;
|
||||
if($name == 'index.md' || $fileType !== 'md' ) continue;
|
||||
|
||||
$item->originalName = $name;
|
||||
$item->elementType = 'file';
|
||||
@@ -92,8 +93,9 @@ class Folder
|
||||
$item->keyPath = $keyPath . '.' . $iteration;
|
||||
$item->keyPathArray = explode('.',$item->keyPath);
|
||||
$item->chapter = $chapter . '.' . $chapternr;
|
||||
$item->urlRel = $fullSlug . '/' . $item->slug;
|
||||
$item->urlAbs = $baseUrl . $fullSlug . '/' . $item->slug;
|
||||
$item->urlRelWoF = $fullSlugWithoutFolder . '/' . $item->slug;
|
||||
$item->urlRel = $fullSlugWithFolder . '/' . $item->slug;
|
||||
$item->urlAbs = $baseUrl . $fullSlugWithoutFolder . '/' . $item->slug;
|
||||
}
|
||||
$iteration++;
|
||||
$chapternr++;
|
||||
|
33
system/Models/VersionCheck.php
Normal file
33
system/Models/VersionCheck.php
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace System\Models;
|
||||
|
||||
class VersionCheck
|
||||
{
|
||||
function checkVersion($url)
|
||||
{
|
||||
$opts = array(
|
||||
'http'=>array(
|
||||
'method' => "GET",
|
||||
'header' => "Referer: $url\r\n"
|
||||
)
|
||||
);
|
||||
|
||||
$context = stream_context_create($opts);
|
||||
|
||||
try {
|
||||
$version = file_get_contents('http://typemill.net/tma1/checkversion', false, $context);
|
||||
|
||||
if ($version)
|
||||
{
|
||||
$version = json_decode($version);
|
||||
return $version->version;
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
?>
|
61
system/Models/Write.php
Normal file
61
system/Models/Write.php
Normal file
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
namespace System\Models;
|
||||
|
||||
class Write
|
||||
{
|
||||
protected $basePath;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$basePath = getcwd() . DIRECTORY_SEPARATOR;
|
||||
$this->basePath = $basePath;
|
||||
}
|
||||
|
||||
protected function checkPath($folder)
|
||||
{
|
||||
$folderPath = $this->basePath . $folder;
|
||||
|
||||
if(!is_dir($folderPath) AND !mkdir($folderPath, 0774, true))
|
||||
{
|
||||
throw new Exception("The folder '{$folder}' is missing and we could not create it. Please create the folder manually on your server.");
|
||||
return false;
|
||||
}
|
||||
if(!is_writable($folderPath))
|
||||
{
|
||||
throw new Exception("Please make the folder '{$folder}' writable.");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function checkFile($folder, $file)
|
||||
{
|
||||
if(!file_exists($this->basePath . $folder . DIRECTORY_SEPARATOR . $file))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function writeFile($folder, $file, $data)
|
||||
{
|
||||
$filePath = $this->basePath . $folder . DIRECTORY_SEPARATOR . $file;
|
||||
$openFile = fopen($filePath, "w");
|
||||
|
||||
fwrite($openFile, $data);
|
||||
fclose($openFile);
|
||||
}
|
||||
|
||||
public function getFile($folderName, $fileName)
|
||||
{
|
||||
if($this->checkFile($folderName, $fileName))
|
||||
{
|
||||
$fileContent = file_get_contents($folderName . DIRECTORY_SEPARATOR . $fileName);
|
||||
return $fileContent;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
85
system/Models/WriteCache.php
Normal file
85
system/Models/WriteCache.php
Normal file
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
namespace System\Models;
|
||||
|
||||
class WriteCache extends Write
|
||||
{
|
||||
/**
|
||||
* Validates, if the cache is valid or invalid and has to be refreshed
|
||||
* @param int $duration how many seconds the cache is valid.
|
||||
* @return boolean for an invalid cache (false) and for a valid cache (true).
|
||||
*/
|
||||
public function validate($folderName, $fileName, $duration)
|
||||
{
|
||||
if(isset($_SERVER['HTTP_CACHE_CONTROL']) && $_SERVER['HTTP_CACHE_CONTROL'] == 'max-age=0')
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!$this->checkPath($folderName))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!$this->checkFile($folderName, $fileName))
|
||||
{
|
||||
$this->writeFile($folderName, $fileName, time());
|
||||
return false;
|
||||
}
|
||||
|
||||
$lastRefresh = file_get_contents($folderName . DIRECTORY_SEPARATOR . $fileName);
|
||||
if(time() - $lastRefresh > $duration)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a cache file.
|
||||
* Serializes an object and writes it to the cache file together with a file that holds the last refresh time.
|
||||
* @param object $cacheData has to be an object (e.g. navigation object).
|
||||
* @param string $cacheFile has to be the name of the file you want to update (in case there are more than one cache files.
|
||||
*/
|
||||
public function updateCache($folderName, $cacheFileName, $requestFileName, $cacheData)
|
||||
{
|
||||
$sCacheData = serialize($cacheData);
|
||||
$this->writeFile($folderName, $cacheFileName, $sCacheData);
|
||||
if($requestFileName)
|
||||
{
|
||||
$this->writeFile($folderName, $requestFileName, time());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the recent cache.
|
||||
* Takes a filename, gets the file and unserializes the cache into an object.
|
||||
* @param string $fileName is the name of the cache file.
|
||||
*/
|
||||
public function getCache($folderName, $cacheFileName)
|
||||
{
|
||||
$sCacheData = $this->getFile($folderName, $cacheFileName);
|
||||
if($sCacheData)
|
||||
{
|
||||
return unserialize($sCacheData);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo Create a function to clear a specific cache file
|
||||
*/
|
||||
public function clearCache($name)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo Create a function to clear all cache files
|
||||
*/
|
||||
public function clearAllCacheFiles()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
47
system/Models/WriteSitemap.php
Normal file
47
system/Models/WriteSitemap.php
Normal file
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace System\Models;
|
||||
|
||||
class WriteSitemap extends Write
|
||||
{
|
||||
public function updateSitemap($folderName, $sitemapFileName, $requestFileName, $data, $baseUrl)
|
||||
{
|
||||
$sitemap = '<?xml version="1.0" encoding="UTF-8"?>' . "\n";
|
||||
$sitemap .= '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">' . "\n";
|
||||
$sitemap = $this->addUrlSet($sitemap, $baseUrl);
|
||||
$sitemap .= $this->generateUrlSets($data);
|
||||
$sitemap .= '</urlset>';
|
||||
|
||||
$this->writeFile($folderName, $sitemapFileName, $sitemap);
|
||||
$this->writeFile($folderName, $requestFileName, time());
|
||||
}
|
||||
|
||||
public function generateUrlSets($data)
|
||||
{
|
||||
$urlset = '';
|
||||
|
||||
foreach($data as $item)
|
||||
{
|
||||
if($item->elementType == 'folder')
|
||||
{
|
||||
$urlset = $this->addUrlSet($urlset, $item->urlAbs);
|
||||
$urlset .= $this->generateUrlSets($item->folderContent, $urlset);
|
||||
}
|
||||
else
|
||||
{
|
||||
$urlset = $this->addUrlSet($urlset, $item->urlAbs);
|
||||
}
|
||||
}
|
||||
return $urlset;
|
||||
}
|
||||
|
||||
public function addUrlSet($urlset, $url)
|
||||
{
|
||||
$urlset .= ' <url>' . "\n";
|
||||
$urlset .= ' <loc>' . $url . '</loc>' . "\n";
|
||||
$urlset .= ' </url>' . "\n";
|
||||
return $urlset;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
35
system/Models/WriteYaml.php
Normal file
35
system/Models/WriteYaml.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace System\Models;
|
||||
|
||||
class WriteYaml extends Write
|
||||
{
|
||||
/**
|
||||
* Get the a yaml file.
|
||||
* @param string $fileName is the name of the Yaml Folder.
|
||||
* @param string $yamlFileName is the name of the Yaml File.
|
||||
*/
|
||||
public function getYaml($folderName, $yamlFileName)
|
||||
{
|
||||
$yaml = $this->getFile($folderName, $yamlFileName);
|
||||
if($yaml)
|
||||
{
|
||||
return \Symfony\Component\Yaml\Yaml::parse($yaml);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a yaml file.
|
||||
* @param string $fileName is the name of the Yaml Folder.
|
||||
* @param string $yamlFileName is the name of the Yaml File.
|
||||
* @param array $contentArray is the content as an array.
|
||||
*/
|
||||
public function updateYaml($folderName, $yamlFileName, $contentArray)
|
||||
{
|
||||
$yaml = \Symfony\Component\Yaml\Yaml::dump($contentArray);
|
||||
$this->writeFile($folderName, $yamlFileName, $yaml);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
@@ -1,7 +1,3 @@
|
||||
<?php
|
||||
/*
|
||||
use App\Controllers\ApiController;
|
||||
|
||||
$app->get('/api', ApiController::class . ':index' )->setName('api.index');
|
||||
*/
|
||||
?>
|
@@ -15,8 +15,8 @@ return [
|
||||
'settingsPath' => __DIR__ . DS . '..' . DS . 'settings',
|
||||
'authorPath' => __DIR__ . DS . 'author' . DS,
|
||||
'contentFolder' => 'content',
|
||||
'displayErrorDetails' => false,
|
||||
'version' => '1.0.0'
|
||||
'displayErrorDetails' => true,
|
||||
'version' => '1.0.1'
|
||||
],
|
||||
];
|
||||
|
||||
|
@@ -71,7 +71,7 @@ $container['notFoundHandler'] = function($c)
|
||||
return new \System\Handlers\NotFoundHandler($c['view']);
|
||||
};
|
||||
|
||||
require __DIR__ . '/Routes/web.php';
|
||||
require __DIR__ . '/Routes/api.php';
|
||||
require __DIR__ . '/Routes/web.php';
|
||||
|
||||
?>
|
@@ -5,4 +5,4 @@
|
||||
{% set copyrightYears = settings.year ~ ' - ' ~ nowYear %}
|
||||
{% endif %}
|
||||
|
||||
<div class="copyrightLine"><p>{{ settings.copyright }} by {{ settings.author }}, {{ copyrightYears }}. All Rights Reserved. Built with <a href="http://typemill.net">TYPEMILL</a>.</p></div>
|
||||
<div class="copyrightLine"><p>{{ settings.copyright }} by {{ settings.author }}, {{ copyrightYears }}. All Rights Reserved. Built with <a href="http://typemill.net">TYPEMILL</a>.{% if settings.version < settings.latestVersion %} Please <a href="http://typemill.com">Update</a>{% endif %}</p></div>
|
Reference in New Issue
Block a user