show_toc            = true;
			$this->exclude_post_types  = [ 'attachment', 'revision', 'nav_menu_item', 'safecss' ];
			$this->collision_collector = [];
			// get options
			$defaults = [  // default options
				'fragment_prefix'                    => 'i',
				'position'                           => TOC_POSITION_BEFORE_FIRST_HEADING,
				'start'                              => 4,
				'show_heading_text'                  => true,
				'heading_text'                       => 'Contents',
				'auto_insert_post_types'             => [ 'page' ],
				'show_heirarchy'                     => true,
				'ordered_list'                       => true,
				'smooth_scroll'                      => false,
				'smooth_scroll_offset'               => TOC_SMOOTH_SCROLL_OFFSET,
				'visibility'                         => true,
				'visibility_show'                    => 'show',
				'visibility_hide'                    => 'hide',
				'visibility_hide_by_default'         => false,
				'width'                              => 'Auto',
				'width_custom'                       => '275',
				'width_custom_units'                 => 'px',
				'wrapping'                           => TOC_WRAPPING_NONE,
				'font_size'                          => '95',
				'font_size_units'                    => '%',
				'theme'                              => TOC_THEME_GREY,
				'custom_background_colour'           => TOC_DEFAULT_BACKGROUND_COLOUR,
				'custom_border_colour'               => TOC_DEFAULT_BORDER_COLOUR,
				'custom_title_colour'                => TOC_DEFAULT_TITLE_COLOUR,
				'custom_links_colour'                => TOC_DEFAULT_LINKS_COLOUR,
				'custom_links_hover_colour'          => TOC_DEFAULT_LINKS_HOVER_COLOUR,
				'custom_links_visited_colour'        => TOC_DEFAULT_LINKS_VISITED_COLOUR,
				'lowercase'                          => false,
				'hyphenate'                          => false,
				'bullet_spacing'                     => false,
				'include_homepage'                   => false,
				'exclude_css'                        => false,
				'exclude'                            => '',
				'heading_levels'                     => [ 1, 2, 3, 4, 5, 6 ],
				'restrict_path'                      => '',
				'css_container_class'                => '',
				'sitemap_show_page_listing'          => true,
				'sitemap_show_category_listing'      => true,
				'sitemap_heading_type'               => 3,
				'sitemap_pages'                      => 'Pages',
				'sitemap_categories'                 => 'Categories',
				'show_toc_in_widget_only'            => false,
				'show_toc_in_widget_only_post_types' => [ 'page' ],
			];
			$options       = get_option( 'toc-options', $defaults );
			$this->options = wp_parse_args( $options, $defaults );
			add_action( 'plugins_loaded', [ $this, 'plugins_loaded' ] );
			add_action( 'wp_enqueue_scripts', [ $this, 'wp_enqueue_scripts' ] );
			add_action( 'admin_init', [ $this, 'admin_init' ] );
			add_action( 'admin_menu', [ $this, 'admin_menu' ] );
			add_action( 'widgets_init', [ $this, 'widgets_init' ] );
			add_action( 'sidebar_admin_setup', [ $this, 'sidebar_admin_setup' ] );
			add_action( 'init', [ $this, 'init' ] );
			add_filter( 'the_content', [ $this, 'the_content' ], 100 );  // run after shortcodes are interpreted (level 10)
			add_filter( 'plugin_action_links', [ $this, 'plugin_action_links' ], 10, 2 );
			add_filter( 'widget_text', 'do_shortcode' );
			add_shortcode( 'toc', [ $this, 'shortcode_toc' ] );
			add_shortcode( 'no_toc', [ $this, 'shortcode_no_toc' ] );
			add_shortcode( 'sitemap', [ $this, 'shortcode_sitemap' ] );
			add_shortcode( 'sitemap_pages', [ $this, 'shortcode_sitemap_pages' ] );
			add_shortcode( 'sitemap_categories', [ $this, 'shortcode_sitemap_categories' ] );
			add_shortcode( 'sitemap_posts', [ $this, 'shortcode_sitemap_posts' ] );
		}
		public function __destruct() {}
		public function get_options() {
			return $this->options;
		}
		public function set_option( $options ) {
			$this->options = array_merge( $this->options, $options );
		}
		/**
		 * Allows the developer to disable TOC execution
		 */
		public function disable() {
			$this->show_toc = false;
		}
		/**
		 * Allows the developer to enable TOC execution
		 */
		public function enable() {
			$this->show_toc = true;
		}
		public function set_show_toc_in_widget_only( $value = false ) {
			if ( $value ) {
				$this->options['show_toc_in_widget_only'] = true;
			} else {
				$this->options['show_toc_in_widget_only'] = false;
			}
			update_option( 'toc-options', $this->options );
		}
		public function set_show_toc_in_widget_only_post_types( $value = false ) {
			if ( $value ) {
				$this->options['show_toc_in_widget_only_post_types'] = $value;
			} else {
				$this->options['show_toc_in_widget_only_post_types'] = [];
			}
			update_option( 'toc-options', $this->options );
		}
		public function get_exclude_post_types() {
			return $this->exclude_post_types;
		}
		public function plugin_action_links( $links, $file ) {
			if ( 'table-of-contents-plus/toc.php' === $file ) {
				$settings_link = '' . __( 'Settings', 'table-of-contents-plus' ) . '';
				$links         = array_merge( [ $settings_link ], $links );
			}
			return $links;
		}
		public function shortcode_toc( $attributes ) {
			$atts = shortcode_atts(
				[
					'label'          => $this->options['heading_text'],
					'label_show'     => $this->options['visibility_show'],
					'label_hide'     => $this->options['visibility_hide'],
					'no_label'       => false,
					'class'          => false,
					'wrapping'       => $this->options['wrapping'],
					'heading_levels' => $this->options['heading_levels'],
					'exclude'        => $this->options['exclude'],
					'collapse'       => false,
					'no_numbers'     => false,
					'start'          => $this->options['start'],
				],
				$attributes
			);
			$re_enqueue_scripts = false;
			if ( $atts['no_label'] ) {
				$this->options['show_heading_text'] = false;
			}
			if ( $atts['label'] ) {
				$this->options['heading_text'] = wp_kses_post( html_entity_decode( $atts['label'] ) );
			}
			if ( $atts['label_show'] ) {
				$this->options['visibility_show'] = wp_kses_post( html_entity_decode( $atts['label_show'] ) );
				$re_enqueue_scripts               = true;
			}
			if ( $atts['label_hide'] ) {
				$this->options['visibility_hide'] = wp_kses_post( html_entity_decode( $atts['label_hide'] ) );
				$re_enqueue_scripts               = true;
			}
			if ( $atts['class'] ) {
				$this->options['css_container_class'] = wp_kses_post( html_entity_decode( $atts['class'] ) );
			}
			if ( $atts['wrapping'] ) {
				switch ( strtolower( trim( $atts['wrapping'] ) ) ) {
					case 'left':
						$this->options['wrapping'] = TOC_WRAPPING_LEFT;
						break;
					case 'right':
						$this->options['wrapping'] = TOC_WRAPPING_RIGHT;
						break;
					default:
						// do nothing
				}
			}
			if ( $atts['exclude'] ) {
				$this->options['exclude'] = $atts['exclude'];
			}
			if ( $atts['collapse'] ) {
				$this->options['visibility_hide_by_default'] = true;
				$re_enqueue_scripts                          = true;
			}
			if ( $atts['no_numbers'] ) {
				$this->options['ordered_list'] = false;
			}
			if ( is_numeric( $atts['start'] ) ) {
				$this->options['start'] = $atts['start'];
			}
			if ( $re_enqueue_scripts ) {
				do_action( 'wp_enqueue_scripts' );
			}
			// if $atts['heading_levels'] is an array, then it came from the global options
			// and wasn't provided by per instance
			if ( $atts['heading_levels'] && ! is_array( $atts['heading_levels'] ) ) {
				// make sure they are numbers between 1 and 6 and put into
				// the $clean_heading_levels array if not already
				$clean_heading_levels = [];
				foreach ( explode( ',', $atts['heading_levels'] ) as $heading_level ) {
					if ( is_numeric( $heading_level ) ) {
						$heading_level = (int) $heading_level;
						if ( 1 <= $heading_level && $heading_level <= 6 ) {
							if ( ! in_array( $heading_level, $clean_heading_levels, true ) ) {
								$clean_heading_levels[] = (int) $heading_level;
							}
						}
					}
				}
				if ( count( $clean_heading_levels ) > 0 ) {
					$this->options['heading_levels'] = $clean_heading_levels;
				}
			}
			if ( ! is_search() && ! is_archive() && ! is_feed() ) {
				return '';
			} else {
				return '';
			}
		}
		public function shortcode_no_toc( $atts ) {
			$this->show_toc = false;
			return '';
		}
		public function shortcode_sitemap( $atts ) {
			$html = '';
			// only do the following if enabled
			if ( $this->options['sitemap_show_page_listing'] || $this->options['sitemap_show_category_listing'] ) {
				$html = '
';
				if ( $this->options['sitemap_show_page_listing'] ) {
					$html .=
						'
options['sitemap_heading_type'] . ' class="toc_sitemap_pages">' . htmlentities( $this->options['sitemap_pages'], ENT_COMPAT, 'UTF-8' ) . 'options['sitemap_heading_type'] . '>' .
						'
' .
							wp_list_pages(
								[
									'title_li' => '',
									'echo'     => false,
								]
							) .
						'
';
				}
				if ( $this->options['sitemap_show_category_listing'] ) {
					$html .=
						'
options['sitemap_heading_type'] . ' class="toc_sitemap_categories">' . htmlentities( $this->options['sitemap_categories'], ENT_COMPAT, 'UTF-8' ) . 'options['sitemap_heading_type'] . '>' .
						'
' .
							wp_list_categories(
								[
									'title_li' => '',
									'echo'     => false,
								]
							) .
						'
';
				}
				$html .= '
';
			if ( ! $atts['no_label'] ) {
				$html .= '
' . htmlentities( $atts['label'], ENT_COMPAT, 'UTF-8' ) . '';
			}
			$html .=
					'
' .
						wp_list_pages(
							[
								'title_li'     => '',
								'echo'         => false,
								'exclude'      => $atts['exclude'],
								'exclude_tree' => $atts['exclude_tree'],
								'hierarchical' => true,
								'child_of'     => $atts['child_of'],
							]
						) .
					'
' .
				'
';
			if ( ! $atts['no_label'] ) {
				$html .= '
' . htmlentities( $atts['label'], ENT_COMPAT, 'UTF-8' ) . '';
			}
			$html .=
					'
' .
						wp_list_categories(
							[
								'title_li'     => '',
								'echo'         => false,
								'exclude'      => $atts['exclude'],
								'exclude_tree' => $atts['exclude_tree'],
							]
						) .
					'
' .
				'
' . strtolower( $title[0] ) . '
';
						$letter = strtolower( $title[0] );
					}
				}
				$html .= '- ' . $title . '';
			}
			if ( $html ) {
				if ( $atts['separate'] ) {
					$html .= '
' . __( 'Options saved.', 'table-of-contents-plus' ) . '
' . __( 'Save failed.', 'table-of-contents-plus' ) . '
';
						if ( $this->options['show_heading_text'] ) {
							$toc_title = htmlentities( $this->options['heading_text'], ENT_COMPAT, 'UTF-8' );
							if ( false !== strpos( $toc_title, '%PAGE_TITLE%' ) ) {
								$toc_title = str_replace( '%PAGE_TITLE%', get_the_title(), $toc_title );
							}
							if ( false !== strpos( $toc_title, '%PAGE_NAME%' ) ) {
								$toc_title = str_replace( '%PAGE_NAME%', get_the_title(), $toc_title );
							}
							$html .= '
' . $toc_title . '
';
						}
						$html .= '