diff --git a/.gitignore b/.gitignore index cba61dd..6ffb0eb 100644 --- a/.gitignore +++ b/.gitignore @@ -16,7 +16,7 @@ settings/settings.yaml settings/formdata.yaml settings/users system/vendor +themes/learn tests -themes/monograf zips build.php \ No newline at end of file diff --git a/cache/lastCache.txt b/cache/lastCache.txt index ad04c68..be5ff7d 100644 --- a/cache/lastCache.txt +++ b/cache/lastCache.txt @@ -1 +1 @@ -1573496522 \ No newline at end of file +1574576173 \ No newline at end of file diff --git a/content/00-Welcome/00-Setup.md b/content/00-Welcome/00-Setup.md index 8ea6b5e..f30d915 100644 --- a/content/00-Welcome/00-Setup.md +++ b/content/00-Welcome/00-Setup.md @@ -1,6 +1,8 @@ -# Setup the System +# Setup -Typemil is a flat file cms that runs out of the box without a complicated installation process. You can create a user account with the [simple setup page](/setup) and then login to the author panel. In the author panel, you can configure your website, use plugins, choose a theme and edit your content. +Congratulations! If you see this page, then the setup of the system has worked successfully!! You can now setup and configure your system, your themes and your plugins in the [settings-area](/tm/settings). + +Anyway, if you read this file in the source code and if you did not manage to setup the system successfully, then try the following. ## If it does not work diff --git a/content/00-Welcome/01-Write-Content.md b/content/00-Welcome/01-Write-Content.md index 7ff21b7..0f24144 100644 --- a/content/00-Welcome/01-Write-Content.md +++ b/content/00-Welcome/01-Write-Content.md @@ -1,30 +1,41 @@ # Write Content -Typemill is a simple Flat File Content Management System (CMS). We work hard to provide the best author experience with easy and intuitive authoring tools. But Typemill is still in early development and it is likely that not everything will work perfectly out of the box. If you miss something or if you have ideas for improvement, then let me know via [GitHub](https://github.com/typemill/typemill/issues). +Typemill is a simple Flat File Content Management System (CMS). We (the community) work hard to provide the best author experience with easy and intuitive authoring tools. But Typemill is still in early development and it is likely that not everything will work perfectly out of the box. If you miss something or if you have ideas for improvements, then post a new issue on [GitHub](https://github.com/typemill/typemill/issues). ## The Navigation You can create, structure and reorder all pages with the navigation on the left. To structure your content, you can create new folders and files with the "add item" button. To reorder the pages, just drag an item and drop it wherever you want. Play around with it and you will notice, that it works pretty similar to the folder- and file-system of your laptop. And in fact, this is exactly what Typemill does in the background: It stores your content in files and folders on the server. -However, there are some limitations when you try to reorder elements, for example, you cannot move a complete folder to another folder. Click on the question-mark at the top of the navigation for detailed informations. +However, there are some limitations when you try to reorder elements. For example, you cannot move a complete folder to another folder. Click on the question-mark at the top of the navigation for detailed information. ## The Editor -You can create and format your content with the Markdown syntax, that is similar to the markup syntax of wikipedia. If you are not familiar with Markdown, then please read the short [Markdown-tutorial](https://typemill.net/) in the documentation of Typemill. You can learn Markdown in less than 10 minutes and there is no easier and faster way to format your webpage. You will love it! +You can create and format your content with the Markdown syntax, that is similar to the markup syntax of Wikipedia. If you are not familiar with Markdown, then please read the short [Markdown-tutorial](https://typemill.net/) in the documentation of Typemill. You can learn Markdown in less than 10 minutes and there is no easier and faster way to format your webpage. You will love it! -Typemill provides two edit modes: The **raw mode** and the **visual mode**. You can switch between the modes in the publish-bar at the bottom of each page. The **raw mode** is the most robust way to create your content, because you write raw markdown into a simple textarea. The **visual mode** is experimental right now. It uses blocks and transforms each content block into a html-preview immediately, so that you can directly see the formatted result. +Typemill provides two edit modes: The **raw mode** and the **visual mode**. You can switch between the modes in the publish-bar at the bottom of each page. The **raw mode** is the most robust way to create your content, because you write raw markdown into a simple textarea. The **visual mode** uses blocks and transforms each content block into a html-preview immediately. This means that you can directly see and check the formatted result. -By default Typemill will use the raw mode. But you can change this behavior in the system settings and use the visual editor as default mode. +By default Typemill will use the **visual mode**. + +* You can change the default mode in the system settings. +* You can also switch each format button on and off in the system settings. ## The Publish Bar The publish bar of Typemill is pretty intuitiv and sticks at the bottom of the screen so that you have always full control of the status of each page. Simply play around with it and you will quickly understand how it works. In short: * The green button "online" indicates, that your page is published and visible for your readers. -* You can depublish a page by clicking the green button. The button turns grey with the label "offline" then. -* With the red button "Publish" you can publish either a page that is offline or you can publish still unpublished changes. +* You can depublish a page by clicking the green "online" button. The button turns grey with the label "offline" then. +* With the green button "Publish" you can either publish a page that is offline or you can publish some unpublished changes of the page. * The publish-button is grey, if the page is online and if there are no unpublished changes. -* With the red button "Save Draft" you can safe a draft. You can also work on a draft as long as you want while the old version of the page is still online. * All buttons will change in real time, so you can always exactly see what is going on. -* To provide an easy status-overview of the whole website, Typemill marks all unpublished pages or changes red in the navigation on the left side. +* To provide an easy status-overview of the whole website, Typemill marks all pages in the navigation on the left side as published (green), changed (orange) and unpublished (red). + +## Working with Drafts + +Ever tried to revise a published article in WordPress? Yes, it works, but if you click on "save", then all your changes are directly live. Typemill is much more flexible here and allows you to keep your original version live while you work on a **drafted Version** in the background. This is how Typemill handles it: + +* In **visual mode**: Typemill stores your changes in a new draft automatically as soon as you save any content-block. +* In **raw mode**: To store changes in a new draft, simply click on the "save draft"-button in the publish controller. +* You can work on a draft as long as you want without changing the live version. Your changes go live if you click the button "publish". +* In visual mode, you can also use the discard-button and go back to the published version. diff --git a/content/00-Welcome/02-Get-Help.md b/content/00-Welcome/02-Get-Help.md index c0cfedd..bacbf31 100644 --- a/content/00-Welcome/02-Get-Help.md +++ b/content/00-Welcome/02-Get-Help.md @@ -4,7 +4,7 @@ If you need any help, then please read the [documentation on typemill.net](https If you found a bug or if you have a question, then please open a new issue on [GitHub](https://github.com/typemill/typemill/issues). -Typemill is open source and a one man project right now, so please understand that I cannot provide individual support. +Typemill is open source and mostly a one man project right now, so please understand that I cannot provide individual support. Contributions, donations and feedbacks are always welcome. diff --git a/content/00-Welcome/index.md b/content/00-Welcome/index.md index d855f77..9509085 100644 --- a/content/00-Welcome/index.md +++ b/content/00-Welcome/index.md @@ -1,3 +1,4 @@ -# Welcome to Typemill - -Great that you give Typemill a try!! Typemill is a small open source cms and a project in work. You will probably miss some important features, but I am working hard to add everything that is needed for a handy and productive writing-system. \ No newline at end of file +# Welcome + +Great that you give Typemill a try!! Typemill is a small open source cms and a project in work. You will probably miss some important features, but I am working hard to add everything that is needed for a handy and productive writing-system. + diff --git a/plugins/math/math.php b/plugins/math/math.php index c075823..288f60c 100644 --- a/plugins/math/math.php +++ b/plugins/math/math.php @@ -33,7 +33,7 @@ class Math extends Plugin if($mathSettings['tool'] == 'katex') { - $this->addJS('/math/public/katex.min.js'); + $this->addJS('/math/public/katex.min.js'); $this->addJS('/math/public/auto-render.min.js'); $this->addCSS('/math/public/katex.min.css'); @@ -43,5 +43,14 @@ class Math extends Plugin $this->addInlineJs('renderMathInElement(document.body);'); } } + + # add math to the blox editor configuration + + $this->addEditorJS('/math/public/math.js'); + $this->addSvgSymbol(' + omega + + '); } + } \ No newline at end of file diff --git a/plugins/math/math.yaml b/plugins/math/math.yaml index 70e56be..409503e 100644 --- a/plugins/math/math.yaml +++ b/plugins/math/math.yaml @@ -1,5 +1,5 @@ name: Math -version: 1.0.2 +version: 1.1.0 description: Adds support for katex and mathjax. author: Sebastian Schürmanns homepage: https://mathjax.org/ diff --git a/plugins/math/public/math.js b/plugins/math/public/math.js new file mode 100644 index 0000000..8972069 --- /dev/null +++ b/plugins/math/public/math.js @@ -0,0 +1,54 @@ +determiner.math = function(block,lines,firstChar,secondChar,thirdChar){ + if( (firstChar == '\\' && secondChar == '[') || (firstChar == '$' && secondChar == '$') ) + { + return "math-component"; + } + return false; +}; + +bloxFormats.math = { label: '', title: 'Math', component: 'math-component' }; + +formatConfig.push('math'); + +const mathComponent = Vue.component('math-component', { + props: ['compmarkdown', 'disabled'], + template: '
' + + '' + + '
' + + '' + + '
', + data: function(){ + return { + mathblock: '' + } + }, + mounted: function(){ + this.$refs.markdown.focus(); + if(this.compmarkdown) + { + var dollarMath = new RegExp(/^\$\$[\S\s]+\$\$$/m); + var bracketMath = new RegExp(/^\\\[[\S\s]+\\\]$/m); + + if(dollarMath.test(this.compmarkdown) || bracketMath.test(this.compmarkdown)) + { + var mathExpression = this.compmarkdown.substring(2,this.compmarkdown.length-2); + this.mathblock = mathExpression.trim(); + } + } + this.$nextTick(function () { + autosize(document.querySelectorAll('textarea')); + }); + }, + methods: { + createmarkdown: function(event) + { + this.codeblock = event.target.value; + var codeblock = '$$\n' + event.target.value + '\n$$'; + this.updatemarkdown(codeblock); + }, + updatemarkdown: function(codeblock) + { + this.$emit('updatedMarkdown', codeblock); + }, + }, +}) \ No newline at end of file diff --git a/readme.md b/readme.md index 7bc99a5..d671469 100644 --- a/readme.md +++ b/readme.md @@ -1,4 +1,4 @@ - # About TYPEMILL +# About TYPEMILL TYPEMILL is a small flat file cms created for editors and writers. It provides a author-friendly dashboard and a visual-block-editor for markdown based on vue.js. Use TYPEMILL for manuals, documentations, web-books and similar publications. The website http://typemill.net itself is an example for TYPEMILL. @@ -83,7 +83,11 @@ TYPEMILL is published under MIT licence. Please check the licence of the include ## How to Contribute -Typemill is still in an early stage and contributions are highly welcome. Here are some ideas for non-coder: +Typemill is still in an early stage and contributions are highly welcome. + +You can check the [roadmap for Typemill](https://github.com/typemill/typemill/issues/35) and scroll through the issues. I will mark issues in future that are easy to start with or where help is highly appreciated. + +Here are some contribution-ideas for non-coder: * Find bugs and errors (open a new issue on github for it). * Improve the documentation. @@ -93,12 +97,11 @@ Typemill is still in an early stage and contributions are highly welcome. Here a Some ideas for devs (please fork this repository make your changes and create a pull request): * Fix a bug. -* Create a theme. -* Create a plugin. -* Auto-update functionality for core system, plugins and themes. -* Create a plugin and theme download page. +* Create or port a theme, especially for documentations, knowlegde bases or web-books. +* Create a fancy plugin. +* An auto-update functionality for core system, plugins and themes is highly needed. * Improve the accessibility of html and css. -* Implement an ACL for user roles and rights. +* Implement user roles and rights with RBAC or ACL. For hints, questions, problems and support, please open up a new issue on GitHub. @@ -107,3 +110,7 @@ For hints, questions, problems and support, please open up a new issue on GitHub This is an open source project. I love it and I spend about 20 hours a week on it (starting in 2017). There is no business model right now, but you can support this project with a donation or simply hire me for implementations. Donate: https://www.paypal.me/typemill + +## Follow + +Twitter: https://twitter.com/typemill \ No newline at end of file diff --git a/system/Assets.php b/system/Assets.php index 0e3cccb..09f5512 100644 --- a/system/Assets.php +++ b/system/Assets.php @@ -8,11 +8,14 @@ class Assets public function __construct($baseUrl) { - $this->baseUrl = $baseUrl; - $this->JS = array(); - $this->CSS = array(); - $this->inlineJS = array(); - $this->inlineCSS = array(); + $this->baseUrl = $baseUrl; + $this->JS = array(); + $this->CSS = array(); + $this->inlineJS = array(); + $this->inlineCSS = array(); + $this->editorJS = array(); + $this->editorInlineJS = array(); + $this->svgSymbols = array(); } public function addCSS($CSS) @@ -75,6 +78,11 @@ class Assets } } + public function addSvgSymbol($symbol) + { + $this->svgSymbols[] = $symbol; + } + public function renderCSS() { return implode('', $this->CSS) . implode('', $this->inlineCSS); @@ -85,6 +93,32 @@ class Assets return implode('', $this->JS) . implode('', $this->inlineJS); } + public function renderSvg() + { + return implode('', $this->svgSymbols); + } + + # add JS to enhance the blox-editor in author area + public function addEditorJS($JS) + { + $JSfile = $this->getFileUrl($JS); + + if($JSfile) + { + $this->editorJS[] = ''; + } + } + + public function addEditorInlineJS($JS) + { + $this->editorInlineJS[] = ''; + } + + public function renderEditorJS() + { + return implode('', $this->editorJS) . implode('', $this->editorInlineJS); + } + /** * Checks, if a string is a valid internal or external ressource like js-file or css-file * @params $path string diff --git a/system/Controllers/AuthController.php b/system/Controllers/AuthController.php index c0b5e1b..b5fa700 100644 --- a/system/Controllers/AuthController.php +++ b/system/Controllers/AuthController.php @@ -11,7 +11,7 @@ use Typemill\Models\WriteYaml; class AuthController extends Controller { - + # redirect if visit /setup route public function redirect(Request $request, Response $response) { if(isset($_SESSION['login'])) @@ -23,6 +23,7 @@ class AuthController extends Controller return $response->withRedirect($this->c->router->pathFor('auth.show')); } } + /** * show login form @@ -125,7 +126,10 @@ class AuthController extends Controller $yaml->updateYaml('settings/users', '.logins', $logins); } - return $response->withRedirect($this->c->router->pathFor('content.raw')); + $settings = $this->c->get('settings'); + $editor = (isset($settings['editor']) && $settings['editor'] == 'visual') ? 'visual' : 'raw'; + + return $response->withRedirect($this->c->router->pathFor('content.' . $editor)); } } diff --git a/system/Controllers/ContentApiController.php b/system/Controllers/ContentApiController.php index b68d2e2..70c7e48 100644 --- a/system/Controllers/ContentApiController.php +++ b/system/Controllers/ContentApiController.php @@ -180,7 +180,12 @@ class ContentApiController extends ContentController $delete = $this->deleteContentFiles(['txt']); # set redirect url to edit page - $url = $this->uri->getBaseUrl() . '/tm/content/' . $this->settings['editor'] . $this->item->urlRelWoF; + + $url = $this->uri->getBaseUrl() . '/tm/content/' . $this->settings['editor']; + if(isset($this->item->urlRelWoF)) + { + $url = $url . $this->item->urlRelWoF; + } # remove the unpublished changes $delete = $this->deleteContentFiles(['txt']); diff --git a/system/Controllers/PageController.php b/system/Controllers/PageController.php index e7504a3..a76d39c 100644 --- a/system/Controllers/PageController.php +++ b/system/Controllers/PageController.php @@ -174,9 +174,22 @@ class PageController extends Controller } } - $route = empty($args) && $settings['startpage'] ? '/cover.twig' : '/index.twig'; - return $this->render($response, $route, array('navigation' => $structure, 'content' => $contentHTML, 'item' => $item, 'breadcrumb' => $breadcrumb, 'settings' => $settings, 'title' => $title, 'description' => $description, 'base_url' => $base_url, 'image' => $firstImage )); + $home = empty($args) ? true : false; + $theme = $settings['theme']; + $route = empty($args) && isset($settings['themes'][$theme]['cover']) ? '/cover.twig' : '/index.twig'; + + return $this->render($response, $route, [ + 'home' => $home, + 'navigation' => $structure, + 'content' => $contentHTML, + 'item' => $item, + 'breadcrumb' => $breadcrumb, + 'settings' => $settings, + 'title' => $title, + 'description' => $description, + 'base_url' => $base_url, + 'image' => $firstImage ]); } protected function getCachedStructure($cache) diff --git a/system/Controllers/SettingsController.php b/system/Controllers/SettingsController.php index 214bc83..d09a334 100644 --- a/system/Controllers/SettingsController.php +++ b/system/Controllers/SettingsController.php @@ -15,15 +15,16 @@ class SettingsController extends Controller public function showSettings($request, $response, $args) { - $user = new User(); - $settings = $this->c->get('settings'); - $copyright = $this->getCopyright(); - $languages = $this->getLanguages(); - $locale = isset($_SERVER['HTTP_ACCEPT_LANGUAGE']) ? substr($_SERVER["HTTP_ACCEPT_LANGUAGE"],0,2) : 'en'; - $users = $user->getUsers(); - $route = $request->getAttribute('route'); + $user = new User(); + $settings = $this->c->get('settings'); + $defaultSettings = \Typemill\Settings::getDefaultSettings(); + $copyright = $this->getCopyright(); + $languages = $this->getLanguages(); + $locale = isset($_SERVER['HTTP_ACCEPT_LANGUAGE']) ? substr($_SERVER["HTTP_ACCEPT_LANGUAGE"],0,2) : 'en'; + $users = $user->getUsers(); + $route = $request->getAttribute('route'); - return $this->render($response, 'settings/system.twig', array('settings' => $settings, 'copyright' => $copyright, 'languages' => $languages, 'locale' => $locale, 'users' => $users, 'route' => $route->getName() )); + return $this->render($response, 'settings/system.twig', array('settings' => $settings, 'copyright' => $copyright, 'languages' => $languages, 'locale' => $locale, 'formats' => $defaultSettings['formats'] ,'users' => $users, 'route' => $route->getName() )); } public function saveSettings($request, $response, $args) @@ -41,10 +42,11 @@ class SettingsController extends Controller return $response->withRedirect($this->c->router->pathFor('settings.show')); } - $settings = \Typemill\Settings::getUserSettings(); - $params = $request->getParams(); - $newSettings = isset($params['settings']) ? $params['settings'] : false; - $validate = new Validation(); + $settings = \Typemill\Settings::getUserSettings(); + $defaultSettings = \Typemill\Settings::getDefaultSettings(); + $params = $request->getParams(); + $newSettings = isset($params['settings']) ? $params['settings'] : false; + $validate = new Validation(); if($newSettings) { @@ -55,13 +57,13 @@ class SettingsController extends Controller 'copyright' => $newSettings['copyright'], 'year' => $newSettings['year'], 'language' => $newSettings['language'], - 'startpage' => isset($newSettings['startpage']) ? true : false, 'editor' => $newSettings['editor'], + 'formats' => $newSettings['formats'], ); $copyright = $this->getCopyright(); - $validate->settings($newSettings, $copyright, 'settings'); + $validate->settings($newSettings, $copyright, $defaultSettings['formats'], 'settings'); } else { diff --git a/system/Middleware/RedirectIfAuthenticated.php b/system/Middleware/RedirectIfAuthenticated.php index f7bdfe1..eb57205 100644 --- a/system/Middleware/RedirectIfAuthenticated.php +++ b/system/Middleware/RedirectIfAuthenticated.php @@ -10,16 +10,19 @@ class RedirectIfAuthenticated { protected $router; - public function __construct(RouterInterface $router) + public function __construct(RouterInterface $router, $settings) { $this->router = $router; + $this->settings = $settings; } public function __invoke(Request $request, Response $response, $next) { + $editor = (isset($this->settings['editor']) && $this->settings['editor'] == 'visual') ? 'visual' : 'raw'; + if(isset($_SESSION['login'])) { - $response = $response->withRedirect($this->router->pathFor('content.raw')); + $response = $response->withRedirect($this->router->pathFor('content.' . $editor)); } return $next($request, $response); diff --git a/system/Models/Validation.php b/system/Models/Validation.php index d6a76a2..d578bd9 100644 --- a/system/Models/Validation.php +++ b/system/Models/Validation.php @@ -20,6 +20,13 @@ class Validation Validator::langDir(__DIR__.'/../vendor/vlucas/valitron/lang'); // always set langDir before lang. Validator::lang('en'); + Validator::addRule('values_allowed', function($field, $value, array $params, array $fields) use ($user) + { + $badvalues = array_diff($value, $params[0]); + if(empty($badvalues)){ return true; } + return false; + }, 'invalid values'); + Validator::addRule('userAvailable', function($field, $value, array $params, array $fields) use ($user) { $userdata = $user->getUser($value); @@ -41,20 +48,6 @@ class Validation return false; }, 'wrong password'); - Validator::addRule('emailAvailable', function($field, $value, array $params, array $fields) - { - $email = 'testmail@gmail.com'; - if($email){ return false; } - return true; - }, 'taken'); - - Validator::addRule('emailKnown', function($field, $value, array $params, array $fields) - { - $email = 'testmail@gmail.com'; - if(!$email){ return false; } - return true; - }, 'unknown'); - Validator::addRule('noSpecialChars', function($field, $value, array $params, array $fields) { $format = '/[!@#$%^&*()_+=\[\]{};\':"\\|,.<>\/?]/'; @@ -183,7 +176,7 @@ class Validation * @return obj $v the validation object passed to a result method. */ - public function settings(array $params, array $copyright, $name = false) + public function settings(array $params, array $copyright, array $formats, $name = false) { $v = new Validator($params); @@ -195,8 +188,9 @@ class Validation $v->rule('integer', 'year'); $v->rule('length', 'year', 4); $v->rule('in', 'editor', ['raw', 'visual']); + $v->rule('values_allowed', 'formats', $formats); $v->rule('in', 'copyright', $copyright); - + return $this->validationResult($v, $name); } diff --git a/system/Plugin.php b/system/Plugin.php index 1ff598e..a182480 100644 --- a/system/Plugin.php +++ b/system/Plugin.php @@ -15,7 +15,7 @@ abstract class Plugin implements EventSubscriberInterface * Constructor * */ - + public function __construct($container) { $this->container = $container; @@ -97,16 +97,31 @@ abstract class Plugin implements EventSubscriberInterface $function = new \Twig_SimpleFunction($name, $function); $this->container->view->getEnvironment()->addFunction($function); } - + protected function addJS($JS) { $this->container->assets->addJS($JS); } + protected function addEditorJS($JS) + { + $this->container->assets->addEditorJS($JS); + } + protected function addInlineJS($JS) { $this->container->assets->addInlineJS($JS); } + + protected function addSvgSymbol($symbol) + { + $this->container->assets->addSvgSymbol($symbol); + } + + protected function addEditorInlineJS($JS) + { + $this->container->assets->addEditorInlineJS($JS); + } protected function addCSS($CSS) { diff --git a/system/Routes/Web.php b/system/Routes/Web.php index 46c7cf2..133e5dd 100644 --- a/system/Routes/Web.php +++ b/system/Routes/Web.php @@ -31,8 +31,8 @@ else $app->post('/tm/formpost', FormController::class . ':savePublicForm')->setName('form.save'); $app->get('/tm', AuthController::class . ':redirect'); -$app->get('/tm/login', AuthController::class . ':show')->setName('auth.show')->add(new RedirectIfAuthenticated($container['router'])); -$app->post('/tm/login', AuthController::class . ':login')->setName('auth.login')->add(new RedirectIfAuthenticated($container['router'])); +$app->get('/tm/login', AuthController::class . ':show')->setName('auth.show')->add(new RedirectIfAuthenticated($container['router'], $container['settings'])); +$app->post('/tm/login', AuthController::class . ':login')->setName('auth.login')->add(new RedirectIfAuthenticated($container['router'], $container['settings'])); $app->get('/tm/logout', AuthController::class . ':logout')->setName('auth.logout')->add(new RedirectIfUnauthenticated($container['router'], $container['flash'])); $app->get('/tm/settings', SettingsController::class . ':showSettings')->setName('settings.show')->add(new RedirectIfNoAdmin($container['router'], $container['flash'])); diff --git a/system/Settings.php b/system/Settings.php index 4007906..8fe26dc 100644 --- a/system/Settings.php +++ b/system/Settings.php @@ -15,7 +15,17 @@ class Settings { $settings = array_merge($defaultSettings, $userSettings); } - + + # We know the used theme now so create the theme path + $settings['themePath'] = $settings['rootPath'] . $settings['themeFolder'] . DIRECTORY_SEPARATOR . $settings['theme']; + + # if there are no theme settings yet (e.g. no setup yet) use default theme settings + if(!isset($settings['themes'])) + { + $themeSettings = self::getObjectSettings('themes', $settings['theme']); + $settings['themes'][$settings['theme']] = isset($themeSettings['settings']) ? $themeSettings['settings'] : false; + } + return array('settings' => $settings); } @@ -32,14 +42,15 @@ class Settings 'language' => 'en', 'startpage' => true, 'rootPath' => $rootPath, - 'theme' => ($theme = 'typemill'), - 'themeFolder' => ($themeFolder = 'themes'), + 'theme' => 'typemill', + 'themeFolder' => 'themes', 'themeBasePath' => $rootPath, - 'themePath' => $rootPath . $themeFolder . DIRECTORY_SEPARATOR . $theme, + 'themePath' => '', 'settingsPath' => $rootPath . 'settings', 'userPath' => $rootPath . 'settings' . DIRECTORY_SEPARATOR . 'users', 'authorPath' => __DIR__ . DIRECTORY_SEPARATOR . 'author' . DIRECTORY_SEPARATOR, - 'editor' => 'raw', + 'editor' => 'visual', + 'formats' => ['markdown', 'headline', 'ulist', 'olist', 'table', 'quote', 'image', 'video', 'toc', 'hr', 'definition', 'code'], 'contentFolder' => 'content', 'cache' => true, 'cachePath' => $rootPath . 'cache', @@ -99,6 +110,7 @@ class Settings 'year' => false, 'theme' => false, 'editor' => false, + 'formats' => false, 'setup' => false, 'welcome' => false, 'images' => false, diff --git a/system/author/auth/login.twig b/system/author/auth/login.twig index 517b9fb..10e618b 100644 --- a/system/author/auth/login.twig +++ b/system/author/auth/login.twig @@ -6,7 +6,7 @@
-

Remember to bookmark this page

+

Remember to bookmark this page

diff --git a/system/author/auth/welcome.twig b/system/author/auth/welcome.twig index d2bfe43..6f80afc 100644 --- a/system/author/auth/welcome.twig +++ b/system/author/auth/welcome.twig @@ -11,7 +11,7 @@

Hurra!

Your account has been created and you are logged in now.

Next step: Visit the author panel and setup your new website. You can configure the system, choose themes and add plugins.

-

New: With the first big community-contribution you can now discard your changes and set a page back to the published version.

+

New: You never use code-examples on your pages? Then disable the code-button and adjust the whole format-bar of the editor exactly to your needs.

Get help: If you have any questions, please consult the docs or open a new issue on github.

Configure your website diff --git a/system/author/css/fontello/LICENSE.txt b/system/author/css/fontello/LICENSE.txt deleted file mode 100644 index 713d3d3..0000000 --- a/system/author/css/fontello/LICENSE.txt +++ /dev/null @@ -1,48 +0,0 @@ -Font license info - - -## Font Awesome - - Copyright (C) 2016 by Dave Gandy - - Author: Dave Gandy - License: SIL () - Homepage: http://fortawesome.github.com/Font-Awesome/ - - -## Entypo - - Copyright (C) 2012 by Daniel Bruce - - Author: Daniel Bruce - License: SIL (http://scripts.sil.org/OFL) - Homepage: http://www.entypo.com - - -## Modern Pictograms - - Copyright (c) 2012 by John Caserta. All rights reserved. - - Author: John Caserta - License: SIL (http://scripts.sil.org/OFL) - Homepage: http://thedesignoffice.org/project/modern-pictograms/ - - -## Typicons - - (c) Stephen Hutchings 2012 - - Author: Stephen Hutchings - License: SIL (http://scripts.sil.org/OFL) - Homepage: http://typicons.com/ - - -## MFG Labs - - Copyright (C) 2012 by Daniel Bruce - - Author: MFG Labs - License: SIL (http://scripts.sil.org/OFL) - Homepage: http://www.mfglabs.com/ - - diff --git a/system/author/css/fontello/README.txt b/system/author/css/fontello/README.txt deleted file mode 100644 index beaab33..0000000 --- a/system/author/css/fontello/README.txt +++ /dev/null @@ -1,75 +0,0 @@ -This webfont is generated by http://fontello.com open source project. - - -================================================================================ -Please, note, that you should obey original font licenses, used to make this -webfont pack. Details available in LICENSE.txt file. - -- Usually, it's enough to publish content of LICENSE.txt file somewhere on your - site in "About" section. - -- If your project is open-source, usually, it will be ok to make LICENSE.txt - file publicly available in your repository. - -- Fonts, used in Fontello, don't require a clickable link on your site. - But any kind of additional authors crediting is welcome. -================================================================================ - - -Comments on archive content ---------------------------- - -- /font/* - fonts in different formats - -- /css/* - different kinds of css, for all situations. Should be ok with - twitter bootstrap. Also, you can skip style and assign icon classes - directly to text elements, if you don't mind about IE7. - -- demo.html - demo file, to show your webfont content - -- LICENSE.txt - license info about source fonts, used to build your one. - -- config.json - keeps your settings. You can import it back into fontello - anytime, to continue your work - - -Why so many CSS files ? ------------------------ - -Because we like to fit all your needs :) - -- basic file, .css - is usually enough, it contains @font-face - and character code definitions - -- *-ie7.css - if you need IE7 support, but still don't wish to put char codes - directly into html - -- *-codes.css and *-ie7-codes.css - if you like to use your own @font-face - rules, but still wish to benefit from css generation. That can be very - convenient for automated asset build systems. When you need to update font - - no need to manually edit files, just override old version with archive - content. See fontello source code for examples. - -- *-embedded.css - basic css file, but with embedded WOFF font, to avoid - CORS issues in Firefox and IE9+, when fonts are hosted on the separate domain. - We strongly recommend to resolve this issue by `Access-Control-Allow-Origin` - server headers. But if you ok with dirty hack - this file is for you. Note, - that data url moved to separate @font-face to avoid problems with - - - - - - - -
-

fontello font demo

- -
-
-
-
icon-bold0xe800
-
icon-italic0xe801
-
icon-check0xe802
-
icon-cancel0xe803
-
-
-
icon-picture0xe804
-
icon-cancel-10xe805
-
icon-plus0xe806
-
icon-home0xe807
-
-
-
icon-link0xe808
-
icon-cog0xe809
-
icon-off0xe80a
-
icon-video0xe80b
-
-
-
icon-upload0xe80c
-
icon-minus0xe80d
-
icon-colon0xe80e
-
icon-pi0xe80f
-
-
-
icon-list-alt0xe810
-
icon-resize-vertical0xe811
-
icon-math0xf01a
-
icon-move0xf047
-
-
-
icon-link-ext0xf08e
-
icon-bookmark-empty0xf097
-
icon-list-bullet0xf0ca
-
icon-list-numbered0xf0cb
-
-
-
icon-table0xf0ce
-
icon-doc-text0xf0f6
-
icon-quote-left0xf10d
-
icon-folder-empty0xf114
-
-
-
icon-code0xf121
-
icon-superscript0xf12b
-
icon-youtube-play0xf16a
-
icon-header0xf1dc
-
-
-
icon-paragraph0xf1dd
-
-
- - - \ No newline at end of file diff --git a/system/author/css/fontello/font/fontello.eot b/system/author/css/fontello/font/fontello.eot deleted file mode 100644 index ab0db13..0000000 Binary files a/system/author/css/fontello/font/fontello.eot and /dev/null differ diff --git a/system/author/css/fontello/font/fontello.svg b/system/author/css/fontello/font/fontello.svg deleted file mode 100644 index d6f7d89..0000000 --- a/system/author/css/fontello/font/fontello.svg +++ /dev/null @@ -1,76 +0,0 @@ - - - -Copyright (C) 2019 by original authors @ fontello.com - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/system/author/css/fontello/font/fontello.ttf b/system/author/css/fontello/font/fontello.ttf deleted file mode 100644 index 24fe07f..0000000 Binary files a/system/author/css/fontello/font/fontello.ttf and /dev/null differ diff --git a/system/author/css/fontello/font/fontello.woff b/system/author/css/fontello/font/fontello.woff deleted file mode 100644 index f46552c..0000000 Binary files a/system/author/css/fontello/font/fontello.woff and /dev/null differ diff --git a/system/author/css/fontello/font/fontello.woff2 b/system/author/css/fontello/font/fontello.woff2 deleted file mode 100644 index 5ad56b5..0000000 Binary files a/system/author/css/fontello/font/fontello.woff2 and /dev/null differ diff --git a/system/author/css/style.css b/system/author/css/style.css index 8a8f171..ab44c3a 100644 --- a/system/author/css/style.css +++ b/system/author/css/style.css @@ -19,7 +19,11 @@ a, a:link, a:visited, a:focus, a:hover, a:active, button, .button, input, .contr -ms-transition: border-color 0.2s ease; transition: border-color 0.2s ease; } -.navi-item a, .navi-item.folder a i, .navi-item.file a i{ +.navi-item a, +.navi-item.file a .iconwrapper, +.navi-item.folder a .iconwrapper, +.navi-item.file a .movewrapper, +.navi-item.folder a .movewrapper{ -webkit-transition: all 0.1s ease; -moz-transition: all 0.1s ease; -o-transition: all 0.1s ease; @@ -131,9 +135,10 @@ aside.sidebar{ .navi-items a:hover, .navi-items a:focus, .navi-items a:active, .navi-items a.active{ border-bottom: 3px solid #66b0a3; } -.navi-items i{ - color: #ddd; +.navi-items .icon{ + color: #ccc; } + .navi-items span{ display: none; } @@ -208,16 +213,16 @@ li.menu-item{ padding: 0px; position: relative; } -.navi-item i.icon-doc-text, -.navi-item i.icon-folder-empty, -.navi-item i.icon-home, -.navi-item i.icon-plus{ +.navi-item .iconwrapper{ display: inline-block; position: absolute; top: 0px; background: transparent; color: #ccc; padding: 7px 2px 7px; + left: -24px; + width: 20px; + height: 16px; } .navi-item .status{ position: absolute; @@ -232,17 +237,15 @@ li.menu-item{ background:#66b0a3; } .status.modified{ -/* background: #FFD700; */ background: #FFA500; } .status.unpublished{ background:#cc4146; } -.navi-item i.icon-resize-full-alt, -.navi-item i.icon-move { +.navi-item .movewrapper { position: absolute; - right: 5px; - top: 7px; + right: 4px; + top: 4px; color: #f9f8f6; color: #444; background: transparent; @@ -263,9 +266,9 @@ li.menu-item{ .navi-item.file a{ font-weight: 300; } -.navi-item a:focus, .navi-item a:focus i, -.navi-item a:hover, .navi-item a:hover i, -.navi-item a.active, .navi-item a.active i{ +.navi-item a:focus, +.navi-item a:hover, +.navi-item a.active{ background:#66b0a3; color: #fff; } @@ -800,7 +803,6 @@ fieldset.card{ } .card img{ width: 100%; - border: 1px solid #f9f8f6; background: #f9f8f6; } .cardInner{ @@ -1442,10 +1444,13 @@ label .help, .label .help{ border-radius: 2px; font-size: 0.9em; } -.blox-buttons button.edit:hover{ +.blox-buttons button.edit{ background: #70c1b3; color: #eee; } +.blox-buttons button.edit:hover{ + background: #4D978A; +} .blox-buttons button.cancel:hover{ background: #e0474c; color: #eee; @@ -1471,7 +1476,7 @@ label .help, .label .help{ color: #fff; width: 20px; height: 20px; - line-height: 20px; + line-height: 25px; text-align: center; padding: 0px; margin: 1px; @@ -1582,6 +1587,30 @@ button.hdown:hover,button.hdown:focus,button.hdown:active{ /* .format-bar at the bottom of the page */ + +/******************** +* SVG ICONS * +********************/ + +.icon { + display: inline-block; + width: 1em; + height: 1em; + stroke-width: 0; + stroke: currentColor; + fill: currentColor; +} +.icon.baseline{ + top: 0.125em; + position: relative; +} +.icon-file-text-o { + width: 0.8571428571428571em; +} +.icon-bookmark-o { + width: 0.7142857142857142em; + margin-right: 10px; +} .format-bar .hidden{ display: none; } @@ -1643,8 +1672,8 @@ button.hdown:hover,button.hdown:focus,button.hdown:active{ opacity: 0.3; } button.format-item{ - margin: 2px 0; - padding: 5px; + margin: 2px; + padding: 12px 5px; background: #f9f8f6; border: 1px solid #eee; color: #444; @@ -1707,8 +1736,10 @@ button.format-item.close:hover{ border-top: 6px solid #333; } .inlineFormatItem { - color: #FFF; + color: #FFF; cursor: pointer; + font-size: 0.9em; + padding: 3px; } .inlineFormatItem:hover { color: #1199ff; @@ -1862,7 +1893,8 @@ button.format-item.close:hover{ padding: 20px 20px 0 20px; box-sizing: border-box; } -.definitionRow .icon-colon{ +.definitionRow .icon-arrows-v, +.definitionRow .icon-dots-two-vertical{ display: inline-block; margin-top: 15px; } @@ -1889,15 +1921,15 @@ button.delDL{ border: 0px; background: transparent; } -button.addDL i, -button.delDL i{ - width: 20px; +button.addDL .icon-plus, +button.delDL .icon-minus{ + width: 10px; + height: 10px; border-radius: 1px; text-align: center; color:#f9f8f6; - padding: 2px 0 0; - line-height: 20px; - height: 20px; + padding: 2px 1px 1px; + line-height: 10px; } button.addDL{ margin: 20px; @@ -1914,9 +1946,17 @@ button.delDL i{ button.delDL i:hover{ background: #cc4146; } -i.icon-resize-vertical{ +.definitionList .icon-arrows-v{ color: #ddd; } +.definitionList .icon-plus{ + background: #66b0a3; + width: 10px; + height: 10px; +} +.definitionList .icon-minus{ + background: #e0474c; +} .blox ul, .blox ol{ padding-left: 0px; margin-left: 18px; @@ -2235,9 +2275,6 @@ footer a:focus, footer a:hover, footer a:active span.level-3{ padding-left: 35px; } span.level-4{ padding-left: 50px; } span.level-5{ padding-left: 65px; } - .navi-item i.icon-doc-text, .navi-item i.icon-folder-empty, .navi-item i.icon-home, .navi-item i.icon-plus{ - left: -24px; - } fieldset.plugin{ width: 49.5%; } @@ -2291,16 +2328,25 @@ footer a:focus, footer a:hover, footer a:active .navi-item .status{ left: -30px; } - .navi-item a i.icon-move, .navi-item a:link i.icon-move, .navi-item a:visited i.icon-move{ + .navi-item a .movewrapper, + .navi-item a:link .movewrapper, + .navi-item a:visited .movewrapper{ color: #f9f8f6; background: transparent; } - .navi-item a:focus, .navi-item a:focus i, .navi-item a:focus i.icon-move, - .navi-item a:hover, .navi-item a:hover i, .navi-item a:hover i.icon-move, - .navi-item a.active, .navi-item a.active i, .navi-item a.active i.icon-move{ + .navi-item a:focus, + .navi-item a:focus .iconwrapper, + .navi-item a:focus .movewrapper, + .navi-item a:hover, + .navi-item a:hover .iconwrapper, + .navi-item a:hover .movewrapper, + .navi-item a.active, + .navi-item a.active .iconwrapper, + .navi-item a.active .movewrapper + { background:#fff; color: #444; - } + } .navi-items span{ display: inline; } diff --git a/system/author/editor/editor-blox.twig b/system/author/editor/editor-blox.twig index d8cf7a6..5183cf1 100644 --- a/system/author/editor/editor-blox.twig +++ b/system/author/editor/editor-blox.twig @@ -2,9 +2,9 @@ {% block title %}Visual Content Editor{% endblock %} {% block content %} - +
- +
@@ -32,40 +32,22 @@
- - - - - - - - - - - - - + + +
+ - - - - - - - - - - - - - + + + +
diff --git a/system/author/editor/publish-controller.twig b/system/author/editor/publish-controller.twig index 273c911..39a3ec4 100644 --- a/system/author/editor/publish-controller.twig +++ b/system/author/editor/publish-controller.twig @@ -7,7 +7,7 @@ raw moderaw visual modevisual - +
diff --git a/system/author/js/vue-blox-config.js b/system/author/js/vue-blox-config.js new file mode 100644 index 0000000..a64aac5 --- /dev/null +++ b/system/author/js/vue-blox-config.js @@ -0,0 +1,74 @@ +let determiner = { + + olist: function(block,lines,firstChar,secondChar,thirdChar){ + if(block.match(/^\d+\./)) + { + return "olist-component"; + } + return false; + }, + definition: function(block,lines,firstChar,secondChar,thirdChar){ + if(lines.length > 1 && lines[1].substr(0,2) == ': ') + { + return "definition-component"; + } + return false; + }, + table: function(block,lines,firstChar,secondChar,thirdChar){ + if(lines.length > 2 && lines[0].indexOf('|') != -1 && /[\-\|: ]{3,}$/.test(lines[1])) + { + return "table-component"; + } + return false; + }, + quote: function(block,lines,firstChar,secondChar,thirdChar){ + if(firstChar == '>') + { + return "quote-component"; + } + return false; + }, + headline: function(block,lines,firstChar,secondChar,thirdChar){ + if(firstChar == '#') + { + return "headline-component"; + } + return false; + }, + image: function(block,lines,firstChar,secondChar,thirdChar){ + if( (firstChar == '!' && secondChar == '[') || (firstChar == '[' && secondChar == '!' && thirdChar == '[') ) + { + return "image-component"; + } + return false; + }, + code: function(block,lines,firstChar,secondChar,thirdChar){ + if( firstChar == '`' && secondChar == '`' && thirdChar == '`') + { + return "code-component"; + } + return false; + }, + ulist: function(block,lines,firstChar,secondChar,thirdChar){ + if( (firstChar == '*' || firstChar == '-' || firstChar == '+') && secondChar == ' ') + { + return "ulist-component"; + } + return false; + } +} + +let bloxFormats = { + markdown: { label: '', title: 'Paragraph', component: 'markdown-component' }, + headline: { label: '', title: 'Headline', component: 'headline-component' }, + ulist: { label: '', title: 'Bullet List', component: 'ulist-component' }, + olist: { label: '', title: 'Numbered List', component: 'olist-component' }, + table: { label: '', title: 'Table', component: 'table-component' }, + quote: { label: '', title: 'Quote', component: 'quote-component' }, + image: { label: '', title: 'Image', component: 'image-component' }, + video: { label: '', title: 'Video', component: 'video-component' }, + toc: { label: '', title: 'Table of Contents', component: 'toc-component' }, + hr: { label: '', title: 'Horizontal Line', component: 'hr-component' }, + definition: { label: '', title: 'Definition List', component: 'definition-component' }, + code: { label: '', title: 'Code', component: 'code-component' }, +}; \ No newline at end of file diff --git a/system/author/js/vue-blox.js b/system/author/js/vue-blox.js index 5a1bc9a..ddc7ba6 100644 --- a/system/author/js/vue-blox.js +++ b/system/author/js/vue-blox.js @@ -6,8 +6,8 @@ const contentComponent = Vue.component('content-block', { '
Choose a content-type
' + '
' + '
' + - '' + - '' + + '' + + '' + '
' + '
' + '
' + @@ -396,15 +396,15 @@ const inlineFormatsComponent = Vue.component('inline-formats', { template: '
' + '
' + '' + - '' + - '' + + '' + + '' + '
' + '
' + - '' + - '' + - '' + - '' + - '' + + '' + + '' + + '' + + '' + + '' + '
' + '
', data: function(){ @@ -420,7 +420,9 @@ const inlineFormatsComponent = Vue.component('inline-formats', { endPos: false, showInlineFormat: false, link: false, - url: '' + url: '', + code: (formatConfig.indexOf("code") > -1) ? true : false, + math: (formatConfig.indexOf("math") > -1) ? true : false, } }, mounted: function() { @@ -433,7 +435,7 @@ const inlineFormatsComponent = Vue.component('inline-formats', { window.removeEventListener('mousedown', this.onMousedown) }, computed: { - highlightableEl () { + highlightableEl: function () { return this.$slots.default[0].elm } }, @@ -568,7 +570,7 @@ const titleComponent = Vue.component('title-component', { const markdownComponent = Vue.component('markdown-component', { props: ['compmarkdown', 'disabled'], template: '
' + - '
' + + '
' + '' + '' + '' + @@ -588,7 +590,7 @@ const markdownComponent = Vue.component('markdown-component', { const hrComponent = Vue.component('hr-component', { props: ['compmarkdown', 'disabled'], template: '
' + - '
' + + '
' + '' + '
', mounted: function(){ @@ -607,7 +609,7 @@ const hrComponent = Vue.component('hr-component', { const tocComponent = Vue.component('toc-component', { props: ['compmarkdown', 'disabled'], template: '
' + - '
' + + '
' + '' + '
', mounted: function(){ @@ -627,7 +629,7 @@ const codeComponent = Vue.component('code-component', { props: ['compmarkdown', 'disabled'], template: '
' + '' + - '
' + + '
' + '' + '
', data: function(){ @@ -668,7 +670,7 @@ const quoteComponent = Vue.component('quote-component', { props: ['compmarkdown', 'disabled'], template: '
' + '' + - '
' + + '
' + '' + '' + '' + @@ -703,7 +705,7 @@ const quoteComponent = Vue.component('quote-component', { const ulistComponent = Vue.component('ulist-component', { props: ['compmarkdown', 'disabled'], template: '
' + - '
' + + '
' + '' + '' + '' + @@ -751,7 +753,7 @@ const ulistComponent = Vue.component('ulist-component', { const olistComponent = Vue.component('olist-component', { props: ['compmarkdown', 'disabled'], template: '
' + - '
' + + '
' + '' + '' + '' + @@ -777,7 +779,7 @@ const olistComponent = Vue.component('olist-component', { const headlineComponent = Vue.component('headline-component', { props: ['compmarkdown', 'disabled'], template: '
' + - '
' + + '
' + '' + '' + '
', @@ -869,7 +871,7 @@ const tableComponent = Vue.component('table-component', { } }, template: '
' + - '
' + + '
' + '' + '' + '' + @@ -1071,17 +1073,17 @@ const definitionComponent = Vue.component('definition-component', { } }, template: '
' + - '
' + + '
' + '' + '
' + - '' + + '' + '' + - '' + + '' + '' + - '' + + '' + '
' + '
' + - '' + + '' + '
' + '
', mounted: function(){ @@ -1147,53 +1149,11 @@ const definitionComponent = Vue.component('definition-component', { }, }) -const mathComponent = Vue.component('math-component', { - props: ['compmarkdown', 'disabled'], - template: '
' + - '' + - '
' + - '' + - '
', - data: function(){ - return { - mathblock: '' - } - }, - mounted: function(){ - this.$refs.markdown.focus(); - if(this.compmarkdown) - { - var dollarMath = new RegExp(/^\$\$[\S\s]+\$\$$/m); - var bracketMath = new RegExp(/^\\\[[\S\s]+\\\]$/m); - - if(dollarMath.test(this.compmarkdown) || bracketMath.test(this.compmarkdown)) - { - var mathExpression = this.compmarkdown.substring(2,this.compmarkdown.length-2); - this.mathblock = mathExpression.trim(); - } - } - this.$nextTick(function () { - autosize(document.querySelectorAll('textarea')); - }); - }, - methods: { - createmarkdown: function(event) - { - this.codeblock = event.target.value; - var codeblock = '$$\n' + event.target.value + '\n$$'; - this.updatemarkdown(codeblock); - }, - updatemarkdown: function(codeblock) - { - this.$emit('updatedMarkdown', codeblock); - }, - }, -}) const videoComponent = Vue.component('video-component', { props: ['compmarkdown', 'disabled', 'load'], template: '
' + - '
' + + '
' + '' + '
' + '
', @@ -1211,7 +1171,7 @@ const imageComponent = Vue.component('image-component', { '' + ' ' + '

drag a picture or click to select

' + - '
' + + '
' + '' + '
' + '
' + @@ -1500,78 +1460,20 @@ let componentList = { } */ +let activeFormats = []; -let determiner = { - - olist: function(block,lines,firstChar,secondChar,thirdChar){ - if(block.match(/^\d+\./)) - { - return "olist-component"; - } - return false; - }, - definition: function(block,lines,firstChar,secondChar,thirdChar){ - if(lines.length > 1 && lines[1].substr(0,2) == ': ') - { - return "definition-component"; - } - return false; - }, - table: function(block,lines,firstChar,secondChar,thirdChar){ - if(lines.length > 2 && lines[0].indexOf('|') != -1 && /[\-\|: ]{3,}$/.test(lines[1])) - { - return "table-component"; - } - return false; - }, - quote: function(block,lines,firstChar,secondChar,thirdChar){ - if(firstChar == '>') - { - return "quote-component"; - } - return false; - }, - headline: function(block,lines,firstChar,secondChar,thirdChar){ - if(firstChar == '#') - { - return "headline-component"; - } - return false; - }, - image: function(block,lines,firstChar,secondChar,thirdChar){ - if( (firstChar == '!' && secondChar == '[') || (firstChar == '[' && secondChar == '!' && thirdChar == '[') ) - { - return "image-component"; - } - return false; - }, - math: function(block,lines,firstChar,secondChar,thirdChar){ - if( (firstChar == '\\' && secondChar == '[') || ( firstChar == '$' && secondChar == '$$' ) ) - { - return "math-component"; - } - return false; - }, - code: function(block,lines,firstChar,secondChar,thirdChar){ - if( firstChar == '`' && secondChar == '`' && thirdChar == '`') - { - return "code-component"; - } - return false; - }, - ulist: function(block,lines,firstChar,secondChar,thirdChar){ - if( (firstChar == '*' || firstChar == '-' || firstChar == '+') && secondChar == ' ') - { - return "ulist-component"; - } - return false; +for(var i = 0; i < formatConfig.length; i++) +{ + if(bloxFormats[formatConfig[i]] !== undefined) + { + activeFormats.push(bloxFormats[formatConfig[i]]); } } let editor = new Vue({ delimiters: ['${', '}'], el: '#blox', -// components: componentList, +/* components: componentList, */ data: { root: document.getElementById("main").dataset.url, html: false, @@ -1587,6 +1489,7 @@ let editor = new Vue({ draftDisabled: true, bloxOverlay: false, sortdisabled: false, + formats: activeFormats }, mounted: function(){ @@ -1649,10 +1552,11 @@ let editor = new Vue({ self.markdown = result.data; /* make math plugin working */ + if (typeof renderMathInElement === "function") { self.$nextTick(function () { - renderMathInElement(document.body); - }); + renderMathInElement(document.getElementById("blox")); + }); } /* check for youtube videos */ diff --git a/system/author/js/vue-navi.js b/system/author/js/vue-navi.js index 458a697..8604aca 100644 --- a/system/author/js/vue-navi.js +++ b/system/author/js/vue-navi.js @@ -21,7 +21,7 @@ const navcomponent = Vue.component('navigation', { return true; }, onStart : function(evt) - { + { /* delete error messages if exist */ publishController.errors.message = false; }, @@ -38,7 +38,7 @@ const navcomponent = Vue.component('navigation', { 'csrf_name': document.getElementById("csrf_name").value, 'csrf_value': document.getElementById("csrf_value").value, }; - + if(locator.parent_id_from == locator.parent_id_to && locator.index_old == locator.index_new) { return @@ -91,13 +91,24 @@ const navcomponent = Vue.component('navigation', { { if(elementtype == 'file') { - return 'icon-doc-text ' + filetype + return '#icon-file-text-o'; } if(elementtype == 'folder') { - return 'icon-folder-empty ' + filetype + return '#icon-folder-o'; } }, + getIconClass : function(elementtype, filetype) + { + if(elementtype == 'file') + { + return 'icon-file-text-o ' + filetype; + } + if(elementtype == 'folder') + { + return 'icon-folder-o ' + filetype; + } + }, checkActive : function(active,parent) { if(active && !parent) diff --git a/system/author/layouts/layout.twig b/system/author/layouts/layout.twig index 8bb69b0..4f11a0e 100644 --- a/system/author/layouts/layout.twig +++ b/system/author/layouts/layout.twig @@ -21,7 +21,28 @@ - + + + + + external-link + + + + text-file + + + + cog + + + + power-off + + + + +
{% include 'partials/navi.twig' %}
diff --git a/system/author/layouts/layoutAuth.twig b/system/author/layouts/layoutAuth.twig index cf0bfa8..e7aec4a 100644 --- a/system/author/layouts/layoutAuth.twig +++ b/system/author/layouts/layoutAuth.twig @@ -22,7 +22,33 @@ - + + + + + external-link + + + + text-file + + + + cog + + + + power-off + + + + bookmark-o + + + + + + {% include 'partials/flash.twig' %}
diff --git a/system/author/layouts/layoutBlank.twig b/system/author/layouts/layoutBlank.twig index c16c966..ed3ad72 100644 --- a/system/author/layouts/layoutBlank.twig +++ b/system/author/layouts/layoutBlank.twig @@ -20,7 +20,28 @@ - + + + + + external-link + + + + text-file + + + + cog + + + + power-off + + + + +
{% include 'partials/navi.twig' %}
diff --git a/system/author/layouts/layoutBlox.twig b/system/author/layouts/layoutBlox.twig index 719fa11..af2a7f7 100644 --- a/system/author/layouts/layoutBlox.twig +++ b/system/author/layouts/layoutBlox.twig @@ -25,7 +25,129 @@ {{ assets.renderCSS() }} - + + + + + + external-link + + + + text-file + + + + cog + + + + power-off + + + + + delete + + + + add + + + + delete/close + + + + home + + + + move vertical + + + + folder + + + + + + image + + + + + + video + + + + quotes + + + + numbered list + + + + bullet list + + + + link + + + + + bold + + + + italic + + + + horizontal line + + + + table + + + + paragraph + + + + code + + + + + headline + + + + table of contents + + + + definition + + + + check + + + + cross + + + {{ assets.renderSvg() }} + + +
{% include 'partials/navi.twig' %}
@@ -45,6 +167,13 @@ + + + + {{ assets.renderEditorJS() }} + diff --git a/system/author/layouts/layoutEditor.twig b/system/author/layouts/layoutEditor.twig index af3b271..87bb5c8 100644 --- a/system/author/layouts/layoutEditor.twig +++ b/system/author/layouts/layoutEditor.twig @@ -22,7 +22,28 @@ - + + + + + external-link + + + + text-file + + + + cog + + + + power-off + + + + +
{% include 'partials/navi.twig' %}
diff --git a/system/author/partials/editorNavi.twig b/system/author/partials/editorNavi.twig index cd46378..0cb1a60 100644 --- a/system/author/partials/editorNavi.twig +++ b/system/author/partials/editorNavi.twig @@ -5,15 +5,38 @@ - - + +
-
- Startpage -

@@ -76,18 +70,29 @@
-
+
+
+ + {% for format in formats %} + + + + {% endfor %} +
diff --git a/system/system.php b/system/system.php index 7df744e..7b626b0 100644 --- a/system/system.php +++ b/system/system.php @@ -50,14 +50,14 @@ $container = $app->getContainer(); * LOAD & UPDATE PLUGINS * ************************/ -$plugins = new Typemill\Plugins(); -$pluginNames = $plugins->load(); +$plugins = new Typemill\Plugins(); +$pluginNames = $plugins->load(); $pluginSettings = $routes = $middleware = array(); foreach($pluginNames as $pluginName) { $className = $pluginName['className']; - $name = $pluginName['name']; + $name = $pluginName['name']; # check if plugin is in the settings already if(isset($settings['settings']['plugins'][$name])) @@ -80,7 +80,7 @@ foreach($pluginNames as $pluginName) # if the plugin is activated, add routes/middleware and add plugin as event subscriber if($pluginSettings[$name]['active']) { - $routes = $plugins->getNewRoutes($className, $routes); + $routes = $plugins->getNewRoutes($className, $routes); $middleware = $plugins->getNewMiddleware($className, $middleware); $dispatcher->addSubscriber(new $className($container)); diff --git a/themes/typemill/css/style.css b/themes/typemill/css/style.css index 38c864c..7979287 100644 --- a/themes/typemill/css/style.css +++ b/themes/typemill/css/style.css @@ -479,17 +479,16 @@ footer p{ * CONTENT ELEMENTS * ************************/ -pre,code{ - white-space: pre; -} code{ display: inline-block; padding: 0 0.5em; font-size: 0.8em; line-height: 1.4em; border-radius: 3px; + word-break: break-all; } pre{ + white-space: pre; padding: 10px; display: block; max-width: 100%; diff --git a/themes/typemill/typemill.yaml b/themes/typemill/typemill.yaml index 2993b16..4ecb352 100644 --- a/themes/typemill/typemill.yaml +++ b/themes/typemill/typemill.yaml @@ -1,5 +1,5 @@ name: Typemill Theme -version: 1.1.7 +version: 1.1.8 description: The standard theme for Typemill. Responsive, minimal and without any dependencies. It uses the system fonts Calibri and Helvetica. No JavaScript is used. author: Sebastian Schürmanns homepage: https://typemill.net @@ -8,6 +8,7 @@ licence: MIT settings: chapter: Chapter start: Start + cover: true modified: true modifiedText: 'Last updated' modifiedFormat: 'd.m.Y' @@ -19,20 +20,25 @@ settings: forms: fields: - chapter: - type: text - label: Text For Chapter - placeholder: Add Name for Chapter + cover: + type: checkbox + label: Different Design for Startpage + checkboxlabel: Activate Special Startpage-Design start: type: text - label: Label For Start Button + label: Label for Start Button placeholder: Add Label for Start-Button required: true + chapter: + type: text + label: Label for Chapter + placeholder: Add Name for Chapter + chapnum: type: checkbox - label: Chapter Numbers + label: Show Chapter Numbers checkboxlabel: Count chapters in navigation? fieldset0: