. * */ /* Name: Table of content for posts Slug: toc-posts Category: content Url: https://www.vvveb.com Description: Show navigable table of content for posts Author: givanz Version: 0.1 Thumb: toc-posts.svg Author url: https://www.vvveb.com */ use \Vvveb\System\Event as Event; use Vvveb\System\Core\View; if (! defined('V_VERSION')) { die('Invalid request!'); } class TocPostsPlugin { private $headings; private $html; public function setHtml($html) { $this->html = $html; $this->setHeadings(); } public function html() { $html = $this->html; $matches = $this->headings; foreach ($matches[1] as $index => $item) { $html = str_replace( '>' . $item . '' . $item . 'setHeadingIds(); return $this->html; } public function setHeadingIds() { foreach ($this->headings[0] as $index => $heading) { $slug = $this->headings[2][$index]; $heading_id = preg_replace('/html = str_replace($heading, $heading_id, $this->html); } } public function list() { $out = ''; $matches = $this->headings; $old_depth = substr($matches[0][0] ?? '', 2, 1) ?? 0; $current_url = $_SERVER['REQUEST_URI']; $list = []; foreach ($matches[1] as $key => $item) { $depth = (int)substr($matches[0][$key], 2, 1); $url = $current_url . '#' . $matches[2][$key]; $onclick = "document.location.hash='{$matches[2][$key]}';return false"; $list[] = ['name' => $item, /* 'slug' => $slug,*/ 'url' => $url, 'onclick' => $onclick, 'depth' => $depth - 1]; $old_depth = $depth; } return $list; } public function listHtml() { $out = ''; $matches = $this->headings; $old_depth = substr($matches[0][0], 2, 1); $current_url = $_SERVER['REQUEST_URI']; foreach ($matches[1] as $key => $item) { $depth = substr($matches[0][$key], 2, 1); if ($old_depth > $depth) { $out .= "\n"; } elseif ($old_depth < $depth) { $out .= "
  • \n"; $out .= "
      \n"; } $url = $current_url . '#' . $matches[2][$key]; $out .= sprintf("
    1. %s
    2. ", $url, $item); $old_depth = $depth; } return "
        \n$out\n
      \n\n"; } private function setHeadings() { preg_match_all('|]+>(.*)]+>|iU', $this->html, $matches); $slugs = []; foreach ($matches[1] as $item) { $slugs[] = $this->slugify($item); } $this->headings = $matches; $this->headings[2] = $slugs; } function slugify($string, $replace = [], $delimiter = '-') { if (! empty($replace)) { $string = str_replace((array) $replace, ' ', $string); } $string = preg_replace('/[^a-zA-Z0-9\/_|+ -]/', '', $string); $string = strtolower($string); $string = preg_replace('/[\/_|+ -]+/', $delimiter, $string); $string = trim($string, $delimiter); return $string; } function admin() { //add admin menu item } function generateToc($post) { } function toc(&$post) { $this->setHtml($post['content']); $this->getHtml(); $post['content'] = $this->getHtml(); $post['toc'] = $this->list(); return $post; } function app() { //register component Event::on('Vvveb\Component\Post', 'results', __CLASS__, function ($results = false) { if ($results && isset($results['content'])) { $this->toc($results); } return [$results]; }); Event::on('Vvveb\Component\Posts', 'results', __CLASS__, function ($results = false) { if ($results && isset($results[0])) { $this->toc($results[0]); } return [$results]; }); $view = View::getInstance(); $template = $view->getTemplateEngineInstance(); $template->loadTemplateFile(__DIR__ . '/app/template/toc-posts.tpl'); } function __construct() { if (APP == 'admin') { $this->admin(); } else { if (APP == 'app') { $this->app(); } } } } $tocPostsPlugin = new TocPostsPlugin();