diff --git a/Assets/js/checkbox.js b/Assets/js/checkbox.js index 589830a..9d615de 100644 --- a/Assets/js/checkbox.js +++ b/Assets/js/checkbox.js @@ -23,10 +23,10 @@ KB.on('dom.ready', function () { else { link = '?controller=CheckboxController&action=toggle&plugin=MarkdownPlus'; } - + KB.http.postJson(link, { 'task_id': task_id, - 'number': e.target.getAttribute('number') + 'number': e.target.dataset.number }); } } diff --git a/Controller/CheckboxController.php b/Controller/CheckboxController.php index 1c53e05..c50b5b5 100644 --- a/Controller/CheckboxController.php +++ b/Controller/CheckboxController.php @@ -7,7 +7,29 @@ class CheckboxController extends BaseController { - private const regexCheckbox = '/\[[x, ]\]/m'; + /* + # must match + + [x] 2 + * [ ] 3 + > - [ ] 1 + + [x] 2 + * [ ] 3 + > > * * [ ] 3 + > * > * * [ ] 3 + [ ] test 8 + + # must not match: + + - [x]1 + + [ ] + test [x] + test [x] + [] test 3 + [a] test + [x](www.google.de) test4 + */ + + private const regexCheckbox = '/^([+,\-,*,>, ] )*(\[[x, ]\] )/m'; private function findCheckBox($text, $number, &$offset) { @@ -17,7 +39,9 @@ private function findCheckBox($text, $number, &$offset) if ($offset >= $number) { return array( 'success' => true, - 'offset' => $matches[0][$count - $offset + $number - 1][1] + 1 + 'offset' => end($matches) // the actual box [ ]/[x] + [$count - $offset + $number - 1] // the requested checkbox + [1] + 1 // the offset to the checkbox content ); } return array('success' => false); @@ -35,69 +59,71 @@ private function togglechar(&$string, $offset) public function toggle() { $values = $this->request->getJson(); - - $foundCheckboxes = 0; - $number = intval($values['number']); $taskId = $values['task_id']; if (isset($taskId)) { $task = $this->taskFinderModel->getById($taskId); - $text = $task['description']; - $result = $this->findCheckBox($text, $number, $foundCheckboxes); - if ($result['success']) { - $this->togglechar($text, $result['offset']); - $task['description'] = $text; - $this->taskModificationModel->update($task); - return; - } + if ($task) { + $foundCheckboxes = 0; + $number = intval($values['number']); - if (isset($this->container["definitionOfDoneModel"])) { - foreach ($this->definitionOfDoneModel->getAll($taskId) as $subtask) { - $dod = $this->definitionOfDoneModel->getById($subtask['id']); + $text = $task['description']; + $result = $this->findCheckBox($text, $number, $foundCheckboxes); + if ($result['success']) { + $this->togglechar($text, $result['offset']); + $task['description'] = $text; + $this->taskModificationModel->update($task); + return; + } - $result = $this->findCheckBox($dod['title'], $number, $foundCheckboxes); - if ($result['success']) { - $this->togglechar($dod['title'], $result['offset']); - $this->definitionOfDoneModel->save($dod); - return; + if (isset($this->container["definitionOfDoneModel"])) { + foreach ($this->definitionOfDoneModel->getAll($taskId) as $subtask) { + $dod = $this->definitionOfDoneModel->getById($subtask['id']); + + $result = $this->findCheckBox($dod['title'], $number, $foundCheckboxes); + if ($result['success']) { + $this->togglechar($dod['title'], $result['offset']); + $this->definitionOfDoneModel->save($dod); + return; + } + + $result = $this->findCheckBox($dod['text'], $number, $foundCheckboxes); + if ($result['success']) { + $this->togglechar($dod['text'], $result['offset']); + $this->definitionOfDoneModel->save($dod); + return; + } } + } - $result = $this->findCheckBox($dod['text'], $number, $foundCheckboxes); - if ($result['success']) { - $this->togglechar($dod['text'], $result['offset']); - $this->definitionOfDoneModel->save($dod); - return; + if (isset($this->container["subtaskResultModel"])) { + foreach ($this->subtaskModel->getAll($taskId) as $subtask) { + $text = $this->subtaskResultModel->getById($subtask['id']); + $result = $this->findCheckBox($text, $number, $foundCheckboxes); + if ($result['success']) { + $this->togglechar($text, $result['offset']); + $this->subtaskResultModel->Save($subtask['id'], $text); + return; + } } } - } - if (isset($this->container["subtaskResultModel"])) { - foreach ($this->subtaskModel->getAll($taskId) as $subtask) { - $text = $this->subtaskResultModel->getById($subtask['id']); + $commentSortingDirection = $this->userMetadataCacheDecorator->get(UserMetadataModel::KEY_COMMENT_SORTING_DIRECTION, 'ASC'); + + foreach ($this->commentModel->getAll($taskId, $commentSortingDirection) as $comment) { + $text = $comment['comment']; + $result = $this->findCheckBox($text, $number, $foundCheckboxes); + if ($result['success']) { $this->togglechar($text, $result['offset']); - $this->subtaskResultModel->Save($subtask['id'], $text); + $comment['comment'] = $text; + $this->commentModel->update($comment); return; } } } - - $commentSortingDirection = $this->userMetadataCacheDecorator->get(UserMetadataModel::KEY_COMMENT_SORTING_DIRECTION, 'ASC'); - - foreach ($this->commentModel->getAll($taskId, $commentSortingDirection) as $comment) { - $text = $comment['comment']; - - $result = $this->findCheckBox($text, $number, $foundCheckboxes); - - if ($result['success']) { - $this->togglechar($text, $result['offset']); - $comment['comment'] = $text; - $this->commentModel->update($comment); - return; - } - } } } } diff --git a/Helper/CoreMarkdown.php b/Helper/CoreMarkdown.php index 87878dc..d36e24a 100755 --- a/Helper/CoreMarkdown.php +++ b/Helper/CoreMarkdown.php @@ -63,7 +63,7 @@ protected function inlineTaskLink(array $Excerpt) if (preg_match('!#(\d+)!i', $Excerpt['text'], $matches)) { $link = $this->buildTaskLink($matches[1]); - if (! empty($link)) { + if (!empty($link)) { return array( 'extent' => strlen($matches[0]), 'element' => array( @@ -89,11 +89,11 @@ protected function inlineTaskLink(array $Excerpt) */ protected function inlineUserLink(array $Excerpt) { - if (! $this->isPublicLink && preg_match('/^@([^\s,!:?]+)/', $Excerpt['text'], $matches)) { + if (!$this->isPublicLink && preg_match('/^@([^\s,!:?]+)/', $Excerpt['text'], $matches)) { $username = rtrim($matches[1], '.'); $user = $this->container['userCacheDecorator']->getByUsername($username); - if (! empty($user)) { + if (!empty($user)) { $url = $this->container['helper']->url->to('UserViewController', 'profile', array('user_id' => $user['id'])); $name = $user['name'] ?: $user['username']; @@ -128,7 +128,7 @@ private function buildTaskLink($task_id) if ($this->isPublicLink) { $token = $this->container['memoryCache']->proxy($this->container['taskFinderModel'], 'getProjectToken', $task_id); - if (! empty($token)) { + if (!empty($token)) { return $this->container['helper']->url->to( 'TaskViewController', 'readonly', @@ -165,4 +165,31 @@ protected function inlineLink($Excerpt) } return $Inline; } -} \ No newline at end of file + + function text($text) + { + $markup = parent::text($text); + + $this->nummerizeCheckboxes($markup); + + return $markup; + } + + private function nummerizeCheckboxes(&$markup) + { + $counter = new Counter; + $count = 0; + + $markup = preg_replace_callback("/activecheckbox\"/m", array($counter, 'count'), $markup, -1, $count, PREG_OFFSET_CAPTURE); + } +} + +class Counter +{ + private static $count = 0; + + public function count($matches) { + $this::$count++; + return $matches[0][0] . " data-number=". $this::$count . " "; + } +}; \ No newline at end of file diff --git a/vendor/erusev/parsedown-extra/ParsedownExtra.php b/vendor/erusev/parsedown-extra/ParsedownExtra.php index 3cdea88..7a58c39 100644 --- a/vendor/erusev/parsedown-extra/ParsedownExtra.php +++ b/vendor/erusev/parsedown-extra/ParsedownExtra.php @@ -628,19 +628,30 @@ protected function processTag($elementMarkup) # recursive $elementMarkup = mb_convert_encoding($elementMarkup, 'HTML-ENTITIES', 'UTF-8'); # http://stackoverflow.com/q/4879946/200145 - $DOMDocument->loadHTML($elementMarkup); - - if (!$DOMDocument->validate()) { - $errormessage = 'could not parse html
'; - $errors = libxml_get_errors(); + $success = $DOMDocument->loadHTML($elementMarkup); + $DOMDocument->removeChild($DOMDocument->doctype); + + $errors = libxml_get_errors(); + if ($errors) + { + $errormessage = "

HTML-parser error:


"; + $errormessage .= "The input was interpret as HTML - did you miss the markdown=1 attribute?
"; foreach ($errors as $error) { - $errormessage .= $error->message; + $errormessage .= "Line: " . $error->line . " - " . $error->message; $errormessage .= '
'; } return $errormessage; } - $DOMDocument->removeChild($DOMDocument->doctype); + if (!isset($DOMDocument->firstChild->firstChild->firstChild)) + { + $errormessage = "

General HTML-parser error:


"; + $errormessage .= "The input was interpret as HTML - did you miss the markdown=1 attribute?
"; + $errormessage .= "Input:
" . htmlspecialchars($elementMarkup) . "
"; + $errormessage .= "Output:
" . htmlspecialchars($DOMDocument->saveHTML()) . "
"; + return $errormessage; + } + $DOMDocument->replaceChild($DOMDocument->firstChild->firstChild->firstChild, $DOMDocument->firstChild); $elementText = ''; diff --git a/vendor/erusev/parsedown/Parsedown.php b/vendor/erusev/parsedown/Parsedown.php index 1832db7..d8b0f89 100644 --- a/vendor/erusev/parsedown/Parsedown.php +++ b/vendor/erusev/parsedown/Parsedown.php @@ -1977,7 +1977,7 @@ static function instance($name = 'default') protected $regexHtmlAttribute = '[a-zA-Z_:][\w:.-]*+(?:\s*+=\s*+(?:[^"\'=<>`\s]+|"[^"]*+"|\'[^\']*+\'))?+'; protected $voidElements = array( - 'area', 'base', 'br', 'col', 'command', 'embed', 'hr', 'img', 'input', 'link', 'meta', 'param', 'source', + 'area', 'base', 'br', 'col', 'command', 'embed', 'hr', 'img', 'input', 'link', 'meta', 'param', 'source' ); protected $textLevelElements = array( diff --git a/vendor/leblanc-simon/parsedown-checkbox/ParsedownCheckbox.php b/vendor/leblanc-simon/parsedown-checkbox/ParsedownCheckbox.php index f8781d8..6d8e548 100644 --- a/vendor/leblanc-simon/parsedown-checkbox/ParsedownCheckbox.php +++ b/vendor/leblanc-simon/parsedown-checkbox/ParsedownCheckbox.php @@ -74,7 +74,7 @@ protected function checkboxUnchecked($text) $text = self::escape($text); } - return ' ' . $this->format($text); + return ' ' . $this->format($text); } protected function checkboxChecked($text) @@ -83,7 +83,7 @@ protected function checkboxChecked($text) $text = self::escape($text); } - return ' ' . $this->format($text); + return ' ' . $this->format($text); } /**