From c38783c4f64ecf7b4ca97bcbd5ec4d21ab75f4a8 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Tue, 24 Jul 2018 10:43:34 +0200 Subject: [PATCH] Version 1.2.2: Draft Management --- cache/lastCache.txt | 2 +- content/5_info/20_Übermaß.md | 5 - system/Controllers/ContentApiController.php | 232 ++++++++++ .../Controllers/ContentBackendController.php | 73 ++++ system/Controllers/ContentController.php | 411 ++++++++++-------- system/Controllers/PageController.php | 10 +- system/Extensions/ParsedownExtension.php | 102 ++++- system/Models/Folder.php | 39 +- system/Routes/Api.php | 7 +- system/Routes/Web.php | 4 +- system/author/content/content.twig | 51 ++- system/author/css/fontello/LICENSE.txt | 9 + system/author/css/fontello/config.json | 42 +- .../css/fontello/css/fontello-codes.css | 7 +- .../css/fontello/css/fontello-embedded.css | 19 +- .../css/fontello/css/fontello-ie7-codes.css | 7 +- .../author/css/fontello/css/fontello-ie7.css | 7 +- system/author/css/fontello/css/fontello.css | 21 +- system/author/css/fontello/demo.html | 17 +- system/author/css/fontello/font/fontello.eot | Bin 7076 -> 6924 bytes system/author/css/fontello/font/fontello.svg | 8 +- system/author/css/fontello/font/fontello.ttf | Bin 6908 -> 6756 bytes system/author/css/fontello/font/fontello.woff | Bin 4156 -> 4168 bytes .../author/css/fontello/font/fontello.woff2 | Bin 3428 -> 3428 bytes system/author/css/style.css | 183 ++++++-- system/author/js/vue-editor.js | 147 ++++++- 26 files changed, 1059 insertions(+), 344 deletions(-) delete mode 100644 content/5_info/20_Übermaß.md create mode 100644 system/Controllers/ContentApiController.php create mode 100644 system/Controllers/ContentBackendController.php diff --git a/cache/lastCache.txt b/cache/lastCache.txt index 1a53266..3398627 100644 --- a/cache/lastCache.txt +++ b/cache/lastCache.txt @@ -1 +1 @@ -1530867542 \ No newline at end of file +1532420761 \ No newline at end of file diff --git a/content/5_info/20_Übermaß.md b/content/5_info/20_Übermaß.md deleted file mode 100644 index e44ee1b..0000000 --- a/content/5_info/20_Übermaß.md +++ /dev/null @@ -1,5 +0,0 @@ -# Ü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 link 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. \ No newline at end of file diff --git a/system/Controllers/ContentApiController.php b/system/Controllers/ContentApiController.php new file mode 100644 index 0000000..17af3f8 --- /dev/null +++ b/system/Controllers/ContentApiController.php @@ -0,0 +1,232 @@ +params = $request->getParams(); + $this->uri = $request->getUri(); + + # validate input + if(!$this->validateEditorInput()){ return $response->withJson($this->errors,422); } + + # set structure + if(!$this->setStructure($draft = true)){ return $response->withJson($this->errors, 404); } + + # set item + if(!$this->setItem()){ return $response->withJson($this->errors, 404); } + + # set the status for published and drafted + $this->setPublishStatus(); + + # set path for the file (or folder) + $this->setItemPath('md'); + + # merge title with content for complete markdown document + $updatedContent = '# ' . $this->params['title'] . "\r\n\r\n" . $this->params['content']; + + # update the file + if($this->write->writeFile($this->settings['contentFolder'], $this->path, $updatedContent)) + { + # update the file + $delete = $this->deleteContentFiles(['txt']); + + # update the structure + $this->setStructure($draft = false, $cache = false); + + return $response->withJson(['success'], 200); + } + else + { + return $response->withJson(['errors' => ['message' => 'Could not write to file. Please check if the file is writable']], 404); + } + } + + public function unpublishArticle(Request $request, Response $response, $args) + { + # get params from call + $this->params = $request->getParams(); + $this->uri = $request->getUri(); + + # set structure + if(!$this->setStructure($draft = true)){ return $response->withJson($this->errors, 404); } + + # set item + if(!$this->setItem()){ return $response->withJson($this->errors, 404); } + + # set the status for published and drafted + $this->setPublishStatus(); + + # check if draft exists, if not, create one. + if(!$this->item->drafted) + { + # set path for the file (or folder) + $this->setItemPath('md'); + + # set content of markdown-file + if(!$this->setContent()){ return $response->withJson($this->errors, 404); } + + # initialize parsedown extension + $parsedown = new ParsedownExtension(); + + # turn markdown into an array of markdown-blocks + $contentArray = $parsedown->markdownToArrayBlocks($this->content); + + # encode the content into json + $contentJson = json_encode($contentArray); + + # set path for the file (or folder) + $this->setItemPath('txt'); + + /* update the file */ + if(!$this->write->writeFile($this->settings['contentFolder'], $this->path, $contentJson)) + { + return $response->withJson(['errors' => ['message' => 'Could not create a draft of the page. Please check if the folder is writable']], 404); + } + } + + # update the file + $delete = $this->deleteContentFiles(['md']); + + if($delete) + { + # update the live structure + $this->setStructure($draft = false, $cache = false); + + return $response->withJson(['success'], 200); + } + else + { + return $response->withJson(['errors' => ['message' => "Could not delete some files. Please check if the files exists and are writable"]], 404); + } + } + + public function deleteArticle(Request $request, Response $response, $args) + { + # get params from call + $this->params = $request->getParams(); + $this->uri = $request->getUri(); + + # set structure + if(!$this->setStructure($draft = true)){ return $response->withJson($this->errors, 404); } + + # set item + if(!$this->setItem()){ return $response->withJson($this->errors, 404); } + + # update the file + $delete = $this->deleteContentFiles(['md','txt']); + + if($delete) + { + # update the live structure + $this->setStructure($draft = false, $cache = false); + + #update the backend structure + $this->setStructure($draft = true, $cache = false); + + return $response->withJson(['success'], 200); + } + else + { + return $response->withJson(['errors' => ['message' => "Could not delete some files. Please check if the files exists and are writable"]], 404); + } + } + + public function updateArticle(Request $request, Response $response, $args) + { + # get params from call + $this->params = $request->getParams(); + $this->uri = $request->getUri(); + + # validate input + if(!$this->validateEditorInput()){ return $response->withJson($this->errors,422); } + + # set structure + if(!$this->setStructure($draft = true)){ return $response->withJson($this->errors, 404); } + + # set item + if(!$this->setItem()){ return $response->withJson($this->errors, 404); } + + # set path for the file (or folder) + $this->setItemPath('txt'); + + # merge title with content for complete markdown document + $updatedContent = '# ' . $this->params['title'] . "\r\n\r\n" . $this->params['content']; + + # initialize parsedown extension + $parsedown = new ParsedownExtension(); + + # turn markdown into an array of markdown-blocks + $contentArray = $parsedown->markdownToArrayBlocks($updatedContent); + + # encode the content into json + $contentJson = json_encode($contentArray); + + /* update the file */ + if($this->write->writeFile($this->settings['contentFolder'], $this->path, $contentJson)) + { + return $response->withJson(['success'], 200); + } + else + { + return $response->withJson(['errors' => ['message' => 'Could not write to file. Please check if the file is writable']], 404); + } + } + + public function createBlock(Request $request, Response $response, $args) + { + + /* get params from call */ + $this->params = $request->getParams(); + $this->uri = $request->getUri(); + + /* validate input */ + if(!$this->validateInput()){ return $response->withJson($this->errors,422); } + + /* set structure */ + if(!$this->setStructure()){ return $response->withJson($this->errors, 404); } + + /* set item */ + if(!$this->setItem()){ return $response->withJson($this->errors, 404); } + + /* set path */ + $this->setItemPath(); + + /* get markdown-file */ + if(!$this->setMarkdownFile()){ return $response->withJson($this->errors, 404); } + + /* get txt-file with content array */ + $contentArray = NULL; + + /* + create a txt-file with parsedown-array. + you will have .md and .txt file. + scan folder with option to show drafts. + but what is with structure? We use the cached structure, do not forget!!! + if there is a draft, replace the md file with txt-file. + display content: you have to check if md or txt. if txt, then directly open the txt-file. + in here set markdown-file or + set txt-file. + if publish, render txt-content, replace markdown-file, delete txt-file + */ + + /* initialize pagedown */ + + /* turn input into array */ + + /* add input to contentArray */ + + /* store updated contentArray */ + + /* transform input to html */ + + /* send html to client */ + } +} \ No newline at end of file diff --git a/system/Controllers/ContentBackendController.php b/system/Controllers/ContentBackendController.php new file mode 100644 index 0000000..3110f3a --- /dev/null +++ b/system/Controllers/ContentBackendController.php @@ -0,0 +1,73 @@ +uri = $request->getUri(); + $this->params = isset($args['params']) ? ['url' => $this->uri->getBasePath() . '/' . $args['params']] : ['url' => $this->uri->getBasePath()]; + + # set structure + if(!$this->setStructure($draft = true)){ die('no structure'); return $this->render404($response, array( 'navigation' => true, 'content' => $this->errors )); } + + # set item + if(!$this->setItem()){ die('no item'); return $this->render404($response, array( 'navigation' => $this->structure, 'settings' => $this->settings, 'content' => $this->errors )); } + + # set the status for published and drafted + $this->setPublishStatus(); + + # set path + $this->setItemPath($this->item->fileType); + + # add the modified date for the file + $this->item->modified = ($this->item->published OR $this->item->drafted) ? filemtime($this->settings['contentFolder'] . $this->path) : false; + + # read content from file + if(!$this->setContent()){ return $this->render404($response, array( 'navigation' => $this->structure, 'settings' => $this->settings, 'content' => $this->errors )); } + + $content = $this->content; + $title = false; + + # if content is an array, then it is a draft + if(is_array($content)) + { + # transform array to markdown + $parsedown = new ParsedownExtension(); + $content = $parsedown->arrayBlocksToMarkdown($content); + } + + # if there is content + if($content != '') + { + # normalize linebreaks + $content = str_replace(array("\r\n", "\r"), "\n", $content); + $content = trim($content, "\n"); + + # and strip out title + if($content[0] == '#') + { + $contentParts = explode("\n", $content, 2); + $title = trim($contentParts[0], "# \t\n\r\0\x0B"); + $content = trim($contentParts[1]); + } + } + + return $this->render($response, 'content/content.twig', array('navigation' => $this->structure, 'title' => $title, 'content' => $content, 'item' => $this->item, 'settings' => $this->settings )); + } +} \ No newline at end of file diff --git a/system/Controllers/ContentController.php b/system/Controllers/ContentController.php index 21f505c..82a7f0f 100644 --- a/system/Controllers/ContentController.php +++ b/system/Controllers/ContentController.php @@ -2,216 +2,243 @@ namespace Typemill\Controllers; -use Slim\Views\Twig; use Slim\Http\Request; use Slim\Http\Response; +use Interop\Container\ContainerInterface; use Typemill\Models\Validation; use Typemill\Models\Folder; use Typemill\Models\Write; -use Typemill\Models\WriteYaml; use Typemill\Models\WriteCache; -use \Symfony\Component\Yaml\Yaml; -use Typemill\Models\Helpers; -use Typemill\Extensions\ParsedownExtension; -use \Parsedown; - -class ContentController extends Controller +abstract class ContentController { + # holds the pimple container + protected $c; - /** - * Show Content - * - * @param obj $request the slim request object - * @param obj $response the slim response object - * @return obje $response with redirect to route - */ + # holds the params from request + protected $params; + + # holds the slim-uri-object + protected $uri; - public function showContent(Request $request, Response $response, $args) + # holds the errors to output in frontend + protected $errors; + + # holds a write object to write files + protected $write; + + # holds the structure of content folder as a serialized array of objects + protected $structure; + + # holds the name of the structure-file with drafts for author environment + protected $structureDraftName; + + # holds the name of the structure-file without drafts for live site + protected $structureLiveName; + + # hold the page-item as an object + protected $item; + + # holds the path to the requested file + protected $path = false; + + # holds the content of the page + protected $content; + + public function __construct(ContainerInterface $c) { - $settings = $this->c->get('settings'); - $pathToContent = $settings['rootPath'] . $settings['contentFolder']; - $uri = $request->getUri(); - - /* scan the content of the folder */ - $structure = Folder::scanFolder($pathToContent); - - /* if there is no content, render an empty page */ - if(count($structure) == 0) - { - return $this->render($response, 'content/content.twig', array( 'navigation' => true, 'content' => 'Nothing found in content folder.' )); - } - - /* create an array of object with the whole content of the folder */ - $structure = Folder::getFolderContentDetails($structure, $uri->getBaseUrl(), $uri->getBasePath()); - - /* if there is no structure at all, the content folder is probably empty */ - if(!$structure) - { - return $this->render($response, 'content/content.twig', array( 'navigation' => true, 'content' => 'Nothing found in content folder.' )); - } - - /* if it is the 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; - - /* if there is content (index.md), then add a marker for frontend, so ajax calls for homepage-index-urls work */ - if($contentMD) - { - $item = new \stdClass; - $item->urlRel = 'is_homepage_index'; - } - } - 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 there is still no item, return a 404-page */ - if(!$item) - { - return $this->render404($response, array( 'navigation' => $structure, 'settings' => $settings, 'base_url' => $base_url )); - } - - /* 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 in that folder */ - if($item->elementType == 'folder' && $item->index) - { - $filePath = $pathToContent . $item->path . DIRECTORY_SEPARATOR . 'index.md'; - } - elseif($item->elementType == 'file') - { - $filePath = $pathToContent . $item->path; - } - - /* add the modified date for the file */ - $item->modified = isset($filePath) ? filemtime($filePath) : false; - - /* read the content of the file */ - $contentMD = isset($filePath) ? file_get_contents($filePath) : false; - } - - $title = false; - $content = $contentMD; - - $content = str_replace(array("\r\n", "\r"), "\n", $content); - $content = trim($content, "\n"); - - if($contentMD[0] == '#') - { - $contentParts = explode("\n", $contentMD, 2); - $title = trim($contentParts[0], "# \t\n\r\0\x0B"); - $content = trim($contentParts[1]); - } - - return $this->render($response, 'content/content.twig', array('navigation' => $structure, 'title' => $title, 'content' => $content, 'item' => $item, 'settings' => $settings )); + $this->c = $c; + $this->settings = $this->c->get('settings'); + $this->structureLiveName = 'structure.txt'; + $this->structureDraftName = 'structure-draft.txt'; } - - public function updateArticle(Request $request, Response $response, $args) + + protected function render($response, $route, $data) { - /* Extract the parameters from get-call */ - $params = $request->getParams(); + if(isset($_SESSION['old'])) + { + unset($_SESSION['old']); + } - /* validate input */ - $validate = new Validation(); - $vResult = $validate->editorInput($params); + if($this->c->request->getUri()->getScheme() == 'https') + { + $response = $response->withAddedHeader('Strict-Transport-Security', 'max-age=63072000'); + } + $response = $response->withAddedHeader('X-Content-Type-Options', 'nosniff'); + $response = $response->withAddedHeader('X-Frame-Options', 'SAMEORIGIN'); + $response = $response->withAddedHeader('X-XSS-Protection', '1;mode=block'); + $response = $response->withAddedHeader('Referrer-Policy', 'no-referrer-when-downgrade'); + + return $this->c->view->render($response, $route, $data); + } + + protected function render404($response, $data = NULL) + { + return $this->c->view->render($response->withStatus(404), '/404.twig', $data); + } + + protected function validateEditorInput() + { + $validate = new Validation(); + $vResult = $validate->editorInput($this->params); + if(is_array($vResult)) - { - return $response->withJson(['errors' => $vResult], 422); - } - - /* initiate variables and objects that we need */ - $settings = $this->c->get('settings'); - $pathToContent = $settings['rootPath'] . $settings['contentFolder']; - $uri = $request->getUri(); - $base_url = $uri->getBaseUrl(); - $write = new writeCache(); - - /* we will use the cached structure to find the url for the page-update. It acts as whitelist and is more secure than a file-path, for example. */ - $structure = $write->getCache('cache', 'structure.txt'); - - /* if there is no structure, create a fresh structure */ - if(!$structure) - { - $structure = $this->getFreshStructure($pathToContent, $write, $uri); - if(!$structure) - { - return $response->withJson(['errors' => ['message' => 'content folder is empty']], 404); - } - } - - /* if it is the homepage */ - if($params['url'] == 'is_homepage_index') - { - $item = new \stdClass; - $item->elementType = 'folder'; - $item->path = ''; - } - else - { - /* search for the url in the structure */ - $item = Folder::getItemForUrl($structure, $params['url']); - } - - if(!$item) - { - return $response->withJson(['errors' => ['message' => 'requested page-url not found']], 404); - } - - if($item->elementType == 'folder') - { - $path = $item->path . DIRECTORY_SEPARATOR . 'index.md'; - } - elseif($item->elementType == 'file') - { - $path = $item->path; - } - - /* get the markdown file */ - $mdFile = $write->getFile($settings['contentFolder'], $path); - if($mdFile) - { - /* merge title with content forcomplete markdown document */ - $updatedContent = '# ' . $params['title'] . "\r\n\r\n" . $params['content']; - - /* update the file */ - if($write->writeFile($settings['contentFolder'], $path, $updatedContent)) - { - return $response->withJson(['success'], 200); - } - else - { - return $response->withJson(['errors' => ['message' => 'Could not write to file. Please check if file is writable']], 404); - } - } - return $response->withJson(['errors' => ['message' => 'requested markdown-file not found']], 404); - } - - 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) - { + { + $this->errors = ['errors' => $vResult]; 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->updateCache('cache', 'structure.txt', 'lastCache.txt', $structure); + return true; + } + + protected function setStructure($draft = false, $cache = true) + { + # name of structure-file for draft or live + $filename = $draft ? $this->structureDraftName : $this->structureLiveName; - return $structure; + # set variables and objects + $this->write = new writeCache(); + + # check, if cached structure is still valid + if($cache && $this->write->validate('cache', 'lastCache.txt', 600)) + { + # get the cached structure + $structure = $this->write->getCache('cache', $filename); + } + else + { + # scan the content of the folder + $structure = Folder::scanFolder($this->settings['rootPath'] . $this->settings['contentFolder'], $draft); + + # if there is no content, render an empty page + if(count($structure) == 0) + { + $this->errors = ['errors' => ['message' => 'content folder is empty']]; + return false; + } + + # create an array of object with the whole content of the folder + $structure = Folder::getFolderContentDetails($structure, $this->uri->getBaseUrl(), $this->uri->getBasePath()); + + # cache navigation + $this->write->updateCache('cache', $filename, 'lastCache.txt', $structure); + } + + $this->structure = $structure; + return true; + } + + protected function setItem() + { + # if it is the homepage + if($this->params['url'] == $this->uri->getBasePath() OR $this->params['url'] == '/') + { + $item = new \stdClass; + $item->elementType = 'folder'; + $item->path = ''; + $item->urlRel = '/'; + } + else + { + # search for the url in the structure + $item = Folder::getItemForUrl($this->structure, $this->params['url']); + } + + if($item) + { + if($item->elementType == 'file') + { + $pathParts = explode('.', $item->path); + $fileType = array_pop($pathParts); + $pathWithoutType = implode('.', $pathParts); + $item->pathWithoutType = $pathWithoutType; + } + elseif($item->elementType == 'folder') + { + $item->path = $item->path . DIRECTORY_SEPARATOR . 'index'; + $item->pathWithoutType = $item->path; + } + $this->item = $item; + return true; + } + + $this->errors = ['errors' => ['message' => 'requested page-url not found']]; + return false; + } + + # determine if you want to write to published file (md) or to draft (txt) + protected function setItemPath($fileType) + { + $this->path = $this->item->pathWithoutType . '.' . $fileType; + } + + protected function setPublishStatus() + { + $this->item->published = false; + $this->item->drafted = false; + + if(file_exists($this->settings['rootPath'] . $this->settings['contentFolder'] . $this->item->pathWithoutType . '.md')) + { + $this->item->published = true; + + # add file-type in case it is a folder + $this->item->fileType = "md"; + } + elseif(file_exists($this->settings['rootPath'] . $this->settings['contentFolder'] . $this->item->pathWithoutType . '.txt')) + { + $this->item->drafted = true; + + # add file-type in case it is a folder + $this->item->fileType = "txt"; + } + elseif($this->item->elementType == "folder") + { + # set txt as default for a folder, so that we can create an index.txt for a folder. + $this->item->fileType = "txt"; + } + } + + protected function deleteContentFiles($fileTypes) + { + $basePath = $this->settings['rootPath'] . $this->settings['contentFolder']; + + foreach($fileTypes as $fileType) + { + if(file_exists($basePath . $this->item->pathWithoutType . '.' . $fileType)) + { + unlink($basePath . $this->item->pathWithoutType . '.' . $fileType); + + # if file could not be deleted + # $this->errors = ['errors' => ['message' => 'Could not delete files, please check, if files are writable.']]; + } + } + + return true; + } + + protected function setContent() + { + # if the file exists + if($this->item->published OR $this->item->drafted) + { + $content = $this->write->getFile($this->settings['contentFolder'], $this->path); + if($this->item->fileType == 'txt') + { + # decode the json-draft to an array + $content = json_decode($content); + } + } + elseif($this->item->elementType == "folder") + { + $content = ''; + } + else + { + $this->errors = ['errors' => ['message' => 'requested file not found']]; + return false; + } + + $this->content = $content; + return true; } } \ No newline at end of file diff --git a/system/Controllers/PageController.php b/system/Controllers/PageController.php index c684c32..16b0439 100644 --- a/system/Controllers/PageController.php +++ b/system/Controllers/PageController.php @@ -9,6 +9,7 @@ use Typemill\Models\WriteYaml; use \Symfony\Component\Yaml\Yaml; use Typemill\Models\VersionCheck; use Typemill\Models\Helpers; +use Typemill\Models\Markdown; use Typemill\Events\OnPagetreeLoaded; use Typemill\Events\OnBreadcrumbLoaded; use Typemill\Events\OnItemLoaded; @@ -21,7 +22,6 @@ class PageController extends Controller { public function index($request, $response, $args) { - /* Initiate Variables */ $structure = false; $contentHTML = false; @@ -33,7 +33,7 @@ class PageController extends Controller $cache = new WriteCache(); $uri = $request->getUri(); $base_url = $uri->getBaseUrl(); - + try { /* if the cached structure is still valid, use it */ @@ -72,7 +72,7 @@ class PageController extends Controller echo $e->getMessage(); exit(1); } - + /* if the user is on startpage */ if(empty($args)) { @@ -122,14 +122,14 @@ class PageController extends Controller /* initialize parsedown */ $parsedown = new ParsedownExtension(); - + /* set safe mode to escape javascript and html in markdown */ $parsedown->setSafeMode(true); /* parse markdown-file to content-array */ $contentArray = $parsedown->text($contentMD); $contentArray = $this->c->dispatcher->dispatch('onContentArrayLoaded', new OnContentArrayLoaded($contentArray))->getData(); - + /* get the first image from content array */ $firstImage = $this->getFirstImage($contentArray); diff --git a/system/Extensions/ParsedownExtension.php b/system/Extensions/ParsedownExtension.php index 058ef67..4099325 100644 --- a/system/Extensions/ParsedownExtension.php +++ b/system/Extensions/ParsedownExtension.php @@ -17,7 +17,7 @@ class ParsedownExtension extends \ParsedownExtra # table of content support array_unshift($this->BlockTypes['['], 'TableOfContents'); } - + function text($text) { $Elements = $this->textElements($text); @@ -67,7 +67,7 @@ class ParsedownExtension extends \ParsedownExtra # Header - private $headlines = array(); + private $headlines = array(); protected function blockHeader($Line) { @@ -266,4 +266,102 @@ class ParsedownExtension extends \ParsedownExtra $Block['element']['text'] = "\$\$\n" . $text . "\n\$\$"; return $Block; } + + # turn markdown into an array of markdown blocks for typemill edit mode + function markdownToArrayBlocks($markdown) + { + # standardize line breaks + $markdown = str_replace(array("\r\n", "\r"), "\n", $markdown); + + # remove surrounding line breaks + $markdown = trim($markdown, "\n"); + + # trim to maximum two linebreaks + + # split text into blocks + $blocks = explode("\n\n", $markdown); + + # clean up code blocks + $cleanBlocks = array(); + + # holds the content of codeblocks + $codeBlock = ''; + + # flag if codeblock is on or off. + $codeBlockOn = false; + + foreach($blocks as $block) + { + // remove empty lines + if (chop($block) === '') continue; + + // if the block starts with a fenced code + if(substr($block,0,2) == '``') + { + // and if we are in an open code-block + if($codeBlockOn) + { + // it must be the end of the codeblock, so add it to the codeblock + $block = $codeBlock . "\n" . $block; + + // reset codeblock-value and close the codeblock. + $codeBlock = ''; + $codeBlockOn = false; + } + else + { + // it must be the start of the codeblock. + $codeBlockOn = true; + } + } + if($codeBlockOn) + { + // if the codeblock is complete + if($this->isComplete($block)) + { + $block = $codeBlock . "\n" . $block; + + // reset codeblock-value and close the codeblock. + $codeBlock = ''; + $codeBlockOn = false; + } + else + { + $codeBlock .= "\n" . $block; + continue; + } + } + + $cleanBlocks[] = $block; + } + + return $cleanBlocks; + } + + protected function isComplete($codeblock) + { + $lines = explode("\n", $codeblock); + if(count($lines) > 1) + { + $lastLine = array_pop($lines); + if(substr($lastLine,0,2) == '``') + { + return true; + } + return false; + } + return false; + } + + public function arrayBlocksToMarkdown(array $arrayBlocks) + { + $markdown = ''; + + foreach($arrayBlocks as $block) + { + $markdown .= $block . "\n\n"; + } + + return $markdown; + } } \ No newline at end of file diff --git a/system/Models/Folder.php b/system/Models/Folder.php index df826d2..dc11488 100644 --- a/system/Models/Folder.php +++ b/system/Models/Folder.php @@ -11,7 +11,7 @@ class Folder * vars: folder path as string * returns: multi-dimensional array with names of folders and files */ - public static function scanFolder($folderPath) + public static function scanFolder($folderPath, $draft = false) { $folderItems = scandir($folderPath); $folderContent = array(); @@ -22,13 +22,31 @@ class Folder { if (is_dir($folderPath . DIRECTORY_SEPARATOR . $item)) { + /* TODO: if folder is empty or folder has only txt files, continue */ $subFolder = $item; - $folderContent[$subFolder] = self::scanFolder($folderPath . DIRECTORY_SEPARATOR . $subFolder); + $folderContent[$subFolder] = self::scanFolder($folderPath . DIRECTORY_SEPARATOR . $subFolder, $draft); } else { - $file = $item; - $folderContent[] = $file; + $nameParts = self::getStringParts($item); + $fileType = array_pop($nameParts); + + if($fileType == 'md') + { + $folderContent[] = $item; + } + + if($draft === true && $fileType == 'txt') + { + if(isset($last) && ($last == implode($nameParts)) ) + { + array_pop($folderContent); + } + $folderContent[] = $item; + } + + /* store the name of the last file */ + $last = implode($nameParts); } } } @@ -78,8 +96,9 @@ class Folder $nameParts = self::getStringParts($name); $fileType = array_pop($nameParts); - if($name == 'index.md' || $fileType !== 'md' ) continue; - + # if($name == 'index.md' || $fileType !== 'md' ) continue; + if($name == 'index.md' || $name == 'index.txt' ) continue; + $item->originalName = $name; $item->elementType = 'file'; $item->fileType = $fileType; @@ -271,5 +290,11 @@ class Folder { $parts = preg_split('/\./',$fileName); return end($parts); - } + } + + public static function splitFileName($fileName) + { + $parts = preg_split('/\./',$fileName); + return $parts; + } } \ No newline at end of file diff --git a/system/Routes/Api.php b/system/Routes/Api.php index 598a287..5d9f4a2 100644 --- a/system/Routes/Api.php +++ b/system/Routes/Api.php @@ -2,7 +2,12 @@ use Typemill\Controllers\SettingsController; use Typemill\Controllers\ContentController; +use Typemill\Controllers\ContentApiController; use Typemill\Middleware\RestrictApiAccess; $app->get('/api/v1/themes', SettingsController::class . ':getThemeSettings')->setName('api.themes')->add(new RestrictApiAccess($container['router'])); -$app->put('/api/v1/article', ContentController::class . ':updateArticle')->setName('api.article.update')->add(new RestrictApiAccess($container['router'])); \ No newline at end of file +$app->post('/api/v1/article/publish', ContentApiController::class . ':publishArticle')->setName('api.article.publish')->add(new RestrictApiAccess($container['router'])); +$app->delete('/api/v1/article/unpublish', ContentApiController::class . ':unpublishArticle')->setName('api.article.unpublish')->add(new RestrictApiAccess($container['router'])); +$app->put('/api/v1/article', ContentApiController::class . ':updateArticle')->setName('api.article.update')->add(new RestrictApiAccess($container['router'])); +$app->delete('/api/v1/article', ContentApiController::class . ':deleteArticle')->setName('api.article.delete')->add(new RestrictApiAccess($container['router'])); +$app->post('/api/v1/block', ContentBackendController::class . ':createBlock')->setName('api.block.create')->add(new RestrictApiAccess($container['router'])); \ No newline at end of file diff --git a/system/Routes/Web.php b/system/Routes/Web.php index 26b3ae1..623e0b4 100644 --- a/system/Routes/Web.php +++ b/system/Routes/Web.php @@ -4,7 +4,7 @@ use Typemill\Controllers\PageController; use Typemill\Controllers\SetupController; use Typemill\Controllers\AuthController; use Typemill\Controllers\SettingsController; -use Typemill\Controllers\ContentController; +use Typemill\Controllers\ContentBackendController; use Typemill\Middleware\RedirectIfUnauthenticated; use Typemill\Middleware\RedirectIfAuthenticated; use Typemill\Middleware\RedirectIfNoAdmin; @@ -46,7 +46,7 @@ $app->post('/tm/user/delete', SettingsController::class . ':deleteUser')->setNam $app->get('/tm/user/{username}', SettingsController::class . ':showUser')->setName('user.show')->add(new RedirectIfUnauthenticated($container['router'], $container['flash'])); $app->get('/tm/user', SettingsController::class . ':listUser')->setName('user.list')->add(new RedirectIfNoAdmin($container['router'], $container['flash'])); -$app->get('/tm/content[/{params:.*}]', ContentController::class . ':showContent')->setName('content.show')->add(new RedirectIfUnauthenticated($container['router'], $container['flash'])); +$app->get('/tm/content[/{params:.*}]', ContentBackendController::class . ':showContent')->setName('content.show')->add(new RedirectIfUnauthenticated($container['router'], $container['flash'])); foreach($routes as $pluginRoute) { diff --git a/system/author/content/content.twig b/system/author/content/content.twig index 8b5b903..6d6ac83 100644 --- a/system/author/content/content.twig +++ b/system/author/content/content.twig @@ -5,35 +5,56 @@
-
-
-
+
+ + +
+
- + ${ errors.title }
- + ${ errors.content }
-
- -
${ errors.message }
-
- -
- - - {{ csrf_field() | raw }} + +
+ +
+
${ errors.message }
+ +
+
+ +
+ +
+
+ + +
- + {{ csrf_field() | raw }} diff --git a/system/author/css/fontello/LICENSE.txt b/system/author/css/fontello/LICENSE.txt index 8fa3da3..3fdba2a 100644 --- a/system/author/css/fontello/LICENSE.txt +++ b/system/author/css/fontello/LICENSE.txt @@ -10,3 +10,12 @@ Font license info Homepage: http://fortawesome.github.com/Font-Awesome/ +## Web Symbols + + Copyright (c) 2011 by Just Be Nice studio. All rights reserved. + + Author: Just Be Nice studio + License: SIL (http://scripts.sil.org/OFL) + Homepage: http://www.justbenicestudio.com/ + + diff --git a/system/author/css/fontello/config.json b/system/author/css/fontello/config.json index 8e2ef1b..7d8ebd4 100644 --- a/system/author/css/fontello/config.json +++ b/system/author/css/fontello/config.json @@ -7,15 +7,27 @@ "ascent": 850, "glyphs": [ { - "uid": "381da2c2f7fd51f8de877c044d7f439d", - "css": "picture", - "code": 59392, + "uid": "8b9e6a8dd8f67f7c003ed8e7e5ee0857", + "css": "off", + "code": 59393, "src": "fontawesome" }, { - "uid": "41087bc74d4b20b55059c60a33bf4008", - "css": "edit", - "code": 59393, + "uid": "c5fd349cbd3d23e4ade333789c29c729", + "css": "eye", + "code": 59394, + "src": "fontawesome" + }, + { + "uid": "e99461abfef3923546da8d745372c995", + "css": "cog", + "code": 59396, + "src": "fontawesome" + }, + { + "uid": "5408be43f7c42bccee419c6be53fdef5", + "css": "doc-text", + "code": 61686, "src": "fontawesome" }, { @@ -25,22 +37,16 @@ "src": "fontawesome" }, { - "uid": "e99461abfef3923546da8d745372c995", - "css": "cog", - "code": 59394, + "uid": "381da2c2f7fd51f8de877c044d7f439d", + "css": "picture", + "code": 59392, "src": "fontawesome" }, { - "uid": "8b9e6a8dd8f67f7c003ed8e7e5ee0857", - "css": "off", + "uid": "8da3ac534210aae9c0f0e13804c1df97", + "css": "cancel", "code": 59395, - "src": "fontawesome" - }, - { - "uid": "5408be43f7c42bccee419c6be53fdef5", - "css": "doc-text", - "code": 61686, - "src": "fontawesome" + "src": "websymbols" } ] } \ No newline at end of file diff --git a/system/author/css/fontello/css/fontello-codes.css b/system/author/css/fontello/css/fontello-codes.css index d0e23e6..1a91f76 100644 --- a/system/author/css/fontello/css/fontello-codes.css +++ b/system/author/css/fontello/css/fontello-codes.css @@ -1,7 +1,8 @@ .icon-picture:before { content: '\e800'; } /* '' */ -.icon-edit:before { content: '\e801'; } /* '' */ -.icon-cog:before { content: '\e802'; } /* '' */ -.icon-off:before { content: '\e803'; } /* '' */ +.icon-off:before { content: '\e801'; } /* '' */ +.icon-eye:before { content: '\e802'; } /* '' */ +.icon-cancel:before { content: '\e803'; } /* '' */ +.icon-cog:before { content: '\e804'; } /* '' */ .icon-link-ext:before { content: '\f08e'; } /* '' */ .icon-doc-text:before { content: '\f0f6'; } /* '' */ \ No newline at end of file diff --git a/system/author/css/fontello/css/fontello-embedded.css b/system/author/css/fontello/css/fontello-embedded.css index eb48e23..c847cde 100644 --- a/system/author/css/fontello/css/fontello-embedded.css +++ b/system/author/css/fontello/css/fontello-embedded.css @@ -1,15 +1,15 @@ @font-face { font-family: 'fontello'; - src: url('../font/fontello.eot?42893505'); - src: url('../font/fontello.eot?42893505#iefix') format('embedded-opentype'), - url('../font/fontello.svg?42893505#fontello') format('svg'); + src: url('../font/fontello.eot?81418204'); + src: url('../font/fontello.eot?81418204#iefix') format('embedded-opentype'), + url('../font/fontello.svg?81418204#fontello') format('svg'); font-weight: normal; font-style: normal; } @font-face { font-family: 'fontello'; - src: url('data:application/octet-stream;base64,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') format('woff'), - url('data:application/octet-stream;base64,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9BY2D0rSBQevBsboFx4B/lOPCggBiQgKCgj+dwgKAZsICgoI/ncICgoIAYkICgoI/ncICgoIAn4QNBj9fhceASAWA3wXHgEWECbSEQavB/ywAjwgFen8pgHjBwoKByQICgoIWQoIJAgKCggkCAqPCggkCAoKCCQICgAAAAABAAAAAQAA1KQuGV8PPPUACwPoAAAAANb5LeoAAAAA1vkt6v/9/2oELwNSAAAACAACAAAAAAAAAAEAAANS/2oAAAQv//3//wQvAAEAAAAAAAAAAAAAAAAAAAAHA+gAAAQv//8D6AAAA1kAAANZ//0D6AAAA1kAAAAAAAAAegFwAjIClgMYA8sAAQAAAAcAawAGAAAAAAACAB4ALgBzAAAAgwtwAAAAAAAAABIA3gABAAAAAAAAADUAAAABAAAAAAABAAgANQABAAAAAAACAAcAPQABAAAAAAADAAgARAABAAAAAAAEAAgATAABAAAAAAAFAAsAVAABAAAAAAAGAAgAXwABAAAAAAAKACsAZwABAAAAAAALABMAkgADAAEECQAAAGoApQADAAEECQABABABDwADAAEECQACAA4BHwADAAEECQADABABLQADAAEECQAEABABPQADAAEECQAFABYBTQADAAEECQAGABABYwADAAEECQAKAFYBcwADAAEECQALACYByUNvcHlyaWdodCAoQykgMjAxOCBieSBvcmlnaW5hbCBhdXRob3JzIEAgZm9udGVsbG8uY29tZm9udGVsbG9SZWd1bGFyZm9udGVsbG9mb250ZWxsb1ZlcnNpb24gMS4wZm9udGVsbG9HZW5lcmF0ZWQgYnkgc3ZnMnR0ZiBmcm9tIEZvbnRlbGxvIHByb2plY3QuaHR0cDovL2ZvbnRlbGxvLmNvbQBDAG8AcAB5AHIAaQBnAGgAdAAgACgAQwApACAAMgAwADEAOAAgAGIAeQAgAG8AcgBpAGcAaQBuAGEAbAAgAGEAdQB0AGgAbwByAHMAIABAACAAZgBvAG4AdABlAGwAbABvAC4AYwBvAG0AZgBvAG4AdABlAGwAbABvAFIAZQBnAHUAbABhAHIAZgBvAG4AdABlAGwAbABvAGYAbwBuAHQAZQBsAGwAbwBWAGUAcgBzAGkAbwBuACAAMQAuADAAZgBvAG4AdABlAGwAbABvAEcAZQBuAGUAcgBhAHQA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RiyxAAEUE7AyKi2wRyywNCotsEgssAAWRSMgLiBGiiNhOLErARQrLbBJLLAII0KwSCstsEossgAAQSstsEsssgABQSstsEwssgEAQSstsE0ssgEBQSstsE4ssgAAQistsE8ssgABQistsFAssgEAQistsFEssgEBQistsFIssgAAPistsFMssgABPistsFQssgEAPistsFUssgEBPistsFYssgAAQCstsFcssgABQCstsFgssgEAQCstsFkssgEBQCstsFossgAAQystsFsssgABQystsFwssgEAQystsF0ssgEBQystsF4ssgAAPystsF8ssgABPystsGAssgEAPystsGEssgEBPystsGIssDcrLrErARQrLbBjLLA3K7A7Ky2wZCywNyuwPCstsGUssAAWsDcrsD0rLbBmLLA4Ky6xKwEUKy2wZyywOCuwOystsGgssDgrsDwrLbBpLLA4K7A9Ky2waiywOSsusSsBFCstsGsssDkrsDsrLbBsLLA5K7A8Ky2wbSywOSuwPSstsG4ssDorLrErARQrLbBvLLA6K7A7Ky2wcCywOiuwPCstsHEssDorsD0rLbByLLMJBAIDRVghGyMhWUIrsAhlsAMkUHiwARUwLQBLuADIUlixAQGOWbABuQgACABjcLEABUKyAAEAKrEABUKzCgIBCCqxAAVCsw4AAQgqsQAGQroCwAABAAkqsQAHQroAQAABAAkqsQMARLEkAYhRWLBAiFixA2REsSYBiFFYugiAAAEEQIhjVFixAwBEWVlZWbMMAgEMKrgB/4WwBI2xAgBEAAA=') format('truetype'); + src: url('data:application/octet-stream;base64,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') format('woff'), + url('data:application/octet-stream;base64,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') format('truetype'); } /* Chrome hack: SVG is rendered more smooth in Windozze. 100% magic, uncomment if you need it. */ /* Note, that will break hinting! In other OS-es font will be not as sharp as it could be */ @@ -17,7 +17,7 @@ @media screen and (-webkit-min-device-pixel-ratio:0) { @font-face { font-family: 'fontello'; - src: url('../font/fontello.svg?42893505#fontello') format('svg'); + src: url('../font/fontello.svg?81418204#fontello') format('svg'); } } */ @@ -53,8 +53,9 @@ /* text-shadow: 1px 1px 1px rgba(127, 127, 127, 0.3); */ } .icon-picture:before { content: '\e800'; } /* '' */ -.icon-edit:before { content: '\e801'; } /* '' */ -.icon-cog:before { content: '\e802'; } /* '' */ -.icon-off:before { content: '\e803'; } /* '' */ +.icon-off:before { content: '\e801'; } /* '' */ +.icon-eye:before { content: '\e802'; } /* '' */ +.icon-cancel:before { content: '\e803'; } /* '' */ +.icon-cog:before { content: '\e804'; } /* '' */ .icon-link-ext:before { content: '\f08e'; } /* '' */ .icon-doc-text:before { content: '\f0f6'; } /* '' */ \ No newline at end of file diff --git a/system/author/css/fontello/css/fontello-ie7-codes.css b/system/author/css/fontello/css/fontello-ie7-codes.css index a914f26..fbaa5fc 100644 --- a/system/author/css/fontello/css/fontello-ie7-codes.css +++ b/system/author/css/fontello/css/fontello-ie7-codes.css @@ -1,7 +1,8 @@ .icon-picture { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } -.icon-edit { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } -.icon-cog { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } -.icon-off { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.icon-off { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.icon-eye { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.icon-cancel { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.icon-cog { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } .icon-link-ext { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } .icon-doc-text { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } \ No newline at end of file diff --git a/system/author/css/fontello/css/fontello-ie7.css b/system/author/css/fontello/css/fontello-ie7.css index 9d78c08..0dfa2dd 100644 --- a/system/author/css/fontello/css/fontello-ie7.css +++ b/system/author/css/fontello/css/fontello-ie7.css @@ -11,8 +11,9 @@ } .icon-picture { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } -.icon-edit { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } -.icon-cog { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } -.icon-off { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.icon-off { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.icon-eye { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.icon-cancel { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.icon-cog { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } .icon-link-ext { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } .icon-doc-text { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } \ No newline at end of file diff --git a/system/author/css/fontello/css/fontello.css b/system/author/css/fontello/css/fontello.css index 7a2d803..200733f 100644 --- a/system/author/css/fontello/css/fontello.css +++ b/system/author/css/fontello/css/fontello.css @@ -1,11 +1,11 @@ @font-face { font-family: 'fontello'; - src: url('../font/fontello.eot?58763890'); - src: url('../font/fontello.eot?58763890#iefix') format('embedded-opentype'), - url('../font/fontello.woff2?58763890') format('woff2'), - url('../font/fontello.woff?58763890') format('woff'), - url('../font/fontello.ttf?58763890') format('truetype'), - url('../font/fontello.svg?58763890#fontello') format('svg'); + src: url('../font/fontello.eot?88351620'); + src: url('../font/fontello.eot?88351620#iefix') format('embedded-opentype'), + url('../font/fontello.woff2?88351620') format('woff2'), + url('../font/fontello.woff?88351620') format('woff'), + url('../font/fontello.ttf?88351620') format('truetype'), + url('../font/fontello.svg?88351620#fontello') format('svg'); font-weight: normal; font-style: normal; } @@ -15,7 +15,7 @@ @media screen and (-webkit-min-device-pixel-ratio:0) { @font-face { font-family: 'fontello'; - src: url('../font/fontello.svg?58763890#fontello') format('svg'); + src: url('../font/fontello.svg?88351620#fontello') format('svg'); } } */ @@ -56,8 +56,9 @@ } .icon-picture:before { content: '\e800'; } /* '' */ -.icon-edit:before { content: '\e801'; } /* '' */ -.icon-cog:before { content: '\e802'; } /* '' */ -.icon-off:before { content: '\e803'; } /* '' */ +.icon-off:before { content: '\e801'; } /* '' */ +.icon-eye:before { content: '\e802'; } /* '' */ +.icon-cancel:before { content: '\e803'; } /* '' */ +.icon-cog:before { content: '\e804'; } /* '' */ .icon-link-ext:before { content: '\f08e'; } /* '' */ .icon-doc-text:before { content: '\f0f6'; } /* '' */ \ No newline at end of file diff --git a/system/author/css/fontello/demo.html b/system/author/css/fontello/demo.html index 4ea073a..7d42f88 100644 --- a/system/author/css/fontello/demo.html +++ b/system/author/css/fontello/demo.html @@ -229,11 +229,11 @@ body { } @font-face { font-family: 'fontello'; - src: url('./font/fontello.eot?16442487'); - src: url('./font/fontello.eot?16442487#iefix') format('embedded-opentype'), - url('./font/fontello.woff?16442487') format('woff'), - url('./font/fontello.ttf?16442487') format('truetype'), - url('./font/fontello.svg?16442487#fontello') format('svg'); + src: url('./font/fontello.eot?8909408'); + src: url('./font/fontello.eot?8909408#iefix') format('embedded-opentype'), + url('./font/fontello.woff?8909408') format('woff'), + url('./font/fontello.ttf?8909408') format('truetype'), + url('./font/fontello.svg?8909408#fontello') format('svg'); font-weight: normal; font-style: normal; } @@ -299,11 +299,12 @@ body {
icon-picture0xe800
-
icon-edit0xe801
-
icon-cog0xe802
-
icon-off0xe803
+
icon-off0xe801
+
icon-eye0xe802
+
icon-cancel0xe803
+
icon-cog0xe804
icon-link-ext0xf08e
icon-doc-text0xf0f6
diff --git a/system/author/css/fontello/font/fontello.eot b/system/author/css/fontello/font/fontello.eot index 7fb61fbf7764ff79fdc5c4226f2d5c00ec15aef3..cb48c5022b230ceb54cd4498aaefd38a300c3d2a 100644 GIT binary patch delta 904 zcmY*XTSyd982=YK50wG7&}7qL7M|G9tI#b=`7xQVTUr1qr(# z>SV=2krdK{Z~G8Y6um`Q_)yqILV{o)eK8DbrhhaaI>R^re3x_nnKS3H|CUco%>oEb zh<+h&YIbp=^7`P;FSq4urPWG~EG6X(r#-N`gGhr-|Pqp3@rZ z?m4;RtM!|N7bLjbI)VXtKy(pbB)&Bk=+SXks!Dv>_S*xo@Z9}uH#MiG?491x)%{>$ z?h(MICGyYdonie)RX(k?ebIP`r}4S*8xPgpB@YSfL!`n91q6W%{hxQ9R6A8bHDyf~ zpn|wU7i~dOFmAD|OwImW$}vg_Ac6!kQOS7COkp<)7=I*fwFs7*O5}(ra12c#;jk7VtnZ)K*rjj0tQL0%vs~FwO)Xqt1-O1!~Ix zFVIp8(VOeaa7w$ew8SsT+35CRiC6YW8BSM` zue8KhT;vm-vLp<;b8@{UeqR9!nJzxvFyxt>pY#kh99}}*k>QyWosVb|E+-Bp^>awbl&e2gkMA^^*RnyeHHQHQy`fxlxobGiF z#o2?aPJ180it;2s1}aF2eG0?Ed?OZQ+&&#jq9Rr0g$gp{D4>WE%JlsXko9P=`%-6^ceJ$daBo-&2HJz+ WHXiJV80~5M#3(;*MH91WtLk5|z0_p@ delta 1075 zcmbVLPfXKr6n?M2w!ed7M}#1o0pXo9P+2#FVCVwwIjb!@b z#MLN(gEZAh#zqa&o#cO{s3eEZ^k2Vl=q&&volg!VVtpm8x5g+}AwN7o0zc2Di0j0C z1L^GPuJvEcWfJ;G*f^Al$E2tH4e@ito$1(V12-3|#IF+f4#(1omp3ZC#AgA7S4L(u zd;iw@Bn@EYcN-%K<5OGxLx2t0{1l$R2l-_@bYPM^B>X-k3XIS|px40RRd0Y)E31KG z(TXlY3vq=`0br5kF9{ya4tCOz6h_q&$VBAZPXsI_xtIXZwQ>cJ^YbiFv2+>00_DQe zx8Ja;@;>ovjx_TJTVN_F4%iO6;2?5c(|7H3G66Y=A*4qgXhRYAAD%5b(xo>7XCmWb znuaGYu`&h|Pbx%Y3FTgp1VK6mk|cD2APF6w!?P;Y)ve}pwB}wd$o;LN{J);0H~l%B z2$=rIbUC3T8jb31fW7UlElpeNYAQYMGWsoKmrc^@{gGO(1vRX3pzPj_;WEu7S66MW zX)XzcBUOR&N+hGUh9sGnxZLGcfp9B^DACQzvAP*~Z6qAngl-ou>79BrYBt+bTPeZU z(_Uz7@9D|4<9v0cjd71sw63_&=nrAohx7iBj%yy diff --git a/system/author/css/fontello/font/fontello.svg b/system/author/css/fontello/font/fontello.svg index d20bd4d..e9617a8 100644 --- a/system/author/css/fontello/font/fontello.svg +++ b/system/author/css/fontello/font/fontello.svg @@ -8,11 +8,13 @@ - + - + - + + + diff --git a/system/author/css/fontello/font/fontello.ttf b/system/author/css/fontello/font/fontello.ttf index 330f324bd7dba3f567749afaf898d71ede151c64..2a98956034aa0360ac6d3344b818ef2f4fc3d536 100644 GIT binary patch delta 875 zcmY*XUr1A76hG(t?!Wb=-gM3)lsRP*YKhKC7NKaCBx0ggM&z1vE}h=YLQ7LYLJCA( zSqu^+kRE#5LqySIL>TmtNF^asut#4KgWT=hi4So(_nhDFcm8m`@B3T+(=(GhmfKtf zfK33<<`4UfkL!zP3BMrw;=euUR8~v|klH}Hv&#sEAI#2NBHRlgjG*tPLA*}5mb@11 z9q!6A6R!dI2!OKD9q@Ig*S60C?CT)i+f9Tz!50ZXC7j(;JR&8Sua85B@sI!i%YXEFsqjktNKD=t}mh?0SN>>B05=GLxJn!$fZR@4t;9Kig; z<7^ZTfD6i?uBt{bCQ(n|>r z=0S%lA1*|9fg{td9K~`^g`(!5(~BOr>QXZ8j#6*A$6HqFmF=n`jXCoR+@1<=5lUGO zzSuhMn)^KG8gD(fj?zZrl`iT!b%$PCB6R#J8WY=zZ;97#1e6_CgncH7PJB8TzmQW$knuyzd`W0bq}i} z5AW`IbH@xtN<`TS&C;Y}rpYgvJ64=Dddhp=s(?H21KaQpJIUVh8-%SVqs8Wh;Kdp; zF+nf> z9TePzcu^qn;K2itcvDYA4~jvfo;+egJdqd(B-nLYA@O2N%**V|_suu+W;e4d>UPbf zd&1Ru3;;U-;7m9c(v}+EKPCKx>~;8J!XG=KB3#3&j?;j+BUuUy~1B6QkV~I;Wc|VM8BKnEg zKN1gzq(%OL@HN8rSm=_5MHv>tlZ0KPp;+YI!vYuKc>rNai;pLs&E!RCfRz5MHWtyo zHI=^r*q4~vJcrNqE^NhV{Sh7rjslVdU=Ub3svvKsw;Tl#>WEk92mq^W?e5x!VNe9S zQMwK(Z>2*eq+?ViflNTw-NL3`C0J}3XIhyB=Q@-EmfvpW$P2f z8Cz_HS%|U0QD}hE$ODc*!*M$kkb|fq-F2!7MQmxCH+S>|s(>?*aWMuUQZAC7gNf%A z0}*7TmLpp(b{Cb_WUBsJw>PH% zDN$BRl*}`;ojGo=zaCW*I#~`D*B~#e^?M7^nT>0K?m!JXOr}NCUb2$j=44fKZ|`U` zE*BS=7|&PCdoq$$9u@s1xa?7-5+%2GE_r)Si2LSz_6mEq{bf^kQ=uR4@AgQ(8m11^ z;6yK4#VmQhA~Myp)1!q`2Lzz`k44;VV#c)u1}8>jy_x6 zI#}3hYGuA`9sa)Sji1J_e#`9h@l;McVi+mU=*MG0Ex!PajML8m diff --git a/system/author/css/fontello/font/fontello.woff b/system/author/css/fontello/font/fontello.woff index da8388acae50b38e10a535947d4f3350cc440812..63d34c0a2a351172c1e1ee726d704c4cfc015b45 100644 GIT binary patch delta 2080 zcmX|?dpy(oAIHDjFkv=Ext}R=Ns%VGZU`&)nM5UHM#Z*V7Se`;7>ej}a+hnJL~fM002q?85$HuXn+r;GJFF-<_7?RDF7hK z;H0Lw`I3XcUidm#Bm94%eEq|y|5`y001%qo$KQVL=R>9d0KyZj(FJu>^0@mQKM=A( zm<|FAC>3}VEYB|>I22@6pqJm_iX;3jf4VmrWIdpl+!6em;O+o&D0nbpYNuvLkbPpJ zG;)9s0Ei2KkGKL}w6h~i3B#ZV1p@#w0<5tE<(19tc)$qs0eg`hpigsv*g!hdG9ZW9 zhK~0nRN#Pklh_v^H1k{PVeuFpF#)xdeZo$ErCfboKclJX(QM>glpkCDdGpQC{dZs0 zIaQ)BBb{Da#s#O84_Dj0`pqpO=NF-S9&(Z9`{MfC1By`6Cp;gOdPHBIeS8!Cqz56X3yi;hVw`QTdb)zG~7{?w6Rn6*`m3 zTKvh1q0?xl)B9}IG6xzL;itdb(=!5sE$h50N*;dv-7~K7a=m?Is6(EgMV*=|rKO5v zVxWz_tZ3vVGL#m`k>I}06fAE2`g#4q^cpT_AP;89rQ0B)qtD$n>!E&H-S}pT9L2t1 zXEQHQLNo0Z{uo!~e|jw6p#^BKIVhbg<6J;l=n`Z}r>6p3daXV*jYlRMzAz zQemQ_P*QX3+iQ^uYDt1aBvXCkejYVYm3Pe8&gX)}%^9~ERf_N=Rjo7G`+XaQtlK!@%_5}I;syPmcB_| zntfnXJzQvQ-EAyy{pYzG5y92&?)SSU?-Rc*EBVEnn>VAZE;|-1dxQxd!nCW!cn2j4!M+_Nv^UB@w(Mx9wb&O>I*+^S} z11X=o>v(>RyH)K{q7N6FsN~0N%ZaOdN3T86*K0V=blq>SZM!%bbMt~awH8Naq`&6H z-EtN1WEEDdiI{ah!BqIiI)=}z7hk6q?}x*QpDId7f0`AjOG8!EliB^TW`zEP1jDuh zE1gDP6wzM!Go^qq5#N$*(JLFJMM>$)8keq3`*n7Y(0YO>aqb7QS_+ ztgCn5-5Yq~?Jro9LGARvY!lNrM}}dyFHk0tdj(Rpb5%eF|(nTn(8aa_FSy5Y2>^&hiFH$7(ocp!SFmbjbvu_i^_ z@2y=%MK6^ZIijMs+e}-o>03FLV1QZlP+HQeJH2N8C^6CHnVO#6hU@(zh<0CD(T~z$ z?NdbD9Q(1%%e?{-EMl#BkHk^(hFef)VuGdLrYfb>y)y)zFq}6$x@uZGZ=Y`SV2GvGn=$)l zP&1TV7=W^r9{VxYaWt$Z>5Eggy;fgho4JEZjb$JEXsNwf7>*hoEj*{M3{Fu8e!gwj3CrXsAS1&VJGts}1>VwSr!dd!_X{Ojg2S zYU5|ss3PC{8p1njcoG?2N6&j*725U2iY65q&q)7Y5L=P&a4S{q_`38_X1aA#0R z1DxutrvI(rf~NQl9r&X%)_eVcr%d7R;LHaj9N0C(`~w2ok3;|f delta 2064 zcmXYydpOhY8^=G}%$C!JVGh+~4yAHf4s&P@ne!o(l*$?sTbuLDmpLb?ERqsZQVuB* zIYuD~i7=^%uS1TNlEbv$$M^a@*Y&>c>;1Z)`+1)GpXcttHQ+E2&SWwG0l~} zfzQR5a&WFjR62zT01zI?Lc!SHP3kG5hKJ$+0O|lTX;3)f0fCSo^DG@?-T(kk2LMrK zDmUHpEF}c2MSKVMApbA)Sz4qY$X3C9{$R|?zF^zu?@RFk0CBJuAb`@BG|dn52O$T9 znIOP{!Xx5fcl_z0ERa=!UICPn{IY;gV^Ap|>jgb}OYm02dpd;$UMxNadfb*EyTnA# zQ|P_`AOTuP1o+VIuG}3sCL;uF3I(1C*nm3zG++KKGuRibMKyyy!x>@^>CDK1=x`KV zvL*2dK&)MC3}D?};I@b-;n0V6zEp3=YE~qkPEln&#mxQN@uswAKQF01(kC3LJPe63 z!<5>fC7?&^KaIus1e1OYnUo+jD)N5UF?OGtlnH(D&{3S7^UHEDeJx-mWX`SnvmUMg z{=~?_G2Q#rZyzct#RH}0F~HML+c9j`ZK}5!ObXqh^ot~#2$7<}K3ATF=D<0*M;vL2 zN6>kZFXo<69}B`WctJ5rkNfdqu2GH2tzo&XRp)F64mf_qyDOJ`aDm(5G3KZw(Fb{Z zl$~$|$(GJGbeM;sa!(2jQO=AN9dCwb8m4V`6S-mMA2Hfw!0^kP%3(~!85$X}cd4<^ zVku@Mhi1FzVy%{RYqa(!8IA~2_#0l@;WkVdn*ChdPQ|*-00P0jR737=(?u$Kn2Xe+ zpNUYjFE&Wfe1S6JE8#9xu^~9@I&YVHs{D7y<0Dt-2 z5b5-*CewaHFUD?#`2tG2#8AkN^;h$hIfT^M4C=3RTbag`T!HZN!?`zX`p0oGJtRt! zS1XTUtxUe28V`t;Iw0reHiPqDQe#@gUvf;4wY$rf!Bd0f3w=tP@h5B=`Gz*(>PG8{ zL(Af~1z|3mA1c+LobM|k^ufWwS$#9=V(4%8uZcOf!$B4ns!&~GR_VWCPcsi0#CIM{ zh%ve8;@N4xW~k*Pd`@M_&-h!2M)ZUCDponh+57JGc<|4VK5pYbYI4=0>Y`VT(DxWD zYB`ZuQ=xNV)Q@jjvt*eA<{xUR&M=S;W?dq%<;K=LUZs2L6fj~Fy?#B zr74e**AjjP+Iz?M(2BD$kcPsSD^xgDu`PMJyf)cWQJ#wZUtAK5wSi%%tePX>y)1 zhFm{0jZ})aY5tRv&_q>>&d0rk z%T_sNAxPr~6Al@;1RDEWk5qkKluUneldtfEiXBtp``o(JB z8YS$KKCBhHm(Nez9WQGCK04|9hZ40(qd$8idDT^L`_4qlnM2$0e^*uerYj!!hB@aH zoo`yMy5m6QX}_rHZ&B<<-B+Ep`>JRVACBGFwatsiIc`gDeBfKf$X5H?%h$Q)t*q-_ z;#5oH$QRKALX5qgXGUIt|QB zY+uevETDqb)_;W+auar}GZHF?p7B4J==yTc_V@5_z1oh>U6@Jx^?q z+pxR-qFQInp_R15L3rZ`auY1iGWSwv*JW!?C4Mi8Jn^g ztxcX+c=97+oLy4~*(K@K=|HD_!dtUn(0GU;X*GfA!@0 zaMs32chf$^RnIWo+S?XOe#Q0TuUS8jEAm&Eg8bcl_!2`sWa}gL@%9GBHSK@lC)POh zCS4}s1(2%kwNbnwLKX-%NSCbgiO7ygZ*S;DC=jbCp#YAI|B58m^V^!6?+OG<0>R#O zF*8X_vjmVeAglrAV_N>pkO=91SA@O_I20NXor;8kV`yu!Axx+)Gz*4>y#*kkM*x9< z@K&Por+6BKO!Yn!3+xx3kIm&?~5lpD#^1(r~~W<(1{g)lhK9x=YROkhEf0k diff --git a/system/author/css/fontello/font/fontello.woff2 b/system/author/css/fontello/font/fontello.woff2 index 09b5a1b9f4b97ffd71cfc5ae47f52ece532ebc1c..255cbd3515e73bb8b1a659b655754a15a3b58bad 100644 GIT binary patch literal 3428 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 G27|NXV|X?I literal 3428 zcmV-q4V&_JPew8T0RR9101adS4*&oF02=%N01XQO0RR9100000000000000000000 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 { this.$el.setAttribute('style', 'height:' + (this.$el.scrollHeight) + 'px;overflow-y:hidden;') }) - this.$el.addEventListener('input', this.resizeTextarea) }, beforeDestroy () { @@ -24,29 +23,81 @@ let app = new Vue({ delimiters: ['${', '}'], el: '#editor', data: { + root: document.getElementById("main").dataset.url, form: { - title: document.getElementById("origTitle").value, - content: document.getElementById("origContent").value, + title: this.title = document.getElementById("title").value, + content: this.title = document.getElementById("content").value, url: document.getElementById("path").value, csrf_name: document.getElementById("csrf_name").value, csrf_value: document.getElementById("csrf_value").value, }, - root: document.getElementById("main").dataset.url, errors:{ title: false, content: false, message: false, }, - bdisabled: false, - bresult: false, + modalWindow: "modal hide", + draftDisabled: true, + publishDisabled: document.getElementById("publishController").dataset.drafted ? false : true, + deleteDisabled: false, + draftResult: "", + publishResult: "", + deleteResult: "", + publishStatus: document.getElementById("publishController").dataset.published ? false : true, + publishLabel: document.getElementById("publishController").dataset.published ? "online" : "offline", }, methods: { - saveMarkdown: function(e){ + submit: function(e){ + /* count submits and react to line before. */ + }, + changeContent: function(e){ + this.draftDisabled = false; + this.publishDisabled = false; + this.draftResult = ""; + this.publishResult = ""; + }, + publishDraft: function(e){ + var self = this; + self.errors = {title: false, content: false, message: false}; + + self.publishResult = "load"; + self.publishDisabled = "disabled"; + + var url = this.root + '/api/v1/article/publish'; + var method = 'POST'; + + sendJson(function(response, httpStatus) + { + if(response) + { + var result = JSON.parse(response); + + if(result.errors) + { + self.publishDisabled = false; + self.publishResult = "fail"; + + if(result.errors.title){ self.errors.title = result.errors.title[0] }; + if(result.errors.content){ self.errors.content = result.errors.content[0] }; + if(result.errors.message){ self.errors.message = result.errors.message }; + } + else + { + self.draftDisabled = "disabled"; + self.publishResult = "success"; + self.publishStatus = false; + self.publishLabel = "online"; + } + } + }, method, url, this.form ); + }, + saveDraft: function(e){ var self = this; - self.errors = {title: false, content: false, message: false}, - self.bresult = ''; - self.bdisabled = "disabled"; + self.errors = {title: false, content: false, message: false}; + + self.draftDisabled = "disabled"; + self.draftResult = "load"; var url = this.root + '/api/v1/article'; var method = 'PUT'; @@ -54,24 +105,88 @@ let app = new Vue({ sendJson(function(response, httpStatus) { if(response) - { - self.bdisabled = false; - + { var result = JSON.parse(response); if(result.errors) { - self.bresult = 'fail'; + self.draftDisabled = false; + self.draftResult = 'fail'; if(result.errors.title){ self.errors.title = result.errors.title[0] }; if(result.errors.content){ self.errors.content = result.errors.content[0] }; if(result.errors.message){ self.errors.message = result.errors.message }; } else { - self.bresult = 'success'; + self.draftResult = 'success'; } } }, method, url, this.form ); - } + }, + depublishArticle: function(e){ + + var self = this; + self.errors = {title: false, content: false, message: false}; + + self.publishStatus = "disabled"; + + var url = this.root + '/api/v1/article/unpublish'; + var method = 'DELETE'; + + sendJson(function(response, httpStatus) + { + if(response) + { + var result = JSON.parse(response); + + if(result.errors) + { + self.publishStatus = false; + if(result.errors.message){ self.errors.message = result.errors.message }; + } + else + { + self.publishResult = ""; + self.publishLabel = "offline"; + self.publishDisabled = false; + } + } + }, method, url, this.form ); + }, + deleteArticle: function(e){ + var self = this; + self.errors = {title: false, content: false, message: false}; + + self.deleteDisabled = "disabled"; + self.deleteResult = "load"; + + var url = this.root + '/api/v1/article'; + var method = 'DELETE'; + + sendJson(function(response, httpStatus) + { + if(response) + { + var result = JSON.parse(response); + + if(result.errors) + { + self.modalWindow = "modal"; + if(result.errors.message){ self.errors.message = result.errors.message }; + } + else + { + self.modalWindow = "modal"; + window.location.replace(self.root + '/tm/content'); + } + } + }, method, url, this.form ); + }, + showModal: function(e){ + this.modalWindow = "modal show"; + }, + hideModal: function(e){ + this.modalWindow = "modal"; + }, } }) \ No newline at end of file