# frozen_string_literal: true module Banzai module Filter # Using `[[_TOC_]]` or `[TOC]` (both case insensitive), inserts a Table of Contents list. # # `[[_TOC_]]` is based on the Gollum syntax. This way we have # some consistency between with wiki and normal markdown. # The support for this has been removed from GollumTagsFilter # # `[toc]` is a generally accepted form, used by Typora for example. # # Based on Banzai::Filter::GollumTagsFilter class TableOfContentsTagFilter < HTML::Pipeline::Filter TEXT_QUERY = %q(descendant-or-self::text()[ancestor::p and contains(translate(., 'TOC', 'toc'), 'toc')]) def call return doc if context[:no_header_anchors] doc.xpath(TEXT_QUERY).each do |node| if toc_tag?(node) # Support [TOC] / [toc] tags, which don't have a wrapping -tag process_toc_tag(node) elsif toc_tag_em?(node) # Support Gollum like ToC tag (`[[_TOC_]]` / `[[_toc_]]`), which will be converted # into `[[TOC]]` by the markdown filter, so it # needs special-case handling process_toc_tag_em(node) end end doc end private # Replace an entire `[[TOC]]` node with the result generated by # TableOfContentsFilter def process_toc_tag_em(node) process_toc_tag(node.parent) end # Replace an entire `[TOC]` node with the result generated by # TableOfContentsFilter def process_toc_tag(node) # we still need to go one step up to also replace the surrounding

node.parent.replace(result[:toc].presence || '') end def toc_tag_em?(node) node.content.casecmp?('toc') && node.parent.name == 'em' && node.parent.parent.text.casecmp?('[[toc]]') end def toc_tag?(node) node.parent.text.casecmp?('[toc]') end end end end