├── screenshot.png ├── AUTHORS ├── field ├── vendor │ ├── autoload.php │ ├── composer │ │ ├── autoload_namespaces.php │ │ ├── autoload_psr4.php │ │ ├── LICENSE │ │ ├── autoload_real.php │ │ ├── installed.json │ │ ├── autoload_classmap.php │ │ └── ClassLoader.php │ └── league │ │ └── html-to-markdown │ │ ├── src │ │ ├── ConfigurationAwareInterface.php │ │ ├── Converter │ │ │ ├── ConverterInterface.php │ │ │ ├── CommentConverter.php │ │ │ ├── HardBreakConverter.php │ │ │ ├── HorizontalRuleConverter.php │ │ │ ├── ListBlockConverter.php │ │ │ ├── ParagraphConverter.php │ │ │ ├── ListItemConverter.php │ │ │ ├── ImageConverter.php │ │ │ ├── TextConverter.php │ │ │ ├── LinkConverter.php │ │ │ ├── DivConverter.php │ │ │ ├── BlockquoteConverter.php │ │ │ ├── EmphasisConverter.php │ │ │ ├── DefaultConverter.php │ │ │ ├── HeaderConverter.php │ │ │ └── PreformattedConverter.php │ │ ├── Configuration.php │ │ ├── ElementInterface.php │ │ ├── Environment.php │ │ ├── Element.php │ │ └── HtmlConverter.php │ │ ├── LICENSE │ │ ├── CHANGELOG.md │ │ └── README.md ├── assets │ ├── js │ │ ├── ins-button.js │ │ ├── del-button.js │ │ ├── mark-button.js │ │ ├── wysiwyg.js │ │ └── vendor │ │ │ ├── rangy-classapplier.min.js │ │ │ └── rangy-core.min.js │ └── css │ │ ├── wysiwyg.css │ │ ├── medium-editor-theme-kirby.css │ │ └── vendor │ │ └── medium-editor.min.css └── wysiwyg.php ├── .editorconfig ├── package.json ├── field-wysiwyg.php ├── LICENSE └── README.md /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/storypioneers/kirby-wysiwyg/HEAD/screenshot.png -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | List of Selector contributors. Updated before every release. 2 | 3 | dgdsp 4 | JonasDoebertin 5 | -------------------------------------------------------------------------------- /field/vendor/autoload.php: -------------------------------------------------------------------------------- 1 | array($vendorDir . '/league/html-to-markdown/src'), 10 | ); 11 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "field-wysiwyg", 3 | "description": "Kirby wysiwyg field", 4 | "author": "digital storytelling pioneers ", 5 | "version": "1.2.1", 6 | "type": "kirby-plugin", 7 | "license": "GNU GPL v3.0 ", 8 | "repository": { 9 | "type": "git", 10 | "url": "https://github.com/storypioneers/kirby-wysiwyg" 11 | } 12 | } -------------------------------------------------------------------------------- /field/vendor/league/html-to-markdown/src/Converter/ConverterInterface.php: -------------------------------------------------------------------------------- 1 | 9 | * @author feat. Jonas Döbertin and others (see AUTHORS) 10 | * @copyright digital storytelling pioneers 11 | * @link https://github.com/storypioneers/kirby-wysiwyg 12 | * @license GNU GPL v3.0 13 | */ 14 | 15 | // register the builder field 16 | $kirby->set('field', 'wysiwyg', __DIR__ . DS . 'field'); 17 | -------------------------------------------------------------------------------- /field/vendor/league/html-to-markdown/src/Converter/CommentConverter.php: -------------------------------------------------------------------------------- 1 | getValue() . "\n"; 17 | } 18 | 19 | /** 20 | * @return string[] 21 | */ 22 | public function getSupportedTags() 23 | { 24 | return array('ol', 'ul'); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /field/vendor/league/html-to-markdown/src/Converter/ParagraphConverter.php: -------------------------------------------------------------------------------- 1 | getValue(); 17 | 18 | return (trim($value)) ? rtrim($value) . "\n\n" : ''; 19 | } 20 | 21 | /** 22 | * @return string[] 23 | */ 24 | public function getSupportedTags() 25 | { 26 | return array('p'); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) 2015 digital storytelling pioneers 2 | 3 | This program is free software: you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation, either version 3 of the License, or 6 | (at your option) any later version. 7 | 8 | This program is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License 14 | along with this program. If not, see . -------------------------------------------------------------------------------- /field/assets/js/ins-button.js: -------------------------------------------------------------------------------- 1 | var InsButton = MediumEditor.extensions.button.extend({ 2 | name: 'ins', 3 | 4 | tagNames: ['INS'], // nodeName which indicates the button should be 'active' when isAlreadyApplied() is called 5 | contentDefault: '+', // default innerHTML of the button 6 | contentFA: '', // innerHTML of button when 'fontawesome' is being used 7 | aria: 'Inserted', // used as both aria-label and title attributes 8 | action: 'ins', // used as the data-action attribute of the button 9 | 10 | init: function () { 11 | MediumEditor.extensions.button.prototype.init.call(this); 12 | 13 | this.classApplier = rangy.createClassApplier('ins', { 14 | elementTagName: 'ins', 15 | normalize: true 16 | }); 17 | }, 18 | 19 | handleClick: function (event) { 20 | event.preventDefault(); 21 | event.stopPropagation(); 22 | 23 | this.classApplier.toggleSelection(); 24 | this.base.checkContentChanged(); 25 | this.button.classList.toggle('medium-editor-button-active'); 26 | }, 27 | }); 28 | -------------------------------------------------------------------------------- /field/vendor/league/html-to-markdown/src/Converter/ListItemConverter.php: -------------------------------------------------------------------------------- 1 | getParent()->getTagName(); 18 | $value = $element->getValue(); 19 | 20 | if ($list_type === 'ul') { 21 | $markdown = '- ' . trim($value) . "\n"; 22 | } else { 23 | $number = $element->getSiblingPosition(); 24 | $markdown = $number . '. ' . trim($value) . "\n"; 25 | } 26 | 27 | return $markdown; 28 | } 29 | 30 | /** 31 | * @return string[] 32 | */ 33 | public function getSupportedTags() 34 | { 35 | return array('li'); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /field/assets/js/del-button.js: -------------------------------------------------------------------------------- 1 | var DelButton = MediumEditor.extensions.button.extend({ 2 | name: 'del', 3 | 4 | tagNames: ['DEL'], // nodeName which indicates the button should be 'active' when isAlreadyApplied() is called 5 | contentDefault: '-', // default innerHTML of the button 6 | contentFA: '', // innerHTML of button when 'fontawesome' is being used 7 | aria: 'Deleted', // used as both aria-label and title attributes 8 | action: 'del', // used as the data-action attribute of the button 9 | 10 | init: function () { 11 | MediumEditor.extensions.button.prototype.init.call(this); 12 | 13 | this.classApplier = rangy.createClassApplier('del', { 14 | elementTagName: 'del', 15 | normalize: true 16 | }); 17 | }, 18 | 19 | handleClick: function (event) { 20 | event.preventDefault(); 21 | event.stopPropagation(); 22 | 23 | this.classApplier.toggleSelection(); 24 | this.base.checkContentChanged(); 25 | this.button.classList.toggle('medium-editor-button-active'); 26 | }, 27 | }); 28 | -------------------------------------------------------------------------------- /field/vendor/league/html-to-markdown/src/Converter/ImageConverter.php: -------------------------------------------------------------------------------- 1 | getAttribute('src'); 17 | $alt = $element->getAttribute('alt'); 18 | $title = $element->getAttribute('title'); 19 | 20 | if ($title !== '') { 21 | // No newlines added. should be in a block-level element. 22 | $markdown = '![' . $alt . '](' . $src . ' "' . $title . '")'; 23 | } else { 24 | $markdown = '![' . $alt . '](' . $src . ')'; 25 | } 26 | 27 | return $markdown; 28 | } 29 | 30 | /** 31 | * @return string[] 32 | */ 33 | public function getSupportedTags() 34 | { 35 | return array('img'); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /field/assets/js/mark-button.js: -------------------------------------------------------------------------------- 1 | var MarkButton = MediumEditor.extensions.button.extend({ 2 | name: 'mark', 3 | 4 | tagNames: ['mark'], // nodeName which indicates the button should be 'active' when isAlreadyApplied() is called 5 | contentDefault: 'H', // default innerHTML of the button 6 | contentFA: '', // innerHTML of button when 'fontawesome' is being used 7 | aria: 'Hightlight', // used as both aria-label and title attributes 8 | action: 'mark', // used as the data-action attribute of the button 9 | 10 | init: function () { 11 | MediumEditor.extensions.button.prototype.init.call(this); 12 | 13 | this.classApplier = rangy.createClassApplier('mark', { 14 | elementTagName: 'mark', 15 | normalize: true 16 | }); 17 | }, 18 | 19 | handleClick: function (event) { 20 | event.preventDefault(); 21 | event.stopPropagation(); 22 | 23 | this.classApplier.toggleSelection(); 24 | this.base.checkContentChanged(); 25 | this.button.classList.toggle('medium-editor-button-active'); 26 | }, 27 | }); 28 | -------------------------------------------------------------------------------- /field/vendor/league/html-to-markdown/src/Converter/TextConverter.php: -------------------------------------------------------------------------------- 1 | getValue(); 17 | 18 | $markdown = preg_replace('~\s+~', ' ', $value); 19 | 20 | //escape the following characters: '*', '_' and '\' 21 | $markdown = preg_replace('~([*_\\\\])~', '\\\\$1', $markdown); 22 | 23 | $markdown = preg_replace('~^#~', '\\\\#', $markdown); 24 | 25 | if ($markdown === ' ') { 26 | $next = $element->getNext(); 27 | if (!$next || $next->isBlock()) { 28 | $markdown = ''; 29 | } 30 | } 31 | 32 | return $markdown; 33 | } 34 | 35 | /** 36 | * @return string[] 37 | */ 38 | public function getSupportedTags() 39 | { 40 | return array('#text'); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /field/vendor/composer/LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Copyright (c) 2015 Nils Adermann, Jordi Boggiano 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is furnished 9 | to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | 22 | -------------------------------------------------------------------------------- /field/vendor/league/html-to-markdown/src/Converter/LinkConverter.php: -------------------------------------------------------------------------------- 1 | getAttribute('href'); 17 | $title = $element->getAttribute('title'); 18 | $text = $element->getValue(); 19 | 20 | if ($title !== '') { 21 | $markdown = '[' . $text . '](' . $href . ' "' . $title . '")'; 22 | } elseif ($href === $text) { 23 | $markdown = '<' . $href . '>'; 24 | } else { 25 | $markdown = '[' . $text . '](' . $href . ')'; 26 | } 27 | 28 | if (!$href) { 29 | $markdown = html_entity_decode($element->getChildrenAsString()); 30 | } 31 | 32 | return $markdown; 33 | } 34 | 35 | /** 36 | * @return string[] 37 | */ 38 | public function getSupportedTags() 39 | { 40 | return array('a'); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /field/vendor/league/html-to-markdown/src/Converter/DivConverter.php: -------------------------------------------------------------------------------- 1 | config = $config; 22 | } 23 | 24 | /** 25 | * @param ElementInterface $element 26 | * 27 | * @return string 28 | */ 29 | public function convert(ElementInterface $element) 30 | { 31 | if ($this->config->getOption('strip_tags', false)) { 32 | return $element->getValue() . "\n\n"; 33 | } 34 | 35 | return html_entity_decode($element->getChildrenAsString()); 36 | } 37 | 38 | /** 39 | * @return string[] 40 | */ 41 | public function getSupportedTags() 42 | { 43 | return array('div'); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /field/vendor/league/html-to-markdown/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Colin O'Dell 4 | 5 | Originally created by Nick Cernis 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | this software and associated documentation files (the "Software"), to deal in 9 | the Software without restriction, including without limitation the rights to 10 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | the Software, and to permit persons to whom the Software is furnished to do so, 12 | subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /field/vendor/league/html-to-markdown/src/Converter/BlockquoteConverter.php: -------------------------------------------------------------------------------- 1 | ' symbols to each line. 18 | 19 | $markdown = ''; 20 | 21 | $quote_content = trim($element->getValue()); 22 | 23 | $lines = preg_split('/\r\n|\r|\n/', $quote_content); 24 | 25 | $total_lines = count($lines); 26 | 27 | foreach ($lines as $i => $line) { 28 | $markdown .= '> ' . $line . "\n"; 29 | if ($i + 1 === $total_lines) { 30 | $markdown .= "\n"; 31 | } 32 | } 33 | 34 | return $markdown; 35 | } 36 | 37 | /** 38 | * @return string[] 39 | */ 40 | public function getSupportedTags() 41 | { 42 | return array('blockquote'); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /field/vendor/league/html-to-markdown/src/Converter/EmphasisConverter.php: -------------------------------------------------------------------------------- 1 | config = $config; 22 | } 23 | 24 | /** 25 | * @param ElementInterface $element 26 | * 27 | * @return string 28 | */ 29 | public function convert(ElementInterface $element) 30 | { 31 | $tag = $element->getTagName(); 32 | $value = $element->getValue(); 33 | 34 | if ($tag === 'i' || $tag === 'em') { 35 | $style = $this->config->getOption('italic_style'); 36 | } else { 37 | $style = $this->config->getOption('bold_style'); 38 | } 39 | 40 | return $style . $value . $style; 41 | } 42 | 43 | /** 44 | * @return string[] 45 | */ 46 | public function getSupportedTags() 47 | { 48 | return array('em', 'i', 'strong', 'b'); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /field/assets/css/wysiwyg.css: -------------------------------------------------------------------------------- 1 | .wysiwyg-editor-input { 2 | display: none; 3 | } 4 | 5 | .wysiwyg-editor { 6 | min-height: 10em; 7 | } 8 | 9 | .wysiwyg-editor.over { 10 | border-color: #000000; 11 | } 12 | 13 | .wysiwyg-editor h1, 14 | .wysiwyg-editor h2, 15 | .wysiwyg-editor h3, 16 | .wysiwyg-editor h4, 17 | .wysiwyg-editor h5, 18 | .wysiwyg-editor h6 { 19 | font-weight: bold; 20 | margin-bottom: 1em; 21 | } 22 | 23 | .wysiwyg-editor p { 24 | margin-bottom: 1em; 25 | } 26 | 27 | .wysiwyg-editor strong, 28 | .wysiwyg-editor b { 29 | font-weight: bold; 30 | } 31 | 32 | .wysiwyg-editor em, 33 | .wysiwyg-editor i { 34 | font-style: italic; 35 | } 36 | 37 | .wysiwyg-editor a { 38 | text-decoration: underline; 39 | } 40 | 41 | .wysiwyg-editor blockquote { 42 | margin-bottom: 1em; 43 | font-style: italic; 44 | padding-left: 1em; 45 | } 46 | 47 | .wysiwyg-editor pre, 48 | .wysiwyg-editor code { 49 | margin-bottom: 1em; 50 | font-family: monospace; 51 | white-space: pre-wrap; 52 | } 53 | 54 | .wysiwyg-editor ul { 55 | list-style: inside square; 56 | } 57 | 58 | .wysiwyg-editor ol { 59 | list-style: inside decimal; 60 | } 61 | 62 | .wysiwyg-editor del { 63 | text-decoration: line-through; 64 | color: red; 65 | } 66 | 67 | .wysiwyg-editor ins { 68 | text-decoration: underline; 69 | color: green; 70 | } 71 | 72 | .wysiwyg-editor mark { 73 | background-color: yellow; 74 | } 75 | -------------------------------------------------------------------------------- /field/vendor/league/html-to-markdown/src/Configuration.php: -------------------------------------------------------------------------------- 1 | config = $config; 15 | } 16 | 17 | /** 18 | * @param array $config 19 | */ 20 | public function merge(array $config = array()) 21 | { 22 | $this->config = array_replace_recursive($this->config, $config); 23 | } 24 | 25 | /** 26 | * @param array $config 27 | */ 28 | public function replace(array $config = array()) 29 | { 30 | $this->config = $config; 31 | } 32 | 33 | /** 34 | * @param string $key 35 | * @param mixed $value 36 | */ 37 | public function setOption($key, $value) 38 | { 39 | $this->config[$key] = $value; 40 | } 41 | 42 | /** 43 | * @param string|null $key 44 | * @param mixed|null $default 45 | * 46 | * @return mixed|null 47 | */ 48 | public function getOption($key = null, $default = null) 49 | { 50 | if ($key === null) { 51 | return $this->config; 52 | } 53 | 54 | if (!isset($this->config[$key])) { 55 | return $default; 56 | } 57 | 58 | return $this->config[$key]; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /field/vendor/league/html-to-markdown/src/Converter/DefaultConverter.php: -------------------------------------------------------------------------------- 1 | config = $config; 24 | } 25 | 26 | /** 27 | * @param ElementInterface $element 28 | * 29 | * @return string 30 | */ 31 | public function convert(ElementInterface $element) 32 | { 33 | // If strip_tags is false (the default), preserve tags that don't have Markdown equivalents, 34 | // such as nodes on their own. C14N() canonicalizes the node to a string. 35 | // See: http://www.php.net/manual/en/domnode.c14n.php 36 | if ($this->config->getOption('strip_tags', false)) { 37 | return $element->getValue(); 38 | } 39 | 40 | return html_entity_decode($element->getChildrenAsString()); 41 | } 42 | 43 | /** 44 | * @return string[] 45 | */ 46 | public function getSupportedTags() 47 | { 48 | return array(self::DEFAULT_CONVERTER); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /field/vendor/composer/autoload_real.php: -------------------------------------------------------------------------------- 1 | $path) { 28 | $loader->set($namespace, $path); 29 | } 30 | 31 | $map = require __DIR__ . '/autoload_psr4.php'; 32 | foreach ($map as $namespace => $path) { 33 | $loader->setPsr4($namespace, $path); 34 | } 35 | 36 | $classMap = require __DIR__ . '/autoload_classmap.php'; 37 | if ($classMap) { 38 | $loader->addClassMap($classMap); 39 | } 40 | 41 | $loader->register(true); 42 | 43 | return $loader; 44 | } 45 | } 46 | 47 | function composerRequiree7bab76da30f67d3624f64064056b0c0($file) 48 | { 49 | require $file; 50 | } 51 | -------------------------------------------------------------------------------- /field/vendor/league/html-to-markdown/src/ElementInterface.php: -------------------------------------------------------------------------------- 1 | =5.3.3" 21 | }, 22 | "require-dev": { 23 | "phpunit/phpunit": "4.*", 24 | "scrutinizer/ocular": "~1.1" 25 | }, 26 | "time": "2015-09-01 22:39:54", 27 | "type": "library", 28 | "extra": { 29 | "branch-alias": { 30 | "dev-master": "4.1-dev" 31 | } 32 | }, 33 | "installation-source": "dist", 34 | "autoload": { 35 | "psr-4": { 36 | "League\\HTMLToMarkdown\\": "src/" 37 | } 38 | }, 39 | "notification-url": "https://packagist.org/downloads/", 40 | "license": [ 41 | "MIT" 42 | ], 43 | "authors": [ 44 | { 45 | "name": "Colin O'Dell", 46 | "email": "colinodell@gmail.com", 47 | "homepage": "http://www.colinodell.com", 48 | "role": "Lead Developer" 49 | }, 50 | { 51 | "name": "Nick Cernis", 52 | "email": "nick@cern.is", 53 | "homepage": "http://modernnerd.net", 54 | "role": "Original Author" 55 | } 56 | ], 57 | "description": "An HTML-to-markdown conversion helper for PHP", 58 | "homepage": "https://github.com/thephpleague/html-to-markdown", 59 | "keywords": [ 60 | "html", 61 | "markdown" 62 | ] 63 | } 64 | ] 65 | -------------------------------------------------------------------------------- /field/vendor/league/html-to-markdown/src/Converter/HeaderConverter.php: -------------------------------------------------------------------------------- 1 | config = $config; 25 | } 26 | 27 | /** 28 | * @param ElementInterface $element 29 | * 30 | * @return string 31 | */ 32 | public function convert(ElementInterface $element) 33 | { 34 | $level = (int) substr($element->getTagName(), 1, 1); 35 | $style = $this->config->getOption('header_style', self::STYLE_SETEXT); 36 | 37 | if (($level === 1 || $level === 2) && !$element->isDescendantOf('blockquote') && $style === self::STYLE_SETEXT) { 38 | return $this->createSetextHeader($level, $element->getValue()); 39 | } else { 40 | return $this->createAtxHeader($level, $element->getValue()); 41 | } 42 | } 43 | 44 | /** 45 | * @return string[] 46 | */ 47 | public function getSupportedTags() 48 | { 49 | return array('h1', 'h2', 'h3', 'h4', 'h5', 'h6'); 50 | } 51 | 52 | /** 53 | * @param int $level 54 | * @param string $content 55 | * 56 | * @return string 57 | */ 58 | private function createSetextHeader($level, $content) 59 | { 60 | $length = (function_exists('mb_strlen')) ? mb_strlen($content, 'utf-8') : strlen($content); 61 | $underline = ($level === 1) ? '=' : '-'; 62 | 63 | return $content . "\n" . str_repeat($underline, $length) . "\n\n"; 64 | } 65 | 66 | /** 67 | * @param int $level 68 | * @param string $content 69 | * 70 | * @return string 71 | */ 72 | private function createAtxHeader($level, $content) 73 | { 74 | $prefix = str_repeat('#', $level) . ' '; 75 | 76 | return $prefix . $content . "\n\n"; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /field/vendor/league/html-to-markdown/src/Converter/PreformattedConverter.php: -------------------------------------------------------------------------------- 1 | getChildrenAsString()); 21 | $code_content = str_replace(array('', ''), '', $code_content); 22 | $code_content = str_replace(array('
', '
'), '', $code_content); 23 | 24 | $lines = preg_split('/\r\n|\r|\n/', $code_content); 25 | $total = count($lines); 26 | 27 | // If there's more than one line of code, prepend each line with four spaces and no backticks. 28 | if ($total > 1 || $element->getTagName() === 'pre') { 29 | // Remove the first and last line if they're empty 30 | $first_line = trim($lines[0]); 31 | $last_line = trim($lines[$total - 1]); 32 | $first_line = trim($first_line, ' '); //trim XML style carriage returns too 33 | $last_line = trim($last_line, ' '); 34 | 35 | if (empty($first_line)) { 36 | array_shift($lines); 37 | } 38 | 39 | if (empty($last_line)) { 40 | array_pop($lines); 41 | } 42 | 43 | $count = 1; 44 | foreach ($lines as $line) { 45 | $line = str_replace(' ', '', $line); 46 | $markdown .= ' ' . $line; 47 | // Add newlines, except final line of the code 48 | if ($count !== $total) { 49 | $markdown .= "\n"; 50 | } 51 | $count++; 52 | } 53 | $markdown .= "\n"; 54 | } else { 55 | // There's only one line of code. It's a code span, not a block. Just wrap it with backticks. 56 | $markdown .= '`' . $lines[0] . '`'; 57 | } 58 | 59 | if ($element->getTagName() === 'pre') { 60 | $markdown = "\n" . $markdown . "\n"; 61 | } 62 | 63 | return $markdown; 64 | } 65 | 66 | /** 67 | * @return string[] 68 | */ 69 | public function getSupportedTags() 70 | { 71 | return array('pre', 'code'); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /field/assets/css/medium-editor-theme-kirby.css: -------------------------------------------------------------------------------- 1 | .medium-toolbar-arrow-under:after { 2 | bottom: -8px; 3 | border-color: #000 transparent transparent transparent; 4 | } 5 | .medium-toolbar-arrow-over:before { 6 | bottom: 8px; 7 | border-color: transparent transparent #000 transparent; 8 | } 9 | .medium-editor-toolbar { 10 | background-color: #000; 11 | box-shadow: rgba(0, 0, 0, .2) 0px 2px 10px; 12 | border-radius: 4px; 13 | } 14 | .medium-editor-toolbar li { padding: 0 } 15 | .medium-editor-toolbar li button { 16 | min-width: 45px; 17 | height: 45px; 18 | border: none; 19 | border-left: 1px solid #222; 20 | background-color: transparent; 21 | color: #fff; 22 | padding: 8px; 23 | font-size: 12px; 24 | } 25 | .medium-editor-toolbar li:first-child button { 26 | border: none; 27 | border-top-left-radius: 4px; 28 | border-bottom-left-radius: 4px; 29 | } 30 | .medium-editor-toolbar li:last-child button { 31 | border-top-right-radius: 4px; 32 | border-bottom-right-radius: 4px; 33 | } 34 | .medium-editor-toolbar li button:hover { 35 | color: #999; 36 | } 37 | .medium-editor-toolbar li .medium-editor-button-active { 38 | background-color: #8dae28; 39 | color: #fff; 40 | } 41 | .medium-editor-toolbar li .medium-editor-button-active:hover { 42 | color: #fff; 43 | } 44 | .medium-editor-toolbar li .medium-editor-button-last { 45 | border-right: none; 46 | } 47 | .medium-editor-toolbar-form .medium-editor-toolbar-input { 48 | height: 48px; 49 | background: #000; 50 | color: #fff; 51 | } 52 | .medium-editor-toolbar-form .medium-editor-toolbar-input::-webkit-input-placeholder { 53 | color: #fff; 54 | color: rgba(255, 255, 255, 0.7); 55 | } 56 | .medium-editor-toolbar-form .medium-editor-toolbar-input:-moz-placeholder { 57 | /* Firefox 18- */ 58 | color: #fff; 59 | color: rgba(255, 255, 255, 0.7); 60 | } 61 | .medium-editor-toolbar-form .medium-editor-toolbar-input::-moz-placeholder { 62 | /* Firefox 19+ */ 63 | color: #fff; 64 | color: rgba(255, 255, 255, 0.7); 65 | } 66 | .medium-editor-toolbar-form .medium-editor-toolbar-input:-ms-input-placeholder { 67 | color: #fff; 68 | color: rgba(255, 255, 255, 0.7); 69 | } 70 | .medium-editor-toolbar-form a { 71 | min-width: 45px; 72 | height: 45px; 73 | border: none; 74 | border-left: 1px solid #222; 75 | background-color: transparent; 76 | color: #fff; 77 | padding: 16px 0 0 16px; 78 | font-size: 12px; 79 | vertical-align: top; 80 | margin: 0; 81 | } 82 | .medium-editor-toolbar a:hover { 83 | color: #999; 84 | } 85 | .medium-editor-toolbar a:last-child { 86 | border-top-right-radius: 4px; 87 | border-bottom-right-radius: 4px; 88 | } 89 | 90 | .medium-editor-toolbar-anchor-preview { 91 | background: #8dae28; 92 | color: #fff; 93 | } 94 | .medium-editor-placeholder:after { 95 | color: #fff; 96 | } 97 | .medium-editor-toolbar-form-row { 98 | color: #fff; 99 | } 100 | .medium-editor-toolbar-form .medium-editor-toolbar-input { 101 | height: 45px; 102 | margin-left: 4px; 103 | } 104 | -------------------------------------------------------------------------------- /field/vendor/composer/autoload_classmap.php: -------------------------------------------------------------------------------- 1 | $vendorDir . '/league/html-to-markdown/src/Configuration.php', 10 | 'League\\HTMLToMarkdown\\ConfigurationAwareInterface' => $vendorDir . '/league/html-to-markdown/src/ConfigurationAwareInterface.php', 11 | 'League\\HTMLToMarkdown\\Converter\\BlockquoteConverter' => $vendorDir . '/league/html-to-markdown/src/Converter/BlockquoteConverter.php', 12 | 'League\\HTMLToMarkdown\\Converter\\CommentConverter' => $vendorDir . '/league/html-to-markdown/src/Converter/CommentConverter.php', 13 | 'League\\HTMLToMarkdown\\Converter\\ConverterInterface' => $vendorDir . '/league/html-to-markdown/src/Converter/ConverterInterface.php', 14 | 'League\\HTMLToMarkdown\\Converter\\DefaultConverter' => $vendorDir . '/league/html-to-markdown/src/Converter/DefaultConverter.php', 15 | 'League\\HTMLToMarkdown\\Converter\\DivConverter' => $vendorDir . '/league/html-to-markdown/src/Converter/DivConverter.php', 16 | 'League\\HTMLToMarkdown\\Converter\\EmphasisConverter' => $vendorDir . '/league/html-to-markdown/src/Converter/EmphasisConverter.php', 17 | 'League\\HTMLToMarkdown\\Converter\\HardBreakConverter' => $vendorDir . '/league/html-to-markdown/src/Converter/HardBreakConverter.php', 18 | 'League\\HTMLToMarkdown\\Converter\\HeaderConverter' => $vendorDir . '/league/html-to-markdown/src/Converter/HeaderConverter.php', 19 | 'League\\HTMLToMarkdown\\Converter\\HorizontalRuleConverter' => $vendorDir . '/league/html-to-markdown/src/Converter/HorizontalRuleConverter.php', 20 | 'League\\HTMLToMarkdown\\Converter\\ImageConverter' => $vendorDir . '/league/html-to-markdown/src/Converter/ImageConverter.php', 21 | 'League\\HTMLToMarkdown\\Converter\\LinkConverter' => $vendorDir . '/league/html-to-markdown/src/Converter/LinkConverter.php', 22 | 'League\\HTMLToMarkdown\\Converter\\ListBlockConverter' => $vendorDir . '/league/html-to-markdown/src/Converter/ListBlockConverter.php', 23 | 'League\\HTMLToMarkdown\\Converter\\ListItemConverter' => $vendorDir . '/league/html-to-markdown/src/Converter/ListItemConverter.php', 24 | 'League\\HTMLToMarkdown\\Converter\\ParagraphConverter' => $vendorDir . '/league/html-to-markdown/src/Converter/ParagraphConverter.php', 25 | 'League\\HTMLToMarkdown\\Converter\\PreformattedConverter' => $vendorDir . '/league/html-to-markdown/src/Converter/PreformattedConverter.php', 26 | 'League\\HTMLToMarkdown\\Converter\\TextConverter' => $vendorDir . '/league/html-to-markdown/src/Converter/TextConverter.php', 27 | 'League\\HTMLToMarkdown\\Element' => $vendorDir . '/league/html-to-markdown/src/Element.php', 28 | 'League\\HTMLToMarkdown\\ElementInterface' => $vendorDir . '/league/html-to-markdown/src/ElementInterface.php', 29 | 'League\\HTMLToMarkdown\\Environment' => $vendorDir . '/league/html-to-markdown/src/Environment.php', 30 | 'League\\HTMLToMarkdown\\HtmlConverter' => $vendorDir . '/league/html-to-markdown/src/HtmlConverter.php', 31 | ); 32 | -------------------------------------------------------------------------------- /field/vendor/league/html-to-markdown/src/Environment.php: -------------------------------------------------------------------------------- 1 | config = new Configuration($config); 37 | $this->addConverter(new DefaultConverter()); 38 | } 39 | 40 | /** 41 | * @return Configuration 42 | */ 43 | public function getConfig() 44 | { 45 | return $this->config; 46 | } 47 | 48 | /** 49 | * @param ConverterInterface $converter 50 | */ 51 | public function addConverter(ConverterInterface $converter) 52 | { 53 | if ($converter instanceof ConfigurationAwareInterface) { 54 | $converter->setConfig($this->config); 55 | } 56 | 57 | foreach ($converter->getSupportedTags() as $tag) { 58 | $this->converters[$tag] = $converter; 59 | } 60 | } 61 | 62 | /** 63 | * @param string $tag 64 | * 65 | * @return ConverterInterface 66 | */ 67 | public function getConverterByTag($tag) 68 | { 69 | if (isset($this->converters[$tag])) { 70 | return $this->converters[$tag]; 71 | } 72 | 73 | return $this->converters[DefaultConverter::DEFAULT_CONVERTER]; 74 | } 75 | 76 | /** 77 | * @param array $config 78 | * 79 | * @return Environment 80 | */ 81 | public static function createDefaultEnvironment(array $config = array()) 82 | { 83 | $environment = new static($config); 84 | 85 | $environment->addConverter(new BlockquoteConverter()); 86 | $environment->addConverter(new CommentConverter()); 87 | $environment->addConverter(new DivConverter()); 88 | $environment->addConverter(new EmphasisConverter()); 89 | $environment->addConverter(new HardBreakConverter()); 90 | $environment->addConverter(new HeaderConverter()); 91 | $environment->addConverter(new HorizontalRuleConverter()); 92 | $environment->addConverter(new ImageConverter()); 93 | $environment->addConverter(new LinkConverter()); 94 | $environment->addConverter(new ListBlockConverter()); 95 | $environment->addConverter(new ListItemConverter()); 96 | $environment->addConverter(new ParagraphConverter()); 97 | $environment->addConverter(new PreformattedConverter()); 98 | $environment->addConverter(new TextConverter()); 99 | 100 | return $environment; 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Kirby WYSIWYG 2 | 3 | This additional panel field for [Kirby 2](http://getkirby.com) allows you to use a medium.com like visual inline editor in the Panel. 4 | 5 | **Authors**: [digital storytelling pioneers](https://github.com/storypioneers) feat. [Jonas Doebertin](https://github.com/JonasDoebertin) 6 | 7 | **License**: [GNU GPL v3.0](http://opensource.org/licenses/GPL-3.0) 8 | 9 | ![screenshot](https://raw.github.com/storypioneers/kirby-wysiwyg/master/screenshot.png) 10 | 11 | ## Installation 12 | 13 | Copy or link the `field-wysiwyg` directory to `site/plugins/` **or** use the [Kirby CLI](https://github.com/getkirby/cli) `kirby plugin:install storypioneers/kirby-wysiwyg`. 14 | 15 | 16 | *Optional: Set some configuration options for Kirby WYSIWYG Editor in your sites `config.php` file. You can get an overview of all available options further down.* 17 | 18 | 19 | ## Usage 20 | 21 | Post installation you can use it in your blueprints: simply replace the `textarea` fields with `wysiwyg` fields (where applicable). 22 | 23 | ```yaml 24 | fields: 25 | richtext: 26 | label: Text 27 | type: wysiwyg 28 | ``` 29 | 30 | As content you create using Kirby WYSIWYG Editor is converted into valid markdown, there's nothing you have to change in your templates. Just use the `wysiwyg` content fields like your previous `textarea` fields: 31 | 32 | ```php 33 |
34 |

title()->html() ?>

35 | 36 | 38 | richtext()->kirbytext() ?> 39 | 40 | 41 | ``` 42 | 43 | ## Global Options 44 | 45 | The Kirby WYSIWYG Editor Field has some global options that you might want to use to alter the fields functionality to suit your specific needs. Below you'll find a list of all available options which can be set from your projects global `config.php` file. 46 | 47 | ### field.wysiwyg.buttons 48 | 49 | Define a list of buttons to display in the editor toolbar. Currently supported button types are: `bold`, `italic`, `underline`, `strikethrough`, `subscript`, `superscript`, `anchor`, `quote`, `pre`, `orderedlist`, `unorderedlist`, `h1`, `h2`, `h3`, `h4`, `h5`, `h6`, and `removeFormat`. Please note that the order in which you list the button names relates to the display order in the toolbar. 50 | 51 | ### field.wysiwyg.heading-style 52 | 53 | Define your preferred heading style. Choose between `setext` (underlined) or `atx` (# Heading 1 and ## Heading 2). Please note that this only affects H1 and H2 headings. All headings of lower priority will always use the ATX style. 54 | 55 | ## Per Field Options 56 | 57 | In addition to the global options explained above, the field offers some options that can be set from a per field basis directly from your blueprints. Please note that these per field options always overwrite global options you might have specified. 58 | 59 | ### buttons 60 | 61 | Define a list of buttons to display in the editor toolbar. Currently supported button types are: `bold`, `italic`, `underline`, `strikethrough`, `subscript`, `superscript`, `anchor`, `quote`, `pre`, `orderedlist`, `unorderedlist`, `h1`, `h2`, `h3`, `h4`, `h5`, `h6`, and `removeFormat`. Please note that the order in which you list the button names relates to the display order in the toolbar. 62 | 63 | ```yaml 64 | fields: 65 | richtext: 66 | label: Text 67 | type: wysiwyg 68 | buttons: 69 | - bold 70 | - italic 71 | - anchor 72 | ``` 73 | 74 | ### headingstyle 75 | 76 | Define your preferred heading style. Choose between `setext` (underlined) or `atx` (# Heading 1 and ## Heading 2). Please note that this only affects H1 and H2 headings. All headings of lower priority will always use the ATX style. 77 | 78 | ```yaml 79 | fields: 80 | richtext: 81 | label: Text 82 | type: wysiwyg 83 | headingstyle: setext 84 | ``` 85 | -------------------------------------------------------------------------------- /field/assets/css/vendor/medium-editor.min.css: -------------------------------------------------------------------------------- 1 | .medium-editor-anchor-preview,.medium-editor-toolbar{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:16px;z-index:2000}@-webkit-keyframes medium-editor-image-loading{0%{-webkit-transform:scale(0);transform:scale(0)}100%{-webkit-transform:scale(1);transform:scale(1)}}@keyframes medium-editor-image-loading{0%{-webkit-transform:scale(0);transform:scale(0)}100%{-webkit-transform:scale(1);transform:scale(1)}}@-webkit-keyframes medium-editor-pop-upwards{0%{opacity:0;-webkit-transform:matrix(.97,0,0,1,0,12);transform:matrix(.97,0,0,1,0,12)}20%{opacity:.7;-webkit-transform:matrix(.99,0,0,1,0,2);transform:matrix(.99,0,0,1,0,2)}40%{opacity:1;-webkit-transform:matrix(1,0,0,1,0,-1);transform:matrix(1,0,0,1,0,-1)}100%{-webkit-transform:matrix(1,0,0,1,0,0);transform:matrix(1,0,0,1,0,0)}}@keyframes medium-editor-pop-upwards{0%{opacity:0;-webkit-transform:matrix(.97,0,0,1,0,12);transform:matrix(.97,0,0,1,0,12)}20%{opacity:.7;-webkit-transform:matrix(.99,0,0,1,0,2);transform:matrix(.99,0,0,1,0,2)}40%{opacity:1;-webkit-transform:matrix(1,0,0,1,0,-1);transform:matrix(1,0,0,1,0,-1)}100%{-webkit-transform:matrix(1,0,0,1,0,0);transform:matrix(1,0,0,1,0,0)}}.medium-editor-anchor-preview{left:0;line-height:1.4;max-width:280px;position:absolute;text-align:center;top:0;word-break:break-all;word-wrap:break-word;visibility:hidden}.medium-editor-anchor-preview a{color:#fff;display:inline-block;margin:5px 5px 10px}.medium-editor-placeholder-relative:after,.medium-editor-placeholder:after{content:attr(data-placeholder)!important;white-space:pre;padding:inherit;margin:inherit;font-style:italic}.medium-editor-anchor-preview-active{visibility:visible}.medium-editor-dragover{background:#ddd}.medium-editor-image-loading{-webkit-animation:medium-editor-image-loading 1s infinite ease-in-out;animation:medium-editor-image-loading 1s infinite ease-in-out;background-color:#333;border-radius:100%;display:inline-block;height:40px;width:40px}.medium-editor-placeholder{position:relative}.medium-editor-placeholder:after{position:absolute;left:0;top:0}.medium-editor-placeholder-relative,.medium-editor-placeholder-relative:after{position:relative}.medium-toolbar-arrow-over:before,.medium-toolbar-arrow-under:after{border-style:solid;content:'';display:block;height:0;left:50%;margin-left:-8px;position:absolute;width:0}.medium-toolbar-arrow-under:after{border-width:8px 8px 0}.medium-toolbar-arrow-over:before{border-width:0 8px 8px;top:-8px}.medium-editor-toolbar{left:0;position:absolute;top:0;visibility:hidden}.medium-editor-toolbar ul{margin:0;padding:0}.medium-editor-toolbar li{float:left;list-style:none;margin:0;padding:0}.medium-editor-toolbar li button{box-sizing:border-box;cursor:pointer;display:block;font-size:14px;line-height:1.33;margin:0;padding:15px;text-decoration:none}.medium-editor-toolbar li button:focus{outline:0}.medium-editor-toolbar li .medium-editor-action-underline{text-decoration:underline}.medium-editor-toolbar li .medium-editor-action-pre{font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace;font-size:12px;font-weight:100;padding:15px 0}.medium-editor-toolbar-active{visibility:visible}.medium-editor-sticky-toolbar{position:fixed;top:1px}.medium-editor-relative-toolbar{position:relative}.medium-editor-toolbar-active.medium-editor-stalker-toolbar{-webkit-animation:medium-editor-pop-upwards 160ms forwards linear;animation:medium-editor-pop-upwards 160ms forwards linear}.medium-editor-action-bold{font-weight:bolder}.medium-editor-action-italic{font-style:italic}.medium-editor-toolbar-form{display:none}.medium-editor-toolbar-form a,.medium-editor-toolbar-form input{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif}.medium-editor-toolbar-form .medium-editor-toolbar-form-row{line-height:14px;margin-left:5px;padding-bottom:5px}.medium-editor-toolbar-form .medium-editor-toolbar-input,.medium-editor-toolbar-form label{border:none;box-sizing:border-box;font-size:14px;margin:0;padding:6px;width:316px;display:inline-block}.medium-editor-toolbar-form .medium-editor-toolbar-input:focus,.medium-editor-toolbar-form label:focus{-webkit-appearance:none;-moz-appearance:none;appearance:none;border:none;box-shadow:none;outline:0}.medium-editor-toolbar-form a{display:inline-block;font-size:24px;font-weight:bolder;margin:0 10px;text-decoration:none}.medium-editor-toolbar-form-active{display:block}.medium-editor-toolbar-actions:after{clear:both;content:"";display:table}.medium-editor-element{word-wrap:break-word;min-height:30px}.medium-editor-element img{max-width:100%}.medium-editor-element sub{vertical-align:sub}.medium-editor-element sup{vertical-align:super}.medium-editor-hidden{display:none} -------------------------------------------------------------------------------- /field/vendor/league/html-to-markdown/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | All notable changes to this project will be documented in this file. 3 | Updates should follow the [Keep a CHANGELOG](http://keepachangelog.com/) principles. 4 | 5 | ## [Unreleased][unreleased] 6 | 7 | ## [4.0.1] 8 | 9 | ### Fixed 10 | - Added escaping to avoid * and _ in a text being rendered as emphasis (#48) 11 | 12 | ### Removed 13 | - Removed the demo (#51) 14 | - `.styleci.yml` and `CONTRIBUTING.md` are no longer included in distributions (#50) 15 | 16 | ## [4.0.0] 17 | 18 | This release changes the visibility of several methods/properties. #42 and #43 brought to light that some visiblities were 19 | not ideally set, so this releases fixes that. Moving forwards this should reduce the chance of introducing BC-breaking changes. 20 | 21 | ### Added 22 | - Added new `HtmlConverter::getEnvironment()` method to expose the `Environment` (#42, #43) 23 | 24 | ### Changed 25 | - Changed `Environment::addConverter()` from `protected` to `public`, enabling custom converters to be added (#42, #43) 26 | - Changed `HtmlConverter::createDOMDocument()` from `protected` to `private` 27 | - Changed `Element::nextCached` from `protected` to `private` 28 | - Made the `Environment` class `final` 29 | 30 | ## [3.1.1] 31 | ### Fixed 32 | - Empty HTML strings now result in empty Markdown documents (#40, #41) 33 | 34 | ## [3.1.0] 35 | ### Added 36 | - Added new `equals` method to `Element` to check for equality 37 | 38 | ### Changes 39 | - Use Linux line endings consistently instead of plaform-specific line endings (#36) 40 | 41 | ### Fixed 42 | - Cleaned up code style 43 | 44 | ## [3.0.0] 45 | ### Changed 46 | - Changed namespace to `League\HTMLToMarkdown` 47 | - Changed packagist name to `league/html-to-markdown` 48 | - Re-organized code into several separate classes 49 | - `` tags with identical href and inner text are now rendered using angular bracket syntax (#31) 50 | - `
` elements are now treated as block-level elements (#33) 51 | 52 | ## [2.2.2] 53 | ### Added 54 | - Added support for PHP 5.6 and HHVM 55 | - Enabled testing against PHP 7 nightlies 56 | - Added this CHANGELOG.md 57 | 58 | ### Fixed 59 | - Fixed whitespace preservation between inline elements (#9 and #10) 60 | 61 | ## [2.2.1] 62 | ### Fixed 63 | - Preserve placeholder links (#22) 64 | 65 | ## [2.2.0] 66 | ### Added 67 | - Added CircleCI config 68 | 69 | ### Changed 70 | - `
` blocks are now treated as code elements
 71 | 
 72 | ### Removed
 73 |  - Dropped support for PHP 5.2
 74 |  - Removed incorrect README comment regarding `#text` nodes (#17)
 75 | 
 76 | ## [2.1.2]
 77 | ### Added
 78 |  - Added the ability to blacklist/remove specific node types (#11)
 79 | 
 80 | ### Changed
 81 |  - Line breaks are now placed after divs instead of before them
 82 |  - Newlines inside of link texts are now removed
 83 |  - Updated the minimum PHPUnit version to 4.*
 84 | 
 85 | ## [2.1.1]
 86 | ### Added
 87 |  - Added options to customize emphasis characters
 88 | 
 89 | ## [2.1.0]
 90 | ### Added
 91 |  - Added option to strip HTML tags without Markdown equivalents
 92 |  - Added `convert()` method for converter reuse
 93 |  - Added ability to set options after instance construction
 94 |  - Documented the required PHP extensions (#4)
 95 | 
 96 | ### Changed
 97 |  - ATX style now used for h1 and h2 tags inside blockquotes
 98 | 
 99 | ### Fixed
100 |  - Newlines inside blockquotes are now started with a bracket
101 |  - Fixed some incorrect docblocks
102 |  - `__toString()` now returns an empty string if input is empty
103 |  - Convert head tag if body tag is empty (#7)
104 |  - Preserve special characters inside tags without md equivalents (#6)
105 | 
106 | 
107 | ## [2.0.1]
108 | ### Fixed
109 |  - Fixed first line indentation for multi-line code blocks
110 |  - Fixed consecutive anchors get separating spaces stripped (#3)
111 | 
112 | ## [2.0.0]
113 | ### Added
114 |  - Initial release
115 | 
116 | [unreleased]: https://github.com/thephpleague/html-to-markdown/compare/4.0.1...master
117 | [4.0.1]: https://github.com/thephpleague/html-to-markdown/compare/4.0.0...4.0.1
118 | [4.0.0]: https://github.com/thephpleague/html-to-markdown/compare/3.1.1...4.0.0
119 | [3.1.1]: https://github.com/thephpleague/html-to-markdown/compare/3.1.0...3.1.1
120 | [3.1.0]: https://github.com/thephpleague/html-to-markdown/compare/3.0.0...3.1.0
121 | [3.0.0]: https://github.com/thephpleague/html-to-markdown/compare/2.2.2...3.0.0
122 | [2.2.2]: https://github.com/thephpleague/html-to-markdown/compare/2.2.1...2.2.2
123 | [2.2.1]: https://github.com/thephpleague/html-to-markdown/compare/2.2.0...2.2.1
124 | [2.2.0]: https://github.com/thephpleague/html-to-markdown/compare/2.1.2...2.2.0
125 | [2.1.2]: https://github.com/thephpleague/html-to-markdown/compare/2.1.1...2.1.2
126 | [2.1.1]: https://github.com/thephpleague/html-to-markdown/compare/2.1.0...2.1.1
127 | [2.1.0]: https://github.com/thephpleague/html-to-markdown/compare/2.0.1...2.1.0
128 | [2.0.1]: https://github.com/thephpleague/html-to-markdown/compare/2.0.0...2.0.1
129 | [2.0.0]: https://github.com/thephpleague/html-to-markdown/compare/775f91e...2.0.0
130 | 
131 | 


--------------------------------------------------------------------------------
/field/vendor/league/html-to-markdown/src/Element.php:
--------------------------------------------------------------------------------
  1 | node = $node;
 20 |     }
 21 | 
 22 |     /**
 23 |      * @return bool
 24 |      */
 25 |     public function isBlock()
 26 |     {
 27 |         switch ($this->getTagName()) {
 28 |             case 'blockquote':
 29 |             case 'body':
 30 |             case 'code':
 31 |             case 'div':
 32 |             case 'h1':
 33 |             case 'h2':
 34 |             case 'h3':
 35 |             case 'h4':
 36 |             case 'h5':
 37 |             case 'h6':
 38 |             case 'hr':
 39 |             case 'html':
 40 |             case 'li':
 41 |             case 'p':
 42 |             case 'ol':
 43 |             case 'ul':
 44 |                 return true;
 45 |             default:
 46 |                 return false;
 47 |         }
 48 |     }
 49 | 
 50 |     /**
 51 |      * @return bool
 52 |      */
 53 |     public function isText()
 54 |     {
 55 |         return $this->getTagName() === '#text';
 56 |     }
 57 | 
 58 |     /**
 59 |      * @return bool
 60 |      */
 61 |     public function isWhitespace()
 62 |     {
 63 |         return $this->getTagName() === '#text' && trim($this->getValue()) === '';
 64 |     }
 65 | 
 66 |     /**
 67 |      * @return string
 68 |      */
 69 |     public function getTagName()
 70 |     {
 71 |         return $this->node->nodeName;
 72 |     }
 73 | 
 74 |     /**
 75 |      * @return string
 76 |      */
 77 |     public function getValue()
 78 |     {
 79 |         return $this->node->nodeValue;
 80 |     }
 81 | 
 82 |     /**
 83 |      * @return ElementInterface|null
 84 |      */
 85 |     public function getParent()
 86 |     {
 87 |         return new static($this->node->parentNode) ?: null;
 88 |     }
 89 | 
 90 |     /**
 91 |      * @return bool
 92 |      */
 93 |     public function hasChildren()
 94 |     {
 95 |         return $this->node->hasChildNodes();
 96 |     }
 97 | 
 98 |     /**
 99 |      * @return ElementInterface[]
100 |      */
101 |     public function getChildren()
102 |     {
103 |         $ret = array();
104 |         /** @var \DOMNode $node */
105 |         foreach ($this->node->childNodes as $node) {
106 |             $ret[] = new static($node);
107 |         }
108 | 
109 |         return $ret;
110 |     }
111 | 
112 |     /**
113 |      * @return ElementInterface|null
114 |      */
115 |     public function getNext()
116 |     {
117 |         if ($this->nextCached === null) {
118 |             $nextNode = $this->getNextNode($this->node);
119 |             if ($nextNode !== null) {
120 |                 $this->nextCached = new static($nextNode);
121 |             }
122 |         }
123 | 
124 |         return $this->nextCached;
125 |     }
126 | 
127 |     /**
128 |      * @param \DomNode $node
129 |      *
130 |      * @return \DomNode|null
131 |      */
132 |     private function getNextNode($node, $checkChildren = true)
133 |     {
134 |         if ($checkChildren && $node->firstChild) {
135 |             return $node->firstChild;
136 |         } elseif ($node->nextSibling) {
137 |             return $node->nextSibling;
138 |         } elseif ($node->parentNode) {
139 |             return $this->getNextNode($node->parentNode, false);
140 |         }
141 |     }
142 | 
143 |     /**
144 |      * @param string[]|string $tagNames
145 |      *
146 |      * @return bool
147 |      */
148 |     public function isDescendantOf($tagNames)
149 |     {
150 |         if (!is_array($tagNames)) {
151 |             $tagNames = array($tagNames);
152 |         }
153 | 
154 |         for ($p = $this->node->parentNode; $p !== false; $p = $p->parentNode) {
155 |             if (is_null($p)) {
156 |                 return false;
157 |             }
158 | 
159 |             if (in_array($p->nodeName, $tagNames)) {
160 |                 return true;
161 |             }
162 |         }
163 | 
164 |         return false;
165 |     }
166 | 
167 |     /**
168 |      * @param string $markdown
169 |      */
170 |     public function setFinalMarkdown($markdown)
171 |     {
172 |         $markdown_node = $this->node->ownerDocument->createTextNode($markdown);
173 |         $this->node->parentNode->replaceChild($markdown_node, $this->node);
174 |     }
175 | 
176 |     /**
177 |      * @return string
178 |      */
179 |     public function getChildrenAsString()
180 |     {
181 |         return $this->node->C14N();
182 |     }
183 | 
184 |     /**
185 |      * @return int
186 |      */
187 |     public function getSiblingPosition()
188 |     {
189 |         $position = 0;
190 | 
191 |         // Loop through all nodes and find the given $node
192 |         foreach ($this->getParent()->getChildren() as $current_node) {
193 |             if (!$current_node->isWhitespace()) {
194 |                 $position++;
195 |             }
196 | 
197 |             // TODO: Need a less-buggy way of comparing these
198 |             // Perhaps we can somehow ensure that we always have the exact same object and use === instead?
199 |             if ($this->equals($current_node)) {
200 |                 break;
201 |             }
202 |         }
203 | 
204 |         return $position;
205 |     }
206 | 
207 |     /**
208 |      * @param string $name
209 |      *
210 |      * @return string
211 |      */
212 |     public function getAttribute($name)
213 |     {
214 |         if ($this->node instanceof \DOMElement) {
215 |             return $this->node->getAttribute($name);
216 |         }
217 | 
218 |         return '';
219 |     }
220 | 
221 |     /**
222 |      * @param ElementInterface $element
223 |      *
224 |      * @return bool
225 |      */
226 |     public function equals(ElementInterface $element)
227 |     {
228 |         if ($element instanceof self) {
229 |             return $element->node === $this->node;
230 |         }
231 | 
232 |         return $element === $this;
233 |     }
234 | }
235 | 


--------------------------------------------------------------------------------
/field/vendor/league/html-to-markdown/src/HtmlConverter.php:
--------------------------------------------------------------------------------
  1 | 
 11 |  * @author Nick Cernis 
 12 |  *
 13 |  * @link https://github.com/thephpleague/html-to-markdown/ Latest version on GitHub.
 14 |  *
 15 |  * @license http://www.opensource.org/licenses/mit-license.php MIT
 16 |  */
 17 | class HtmlConverter
 18 | {
 19 |     /**
 20 |      * @var Environment
 21 |      */
 22 |     protected $environment;
 23 | 
 24 |     /**
 25 |      * Constructor
 26 |      *
 27 |      * @param array $options Configuration options
 28 |      */
 29 |     public function __construct(array $options = array())
 30 |     {
 31 |         $defaults = array(
 32 |             'header_style'    => 'setext', // Set to 'atx' to output H1 and H2 headers as # Header1 and ## Header2
 33 |             'suppress_errors' => true, // Set to false to show warnings when loading malformed HTML
 34 |             'strip_tags'      => false, // Set to true to strip tags that don't have markdown equivalents. N.B. Strips tags, not their content. Useful to clean MS Word HTML output.
 35 |             'bold_style'      => '**', // Set to '__' if you prefer the underlined style
 36 |             'italic_style'    => '*', // Set to '_' if you prefer the underlined style
 37 |             'remove_nodes'    => '', // space-separated list of dom nodes that should be removed. example: 'meta style script'
 38 |         );
 39 | 
 40 |         $this->environment = Environment::createDefaultEnvironment($defaults);
 41 | 
 42 |         $this->environment->getConfig()->merge($options);
 43 |     }
 44 | 
 45 |     /**
 46 |      * @return Environment
 47 |      */
 48 |     public function getEnvironment()
 49 |     {
 50 |         return $this->environment;
 51 |     }
 52 | 
 53 |     /**
 54 |      * @return Configuration
 55 |      */
 56 |     public function getConfig()
 57 |     {
 58 |         return $this->environment->getConfig();
 59 |     }
 60 | 
 61 |     /**
 62 |      * Convert
 63 |      *
 64 |      * Loads HTML and passes to getMarkdown()
 65 |      *
 66 |      * @param $html
 67 |      *
 68 |      * @return string The Markdown version of the html
 69 |      */
 70 |     public function convert($html)
 71 |     {
 72 |         if (trim($html) === '') {
 73 |             return '';
 74 |         }
 75 | 
 76 |         $document = $this->createDOMDocument($html);
 77 | 
 78 |         // Work on the entire DOM tree (including head and body)
 79 |         if (!($root = $document->getElementsByTagName('html')->item(0))) {
 80 |             throw new \InvalidArgumentException('Invalid HTML was provided');
 81 |         }
 82 | 
 83 |         $rootElement = new Element($root);
 84 |         $this->convertChildren($rootElement);
 85 | 
 86 |         // Store the now-modified DOMDocument as a string
 87 |         $markdown = $document->saveHTML();
 88 | 
 89 |         $markdown = $this->sanitize($markdown);
 90 | 
 91 |         return $markdown;
 92 |     }
 93 | 
 94 |     /**
 95 |      * @param string $html
 96 |      *
 97 |      * @return \DOMDocument
 98 |      */
 99 |     private function createDOMDocument($html)
100 |     {
101 |         $document = new \DOMDocument();
102 | 
103 |         if ($this->getConfig()->getOption('suppress_errors')) {
104 |             // Suppress conversion errors (from http://bit.ly/pCCRSX)
105 |             libxml_use_internal_errors(true);
106 |         }
107 | 
108 |         // Hack to load utf-8 HTML (from http://bit.ly/pVDyCt)
109 |         $document->loadHTML('' . $html);
110 |         $document->encoding = 'UTF-8';
111 | 
112 |         if ($this->getConfig()->getOption('suppress_errors')) {
113 |             libxml_clear_errors();
114 |         }
115 | 
116 |         return $document;
117 |     }
118 | 
119 |     /**
120 |      * Convert Children
121 |      *
122 |      * Recursive function to drill into the DOM and convert each node into Markdown from the inside out.
123 |      *
124 |      * Finds children of each node and convert those to #text nodes containing their Markdown equivalent,
125 |      * starting with the innermost element and working up to the outermost element.
126 |      *
127 |      * @param ElementInterface $element
128 |      */
129 |     private function convertChildren(ElementInterface $element)
130 |     {
131 |         // Don't convert HTML code inside  and 
 blocks to Markdown - that should stay as HTML
132 |         if ($element->isDescendantOf(array('pre', 'code'))) {
133 |             return;
134 |         }
135 | 
136 |         // If the node has children, convert those to Markdown first
137 |         if ($element->hasChildren()) {
138 |             foreach ($element->getChildren() as $child) {
139 |                 $this->convertChildren($child);
140 |             }
141 |         }
142 | 
143 |         // Now that child nodes have been converted, convert the original node
144 |         $markdown = $this->convertToMarkdown($element);
145 | 
146 |         // Create a DOM text node containing the Markdown equivalent of the original node
147 | 
148 |         // Replace the old $node e.g. '

Title

' with the new $markdown_node e.g. '### Title' 149 | $element->setFinalMarkdown($markdown); 150 | } 151 | 152 | /** 153 | * Convert to Markdown 154 | * 155 | * Converts an individual node into a #text node containing a string of its Markdown equivalent. 156 | * 157 | * Example: An

node with text content of 'Title' becomes a text node with content of '### Title' 158 | * 159 | * @param ElementInterface $element 160 | * 161 | * @return string The converted HTML as Markdown 162 | */ 163 | protected function convertToMarkdown(ElementInterface $element) 164 | { 165 | $tag = $element->getTagName(); 166 | 167 | // Strip nodes named in remove_nodes 168 | $tags_to_remove = explode(' ', $this->getConfig()->getOption('remove_nodes')); 169 | if (in_array($tag, $tags_to_remove)) { 170 | return false; 171 | } 172 | 173 | $converter = $this->environment->getConverterByTag($tag); 174 | 175 | return $converter->convert($element); 176 | } 177 | 178 | /** 179 | * @param string $markdown 180 | * 181 | * @return string 182 | */ 183 | protected function sanitize($markdown) 184 | { 185 | $markdown = html_entity_decode($markdown, ENT_QUOTES, 'UTF-8'); 186 | $markdown = html_entity_decode($markdown, ENT_QUOTES, 'UTF-8'); // Double decode to cover cases like &nbsp; http://www.php.net/manual/en/function.htmlentities.php#99984 187 | $markdown = preg_replace('/]+>/', '', $markdown); // Strip doctype declaration 188 | $unwanted = array('', '', '', '', '', '', '', ' '); 189 | $markdown = str_replace($unwanted, '', $markdown); // Strip unwanted tags 190 | $markdown = trim($markdown, "\n\r\0\x0B"); 191 | 192 | return $markdown; 193 | } 194 | } 195 | -------------------------------------------------------------------------------- /field/vendor/league/html-to-markdown/README.md: -------------------------------------------------------------------------------- 1 | HTML To Markdown for PHP 2 | ======================== 3 | 4 | [![Latest Version](https://img.shields.io/packagist/v/league/html-to-markdown.svg?style=flat-square)](https://packagist.org/packages/league/html-to-markdown) 5 | [![Software License](http://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE) 6 | [![Build Status](https://img.shields.io/travis/thephpleague/html-to-markdown/master.svg?style=flat-square)](https://travis-ci.org/thephpleague/html-to-markdown) 7 | [![Coverage Status](https://img.shields.io/scrutinizer/coverage/g/thephpleague/html-to-markdown.svg?style=flat-square)](https://scrutinizer-ci.com/g/thephpleague/html-to-markdown/code-structure) 8 | [![Quality Score](https://img.shields.io/scrutinizer/g/thephpleague/html-to-markdown.svg?style=flat-square)](https://scrutinizer-ci.com/g/thephpleague/html-to-markdown) 9 | [![Total Downloads](https://img.shields.io/packagist/dt/league/html-to-markdown.svg?style=flat-square)](https://packagist.org/packages/league/html-to-markdown) 10 | 11 | Library which converts HTML to [Markdown](http://daringfireball.net/projects/markdown/) for your sanity and convenience. 12 | 13 | 14 | **Requires**: PHP 5.3+ 15 | 16 | **Lead Developer**: [@colinodell](http://twitter.com/colinodell) 17 | 18 | **Original Author**: [@nickcernis](http://twitter.com/nickcernis) 19 | 20 | 21 | ### Why convert HTML to Markdown? 22 | 23 | *"What alchemy is this?"* you mutter. *"I can see why you'd convert [Markdown to HTML](https://github.com/thephpleague/commonmark),"* you continue, already labouring the question somewhat, *"but why go the other way?"* 24 | 25 | Typically you would convert HTML to Markdown if: 26 | 27 | 1. You have an existing HTML document that needs to be edited by people with good taste. 28 | 2. You want to store new content in HTML format but edit it as Markdown. 29 | 3. You want to convert HTML email to plain text email. 30 | 4. You know a guy who's been converting HTML to Markdown for years, and now he can speak Elvish. You'd quite like to be able to speak Elvish. 31 | 5. You just really like Markdown. 32 | 33 | ### How to use it 34 | 35 | Require the library in your composer.json: 36 | 37 | { 38 | "require": { 39 | "league/html-to-markdown": "~4.0" 40 | } 41 | } 42 | 43 | Then `composer install` and add `require 'vendor/autoload.php';` to the top of your script. 44 | 45 | Next, create a new HtmlConverter instance, passing in your valid HTML code to its `convert()` function: 46 | 47 | use League\HTMLToMarkdown\HtmlConverter; 48 | 49 | $converter = new HtmlConverter(); 50 | 51 | $html = "

Quick, to the Batpoles!

"; 52 | $markdown = $converter->convert($html); 53 | 54 | The `$markdown` variable now contains the Markdown version of your HTML as a string: 55 | 56 | echo $markdown; // ==> ### Quick, to the Batpoles! 57 | 58 | The included `demo` directory contains an HTML->Markdown conversion form to try out. 59 | 60 | ### Conversion options 61 | 62 | By default, HTML To Markdown preserves HTML tags without Markdown equivalents, like `` and `
`. 63 | 64 | To strip HTML tags that don't have a Markdown equivalent while preserving the content inside them, set `strip_tags` to true, like this: 65 | 66 | $converter = new HtmlConverter(array('strip_tags' => true)); 67 | 68 | $html = 'Turnips!'; 69 | $markdown = $converter->convert($html); // $markdown now contains "Turnips!" 70 | 71 | Or more explicitly, like this: 72 | 73 | $converter = new HtmlConverter(); 74 | $converter->setOption('strip_tags', true); 75 | 76 | $html = 'Turnips!'; 77 | $markdown = $converter->convert($html); // $markdown now contains "Turnips!" 78 | 79 | Note that only the tags themselves are stripped, not the content they hold. 80 | 81 | To strip tags and their content, pass a space-separated list of tags in `remove_nodes`, like this: 82 | 83 | $converter = new HtmlConverter(array('remove_nodes' => 'span div')); 84 | 85 | $html = 'Turnips!
Monkeys!
'; 86 | $markdown = $converter->convert($html); // $markdown now contains "" 87 | 88 | ### Style options 89 | 90 | Bold and italic tags are converted using the asterisk syntax by default. Change this to the underlined syntax using the `bold_style` and `italic_style` options. 91 | 92 | $converter = new HtmlConverter(); 93 | $converter->setOption('italic_style', '_'); 94 | $converter->setOption('bold_style', '__'); 95 | 96 | $html = 'Italic and a bold'; 97 | $markdown = $converter->convert($html); // $markdown now contains "_Italic_ and a __bold__" 98 | 99 | ### Limitations 100 | 101 | - Markdown Extra, MultiMarkdown and other variants aren't supported – just Markdown. 102 | 103 | ### Known issues 104 | 105 | - Nested lists and lists containing multiple paragraphs aren't converted correctly. 106 | - Lists inside blockquotes aren't converted correctly. 107 | - Any reported [open issues here](https://github.com/thephpleague/html-to-markdown/issues?state=open). 108 | 109 | [Report your issue or request a feature here.](https://github.com/thephpleague/html-to-markdown/issues/new) Issues with patches or failing tests are especially welcome. 110 | 111 | ### Style notes 112 | 113 | - Setext (underlined) headers are the default for H1 and H2. If you prefer the ATX style for H1 and H2 (# Header 1 and ## Header 2), set `header_style` to 'atx' in the options array when you instantiate the object: 114 | 115 | `$converter = new HtmlConverter(array('header_style'=>'atx'));` 116 | 117 | Headers of H3 priority and lower always use atx style. 118 | 119 | - Links and images are referenced inline. Footnote references (where image src and anchor href attributes are listed in the footnotes) are not used. 120 | - Blockquotes aren't line wrapped – it makes the converted Markdown easier to edit. 121 | 122 | ### Dependencies 123 | 124 | HTML To Markdown requires PHP's [xml](http://www.php.net/manual/en/xml.installation.php), [lib-xml](http://www.php.net/manual/en/libxml.installation.php), and [dom](http://www.php.net/manual/en/dom.installation.php) extensions, all of which are enabled by default on most distributions. 125 | 126 | Errors such as "Fatal error: Class 'DOMDocument' not found" on distributions such as CentOS that disable PHP's xml extension can be resolved by installing php-xml. 127 | 128 | ### Contributors 129 | 130 | Many thanks to all [contributors](https://github.com/thephpleague/html-to-markdown/graphs/contributors) so far. Further improvements and feature suggestions are very welcome. 131 | 132 | ### How it works 133 | 134 | HTML To Markdown creates a DOMDocument from the supplied HTML, walks through the tree, and converts each node to a text node containing the equivalent markdown, starting from the most deeply nested node and working inwards towards the root node. 135 | 136 | ### To-do 137 | 138 | - Support for nested lists and lists inside blockquotes. 139 | - Offer an option to preserve tags as HTML if they contain attributes that can't be represented with Markdown (e.g. `style`). 140 | 141 | ### Trying to convert Markdown to HTML? 142 | 143 | Use one of these great libraries: 144 | 145 | - [league/commonmark](https://github.com/thephpleague/commonmark) (recommended) 146 | - [cebe/markdown](https://github.com/cebe/markdown) 147 | - [PHP Markdown](https://michelf.ca/projects/php-markdown/) 148 | - [Parsedown](https://github.com/erusev/parsedown) 149 | 150 | No guarantees about the Elvish, though. 151 | 152 | -------------------------------------------------------------------------------- /field/wysiwyg.php: -------------------------------------------------------------------------------- 1 | tags with all 15 | * their attributes. This will be used to strip them from 16 | * the editor output on saving the field. 17 | * 18 | * @since 1.0.0 19 | */ 20 | const SPAN_REMOVAL_REGEX = '/<\s*\/?\s*span[^>]*>/i'; 21 | 22 | /** 23 | * Define frontend assets 24 | * 25 | * @var array 26 | * @since 1.0.0 27 | */ 28 | public static $assets = array( 29 | 'js' => array( 30 | 'vendor/medium-editor.min.js', 31 | 'vendor/rangy-core.min.js', 32 | 'vendor/rangy-classapplier.min.js', 33 | 'del-button.js', 34 | 'ins-button.js', 35 | 'mark-button.js', 36 | 'wysiwyg.js', 37 | ), 38 | 'css' => array( 39 | 'wysiwyg.css', 40 | 'vendor/medium-editor.min.css', 41 | 'medium-editor-theme-kirby.css', 42 | ), 43 | ); 44 | 45 | /** 46 | * Array of buttons to display in the editor toolbar 47 | * 48 | * @var array 49 | * @since 1.0.0 50 | */ 51 | public $buttons; 52 | 53 | /** 54 | * Heading markdown style to use in output 55 | * 56 | * @var string 57 | * @since 1.0.0 58 | */ 59 | protected $headingStyle; 60 | 61 | /** 62 | * Default configuration values 63 | * 64 | * @var array 65 | * @since 1.0.0 66 | */ 67 | protected $defaults = array( 68 | 'buttons' => array( 69 | 'h1', 70 | 'h2', 71 | 'bold', 72 | 'italic', 73 | 'anchor', 74 | 'quote', 75 | 'unorderedlist', 76 | 'orderedlist', 77 | 'pre', 78 | ), 79 | 'heading-style' => 'atx', 80 | 'double-returns' => false, 81 | ); 82 | 83 | /** 84 | * Load and prepare configuration 85 | * 86 | * @since 1.0.0 87 | * 88 | * @return \WysiwygField 89 | */ 90 | public function __construct() 91 | { 92 | /* 93 | (1) Load button configuration 94 | */ 95 | $this->buttons = c::get('field.wysiwyg.buttons', false); 96 | if(!is_array($this->buttons) or (count($this->buttons) <= 0)) 97 | { 98 | $this->buttons = $this->defaults['buttons']; 99 | } 100 | 101 | /* 102 | (2) Load heading style configuration 103 | */ 104 | $this->headingStyle = c::get('field.wysiwyg.heading-style', false); 105 | if(!in_array($this->headingStyle, array('atx', 'setext'))) 106 | { 107 | $this->headingStyle = $this->defaults['heading-style']; 108 | } 109 | 110 | /* 111 | (3) Load double returns configuration 112 | */ 113 | $this->doubleReturns = c::get('field.wysiwyg.double-returns', null); 114 | if(!is_bool($this->doubleReturns)) 115 | { 116 | $this->doubleReturns = $this->defaults['double-returns']; 117 | } 118 | 119 | /* 120 | (4) Load drag/drop configuration 121 | */ 122 | $this->kirbyDragDrop = c::get('field.wysiwyg.dragdrop.kirby', false); 123 | if(!is_bool($this->kirbyDragDrop)) 124 | { 125 | $this->kirbyDragDrop = false; 126 | } 127 | $this->mediumDragDrop = c::get('field.wysiwyg.dragdrop.medium', false); 128 | if(!is_bool($this->mediumDragDrop)) 129 | { 130 | $this->mediumDragDrop = false; 131 | } 132 | } 133 | 134 | /** 135 | * Create input element 136 | * 137 | * @since 1.0.0 138 | * 139 | * @return \Brick 140 | */ 141 | public function input() 142 | { 143 | $input = new Brick('textarea'); 144 | $input->addClass('input wysiwyg-editor-input'); 145 | $input->attr(array( 146 | 'required' => $this->required(), 147 | 'name' => $this->name(), 148 | 'readonly' => 'readonly', 149 | 'id' => $this->id() 150 | )); 151 | $input->html($this->convertToHtml($this->value() ?: '')); 152 | $input->data(array( 153 | 'field' => 'wysiwygeditorfield', 154 | 'editor' => '#' . $this->id() . '-editor', 155 | 'dragdrop-kirby' => $this->kirbyDragDrop, 156 | )); 157 | return $input; 158 | } 159 | 160 | /** 161 | * Create content element 162 | * 163 | * This appends our main editor
to the fields markup. 164 | * 165 | * @since 1.0.0 166 | * 167 | * @return \Brick 168 | */ 169 | public function content() 170 | { 171 | $content = parent::content(); 172 | $content->append($this->editor()); 173 | return $content; 174 | } 175 | 176 | /** 177 | * Create editor element 178 | * 179 | * This creates our main editor
. 180 | * 181 | * @since 1.0.0 182 | * 183 | * @return \Brick 184 | */ 185 | protected function editor() 186 | { 187 | /* 188 | Prepare editor element 189 | */ 190 | $editor = new Brick('div'); 191 | $editor->addClass('input'); 192 | $editor->addClass('wysiwyg-editor'); 193 | $editor->attr('id', $this->id() . '-editor'); 194 | $editor->data(array( 195 | 'storage' => $this->id(), 196 | 'buttons' => implode(',', $this->buttons), 197 | 'double-returns' => $this->doubleReturns, 198 | 'dragdrop-medium' => $this->mediumDragDrop, 199 | )); 200 | 201 | /* 202 | Parse markdown and set editor content 203 | */ 204 | $editor->html($this->convertToHtml($this->value() ?: '')); 205 | return $editor; 206 | } 207 | 208 | /** 209 | * Convert result to markdown 210 | * 211 | * (1) This converts the HTML we get from the