Skip to content

Commit

Permalink
Merge pull request #22 from Chaosmeister/master
Browse files Browse the repository at this point in the history
fix checkboxhandling with nested checkboxes
  • Loading branch information
Chaosmeister authored Nov 22, 2023
2 parents 9791529 + d896ca8 commit 6314f1b
Show file tree
Hide file tree
Showing 6 changed files with 127 additions and 63 deletions.
4 changes: 2 additions & 2 deletions Assets/js/checkbox.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
});
}
}
Expand Down
118 changes: 72 additions & 46 deletions Controller/CheckboxController.php
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand All @@ -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);
Expand All @@ -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;
}
}
}
}
}
37 changes: 32 additions & 5 deletions Helper/CoreMarkdown.php
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand All @@ -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'];

Expand Down Expand Up @@ -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',
Expand Down Expand Up @@ -165,4 +165,31 @@ protected function inlineLink($Excerpt)
}
return $Inline;
}
}

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 . " ";
}
};
25 changes: 18 additions & 7 deletions vendor/erusev/parsedown-extra/ParsedownExtra.php
Original file line number Diff line number Diff line change
Expand Up @@ -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<br>';
$errors = libxml_get_errors();
$success = $DOMDocument->loadHTML($elementMarkup);
$DOMDocument->removeChild($DOMDocument->doctype);

$errors = libxml_get_errors();
if ($errors)
{
$errormessage = "<h1>HTML-parser error:</h1><br>";
$errormessage .= "The input was interpret as HTML - did you miss the <code>markdown=1</code> attribute?<br>";
foreach ($errors as $error) {
$errormessage .= $error->message;
$errormessage .= "Line: " . $error->line . " - " . $error->message;
$errormessage .= '<br>';
}
return $errormessage;
}

$DOMDocument->removeChild($DOMDocument->doctype);
if (!isset($DOMDocument->firstChild->firstChild->firstChild))
{
$errormessage = "<h1>General HTML-parser error:</h1><br>";
$errormessage .= "The input was interpret as HTML - did you miss the <code>markdown=1</code> attribute?<br>";
$errormessage .= "Input:<pre><code>" . htmlspecialchars($elementMarkup) . "</code></pre>";
$errormessage .= "Output:<pre><code>" . htmlspecialchars($DOMDocument->saveHTML()) . "</code></pre>";
return $errormessage;
}

$DOMDocument->replaceChild($DOMDocument->firstChild->firstChild->firstChild, $DOMDocument->firstChild);

$elementText = '';
Expand Down
2 changes: 1 addition & 1 deletion vendor/erusev/parsedown/Parsedown.php
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
4 changes: 2 additions & 2 deletions vendor/leblanc-simon/parsedown-checkbox/ParsedownCheckbox.php
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ protected function checkboxUnchecked($text)
$text = self::escape($text);
}

return '<input type="checkbox" class="activecheckbox" number="'. ParsedownCheckbox::$count++ .'"/> ' . $this->format($text);
return '<input type="checkbox" class="activecheckbox"> ' . $this->format($text);
}

protected function checkboxChecked($text)
Expand All @@ -83,7 +83,7 @@ protected function checkboxChecked($text)
$text = self::escape($text);
}

return '<input type="checkbox" class="activecheckbox" number="'. ParsedownCheckbox::$count++ .'" checked/> ' . $this->format($text);
return '<input type="checkbox" class="activecheckbox" checked/> ' . $this->format($text);
}

/**
Expand Down

0 comments on commit 6314f1b

Please sign in to comment.