diff --git a/src/Kunoichi/TocGenerator/Item.php b/src/Kunoichi/TocGenerator/Item.php index f8e8a4b..0694fed 100644 --- a/src/Kunoichi/TocGenerator/Item.php +++ b/src/Kunoichi/TocGenerator/Item.php @@ -13,7 +13,7 @@ class Item { /** * @var \DOMNode */ - private $dom = null; + protected $dom = null; /** * Item constructor. diff --git a/src/Kunoichi/TocGenerator/Parser.php b/src/Kunoichi/TocGenerator/Parser.php index f05c848..81e5a9a 100644 --- a/src/Kunoichi/TocGenerator/Parser.php +++ b/src/Kunoichi/TocGenerator/Parser.php @@ -27,17 +27,21 @@ class Parser { protected $title = ''; + protected $item_class = ''; + /** * Constructor * * @param int $max_depth * @param bool $ignore_deeper * @param string $id + * @param string $item_class */ - public function __construct( $max_depth = 3, $ignore_deeper = false, $id = 'content-section-' ) { + public function __construct( $max_depth = 3, $ignore_deeper = false, $id = 'content-section-', $item_class = Item::class ) { $this->id_prefix = $id; $this->max_depth = $max_depth; $this->ignore_deeper = $ignore_deeper; + $this->item_class = $item_class; } /** @@ -95,7 +99,7 @@ public function parse_html( $html ) { if ( $this->ignore_deeper && ( (int) $level > $this->max_depth ) ) { continue; } - $items[] = new Item( $hn ); + $items[] = new $this->item_class( $hn ); } return $items; } diff --git a/src/Kunoichi/TocGenerator/WpItem.php b/src/Kunoichi/TocGenerator/WpItem.php new file mode 100644 index 0000000..26c543b --- /dev/null +++ b/src/Kunoichi/TocGenerator/WpItem.php @@ -0,0 +1,76 @@ +page(); + + if ( $page !== $item_page ) { + // @see _wp_link_page() + global $wp_rewrite; + $post = get_post(); + $query_args = array(); + $item_page = $this->page(); + + if ( 1 === $item_page ) { + $url = get_permalink(); + } else { + if ( ! get_option( 'permalink_structure' ) || in_array( get_post_status(), array( + 'draft', + 'pending' + ), true ) ) { + $url = add_query_arg( 'page', $item_page, get_permalink() ); + } elseif ( 'page' === get_option( 'show_on_front' ) && (int) get_option( 'page_on_front' ) === get_the_ID() ) { + $url = trailingslashit( get_permalink() ) . user_trailingslashit( "$wp_rewrite->pagination_base/" . $item_page, 'single_paged' ); + } else { + $url = trailingslashit( get_permalink() ) . user_trailingslashit( $item_page, 'single_paged' ); + } + } + + if ( is_preview() ) { + if ( ( 'draft' !== $post->post_status ) && isset( $_GET['preview_id'], $_GET['preview_nonce'] ) ) { + $query_args['preview_id'] = wp_unslash( $_GET['preview_id'] ); + $query_args['preview_nonce'] = wp_unslash( $_GET['preview_nonce'] ); + } + $url = get_preview_post_link( $post, $query_args, $url ); + } + $link = sprintf( '%s%s', $url, $this->href() ); + + } else { + $link = $this->href(); + } + + return sprintf( '%s', esc_url( $link ), esc_attr( $item_page ), esc_html( $this->text() ) ); + } + + /** + * Return page attributes + * + * @return int + */ + public function page() { + return (int) $this->dom->getAttribute( 'data-page' ); + } +} diff --git a/src/Kunoichi/TocGenerator/WpParser.php b/src/Kunoichi/TocGenerator/WpParser.php index 98c9cc7..3f34513 100644 --- a/src/Kunoichi/TocGenerator/WpParser.php +++ b/src/Kunoichi/TocGenerator/WpParser.php @@ -14,15 +14,18 @@ class WpParser extends Parser { protected $done = false; + protected $page_counter = 0; + /** * Constructor * * @param int $max_depth * @param bool $ignore_deeper * @param string $id + * @param string $item_class */ - public function __construct( $max_depth = 3, $ignore_deeper = false, $id = 'content-section-' ) { - parent::__construct( $max_depth, $ignore_deeper, $id ); + public function __construct( $max_depth = 3, $ignore_deeper = false, $id = 'content-section-', $item_class = WpItem::class ) { + parent::__construct( $max_depth, $ignore_deeper, $id, $item_class ); add_action( 'wp_head', [ $this, 'prepare' ] ); add_filter( 'the_content', [ $this, 'post_content' ] ); add_action( 'kunoichi_toc_generate', [ $this, 'generate' ], 10 ); @@ -56,9 +59,56 @@ public function post_content( $content ) { $this->save_parsed_html( $content ); $this->done = true; } + return $content; } + /** + * Add link id to html elements. + * + * @param string $html + * + * @return string + */ + public function add_link_html( $html ) { + $contents = preg_split( '//u', $html ); + if ( is_array( $contents ) ) { + $replaced_html = ''; + $this->page_counter = 0; + foreach ( $contents as $content ) { + $this->counter = 0; + $this->page_counter ++; + $replaced_html .= preg_replace_callback( '/<(h[1-6])([^>]*?)>/u', [ $this, 'convert_link' ], $content ); + } + + return $replaced_html; + } else { + return preg_replace_callback( '/<(h[1-6])([^>]*?)>/u', [ $this, 'convert_link' ], $html ); + } + } + + /** + * Add link to title elements. + * + * @param string[] $matches + * + * @return string + */ + protected function convert_link( $matches ) { + $this->counter ++; + $attributes = $matches[2]; + if ( preg_match( '/id=\'|"([\'"]*)(\'|")/u', $matches[2], $id_matches ) ) { + $id = $id_matches[1]; + } else { + $id = sprintf( '%s%d', $this->id_prefix, $this->counter ); + $attributes .= sprintf( ' id="%s"', $id ) . $matches[2]; + } + // Add an attribute for the page number. + $attributes .= sprintf( ' data-page="%d"', $this->page_counter ); + + return sprintf( '<%s%s>', $matches[1], $attributes ); + } + /** * If post id is *