, * @link https://getkirby.com * @copyright Bastian Allgeier * @license https://getkirby.com/license */ class Blocks extends Plain { /** * @param \Kirby\Parsley\Element $node * @return array */ public function blockquote(Element $node): array { $citation = null; $text = []; // get all the text for the quote foreach ($node->children() as $child) { if (is_a($child, 'DOMText') === true) { $text[] = trim($child->textContent); } if (is_a($child, 'DOMElement') === true && $child->tagName !== 'footer') { $text[] = (new Element($child))->innerHTML($this->marks()); } } // filter empty blocks and separate text blocks with breaks $text = implode('', array_filter($text)); // get the citation from the footer if ($footer = $node->find('footer')) { $citation = $footer->innerHTML($this->marks()); } return [ 'content' => [ 'citation' => $citation, 'text' => $text ], 'type' => 'quote', ]; } /** * Creates the fallback block type * if no other block can be found * * @param \Kirby\Parsley\Element|string $element * @return array|null */ public function fallback($element): ?array { if (is_a($element, Element::class) === true) { $html = $element->innerHtml(); // wrap the inner HTML in a p tag if it doesn't // contain one yet. if (Str::contains($html, '
') === false) { $html = '
' . $html . '
'; } } elseif (is_string($element) === true) { $html = trim($element); if (Str::length($html) === 0) { return null; } $html = '' . $html . '
'; } else { return null; } return [ 'content' => [ 'text' => $html, ], 'type' => 'text', ]; } /** * Converts a heading element to a heading block * * @param \Kirby\Parsley\Element $node * @return array */ public function heading(Element $node): array { $content = [ 'level' => strtolower($node->tagName()), 'text' => $node->innerHTML() ]; if ($id = $node->attr('id')) { $content['id'] = $id; } ksort($content); return [ 'content' => $content, 'type' => 'heading', ]; } /** * @param \Kirby\Parsley\Element $node * @return array */ public function iframe(Element $node): array { $caption = null; $src = $node->attr('src'); if ($figcaption = $node->find('ancestor::figure[1]//figcaption')) { $caption = $figcaption->innerHTML($this->marks()); // avoid parsing the caption twice $figcaption->remove(); } // reverse engineer video URLs if (preg_match('!player.vimeo.com\/video\/([0-9]+)!i', $src, $array) === 1) { $src = 'https://vimeo.com/' . $array[1]; } elseif (preg_match('!youtube.com\/embed\/([a-zA-Z0-9_-]+)!', $src, $array) === 1) { $src = 'https://youtube.com/watch?v=' . $array[1]; } elseif (preg_match('!youtube-nocookie.com\/embed\/([a-zA-Z0-9_-]+)!', $src, $array) === 1) { $src = 'https://youtube.com/watch?v=' . $array[1]; } else { $src = false; } // correct video URL if ($src) { return [ 'content' => [ 'caption' => $caption, 'url' => $src ], 'type' => 'video', ]; } return [ 'content' => [ 'text' => $node->outerHTML() ], 'type' => 'markdown', ]; } /** * @param \Kirby\Parsley\Element $node * @return array */ public function img(Element $node): array { $caption = null; $link = null; if ($figcaption = $node->find('ancestor::figure[1]//figcaption')) { $caption = $figcaption->innerHTML($this->marks()); // avoid parsing the caption twice $figcaption->remove(); } if ($a = $node->find('ancestor::a')) { $link = $a->attr('href'); } return [ 'content' => [ 'alt' => $node->attr('alt'), 'caption' => $caption, 'link' => $link, 'location' => 'web', 'src' => $node->attr('src'), ], 'type' => 'image', ]; } /** * Converts a list element to HTML * * @param \Kirby\Parsley\Element $node * @return string */ public function list(Element $node): string { $html = []; foreach ($node->filter('li') as $li) { $innerHtml = ''; foreach ($li->children() as $child) { if (is_a($child, 'DOMText') === true) { $innerHtml .= $child->textContent; } elseif (is_a($child, 'DOMElement') === true) { $child = new Element($child); if (in_array($child->tagName(), ['ul', 'ol']) === true) { $innerHtml .= $this->list($child); } else { $innerHtml .= $child->innerHTML($this->marks()); } } } $html[] = '