diff --git a/.gitignore b/.gitignore index cba61ddb7206c05f47cd7691ed277dff8b5a96d3..6ffb0eb999180ef60dc7562b8f0d5271f0784685 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 ad04c6825e96e0101b05066e755ab25d5973f85d..be5ff7d6a9e710220fcade599ae3b6971f4f5779 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 8ea6b5eab43549fe13be084d769c0a077cc2b276..f30d9153d7a27b6a6b036732b45b1d13e00a0161 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 7ff21b7a0f60ff870cbcf3d67a5cc363696d9ea1..0f241440a714a3809e88f92af1b82ba60ad5193e 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 c0cfeddd717aedaa7aa5ceff1dde12acbf3a3ead..bacbf318144a6c384590b6ec47555f98f3a7b80e 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 d855f77a1ffcad4c86d31a8f3042acdeed6f1078..95090855812df4f08bdec93dfbc9a7609c7eee71 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 c075823735953c5ef2a90a8c6d3b328cefe23479..288f60c8455261a4d56ecb21413fbb682b05e4f8 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 70e56becac7d01a4a4537f83ff2721b8d15528f7..409503e92aa4aba45f04b03aa0395fd3314745be 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 0000000000000000000000000000000000000000..897206932e66dd12dbb90ba69074158a7c9fb056 --- /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 7bc99a5534a5184440f1a975297d8602d4eecb7a..d67146931e4823f3f7695ba013564a025624cd75 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 0e3cccb254ed588d80f48482c8d705986698fd26..09f5512912646852318acb677a793c67b0514328 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 c0b5e1bce3f0b4f105773502c0c4053483ed345e..b5fa7002e522f52ff1876c166967fbd6494c3d90 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 b68d2e2e0a9395568434ed866d388a60dfc40775..70c7e48c35f8a21da71ec95ce6a1a1f85d409cdb 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 e7504a32e6f4470eb27a0aa90037823233dded4f..a76d39cf4c6c970a491b9992faea1be824233cf8 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 214bc834b52142bfbf34bf11303d5740fbb38ec7..d09a33486a044283d52697f1b3d49b911c735c41 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 f7bdfe1a03d8a6f8dbf716f9f72a7482ce68049a..eb57205a799ae10cfa82c14963d9fd457be6213c 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 d6a76a25fdaa63e7faf2c3beaecfe2f23c647029..d578bd9a311cb33d4c67d3a83187fa7057fa539c 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 1ff598e9a356654cbfe739fbb3ddbc6952702c83..a182480c4b4d3c86fd509a9748ad79a6f6e8a8cd 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 46c7cf2ea4ed1032c4567844df760663a3ff7f17..133e5dd2d6f6fb137bd913e89640d07ad4916273 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 4007906bd112ba2873cab2f0d661bb6c3bda3bb2..8fe26dc8596f0565366164cf3c580dd2904d5293 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 517b9fbfe2b008625b29974bda3012f41bf52752..10e618b7c0cf05541375a33b87b826e15bb7f72f 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 d2bfe43e185eb5b20a60b7092acd57dcb2f6e8eb..6f80afc82e8570a4ad4ff7c5608cea364d6f3f32 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 713d3d3ca6bc898c45a1075666654fe16f64f512..0000000000000000000000000000000000000000 --- 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 beaab3366f0de9c53ee27b2255b6687eaeac444f..0000000000000000000000000000000000000000 --- 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 ab0db13df3428a5d665c3158e5265400b323a3de..0000000000000000000000000000000000000000 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 d6f7d89dc663ffc12f39582e296da876821f0bb3..0000000000000000000000000000000000000000 --- 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 24fe07ffae5ff4cde067dd52376ca850ae825ece..0000000000000000000000000000000000000000 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 f46552c9e6dbd6361e87a08dcce8189dd35d105c..0000000000000000000000000000000000000000 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 5ad56b5c6721e6ca073b1ef61b31542734f0ade3..0000000000000000000000000000000000000000 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 8a8f1711e2cf3ae97dbeaf05e4c0cfd138c5b606..ab44c3ac567f31cb4e85b52796a0e6957818fec2 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 d8cf7a6c25b59cbb3d2fdfa8222bbc95778e54bb..5183cf1deeaa95491009bd7c9f51375a6ec2c01c 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 273c9115b28fed1661b563bb4009089717907844..39a3ec4d9b21ed1b45b75764c16ed5fffc77fc40 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 0000000000000000000000000000000000000000..a64aac502fc83688441002250247fe27535757e6 --- /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 5a1bc9ae4ec128ee71d48c1c470d4e635fa460f5..ddc7ba6068e0903980f67c8b2b76d8acfd09ef38 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 458a697b67461fa612a97dc8ee0616b3302aa25f..8604aca5fb5f00863050d5283c869106ebc39a74 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 8bb69b05a6ff512e265b702bf7f35aa8959c3f29..4f11a0e4d8963c08d8bd3ce2c770dd383ec341be 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 cf0bfa8294f5537fb25c911613bc8490f63d0c7e..e7aec4a45151280363a38700ccf5c671896bd68d 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 c16c966736a01085a86012f2283c4741a385cd9b..ed3ad722ee29baf5b876ec98d9725df85b11b7e5 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 719fa11825d1731d99b19490cb09f27a37c91583..af2a7f772f718e47c425aa2555f105dfb91eb0a0 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 af3b271ffbc555c4bdd03e53edc3fc029a2dec78..87bb5c8de9498d5b4a3953ca8c10d7204fb4037c 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 cd4637878eb227e800f15b6b5b8c7f82d8b9b161..0cb1a6069a07a5c43d4a958eb4b8597eed40242f 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 7df744eec600bac1f4ce1fb9e0008d866cac0fbf..7b626b0fde35b0e54f5b1a089633ae01f39fcfa9 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 38c864c5487e2779587aee2236bcf1e118002c41..7979287040f5a27783e1233f7aeb4b331eaf0f6e 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 2993b16db96902727436ab2edc3d8c43e60d392d..4ecb35205edef318ec45d4fe9917a6cb87090112 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: