Changeset 11341 for sites/trunk/wordpress.org/public_html/wp-content/plugins/handbook/inc/table-of-contents.php
- Timestamp:
- 11/25/2021 01:11:00 AM (3 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
sites/trunk/wordpress.org/public_html/wp-content/plugins/handbook/inc/table-of-contents.php
r11118 r11341 46 46 } 47 47 48 function load_filters() {48 public function load_filters() { 49 49 if ( is_singular( $this->post_types ) && ! is_embed() ) { 50 50 add_filter( 'the_content', array( $this, 'add_toc' ) ); … … 103 103 } 104 104 105 $toc = ''; 106 107 $items = $this->get_tags( 'h([1-4])', $content ); 105 $toc = ''; 106 $items = $this->get_tags( 'h(?P<level>[1-4])', $content ); 108 107 109 108 if ( count( $items ) < 2 ) { … … 111 110 } 112 111 112 // Generate a list of the IDs in the document (generating them as needed). 113 113 $this->used_ids = $this->get_reserved_ids(); 114 for ( $i = 1; $i <= 4; $i++ ) 115 $content = $this->add_ids_and_jumpto_links( "h$i", $content ); 114 foreach ( $items as $i => $item ) { 115 $items[ $i ]['id'] = $this->get_id_for_item( $item ); 116 } 117 118 // Replace each level of the headings. 119 $content = $this->add_ids_and_jumpto_links( $items, $content ); 116 120 117 121 if ( ! apply_filters( 'handbook_display_toc', true ) ) { … … 119 123 } 120 124 121 if ( $items ) { 122 $contents_header = 'h' . $items[0][2]; // Duplicate the first <h#> tag in the document. 123 $toc .= $this->styles; 124 $toc .= '<div class="table-of-contents">'; 125 $toc .= "<$contents_header>" . esc_html( $this->args->header_text ) . "</$contents_header><ul class=\"items\">"; 126 $last_item = false; 127 $used_ids = $this->get_reserved_ids(); 128 129 foreach ( $items as $item ) { 130 if ( $last_item ) { 131 if ( $last_item < $item[2] ) 132 $toc .= "\n<ul>\n"; 133 elseif ( $last_item > $item[2] ) 134 $toc .= "\n</ul></li>\n"; 135 else 136 $toc .= "</li>\n"; 125 $contents_header = 'h' . $items[0]['level']; // Duplicate the first <h#> tag in the document for the TOC header 126 $toc .= $this->styles; 127 $toc .= '<div class="table-of-contents">'; 128 $toc .= "<$contents_header>" . esc_html( $this->args->header_text ) . "</$contents_header><ul class=\"items\">"; 129 $last_item = false; 130 131 foreach ( $items as $item ) { 132 if ( $last_item ) { 133 if ( $last_item < $item['level'] ) { 134 $toc .= "\n<ul>\n"; 135 } elseif ( $last_item > $item['level'] ) { 136 $toc .= "\n</ul></li>\n"; 137 } else { 138 $toc .= "</li>\n"; 137 139 } 138 139 $last_item = $item[2]; 140 141 $id = sanitize_title( $item[3] ); 142 // Append unique suffix if anchor ID isn't unique. 143 $count = 2; 144 $orig_id = $id; 145 while ( in_array( $id, $used_ids ) && $count < 50 ) { 146 $id = $orig_id . '-' . $count; 147 $count++; 148 } 149 $used_ids[] = $id; 150 151 $toc .= '<li><a href="#' . esc_attr( $id ) . '">' . $item[3] . '</a>'; 152 } 153 $toc .= "</ul>\n</div>\n"; 154 } 140 } 141 142 $last_item = $item['level']; 143 144 $toc .= '<li><a href="#' . esc_attr( $item['id'] ) . '">' . $item['title'] . '</a>'; 145 } 146 147 $toc .= "</ul>\n</div>\n"; 155 148 156 149 return $toc . $content; 157 150 } 158 151 159 protected function add_ids_and_jumpto_links( $tag, $content ) { 160 $items = $this->get_tags( $tag, $content ); 152 /** 153 * Add the HTML markup for the in-content header elements. 154 */ 155 protected function add_ids_and_jumpto_links( $items, $content ) { 161 156 $first = true; 162 157 $matches = array(); … … 165 160 foreach ( $items as $item ) { 166 161 $replacement = ''; 167 $matches[] = $item[0]; 168 $id = sanitize_title( $item[2] ); 169 170 // Append unique suffix if anchor ID isn't unique. 171 $count = 2; 172 $orig_id = $id; 173 while ( in_array( $id, $this->used_ids ) && $count < 50 ) { 174 $id = $orig_id . '-' . $count; 175 $count++; 176 } 177 $this->used_ids[] = $id; 178 162 $matches[] = $item[0]; 163 $tag = 'h' . $item['level']; // 'h2' 164 $id = $item['id']; 165 $title = $item['title']; 166 $extra_attrs = $item['attrs']; // 'class="" style=""' 167 $class = 'toc-heading'; 168 169 if ( $extra_attrs ) { 170 // Strip all IDs from the heading attributes (including empty), we'll replace it with one below. 171 $extra_attrs = trim( preg_replace( '/id=(["\'])[^"\']*\\1/i', '', $extra_attrs ) ); 172 173 // Extract any classes present, we're adding our own attribute. 174 if ( preg_match( '/class=(["\'])(?P<class>[^"\']+)\\1/i', $extra_attrs, $m ) ) { 175 $extra_attrs = str_replace( $m[0], '', $extra_attrs ); 176 $class .= ' ' . $m['class']; 177 } 178 } 179 179 180 if ( ! $first ) { 180 181 $replacement .= '<p class="toc-jump"><a href="#top">' . __( 'Top ↑', 'wporg' ) . '</a></p>'; … … 182 183 $first = false; 183 184 } 184 $a11y_text = sprintf( '<span class="screen-reader-text">%s</span>', $item[2] ); 185 186 $a11y_text = sprintf( '<span class="screen-reader-text">%s</span>', $title ); 185 187 $anchor = sprintf( '<a href="#%1$s" class="anchor"><span aria-hidden="true">#</span>%2$s</a>', $id, $a11y_text ); 186 $replacement .= sprintf( '<%1$s class="toc-heading" id="%2$s" tabindex="-1">%3$s %4$s</%1$s>', $tag, $id, $item[2], $anchor );188 $replacement .= sprintf( '<%1$s id="%2$s" class="%3$s" tabindex="-1" %4$s>%5$s %6$s</%1$s>', $tag, $id, $class, $extra_attrs, $title, $anchor ); 187 189 $replacements[] = $replacement; 188 190 } … … 201 203 } 202 204 203 private function get_tags( $tag, $content = '' ) { 204 if ( empty( $content ) ) 205 /** 206 * Generate an ID for a given HTML element, use the tags `id` attribute if set. 207 */ 208 protected function get_id_for_item( $item ) { 209 if ( ! empty( $item['id'] ) ) { 210 return $item['id']; 211 } 212 213 // Check to see if the item already had a non-empty ID, else generate one from the title. 214 if ( preg_match( '/id=(["\'])(?P<id>[^"\']+)\\1/', $item['attrs'], $m ) ) { 215 $id = $m['id']; 216 } else { 217 $id = sanitize_title( $item['title'] ); 218 } 219 220 // Append unique suffix if anchor ID isn't unique in the document. 221 $count = 2; 222 $orig_id = $id; 223 while ( in_array( $id, $this->used_ids ) && $count < 50 ) { 224 $id = $orig_id . '-' . $count; 225 $count++; 226 } 227 228 $this->used_ids[] = $id; 229 230 return $id; 231 } 232 233 protected function get_tags( $tag, $content = '' ) { 234 if ( empty( $content ) ) { 205 235 $content = get_the_content(); 206 preg_match_all( "/(<{$tag}>)(.*)(<\/{$tag}>)/", $content, $matches, PREG_SET_ORDER ); 236 } 237 238 preg_match_all( "/(?P<tag><{$tag}(?P<attrs>[^>]*)>)(?P<title>.*)(<\/{$tag}>)/iJ", $content, $matches, PREG_SET_ORDER ); 239 207 240 return $matches; 208 241 }
Note: See TracChangeset
for help on using the changeset viewer.