Version Description
05/05/2022 = * TWEAK: Added Toggle with CSS for websites runs without jQuery #153 * TWEAK: Added telegram group join link for suggestions and feedback #159 * BUG: TOC links not jumping in some posts which have special characters #163 * BUG: Incorrect email ID updated in the plugin #165 * BUG: Proper documentation added for adding TOC with shortcodes & do_shortcode #152 * BUG: TOC links not working when do_shortcode added directly in the template #147 * BUG: TOC links not working with some specical character with Elementor #162
Download this release
Release Info
Developer | magazine3 |
Plugin | Easy Table of Contents |
Version | 2.0.20 |
Comparing to | |
See all releases |
Code changes from version 2.0.19 to 2.0.20
- README.txt +495 -480
- assets/css/admin.css +222 -222
- assets/css/screen.css +374 -347
- assets/css/screen.min.css +1 -1
- assets/js/front.js +309 -309
- easy-table-of-contents.php +743 -738
- includes/Debug.php +180 -180
- includes/class.admin.php +569 -569
- includes/class.options.php +1294 -1281
- includes/class.post.php +1415 -1405
- includes/inc.admin-options-page.php +92 -92
- includes/inc.string-functions.php +344 -344
README.txt
CHANGED
@@ -1,480 +1,495 @@
|
|
1 |
-
=== Easy Table of Contents ===
|
2 |
-
Contributors: magazine3
|
3 |
-
Donate link: https://magazine3.company/
|
4 |
-
Tags: table of contents, toc
|
5 |
-
Requires at least: 5.3
|
6 |
-
Tested up to: 5.9.3
|
7 |
-
Requires PHP: 5.6.20
|
8 |
-
Stable tag: 2.0.
|
9 |
-
License: GPLv2 or later
|
10 |
-
License URI: https://www.gnu.org/licenses/gpl-2.0.html
|
11 |
-
|
12 |
-
Adds a user friendly and fully automatic way to create and display a table of contents generated from the page content.
|
13 |
-
|
14 |
-
== Description ==
|
15 |
-
|
16 |
-
A user friendly, featured focused plugin which allows you to insert a table of contents into your posts, pages and custom post types.
|
17 |
-
|
18 |
-
### Features
|
19 |
-
* Automatically generate a table of contents for your posts, pages and custom post types by parsing its contents for headers.
|
20 |
-
* Supports the `<!--nextpage-->` tag.
|
21 |
-
* Supports the Rank Math plugin.
|
22 |
-
* Works with the Classic Editor, Gutenberg, Divi, Elementor, WPBakery Page Builder and Visual Composer page editors.
|
23 |
-
* Optionally enable for pages and/or posts. Custom post types are supported, as long as their content is output with the `the_content()` template tag.
|
24 |
-
* Optionally auto insert the table of contents into the page, selectable by enabled post type.
|
25 |
-
* Provides many easy to understand options to configure when and where to insert the table of contents.
|
26 |
-
* Many options are available to configure how the inserted table of contents appears which include several builtin themes. If the supplied themes do no meet you needs, you can create your own by choosing you own colors for the border, background and link color.
|
27 |
-
* Multiple counter bullet formats to choose from; none, decimal, numeric and roman.
|
28 |
-
* Choose to display the table of contents hierarchical or not. This means headings of lower priority will be nested under headings of higher priority.
|
29 |
-
* User can optionally hide the table of contents. You full control of this feature. It can be disabled and you can choose to have it hidden by default.
|
30 |
-
* Supports smooth scrolling.
|
31 |
-
* Selectively enable or disabled the table of contents on a post by post basis.
|
32 |
-
* Choose which headings are used to generate the table of contents. This too can be set on a post by post basis.
|
33 |
-
* Easily exclude headers globally and on a post by post basis.
|
34 |
-
* If you rather not insert the table of contents in the post content, you can use the supplied widget and place the table of contents in your theme's sidebar.
|
35 |
-
* The widgets supports being affixed or stuck on the page so it is always visible as you scroll down the page. NOTE: this is an advanced option since every theme is different, you might need support from your theme developer to learn what the correct item selector to use in the settings to enable this feature.
|
36 |
-
* The widget auto highlights the sections currently visible on the page. The highlight color is configurable.
|
37 |
-
* Developer friendly with many action hooks and filters available. More can be added by request on [Github](https://github.com/shazahm1/Easy-Table-of-Contents). Pull requests are welcomed.
|
38 |
-
|
39 |
-
### Support
|
40 |
-
|
41 |
-
We try our best to provide support on WordPress.org forums. However, We have a special [team support](https://magazine3.company/contact/) where you can ask us questions and get help. Delivering a good user experience means a lot to us and so we try our best to reply each and every question that gets asked.
|
42 |
-
|
43 |
-
### Bug Reports
|
44 |
-
|
45 |
-
Bug reports for Easy Table of Contents are [welcomed on GitHub](https://github.com/ahmedkaludi/Easy-Table-of-Contents). Please note GitHub is not a support forum, and issues that aren't properly qualified as bugs will be closed.
|
46 |
-
|
47 |
-
###
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
* [
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
*
|
57 |
-
*
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
*
|
104 |
-
|
105 |
-
|
106 |
-
*
|
107 |
-
*
|
108 |
-
|
109 |
-
= 2.0.
|
110 |
-
*
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
* TWEAK: Add additional
|
118 |
-
*
|
119 |
-
|
120 |
-
= 2.0.
|
121 |
-
* TWEAK:
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
* TWEAK:
|
128 |
-
* TWEAK:
|
129 |
-
*
|
130 |
-
|
131 |
-
|
132 |
-
*
|
133 |
-
*
|
134 |
-
* DEV:
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
*
|
139 |
-
*
|
140 |
-
*
|
141 |
-
|
142 |
-
|
143 |
-
*
|
144 |
-
*
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
*
|
150 |
-
*
|
151 |
-
* DEV:
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
* TWEAK:
|
160 |
-
*
|
161 |
-
*
|
162 |
-
*
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
* TWEAK:
|
168 |
-
* TWEAK:
|
169 |
-
* TWEAK:
|
170 |
-
* TWEAK:
|
171 |
-
*
|
172 |
-
*
|
173 |
-
*
|
174 |
-
|
175 |
-
|
176 |
-
*
|
177 |
-
*
|
178 |
-
|
179 |
-
|
180 |
-
*
|
181 |
-
|
182 |
-
|
183 |
-
*
|
184 |
-
|
185 |
-
|
186 |
-
*
|
187 |
-
*
|
188 |
-
* BUG: `
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
*
|
198 |
-
* TWEAK:
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
*
|
204 |
-
*
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
*
|
210 |
-
|
211 |
-
|
212 |
-
*
|
213 |
-
*
|
214 |
-
*
|
215 |
-
*
|
216 |
-
*
|
217 |
-
* TWEAK:
|
218 |
-
|
219 |
-
|
220 |
-
*
|
221 |
-
*
|
222 |
-
*
|
223 |
-
*
|
224 |
-
*
|
225 |
-
*
|
226 |
-
*
|
227 |
-
* TWEAK: Improve
|
228 |
-
* TWEAK:
|
229 |
-
* TWEAK
|
230 |
-
* TWEAK:
|
231 |
-
* TWEAK: Add
|
232 |
-
* TWEAK:
|
233 |
-
* TWEAK:
|
234 |
-
* TWEAK:
|
235 |
-
* TWEAK:
|
236 |
-
* TWEAK:
|
237 |
-
* TWEAK:
|
238 |
-
* TWEAK:
|
239 |
-
* TWEAK:
|
240 |
-
*
|
241 |
-
*
|
242 |
-
*
|
243 |
-
*
|
244 |
-
*
|
245 |
-
*
|
246 |
-
*
|
247 |
-
|
248 |
-
|
249 |
-
*
|
250 |
-
* TWEAK:
|
251 |
-
*
|
252 |
-
*
|
253 |
-
*
|
254 |
-
*
|
255 |
-
*
|
256 |
-
*
|
257 |
-
*
|
258 |
-
|
259 |
-
|
260 |
-
*
|
261 |
-
* TWEAK:
|
262 |
-
* TWEAK:
|
263 |
-
* TWEAK:
|
264 |
-
*
|
265 |
-
*
|
266 |
-
*
|
267 |
-
*
|
268 |
-
*
|
269 |
-
|
270 |
-
|
271 |
-
* TWEAK:
|
272 |
-
*
|
273 |
-
|
274 |
-
|
275 |
-
*
|
276 |
-
*
|
277 |
-
*
|
278 |
-
*
|
279 |
-
*
|
280 |
-
|
281 |
-
|
282 |
-
* TWEAK:
|
283 |
-
*
|
284 |
-
|
285 |
-
|
286 |
-
*
|
287 |
-
*
|
288 |
-
|
289 |
-
|
290 |
-
*
|
291 |
-
*
|
292 |
-
*
|
293 |
-
|
294 |
-
|
295 |
-
* TWEAK:
|
296 |
-
*
|
297 |
-
*
|
298 |
-
*
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
*
|
304 |
-
|
305 |
-
|
306 |
-
* TWEAK:
|
307 |
-
* TWEAK:
|
308 |
-
*
|
309 |
-
|
310 |
-
|
311 |
-
*
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
*
|
317 |
-
*
|
318 |
-
*
|
319 |
-
*
|
320 |
-
|
321 |
-
|
322 |
-
* TWEAK:
|
323 |
-
* TWEAK:
|
324 |
-
*
|
325 |
-
|
326 |
-
|
327 |
-
*
|
328 |
-
*
|
329 |
-
*
|
330 |
-
*
|
331 |
-
*
|
332 |
-
|
333 |
-
|
334 |
-
*
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
`<h1
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
<h1>Item 3</h1>
|
376 |
-
|
377 |
-
<h1>Item
|
378 |
-
<h1>Item
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
<h2>Item
|
396 |
-
<
|
397 |
-
|
398 |
-
|
399 |
-
<
|
400 |
-
<
|
401 |
-
<
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
-
|
411 |
-
|
412 |
-
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
=
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
|
421 |
-
|
422 |
-
= 1.
|
423 |
-
|
424 |
-
|
425 |
-
= 1.
|
426 |
-
Requires WordPress >= 4.4 and PHP >= 5.3. PHP version >= 7.1 recommended.
|
427 |
-
|
428 |
-
=
|
429 |
-
Requires WordPress >=
|
430 |
-
|
431 |
-
=
|
432 |
-
Requires WordPress >=
|
433 |
-
|
434 |
-
=
|
435 |
-
Requires WordPress >=
|
436 |
-
|
437 |
-
=
|
438 |
-
Requires WordPress >=
|
439 |
-
|
440 |
-
=
|
441 |
-
Requires WordPress >=
|
442 |
-
|
443 |
-
= 2.0
|
444 |
-
Requires WordPress >= 5.0 and PHP version >= 5.6.20 (>= 7.1 is recommended).
|
445 |
-
|
446 |
-
= 2.0.
|
447 |
-
Requires WordPress >= 5.0 and PHP version >= 5.6.20 (>= 7.1 is recommended).
|
448 |
-
|
449 |
-
= 2.0.
|
450 |
-
Requires WordPress >= 5.0 and PHP version >= 5.6.20 (>= 7.1 is recommended).
|
451 |
-
|
452 |
-
= 2.0.
|
453 |
-
Requires WordPress >= 5.0 and PHP version >= 5.6.20 (>= 7.1 is recommended).
|
454 |
-
|
455 |
-
= 2.0.
|
456 |
-
Requires WordPress >= 5.0 and PHP version >= 5.6.20 (>= 7.1 is recommended).
|
457 |
-
|
458 |
-
= 2.0.
|
459 |
-
Requires WordPress >= 5.0 and PHP version >= 5.6.20 (>= 7.1 is recommended).
|
460 |
-
|
461 |
-
= 2.0.
|
462 |
-
Requires WordPress >= 5.0 and PHP version >= 5.6.20 (>= 7.1 is recommended).
|
463 |
-
|
464 |
-
= 2.0.
|
465 |
-
Requires WordPress >= 5.
|
466 |
-
|
467 |
-
= 2.0.
|
468 |
-
Requires WordPress >= 5.
|
469 |
-
|
470 |
-
= 2.0.
|
471 |
-
Requires WordPress >= 5.
|
472 |
-
|
473 |
-
= 2.0.
|
474 |
-
Requires WordPress >= 5.
|
475 |
-
|
476 |
-
= 2.0.
|
477 |
-
Requires WordPress >= 5.
|
478 |
-
|
479 |
-
= 2.0.
|
480 |
-
Requires WordPress >= 5.3 and PHP version >= 5.6.20 (>= 7.4 is recommended).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
=== Easy Table of Contents ===
|
2 |
+
Contributors: magazine3
|
3 |
+
Donate link: https://magazine3.company/
|
4 |
+
Tags: table of contents, toc
|
5 |
+
Requires at least: 5.3
|
6 |
+
Tested up to: 5.9.3
|
7 |
+
Requires PHP: 5.6.20
|
8 |
+
Stable tag: 2.0.20
|
9 |
+
License: GPLv2 or later
|
10 |
+
License URI: https://www.gnu.org/licenses/gpl-2.0.html
|
11 |
+
|
12 |
+
Adds a user friendly and fully automatic way to create and display a table of contents generated from the page content.
|
13 |
+
|
14 |
+
== Description ==
|
15 |
+
|
16 |
+
A user friendly, featured focused plugin which allows you to insert a table of contents into your posts, pages and custom post types.
|
17 |
+
|
18 |
+
### Features
|
19 |
+
* Automatically generate a table of contents for your posts, pages and custom post types by parsing its contents for headers.
|
20 |
+
* Supports the `<!--nextpage-->` tag.
|
21 |
+
* Supports the Rank Math plugin.
|
22 |
+
* Works with the Classic Editor, Gutenberg, Divi, Elementor, WPBakery Page Builder and Visual Composer page editors.
|
23 |
+
* Optionally enable for pages and/or posts. Custom post types are supported, as long as their content is output with the `the_content()` template tag.
|
24 |
+
* Optionally auto insert the table of contents into the page, selectable by enabled post type.
|
25 |
+
* Provides many easy to understand options to configure when and where to insert the table of contents.
|
26 |
+
* Many options are available to configure how the inserted table of contents appears which include several builtin themes. If the supplied themes do no meet you needs, you can create your own by choosing you own colors for the border, background and link color.
|
27 |
+
* Multiple counter bullet formats to choose from; none, decimal, numeric and roman.
|
28 |
+
* Choose to display the table of contents hierarchical or not. This means headings of lower priority will be nested under headings of higher priority.
|
29 |
+
* User can optionally hide the table of contents. You full control of this feature. It can be disabled and you can choose to have it hidden by default.
|
30 |
+
* Supports smooth scrolling.
|
31 |
+
* Selectively enable or disabled the table of contents on a post by post basis.
|
32 |
+
* Choose which headings are used to generate the table of contents. This too can be set on a post by post basis.
|
33 |
+
* Easily exclude headers globally and on a post by post basis.
|
34 |
+
* If you rather not insert the table of contents in the post content, you can use the supplied widget and place the table of contents in your theme's sidebar.
|
35 |
+
* The widgets supports being affixed or stuck on the page so it is always visible as you scroll down the page. NOTE: this is an advanced option since every theme is different, you might need support from your theme developer to learn what the correct item selector to use in the settings to enable this feature.
|
36 |
+
* The widget auto highlights the sections currently visible on the page. The highlight color is configurable.
|
37 |
+
* Developer friendly with many action hooks and filters available. More can be added by request on [Github](https://github.com/shazahm1/Easy-Table-of-Contents). Pull requests are welcomed.
|
38 |
+
|
39 |
+
### Support
|
40 |
+
|
41 |
+
We try our best to provide support on WordPress.org forums. However, We have a special [team support](https://magazine3.company/contact/) where you can ask us questions and get help. Delivering a good user experience means a lot to us and so we try our best to reply each and every question that gets asked.
|
42 |
+
|
43 |
+
### Bug Reports
|
44 |
+
|
45 |
+
Bug reports for Easy Table of Contents are [welcomed on GitHub](https://github.com/ahmedkaludi/Easy-Table-of-Contents). Please note GitHub is not a support forum, and issues that aren't properly qualified as bugs will be closed.
|
46 |
+
|
47 |
+
### [JOIN CHAT GROUP COMMUNITY](https://t.me/+XADGN24lHNk0YjE1/)**: Purpose of this group is to get proper suggestions and feedback from plugin users and the community so that we can make the plugin even better.
|
48 |
+
|
49 |
+
### Live Examples
|
50 |
+
|
51 |
+
* [cMap Template Docs](http://connections-pro.com/documentation/cmap/)
|
52 |
+
* [Circled Template Docs](http://connections-pro.com/documentation/circled/)
|
53 |
+
* [Gridder Template Docs](http://connections-pro.com/documentation/gridder/)
|
54 |
+
|
55 |
+
### Roadmap
|
56 |
+
* Fragment caching for improved performance.
|
57 |
+
* Improve SEO by adding options to add nofollow to TOC link and wrap TOC nav in noindex tag.
|
58 |
+
* Improve accessibility.
|
59 |
+
* Add Bullet and Arrow options for list counter style.
|
60 |
+
|
61 |
+
### Credit
|
62 |
+
|
63 |
+
Easy Table Contents is a fork of the excellent [Table of Contents Plus](https://wordpress.org/plugins/table-of-contents-plus/) plugin by [Michael Tran](http://dublue.com/plugins/toc/).
|
64 |
+
|
65 |
+
### Screenshots
|
66 |
+
|
67 |
+
1. The General section of the settings.
|
68 |
+
2. The Appearance section of the settings.
|
69 |
+
3. The Advanced section of the settings.
|
70 |
+
|
71 |
+
### Installation
|
72 |
+
|
73 |
+
= Using the WordPress Plugin Search =
|
74 |
+
|
75 |
+
1. Navigate to the `Add New` sub-page under the Plugins admin page.
|
76 |
+
2. Search for `easy table of contents`.
|
77 |
+
3. The plugin should be listed first in the search results.
|
78 |
+
4. Click the `Install Now` link.
|
79 |
+
5. Lastly click the `Activate Plugin` link to activate the plugin.
|
80 |
+
|
81 |
+
= Uploading in WordPress Admin =
|
82 |
+
|
83 |
+
1. [Download the plugin zip file](http://wordpress.org/plugins/easy-table-of-contents/) and save it to your computer.
|
84 |
+
2. Navigate to the `Add New` sub-page under the Plugins admin page.
|
85 |
+
3. Click the `Upload` link.
|
86 |
+
4. Select Easy Table of Contents zip file from where you saved the zip file on your computer.
|
87 |
+
5. Click the `Install Now` button.
|
88 |
+
6. Lastly click the `Activate Plugin` link to activate the plugin.
|
89 |
+
|
90 |
+
= Using FTP =
|
91 |
+
|
92 |
+
1. [Download the plugin zip file](http://wordpress.org/plugins/easy-table-of-contents/) and save it to your computer.
|
93 |
+
2. Extract the Easy Table of Contents zip file.
|
94 |
+
3. Create a new directory named `easy-table-of-contents` directory in the `../wp-content/plugins/` directory.
|
95 |
+
4. Upload the files from the folder extracted in Step 2.
|
96 |
+
4. Activate the plugin on the Plugins admin page.
|
97 |
+
|
98 |
+
== Changelog ==
|
99 |
+
|
100 |
+
= 2.0.20 05/05/2022 =
|
101 |
+
* TWEAK: Added Toggle with CSS for websites runs without jQuery #153
|
102 |
+
* TWEAK: Added telegram group join link for suggestions and feedback #159
|
103 |
+
* BUG: TOC links not jumping in some posts which have special characters #163
|
104 |
+
* BUG: Incorrect email ID updated in the plugin #165
|
105 |
+
* BUG: Proper documentation added for adding TOC with shortcodes & do_shortcode #152
|
106 |
+
* BUG: TOC links not working when do_shortcode added directly in the template #147
|
107 |
+
* BUG: TOC links not working with some specical character with Elementor #162
|
108 |
+
|
109 |
+
= 2.0.19 04/16/2022 =
|
110 |
+
* Bug Fixed : While Using Elementor Page builder TOC is not working when special characters are used in headings. #150
|
111 |
+
* Bug Fixed : Need to load CSS/JS files only on the selected post types. #154
|
112 |
+
|
113 |
+
= 2.0.18 03/29/2022 =
|
114 |
+
* TWEAK: Added Technical Support Tab in Settings Panel.
|
115 |
+
|
116 |
+
= 2.0.17 03/26/2021 =
|
117 |
+
* TWEAK: Add additional check to prevent `Uncaught Error: Call to undefined function is_woocommerce()`.
|
118 |
+
* TWEAK: Ensure an instance of `ezTOC_Post ` is returned before accessing methods/properties.
|
119 |
+
|
120 |
+
= 2.0.16 02/01/2021 =
|
121 |
+
* TWEAK: Remove special characters such as fancy quotes, en and, em dashes when generating in-page anchor IDs.
|
122 |
+
|
123 |
+
= 2.0.15 01/27/2021 =
|
124 |
+
* TWEAK: Remove additional reserved characters when generating in-page anchor IDs.
|
125 |
+
|
126 |
+
= 2.0.14 01/26/2021 =
|
127 |
+
* TWEAK: Refactor debug log as a Singleton.
|
128 |
+
* TWEAK: Add additional logging to aid in debugging.
|
129 |
+
* BUG: Correct logic for PHP where empty string no longer evaluates as integer `0`.
|
130 |
+
|
131 |
+
= 2.0.13 01/25/2021 =
|
132 |
+
* TWEAK: Restrict debug logging to when `WP_DEBUG` is enabled *and* current user capability of `manage_options`.
|
133 |
+
* TWEAK: Add logging to aid in support.
|
134 |
+
* DEV: phpDoc update.
|
135 |
+
|
136 |
+
= 2.0.12 01/22/2021 =
|
137 |
+
* TWEAK: Allow `_` and `-` in anchors.
|
138 |
+
* TWEAK: Minor CSS tweaks that prevent theme from breaking the layout.
|
139 |
+
* TWEAK: Minor tweak to class initialization.
|
140 |
+
* TWEAK: Do not display the view toggle if JavaScript is broken on the site.
|
141 |
+
* TWEAK: Add the ability to enable displaying of displaying debug information on the page.
|
142 |
+
* BUG: Check for array and keys before accessing values.
|
143 |
+
* BUG: Check for array key be fore access.
|
144 |
+
* BUG: Remove reserved characters when generating in-page anchor IDs.
|
145 |
+
* DEV: Remove unnecessary vendor library files.
|
146 |
+
* DEV: Deal with phpStorm showing a warning about path not found when including files.
|
147 |
+
|
148 |
+
= 2.0.11 05/01/2020 =
|
149 |
+
* COMPATIBILITY: Add support for the Uncode theme.
|
150 |
+
* COMPATIBILITY: Do not run on WooCommerce pages.
|
151 |
+
* DEV: Correct typo in phpDoc.
|
152 |
+
|
153 |
+
= 2.0.10 04/20/2020 =
|
154 |
+
* TWEAK: Add trailing `span` to heading, to prepare for `#` option and to fix duplicate heading title matching.
|
155 |
+
* TWEAK: Add second heading search/replace function to search for heading in content with heading html entities decoded. May help Beaver Builder users as it seems like it does not encode HTML entities as WP core does.
|
156 |
+
|
157 |
+
|
158 |
+
= 2.0.9 04/08/2020 =
|
159 |
+
* TWEAK: AMP/Caching plugins seems to break anchors with colons and periods even though they are valid characters for the id attribute in HTML5.
|
160 |
+
* TWEAK: Replace multiple underscores with a single underscore.
|
161 |
+
* DEV: Update the UWS library which fixes the deprecation notice for PHP 7.4.
|
162 |
+
* DEV: Add phpcs.xml.dist.
|
163 |
+
* DEV: Strict type checks.
|
164 |
+
* DEV: Inline doc updates.
|
165 |
+
|
166 |
+
= 2.0.8 04/03/2020 =
|
167 |
+
* TWEAK: Convert `<br />` tags in headings to a space.
|
168 |
+
* TWEAK: Add additional widget classes.
|
169 |
+
* TWEAK: Improve the sanitization of the excluded headings field post setting.
|
170 |
+
* TWEAK: Minor optimization of creating the matching pattern for excluding headings for improved performance.
|
171 |
+
* COMPATIBILITY: Exclude Create by Mediavine from heading eligibility.
|
172 |
+
* BUG: Ensure excluded headings are removed from the headings array.
|
173 |
+
* BUG: Ensure empty headings are removed from the headings array.
|
174 |
+
|
175 |
+
= 2.0.7 04/02/2020 =
|
176 |
+
* NEW: Exclude any HTML nodes with the class of `.ez-toc-exclude-headings`.
|
177 |
+
* TWEAK: Change smooth scroll selector from `'body a'` to `'a.ez-toc-link'`.
|
178 |
+
* TWEAK: Declare JS variables.
|
179 |
+
* TWEAK: Support unicode characters for the `id` attribute. Permitted by HTML5.
|
180 |
+
* TWEAK: Move the in-page anchor/span to before the heading text to account for long headings where it line wraps.
|
181 |
+
* TWEAK: Slight rework to ezTOC widget container classes logic.
|
182 |
+
* TWEAK: Cache bust the JS to make dev easier.
|
183 |
+
* TWEAK: JavaScript cleanup.
|
184 |
+
* TWEAK: URI Encode the id attribute to deal with reserved characters in JavaScript. Technically not necessary for the id attribute but needed to work with the jQuery smoothScroll library.
|
185 |
+
* COMPATIBILITY: Reintroduce filter to exclude Ultimate Addons for VC Composer Tabs from heading eligibility.
|
186 |
+
* BUG: Correct array iteration logic when processing headings.
|
187 |
+
* BUG: Tighten matching for headings in excluded HTML nodes. The loose matching was excluding far too many headings.
|
188 |
+
* BUG: Use `esc_attr()` instead of `esc_url()` for the anchor href because valid id attribute characters would cause it to return an empty href which cause a nonworking link.
|
189 |
+
|
190 |
+
= 2.0.6 03/30/2020 =
|
191 |
+
* BUG: Ensure minified files are current.
|
192 |
+
|
193 |
+
= 2.0.5 03/27/2020 =
|
194 |
+
* BUG: Prevent possible "strpos(): Empty needle in" warnings when excluding nodes from TOC eligibility.
|
195 |
+
|
196 |
+
= 2.0.4 03/16/2020 =
|
197 |
+
* NEW: Introduce the `ez_toc_container_class` filter.
|
198 |
+
* TWEAK: Slight rework to ezTOC container classes logic.
|
199 |
+
* BUG: `sprintf()` was eating `%` in the TOC heading item.
|
200 |
+
* BUG: Do not insert TOC at top of post if before first heading option is selected even if first heading can not be found. Some page builders cause the TOC to insert twice or on blog pages.
|
201 |
+
|
202 |
+
= 2.0.3 03/12/2020 =
|
203 |
+
* TWEAK: Slightly tighten heading matching, last update made it a little too loose.
|
204 |
+
* BUG: Correct logic required to place TOC before first heading which is required for the more lax heading matching required for page builders.
|
205 |
+
|
206 |
+
= 2.0.2 03/12/2020 =
|
207 |
+
* COMPATIBILITY: Remove filter to exclude Ultimate Addons for VC Composer Tabs from heading eligibility.
|
208 |
+
* COMPATIBILITY: Add additional filters to improve Elementor compatibility.
|
209 |
+
* TWEAK: Loosen heading matching when doing find/replace to insert in page links. Excluding the opening heading tag to allow matching heading where page builders dynamically add classes and id which break heading matching during find/replace.
|
210 |
+
|
211 |
+
= 2.0.1 03/09/2020 =
|
212 |
+
* COMPATIBILITY: Exclude the WordPress Related Posts plugin nodes.
|
213 |
+
* COMPATIBILITY: Exclude a couple Atomic Block plugin nodes.
|
214 |
+
* COMPATIBILITY: Exclude JetPack Related Posts from heading eligibility.
|
215 |
+
* COMPATIBILITY: Exclude Ultimate Addons for VC Composer Tabs from heading eligibility.
|
216 |
+
* COMPATIBILITY: Exclude WP Product Reviews from heading eligibility.
|
217 |
+
* TWEAK: Prevent possible "strpos(): Empty needle in" warnings when excluding nodes from TOC eligibility.
|
218 |
+
|
219 |
+
= 2.0 02/01/2020 =
|
220 |
+
* NEW: Major rewrite of all code and processing logic to make it faster and more reliable.
|
221 |
+
* NEW: Support for the <!--nextpage--> tag.
|
222 |
+
* NEW: Introduce helper functions for devs.
|
223 |
+
* NEW: Support WPML.
|
224 |
+
* NEW: Support Polylang.
|
225 |
+
* NEW: Add filter to support the Rank Math plugin.
|
226 |
+
* NEW: Introduce the `ez_toc_maybe_apply_the_content_filter` filter.
|
227 |
+
* TWEAK: Improve translation compatibility.
|
228 |
+
* TWEAK: Rework widget logic to allow multi-line TOC items, improve active item highlighting while removing the use of the jQuery Waypoints library.
|
229 |
+
* TWEAK Add additional classes to TOC list items.
|
230 |
+
* TWEAK: Add WOFF2 format for icon format and change font references in CSS.
|
231 |
+
* TWEAK: Add font-display: swap for toggle icon.
|
232 |
+
* TWEAK: Update JS Cookie to 2.2.1.
|
233 |
+
* TWEAK: Update jQuery Smooth Scroll to 2.2.0.
|
234 |
+
* TWEAK: Allow forward slash and angle brackets in headings and alternate headings.
|
235 |
+
* TWEAK: Allow forward slash in excluded headings.
|
236 |
+
* TWEAK: Remove new line/returns when matching excluded headings.
|
237 |
+
* TWEAK: Simple transient cache to ensure a post is only processed once per request for a TOC.
|
238 |
+
* TWEAK: Improve sanitization of alternate headings field value.
|
239 |
+
* TWEAK: Deal with non-breaking-spaces in alternate headings.
|
240 |
+
* TWEAK: Add the ability to exclude by selector content eligible to be included in the TOC.
|
241 |
+
* TWEAK: Change the shortcode priority to a higher value.
|
242 |
+
* TWEAK: Add filter to remove shortcodes from the content prior to the `the_content` filter being run to exclude shortcode content from being eligible as TOC items.
|
243 |
+
* TWEAK: Add compatibility filters to remove shortcodes for Connections and Striking theme to remove them from eligible TOC item content.
|
244 |
+
* TWEAK: Do not execute if root current filter is the `wp_head` or `get_the_excerpt` filters.
|
245 |
+
* TWEAK: Add filter to exclude content by selector.
|
246 |
+
* TWEAK: Move in-page anchor to after the heading instead of wrapping the heading to prevent conflicts with theme styling.
|
247 |
+
* TWEAK: Utilize the `ez_toc_exclude_by_selector` filter the exclude the JetPack share buttons from eligible headings.
|
248 |
+
* TWEAK: Remove the Elegant Themes Bloom plugin node from the post content before extracting headings.
|
249 |
+
* TWEAK: Add compatibility filter for the Visual Composer plugin.
|
250 |
+
* TWEAK: Utilize the `ez_toc_exclude_by_selector` filter the exclude the Starbox author heading from eligible headings.
|
251 |
+
* I18N: Add wpml-config.xml file.
|
252 |
+
* BUG: Correct option misspelling.
|
253 |
+
* BUG: Do not need to run values for alternate and exclude headings thru `wp_unslash()` because `update_post_meta()` already does.
|
254 |
+
* BUG: Do not need to run `stripslashes()` when escaping the alternate heading value.
|
255 |
+
* BUG: Sanitize the excluded heading string before saving post meta.
|
256 |
+
* DEV: Change PHP keywords to comply with PSR2.
|
257 |
+
* DEV:Bump minimum PHP version to 5.6.20 which matches WP core.
|
258 |
+
|
259 |
+
= 1.7 05/09/2018 =
|
260 |
+
* NEW: Introduce the `ez_toc_shortcode` filter.
|
261 |
+
* TWEAK: Fix notices due to late eligibility check. props unixtam
|
262 |
+
* TWEAK: Tweak eligibility check to support the TOC widget.
|
263 |
+
* TWEAK: Prefix a few CSS classes in order to prevent collisions with theme's and other plugins.
|
264 |
+
* TWEAK: Avoid potential PHP notice in admin when saving the post by checking for nonce before validating it.
|
265 |
+
* TWEAK: Using the shortcode now overrides global options.
|
266 |
+
* TWEAK: `the_content()` now caches result of `is_eligible()`.
|
267 |
+
* TWEAK: Refactor to pass the WP_Post object internally vs. accessing it via the `$wp_query->post` which may not in all cases exist.
|
268 |
+
* TWEAK: Use `pre_replace()` to replace one or more spaces with an underscore.
|
269 |
+
* TWEAK: Return original title in the `ez_toc_url_anchor_target` filter.
|
270 |
+
* TWEAK: Strip ` `, replacing it with a space character.
|
271 |
+
* TWEAK: Minor tweaks to the in page URL creating.
|
272 |
+
* TWEAK: Wrap TOC list in a nav element.
|
273 |
+
* TWEAK: Init plugin on the `plugins_loaded` hook.
|
274 |
+
* TWEAK: Tweak the minimum number of headers to 1.
|
275 |
+
* BUG: The header options from the post meta should be used when building the TOC hierarchy, not the header options from the global settings.
|
276 |
+
* BUG: Do not double escape field values.
|
277 |
+
* BUG: Ensure Apostrophe / Single quote use in Exclude Headings work.
|
278 |
+
* OTHER: Update CSS to include the newly prefixed classes.
|
279 |
+
* DEV: Remove some commented out unused code.
|
280 |
+
|
281 |
+
= 1.6.1 03/16/2018 =
|
282 |
+
* TWEAK: Revert change made to allow HTML added via the `ez_toc_title` filter as it caused undesirable side effects.
|
283 |
+
* BUG: Ensure Smooth Scroll Offset is parsed as an integer.
|
284 |
+
|
285 |
+
= 1.6 03/15/2018 =
|
286 |
+
* NEW: Add `px` option for font size unit.
|
287 |
+
* NEW: Add title font size and weight settings options.
|
288 |
+
* NEW: Add the Mobile Smooth Scroll Offset option.
|
289 |
+
* TWEAK: Change default for font size unit from `px` to `%` to match the default options values.
|
290 |
+
* TWEAK: Correct CSS selector so margin is properly applied between the title and TOC items.
|
291 |
+
* TWEAK: Honor HTML added via `ez_toc_title` filter.
|
292 |
+
* TWEAK: Ensure the ezTOC content filter is not applied when running `the_content` filter.
|
293 |
+
* TWEAK: Only enqueue the javascript if the page is eligible for a TOC.
|
294 |
+
* TWEAK: Update icomoon CSS to remove unecessary CSS selectors to prevent possible conflicts.
|
295 |
+
* TWEAK: The smooth scroll offset needs to be taken into account when defining the offset_top property when affixing the widget.
|
296 |
+
* OTHER: Update frontend minified CSS file.
|
297 |
+
* OTHER: Update the frontend minified javascript file.
|
298 |
+
* DEV: phpDoc corrections.
|
299 |
+
|
300 |
+
= 1.5 02/20/2018 =
|
301 |
+
* BUG: Correct CSS selector to properly target the link color.
|
302 |
+
* OTHER: Update the WayPoints library.
|
303 |
+
* DEV: Add a couple @todo's.
|
304 |
+
|
305 |
+
= 1.4 01/29/2018 =
|
306 |
+
* TWEAK: Change text domain from ez_toc to easy-table-of-contents.
|
307 |
+
* TWEAK: Rename translation files with correct text domain.
|
308 |
+
* BUG: Ensure page headers are processed to add the in page header link when using the shortcodes.
|
309 |
+
* BUG: Add forward slash to domain path in the plugin header.
|
310 |
+
* I18N: Update POT file.
|
311 |
+
* I18N: Update Dutch (nl_NL) translation.
|
312 |
+
|
313 |
+
= 1.3 12/18/2017 =
|
314 |
+
* FEATURE: Add support for the `[ez-toc]` shortcode.
|
315 |
+
* NEW: For backwards compatibility with "Table of Content Plus", register the `[toc]` shortcode.
|
316 |
+
* NEW: Introduce the `ez_toc_extract_headings_content` filter.
|
317 |
+
* TWEAK: Update the tested to and required readme header text.
|
318 |
+
* TWEAK: Do not show the widget on the 404, archive, search and posts pages.
|
319 |
+
* I18N: Add the nl_NL translation.
|
320 |
+
|
321 |
+
= 1.2 04/29/2016 =
|
322 |
+
* TWEAK: Remove the font family from styling the TOC title header.
|
323 |
+
* TWEAK: Pass the raw title to the `ez_toc_title` filter.
|
324 |
+
* BUG: A jQuery 1.12 fix for WordPress 4.5.
|
325 |
+
|
326 |
+
= 1.1 02/24/2016 =
|
327 |
+
* FEATURE: Add option to replace header wither alternate header text in the table of content.
|
328 |
+
* NEW: Introduce the ez_toc_filter.
|
329 |
+
* NEW: Introduce ezTOC_Option::textarea() to render textareas.
|
330 |
+
* NEW: Introduce array_search_deep() to recursively search an array for a value.
|
331 |
+
* TWEAK: Run table of contents headers thru wp_kses_post().
|
332 |
+
* TWEAK: Escape URL.
|
333 |
+
* TWEAK: Count excluded headings only once instead of multiple times.
|
334 |
+
* TWEAK: Escape translated string before rendering.
|
335 |
+
* TWEAK: Use wp_unslash() instead of stripslashes().
|
336 |
+
* TWEAK: Escape translated string.
|
337 |
+
* BUG: Fix restrict path logic.
|
338 |
+
* OTHER: Readme tweaks.
|
339 |
+
* I18N: Add POT file.
|
340 |
+
* I18N: Add Dutch translation.
|
341 |
+
* DEV: Update .gitignore to allow PO files.
|
342 |
+
* DEV: phpDoc fix.
|
343 |
+
|
344 |
+
= 1.0 09/08/2015 =
|
345 |
+
* Initial release.
|
346 |
+
- Complete refactor and restructure of the original code for better design and separation of function to make code base much easier to maintain and extend.
|
347 |
+
- Update all third party libraries.
|
348 |
+
- Make much better use of the WordPress Settings API.
|
349 |
+
- Minified CSS and JS files are used by default. Using SCRIPT_DEBUG will use the un-minified versions.
|
350 |
+
- Add substantial amounts of phpDoc for developers.
|
351 |
+
- Add many hooks to permit third party integrations.
|
352 |
+
- Widget can be affixed/stuck to the page so it is always visible.
|
353 |
+
- Widget will highlight the table of content sections that are currently visible in the browser viewport.
|
354 |
+
- Widget will now generate table of contents using output from third party shortcodes.
|
355 |
+
- Use wpColorPicker instead of farbtastic.
|
356 |
+
- Remove all shortcodes.
|
357 |
+
- Per post options are saved in post meta instead of set by shortcode.
|
358 |
+
|
359 |
+
== Frequently Asked Questions ==
|
360 |
+
|
361 |
+
= Ok, I've installed this... what do I do next? =
|
362 |
+
|
363 |
+
You first stop should be the Table of Contents settings admin page. You can find this under the Settings menu item.
|
364 |
+
|
365 |
+
You first and only required decision is you need to decide which post types you want to enable Table of Contents support for. By default it is the Pages post type. If on Pages is the only place you plan on using Table of Contents, you have nothing to do on the Settings page. To keep things simple, I recommend not changing any of the other settings at this point. Many of the other settings control when and where the table of contents is inserted and changing these settings could cause it not to display making getting started a bit more difficult. After you get comfortable with how this works... then tweak away :)
|
366 |
+
|
367 |
+
With that out of the way make sure to read the **How are the tables of contents created?** FAQ so you know how the Table of Contents is automatically generated. After you have the page headers setup, or before, either way... Scroll down on the page you'll see a metabox named "*Table of Contents*", enable the *Insert table of contents.* option and Update and/or Publish you page. The table of contents should automatically be shown at the top of the page.
|
368 |
+
|
369 |
+
= How are the tables of contents created? =
|
370 |
+
|
371 |
+
The table of contents is generated by the headers found on a page. Headers are the [`<h1>,<h2>,<h3>,<h4>,<h5>,<h6>` HTML tags](http://www.w3schools.com/tags/tag_hn.asp). If you are using the WordPres Visual Post Editor, these header tags are used and inserted into the post when you select one of the [*Heading n* options from the formatting drop down](http://torquemag.io/wordpress-heading-tags/). Each header that is found on the page will create a table of content item. Here's an example which will create a table of contents containing the six items.
|
372 |
+
|
373 |
+
`<h1>Item 1</h1>
|
374 |
+
<h1>Item 2</h1>
|
375 |
+
<h1>Item 3</h1>
|
376 |
+
<h1>Item 4</h1>
|
377 |
+
<h1>Item 5</h1>
|
378 |
+
<h1>Item 6</h1>`
|
379 |
+
|
380 |
+
You can also create "nested" table of contents. This is difficult to explain so I'll illustrate building on the previous example. In this example a table of contents will be created with the same six items but now the first three will each an child item nested underneath it. The indentation is not necessary, it was only added for illustration purposes.
|
381 |
+
|
382 |
+
`<h1>Item 1</h1>
|
383 |
+
<h2>Item 1.1 -- Level 2</h2>
|
384 |
+
<h1>Item 2</h1>
|
385 |
+
<h2>Item 2.1 -- Level 2</h2>
|
386 |
+
<h1>Item 3</h1>
|
387 |
+
<h2>Item 3.1 -- Level 2</h2>
|
388 |
+
<h1>Item 4</h1>
|
389 |
+
<h1>Item 5</h1>
|
390 |
+
<h1>Item 6</h1>`
|
391 |
+
|
392 |
+
You are not limited to a single a single nested item either. You can add as many as you need. You can even create multiple nested levels...
|
393 |
+
|
394 |
+
`<h1>Item 1</h1>
|
395 |
+
<h2>Item 1.1 -- Level 2</h2>
|
396 |
+
<h3>Item 1.1.1 -- Level 3</h3>
|
397 |
+
<h3>Item 1.1.2 -- Level 3</h3>
|
398 |
+
<h3>Item 1.1.3 -- Level 3</h3>
|
399 |
+
<h2>Item 1.2 -- Level 2</h2>
|
400 |
+
<h3>Item 1.2.1 -- Level 3</h3>
|
401 |
+
<h3>Item 1.2.2 -- Level 3</h3>
|
402 |
+
<h3>Item 1.2.3 -- Level 3</h3>
|
403 |
+
<h2>Item 1.3 -- Level 2</h2>
|
404 |
+
<h1>Item 2</h1>
|
405 |
+
<h2>Item 2.1 -- Level 2</h2>
|
406 |
+
<h2>Item 2.2 -- Level 2</h2>
|
407 |
+
<h1>Item 3</h1>
|
408 |
+
<h2>Item 3.1 -- Level 2</h2>
|
409 |
+
<h2>Item 3.2 -- Level 2</h2>
|
410 |
+
<h1>Item 4</h1>
|
411 |
+
<h1>Item 5</h1>
|
412 |
+
<h1>Item 6</h1>`
|
413 |
+
|
414 |
+
You can nest up 6 levels deep if needed. I hope this helps you understand how to create and build your own auto generated table of contents on your sites!
|
415 |
+
|
416 |
+
= Is there any shortcode to add the table of content to anywhere I want ? =
|
417 |
+
|
418 |
+
Yes you can add the TOC with this shortcode – [ez-toc] and with the help of this you can easily add the TOC in the content or anywhere in the WordPress and if you want to add the shortcode on the theme file then you can add it with the help of this code – <?php echo do_shortcode( ‘[ez-toc]’ ); ?> and with this, you can add the TOC on any file according to your need.
|
419 |
+
|
420 |
+
== Upgrade Notice ==
|
421 |
+
|
422 |
+
= 1.0 =
|
423 |
+
Initial release.
|
424 |
+
|
425 |
+
= 1.3 =
|
426 |
+
Requires WordPress >= 4.4 and PHP >= 5.3. PHP version >= 7.1 recommended.
|
427 |
+
|
428 |
+
= 1.4 =
|
429 |
+
Requires WordPress >= 4.4 and PHP >= 5.3. PHP version >= 7.1 recommended.
|
430 |
+
|
431 |
+
= 1.5 =
|
432 |
+
Requires WordPress >= 4.4 and PHP >= 5.3. PHP version >= 7.1 recommended.
|
433 |
+
|
434 |
+
= 1.6 =
|
435 |
+
Requires WordPress >= 4.4 and PHP >= 5.3. PHP version >= 7.1 recommended.
|
436 |
+
|
437 |
+
= 1.6.1 =
|
438 |
+
Requires WordPress >= 4.4 and PHP >= 5.3. PHP version >= 7.1 recommended.
|
439 |
+
|
440 |
+
= 1.7 =
|
441 |
+
Requires WordPress >= 4.4 and PHP >= 5.3. PHP version >= 7.1 recommended.
|
442 |
+
|
443 |
+
= 2.0-rc4 =
|
444 |
+
Requires WordPress >= 5.0 and PHP version >= 5.6.20 (>= 7.1 is recommended).
|
445 |
+
|
446 |
+
= 2.0.1 =
|
447 |
+
Requires WordPress >= 5.0 and PHP version >= 5.6.20 (>= 7.1 is recommended).
|
448 |
+
|
449 |
+
= 2.0.2 =
|
450 |
+
Requires WordPress >= 5.0 and PHP version >= 5.6.20 (>= 7.1 is recommended).
|
451 |
+
|
452 |
+
= 2.0.3 =
|
453 |
+
Requires WordPress >= 5.0 and PHP version >= 5.6.20 (>= 7.1 is recommended).
|
454 |
+
|
455 |
+
= 2.0.4 =
|
456 |
+
Requires WordPress >= 5.0 and PHP version >= 5.6.20 (>= 7.1 is recommended).
|
457 |
+
|
458 |
+
= 2.0.5 =
|
459 |
+
Requires WordPress >= 5.0 and PHP version >= 5.6.20 (>= 7.1 is recommended).
|
460 |
+
|
461 |
+
= 2.0.6 =
|
462 |
+
Requires WordPress >= 5.0 and PHP version >= 5.6.20 (>= 7.1 is recommended).
|
463 |
+
|
464 |
+
= 2.0.7 =
|
465 |
+
Requires WordPress >= 5.0 and PHP version >= 5.6.20 (>= 7.1 is recommended).
|
466 |
+
|
467 |
+
= 2.0.8 =
|
468 |
+
Requires WordPress >= 5.0 and PHP version >= 5.6.20 (>= 7.1 is recommended).
|
469 |
+
|
470 |
+
= 2.0.9 =
|
471 |
+
Requires WordPress >= 5.0 and PHP version >= 5.6.20 (>= 7.1 is recommended).
|
472 |
+
|
473 |
+
= 2.0.10 =
|
474 |
+
Requires WordPress >= 5.0 and PHP version >= 5.6.20 (>= 7.1 is recommended).
|
475 |
+
|
476 |
+
= 2.0.11 =
|
477 |
+
Requires WordPress >= 5.0 and PHP version >= 5.6.20 (>= 7.1 is recommended).
|
478 |
+
|
479 |
+
= 2.0.12 =
|
480 |
+
Requires WordPress >= 5.3 and PHP version >= 5.6.20 (>= 7.4 is recommended).
|
481 |
+
|
482 |
+
= 2.0.13 =
|
483 |
+
Requires WordPress >= 5.3 and PHP version >= 5.6.20 (>= 7.4 is recommended).
|
484 |
+
|
485 |
+
= 2.0.14 =
|
486 |
+
Requires WordPress >= 5.3 and PHP version >= 5.6.20 (>= 7.4 is recommended).
|
487 |
+
|
488 |
+
= 2.0.15 =
|
489 |
+
Requires WordPress >= 5.3 and PHP version >= 5.6.20 (>= 7.4 is recommended).
|
490 |
+
|
491 |
+
= 2.0.16 =
|
492 |
+
Requires WordPress >= 5.3 and PHP version >= 5.6.20 (>= 7.4 is recommended).
|
493 |
+
|
494 |
+
= 2.0.17 =
|
495 |
+
Requires WordPress >= 5.3 and PHP version >= 5.6.20 (>= 7.4 is recommended).
|
assets/css/admin.css
CHANGED
@@ -1,222 +1,222 @@
|
|
1 |
-
div.tab_content table {
|
2 |
-
margin-bottom: 1em;
|
3 |
-
}
|
4 |
-
table.more_toc_options_table th, table.more_toc_options_table td {
|
5 |
-
padding: 0;
|
6 |
-
margin: 0;
|
7 |
-
}
|
8 |
-
table.more_toc_options_table th {
|
9 |
-
width: auto;
|
10 |
-
padding-right: 4px;
|
11 |
-
padding-top: 2px;
|
12 |
-
}
|
13 |
-
div.tab_content ul li {
|
14 |
-
margin-left: 2em;
|
15 |
-
list-style-type: disc;
|
16 |
-
}
|
17 |
-
div.tab_content ol li {
|
18 |
-
list-style: inherit;
|
19 |
-
}
|
20 |
-
div.tab_content pre {
|
21 |
-
margin-left: 2em;
|
22 |
-
}
|
23 |
-
ul#tabbed-nav {
|
24 |
-
margin-top: 1em;
|
25 |
-
}
|
26 |
-
#tabbed-nav {
|
27 |
-
margin: 0;
|
28 |
-
padding: 0;
|
29 |
-
float: left;
|
30 |
-
list-style: none;
|
31 |
-
height: 32px;
|
32 |
-
border-bottom: 1px solid #DFDFDF;
|
33 |
-
border-left: 1px solid #DFDFDF;
|
34 |
-
width: 100%;
|
35 |
-
}
|
36 |
-
#tabbed-nav li {
|
37 |
-
float: left;
|
38 |
-
margin: 0;
|
39 |
-
padding: 0;
|
40 |
-
height: 31px;
|
41 |
-
line-height: 31px;
|
42 |
-
border: 1px solid #DFDFDF;
|
43 |
-
border-left: none;
|
44 |
-
margin-bottom: -1px;
|
45 |
-
overflow: hidden;
|
46 |
-
position: relative;
|
47 |
-
background: #F5F5F5;
|
48 |
-
background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#F5F5F5));
|
49 |
-
background-image: -webkit-linear-gradient(center top, #fff, #F5F5F5);
|
50 |
-
background-image: -moz-linear-gradient(center top, #fff, #F5F5F5);
|
51 |
-
background-image: -ms-linear-gradient(center top, #fff, #F5F5F5);
|
52 |
-
background-image: -o-linear-gradient(center top, #fff, #F5F5F5);
|
53 |
-
background-image: linear-gradient(center top, #fff, #F5F5F5);
|
54 |
-
}
|
55 |
-
#tabbed-nav li a {
|
56 |
-
text-decoration: none;
|
57 |
-
color: #000;
|
58 |
-
display: block;
|
59 |
-
font-size: 1.2em;
|
60 |
-
padding: 0 20px;
|
61 |
-
border: 1px solid #fff;
|
62 |
-
outline: none;
|
63 |
-
}
|
64 |
-
#tabbed-nav li a:hover {
|
65 |
-
background: #ECECEC;
|
66 |
-
}
|
67 |
-
html #tabbed-nav li.active, html #tabbed-nav li.active a:hover {
|
68 |
-
background: #fff;
|
69 |
-
border-bottom: 1px solid #fff;
|
70 |
-
}
|
71 |
-
div.tab_container {
|
72 |
-
border: 1px solid #DFDFDF;
|
73 |
-
border-top: none;
|
74 |
-
overflow: hidden;
|
75 |
-
clear: both;
|
76 |
-
float: left; width: 100%;
|
77 |
-
background: #fff;
|
78 |
-
margin-bottom: 2em;
|
79 |
-
padding-bottom: 2em;
|
80 |
-
}
|
81 |
-
div.tab_content {
|
82 |
-
padding: 10px;
|
83 |
-
padding-bottom: 0;
|
84 |
-
font-size: 1em;
|
85 |
-
}
|
86 |
-
h3 span.show_hide {
|
87 |
-
font-size: 0.85em;
|
88 |
-
font-weight: normal;
|
89 |
-
}
|
90 |
-
div.more_toc_options {
|
91 |
-
margin-top: 4px;
|
92 |
-
margin-left: 2em;
|
93 |
-
}
|
94 |
-
div.toc_theme_option {
|
95 |
-
width: 200px;
|
96 |
-
float: left;
|
97 |
-
margin-right: 5px;
|
98 |
-
}
|
99 |
-
#wpcontent select optgroup option {
|
100 |
-
padding-left: 15px;
|
101 |
-
}
|
102 |
-
input#width_custom,
|
103 |
-
input#font_size,
|
104 |
-
input#smooth_scroll_offset {
|
105 |
-
width: 50px;
|
106 |
-
text-align: center;
|
107 |
-
}
|
108 |
-
input.custom_colour_option {
|
109 |
-
width: 75px;
|
110 |
-
}
|
111 |
-
table#theme_custom, div#farbtastic_colour_wheel {
|
112 |
-
float: left;
|
113 |
-
}
|
114 |
-
table#theme_custom {
|
115 |
-
margin-top: 30px;
|
116 |
-
}
|
117 |
-
table#theme_custom img {
|
118 |
-
vertical-align: middle;
|
119 |
-
opacity: 0.4;
|
120 |
-
}
|
121 |
-
table#theme_custom img:hover {
|
122 |
-
cursor: pointer;
|
123 |
-
opacity: 1;
|
124 |
-
}
|
125 |
-
div#farbtastic_colour_wheel {
|
126 |
-
margin-left: 20px;
|
127 |
-
}
|
128 |
-
#tab3 h3:not(:first-child) {
|
129 |
-
margin-top: 2em;
|
130 |
-
}
|
131 |
-
|
132 |
-
/* My styles */
|
133 |
-
#toc input.small-text {
|
134 |
-
width: 50px;
|
135 |
-
padding: 2px;
|
136 |
-
height: 28px;
|
137 |
-
line-height: 28px;
|
138 |
-
vertical-align: bottom;
|
139 |
-
}
|
140 |
-
|
141 |
-
#toc .form-table tr > th > strong {
|
142 |
-
font-size: 18px;
|
143 |
-
font-style: italic;
|
144 |
-
}
|
145 |
-
/* Tab panel styles */
|
146 |
-
.postbox{
|
147 |
-
padding: 10px;
|
148 |
-
}
|
149 |
-
html {
|
150 |
-
scroll-behavior: smooth;
|
151 |
-
}
|
152 |
-
.toc-tab-panel {
|
153 |
-
overflow: hidden;
|
154 |
-
border: 1px solid #ccc;
|
155 |
-
background-color: #fff;
|
156 |
-
margin-top: 15px;}
|
157 |
-
.toc-tab-panel a {
|
158 |
-
background-color: inherit;
|
159 |
-
text-decoration: none;
|
160 |
-
float: left;
|
161 |
-
border: none;
|
162 |
-
outline: none;
|
163 |
-
cursor: pointer;
|
164 |
-
padding: 14px 16px;
|
165 |
-
transition: 0s;
|
166 |
-
font-size: 15px;
|
167 |
-
color: #2271b1;
|
168 |
-
}
|
169 |
-
.toc-tab-panel a:hover {
|
170 |
-
color: #0a4b78;
|
171 |
-
}
|
172 |
-
.toc-tab-panel a.active {
|
173 |
-
box-shadow: none;
|
174 |
-
border-bottom: 4px solid #646970;
|
175 |
-
color: #1d2327;
|
176 |
-
}
|
177 |
-
.toc-tab-panel a:focus {
|
178 |
-
box-shadow: none;
|
179 |
-
outline: none;
|
180 |
-
}
|
181 |
-
.eztoc-tabcontent {
|
182 |
-
display: none;
|
183 |
-
border-top: none;
|
184 |
-
animation: fadeEffect 1s;
|
185 |
-
}
|
186 |
-
.eztoc_support_div {
|
187 |
-
background: #fff;
|
188 |
-
margin-top: 10px;
|
189 |
-
padding: 28px;
|
190 |
-
min-width: 255px;
|
191 |
-
border: 1px solid #c3c4c7;
|
192 |
-
box-shadow: 0 1px 1px rgb(0 0 0 / 4%);
|
193 |
-
}
|
194 |
-
.support-label {
|
195 |
-
float: left;
|
196 |
-
width: 70px;
|
197 |
-
font-size: 14px;
|
198 |
-
}
|
199 |
-
.star-mark{
|
200 |
-
color: red;
|
201 |
-
margin-left: 4px;
|
202 |
-
font-family:bold;
|
203 |
-
}
|
204 |
-
.eztoc_support_div li {
|
205 |
-
margin:25px 0px 20px 0px;
|
206 |
-
}
|
207 |
-
.eztoc-query-success{
|
208 |
-
color: green;
|
209 |
-
}
|
210 |
-
.eztoc-query-error{
|
211 |
-
color: red;
|
212 |
-
}
|
213 |
-
.eztoc_hide{
|
214 |
-
display: none;
|
215 |
-
}
|
216 |
-
.eztoc-result{
|
217 |
-
margin-left: 70px;
|
218 |
-
}
|
219 |
-
.eztoc-send-query{
|
220 |
-
margin-left: 70px !important;;
|
221 |
-
}
|
222 |
-
@keyframes fadeEffect { from {opacity: 0;} to {opacity: 1;} }
|
1 |
+
div.tab_content table {
|
2 |
+
margin-bottom: 1em;
|
3 |
+
}
|
4 |
+
table.more_toc_options_table th, table.more_toc_options_table td {
|
5 |
+
padding: 0;
|
6 |
+
margin: 0;
|
7 |
+
}
|
8 |
+
table.more_toc_options_table th {
|
9 |
+
width: auto;
|
10 |
+
padding-right: 4px;
|
11 |
+
padding-top: 2px;
|
12 |
+
}
|
13 |
+
div.tab_content ul li {
|
14 |
+
margin-left: 2em;
|
15 |
+
list-style-type: disc;
|
16 |
+
}
|
17 |
+
div.tab_content ol li {
|
18 |
+
list-style: inherit;
|
19 |
+
}
|
20 |
+
div.tab_content pre {
|
21 |
+
margin-left: 2em;
|
22 |
+
}
|
23 |
+
ul#tabbed-nav {
|
24 |
+
margin-top: 1em;
|
25 |
+
}
|
26 |
+
#tabbed-nav {
|
27 |
+
margin: 0;
|
28 |
+
padding: 0;
|
29 |
+
float: left;
|
30 |
+
list-style: none;
|
31 |
+
height: 32px;
|
32 |
+
border-bottom: 1px solid #DFDFDF;
|
33 |
+
border-left: 1px solid #DFDFDF;
|
34 |
+
width: 100%;
|
35 |
+
}
|
36 |
+
#tabbed-nav li {
|
37 |
+
float: left;
|
38 |
+
margin: 0;
|
39 |
+
padding: 0;
|
40 |
+
height: 31px;
|
41 |
+
line-height: 31px;
|
42 |
+
border: 1px solid #DFDFDF;
|
43 |
+
border-left: none;
|
44 |
+
margin-bottom: -1px;
|
45 |
+
overflow: hidden;
|
46 |
+
position: relative;
|
47 |
+
background: #F5F5F5;
|
48 |
+
background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#F5F5F5));
|
49 |
+
background-image: -webkit-linear-gradient(center top, #fff, #F5F5F5);
|
50 |
+
background-image: -moz-linear-gradient(center top, #fff, #F5F5F5);
|
51 |
+
background-image: -ms-linear-gradient(center top, #fff, #F5F5F5);
|
52 |
+
background-image: -o-linear-gradient(center top, #fff, #F5F5F5);
|
53 |
+
background-image: linear-gradient(center top, #fff, #F5F5F5);
|
54 |
+
}
|
55 |
+
#tabbed-nav li a {
|
56 |
+
text-decoration: none;
|
57 |
+
color: #000;
|
58 |
+
display: block;
|
59 |
+
font-size: 1.2em;
|
60 |
+
padding: 0 20px;
|
61 |
+
border: 1px solid #fff;
|
62 |
+
outline: none;
|
63 |
+
}
|
64 |
+
#tabbed-nav li a:hover {
|
65 |
+
background: #ECECEC;
|
66 |
+
}
|
67 |
+
html #tabbed-nav li.active, html #tabbed-nav li.active a:hover {
|
68 |
+
background: #fff;
|
69 |
+
border-bottom: 1px solid #fff;
|
70 |
+
}
|
71 |
+
div.tab_container {
|
72 |
+
border: 1px solid #DFDFDF;
|
73 |
+
border-top: none;
|
74 |
+
overflow: hidden;
|
75 |
+
clear: both;
|
76 |
+
float: left; width: 100%;
|
77 |
+
background: #fff;
|
78 |
+
margin-bottom: 2em;
|
79 |
+
padding-bottom: 2em;
|
80 |
+
}
|
81 |
+
div.tab_content {
|
82 |
+
padding: 10px;
|
83 |
+
padding-bottom: 0;
|
84 |
+
font-size: 1em;
|
85 |
+
}
|
86 |
+
h3 span.show_hide {
|
87 |
+
font-size: 0.85em;
|
88 |
+
font-weight: normal;
|
89 |
+
}
|
90 |
+
div.more_toc_options {
|
91 |
+
margin-top: 4px;
|
92 |
+
margin-left: 2em;
|
93 |
+
}
|
94 |
+
div.toc_theme_option {
|
95 |
+
width: 200px;
|
96 |
+
float: left;
|
97 |
+
margin-right: 5px;
|
98 |
+
}
|
99 |
+
#wpcontent select optgroup option {
|
100 |
+
padding-left: 15px;
|
101 |
+
}
|
102 |
+
input#width_custom,
|
103 |
+
input#font_size,
|
104 |
+
input#smooth_scroll_offset {
|
105 |
+
width: 50px;
|
106 |
+
text-align: center;
|
107 |
+
}
|
108 |
+
input.custom_colour_option {
|
109 |
+
width: 75px;
|
110 |
+
}
|
111 |
+
table#theme_custom, div#farbtastic_colour_wheel {
|
112 |
+
float: left;
|
113 |
+
}
|
114 |
+
table#theme_custom {
|
115 |
+
margin-top: 30px;
|
116 |
+
}
|
117 |
+
table#theme_custom img {
|
118 |
+
vertical-align: middle;
|
119 |
+
opacity: 0.4;
|
120 |
+
}
|
121 |
+
table#theme_custom img:hover {
|
122 |
+
cursor: pointer;
|
123 |
+
opacity: 1;
|
124 |
+
}
|
125 |
+
div#farbtastic_colour_wheel {
|
126 |
+
margin-left: 20px;
|
127 |
+
}
|
128 |
+
#tab3 h3:not(:first-child) {
|
129 |
+
margin-top: 2em;
|
130 |
+
}
|
131 |
+
|
132 |
+
/* My styles */
|
133 |
+
#toc input.small-text {
|
134 |
+
width: 50px;
|
135 |
+
padding: 2px;
|
136 |
+
height: 28px;
|
137 |
+
line-height: 28px;
|
138 |
+
vertical-align: bottom;
|
139 |
+
}
|
140 |
+
|
141 |
+
#toc .form-table tr > th > strong {
|
142 |
+
font-size: 18px;
|
143 |
+
font-style: italic;
|
144 |
+
}
|
145 |
+
/* Tab panel styles */
|
146 |
+
.postbox{
|
147 |
+
padding: 10px;
|
148 |
+
}
|
149 |
+
html {
|
150 |
+
scroll-behavior: smooth;
|
151 |
+
}
|
152 |
+
.toc-tab-panel {
|
153 |
+
overflow: hidden;
|
154 |
+
border: 1px solid #ccc;
|
155 |
+
background-color: #fff;
|
156 |
+
margin-top: 15px;}
|
157 |
+
.toc-tab-panel a {
|
158 |
+
background-color: inherit;
|
159 |
+
text-decoration: none;
|
160 |
+
float: left;
|
161 |
+
border: none;
|
162 |
+
outline: none;
|
163 |
+
cursor: pointer;
|
164 |
+
padding: 14px 16px;
|
165 |
+
transition: 0s;
|
166 |
+
font-size: 15px;
|
167 |
+
color: #2271b1;
|
168 |
+
}
|
169 |
+
.toc-tab-panel a:hover {
|
170 |
+
color: #0a4b78;
|
171 |
+
}
|
172 |
+
.toc-tab-panel a.active {
|
173 |
+
box-shadow: none;
|
174 |
+
border-bottom: 4px solid #646970;
|
175 |
+
color: #1d2327;
|
176 |
+
}
|
177 |
+
.toc-tab-panel a:focus {
|
178 |
+
box-shadow: none;
|
179 |
+
outline: none;
|
180 |
+
}
|
181 |
+
.eztoc-tabcontent {
|
182 |
+
display: none;
|
183 |
+
border-top: none;
|
184 |
+
animation: fadeEffect 1s;
|
185 |
+
}
|
186 |
+
.eztoc_support_div {
|
187 |
+
background: #fff;
|
188 |
+
margin-top: 10px;
|
189 |
+
padding: 28px;
|
190 |
+
min-width: 255px;
|
191 |
+
border: 1px solid #c3c4c7;
|
192 |
+
box-shadow: 0 1px 1px rgb(0 0 0 / 4%);
|
193 |
+
}
|
194 |
+
.support-label {
|
195 |
+
float: left;
|
196 |
+
width: 70px;
|
197 |
+
font-size: 14px;
|
198 |
+
}
|
199 |
+
.star-mark{
|
200 |
+
color: red;
|
201 |
+
margin-left: 4px;
|
202 |
+
font-family:bold;
|
203 |
+
}
|
204 |
+
.eztoc_support_div li {
|
205 |
+
margin:25px 0px 20px 0px;
|
206 |
+
}
|
207 |
+
.eztoc-query-success{
|
208 |
+
color: green;
|
209 |
+
}
|
210 |
+
.eztoc-query-error{
|
211 |
+
color: red;
|
212 |
+
}
|
213 |
+
.eztoc_hide{
|
214 |
+
display: none;
|
215 |
+
}
|
216 |
+
.eztoc-result{
|
217 |
+
margin-left: 70px;
|
218 |
+
}
|
219 |
+
.eztoc-send-query{
|
220 |
+
margin-left: 70px !important;;
|
221 |
+
}
|
222 |
+
@keyframes fadeEffect { from {opacity: 0;} to {opacity: 1;} }
|
assets/css/screen.css
CHANGED
@@ -1,347 +1,374 @@
|
|
1 |
-
#ez-toc-container {
|
2 |
-
background: #F9F9F9;
|
3 |
-
border: 1px solid #AAAAAA;
|
4 |
-
border-radius: 4px;
|
5 |
-
-webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);
|
6 |
-
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);
|
7 |
-
display: table;
|
8 |
-
/*font-size: 95%;*/
|
9 |
-
margin-bottom: 1em;
|
10 |
-
padding: 10px;
|
11 |
-
position: relative;
|
12 |
-
width: auto;
|
13 |
-
}
|
14 |
-
|
15 |
-
div.ez-toc-widget-container {
|
16 |
-
padding: 0;
|
17 |
-
position: relative;
|
18 |
-
}
|
19 |
-
|
20 |
-
#ez-toc-container.ez-toc-light-blue {
|
21 |
-
background: #EDF6FF;
|
22 |
-
}
|
23 |
-
|
24 |
-
#ez-toc-container.ez-toc-white {
|
25 |
-
background: #FFFFFF;
|
26 |
-
}
|
27 |
-
|
28 |
-
#ez-toc-container.ez-toc-black {
|
29 |
-
background: #000000;
|
30 |
-
}
|
31 |
-
|
32 |
-
#ez-toc-container.ez-toc-transparent {
|
33 |
-
background: none transparent;
|
34 |
-
}
|
35 |
-
|
36 |
-
div.ez-toc-widget-container ul {
|
37 |
-
display: block;
|
38 |
-
}
|
39 |
-
|
40 |
-
div.ez-toc-widget-container li {
|
41 |
-
border: none;
|
42 |
-
padding: 0;
|
43 |
-
}
|
44 |
-
|
45 |
-
div.ez-toc-widget-container ul.ez-toc-list {
|
46 |
-
padding: 10px;
|
47 |
-
}
|
48 |
-
|
49 |
-
#ez-toc-container ul ul,
|
50 |
-
.ez-toc div.ez-toc-widget-container ul ul {
|
51 |
-
margin-left: 1.5em;
|
52 |
-
}
|
53 |
-
|
54 |
-
#ez-toc-container ul,
|
55 |
-
#ez-toc-container li {
|
56 |
-
margin: 0;
|
57 |
-
padding: 0;
|
58 |
-
}
|
59 |
-
|
60 |
-
#ez-toc-container ul,
|
61 |
-
#ez-toc-container li,
|
62 |
-
#ez-toc-container ul li,
|
63 |
-
div.ez-toc-widget-container,
|
64 |
-
div.ez-toc-widget-container li {
|
65 |
-
background: none;
|
66 |
-
list-style: none none;
|
67 |
-
line-height: 1.6;
|
68 |
-
margin: 0;
|
69 |
-
overflow: hidden;
|
70 |
-
z-index: 1;
|
71 |
-
}
|
72 |
-
|
73 |
-
/*#ez-toc-container.have_bullets li {*/
|
74 |
-
/*padding-left: 12px;*/
|
75 |
-
/*}*/
|
76 |
-
|
77 |
-
#ez-toc-container p.ez-toc-title {
|
78 |
-
text-align: left;
|
79 |
-
/*font-family: "Arial Narrow", sans-serif;*/
|
80 |
-
/*font-size: 120%;*/
|
81 |
-
/*font-weight: 500;*/
|
82 |
-
line-height: 1.45;
|
83 |
-
margin: 0;
|
84 |
-
padding: 0;
|
85 |
-
}
|
86 |
-
|
87 |
-
.ez-toc-title-container {
|
88 |
-
display: table;
|
89 |
-
width: 100%;
|
90 |
-
}
|
91 |
-
|
92 |
-
.ez-toc-title,
|
93 |
-
.ez-toc-title-toggle {
|
94 |
-
display: table-cell;
|
95 |
-
text-align: left;
|
96 |
-
vertical-align: middle;
|
97 |
-
}
|
98 |
-
|
99 |
-
#ez-toc-container.ez-toc-black p.ez-toc-title {
|
100 |
-
color: #FFF;
|
101 |
-
}
|
102 |
-
|
103 |
-
/*#ez-toc-container span.ez-toc-toggle {*/
|
104 |
-
/*font-weight: 400;*/
|
105 |
-
/*font-size: 90%;*/
|
106 |
-
/*}*/
|
107 |
-
|
108 |
-
#ez-toc-container div.ez-toc-title-container + ul.ez-toc-list {
|
109 |
-
margin-top: 1em;
|
110 |
-
}
|
111 |
-
|
112 |
-
.ez-toc-wrap-left {
|
113 |
-
float: left;
|
114 |
-
margin-right: 10px;
|
115 |
-
}
|
116 |
-
|
117 |
-
.ez-toc-wrap-right {
|
118 |
-
float: right;
|
119 |
-
margin-left: 10px;
|
120 |
-
}
|
121 |
-
|
122 |
-
#ez-toc-container a {
|
123 |
-
color: #444444;
|
124 |
-
box-shadow: none;
|
125 |
-
text-decoration: none;
|
126 |
-
text-shadow: none;
|
127 |
-
}
|
128 |
-
|
129 |
-
#ez-toc-container a:visited {
|
130 |
-
color: #9f9f9f;
|
131 |
-
}
|
132 |
-
|
133 |
-
#ez-toc-container a:hover {
|
134 |
-
text-decoration: underline;
|
135 |
-
}
|
136 |
-
|
137 |
-
#ez-toc-container.ez-toc-black a {
|
138 |
-
color: #FFF;
|
139 |
-
}
|
140 |
-
|
141 |
-
#ez-toc-container.ez-toc-black a:visited {
|
142 |
-
color: #FFF;
|
143 |
-
}
|
144 |
-
|
145 |
-
#ez-toc-container a.ez-toc-toggle {
|
146 |
-
color: #444444;
|
147 |
-
}
|
148 |
-
|
149 |
-
#ez-toc-container.counter-hierarchy ul,
|
150 |
-
.ez-toc-widget-container.counter-hierarchy ul,
|
151 |
-
#ez-toc-container.counter-flat ul,
|
152 |
-
.ez-toc-widget-container.counter-flat ul {
|
153 |
-
counter-reset: item;
|
154 |
-
}
|
155 |
-
|
156 |
-
#ez-toc-container.counter-numeric li,
|
157 |
-
.ez-toc-widget-container.counter-numeric li {
|
158 |
-
list-style-type: decimal;
|
159 |
-
list-style-position: inside;
|
160 |
-
}
|
161 |
-
|
162 |
-
#ez-toc-container.counter-decimal ul.ez-toc-list li a::before,
|
163 |
-
.ez-toc-widget-container.counter-decimal ul.ez-toc-list li a::before {
|
164 |
-
content: counters(item, ".") ". ";
|
165 |
-
display: inline-block;
|
166 |
-
counter-increment: item;
|
167 |
-
margin-right: .2em;
|
168 |
-
}
|
169 |
-
|
170 |
-
#ez-toc-container.counter-roman li a::before,
|
171 |
-
.ez-toc-widget-container.counter-roman ul.ez-toc-list li a::before {
|
172 |
-
content: counters(item, ".", upper-roman) ". ";
|
173 |
-
counter-increment: item;
|
174 |
-
}
|
175 |
-
|
176 |
-
.ez-toc-widget-container ul.ez-toc-list li::before {
|
177 |
-
content: ' ';
|
178 |
-
position: absolute;
|
179 |
-
left: 0;
|
180 |
-
right: 0;
|
181 |
-
height: 30px;
|
182 |
-
line-height: 30px;
|
183 |
-
z-index: -1;
|
184 |
-
}
|
185 |
-
|
186 |
-
.ez-toc-widget-container ul.ez-toc-list li.active::before {
|
187 |
-
background-color: #EDEDED;
|
188 |
-
}
|
189 |
-
|
190 |
-
.ez-toc-widget-container li.active > a {
|
191 |
-
font-weight: 900;
|
192 |
-
}
|
193 |
-
|
194 |
-
.ez-toc-btn {
|
195 |
-
display: inline-block;
|
196 |
-
padding: 6px 12px;
|
197 |
-
margin-bottom: 0;
|
198 |
-
font-size: 14px;
|
199 |
-
font-weight: normal;
|
200 |
-
line-height: 1.428571429;
|
201 |
-
text-align: center;
|
202 |
-
white-space: nowrap;
|
203 |
-
vertical-align: middle;
|
204 |
-
cursor: pointer;
|
205 |
-
background-image: none;
|
206 |
-
border: 1px solid transparent;
|
207 |
-
border-radius: 4px;
|
208 |
-
-webkit-user-select: none;
|
209 |
-
-moz-user-select: none;
|
210 |
-
-ms-user-select: none;
|
211 |
-
-o-user-select: none;
|
212 |
-
user-select: none
|
213 |
-
}
|
214 |
-
|
215 |
-
.ez-toc-btn:focus {
|
216 |
-
outline: thin dotted #333;
|
217 |
-
outline: 5px auto -webkit-focus-ring-color;
|
218 |
-
outline-offset: -2px
|
219 |
-
}
|
220 |
-
|
221 |
-
.ez-toc-btn:hover,.ez-toc-btn:focus {
|
222 |
-
color: #333;
|
223 |
-
text-decoration: none
|
224 |
-
}
|
225 |
-
|
226 |
-
.ez-toc-btn:active,.ez-toc-btn.active {
|
227 |
-
background-image: none;
|
228 |
-
outline: 0;
|
229 |
-
-webkit-box-shadow: inset 0 3px 5px rgba(0,0,0,0.125);
|
230 |
-
box-shadow: inset 0 3px 5px rgba(0,0,0,0.125)
|
231 |
-
}
|
232 |
-
|
233 |
-
.ez-toc-btn-default {
|
234 |
-
color: #333;
|
235 |
-
background-color: #fff;
|
236 |
-
border-color: #ccc
|
237 |
-
}
|
238 |
-
|
239 |
-
.ez-toc-btn-default:hover,.ez-toc-btn-default:focus,.ez-toc-btn-default:active,.ez-toc-btn-default.active {
|
240 |
-
color: #333;
|
241 |
-
background-color: #ebebeb;
|
242 |
-
border-color: #adadad
|
243 |
-
}
|
244 |
-
|
245 |
-
.ez-toc-btn-default:active,.ez-toc-btn-default.active {
|
246 |
-
background-image: none
|
247 |
-
}
|
248 |
-
|
249 |
-
/*.btn-lg {*/
|
250 |
-
/*padding: 10px 16px;*/
|
251 |
-
/*font-size: 18px;*/
|
252 |
-
/*line-height: 1.33;*/
|
253 |
-
/*border-radius: 6px*/
|
254 |
-
/*}*/
|
255 |
-
|
256 |
-
.ez-toc-btn-sm,.ez-toc-btn-xs {
|
257 |
-
padding: 5px 10px;
|
258 |
-
font-size: 12px;
|
259 |
-
line-height: 1.5;
|
260 |
-
border-radius: 3px
|
261 |
-
}
|
262 |
-
|
263 |
-
.ez-toc-btn-xs {
|
264 |
-
padding: 1px 5px
|
265 |
-
}
|
266 |
-
|
267 |
-
.ez-toc-btn-default {
|
268 |
-
text-shadow: 0 -1px 0 rgba(0,0,0,0.2);
|
269 |
-
-webkit-box-shadow: inset 0 1px 0 rgba(255,255,255,0.15),0 1px 1px rgba(0,0,0,0.075);
|
270 |
-
box-shadow: inset 0 1px 0 rgba(255,255,255,0.15),0 1px 1px rgba(0,0,0,0.075)
|
271 |
-
}
|
272 |
-
|
273 |
-
.ez-toc-btn-default:active {
|
274 |
-
-webkit-box-shadow: inset 0 3px 5px rgba(0,0,0,0.125);
|
275 |
-
box-shadow: inset 0 3px 5px rgba(0,0,0,0.125)
|
276 |
-
}
|
277 |
-
|
278 |
-
.ez-toc-btn:active,.btn.active {
|
279 |
-
background-image: none
|
280 |
-
}
|
281 |
-
|
282 |
-
.ez-toc-btn-default {
|
283 |
-
text-shadow: 0 1px 0 #fff;
|
284 |
-
background-image: -webkit-gradient(linear,left 0,left 100%,from(#fff),to(#e0e0e0));
|
285 |
-
background-image: -webkit-linear-gradient(top,#fff 0,#e0e0e0 100%);
|
286 |
-
background-image: -moz-linear-gradient(top,#fff 0,#e0e0e0 100%);
|
287 |
-
background-image: linear-gradient(to bottom,#fff 0,#e0e0e0 100%);
|
288 |
-
background-repeat: repeat-x;
|
289 |
-
border-color: #dbdbdb;
|
290 |
-
border-color: #ccc;
|
291 |
-
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#ffe0e0e0',GradientType=0);
|
292 |
-
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false)
|
293 |
-
}
|
294 |
-
|
295 |
-
.ez-toc-btn-default:hover,.ez-toc-btn-default:focus {
|
296 |
-
background-color: #e0e0e0;
|
297 |
-
background-position: 0 -15px
|
298 |
-
}
|
299 |
-
|
300 |
-
.ez-toc-btn-default:active,.ez-toc-btn-default.active {
|
301 |
-
background-color: #e0e0e0;
|
302 |
-
border-color: #dbdbdb
|
303 |
-
}
|
304 |
-
|
305 |
-
.ez-toc-pull-right {
|
306 |
-
float: right !important;
|
307 |
-
margin-left: 10px;
|
308 |
-
}
|
309 |
-
|
310 |
-
.ez-toc-glyphicon {
|
311 |
-
position: relative;
|
312 |
-
top: 1px;
|
313 |
-
display: inline-block;
|
314 |
-
font-family: 'Glyphicons Halflings';
|
315 |
-
-webkit-font-smoothing: antialiased;
|
316 |
-
font-style: normal;
|
317 |
-
font-weight: normal;
|
318 |
-
line-height: 1;
|
319 |
-
-moz-osx-font-smoothing: grayscale
|
320 |
-
}
|
321 |
-
|
322 |
-
.ez-toc-glyphicon:empty {
|
323 |
-
width: 1em
|
324 |
-
}
|
325 |
-
|
326 |
-
.ez-toc-toggle i.ez-toc-glyphicon {
|
327 |
-
font-size: 16px;
|
328 |
-
margin-left: 2px;
|
329 |
-
}
|
330 |
-
|
331 |
-
[class*="ez-toc-icon-"] {
|
332 |
-
font-family: 'ez-toc-icomoon' !important; /* For better glyphicon compatibility */
|
333 |
-
speak: none;
|
334 |
-
font-style: normal;
|
335 |
-
font-weight: normal;
|
336 |
-
font-variant: normal;
|
337 |
-
text-transform: none;
|
338 |
-
line-height: 1;
|
339 |
-
|
340 |
-
/* Better Font Rendering =========== */
|
341 |
-
-webkit-font-smoothing: antialiased;
|
342 |
-
-moz-osx-font-smoothing: grayscale;
|
343 |
-
}
|
344 |
-
|
345 |
-
.ez-toc-icon-toggle:before {
|
346 |
-
content: "\e87a";
|
347 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#ez-toc-container {
|
2 |
+
background: #F9F9F9;
|
3 |
+
border: 1px solid #AAAAAA;
|
4 |
+
border-radius: 4px;
|
5 |
+
-webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);
|
6 |
+
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);
|
7 |
+
display: table;
|
8 |
+
/*font-size: 95%;*/
|
9 |
+
margin-bottom: 1em;
|
10 |
+
padding: 10px;
|
11 |
+
position: relative;
|
12 |
+
width: auto;
|
13 |
+
}
|
14 |
+
|
15 |
+
div.ez-toc-widget-container {
|
16 |
+
padding: 0;
|
17 |
+
position: relative;
|
18 |
+
}
|
19 |
+
|
20 |
+
#ez-toc-container.ez-toc-light-blue {
|
21 |
+
background: #EDF6FF;
|
22 |
+
}
|
23 |
+
|
24 |
+
#ez-toc-container.ez-toc-white {
|
25 |
+
background: #FFFFFF;
|
26 |
+
}
|
27 |
+
|
28 |
+
#ez-toc-container.ez-toc-black {
|
29 |
+
background: #000000;
|
30 |
+
}
|
31 |
+
|
32 |
+
#ez-toc-container.ez-toc-transparent {
|
33 |
+
background: none transparent;
|
34 |
+
}
|
35 |
+
|
36 |
+
div.ez-toc-widget-container ul {
|
37 |
+
display: block;
|
38 |
+
}
|
39 |
+
|
40 |
+
div.ez-toc-widget-container li {
|
41 |
+
border: none;
|
42 |
+
padding: 0;
|
43 |
+
}
|
44 |
+
|
45 |
+
div.ez-toc-widget-container ul.ez-toc-list {
|
46 |
+
padding: 10px;
|
47 |
+
}
|
48 |
+
|
49 |
+
#ez-toc-container ul ul,
|
50 |
+
.ez-toc div.ez-toc-widget-container ul ul {
|
51 |
+
margin-left: 1.5em;
|
52 |
+
}
|
53 |
+
|
54 |
+
#ez-toc-container ul,
|
55 |
+
#ez-toc-container li {
|
56 |
+
margin: 0;
|
57 |
+
padding: 0;
|
58 |
+
}
|
59 |
+
|
60 |
+
#ez-toc-container ul,
|
61 |
+
#ez-toc-container li,
|
62 |
+
#ez-toc-container ul li,
|
63 |
+
div.ez-toc-widget-container,
|
64 |
+
div.ez-toc-widget-container li {
|
65 |
+
background: none;
|
66 |
+
list-style: none none;
|
67 |
+
line-height: 1.6;
|
68 |
+
margin: 0;
|
69 |
+
overflow: hidden;
|
70 |
+
z-index: 1;
|
71 |
+
}
|
72 |
+
|
73 |
+
/*#ez-toc-container.have_bullets li {*/
|
74 |
+
/*padding-left: 12px;*/
|
75 |
+
/*}*/
|
76 |
+
|
77 |
+
#ez-toc-container p.ez-toc-title {
|
78 |
+
text-align: left;
|
79 |
+
/*font-family: "Arial Narrow", sans-serif;*/
|
80 |
+
/*font-size: 120%;*/
|
81 |
+
/*font-weight: 500;*/
|
82 |
+
line-height: 1.45;
|
83 |
+
margin: 0;
|
84 |
+
padding: 0;
|
85 |
+
}
|
86 |
+
|
87 |
+
.ez-toc-title-container {
|
88 |
+
display: table;
|
89 |
+
width: 100%;
|
90 |
+
}
|
91 |
+
|
92 |
+
.ez-toc-title,
|
93 |
+
.ez-toc-title-toggle {
|
94 |
+
display: table-cell;
|
95 |
+
text-align: left;
|
96 |
+
vertical-align: middle;
|
97 |
+
}
|
98 |
+
|
99 |
+
#ez-toc-container.ez-toc-black p.ez-toc-title {
|
100 |
+
color: #FFF;
|
101 |
+
}
|
102 |
+
|
103 |
+
/*#ez-toc-container span.ez-toc-toggle {*/
|
104 |
+
/*font-weight: 400;*/
|
105 |
+
/*font-size: 90%;*/
|
106 |
+
/*}*/
|
107 |
+
|
108 |
+
#ez-toc-container div.ez-toc-title-container + ul.ez-toc-list {
|
109 |
+
margin-top: 1em;
|
110 |
+
}
|
111 |
+
|
112 |
+
.ez-toc-wrap-left {
|
113 |
+
float: left;
|
114 |
+
margin-right: 10px;
|
115 |
+
}
|
116 |
+
|
117 |
+
.ez-toc-wrap-right {
|
118 |
+
float: right;
|
119 |
+
margin-left: 10px;
|
120 |
+
}
|
121 |
+
|
122 |
+
#ez-toc-container a {
|
123 |
+
color: #444444;
|
124 |
+
box-shadow: none;
|
125 |
+
text-decoration: none;
|
126 |
+
text-shadow: none;
|
127 |
+
}
|
128 |
+
|
129 |
+
#ez-toc-container a:visited {
|
130 |
+
color: #9f9f9f;
|
131 |
+
}
|
132 |
+
|
133 |
+
#ez-toc-container a:hover {
|
134 |
+
text-decoration: underline;
|
135 |
+
}
|
136 |
+
|
137 |
+
#ez-toc-container.ez-toc-black a {
|
138 |
+
color: #FFF;
|
139 |
+
}
|
140 |
+
|
141 |
+
#ez-toc-container.ez-toc-black a:visited {
|
142 |
+
color: #FFF;
|
143 |
+
}
|
144 |
+
|
145 |
+
#ez-toc-container a.ez-toc-toggle {
|
146 |
+
color: #444444;
|
147 |
+
}
|
148 |
+
|
149 |
+
#ez-toc-container.counter-hierarchy ul,
|
150 |
+
.ez-toc-widget-container.counter-hierarchy ul,
|
151 |
+
#ez-toc-container.counter-flat ul,
|
152 |
+
.ez-toc-widget-container.counter-flat ul {
|
153 |
+
counter-reset: item;
|
154 |
+
}
|
155 |
+
|
156 |
+
#ez-toc-container.counter-numeric li,
|
157 |
+
.ez-toc-widget-container.counter-numeric li {
|
158 |
+
list-style-type: decimal;
|
159 |
+
list-style-position: inside;
|
160 |
+
}
|
161 |
+
|
162 |
+
#ez-toc-container.counter-decimal ul.ez-toc-list li a::before,
|
163 |
+
.ez-toc-widget-container.counter-decimal ul.ez-toc-list li a::before {
|
164 |
+
content: counters(item, ".") ". ";
|
165 |
+
display: inline-block;
|
166 |
+
counter-increment: item;
|
167 |
+
margin-right: .2em;
|
168 |
+
}
|
169 |
+
|
170 |
+
#ez-toc-container.counter-roman li a::before,
|
171 |
+
.ez-toc-widget-container.counter-roman ul.ez-toc-list li a::before {
|
172 |
+
content: counters(item, ".", upper-roman) ". ";
|
173 |
+
counter-increment: item;
|
174 |
+
}
|
175 |
+
|
176 |
+
.ez-toc-widget-container ul.ez-toc-list li::before {
|
177 |
+
content: ' ';
|
178 |
+
position: absolute;
|
179 |
+
left: 0;
|
180 |
+
right: 0;
|
181 |
+
height: 30px;
|
182 |
+
line-height: 30px;
|
183 |
+
z-index: -1;
|
184 |
+
}
|
185 |
+
|
186 |
+
.ez-toc-widget-container ul.ez-toc-list li.active::before {
|
187 |
+
background-color: #EDEDED;
|
188 |
+
}
|
189 |
+
|
190 |
+
.ez-toc-widget-container li.active > a {
|
191 |
+
font-weight: 900;
|
192 |
+
}
|
193 |
+
|
194 |
+
.ez-toc-btn {
|
195 |
+
display: inline-block;
|
196 |
+
padding: 6px 12px;
|
197 |
+
margin-bottom: 0;
|
198 |
+
font-size: 14px;
|
199 |
+
font-weight: normal;
|
200 |
+
line-height: 1.428571429;
|
201 |
+
text-align: center;
|
202 |
+
white-space: nowrap;
|
203 |
+
vertical-align: middle;
|
204 |
+
cursor: pointer;
|
205 |
+
background-image: none;
|
206 |
+
border: 1px solid transparent;
|
207 |
+
border-radius: 4px;
|
208 |
+
-webkit-user-select: none;
|
209 |
+
-moz-user-select: none;
|
210 |
+
-ms-user-select: none;
|
211 |
+
-o-user-select: none;
|
212 |
+
user-select: none
|
213 |
+
}
|
214 |
+
|
215 |
+
.ez-toc-btn:focus {
|
216 |
+
outline: thin dotted #333;
|
217 |
+
outline: 5px auto -webkit-focus-ring-color;
|
218 |
+
outline-offset: -2px
|
219 |
+
}
|
220 |
+
|
221 |
+
.ez-toc-btn:hover,.ez-toc-btn:focus {
|
222 |
+
color: #333;
|
223 |
+
text-decoration: none
|
224 |
+
}
|
225 |
+
|
226 |
+
.ez-toc-btn:active,.ez-toc-btn.active {
|
227 |
+
background-image: none;
|
228 |
+
outline: 0;
|
229 |
+
-webkit-box-shadow: inset 0 3px 5px rgba(0,0,0,0.125);
|
230 |
+
box-shadow: inset 0 3px 5px rgba(0,0,0,0.125)
|
231 |
+
}
|
232 |
+
|
233 |
+
.ez-toc-btn-default {
|
234 |
+
color: #333;
|
235 |
+
background-color: #fff;
|
236 |
+
border-color: #ccc
|
237 |
+
}
|
238 |
+
|
239 |
+
.ez-toc-btn-default:hover,.ez-toc-btn-default:focus,.ez-toc-btn-default:active,.ez-toc-btn-default.active {
|
240 |
+
color: #333;
|
241 |
+
background-color: #ebebeb;
|
242 |
+
border-color: #adadad
|
243 |
+
}
|
244 |
+
|
245 |
+
.ez-toc-btn-default:active,.ez-toc-btn-default.active {
|
246 |
+
background-image: none
|
247 |
+
}
|
248 |
+
|
249 |
+
/*.btn-lg {*/
|
250 |
+
/*padding: 10px 16px;*/
|
251 |
+
/*font-size: 18px;*/
|
252 |
+
/*line-height: 1.33;*/
|
253 |
+
/*border-radius: 6px*/
|
254 |
+
/*}*/
|
255 |
+
|
256 |
+
.ez-toc-btn-sm,.ez-toc-btn-xs {
|
257 |
+
padding: 5px 10px;
|
258 |
+
font-size: 12px;
|
259 |
+
line-height: 1.5;
|
260 |
+
border-radius: 3px
|
261 |
+
}
|
262 |
+
|
263 |
+
.ez-toc-btn-xs {
|
264 |
+
padding: 1px 5px
|
265 |
+
}
|
266 |
+
|
267 |
+
.ez-toc-btn-default {
|
268 |
+
text-shadow: 0 -1px 0 rgba(0,0,0,0.2);
|
269 |
+
-webkit-box-shadow: inset 0 1px 0 rgba(255,255,255,0.15),0 1px 1px rgba(0,0,0,0.075);
|
270 |
+
box-shadow: inset 0 1px 0 rgba(255,255,255,0.15),0 1px 1px rgba(0,0,0,0.075)
|
271 |
+
}
|
272 |
+
|
273 |
+
.ez-toc-btn-default:active {
|
274 |
+
-webkit-box-shadow: inset 0 3px 5px rgba(0,0,0,0.125);
|
275 |
+
box-shadow: inset 0 3px 5px rgba(0,0,0,0.125)
|
276 |
+
}
|
277 |
+
|
278 |
+
.ez-toc-btn:active,.btn.active {
|
279 |
+
background-image: none
|
280 |
+
}
|
281 |
+
|
282 |
+
.ez-toc-btn-default {
|
283 |
+
text-shadow: 0 1px 0 #fff;
|
284 |
+
background-image: -webkit-gradient(linear,left 0,left 100%,from(#fff),to(#e0e0e0));
|
285 |
+
background-image: -webkit-linear-gradient(top,#fff 0,#e0e0e0 100%);
|
286 |
+
background-image: -moz-linear-gradient(top,#fff 0,#e0e0e0 100%);
|
287 |
+
background-image: linear-gradient(to bottom,#fff 0,#e0e0e0 100%);
|
288 |
+
background-repeat: repeat-x;
|
289 |
+
border-color: #dbdbdb;
|
290 |
+
border-color: #ccc;
|
291 |
+
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#ffe0e0e0',GradientType=0);
|
292 |
+
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false)
|
293 |
+
}
|
294 |
+
|
295 |
+
.ez-toc-btn-default:hover,.ez-toc-btn-default:focus {
|
296 |
+
background-color: #e0e0e0;
|
297 |
+
background-position: 0 -15px
|
298 |
+
}
|
299 |
+
|
300 |
+
.ez-toc-btn-default:active,.ez-toc-btn-default.active {
|
301 |
+
background-color: #e0e0e0;
|
302 |
+
border-color: #dbdbdb
|
303 |
+
}
|
304 |
+
|
305 |
+
.ez-toc-pull-right {
|
306 |
+
float: right !important;
|
307 |
+
margin-left: 10px;
|
308 |
+
}
|
309 |
+
|
310 |
+
.ez-toc-glyphicon {
|
311 |
+
position: relative;
|
312 |
+
top: 1px;
|
313 |
+
display: inline-block;
|
314 |
+
font-family: 'Glyphicons Halflings';
|
315 |
+
-webkit-font-smoothing: antialiased;
|
316 |
+
font-style: normal;
|
317 |
+
font-weight: normal;
|
318 |
+
line-height: 1;
|
319 |
+
-moz-osx-font-smoothing: grayscale
|
320 |
+
}
|
321 |
+
|
322 |
+
.ez-toc-glyphicon:empty {
|
323 |
+
width: 1em
|
324 |
+
}
|
325 |
+
|
326 |
+
.ez-toc-toggle i.ez-toc-glyphicon {
|
327 |
+
font-size: 16px;
|
328 |
+
margin-left: 2px;
|
329 |
+
}
|
330 |
+
|
331 |
+
[class*="ez-toc-icon-"] {
|
332 |
+
font-family: 'ez-toc-icomoon' !important; /* For better glyphicon compatibility */
|
333 |
+
speak: none;
|
334 |
+
font-style: normal;
|
335 |
+
font-weight: normal;
|
336 |
+
font-variant: normal;
|
337 |
+
text-transform: none;
|
338 |
+
line-height: 1;
|
339 |
+
|
340 |
+
/* Better Font Rendering =========== */
|
341 |
+
-webkit-font-smoothing: antialiased;
|
342 |
+
-moz-osx-font-smoothing: grayscale;
|
343 |
+
}
|
344 |
+
|
345 |
+
.ez-toc-icon-toggle:before {
|
346 |
+
content: "\e87a";
|
347 |
+
}
|
348 |
+
#ez-toc-container input {
|
349 |
+
position: absolute;
|
350 |
+
left: -999em;
|
351 |
+
}
|
352 |
+
#ez-toc-container input[type="checkbox"]:checked + nav {
|
353 |
+
opacity: 0;
|
354 |
+
max-height: 0;
|
355 |
+
border: none;
|
356 |
+
}
|
357 |
+
|
358 |
+
#ez-toc-container label {
|
359 |
+
float: right;
|
360 |
+
position: relative;
|
361 |
+
left: 10px;
|
362 |
+
font-size: 16px;
|
363 |
+
background: #f9efef;
|
364 |
+
padding: 0px 4px 0px 5px;
|
365 |
+
border: 1px solid #999191;
|
366 |
+
border-radius: 5px;
|
367 |
+
cursor: pointer;
|
368 |
+
}
|
369 |
+
div#ez-toc-container p.ez-toc-title {
|
370 |
+
display: contents;
|
371 |
+
}
|
372 |
+
div#ez-toc-container {
|
373 |
+
padding-right: 20px;
|
374 |
+
}
|
assets/css/screen.min.css
CHANGED
@@ -1 +1 @@
|
|
1 |
-
#ez-toc-container{background
|
1 |
+
#ez-toc-container {background: #F9F9F9;border: 1px solid #AAAAAA;border-radius: 4px;-webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);display: table;margin-bottom: 1em;padding: 10px;position: relative;width: auto;}div.ez-toc-widget-container {padding: 0;position: relative;}#ez-toc-container.ez-toc-light-blue {background: #EDF6FF;}#ez-toc-container.ez-toc-white {background: #FFFFFF;}#ez-toc-container.ez-toc-black {background: #000000;}#ez-toc-container.ez-toc-transparent {background: none transparent;}div.ez-toc-widget-container ul {display: block;}div.ez-toc-widget-container li {border: none;padding: 0;}div.ez-toc-widget-container ul.ez-toc-list {padding: 10px;}#ez-toc-container ul ul, .ez-toc div.ez-toc-widget-container ul ul {margin-left: 1.5em;}#ez-toc-container ul, #ez-toc-container li {margin: 0;padding: 0;}#ez-toc-container ul, #ez-toc-container li, #ez-toc-container ul li, div.ez-toc-widget-container, div.ez-toc-widget-container li {background: none;list-style: none none;line-height: 1.6;margin: 0;overflow: hidden;z-index: 1;}#ez-toc-container p.ez-toc-title {text-align: left;line-height: 1.45;margin: 0;padding: 0;}.ez-toc-title-container {display: table;width: 100%;}.ez-toc-title, .ez-toc-title-toggle {display: table-cell;text-align: left;vertical-align: middle;}#ez-toc-container.ez-toc-black p.ez-toc-title {color: #FFF;}#ez-toc-container div.ez-toc-title-container + ul.ez-toc-list {margin-top: 1em;}.ez-toc-wrap-left {float: left;margin-right: 10px;}.ez-toc-wrap-right {float: right;margin-left: 10px;}#ez-toc-container a {color: #444444;box-shadow: none;text-decoration: none;text-shadow: none;}#ez-toc-container a:visited {color: #9f9f9f;}#ez-toc-container a:hover {text-decoration: underline;}#ez-toc-container.ez-toc-black a {color: #FFF;}#ez-toc-container.ez-toc-black a:visited {color: #FFF;}#ez-toc-container a.ez-toc-toggle {color: #444444;}#ez-toc-container.counter-hierarchy ul, .ez-toc-widget-container.counter-hierarchy ul, #ez-toc-container.counter-flat ul, .ez-toc-widget-container.counter-flat ul {counter-reset: item;}#ez-toc-container.counter-numeric li, .ez-toc-widget-container.counter-numeric li {list-style-type: decimal;list-style-position: inside;}#ez-toc-container.counter-decimal ul.ez-toc-list li a::before, .ez-toc-widget-container.counter-decimal ul.ez-toc-list li a::before {content: counters(item, ".") ". ";display: inline-block;counter-increment: item;margin-right: .2em;}#ez-toc-container.counter-roman li a::before, .ez-toc-widget-container.counter-roman ul.ez-toc-list li a::before {content: counters(item, ".", upper-roman) ". ";counter-increment: item;}.ez-toc-widget-container ul.ez-toc-list li::before {content: ' ';position: absolute;left: 0;right: 0;height: 30px;line-height: 30px;z-index: -1;}.ez-toc-widget-container ul.ez-toc-list li.active::before {background-color: #EDEDED;}.ez-toc-widget-container li.active > a {font-weight: 900;}.ez-toc-btn {display: inline-block;padding: 6px 12px;margin-bottom: 0;font-size: 14px;font-weight: normal;line-height: 1.428571429;text-align: center;white-space: nowrap;vertical-align: middle;cursor: pointer;background-image: none;border: 1px solid transparent;border-radius: 4px;-webkit-user-select: none;-moz-user-select: none;-ms-user-select: none;-o-user-select: none;user-select: none }.ez-toc-btn:focus {outline: thin dotted #333;outline: 5px auto -webkit-focus-ring-color;outline-offset: -2px }.ez-toc-btn:hover,.ez-toc-btn:focus {color: #333;text-decoration: none }.ez-toc-btn:active,.ez-toc-btn.active {background-image: none;outline: 0;-webkit-box-shadow: inset 0 3px 5px rgba(0,0,0,0.125);box-shadow: inset 0 3px 5px rgba(0,0,0,0.125) }.ez-toc-btn-default {color: #333;background-color: #fff;border-color: #ccc }.ez-toc-btn-default:hover,.ez-toc-btn-default:focus,.ez-toc-btn-default:active,.ez-toc-btn-default.active {color: #333;background-color: #ebebeb;border-color: #adadad }.ez-toc-btn-default:active,.ez-toc-btn-default.active {background-image: none }.ez-toc-btn-sm,.ez-toc-btn-xs {padding: 5px 10px;font-size: 12px;line-height: 1.5;border-radius: 3px }.ez-toc-btn-xs {padding: 1px 5px }.ez-toc-btn-default {text-shadow: 0 -1px 0 rgba(0,0,0,0.2);-webkit-box-shadow: inset 0 1px 0 rgba(255,255,255,0.15),0 1px 1px rgba(0,0,0,0.075);box-shadow: inset 0 1px 0 rgba(255,255,255,0.15),0 1px 1px rgba(0,0,0,0.075) }.ez-toc-btn-default:active {-webkit-box-shadow: inset 0 3px 5px rgba(0,0,0,0.125);box-shadow: inset 0 3px 5px rgba(0,0,0,0.125) }.ez-toc-btn:active,.btn.active {background-image: none }.ez-toc-btn-default {text-shadow: 0 1px 0 #fff;background-image: -webkit-gradient(linear,left 0,left 100%,from(#fff),to(#e0e0e0));background-image: -webkit-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image: -moz-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image: linear-gradient(to bottom,#fff 0,#e0e0e0 100%);background-repeat: repeat-x;border-color: #dbdbdb;border-color: #ccc;filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#ffe0e0e0',GradientType=0);filter: progid:DXImageTransform.Microsoft.gradient(enabled=false) }.ez-toc-btn-default:hover,.ez-toc-btn-default:focus {background-color: #e0e0e0;background-position: 0 -15px }.ez-toc-btn-default:active,.ez-toc-btn-default.active {background-color: #e0e0e0;border-color: #dbdbdb }.ez-toc-pull-right {float: right !important;margin-left: 10px;}.ez-toc-glyphicon {position: relative;top: 1px;display: inline-block;font-family: 'Glyphicons Halflings';-webkit-font-smoothing: antialiased;font-style: normal;font-weight: normal;line-height: 1;-moz-osx-font-smoothing: grayscale }.ez-toc-glyphicon:empty {width: 1em }.ez-toc-toggle i.ez-toc-glyphicon {font-size: 16px;margin-left: 2px;}[class*="ez-toc-icon-"] {font-family: 'ez-toc-icomoon' !important;speak: none;font-style: normal;font-weight: normal;font-variant: normal;text-transform: none;line-height: 1;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;}.ez-toc-icon-toggle:before {content: "\e87a";}#ez-toc-container input {position: absolute;left: -999em;}#ez-toc-container input[type="checkbox"]:checked + nav {opacity: 0;max-height: 0;border: none;}#ez-toc-container label {float: right;position: relative;left: 3px;font-size: 16px;background: #f9efef;padding: 0px 4px 0px 5px;border: 1px solid #999191;border-radius: 5px;cursor: pointer;}div#ez-toc-container p.ez-toc-title {display: contents;}div#ez-toc-container {padding-right: 20px;}#ez-toc-container label {left: 10px;}
|
assets/js/front.js
CHANGED
@@ -1,309 +1,309 @@
|
|
1 |
-
jQuery( function( $ ) {
|
2 |
-
|
3 |
-
/**
|
4 |
-
* @typedef ezTOC
|
5 |
-
* @type {Object} ezTOC
|
6 |
-
* @property {string} affixSelector
|
7 |
-
* @property {string} scroll_offset
|
8 |
-
* @property {string} smooth_scroll
|
9 |
-
* @property {string} visibility_hide_by_default
|
10 |
-
*/
|
11 |
-
|
12 |
-
if ( typeof ezTOC != 'undefined' ) {
|
13 |
-
|
14 |
-
var affix = $( '.ez-toc-widget-container.ez-toc-affix' );
|
15 |
-
|
16 |
-
if ( 0 !== affix.length ) {
|
17 |
-
|
18 |
-
/**
|
19 |
-
* The smooth scroll offset needs to be taken into account when defining the offset_top property.
|
20 |
-
* @link https://github.com/shazahm1/Easy-Table-of-Contents/issues/19
|
21 |
-
*
|
22 |
-
* @type {number}
|
23 |
-
*/
|
24 |
-
var affixOffset = 30;
|
25 |
-
|
26 |
-
// check offset setting
|
27 |
-
if ( typeof ezTOC.scroll_offset != 'undefined' ) {
|
28 |
-
|
29 |
-
affixOffset = parseInt( ezTOC.scroll_offset );
|
30 |
-
}
|
31 |
-
|
32 |
-
$( ezTOC.affixSelector ).stick_in_parent( {
|
33 |
-
inner_scrolling: false,
|
34 |
-
offset_top: affixOffset
|
35 |
-
} )
|
36 |
-
}
|
37 |
-
|
38 |
-
$.fn.shrinkTOCWidth = function() {
|
39 |
-
|
40 |
-
$( this ).css( {
|
41 |
-
width: 'auto',
|
42 |
-
display: 'table'
|
43 |
-
});
|
44 |
-
|
45 |
-
if ( /MSIE 7\./.test( navigator.userAgent ) )
|
46 |
-
$( this ).css( 'width', '' );
|
47 |
-
};
|
48 |
-
|
49 |
-
var smoothScroll = parseInt( ezTOC.smooth_scroll );
|
50 |
-
|
51 |
-
if ( 1 === smoothScroll ) {
|
52 |
-
|
53 |
-
$( 'a.ez-toc-link' ).on( 'click', function() {
|
54 |
-
|
55 |
-
var self = $( this );
|
56 |
-
|
57 |
-
var target = '';
|
58 |
-
var hostname = self.prop( 'hostname' );
|
59 |
-
var pathname = self.prop( 'pathname' );
|
60 |
-
var qs = self.prop( 'search' );
|
61 |
-
var hash = self.prop( 'hash' );
|
62 |
-
|
63 |
-
// ie strips out the preceding / from pathname
|
64 |
-
if ( pathname.length > 0 ) {
|
65 |
-
if ( pathname.charAt( 0 ) !== '/' ) {
|
66 |
-
pathname = '/' + pathname;
|
67 |
-
}
|
68 |
-
}
|
69 |
-
|
70 |
-
if ( ( window.location.hostname === hostname ) &&
|
71 |
-
( window.location.pathname === pathname ) &&
|
72 |
-
( window.location.search === qs ) &&
|
73 |
-
( hash !== '' )
|
74 |
-
) {
|
75 |
-
|
76 |
-
// var id = decodeURIComponent( hash.replace( '#', '' ) );
|
77 |
-
target = '[id="' + hash.replace( '#', '' ) + '"]';
|
78 |
-
|
79 |
-
// verify it exists
|
80 |
-
if ( $( target ).length === 0 ) {
|
81 |
-
console.log( 'ezTOC scrollTarget Not Found: ' + target );
|
82 |
-
target = '';
|
83 |
-
}
|
84 |
-
|
85 |
-
// check offset setting
|
86 |
-
if ( typeof ezTOC.scroll_offset != 'undefined' ) {
|
87 |
-
|
88 |
-
var offset = -1 * ezTOC.scroll_offset;
|
89 |
-
|
90 |
-
} else {
|
91 |
-
|
92 |
-
var adminbar = $( '#wpadminbar' );
|
93 |
-
|
94 |
-
if ( adminbar.length > 0 ) {
|
95 |
-
|
96 |
-
if ( adminbar.is( ':visible' ) )
|
97 |
-
offset = -30; // admin bar exists, give it the default
|
98 |
-
else
|
99 |
-
offset = 0; // there is an admin bar but it's hidden, so no offset!
|
100 |
-
|
101 |
-
} else {
|
102 |
-
|
103 |
-
// no admin bar, so no offset!
|
104 |
-
offset = 0;
|
105 |
-
}
|
106 |
-
}
|
107 |
-
|
108 |
-
if ( target ) {
|
109 |
-
$.smoothScroll( {
|
110 |
-
scrollTarget: target,
|
111 |
-
offset: offset,
|
112 |
-
beforeScroll: deactivateSetActiveEzTocListElement,
|
113 |
-
afterScroll: function() { setActiveEzTocListElement(); activateSetActiveEzTocListElement(); }
|
114 |
-
} );
|
115 |
-
|
116 |
-
}
|
117 |
-
}
|
118 |
-
} );
|
119 |
-
}
|
120 |
-
|
121 |
-
if ( typeof ezTOC.visibility_hide_by_default != 'undefined' ) {
|
122 |
-
|
123 |
-
var toc = $( 'ul.ez-toc-list' );
|
124 |
-
var toggle = $( 'a.ez-toc-toggle' );
|
125 |
-
var invert = ezTOC.visibility_hide_by_default;
|
126 |
-
|
127 |
-
toggle.css( 'display', 'inline' );
|
128 |
-
|
129 |
-
if ( Cookies ) {
|
130 |
-
|
131 |
-
Cookies.get( 'ezTOC_hidetoc' ) == 1 ? toggle.data( 'visible', false ) : toggle.data( 'visible', true );
|
132 |
-
|
133 |
-
} else {
|
134 |
-
|
135 |
-
toggle.data( 'visible', true );
|
136 |
-
}
|
137 |
-
|
138 |
-
if ( invert ) {
|
139 |
-
|
140 |
-
toggle.data( 'visible', false )
|
141 |
-
}
|
142 |
-
|
143 |
-
if ( ! toggle.data( 'visible' ) ) {
|
144 |
-
|
145 |
-
toc.hide();
|
146 |
-
}
|
147 |
-
|
148 |
-
toggle.on( 'click', function( event ) {
|
149 |
-
|
150 |
-
event.preventDefault();
|
151 |
-
|
152 |
-
if ( $( this ).data( 'visible' ) ) {
|
153 |
-
|
154 |
-
$( this ).data( 'visible', false );
|
155 |
-
|
156 |
-
if ( Cookies ) {
|
157 |
-
|
158 |
-
if ( invert )
|
159 |
-
Cookies.set( 'ezTOC_hidetoc', null, { path: '/' } );
|
160 |
-
else
|
161 |
-
Cookies.set( 'ezTOC_hidetoc', '1', { expires: 30, path: '/' } );
|
162 |
-
}
|
163 |
-
|
164 |
-
toc.hide( 'fast' );
|
165 |
-
|
166 |
-
} else {
|
167 |
-
|
168 |
-
$( this ).data( 'visible', true );
|
169 |
-
|
170 |
-
if ( Cookies ) {
|
171 |
-
|
172 |
-
if ( invert )
|
173 |
-
Cookies.set( 'ezTOC_hidetoc', '1', { expires: 30, path: '/' } );
|
174 |
-
else
|
175 |
-
Cookies.set( 'ezTOC_hidetoc', null, { path: '/' } );
|
176 |
-
}
|
177 |
-
|
178 |
-
toc.show( 'fast' );
|
179 |
-
|
180 |
-
}
|
181 |
-
|
182 |
-
} );
|
183 |
-
}
|
184 |
-
|
185 |
-
|
186 |
-
// ======================================
|
187 |
-
// Set active heading in ez-toc-widget list
|
188 |
-
// ======================================
|
189 |
-
|
190 |
-
var headings = $( 'span.ez-toc-section' ).toArray();
|
191 |
-
var headingToListElementLinkMap = getHeadingToListElementLinkMap( headings );
|
192 |
-
var listElementLinks = $.map( headingToListElementLinkMap, function ( value, key ) {
|
193 |
-
return value
|
194 |
-
} );
|
195 |
-
var scrollOffset = getScrollOffset();
|
196 |
-
|
197 |
-
activateSetActiveEzTocListElement();
|
198 |
-
|
199 |
-
function setActiveEzTocListElement() {
|
200 |
-
var activeHeading = getActiveHeading( scrollOffset, headings );
|
201 |
-
if ( activeHeading ) {
|
202 |
-
var activeListElementLink = headingToListElementLinkMap[ activeHeading.id ];
|
203 |
-
removeStyleFromNonActiveListElement( activeListElementLink, listElementLinks );
|
204 |
-
setStyleForActiveListElementElement( activeListElementLink );
|
205 |
-
}
|
206 |
-
}
|
207 |
-
|
208 |
-
function activateSetActiveEzTocListElement() {
|
209 |
-
if ( headings.length > 0 && $('.ez-toc-widget-container').length) {
|
210 |
-
$( window ).on( 'load resize scroll', setActiveEzTocListElement );
|
211 |
-
}
|
212 |
-
}
|
213 |
-
|
214 |
-
function deactivateSetActiveEzTocListElement() {
|
215 |
-
$( window ).off( 'load resize scroll', setActiveEzTocListElement );
|
216 |
-
}
|
217 |
-
|
218 |
-
function getEzTocListElementLinkByHeading( heading ) {
|
219 |
-
return $( '.ez-toc-widget-container .ez-toc-list a[href="#' + $( heading ).attr( 'id' ) + '"]' );
|
220 |
-
}
|
221 |
-
|
222 |
-
function getHeadingToListElementLinkMap( headings ) {
|
223 |
-
return headings.reduce( function ( map, heading ) {
|
224 |
-
map[ heading.id ] = getEzTocListElementLinkByHeading( heading );
|
225 |
-
return map;
|
226 |
-
}, {} );
|
227 |
-
}
|
228 |
-
|
229 |
-
function getScrollOffset() {
|
230 |
-
var scrollOffset = 5; // so if smooth offset is off, the correct title is set as active
|
231 |
-
if ( typeof ezTOC.smooth_scroll != 'undefined' && parseInt( ezTOC.smooth_scroll ) === 1 ) {
|
232 |
-
scrollOffset = ( typeof ezTOC.scroll_offset != 'undefined' ) ? parseInt( ezTOC.scroll_offset ) : 30;
|
233 |
-
}
|
234 |
-
|
235 |
-
var adminbar = $( '#wpadminbar' );
|
236 |
-
|
237 |
-
if ( adminbar.length ) {
|
238 |
-
scrollOffset += adminbar.height();
|
239 |
-
}
|
240 |
-
return scrollOffset;
|
241 |
-
}
|
242 |
-
|
243 |
-
function getActiveHeading( topOffset, headings ) {
|
244 |
-
var scrollTop = $( window ).scrollTop();
|
245 |
-
var relevantOffset = scrollTop + topOffset + 1;
|
246 |
-
var activeHeading = headings[ 0 ];
|
247 |
-
var closestHeadingAboveOffset = relevantOffset - $( activeHeading ).offset().top;
|
248 |
-
headings.forEach( function ( section ) {
|
249 |
-
var topOffset = relevantOffset - $( section ).offset().top;
|
250 |
-
if ( topOffset > 0 && topOffset < closestHeadingAboveOffset ) {
|
251 |
-
closestHeadingAboveOffset = topOffset;
|
252 |
-
activeHeading = section;
|
253 |
-
}
|
254 |
-
} );
|
255 |
-
return activeHeading;
|
256 |
-
}
|
257 |
-
|
258 |
-
function removeStyleFromNonActiveListElement( activeListElementLink, listElementLinks ) {
|
259 |
-
listElementLinks.forEach( function ( listElementLink ) {
|
260 |
-
if ( activeListElementLink !== listElementLink && listElementLink.parent().hasClass( 'active' ) ) {
|
261 |
-
listElementLink.parent().removeClass( 'active' );
|
262 |
-
}
|
263 |
-
} );
|
264 |
-
}
|
265 |
-
|
266 |
-
function correctActiveListElementBackgroundColorHeight( activeListElement ) {
|
267 |
-
var listElementHeight = getListElementHeightWithoutUlChildren( activeListElement );
|
268 |
-
addListElementBackgroundColorHeightStyleToHead( listElementHeight );
|
269 |
-
}
|
270 |
-
|
271 |
-
function getListElementHeightWithoutUlChildren( listElement ) {
|
272 |
-
var $listElement = $( listElement );
|
273 |
-
var content = $listElement.html();
|
274 |
-
// Adding list item with class '.active' to get the real height.
|
275 |
-
// When adding a class to an existing element and using jQuery(..).height() directly afterwards,
|
276 |
-
// the height is the 'old' height. The height might change due to text-wraps when setting the text-weight bold for example
|
277 |
-
// When adding a new item, the height is calculated correctly.
|
278 |
-
// But only when it might be visible (so display:none; is not possible...)
|
279 |
-
// But because it get's directly removed afterwards it never will be rendered by the browser
|
280 |
-
// (at least in my tests in FF, Chrome, IE11 and Edge)
|
281 |
-
$listElement.parent().append( '<li id="ez-toc-height-test" class="active">' + content + '</li>' );
|
282 |
-
var listItem = $( '#ez-toc-height-test' );
|
283 |
-
var height = listItem.height();
|
284 |
-
listItem.remove();
|
285 |
-
return height - $listElement.children( 'ul' ).first().height();
|
286 |
-
}
|
287 |
-
|
288 |
-
function addListElementBackgroundColorHeightStyleToHead( listElementHeight ) {
|
289 |
-
// Remove existing
|
290 |
-
$( '#ez-toc-active-height' ).remove();
|
291 |
-
// jQuery(..).css(..) doesn't work, because ::before is a pseudo element and not part of the DOM
|
292 |
-
// Workaround is to add it to head
|
293 |
-
$( '<style id="ez-toc-active-height">' +
|
294 |
-
'.ez-toc-widget-container ul.ez-toc-list li.active::before {' +
|
295 |
-
// 'line-heigh:' + listElementHeight + 'px; ' +
|
296 |
-
'height:' + listElementHeight + 'px;' +
|
297 |
-
'} </style>' )
|
298 |
-
.appendTo( 'head' );
|
299 |
-
}
|
300 |
-
|
301 |
-
function setStyleForActiveListElementElement( activeListElementLink ) {
|
302 |
-
var activeListElement = activeListElementLink.parent();
|
303 |
-
if ( !activeListElement.hasClass( 'active' ) ) {
|
304 |
-
activeListElement.addClass( 'active' );
|
305 |
-
}
|
306 |
-
correctActiveListElementBackgroundColorHeight( activeListElement );
|
307 |
-
}
|
308 |
-
}
|
309 |
-
} );
|
1 |
+
jQuery( function( $ ) {
|
2 |
+
|
3 |
+
/**
|
4 |
+
* @typedef ezTOC
|
5 |
+
* @type {Object} ezTOC
|
6 |
+
* @property {string} affixSelector
|
7 |
+
* @property {string} scroll_offset
|
8 |
+
* @property {string} smooth_scroll
|
9 |
+
* @property {string} visibility_hide_by_default
|
10 |
+
*/
|
11 |
+
|
12 |
+
if ( typeof ezTOC != 'undefined' ) {
|
13 |
+
|
14 |
+
var affix = $( '.ez-toc-widget-container.ez-toc-affix' );
|
15 |
+
|
16 |
+
if ( 0 !== affix.length ) {
|
17 |
+
|
18 |
+
/**
|
19 |
+
* The smooth scroll offset needs to be taken into account when defining the offset_top property.
|
20 |
+
* @link https://github.com/shazahm1/Easy-Table-of-Contents/issues/19
|
21 |
+
*
|
22 |
+
* @type {number}
|
23 |
+
*/
|
24 |
+
var affixOffset = 30;
|
25 |
+
|
26 |
+
// check offset setting
|
27 |
+
if ( typeof ezTOC.scroll_offset != 'undefined' ) {
|
28 |
+
|
29 |
+
affixOffset = parseInt( ezTOC.scroll_offset );
|
30 |
+
}
|
31 |
+
|
32 |
+
$( ezTOC.affixSelector ).stick_in_parent( {
|
33 |
+
inner_scrolling: false,
|
34 |
+
offset_top: affixOffset
|
35 |
+
} )
|
36 |
+
}
|
37 |
+
|
38 |
+
$.fn.shrinkTOCWidth = function() {
|
39 |
+
|
40 |
+
$( this ).css( {
|
41 |
+
width: 'auto',
|
42 |
+
display: 'table'
|
43 |
+
});
|
44 |
+
|
45 |
+
if ( /MSIE 7\./.test( navigator.userAgent ) )
|
46 |
+
$( this ).css( 'width', '' );
|
47 |
+
};
|
48 |
+
|
49 |
+
var smoothScroll = parseInt( ezTOC.smooth_scroll );
|
50 |
+
|
51 |
+
if ( 1 === smoothScroll ) {
|
52 |
+
|
53 |
+
$( 'a.ez-toc-link' ).on( 'click', function() {
|
54 |
+
|
55 |
+
var self = $( this );
|
56 |
+
|
57 |
+
var target = '';
|
58 |
+
var hostname = self.prop( 'hostname' );
|
59 |
+
var pathname = self.prop( 'pathname' );
|
60 |
+
var qs = self.prop( 'search' );
|
61 |
+
var hash = self.prop( 'hash' );
|
62 |
+
|
63 |
+
// ie strips out the preceding / from pathname
|
64 |
+
if ( pathname.length > 0 ) {
|
65 |
+
if ( pathname.charAt( 0 ) !== '/' ) {
|
66 |
+
pathname = '/' + pathname;
|
67 |
+
}
|
68 |
+
}
|
69 |
+
|
70 |
+
if ( ( window.location.hostname === hostname ) &&
|
71 |
+
( window.location.pathname === pathname ) &&
|
72 |
+
( window.location.search === qs ) &&
|
73 |
+
( hash !== '' )
|
74 |
+
) {
|
75 |
+
|
76 |
+
// var id = decodeURIComponent( hash.replace( '#', '' ) );
|
77 |
+
target = '[id="' + hash.replace( '#', '' ) + '"]';
|
78 |
+
|
79 |
+
// verify it exists
|
80 |
+
if ( $( target ).length === 0 ) {
|
81 |
+
console.log( 'ezTOC scrollTarget Not Found: ' + target );
|
82 |
+
target = '';
|
83 |
+
}
|
84 |
+
|
85 |
+
// check offset setting
|
86 |
+
if ( typeof ezTOC.scroll_offset != 'undefined' ) {
|
87 |
+
|
88 |
+
var offset = -1 * ezTOC.scroll_offset;
|
89 |
+
|
90 |
+
} else {
|
91 |
+
|
92 |
+
var adminbar = $( '#wpadminbar' );
|
93 |
+
|
94 |
+
if ( adminbar.length > 0 ) {
|
95 |
+
|
96 |
+
if ( adminbar.is( ':visible' ) )
|
97 |
+
offset = -30; // admin bar exists, give it the default
|
98 |
+
else
|
99 |
+
offset = 0; // there is an admin bar but it's hidden, so no offset!
|
100 |
+
|
101 |
+
} else {
|
102 |
+
|
103 |
+
// no admin bar, so no offset!
|
104 |
+
offset = 0;
|
105 |
+
}
|
106 |
+
}
|
107 |
+
|
108 |
+
if ( target ) {
|
109 |
+
$.smoothScroll( {
|
110 |
+
scrollTarget: target,
|
111 |
+
offset: offset,
|
112 |
+
beforeScroll: deactivateSetActiveEzTocListElement,
|
113 |
+
afterScroll: function() { setActiveEzTocListElement(); activateSetActiveEzTocListElement(); }
|
114 |
+
} );
|
115 |
+
|
116 |
+
}
|
117 |
+
}
|
118 |
+
} );
|
119 |
+
}
|
120 |
+
|
121 |
+
if ( typeof ezTOC.visibility_hide_by_default != 'undefined' ) {
|
122 |
+
|
123 |
+
var toc = $( 'ul.ez-toc-list' );
|
124 |
+
var toggle = $( 'a.ez-toc-toggle' );
|
125 |
+
var invert = ezTOC.visibility_hide_by_default;
|
126 |
+
|
127 |
+
toggle.css( 'display', 'inline' );
|
128 |
+
|
129 |
+
if ( Cookies ) {
|
130 |
+
|
131 |
+
Cookies.get( 'ezTOC_hidetoc' ) == 1 ? toggle.data( 'visible', false ) : toggle.data( 'visible', true );
|
132 |
+
|
133 |
+
} else {
|
134 |
+
|
135 |
+
toggle.data( 'visible', true );
|
136 |
+
}
|
137 |
+
|
138 |
+
if ( invert ) {
|
139 |
+
|
140 |
+
toggle.data( 'visible', false )
|
141 |
+
}
|
142 |
+
|
143 |
+
if ( ! toggle.data( 'visible' ) ) {
|
144 |
+
|
145 |
+
toc.hide();
|
146 |
+
}
|
147 |
+
|
148 |
+
toggle.on( 'click', function( event ) {
|
149 |
+
|
150 |
+
event.preventDefault();
|
151 |
+
|
152 |
+
if ( $( this ).data( 'visible' ) ) {
|
153 |
+
|
154 |
+
$( this ).data( 'visible', false );
|
155 |
+
|
156 |
+
if ( Cookies ) {
|
157 |
+
|
158 |
+
if ( invert )
|
159 |
+
Cookies.set( 'ezTOC_hidetoc', null, { path: '/' } );
|
160 |
+
else
|
161 |
+
Cookies.set( 'ezTOC_hidetoc', '1', { expires: 30, path: '/' } );
|
162 |
+
}
|
163 |
+
|
164 |
+
toc.hide( 'fast' );
|
165 |
+
|
166 |
+
} else {
|
167 |
+
|
168 |
+
$( this ).data( 'visible', true );
|
169 |
+
|
170 |
+
if ( Cookies ) {
|
171 |
+
|
172 |
+
if ( invert )
|
173 |
+
Cookies.set( 'ezTOC_hidetoc', '1', { expires: 30, path: '/' } );
|
174 |
+
else
|
175 |
+
Cookies.set( 'ezTOC_hidetoc', null, { path: '/' } );
|
176 |
+
}
|
177 |
+
|
178 |
+
toc.show( 'fast' );
|
179 |
+
|
180 |
+
}
|
181 |
+
|
182 |
+
} );
|
183 |
+
}
|
184 |
+
|
185 |
+
|
186 |
+
// ======================================
|
187 |
+
// Set active heading in ez-toc-widget list
|
188 |
+
// ======================================
|
189 |
+
|
190 |
+
var headings = $( 'span.ez-toc-section' ).toArray();
|
191 |
+
var headingToListElementLinkMap = getHeadingToListElementLinkMap( headings );
|
192 |
+
var listElementLinks = $.map( headingToListElementLinkMap, function ( value, key ) {
|
193 |
+
return value
|
194 |
+
} );
|
195 |
+
var scrollOffset = getScrollOffset();
|
196 |
+
|
197 |
+
activateSetActiveEzTocListElement();
|
198 |
+
|
199 |
+
function setActiveEzTocListElement() {
|
200 |
+
var activeHeading = getActiveHeading( scrollOffset, headings );
|
201 |
+
if ( activeHeading ) {
|
202 |
+
var activeListElementLink = headingToListElementLinkMap[ activeHeading.id ];
|
203 |
+
removeStyleFromNonActiveListElement( activeListElementLink, listElementLinks );
|
204 |
+
setStyleForActiveListElementElement( activeListElementLink );
|
205 |
+
}
|
206 |
+
}
|
207 |
+
|
208 |
+
function activateSetActiveEzTocListElement() {
|
209 |
+
if ( headings.length > 0 && $('.ez-toc-widget-container').length) {
|
210 |
+
$( window ).on( 'load resize scroll', setActiveEzTocListElement );
|
211 |
+
}
|
212 |
+
}
|
213 |
+
|
214 |
+
function deactivateSetActiveEzTocListElement() {
|
215 |
+
$( window ).off( 'load resize scroll', setActiveEzTocListElement );
|
216 |
+
}
|
217 |
+
|
218 |
+
function getEzTocListElementLinkByHeading( heading ) {
|
219 |
+
return $( '.ez-toc-widget-container .ez-toc-list a[href="#' + $( heading ).attr( 'id' ) + '"]' );
|
220 |
+
}
|
221 |
+
|
222 |
+
function getHeadingToListElementLinkMap( headings ) {
|
223 |
+
return headings.reduce( function ( map, heading ) {
|
224 |
+
map[ heading.id ] = getEzTocListElementLinkByHeading( heading );
|
225 |
+
return map;
|
226 |
+
}, {} );
|
227 |
+
}
|
228 |
+
|
229 |
+
function getScrollOffset() {
|
230 |
+
var scrollOffset = 5; // so if smooth offset is off, the correct title is set as active
|
231 |
+
if ( typeof ezTOC.smooth_scroll != 'undefined' && parseInt( ezTOC.smooth_scroll ) === 1 ) {
|
232 |
+
scrollOffset = ( typeof ezTOC.scroll_offset != 'undefined' ) ? parseInt( ezTOC.scroll_offset ) : 30;
|
233 |
+
}
|
234 |
+
|
235 |
+
var adminbar = $( '#wpadminbar' );
|
236 |
+
|
237 |
+
if ( adminbar.length ) {
|
238 |
+
scrollOffset += adminbar.height();
|
239 |
+
}
|
240 |
+
return scrollOffset;
|
241 |
+
}
|
242 |
+
|
243 |
+
function getActiveHeading( topOffset, headings ) {
|
244 |
+
var scrollTop = $( window ).scrollTop();
|
245 |
+
var relevantOffset = scrollTop + topOffset + 1;
|
246 |
+
var activeHeading = headings[ 0 ];
|
247 |
+
var closestHeadingAboveOffset = relevantOffset - $( activeHeading ).offset().top;
|
248 |
+
headings.forEach( function ( section ) {
|
249 |
+
var topOffset = relevantOffset - $( section ).offset().top;
|
250 |
+
if ( topOffset > 0 && topOffset < closestHeadingAboveOffset ) {
|
251 |
+
closestHeadingAboveOffset = topOffset;
|
252 |
+
activeHeading = section;
|
253 |
+
}
|
254 |
+
} );
|
255 |
+
return activeHeading;
|
256 |
+
}
|
257 |
+
|
258 |
+
function removeStyleFromNonActiveListElement( activeListElementLink, listElementLinks ) {
|
259 |
+
listElementLinks.forEach( function ( listElementLink ) {
|
260 |
+
if ( activeListElementLink !== listElementLink && listElementLink.parent().hasClass( 'active' ) ) {
|
261 |
+
listElementLink.parent().removeClass( 'active' );
|
262 |
+
}
|
263 |
+
} );
|
264 |
+
}
|
265 |
+
|
266 |
+
function correctActiveListElementBackgroundColorHeight( activeListElement ) {
|
267 |
+
var listElementHeight = getListElementHeightWithoutUlChildren( activeListElement );
|
268 |
+
addListElementBackgroundColorHeightStyleToHead( listElementHeight );
|
269 |
+
}
|
270 |
+
|
271 |
+
function getListElementHeightWithoutUlChildren( listElement ) {
|
272 |
+
var $listElement = $( listElement );
|
273 |
+
var content = $listElement.html();
|
274 |
+
// Adding list item with class '.active' to get the real height.
|
275 |
+
// When adding a class to an existing element and using jQuery(..).height() directly afterwards,
|
276 |
+
// the height is the 'old' height. The height might change due to text-wraps when setting the text-weight bold for example
|
277 |
+
// When adding a new item, the height is calculated correctly.
|
278 |
+
// But only when it might be visible (so display:none; is not possible...)
|
279 |
+
// But because it get's directly removed afterwards it never will be rendered by the browser
|
280 |
+
// (at least in my tests in FF, Chrome, IE11 and Edge)
|
281 |
+
$listElement.parent().append( '<li id="ez-toc-height-test" class="active">' + content + '</li>' );
|
282 |
+
var listItem = $( '#ez-toc-height-test' );
|
283 |
+
var height = listItem.height();
|
284 |
+
listItem.remove();
|
285 |
+
return height - $listElement.children( 'ul' ).first().height();
|
286 |
+
}
|
287 |
+
|
288 |
+
function addListElementBackgroundColorHeightStyleToHead( listElementHeight ) {
|
289 |
+
// Remove existing
|
290 |
+
$( '#ez-toc-active-height' ).remove();
|
291 |
+
// jQuery(..).css(..) doesn't work, because ::before is a pseudo element and not part of the DOM
|
292 |
+
// Workaround is to add it to head
|
293 |
+
$( '<style id="ez-toc-active-height">' +
|
294 |
+
'.ez-toc-widget-container ul.ez-toc-list li.active::before {' +
|
295 |
+
// 'line-heigh:' + listElementHeight + 'px; ' +
|
296 |
+
'height:' + listElementHeight + 'px;' +
|
297 |
+
'} </style>' )
|
298 |
+
.appendTo( 'head' );
|
299 |
+
}
|
300 |
+
|
301 |
+
function setStyleForActiveListElementElement( activeListElementLink ) {
|
302 |
+
var activeListElement = activeListElementLink.parent();
|
303 |
+
if ( !activeListElement.hasClass( 'active' ) ) {
|
304 |
+
activeListElement.addClass( 'active' );
|
305 |
+
}
|
306 |
+
correctActiveListElementBackgroundColorHeight( activeListElement );
|
307 |
+
}
|
308 |
+
}
|
309 |
+
} );
|
easy-table-of-contents.php
CHANGED
@@ -1,738 +1,743 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Plugin Name: Easy Table of Contents
|
4 |
-
* Plugin URI: https://magazine3.company/
|
5 |
-
* Description: Adds a user friendly and fully automatic way to create and display a table of contents generated from the page content.
|
6 |
-
* Version: 2.0.
|
7 |
-
* Author: Magazine3
|
8 |
-
* Author URI: https://magazine3.company/
|
9 |
-
* Text Domain: easy-table-of-contents
|
10 |
-
* Domain Path: /languages
|
11 |
-
*
|
12 |
-
* Copyright 2022 Magazine3 ( email :
|
13 |
-
*
|
14 |
-
* Easy Table of Contents is free software; you can redistribute it and/or modify
|
15 |
-
* it under the terms of the GNU General Public License, version 2, as
|
16 |
-
* published by the Free Software Foundation.
|
17 |
-
*
|
18 |
-
* This program is distributed in the hope that it will be useful,
|
19 |
-
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
20 |
-
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
21 |
-
* GNU General Public License for more details.
|
22 |
-
*
|
23 |
-
* You should have received a copy of the GNU General Public License
|
24 |
-
* along with Easy Table of Contents; if not, see <http://www.gnu.org/licenses/>.
|
25 |
-
*
|
26 |
-
* @package Easy Table of Contents
|
27 |
-
* @category Plugin
|
28 |
-
* @author Magazine3
|
29 |
-
* @version 2.0.
|
30 |
-
*/
|
31 |
-
|
32 |
-
use Easy_Plugins\Table_Of_Contents\Debug;
|
33 |
-
use function Easy_Plugins\Table_Of_Contents\String\mb_find_replace;
|
34 |
-
|
35 |
-
// Exit if accessed directly
|
36 |
-
if ( ! defined( 'ABSPATH' ) ) exit;
|
37 |
-
|
38 |
-
if ( ! class_exists( 'ezTOC' ) ) {
|
39 |
-
|
40 |
-
/**
|
41 |
-
* Class ezTOC
|
42 |
-
*/
|
43 |
-
final class ezTOC {
|
44 |
-
|
45 |
-
/**
|
46 |
-
* Current version.
|
47 |
-
*
|
48 |
-
* @since 1.0
|
49 |
-
* @var string
|
50 |
-
*/
|
51 |
-
const VERSION = '2.0.
|
52 |
-
|
53 |
-
/**
|
54 |
-
* Stores the instance of this class.
|
55 |
-
*
|
56 |
-
* @access private
|
57 |
-
* @since 1.0
|
58 |
-
* @static
|
59 |
-
*
|
60 |
-
* @var ezTOC
|
61 |
-
*/
|
62 |
-
private static $instance;
|
63 |
-
|
64 |
-
/**
|
65 |
-
* @since 2.0
|
66 |
-
* @var array
|
67 |
-
*/
|
68 |
-
private static $store = array();
|
69 |
-
|
70 |
-
/**
|
71 |
-
* A dummy constructor to prevent the class from being loaded more than once.
|
72 |
-
*
|
73 |
-
* @access public
|
74 |
-
* @since 1.0
|
75 |
-
*/
|
76 |
-
public function __construct() { /* Do nothing here */ }
|
77 |
-
|
78 |
-
/**
|
79 |
-
* @access private
|
80 |
-
* @since 1.0
|
81 |
-
* @static
|
82 |
-
*
|
83 |
-
* @return ezTOC
|
84 |
-
*/
|
85 |
-
public static function instance() {
|
86 |
-
|
87 |
-
if ( ! isset( self::$instance ) && ! ( self::$instance instanceof self ) ) {
|
88 |
-
|
89 |
-
self::$instance = new self;
|
90 |
-
|
91 |
-
self::defineConstants();
|
92 |
-
self::includes();
|
93 |
-
self::hooks();
|
94 |
-
|
95 |
-
self::loadTextdomain();
|
96 |
-
}
|
97 |
-
|
98 |
-
return self::$instance;
|
99 |
-
}
|
100 |
-
|
101 |
-
/**
|
102 |
-
* Define the plugin constants.
|
103 |
-
*
|
104 |
-
* @access private
|
105 |
-
* @since 1.0
|
106 |
-
* @static
|
107 |
-
*/
|
108 |
-
private static function defineConstants() {
|
109 |
-
|
110 |
-
define( 'EZ_TOC_DIR_NAME', plugin_basename( dirname( __FILE__ ) ) );
|
111 |
-
define( 'EZ_TOC_BASE_NAME', plugin_basename( __FILE__ ) );
|
112 |
-
define( 'EZ_TOC_PATH', dirname( __FILE__ ) );
|
113 |
-
define( 'EZ_TOC_URL', plugin_dir_url( __FILE__ ) );
|
114 |
-
}
|
115 |
-
|
116 |
-
/**
|
117 |
-
* Includes the plugin dependency files.
|
118 |
-
*
|
119 |
-
* @access private
|
120 |
-
* @since 1.0
|
121 |
-
* @static
|
122 |
-
*/
|
123 |
-
private static function includes() {
|
124 |
-
|
125 |
-
require_once( EZ_TOC_PATH . '/includes/class.options.php' );
|
126 |
-
|
127 |
-
if ( is_admin() ) {
|
128 |
-
|
129 |
-
// This must be included after `class.options.php` because it depends on it methods.
|
130 |
-
require_once( EZ_TOC_PATH . '/includes/class.admin.php' );
|
131 |
-
}
|
132 |
-
|
133 |
-
require_once( EZ_TOC_PATH . '/includes/class.post.php' );
|
134 |
-
require_once( EZ_TOC_PATH . '/includes/class.widget-toc.php' );
|
135 |
-
require_once( EZ_TOC_PATH . '/includes/Debug.php' );
|
136 |
-
require_once( EZ_TOC_PATH . '/includes/inc.functions.php' );
|
137 |
-
require_once( EZ_TOC_PATH . '/includes/inc.string-functions.php' );
|
138 |
-
|
139 |
-
require_once( EZ_TOC_PATH . '/includes/inc.plugin-compatibility.php' );
|
140 |
-
}
|
141 |
-
|
142 |
-
/**
|
143 |
-
* Add the core action filter hook.
|
144 |
-
*
|
145 |
-
* @access private
|
146 |
-
* @since 1.0
|
147 |
-
* @static
|
148 |
-
*/
|
149 |
-
private static function hooks() {
|
150 |
-
|
151 |
-
//add_action( 'plugins_loaded', array( __CLASS__, 'loadTextdomain' ) );
|
152 |
-
add_action( 'wp_enqueue_scripts', array( __CLASS__, 'enqueueScripts' ) );
|
153 |
-
|
154 |
-
// Run after shortcodes are interpreted (priority 10).
|
155 |
-
add_filter( 'the_content', array( __CLASS__, 'the_content' ), 100 );
|
156 |
-
add_shortcode( 'ez-toc', array( __CLASS__, 'shortcode' ) );
|
157 |
-
add_shortcode( apply_filters( 'ez_toc_shortcode', 'toc' ), array( __CLASS__, 'shortcode' ) );
|
158 |
-
}
|
159 |
-
|
160 |
-
/**
|
161 |
-
* Load the plugin translation.
|
162 |
-
*
|
163 |
-
* Credit: Adapted from Ninja Forms / Easy Digital Downloads.
|
164 |
-
*
|
165 |
-
* @access private
|
166 |
-
* @since 1.0
|
167 |
-
* @static
|
168 |
-
*
|
169 |
-
* @uses apply_filters()
|
170 |
-
* @uses get_locale()
|
171 |
-
* @uses load_textdomain()
|
172 |
-
* @uses load_plugin_textdomain()
|
173 |
-
*
|
174 |
-
* @return void
|
175 |
-
*/
|
176 |
-
public static function loadTextdomain() {
|
177 |
-
|
178 |
-
// Plugin textdomain. This should match the one set in the plugin header.
|
179 |
-
$domain = 'easy-table-of-contents';
|
180 |
-
|
181 |
-
// Set filter for plugin's languages directory
|
182 |
-
$languagesDirectory = apply_filters( "ez_{$domain}_languages_directory", EZ_TOC_DIR_NAME . '/languages/' );
|
183 |
-
|
184 |
-
// Traditional WordPress plugin locale filter
|
185 |
-
$locale = apply_filters( 'plugin_locale', get_locale(), $domain );
|
186 |
-
$fileName = sprintf( '%1$s-%2$s.mo', $domain, $locale );
|
187 |
-
|
188 |
-
// Setup paths to current locale file
|
189 |
-
$local = $languagesDirectory . $fileName;
|
190 |
-
$global = WP_LANG_DIR . "/{$domain}/" . $fileName;
|
191 |
-
|
192 |
-
if ( file_exists( $global ) ) {
|
193 |
-
|
194 |
-
// Look in global `../wp-content/languages/{$domain}/` folder.
|
195 |
-
load_textdomain( $domain, $global );
|
196 |
-
|
197 |
-
} elseif ( file_exists( $local ) ) {
|
198 |
-
|
199 |
-
// Look in local `../wp-content/plugins/{plugin-directory}/languages/` folder.
|
200 |
-
load_textdomain( $domain, $local );
|
201 |
-
|
202 |
-
} else {
|
203 |
-
|
204 |
-
// Load the default language files
|
205 |
-
load_plugin_textdomain( $domain, false, $languagesDirectory );
|
206 |
-
}
|
207 |
-
}
|
208 |
-
|
209 |
-
/**
|
210 |
-
* Call back for the `wp_enqueue_scripts` action.
|
211 |
-
*
|
212 |
-
* Register and enqueue CSS and javascript files for frontend.
|
213 |
-
*
|
214 |
-
* @access private
|
215 |
-
* @since 1.0
|
216 |
-
* @static
|
217 |
-
*/
|
218 |
-
public static function enqueueScripts() {
|
219 |
-
|
220 |
-
// If SCRIPT_DEBUG is set and TRUE load the non-minified JS files, otherwise, load the minified files.
|
221 |
-
$min = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
|
222 |
-
|
223 |
-
$js_vars = array();
|
224 |
-
|
225 |
-
$isEligible = self::is_eligible( get_post() );
|
226 |
-
|
227 |
-
if ( ! $isEligible && ! is_active_widget( false, false, 'ezw_tco' ) ) {
|
228 |
-
return false;
|
229 |
-
}
|
230 |
-
|
231 |
-
wp_register_style( 'ez-icomoon', EZ_TOC_URL . "vendor/icomoon/style$min.css", array(), ezTOC::VERSION );
|
232 |
-
wp_register_style( 'ez-toc', EZ_TOC_URL . "assets/css/screen$min.css", array( 'ez-icomoon' ), ezTOC::VERSION );
|
233 |
-
|
234 |
-
wp_register_script( 'js-cookie', EZ_TOC_URL . "vendor/js-cookie/js.cookie$min.js", array(), '2.2.1', TRUE );
|
235 |
-
wp_register_script( 'jquery-smooth-scroll', EZ_TOC_URL . "vendor/smooth-scroll/jquery.smooth-scroll$min.js", array( 'jquery' ), '2.2.0', TRUE );
|
236 |
-
wp_register_script( 'jquery-sticky-kit', EZ_TOC_URL . "vendor/sticky-kit/jquery.sticky-kit$min.js", array( 'jquery' ), '1.9.2', TRUE );
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
$
|
264 |
-
|
265 |
-
$js_vars['
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
$
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
*
|
287 |
-
*
|
288 |
-
* @
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
$css .= 'div#ez-toc-container
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
$css .= 'div#ez-toc-container
|
333 |
-
|
334 |
-
$css .= 'div#ez-toc-container ul.ez-toc-list a
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
*
|
348 |
-
*
|
349 |
-
*
|
350 |
-
*
|
351 |
-
* @
|
352 |
-
*
|
353 |
-
* @param
|
354 |
-
*
|
355 |
-
* @
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
}
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
*
|
373 |
-
*
|
374 |
-
*
|
375 |
-
*
|
376 |
-
* @
|
377 |
-
*
|
378 |
-
* @
|
379 |
-
*
|
380 |
-
* @
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
//
|
395 |
-
//
|
396 |
-
//
|
397 |
-
//
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
-
|
411 |
-
|
412 |
-
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
|
452 |
-
|
453 |
-
|
454 |
-
|
455 |
-
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
|
470 |
-
|
471 |
-
|
472 |
-
|
473 |
-
|
474 |
-
|
475 |
-
|
476 |
-
|
477 |
-
*
|
478 |
-
*
|
479 |
-
* @
|
480 |
-
*
|
481 |
-
* @
|
482 |
-
|
483 |
-
|
484 |
-
|
485 |
-
|
486 |
-
|
487 |
-
|
488 |
-
|
489 |
-
|
490 |
-
|
491 |
-
|
492 |
-
|
493 |
-
|
494 |
-
|
495 |
-
|
496 |
-
|
497 |
-
|
498 |
-
|
499 |
-
|
500 |
-
|
501 |
-
|
502 |
-
|
503 |
-
|
504 |
-
|
505 |
-
|
506 |
-
|
507 |
-
*
|
508 |
-
*
|
509 |
-
* @
|
510 |
-
*
|
511 |
-
*
|
512 |
-
* @
|
513 |
-
*
|
514 |
-
* @param string
|
515 |
-
*
|
516 |
-
* @
|
517 |
-
|
518 |
-
|
519 |
-
|
520 |
-
|
521 |
-
|
522 |
-
|
523 |
-
|
524 |
-
|
525 |
-
|
526 |
-
|
527 |
-
|
528 |
-
|
529 |
-
|
530 |
-
|
531 |
-
|
532 |
-
|
533 |
-
|
534 |
-
|
535 |
-
|
536 |
-
|
537 |
-
|
538 |
-
|
539 |
-
|
540 |
-
|
541 |
-
|
542 |
-
|
543 |
-
|
544 |
-
*
|
545 |
-
*
|
546 |
-
* @
|
547 |
-
|
548 |
-
|
549 |
-
|
550 |
-
|
551 |
-
|
552 |
-
|
553 |
-
|
554 |
-
|
555 |
-
|
556 |
-
|
557 |
-
|
558 |
-
|
559 |
-
|
560 |
-
|
561 |
-
|
562 |
-
|
563 |
-
|
564 |
-
|
565 |
-
|
566 |
-
|
567 |
-
|
568 |
-
|
569 |
-
*
|
570 |
-
*
|
571 |
-
* @
|
572 |
-
*
|
573 |
-
* @
|
574 |
-
|
575 |
-
|
576 |
-
|
577 |
-
|
578 |
-
|
579 |
-
|
580 |
-
|
581 |
-
*
|
582 |
-
*
|
583 |
-
*
|
584 |
-
*
|
585 |
-
*
|
586 |
-
* @
|
587 |
-
*
|
588 |
-
* @
|
589 |
-
|
590 |
-
|
591 |
-
|
592 |
-
|
593 |
-
|
594 |
-
|
595 |
-
|
596 |
-
|
597 |
-
|
598 |
-
|
599 |
-
|
600 |
-
|
601 |
-
|
602 |
-
|
603 |
-
|
604 |
-
|
605 |
-
|
606 |
-
|
607 |
-
|
608 |
-
|
609 |
-
|
610 |
-
|
611 |
-
|
612 |
-
|
613 |
-
|
614 |
-
|
615 |
-
|
616 |
-
|
617 |
-
|
618 |
-
|
619 |
-
|
620 |
-
|
621 |
-
|
622 |
-
|
623 |
-
|
624 |
-
|
625 |
-
|
626 |
-
|
627 |
-
|
628 |
-
|
629 |
-
|
630 |
-
$
|
631 |
-
$
|
632 |
-
|
633 |
-
$
|
634 |
-
$
|
635 |
-
|
636 |
-
$
|
637 |
-
|
638 |
-
|
639 |
-
|
640 |
-
|
641 |
-
|
642 |
-
|
643 |
-
|
644 |
-
|
645 |
-
'
|
646 |
-
'
|
647 |
-
|
648 |
-
|
649 |
-
|
650 |
-
|
651 |
-
|
652 |
-
|
653 |
-
|
654 |
-
|
655 |
-
|
656 |
-
|
657 |
-
|
658 |
-
|
659 |
-
|
660 |
-
|
661 |
-
|
662 |
-
|
663 |
-
|
664 |
-
|
665 |
-
|
666 |
-
|
667 |
-
|
668 |
-
|
669 |
-
|
670 |
-
|
671 |
-
|
672 |
-
|
673 |
-
|
674 |
-
|
675 |
-
$content
|
676 |
-
break;
|
677 |
-
|
678 |
-
case '
|
679 |
-
|
680 |
-
|
681 |
-
|
682 |
-
|
683 |
-
|
684 |
-
|
685 |
-
|
686 |
-
|
687 |
-
|
688 |
-
|
689 |
-
|
690 |
-
|
691 |
-
|
692 |
-
|
693 |
-
|
694 |
-
|
695 |
-
|
696 |
-
|
697 |
-
|
698 |
-
|
699 |
-
|
700 |
-
|
701 |
-
|
702 |
-
|
703 |
-
|
704 |
-
|
705 |
-
|
706 |
-
|
707 |
-
|
708 |
-
|
709 |
-
|
710 |
-
|
711 |
-
|
712 |
-
|
713 |
-
|
714 |
-
|
715 |
-
|
716 |
-
|
717 |
-
|
718 |
-
|
719 |
-
|
720 |
-
|
721 |
-
|
722 |
-
|
723 |
-
|
724 |
-
|
725 |
-
*
|
726 |
-
*
|
727 |
-
*
|
728 |
-
*
|
729 |
-
*
|
730 |
-
|
731 |
-
|
732 |
-
|
733 |
-
|
734 |
-
|
735 |
-
|
736 |
-
|
737 |
-
|
738 |
-
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Plugin Name: Easy Table of Contents
|
4 |
+
* Plugin URI: https://magazine3.company/
|
5 |
+
* Description: Adds a user friendly and fully automatic way to create and display a table of contents generated from the page content.
|
6 |
+
* Version: 2.0.20
|
7 |
+
* Author: Magazine3
|
8 |
+
* Author URI: https://magazine3.company/
|
9 |
+
* Text Domain: easy-table-of-contents
|
10 |
+
* Domain Path: /languages
|
11 |
+
*
|
12 |
+
* Copyright 2022 Magazine3 ( email : team@magazine3.in )
|
13 |
+
*
|
14 |
+
* Easy Table of Contents is free software; you can redistribute it and/or modify
|
15 |
+
* it under the terms of the GNU General Public License, version 2, as
|
16 |
+
* published by the Free Software Foundation.
|
17 |
+
*
|
18 |
+
* This program is distributed in the hope that it will be useful,
|
19 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
20 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
21 |
+
* GNU General Public License for more details.
|
22 |
+
*
|
23 |
+
* You should have received a copy of the GNU General Public License
|
24 |
+
* along with Easy Table of Contents; if not, see <http://www.gnu.org/licenses/>.
|
25 |
+
*
|
26 |
+
* @package Easy Table of Contents
|
27 |
+
* @category Plugin
|
28 |
+
* @author Magazine3
|
29 |
+
* @version 2.0.20
|
30 |
+
*/
|
31 |
+
|
32 |
+
use Easy_Plugins\Table_Of_Contents\Debug;
|
33 |
+
use function Easy_Plugins\Table_Of_Contents\String\mb_find_replace;
|
34 |
+
|
35 |
+
// Exit if accessed directly
|
36 |
+
if ( ! defined( 'ABSPATH' ) ) exit;
|
37 |
+
|
38 |
+
if ( ! class_exists( 'ezTOC' ) ) {
|
39 |
+
|
40 |
+
/**
|
41 |
+
* Class ezTOC
|
42 |
+
*/
|
43 |
+
final class ezTOC {
|
44 |
+
|
45 |
+
/**
|
46 |
+
* Current version.
|
47 |
+
*
|
48 |
+
* @since 1.0
|
49 |
+
* @var string
|
50 |
+
*/
|
51 |
+
const VERSION = '2.0.20';
|
52 |
+
|
53 |
+
/**
|
54 |
+
* Stores the instance of this class.
|
55 |
+
*
|
56 |
+
* @access private
|
57 |
+
* @since 1.0
|
58 |
+
* @static
|
59 |
+
*
|
60 |
+
* @var ezTOC
|
61 |
+
*/
|
62 |
+
private static $instance;
|
63 |
+
|
64 |
+
/**
|
65 |
+
* @since 2.0
|
66 |
+
* @var array
|
67 |
+
*/
|
68 |
+
private static $store = array();
|
69 |
+
|
70 |
+
/**
|
71 |
+
* A dummy constructor to prevent the class from being loaded more than once.
|
72 |
+
*
|
73 |
+
* @access public
|
74 |
+
* @since 1.0
|
75 |
+
*/
|
76 |
+
public function __construct() { /* Do nothing here */ }
|
77 |
+
|
78 |
+
/**
|
79 |
+
* @access private
|
80 |
+
* @since 1.0
|
81 |
+
* @static
|
82 |
+
*
|
83 |
+
* @return ezTOC
|
84 |
+
*/
|
85 |
+
public static function instance() {
|
86 |
+
|
87 |
+
if ( ! isset( self::$instance ) && ! ( self::$instance instanceof self ) ) {
|
88 |
+
|
89 |
+
self::$instance = new self;
|
90 |
+
|
91 |
+
self::defineConstants();
|
92 |
+
self::includes();
|
93 |
+
self::hooks();
|
94 |
+
|
95 |
+
self::loadTextdomain();
|
96 |
+
}
|
97 |
+
|
98 |
+
return self::$instance;
|
99 |
+
}
|
100 |
+
|
101 |
+
/**
|
102 |
+
* Define the plugin constants.
|
103 |
+
*
|
104 |
+
* @access private
|
105 |
+
* @since 1.0
|
106 |
+
* @static
|
107 |
+
*/
|
108 |
+
private static function defineConstants() {
|
109 |
+
|
110 |
+
define( 'EZ_TOC_DIR_NAME', plugin_basename( dirname( __FILE__ ) ) );
|
111 |
+
define( 'EZ_TOC_BASE_NAME', plugin_basename( __FILE__ ) );
|
112 |
+
define( 'EZ_TOC_PATH', dirname( __FILE__ ) );
|
113 |
+
define( 'EZ_TOC_URL', plugin_dir_url( __FILE__ ) );
|
114 |
+
}
|
115 |
+
|
116 |
+
/**
|
117 |
+
* Includes the plugin dependency files.
|
118 |
+
*
|
119 |
+
* @access private
|
120 |
+
* @since 1.0
|
121 |
+
* @static
|
122 |
+
*/
|
123 |
+
private static function includes() {
|
124 |
+
|
125 |
+
require_once( EZ_TOC_PATH . '/includes/class.options.php' );
|
126 |
+
|
127 |
+
if ( is_admin() ) {
|
128 |
+
|
129 |
+
// This must be included after `class.options.php` because it depends on it methods.
|
130 |
+
require_once( EZ_TOC_PATH . '/includes/class.admin.php' );
|
131 |
+
}
|
132 |
+
|
133 |
+
require_once( EZ_TOC_PATH . '/includes/class.post.php' );
|
134 |
+
require_once( EZ_TOC_PATH . '/includes/class.widget-toc.php' );
|
135 |
+
require_once( EZ_TOC_PATH . '/includes/Debug.php' );
|
136 |
+
require_once( EZ_TOC_PATH . '/includes/inc.functions.php' );
|
137 |
+
require_once( EZ_TOC_PATH . '/includes/inc.string-functions.php' );
|
138 |
+
|
139 |
+
require_once( EZ_TOC_PATH . '/includes/inc.plugin-compatibility.php' );
|
140 |
+
}
|
141 |
+
|
142 |
+
/**
|
143 |
+
* Add the core action filter hook.
|
144 |
+
*
|
145 |
+
* @access private
|
146 |
+
* @since 1.0
|
147 |
+
* @static
|
148 |
+
*/
|
149 |
+
private static function hooks() {
|
150 |
+
|
151 |
+
//add_action( 'plugins_loaded', array( __CLASS__, 'loadTextdomain' ) );
|
152 |
+
add_action( 'wp_enqueue_scripts', array( __CLASS__, 'enqueueScripts' ) );
|
153 |
+
|
154 |
+
// Run after shortcodes are interpreted (priority 10).
|
155 |
+
add_filter( 'the_content', array( __CLASS__, 'the_content' ), 100 );
|
156 |
+
add_shortcode( 'ez-toc', array( __CLASS__, 'shortcode' ) );
|
157 |
+
add_shortcode( apply_filters( 'ez_toc_shortcode', 'toc' ), array( __CLASS__, 'shortcode' ) );
|
158 |
+
}
|
159 |
+
|
160 |
+
/**
|
161 |
+
* Load the plugin translation.
|
162 |
+
*
|
163 |
+
* Credit: Adapted from Ninja Forms / Easy Digital Downloads.
|
164 |
+
*
|
165 |
+
* @access private
|
166 |
+
* @since 1.0
|
167 |
+
* @static
|
168 |
+
*
|
169 |
+
* @uses apply_filters()
|
170 |
+
* @uses get_locale()
|
171 |
+
* @uses load_textdomain()
|
172 |
+
* @uses load_plugin_textdomain()
|
173 |
+
*
|
174 |
+
* @return void
|
175 |
+
*/
|
176 |
+
public static function loadTextdomain() {
|
177 |
+
|
178 |
+
// Plugin textdomain. This should match the one set in the plugin header.
|
179 |
+
$domain = 'easy-table-of-contents';
|
180 |
+
|
181 |
+
// Set filter for plugin's languages directory
|
182 |
+
$languagesDirectory = apply_filters( "ez_{$domain}_languages_directory", EZ_TOC_DIR_NAME . '/languages/' );
|
183 |
+
|
184 |
+
// Traditional WordPress plugin locale filter
|
185 |
+
$locale = apply_filters( 'plugin_locale', get_locale(), $domain );
|
186 |
+
$fileName = sprintf( '%1$s-%2$s.mo', $domain, $locale );
|
187 |
+
|
188 |
+
// Setup paths to current locale file
|
189 |
+
$local = $languagesDirectory . $fileName;
|
190 |
+
$global = WP_LANG_DIR . "/{$domain}/" . $fileName;
|
191 |
+
|
192 |
+
if ( file_exists( $global ) ) {
|
193 |
+
|
194 |
+
// Look in global `../wp-content/languages/{$domain}/` folder.
|
195 |
+
load_textdomain( $domain, $global );
|
196 |
+
|
197 |
+
} elseif ( file_exists( $local ) ) {
|
198 |
+
|
199 |
+
// Look in local `../wp-content/plugins/{plugin-directory}/languages/` folder.
|
200 |
+
load_textdomain( $domain, $local );
|
201 |
+
|
202 |
+
} else {
|
203 |
+
|
204 |
+
// Load the default language files
|
205 |
+
load_plugin_textdomain( $domain, false, $languagesDirectory );
|
206 |
+
}
|
207 |
+
}
|
208 |
+
|
209 |
+
/**
|
210 |
+
* Call back for the `wp_enqueue_scripts` action.
|
211 |
+
*
|
212 |
+
* Register and enqueue CSS and javascript files for frontend.
|
213 |
+
*
|
214 |
+
* @access private
|
215 |
+
* @since 1.0
|
216 |
+
* @static
|
217 |
+
*/
|
218 |
+
public static function enqueueScripts() {
|
219 |
+
|
220 |
+
// If SCRIPT_DEBUG is set and TRUE load the non-minified JS files, otherwise, load the minified files.
|
221 |
+
$min = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
|
222 |
+
|
223 |
+
$js_vars = array();
|
224 |
+
|
225 |
+
$isEligible = self::is_eligible( get_post() );
|
226 |
+
|
227 |
+
if ( ! $isEligible && ! is_active_widget( false, false, 'ezw_tco' ) ) {
|
228 |
+
return false;
|
229 |
+
}
|
230 |
+
|
231 |
+
wp_register_style( 'ez-icomoon', EZ_TOC_URL . "vendor/icomoon/style$min.css", array(), ezTOC::VERSION );
|
232 |
+
wp_register_style( 'ez-toc', EZ_TOC_URL . "assets/css/screen$min.css", array( 'ez-icomoon' ), ezTOC::VERSION );
|
233 |
+
|
234 |
+
wp_register_script( 'js-cookie', EZ_TOC_URL . "vendor/js-cookie/js.cookie$min.js", array(), '2.2.1', TRUE );
|
235 |
+
wp_register_script( 'jquery-smooth-scroll', EZ_TOC_URL . "vendor/smooth-scroll/jquery.smooth-scroll$min.js", array( 'jquery' ), '2.2.0', TRUE );
|
236 |
+
wp_register_script( 'jquery-sticky-kit', EZ_TOC_URL . "vendor/sticky-kit/jquery.sticky-kit$min.js", array( 'jquery' ), '1.9.2', TRUE );
|
237 |
+
|
238 |
+
if (ezTOC_Option::get( 'toc_loading' ) != 'css') {
|
239 |
+
wp_register_script(
|
240 |
+
'ez-toc-js',
|
241 |
+
EZ_TOC_URL . "assets/js/front{$min}.js",
|
242 |
+
array( 'jquery-smooth-scroll', 'js-cookie', 'jquery-sticky-kit' ),
|
243 |
+
ezTOC::VERSION . '-' . filemtime( EZ_TOC_PATH . "/assets/js/front{$min}.js" ),
|
244 |
+
true
|
245 |
+
);
|
246 |
+
}
|
247 |
+
|
248 |
+
if ( ! ezTOC_Option::get( 'exclude_css' ) ) {
|
249 |
+
|
250 |
+
wp_enqueue_style( 'ez-toc' );
|
251 |
+
self::inlineCSS();
|
252 |
+
}
|
253 |
+
|
254 |
+
if ( ezTOC_Option::get( 'smooth_scroll' ) ) {
|
255 |
+
|
256 |
+
$js_vars['smooth_scroll'] = true;
|
257 |
+
}
|
258 |
+
|
259 |
+
//wp_enqueue_script( 'ez-toc-js' );
|
260 |
+
|
261 |
+
if ( ezTOC_Option::get( 'show_heading_text' ) && ezTOC_Option::get( 'visibility' ) ) {
|
262 |
+
|
263 |
+
$width = ezTOC_Option::get( 'width' ) !== 'custom' ? ezTOC_Option::get( 'width' ) : ezTOC_Option::get( 'width_custom' ) . ezTOC_Option::get( 'width_custom_units' );
|
264 |
+
|
265 |
+
$js_vars['visibility_hide_by_default'] = ezTOC_Option::get( 'visibility_hide_by_default' ) ? true : false;
|
266 |
+
|
267 |
+
$js_vars['width'] = esc_js( $width );
|
268 |
+
}
|
269 |
+
|
270 |
+
$offset = wp_is_mobile() ? ezTOC_Option::get( 'mobile_smooth_scroll_offset', 0 ) : ezTOC_Option::get( 'smooth_scroll_offset', 30 );
|
271 |
+
|
272 |
+
$js_vars['scroll_offset'] = esc_js( $offset );
|
273 |
+
|
274 |
+
if ( ezTOC_Option::get( 'widget_affix_selector' ) ) {
|
275 |
+
|
276 |
+
$js_vars['affixSelector'] = ezTOC_Option::get( 'widget_affix_selector' );
|
277 |
+
}
|
278 |
+
|
279 |
+
if ( 0 < count( $js_vars ) ) {
|
280 |
+
|
281 |
+
wp_localize_script( 'ez-toc-js', 'ezTOC', $js_vars );
|
282 |
+
}
|
283 |
+
}
|
284 |
+
|
285 |
+
/**
|
286 |
+
* Prints out inline CSS after the core CSS file to allow overriding core styles via options.
|
287 |
+
*
|
288 |
+
* @access private
|
289 |
+
* @since 1.0
|
290 |
+
* @static
|
291 |
+
*/
|
292 |
+
public static function inlineCSS() {
|
293 |
+
|
294 |
+
$css = '';
|
295 |
+
|
296 |
+
if ( ! ezTOC_Option::get( 'exclude_css' ) ) {
|
297 |
+
|
298 |
+
$css .= 'div#ez-toc-container p.ez-toc-title {font-size: ' . ezTOC_Option::get( 'title_font_size', 120 ) . ezTOC_Option::get( 'title_font_size_units', '%' ) . ';}';
|
299 |
+
$css .= 'div#ez-toc-container p.ez-toc-title {font-weight: ' . ezTOC_Option::get( 'title_font_weight', 500 ) . ';}';
|
300 |
+
$css .= 'div#ez-toc-container ul li {font-size: ' . ezTOC_Option::get( 'font_size' ) . ezTOC_Option::get( 'font_size_units' ) . ';}';
|
301 |
+
|
302 |
+
if ( ezTOC_Option::get( 'theme' ) === 'custom' || ezTOC_Option::get( 'width' ) != 'auto' ) {
|
303 |
+
|
304 |
+
$css .= 'div#ez-toc-container {';
|
305 |
+
|
306 |
+
if ( ezTOC_Option::get( 'theme' ) === 'custom' ) {
|
307 |
+
|
308 |
+
$css .= 'background: ' . ezTOC_Option::get( 'custom_background_colour' ) . ';border: 1px solid ' . ezTOC_Option::get( 'custom_border_colour' ) . ';';
|
309 |
+
}
|
310 |
+
|
311 |
+
if ( 'auto' !== ezTOC_Option::get( 'width' ) ) {
|
312 |
+
|
313 |
+
$css .= 'width: ';
|
314 |
+
|
315 |
+
if ( 'custom' !== ezTOC_Option::get( 'width' ) ) {
|
316 |
+
|
317 |
+
$css .= ezTOC_Option::get( 'width' );
|
318 |
+
|
319 |
+
} else {
|
320 |
+
|
321 |
+
$css .= ezTOC_Option::get( 'width_custom' ) . ezTOC_Option::get( 'width_custom_units' );
|
322 |
+
}
|
323 |
+
|
324 |
+
$css .= ';';
|
325 |
+
}
|
326 |
+
|
327 |
+
$css .= '}';
|
328 |
+
}
|
329 |
+
|
330 |
+
if ( 'custom' === ezTOC_Option::get( 'theme' ) ) {
|
331 |
+
|
332 |
+
$css .= 'div#ez-toc-container p.ez-toc-title {color: ' . ezTOC_Option::get( 'custom_title_colour' ) . ';}';
|
333 |
+
//$css .= 'div#ez-toc-container p.ez-toc-title a,div#ez-toc-container ul.ez-toc-list a {color: ' . ezTOC_Option::get( 'custom_link_colour' ) . ';}';
|
334 |
+
$css .= 'div#ez-toc-container ul.ez-toc-list a {color: ' . ezTOC_Option::get( 'custom_link_colour' ) . ';}';
|
335 |
+
$css .= 'div#ez-toc-container ul.ez-toc-list a:hover {color: ' . ezTOC_Option::get( 'custom_link_hover_colour' ) . ';}';
|
336 |
+
$css .= 'div#ez-toc-container ul.ez-toc-list a:visited {color: ' . ezTOC_Option::get( 'custom_link_visited_colour' ) . ';}';
|
337 |
+
}
|
338 |
+
}
|
339 |
+
|
340 |
+
if ( $css ) {
|
341 |
+
|
342 |
+
wp_add_inline_style( 'ez-toc', $css );
|
343 |
+
}
|
344 |
+
}
|
345 |
+
|
346 |
+
/**
|
347 |
+
* Array search deep.
|
348 |
+
*
|
349 |
+
* Search an array recursively for a value.
|
350 |
+
*
|
351 |
+
* @link https://stackoverflow.com/a/5427665/5351316
|
352 |
+
*
|
353 |
+
* @param $search
|
354 |
+
* @param array $array
|
355 |
+
* @param string $mode
|
356 |
+
*
|
357 |
+
* @return bool
|
358 |
+
*/
|
359 |
+
public static function array_search_deep( $search, array $array, $mode = 'value' ) {
|
360 |
+
|
361 |
+
foreach ( new RecursiveIteratorIterator( new RecursiveArrayIterator( $array ) ) as $key => $value ) {
|
362 |
+
|
363 |
+
if ( $search === ${${"mode"}} ) {
|
364 |
+
return true;
|
365 |
+
}
|
366 |
+
}
|
367 |
+
|
368 |
+
return false;
|
369 |
+
}
|
370 |
+
|
371 |
+
/**
|
372 |
+
* Returns true if the table of contents is eligible to be printed, false otherwise.
|
373 |
+
*
|
374 |
+
* NOTE: Must bve use only within the loop.
|
375 |
+
*
|
376 |
+
* @access public
|
377 |
+
* @since 1.0
|
378 |
+
* @static
|
379 |
+
*
|
380 |
+
* @param WP_Post $post
|
381 |
+
*
|
382 |
+
* @return bool
|
383 |
+
*/
|
384 |
+
public static function is_eligible( $post ) {
|
385 |
+
|
386 |
+
//global $wp_current_filter;
|
387 |
+
|
388 |
+
if ( empty( $post ) || ! $post instanceof WP_Post ) {
|
389 |
+
|
390 |
+
Debug::log( 'not_instance_of_post', 'Not an instance if `WP_Post`.', $post );
|
391 |
+
return false;
|
392 |
+
}
|
393 |
+
|
394 |
+
// This can likely be removed since it is checked in maybeApplyTheContentFilter().
|
395 |
+
// Do not execute if root filter is one of those in the array.
|
396 |
+
//if ( in_array( $wp_current_filter[0], array( 'get_the_excerpt', 'wp_head' ), true ) ) {
|
397 |
+
//
|
398 |
+
// return false;
|
399 |
+
//}
|
400 |
+
|
401 |
+
if ( has_shortcode( $post->post_content, apply_filters( 'ez_toc_shortcode', 'toc' ) ) ||
|
402 |
+
has_shortcode( $post->post_content, 'ez-toc' ) ) {
|
403 |
+
|
404 |
+
Debug::log( 'has_ez_toc_shortcode', 'Has instance of shortcode.', true );
|
405 |
+
return true;
|
406 |
+
}
|
407 |
+
|
408 |
+
if ( is_front_page() && ! ezTOC_Option::get( 'include_homepage' ) ) {
|
409 |
+
|
410 |
+
Debug::log( 'is_front_page', 'Is frontpage, TOC is not enabled.', false );
|
411 |
+
return false;
|
412 |
+
}
|
413 |
+
|
414 |
+
$type = get_post_type( $post->ID );
|
415 |
+
|
416 |
+
Debug::log( 'current_post_type', 'Post type is.', $type );
|
417 |
+
|
418 |
+
$enabled = in_array( $type, ezTOC_Option::get( 'enabled_post_types', array() ), true );
|
419 |
+
$insert = in_array( $type, ezTOC_Option::get( 'auto_insert_post_types', array() ), true );
|
420 |
+
|
421 |
+
Debug::log( 'is_supported_post_type', 'Is supported post type?', $enabled );
|
422 |
+
Debug::log( 'is_auto_insert_post_type', 'Is auto insert for post types?', $insert );
|
423 |
+
|
424 |
+
if ( $insert || $enabled ) {
|
425 |
+
|
426 |
+
if ( ezTOC_Option::get( 'restrict_path' ) ) {
|
427 |
+
|
428 |
+
/**
|
429 |
+
* @link https://wordpress.org/support/topic/restrict-path-logic-does-not-work-correctly?
|
430 |
+
*/
|
431 |
+
if ( false !== strpos( ezTOC_Option::get( 'restrict_path' ), $_SERVER['REQUEST_URI'] ) ) {
|
432 |
+
|
433 |
+
Debug::log( 'is_restricted_path', 'In restricted path, post not eligible.', ezTOC_Option::get( 'restrict_path' ) );
|
434 |
+
return false;
|
435 |
+
|
436 |
+
} else {
|
437 |
+
|
438 |
+
Debug::log( 'is_not_restricted_path', 'Not in restricted path, post is eligible.', ezTOC_Option::get( 'restrict_path' ) );
|
439 |
+
return true;
|
440 |
+
}
|
441 |
+
|
442 |
+
} else {
|
443 |
+
|
444 |
+
if ( $insert && 1 === (int) get_post_meta( $post->ID, '_ez-toc-disabled', true ) ) {
|
445 |
+
|
446 |
+
Debug::log( 'is_auto_insert_disable_post_meta', 'Auto insert enabled and disable TOC is enabled in post meta.', false );
|
447 |
+
return false;
|
448 |
+
|
449 |
+
} elseif ( $insert && 0 === (int) get_post_meta( $post->ID, '_ez-toc-disabled', true ) ) {
|
450 |
+
|
451 |
+
Debug::log( 'is_auto_insert_enabled_post_meta', 'Auto insert enabled and disable TOC is not enabled in post meta.', true );
|
452 |
+
return true;
|
453 |
+
|
454 |
+
} elseif ( $enabled && 1 === (int) get_post_meta( $post->ID, '_ez-toc-insert', true ) ) {
|
455 |
+
|
456 |
+
Debug::log( 'is_supported_post_type_disable_insert_post_meta', 'Supported post type and insert TOC is enabled in post meta.', true );
|
457 |
+
return true;
|
458 |
+
|
459 |
+
} elseif ( $enabled && $insert ) {
|
460 |
+
|
461 |
+
Debug::log( 'supported_post_type_and_auto_insert', 'Supported post type and auto insert TOC is enabled.', true );
|
462 |
+
return true;
|
463 |
+
}
|
464 |
+
|
465 |
+
Debug::log( 'not_auto_insert_or_not_supported_post_type', 'Not supported post type or insert TOC is disabled.', false );
|
466 |
+
return false;
|
467 |
+
}
|
468 |
+
|
469 |
+
} else {
|
470 |
+
|
471 |
+
Debug::log( 'not_auto_insert_and_not_supported post_type', 'Not supported post type and do not auto insert TOC.', false );
|
472 |
+
return false;
|
473 |
+
}
|
474 |
+
}
|
475 |
+
|
476 |
+
/**
|
477 |
+
* Get TOC from store and if not in store process post and add it to the store.
|
478 |
+
*
|
479 |
+
* @since 2.0
|
480 |
+
*
|
481 |
+
* @param int $id
|
482 |
+
*
|
483 |
+
* @return ezTOC_Post|null
|
484 |
+
*/
|
485 |
+
public static function get( $id ) {
|
486 |
+
|
487 |
+
$post = null;
|
488 |
+
|
489 |
+
if ( isset( self::$store[ $id ] ) && self::$store[ $id ] instanceof ezTOC_Post ) {
|
490 |
+
|
491 |
+
$post = self::$store[ $id ];
|
492 |
+
|
493 |
+
} else {
|
494 |
+
|
495 |
+
$post = ezTOC_Post::get( get_the_ID() );
|
496 |
+
|
497 |
+
if ( $post instanceof ezTOC_Post ) {
|
498 |
+
|
499 |
+
self::$store[ $id ] = $post;
|
500 |
+
}
|
501 |
+
}
|
502 |
+
|
503 |
+
return $post;
|
504 |
+
}
|
505 |
+
|
506 |
+
/**
|
507 |
+
* Callback for the registered shortcode `[ez-toc]`
|
508 |
+
*
|
509 |
+
* NOTE: Shortcode is run before the callback @see ezTOC::the_content() for the `the_content` filter
|
510 |
+
*
|
511 |
+
* @access private
|
512 |
+
* @since 1.3
|
513 |
+
*
|
514 |
+
* @param array|string $atts Shortcode attributes array or empty string.
|
515 |
+
* @param string $content The enclosed content (if the shortcode is used in its enclosing form)
|
516 |
+
* @param string $tag Shortcode name.
|
517 |
+
*
|
518 |
+
* @return string
|
519 |
+
*/
|
520 |
+
public static function shortcode( $atts, $content, $tag ) {
|
521 |
+
|
522 |
+
static $run = true;
|
523 |
+
$html = '';
|
524 |
+
|
525 |
+
if ( $run ) {
|
526 |
+
|
527 |
+
$post = self::get( get_the_ID() );
|
528 |
+
|
529 |
+
if ( ! $post instanceof ezTOC_Post ) {
|
530 |
+
|
531 |
+
Debug::log( 'not_instance_of_post', 'Not an instance if `WP_Post`.', get_the_ID() );
|
532 |
+
|
533 |
+
return Debug::log()->appendTo( $content );
|
534 |
+
}
|
535 |
+
|
536 |
+
$html = $post->getTOC();
|
537 |
+
$run = false;
|
538 |
+
}
|
539 |
+
|
540 |
+
return $html;
|
541 |
+
}
|
542 |
+
|
543 |
+
/**
|
544 |
+
* Whether or not apply `the_content` filter.
|
545 |
+
*
|
546 |
+
* @since 2.0
|
547 |
+
*
|
548 |
+
* @return bool
|
549 |
+
*/
|
550 |
+
private static function maybeApplyTheContentFilter() {
|
551 |
+
|
552 |
+
$apply = true;
|
553 |
+
|
554 |
+
global $wp_current_filter;
|
555 |
+
|
556 |
+
// Do not execute if root current filter is one of those in the array.
|
557 |
+
if ( in_array( $wp_current_filter[0], array( 'get_the_excerpt', 'init', 'wp_head' ), true ) ) {
|
558 |
+
|
559 |
+
$apply = false;
|
560 |
+
}
|
561 |
+
|
562 |
+
// bail if feed, search or archive
|
563 |
+
if ( is_feed() || is_search() || is_archive() ) {
|
564 |
+
|
565 |
+
$apply = false;
|
566 |
+
}
|
567 |
+
|
568 |
+
/**
|
569 |
+
* Whether or not to apply `the_content` filter callback.
|
570 |
+
*
|
571 |
+
* @see ezTOC::the_content()
|
572 |
+
*
|
573 |
+
* @since 2.0
|
574 |
+
*
|
575 |
+
* @param bool $apply
|
576 |
+
*/
|
577 |
+
return apply_filters( 'ez_toc_maybe_apply_the_content_filter', $apply );
|
578 |
+
}
|
579 |
+
|
580 |
+
/**
|
581 |
+
* Callback for the `the_content` filter.
|
582 |
+
*
|
583 |
+
* This will add the inline table of contents page anchors to the post content. It will also insert the
|
584 |
+
* table of contents inline with the post content as defined by the user defined preference.
|
585 |
+
*
|
586 |
+
* @since 1.0
|
587 |
+
*
|
588 |
+
* @param string $content
|
589 |
+
*
|
590 |
+
* @return string
|
591 |
+
*/
|
592 |
+
public static function the_content( $content ) {
|
593 |
+
$content = str_replace('–', '', $content);
|
594 |
+
$maybeApplyFilter = self::maybeApplyTheContentFilter();
|
595 |
+
|
596 |
+
Debug::log( 'the_content_filter', 'The `the_content` filter applied.', $maybeApplyFilter );
|
597 |
+
|
598 |
+
if ( ! $maybeApplyFilter ) {
|
599 |
+
|
600 |
+
return Debug::log()->appendTo( $content );
|
601 |
+
}
|
602 |
+
|
603 |
+
// Bail if post not eligible and widget is not active.
|
604 |
+
$isEligible = self::is_eligible( get_post() );
|
605 |
+
|
606 |
+
Debug::log( 'post_eligible', 'Post eligible.', $isEligible );
|
607 |
+
|
608 |
+
$getpost = self::get( get_the_ID() );
|
609 |
+
$getTOC = $getpost->getTOC();
|
610 |
+
if ( ! $isEligible && ! is_active_widget( false, false, 'ezw_tco' ) && empty($getTOC) ) {
|
611 |
+
|
612 |
+
return Debug::log()->appendTo( $content );
|
613 |
+
}
|
614 |
+
|
615 |
+
$post = self::get( get_the_ID() );
|
616 |
+
|
617 |
+
if ( ! $post instanceof ezTOC_Post ) {
|
618 |
+
|
619 |
+
Debug::log( 'not_instance_of_post', 'Not an instance if `WP_Post`.', get_the_ID() );
|
620 |
+
|
621 |
+
return Debug::log()->appendTo( $content );
|
622 |
+
}
|
623 |
+
|
624 |
+
// Bail if no headings found.
|
625 |
+
if ( ! $post->hasTOCItems() ) {
|
626 |
+
|
627 |
+
return Debug::log()->appendTo( $content );
|
628 |
+
}
|
629 |
+
|
630 |
+
$find = $post->getHeadings();
|
631 |
+
$replace = $post->getHeadingsWithAnchors();
|
632 |
+
$toc = $post->getTOC();
|
633 |
+
$find = str_replace('–', '', $find);
|
634 |
+
$replace = str_replace('–', '', $replace);
|
635 |
+
$headings = implode( PHP_EOL, $find );
|
636 |
+
$anchors = implode( PHP_EOL, $replace );
|
637 |
+
|
638 |
+
$headingRows = count( $find ) + 1;
|
639 |
+
$anchorRows = count( $replace ) + 1;
|
640 |
+
|
641 |
+
$style = "background-image: linear-gradient(#F1F1F1 50%, #F9F9F9 50%); background-size: 100% 4em; border: 1px solid #CCC; font-family: monospace; font-size: 1em; line-height: 2em; margin: 0 auto; overflow: auto; padding: 0 8px 4px; white-space: nowrap; width: 100%;";
|
642 |
+
|
643 |
+
Debug::log(
|
644 |
+
'found_post_headings',
|
645 |
+
'Found headings:',
|
646 |
+
"<textarea rows='{$headingRows}' style='{$style}' wrap='soft'>{$headings}</textarea>"
|
647 |
+
);
|
648 |
+
|
649 |
+
Debug::log(
|
650 |
+
'replace_post_headings',
|
651 |
+
'Replace found headings with:',
|
652 |
+
"<textarea rows='{$anchorRows}' style='{$style}' wrap='soft'>{$anchors}</textarea>"
|
653 |
+
);
|
654 |
+
|
655 |
+
// If shortcode used or post not eligible, return content with anchored headings.
|
656 |
+
if ( strpos( $content, 'ez-toc-container' ) || ! $isEligible ) {
|
657 |
+
|
658 |
+
Debug::log( 'shortcode_found', 'Shortcode found, add links to content.', true );
|
659 |
+
|
660 |
+
return mb_find_replace( $find, $replace, $content );
|
661 |
+
}
|
662 |
+
|
663 |
+
$position = ezTOC_Option::get( 'position' );
|
664 |
+
|
665 |
+
Debug::log( 'toc_insert_position', 'Insert TOC at position', $position );
|
666 |
+
|
667 |
+
// else also add toc to content
|
668 |
+
switch ( $position ) {
|
669 |
+
|
670 |
+
case 'top':
|
671 |
+
$content = $toc . mb_find_replace( $find, $replace, $content );
|
672 |
+
break;
|
673 |
+
|
674 |
+
case 'bottom':
|
675 |
+
$content = mb_find_replace( $find, $replace, $content ) . $toc;
|
676 |
+
break;
|
677 |
+
|
678 |
+
case 'after':
|
679 |
+
$replace[0] = $replace[0] . $toc;
|
680 |
+
$content = mb_find_replace( $find, $replace, $content );
|
681 |
+
break;
|
682 |
+
|
683 |
+
case 'before':
|
684 |
+
default:
|
685 |
+
//$replace[0] = $html . $replace[0];
|
686 |
+
$content = mb_find_replace( $find, $replace, $content );
|
687 |
+
|
688 |
+
/**
|
689 |
+
* @link https://wordpress.org/support/topic/php-notice-undefined-offset-8/
|
690 |
+
*/
|
691 |
+
if ( ! array_key_exists( 0, $replace ) ) {
|
692 |
+
break;
|
693 |
+
}
|
694 |
+
|
695 |
+
$pattern = '`<h[1-6]{1}[^>]*' . preg_quote( $replace[0], '`' ) . '`msuU';
|
696 |
+
$result = preg_match( $pattern, $content, $matches );
|
697 |
+
|
698 |
+
/*
|
699 |
+
* Try to place TOC before the first heading found in eligible heading, failing that,
|
700 |
+
* insert TOC at top of content.
|
701 |
+
*/
|
702 |
+
if ( 1 === $result ) {
|
703 |
+
|
704 |
+
Debug::log( 'toc_insert_position_found', 'Insert TOC before first eligible heading.', $result );
|
705 |
+
|
706 |
+
$start = strpos( $content, $matches[0] );
|
707 |
+
$content = substr_replace( $content, $toc, $start, 0 );
|
708 |
+
|
709 |
+
} else {
|
710 |
+
|
711 |
+
Debug::log( 'toc_insert_position_not_found', 'Insert TOC before first eligible heading not found.', $result );
|
712 |
+
|
713 |
+
// Somehow, there are scenarios where the processing get this far and
|
714 |
+
// the TOC is being added to pages where it should not. Disable for now.
|
715 |
+
//$content = $html . $content;
|
716 |
+
}
|
717 |
+
}
|
718 |
+
|
719 |
+
return Debug::log()->appendTo( $content );
|
720 |
+
}
|
721 |
+
|
722 |
+
}
|
723 |
+
|
724 |
+
/**
|
725 |
+
* The main function responsible for returning the Easy Table of Contents instance to functions everywhere.
|
726 |
+
*
|
727 |
+
* Use this function like you would a global variable, except without needing to declare the global.
|
728 |
+
*
|
729 |
+
* Example: <?php $instance = ezTOC(); ?>
|
730 |
+
*
|
731 |
+
* @access public
|
732 |
+
* @since 1.0
|
733 |
+
*
|
734 |
+
* @return ezTOC
|
735 |
+
*/
|
736 |
+
function ezTOC() {
|
737 |
+
|
738 |
+
return ezTOC::instance();
|
739 |
+
}
|
740 |
+
|
741 |
+
// Start Easy Table of Contents.
|
742 |
+
add_action( 'plugins_loaded', 'ezTOC' );
|
743 |
+
}
|
includes/Debug.php
CHANGED
@@ -1,180 +1,180 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace Easy_Plugins\Table_Of_Contents;
|
4 |
-
|
5 |
-
use WP_Error;
|
6 |
-
|
7 |
-
/**
|
8 |
-
* Class Debug
|
9 |
-
*
|
10 |
-
* @package Easy_Plugins\Table_Of_Contents
|
11 |
-
*/
|
12 |
-
final class Debug extends WP_Error {
|
13 |
-
|
14 |
-
/**
|
15 |
-
* @since 2.0.13
|
16 |
-
* @var bool
|
17 |
-
*/
|
18 |
-
protected $display = false;
|
19 |
-
|
20 |
-
/**
|
21 |
-
* @since 2.0.13
|
22 |
-
* @var bool
|
23 |
-
*/
|
24 |
-
protected $enabled = false;
|
25 |
-
|
26 |
-
/**
|
27 |
-
* @var self
|
28 |
-
*/
|
29 |
-
private static $instance;
|
30 |
-
|
31 |
-
/**
|
32 |
-
* Debug constructor.
|
33 |
-
*
|
34 |
-
* @since 2.0.13
|
35 |
-
*
|
36 |
-
* @param string $code
|
37 |
-
* @param string $message
|
38 |
-
* @param string $data
|
39 |
-
*/
|
40 |
-
public function __construct( $code = '', $message = '', $data = '' ) {
|
41 |
-
|
42 |
-
parent::__construct( $code, $message, $data );
|
43 |
-
}
|
44 |
-
|
45 |
-
/**
|
46 |
-
* @since 2.0.14
|
47 |
-
*
|
48 |
-
* @param string $code
|
49 |
-
* @param string $message
|
50 |
-
* @param string $data
|
51 |
-
*
|
52 |
-
* @return Debug
|
53 |
-
*/
|
54 |
-
public static function log( $code = '', $message = '', $data = '' ) {
|
55 |
-
|
56 |
-
if ( ! isset( self::$instance ) && ! ( self::$instance instanceof self ) ) {
|
57 |
-
|
58 |
-
self::$instance = new self( $code, $message, $data );
|
59 |
-
|
60 |
-
self::$instance->display = apply_filters(
|
61 |
-
'Easy_Plugins/Table_Of_Contents/Debug/Display',
|
62 |
-
defined( 'WP_DEBUG_DISPLAY' ) && WP_DEBUG_DISPLAY
|
63 |
-
);
|
64 |
-
|
65 |
-
self::$instance->enabled = apply_filters(
|
66 |
-
'Easy_Plugins/Table_Of_Contents/Debug/Enabled',
|
67 |
-
( defined( 'WP_DEBUG' ) && WP_DEBUG ) && current_user_can( 'manage_options' )
|
68 |
-
);
|
69 |
-
|
70 |
-
} else {
|
71 |
-
|
72 |
-
if ( ! empty( $code ) && ! empty( $message ) ) {
|
73 |
-
|
74 |
-
self::$instance->add( $code, $message, $data );
|
75 |
-
}
|
76 |
-
}
|
77 |
-
|
78 |
-
return self::$instance;
|
79 |
-
}
|
80 |
-
|
81 |
-
/**
|
82 |
-
* Adds an error or appends an additional message to an existing error.
|
83 |
-
*
|
84 |
-
* NOTE: Overrides WP_Error::add() to allow support of passing `false` as `$data`.
|
85 |
-
*
|
86 |
-
* @since 2.0.14
|
87 |
-
*
|
88 |
-
* @param string|int $code Error code.
|
89 |
-
* @param string $message Error message.
|
90 |
-
* @param mixed $data Optional. Error data.
|
91 |
-
*/
|
92 |
-
public function add( $code, $message, $data = null ) {
|
93 |
-
$this->errors[ $code ][] = $message;
|
94 |
-
|
95 |
-
if ( ! is_null( $data ) ) {
|
96 |
-
$this->add_data( $data, $code );
|
97 |
-
}
|
98 |
-
|
99 |
-
/**
|
100 |
-
* Fires when an error is added to a WP_Error object.
|
101 |
-
*
|
102 |
-
* @since 5.6.0
|
103 |
-
*
|
104 |
-
* @param string|int $code Error code.
|
105 |
-
* @param string $message Error message.
|
106 |
-
* @param mixed $data Error data. Might be empty.
|
107 |
-
* @param WP_Error $wp_error The WP_Error object.
|
108 |
-
*/
|
109 |
-
do_action( 'wp_error_added', $code, $message, $data, $this );
|
110 |
-
}
|
111 |
-
|
112 |
-
/**
|
113 |
-
* @since 2.0.13
|
114 |
-
*
|
115 |
-
* @param string $content
|
116 |
-
*
|
117 |
-
* @return string
|
118 |
-
*/
|
119 |
-
public function appendTo( $content = '' ) {
|
120 |
-
|
121 |
-
return $content . $this;
|
122 |
-
}
|
123 |
-
|
124 |
-
/**
|
125 |
-
* @since 2.0.13
|
126 |
-
*
|
127 |
-
* @return string
|
128 |
-
*/
|
129 |
-
public function dump() {
|
130 |
-
|
131 |
-
$dump = array();
|
132 |
-
|
133 |
-
foreach ( (array) $this->errors as $code => $messages ) {
|
134 |
-
|
135 |
-
$data = $this->get_error_data( $code );
|
136 |
-
$data = is_string( $data ) ? $data : '<code>' . var_export( $data, true ) . '</code>';
|
137 |
-
$data = "\t\t<li class=\"ez-toc-debug-message-data\">{$data}</li>" . PHP_EOL;
|
138 |
-
|
139 |
-
array_push(
|
140 |
-
$dump,
|
141 |
-
PHP_EOL . "\t<ul class=\"ez-toc-debug-message-{$code}\">" . PHP_EOL . "\t\t<li class=\"ez-toc-debug-message\">" . implode( '</li>' . PHP_EOL . '<li>' . PHP_EOL, $messages ) . '</li>' . PHP_EOL . "{$data}\t</ul>" . PHP_EOL
|
142 |
-
);
|
143 |
-
}
|
144 |
-
|
145 |
-
return '<div class="ez-toc-debug-message">' . implode( '</div>' . PHP_EOL . '<div class="ez-toc-debug-message">', $dump ) . '</div>' . PHP_EOL;
|
146 |
-
}
|
147 |
-
|
148 |
-
/**
|
149 |
-
* @since 2.0.13
|
150 |
-
*
|
151 |
-
* @return string
|
152 |
-
*/
|
153 |
-
public function __toString() {
|
154 |
-
|
155 |
-
if ( false === $this->enabled ) {
|
156 |
-
|
157 |
-
return '';
|
158 |
-
}
|
159 |
-
|
160 |
-
if ( false === $this->display ) {
|
161 |
-
|
162 |
-
return '';
|
163 |
-
}
|
164 |
-
|
165 |
-
if ( ! $this->has_errors() ) {
|
166 |
-
|
167 |
-
return '';
|
168 |
-
}
|
169 |
-
|
170 |
-
$intro = sprintf(
|
171 |
-
'You see the following because <a href="%1$s"><code>WP_DEBUG</code></a> and <a href="%1$s"><code>WP_DEBUG_DISPLAY</code></a> are enabled on this site. Please disabled these to prevent the display of these developers\' debug messages.',
|
172 |
-
'https://codex.wordpress.org/WP_DEBUG'
|
173 |
-
);
|
174 |
-
|
175 |
-
$intro = PHP_EOL . "<p>{$intro}</p>" .PHP_EOL;
|
176 |
-
$dump = $this->dump();
|
177 |
-
|
178 |
-
return PHP_EOL . "<div class='ez-toc-debug-messages'>{$intro}{$dump}</div>" . PHP_EOL;
|
179 |
-
}
|
180 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace Easy_Plugins\Table_Of_Contents;
|
4 |
+
|
5 |
+
use WP_Error;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Class Debug
|
9 |
+
*
|
10 |
+
* @package Easy_Plugins\Table_Of_Contents
|
11 |
+
*/
|
12 |
+
final class Debug extends WP_Error {
|
13 |
+
|
14 |
+
/**
|
15 |
+
* @since 2.0.13
|
16 |
+
* @var bool
|
17 |
+
*/
|
18 |
+
protected $display = false;
|
19 |
+
|
20 |
+
/**
|
21 |
+
* @since 2.0.13
|
22 |
+
* @var bool
|
23 |
+
*/
|
24 |
+
protected $enabled = false;
|
25 |
+
|
26 |
+
/**
|
27 |
+
* @var self
|
28 |
+
*/
|
29 |
+
private static $instance;
|
30 |
+
|
31 |
+
/**
|
32 |
+
* Debug constructor.
|
33 |
+
*
|
34 |
+
* @since 2.0.13
|
35 |
+
*
|
36 |
+
* @param string $code
|
37 |
+
* @param string $message
|
38 |
+
* @param string $data
|
39 |
+
*/
|
40 |
+
public function __construct( $code = '', $message = '', $data = '' ) {
|
41 |
+
|
42 |
+
parent::__construct( $code, $message, $data );
|
43 |
+
}
|
44 |
+
|
45 |
+
/**
|
46 |
+
* @since 2.0.14
|
47 |
+
*
|
48 |
+
* @param string $code
|
49 |
+
* @param string $message
|
50 |
+
* @param string $data
|
51 |
+
*
|
52 |
+
* @return Debug
|
53 |
+
*/
|
54 |
+
public static function log( $code = '', $message = '', $data = '' ) {
|
55 |
+
|
56 |
+
if ( ! isset( self::$instance ) && ! ( self::$instance instanceof self ) ) {
|
57 |
+
|
58 |
+
self::$instance = new self( $code, $message, $data );
|
59 |
+
|
60 |
+
self::$instance->display = apply_filters(
|
61 |
+
'Easy_Plugins/Table_Of_Contents/Debug/Display',
|
62 |
+
defined( 'WP_DEBUG_DISPLAY' ) && WP_DEBUG_DISPLAY
|
63 |
+
);
|
64 |
+
|
65 |
+
self::$instance->enabled = apply_filters(
|
66 |
+
'Easy_Plugins/Table_Of_Contents/Debug/Enabled',
|
67 |
+
( defined( 'WP_DEBUG' ) && WP_DEBUG ) && current_user_can( 'manage_options' )
|
68 |
+
);
|
69 |
+
|
70 |
+
} else {
|
71 |
+
|
72 |
+
if ( ! empty( $code ) && ! empty( $message ) ) {
|
73 |
+
|
74 |
+
self::$instance->add( $code, $message, $data );
|
75 |
+
}
|
76 |
+
}
|
77 |
+
|
78 |
+
return self::$instance;
|
79 |
+
}
|
80 |
+
|
81 |
+
/**
|
82 |
+
* Adds an error or appends an additional message to an existing error.
|
83 |
+
*
|
84 |
+
* NOTE: Overrides WP_Error::add() to allow support of passing `false` as `$data`.
|
85 |
+
*
|
86 |
+
* @since 2.0.14
|
87 |
+
*
|
88 |
+
* @param string|int $code Error code.
|
89 |
+
* @param string $message Error message.
|
90 |
+
* @param mixed $data Optional. Error data.
|
91 |
+
*/
|
92 |
+
public function add( $code, $message, $data = null ) {
|
93 |
+
$this->errors[ $code ][] = $message;
|
94 |
+
|
95 |
+
if ( ! is_null( $data ) ) {
|
96 |
+
$this->add_data( $data, $code );
|
97 |
+
}
|
98 |
+
|
99 |
+
/**
|
100 |
+
* Fires when an error is added to a WP_Error object.
|
101 |
+
*
|
102 |
+
* @since 5.6.0
|
103 |
+
*
|
104 |
+
* @param string|int $code Error code.
|
105 |
+
* @param string $message Error message.
|
106 |
+
* @param mixed $data Error data. Might be empty.
|
107 |
+
* @param WP_Error $wp_error The WP_Error object.
|
108 |
+
*/
|
109 |
+
do_action( 'wp_error_added', $code, $message, $data, $this );
|
110 |
+
}
|
111 |
+
|
112 |
+
/**
|
113 |
+
* @since 2.0.13
|
114 |
+
*
|
115 |
+
* @param string $content
|
116 |
+
*
|
117 |
+
* @return string
|
118 |
+
*/
|
119 |
+
public function appendTo( $content = '' ) {
|
120 |
+
|
121 |
+
return $content . $this;
|
122 |
+
}
|
123 |
+
|
124 |
+
/**
|
125 |
+
* @since 2.0.13
|
126 |
+
*
|
127 |
+
* @return string
|
128 |
+
*/
|
129 |
+
public function dump() {
|
130 |
+
|
131 |
+
$dump = array();
|
132 |
+
|
133 |
+
foreach ( (array) $this->errors as $code => $messages ) {
|
134 |
+
|
135 |
+
$data = $this->get_error_data( $code );
|
136 |
+
$data = is_string( $data ) ? $data : '<code>' . var_export( $data, true ) . '</code>';
|
137 |
+
$data = "\t\t<li class=\"ez-toc-debug-message-data\">{$data}</li>" . PHP_EOL;
|
138 |
+
|
139 |
+
array_push(
|
140 |
+
$dump,
|
141 |
+
PHP_EOL . "\t<ul class=\"ez-toc-debug-message-{$code}\">" . PHP_EOL . "\t\t<li class=\"ez-toc-debug-message\">" . implode( '</li>' . PHP_EOL . '<li>' . PHP_EOL, $messages ) . '</li>' . PHP_EOL . "{$data}\t</ul>" . PHP_EOL
|
142 |
+
);
|
143 |
+
}
|
144 |
+
|
145 |
+
return '<div class="ez-toc-debug-message">' . implode( '</div>' . PHP_EOL . '<div class="ez-toc-debug-message">', $dump ) . '</div>' . PHP_EOL;
|
146 |
+
}
|
147 |
+
|
148 |
+
/**
|
149 |
+
* @since 2.0.13
|
150 |
+
*
|
151 |
+
* @return string
|
152 |
+
*/
|
153 |
+
public function __toString() {
|
154 |
+
|
155 |
+
if ( false === $this->enabled ) {
|
156 |
+
|
157 |
+
return '';
|
158 |
+
}
|
159 |
+
|
160 |
+
if ( false === $this->display ) {
|
161 |
+
|
162 |
+
return '';
|
163 |
+
}
|
164 |
+
|
165 |
+
if ( ! $this->has_errors() ) {
|
166 |
+
|
167 |
+
return '';
|
168 |
+
}
|
169 |
+
|
170 |
+
$intro = sprintf(
|
171 |
+
'You see the following because <a href="%1$s"><code>WP_DEBUG</code></a> and <a href="%1$s"><code>WP_DEBUG_DISPLAY</code></a> are enabled on this site. Please disabled these to prevent the display of these developers\' debug messages.',
|
172 |
+
'https://codex.wordpress.org/WP_DEBUG'
|
173 |
+
);
|
174 |
+
|
175 |
+
$intro = PHP_EOL . "<p>{$intro}</p>" .PHP_EOL;
|
176 |
+
$dump = $this->dump();
|
177 |
+
|
178 |
+
return PHP_EOL . "<div class='ez-toc-debug-messages'>{$intro}{$dump}</div>" . PHP_EOL;
|
179 |
+
}
|
180 |
+
}
|
includes/class.admin.php
CHANGED
@@ -1,569 +1,569 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
// Exit if accessed directly
|
4 |
-
if ( ! defined( 'ABSPATH' ) ) exit;
|
5 |
-
|
6 |
-
if ( ! class_exists( 'ezTOC_Admin' ) ) {
|
7 |
-
|
8 |
-
/**
|
9 |
-
* Class ezTOC_Admin
|
10 |
-
*/
|
11 |
-
final class ezTOC_Admin {
|
12 |
-
|
13 |
-
/**
|
14 |
-
* Setup plugin for admin use.
|
15 |
-
*
|
16 |
-
* @access private
|
17 |
-
* @since 1.0
|
18 |
-
* @static
|
19 |
-
*/
|
20 |
-
public function __construct() {
|
21 |
-
|
22 |
-
$this->hooks();
|
23 |
-
//$this->registerMetaboxes();
|
24 |
-
}
|
25 |
-
|
26 |
-
/**
|
27 |
-
* Add the core admin hooks.
|
28 |
-
*
|
29 |
-
* @access private
|
30 |
-
* @since 1.0
|
31 |
-
* @static
|
32 |
-
*/
|
33 |
-
private function hooks() {
|
34 |
-
|
35 |
-
add_action( 'admin_init', array( $this, 'registerScripts' ) );
|
36 |
-
add_action( 'admin_menu', array( $this, 'menu' ) );
|
37 |
-
add_action( 'init', array( $this, 'registerMetaboxes' ), 99 );
|
38 |
-
add_filter( 'plugin_action_links_' . EZ_TOC_BASE_NAME, array( $this, 'pluginActionLinks' ), 10, 2 );
|
39 |
-
add_action( 'admin_enqueue_scripts', array( $this, 'load_scripts' ) );
|
40 |
-
add_action('wp_ajax_eztoc_send_query_message', array( $this, 'eztoc_send_query_message'));
|
41 |
-
}
|
42 |
-
|
43 |
-
/**
|
44 |
-
* Callback to add the Settings link to the plugin action links.
|
45 |
-
*
|
46 |
-
* @access private
|
47 |
-
* @since 1.0
|
48 |
-
* @static
|
49 |
-
*
|
50 |
-
* @param $links
|
51 |
-
* @param $file
|
52 |
-
*
|
53 |
-
* @return array
|
54 |
-
*/
|
55 |
-
public function pluginActionLinks( $links, $file ) {
|
56 |
-
|
57 |
-
$action = array();
|
58 |
-
|
59 |
-
$action[] = sprintf(
|
60 |
-
'<a href="%1$s">%2$s</a>',
|
61 |
-
esc_url( add_query_arg( 'page', 'table-of-contents', self_admin_url( 'options-general.php' ) ) ),
|
62 |
-
esc_html__( 'Settings', 'easy-table-of-contents' )
|
63 |
-
);
|
64 |
-
|
65 |
-
return array_merge( $action, $links );
|
66 |
-
}
|
67 |
-
|
68 |
-
/**
|
69 |
-
* Register the scripts used in the admin.
|
70 |
-
*
|
71 |
-
* @access private
|
72 |
-
* @since 1.0
|
73 |
-
* @static
|
74 |
-
*/
|
75 |
-
public function registerScripts() {
|
76 |
-
|
77 |
-
wp_register_script( 'cn_toc_admin_script', EZ_TOC_URL . 'assets/js/admin.js', array( 'jquery', 'wp-color-picker' ), ezTOC::VERSION, true );
|
78 |
-
wp_register_style( 'cn_toc_admin_style', EZ_TOC_URL . 'assets/css/admin.css', array( 'wp-color-picker' ), ezTOC::VERSION );
|
79 |
-
}
|
80 |
-
|
81 |
-
/**
|
82 |
-
* Callback to add plugin as a submenu page of the Options page.
|
83 |
-
*
|
84 |
-
* This also adds the action to enqueue the scripts to be loaded on plugin's admin pages only.
|
85 |
-
*
|
86 |
-
* @access private
|
87 |
-
* @since 1.0
|
88 |
-
* @static
|
89 |
-
*/
|
90 |
-
public function menu() {
|
91 |
-
|
92 |
-
$page = add_submenu_page(
|
93 |
-
'options-general.php',
|
94 |
-
esc_html__( 'Table of Contents', 'easy-table-of-contents' ),
|
95 |
-
esc_html__( 'Table of Contents', 'easy-table-of-contents' ),
|
96 |
-
'manage_options',
|
97 |
-
'table-of-contents',
|
98 |
-
array( $this, 'page' )
|
99 |
-
);
|
100 |
-
|
101 |
-
add_action( 'admin_print_styles-' . $page, array( $this, 'enqueueScripts' ) );
|
102 |
-
}
|
103 |
-
|
104 |
-
/**
|
105 |
-
* Enqueue the scripts.
|
106 |
-
*
|
107 |
-
* @access private
|
108 |
-
* @since 1.0
|
109 |
-
* @static
|
110 |
-
*/
|
111 |
-
public function enqueueScripts() {
|
112 |
-
|
113 |
-
wp_enqueue_script( 'cn_toc_admin_script' );
|
114 |
-
wp_enqueue_style( 'cn_toc_admin_style' );
|
115 |
-
}
|
116 |
-
|
117 |
-
/**
|
118 |
-
* Callback to add the action which will register the table of contents post metaboxes.
|
119 |
-
*
|
120 |
-
* Metaboxes will only be registered for the post types per user preferences.
|
121 |
-
*
|
122 |
-
* @access private
|
123 |
-
* @since 1.0
|
124 |
-
* @static
|
125 |
-
*/
|
126 |
-
public function registerMetaboxes() {
|
127 |
-
|
128 |
-
foreach ( get_post_types() as $type ) {
|
129 |
-
|
130 |
-
if ( in_array( $type, ezTOC_Option::get( 'enabled_post_types', array() ) ) ) {
|
131 |
-
|
132 |
-
add_action( "add_meta_boxes_$type", array( $this, 'metabox' ) );
|
133 |
-
add_action( "save_post_$type", array( $this, 'save' ), 10, 3 );
|
134 |
-
}
|
135 |
-
}
|
136 |
-
}
|
137 |
-
|
138 |
-
/**
|
139 |
-
* Callback to register the table of contents metaboxes.
|
140 |
-
*
|
141 |
-
* @access private
|
142 |
-
* @since 1.0
|
143 |
-
* @static
|
144 |
-
*/
|
145 |
-
public function metabox() {
|
146 |
-
|
147 |
-
add_meta_box( 'ez-toc', esc_html__( 'Table of Contents', 'ez-toc' ), array( $this, 'displayMetabox' ) );
|
148 |
-
}
|
149 |
-
|
150 |
-
/**
|
151 |
-
* Callback to render the content of the table of contents metaboxes.
|
152 |
-
*
|
153 |
-
* @access private
|
154 |
-
* @since 1.0
|
155 |
-
* @static
|
156 |
-
*
|
157 |
-
* @param object $post The post object.
|
158 |
-
* @param $atts
|
159 |
-
*/
|
160 |
-
public function displayMetabox( $post, $atts ) {
|
161 |
-
|
162 |
-
// Add an nonce field so we can check for it on save.
|
163 |
-
wp_nonce_field( 'ez_toc_save', '_ez_toc_nonce' );
|
164 |
-
|
165 |
-
$suppress = get_post_meta( $post->ID, '_ez-toc-disabled', true ) == 1 ? true : false;
|
166 |
-
$insert = get_post_meta( $post->ID, '_ez-toc-insert', true ) == 1 ? true : false;
|
167 |
-
$headings = get_post_meta( $post->ID, '_ez-toc-heading-levels', true );
|
168 |
-
$exclude = get_post_meta( $post->ID, '_ez-toc-exclude', true );
|
169 |
-
$altText = get_post_meta( $post->ID, '_ez-toc-alttext', true );
|
170 |
-
|
171 |
-
if ( ! is_array( $headings ) ) {
|
172 |
-
|
173 |
-
$headings = array();
|
174 |
-
}
|
175 |
-
?>
|
176 |
-
|
177 |
-
<table class="form-table">
|
178 |
-
|
179 |
-
<tbody>
|
180 |
-
|
181 |
-
<tr>
|
182 |
-
<th scope="row"></th>
|
183 |
-
<td>
|
184 |
-
|
185 |
-
<?php if ( in_array( get_post_type( $post ), ezTOC_Option::get( 'auto_insert_post_types', array() ) ) ) :
|
186 |
-
|
187 |
-
ezTOC_Option::checkbox(
|
188 |
-
array(
|
189 |
-
'id' => 'disabled-toc',
|
190 |
-
'desc' => esc_html__( 'Disable the automatic insertion of the table of contents.', 'easy-table-of-contents' ),
|
191 |
-
'default' => $suppress,
|
192 |
-
),
|
193 |
-
$suppress
|
194 |
-
);
|
195 |
-
|
196 |
-
elseif( in_array( get_post_type( $post ), ezTOC_Option::get( 'enabled_post_types', array() ) ) ):
|
197 |
-
|
198 |
-
ezTOC_Option::checkbox(
|
199 |
-
array(
|
200 |
-
'id' => 'insert-toc',
|
201 |
-
'desc' => esc_html__( 'Insert table of contents.', 'easy-table-of-contents' ),
|
202 |
-
'default' => $insert,
|
203 |
-
),
|
204 |
-
$insert
|
205 |
-
);
|
206 |
-
|
207 |
-
endif; ?>
|
208 |
-
|
209 |
-
</td>
|
210 |
-
</tr>
|
211 |
-
|
212 |
-
<tr>
|
213 |
-
<th scope="row"><?php esc_html_e( 'Advanced:', 'easy-table-of-contents' ); ?></th>
|
214 |
-
<td>
|
215 |
-
<?php
|
216 |
-
ezTOC_Option::descriptive_text(
|
217 |
-
array(
|
218 |
-
'id' => 'exclude-desc',
|
219 |
-
'name' => '',
|
220 |
-
'desc' => '<p><strong>' . esc_html__( 'NOTE:', 'easy-table-of-contents' ) . '</strong></p>' .
|
221 |
-
'<ul>' .
|
222 |
-
'<li>' . esc_html__( 'Using the advanced options below will override the global advanced settings.', 'easy-table-of-contents' ) . '</li>' .
|
223 |
-
'</ul>',
|
224 |
-
)
|
225 |
-
);
|
226 |
-
?>
|
227 |
-
</td>
|
228 |
-
</tr>
|
229 |
-
|
230 |
-
<tr>
|
231 |
-
<th scope="row"><?php esc_html_e( 'Headings:', 'easy-table-of-contents' ); ?></th>
|
232 |
-
<td>
|
233 |
-
<?php
|
234 |
-
ezTOC_Option::checkboxgroup(
|
235 |
-
array(
|
236 |
-
'id' => 'heading-levels',
|
237 |
-
'desc' => esc_html__( 'Select the heading to consider when generating the table of contents. Deselecting a heading will exclude it.', 'easy-table-of-contents' ),
|
238 |
-
'options' => array(
|
239 |
-
'1' => __( 'Heading 1 (h1)', 'easy-table-of-contents' ),
|
240 |
-
'2' => __( 'Heading 2 (h2)', 'easy-table-of-contents' ),
|
241 |
-
'3' => __( 'Heading 3 (h3)', 'easy-table-of-contents' ),
|
242 |
-
'4' => __( 'Heading 4 (h4)', 'easy-table-of-contents' ),
|
243 |
-
'5' => __( 'Heading 5 (h5)', 'easy-table-of-contents' ),
|
244 |
-
'6' => __( 'Heading 6 (h6)', 'easy-table-of-contents' ),
|
245 |
-
),
|
246 |
-
'default' => array(),
|
247 |
-
),
|
248 |
-
array_map( 'absint', $headings )
|
249 |
-
);
|
250 |
-
?>
|
251 |
-
</td>
|
252 |
-
</tr>
|
253 |
-
<tr>
|
254 |
-
<th scope="row"><?php esc_html_e( 'Alternate Headings', 'easy-table-of-contents' ); ?></th>
|
255 |
-
<td>
|
256 |
-
<?php
|
257 |
-
ezTOC_Option::textarea(
|
258 |
-
array(
|
259 |
-
'id' => 'alttext',
|
260 |
-
'desc' => __( 'Specify alternate table of contents header string. Add the header to be replaced and the alternate header on a single line separated with a pipe <code>|</code>. Put each additional original and alternate header on its own line.', 'easy-table-of-contents' ),
|
261 |
-
'size' => 'large',
|
262 |
-
'default' => '',
|
263 |
-
),
|
264 |
-
$altText
|
265 |
-
);
|
266 |
-
?>
|
267 |
-
</td>
|
268 |
-
</tr>
|
269 |
-
<tr>
|
270 |
-
<th scope="row"></th>
|
271 |
-
<td>
|
272 |
-
<?php
|
273 |
-
ezTOC_Option::descriptive_text(
|
274 |
-
array(
|
275 |
-
'id' => 'alttext-desc',
|
276 |
-
'name' => '',
|
277 |
-
'desc' => '<p><strong>' . esc_html__( 'Examples:', 'easy-table-of-contents' ) . '</strong></p>' .
|
278 |
-
'<ul>' .
|
279 |
-
'<li>' . __( '<code>Level [1.1]|Alternate TOC Header</code> Replaces Level [1.1] in the table of contents with Alternate TOC Header.', 'easy-table-of-contents' ) . '</li>' .
|
280 |
-
'</ul>' .
|
281 |
-
'<p>' . __( '<strong>Note:</strong> This is case sensitive.', 'easy-table-of-contents' ) . '</p>',
|
282 |
-
)
|
283 |
-
);
|
284 |
-
?>
|
285 |
-
</td>
|
286 |
-
</tr>
|
287 |
-
<tr>
|
288 |
-
<th scope="row"><?php esc_html_e( 'Exclude Headings', 'easy-table-of-contents' ); ?></th>
|
289 |
-
<td>
|
290 |
-
<?php
|
291 |
-
ezTOC_Option::text(
|
292 |
-
array(
|
293 |
-
'id' => 'exclude',
|
294 |
-
'desc' => __( 'Specify headings to be excluded from appearing in the table of contents. Separate multiple headings with a pipe <code>|</code>. Use an asterisk <code>*</code> as a wildcard to match other text.', 'easy-table-of-contents' ),
|
295 |
-
'size' => 'large',
|
296 |
-
'default' => '',
|
297 |
-
),
|
298 |
-
$exclude
|
299 |
-
);
|
300 |
-
?>
|
301 |
-
</td>
|
302 |
-
</tr>
|
303 |
-
<tr>
|
304 |
-
<th scope="row"></th>
|
305 |
-
<td>
|
306 |
-
<?php
|
307 |
-
ezTOC_Option::descriptive_text(
|
308 |
-
array(
|
309 |
-
'id' => 'exclude-desc',
|
310 |
-
'name' => '',
|
311 |
-
'desc' => '<p><strong>' . esc_html__( 'Examples:', 'easy-table-of-contents' ) . '</strong></p>' .
|
312 |
-
'<ul>' .
|
313 |
-
'<li>' . __( '<code>Fruit*</code> Ignore headings starting with "Fruit".', 'easy-table-of-contents' ) . '</li>' .
|
314 |
-
'<li>' . __( '<code>*Fruit Diet*</code> Ignore headings with "Fruit Diet" somewhere in the heading.', 'easy-table-of-contents' ) . '</li>' .
|
315 |
-
'<li>' . __( '<code>Apple Tree|Oranges|Yellow Bananas</code> Ignore headings that are exactly "Apple Tree", "Oranges" or "Yellow Bananas".', 'easy-table-of-contents' ) . '</li>' .
|
316 |
-
'</ul>' .
|
317 |
-
'<p>' . __( '<strong>Note:</strong> This is not case sensitive.', 'easy-table-of-contents' ) . '</p>',
|
318 |
-
)
|
319 |
-
);
|
320 |
-
?>
|
321 |
-
</td>
|
322 |
-
</tr>
|
323 |
-
</tbody>
|
324 |
-
</table>
|
325 |
-
|
326 |
-
<?php
|
327 |
-
}
|
328 |
-
|
329 |
-
/**
|
330 |
-
* Callback which saves the user preferences from the table of contents metaboxes.
|
331 |
-
*
|
332 |
-
* @access private
|
333 |
-
* @since 1.0
|
334 |
-
* @static
|
335 |
-
*
|
336 |
-
* @param int $post_id The post ID.
|
337 |
-
* @param object $post The post object.
|
338 |
-
* @param bool $update Whether this is an existing post being updated or not.
|
339 |
-
*/
|
340 |
-
public function save( $post_id, $post, $update ) {
|
341 |
-
|
342 |
-
if ( current_user_can( 'edit_post', $post_id ) &&
|
343 |
-
isset( $_REQUEST['_ez_toc_nonce'] ) &&
|
344 |
-
wp_verify_nonce( $_REQUEST['_ez_toc_nonce'], 'ez_toc_save' )
|
345 |
-
) {
|
346 |
-
|
347 |
-
// Checkboxes are present if checked, absent if not.
|
348 |
-
if ( isset( $_REQUEST['ez-toc-settings']['disabled-toc'] ) ) {
|
349 |
-
|
350 |
-
update_post_meta( $post_id, '_ez-toc-disabled', true );
|
351 |
-
|
352 |
-
} else {
|
353 |
-
|
354 |
-
update_post_meta( $post_id, '_ez-toc-disabled', false );
|
355 |
-
|
356 |
-
}
|
357 |
-
|
358 |
-
if ( isset( $_REQUEST['ez-toc-settings']['insert-toc'] ) ) {
|
359 |
-
|
360 |
-
update_post_meta( $post_id, '_ez-toc-insert', true );
|
361 |
-
|
362 |
-
} else {
|
363 |
-
|
364 |
-
update_post_meta( $post_id, '_ez-toc-insert', false );
|
365 |
-
}
|
366 |
-
|
367 |
-
if ( isset( $_REQUEST['ez-toc-settings']['heading-levels'] ) && ! empty( $_REQUEST['ez-toc-settings']['heading-levels'] ) ) {
|
368 |
-
|
369 |
-
if ( is_array( $_REQUEST['ez-toc-settings']['heading-levels'] ) ) {
|
370 |
-
|
371 |
-
$headings = array_map( 'absint', $_REQUEST['ez-toc-settings']['heading-levels'] );
|
372 |
-
|
373 |
-
} else {
|
374 |
-
|
375 |
-
$headings = array();
|
376 |
-
}
|
377 |
-
|
378 |
-
update_post_meta( $post_id, '_ez-toc-heading-levels', $headings );
|
379 |
-
|
380 |
-
} else {
|
381 |
-
|
382 |
-
update_post_meta( $post_id, '_ez-toc-heading-levels', array() );
|
383 |
-
}
|
384 |
-
|
385 |
-
if ( isset( $_REQUEST['ez-toc-settings']['alttext'] ) && ! empty( $_REQUEST['ez-toc-settings']['alttext'] ) ) {
|
386 |
-
|
387 |
-
if ( is_string( $_REQUEST['ez-toc-settings']['alttext'] ) ) {
|
388 |
-
|
389 |
-
$alttext = trim( $_REQUEST['ez-toc-settings']['alttext'] );
|
390 |
-
|
391 |
-
} else {
|
392 |
-
|
393 |
-
$alttext = '';
|
394 |
-
}
|
395 |
-
|
396 |
-
/*
|
397 |
-
* This is basically `esc_html()` but does not encode quotes.
|
398 |
-
* This is to allow angle brackets and such which `wp_kses_post` would strip as "evil" scripts.
|
399 |
-
*/
|
400 |
-
$alttext = wp_check_invalid_utf8( $alttext );
|
401 |
-
$alttext = _wp_specialchars( $alttext, ENT_NOQUOTES );
|
402 |
-
|
403 |
-
update_post_meta( $post_id, '_ez-toc-alttext', wp_kses_post( $alttext ) );
|
404 |
-
|
405 |
-
} else {
|
406 |
-
|
407 |
-
update_post_meta( $post_id, '_ez-toc-alttext', '' );
|
408 |
-
}
|
409 |
-
|
410 |
-
if ( isset( $_REQUEST['ez-toc-settings']['exclude'] ) && ! empty( $_REQUEST['ez-toc-settings']['exclude'] ) ) {
|
411 |
-
|
412 |
-
if ( is_string( $_REQUEST['ez-toc-settings']['exclude'] ) ) {
|
413 |
-
|
414 |
-
$exclude = trim( $_REQUEST['ez-toc-settings']['exclude'] );
|
415 |
-
|
416 |
-
} else {
|
417 |
-
|
418 |
-
$exclude = '';
|
419 |
-
}
|
420 |
-
|
421 |
-
/*
|
422 |
-
* This is basically `esc_html()` but does not encode quotes.
|
423 |
-
* This is to allow angle brackets and such which `wp_kses_post` would strip as "evil" scripts.
|
424 |
-
*/
|
425 |
-
$exclude = wp_check_invalid_utf8( $exclude );
|
426 |
-
$exclude = _wp_specialchars( $exclude, ENT_NOQUOTES );
|
427 |
-
|
428 |
-
update_post_meta( $post_id, '_ez-toc-exclude', wp_kses_post( $exclude ) );
|
429 |
-
|
430 |
-
} else {
|
431 |
-
|
432 |
-
update_post_meta( $post_id, '_ez-toc-exclude', '' );
|
433 |
-
}
|
434 |
-
|
435 |
-
}
|
436 |
-
|
437 |
-
}
|
438 |
-
|
439 |
-
|
440 |
-
/**
|
441 |
-
* Enqueue Admin js scripts
|
442 |
-
*
|
443 |
-
*/
|
444 |
-
public function load_scripts($pagenow){
|
445 |
-
|
446 |
-
if (isset($pagenow) && $pagenow != 'settings_page_table-of-contents' && strpos($pagenow, 'table-of-contents') == false) {
|
447 |
-
|
448 |
-
return false;
|
449 |
-
}
|
450 |
-
|
451 |
-
wp_enqueue_script( 'eztoc-admin-js', EZ_TOC_URL . 'assets/js/eztoc-admin.js',array('jquery'), ezTOC::VERSION,true );
|
452 |
-
|
453 |
-
$data = array(
|
454 |
-
'ajax_url' => admin_url( 'admin-ajax.php' ),
|
455 |
-
'eztoc_security_nonce' => wp_create_nonce('eztoc_ajax_check_nonce'),
|
456 |
-
);
|
457 |
-
|
458 |
-
$data = apply_filters('eztoc_localize_filter',$data,'eztoc_admin_data');
|
459 |
-
|
460 |
-
wp_localize_script( 'eztoc-admin-js', 'eztoc_admin_data', $data );
|
461 |
-
}
|
462 |
-
|
463 |
-
/**
|
464 |
-
* This is a ajax handler function for sending email from user admin panel to us.
|
465 |
-
* @return type json string
|
466 |
-
*/
|
467 |
-
|
468 |
-
public function eztoc_send_query_message(){
|
469 |
-
|
470 |
-
if ( ! isset( $_POST['eztoc_security_nonce'] ) ){
|
471 |
-
return;
|
472 |
-
}
|
473 |
-
if ( !wp_verify_nonce( $_POST['eztoc_security_nonce'], 'eztoc_ajax_check_nonce' ) ){
|
474 |
-
return;
|
475 |
-
}
|
476 |
-
$message = $this->eztoc_sanitize_textarea_field($_POST['message']);
|
477 |
-
$email = $this->eztoc_sanitize_textarea_field($_POST['email']);
|
478 |
-
|
479 |
-
if(function_exists('wp_get_current_user')){
|
480 |
-
|
481 |
-
$user = wp_get_current_user();
|
482 |
-
|
483 |
-
|
484 |
-
$message = '<p>'.$message.'</p><br><br>'.'Query from Easy Table of Content plugin support tab';
|
485 |
-
|
486 |
-
$user_data = $user->data;
|
487 |
-
$user_email = $user_data->user_email;
|
488 |
-
|
489 |
-
if($email){
|
490 |
-
$user_email = $email;
|
491 |
-
}
|
492 |
-
//php mailer variables
|
493 |
-
$sendto = '
|
494 |
-
$subject = "Easy Table of Content Query";
|
495 |
-
|
496 |
-
$headers[] = 'Content-Type: text/html; charset=UTF-8';
|
497 |
-
$headers[] = 'From: '. esc_attr($user_email);
|
498 |
-
$headers[] = 'Reply-To: ' . esc_attr($user_email);
|
499 |
-
// Load WP components, no themes.
|
500 |
-
|
501 |
-
$sent = wp_mail($sendto, $subject, $message, $headers);
|
502 |
-
|
503 |
-
if($sent){
|
504 |
-
|
505 |
-
echo json_encode(array('status'=>'t'));
|
506 |
-
|
507 |
-
}else{
|
508 |
-
|
509 |
-
echo json_encode(array('status'=>'f'));
|
510 |
-
|
511 |
-
}
|
512 |
-
|
513 |
-
}
|
514 |
-
|
515 |
-
wp_die();
|
516 |
-
}
|
517 |
-
|
518 |
-
public function eztoc_sanitize_textarea_field( $str ) {
|
519 |
-
|
520 |
-
if ( is_object( $str ) || is_array( $str ) ) {
|
521 |
-
return '';
|
522 |
-
}
|
523 |
-
|
524 |
-
$str = (string) $str;
|
525 |
-
|
526 |
-
$filtered = wp_check_invalid_utf8( $str );
|
527 |
-
|
528 |
-
if ( strpos( $filtered, '<' ) !== false ) {
|
529 |
-
$filtered = wp_pre_kses_less_than( $filtered );
|
530 |
-
// This will strip extra whitespace for us.
|
531 |
-
$filtered = wp_strip_all_tags( $filtered, false );
|
532 |
-
|
533 |
-
// Use HTML entities in a special case to make sure no later
|
534 |
-
// newline stripping stage could lead to a functional tag.
|
535 |
-
$filtered = str_replace( "<\n", "<\n", $filtered );
|
536 |
-
}
|
537 |
-
|
538 |
-
$filtered = trim( $filtered );
|
539 |
-
|
540 |
-
$found = false;
|
541 |
-
while ( preg_match( '/%[a-f0-9]{2}/i', $filtered, $match ) ) {
|
542 |
-
$filtered = str_replace( $match[0], '', $filtered );
|
543 |
-
$found = true;
|
544 |
-
}
|
545 |
-
|
546 |
-
if ( $found ) {
|
547 |
-
// Strip out the whitespace that may now exist after removing the octets.
|
548 |
-
$filtered = trim( preg_replace( '/ +/', ' ', $filtered ) );
|
549 |
-
}
|
550 |
-
|
551 |
-
return $filtered;
|
552 |
-
}
|
553 |
-
|
554 |
-
/**
|
555 |
-
* Callback used to render the admin options page.
|
556 |
-
*
|
557 |
-
* @access private
|
558 |
-
* @since 1.0
|
559 |
-
* @static
|
560 |
-
*/
|
561 |
-
public function page() {
|
562 |
-
|
563 |
-
include EZ_TOC_PATH . '/includes/inc.admin-options-page.php';
|
564 |
-
}
|
565 |
-
}
|
566 |
-
|
567 |
-
new ezTOC_Admin();
|
568 |
-
|
569 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// Exit if accessed directly
|
4 |
+
if ( ! defined( 'ABSPATH' ) ) exit;
|
5 |
+
|
6 |
+
if ( ! class_exists( 'ezTOC_Admin' ) ) {
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Class ezTOC_Admin
|
10 |
+
*/
|
11 |
+
final class ezTOC_Admin {
|
12 |
+
|
13 |
+
/**
|
14 |
+
* Setup plugin for admin use.
|
15 |
+
*
|
16 |
+
* @access private
|
17 |
+
* @since 1.0
|
18 |
+
* @static
|
19 |
+
*/
|
20 |
+
public function __construct() {
|
21 |
+
|
22 |
+
$this->hooks();
|
23 |
+
//$this->registerMetaboxes();
|
24 |
+
}
|
25 |
+
|
26 |
+
/**
|
27 |
+
* Add the core admin hooks.
|
28 |
+
*
|
29 |
+
* @access private
|
30 |
+
* @since 1.0
|
31 |
+
* @static
|
32 |
+
*/
|
33 |
+
private function hooks() {
|
34 |
+
|
35 |
+
add_action( 'admin_init', array( $this, 'registerScripts' ) );
|
36 |
+
add_action( 'admin_menu', array( $this, 'menu' ) );
|
37 |
+
add_action( 'init', array( $this, 'registerMetaboxes' ), 99 );
|
38 |
+
add_filter( 'plugin_action_links_' . EZ_TOC_BASE_NAME, array( $this, 'pluginActionLinks' ), 10, 2 );
|
39 |
+
add_action( 'admin_enqueue_scripts', array( $this, 'load_scripts' ) );
|
40 |
+
add_action('wp_ajax_eztoc_send_query_message', array( $this, 'eztoc_send_query_message'));
|
41 |
+
}
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Callback to add the Settings link to the plugin action links.
|
45 |
+
*
|
46 |
+
* @access private
|
47 |
+
* @since 1.0
|
48 |
+
* @static
|
49 |
+
*
|
50 |
+
* @param $links
|
51 |
+
* @param $file
|
52 |
+
*
|
53 |
+
* @return array
|
54 |
+
*/
|
55 |
+
public function pluginActionLinks( $links, $file ) {
|
56 |
+
|
57 |
+
$action = array();
|
58 |
+
|
59 |
+
$action[] = sprintf(
|
60 |
+
'<a href="%1$s">%2$s</a>',
|
61 |
+
esc_url( add_query_arg( 'page', 'table-of-contents', self_admin_url( 'options-general.php' ) ) ),
|
62 |
+
esc_html__( 'Settings', 'easy-table-of-contents' )
|
63 |
+
);
|
64 |
+
|
65 |
+
return array_merge( $action, $links );
|
66 |
+
}
|
67 |
+
|
68 |
+
/**
|
69 |
+
* Register the scripts used in the admin.
|
70 |
+
*
|
71 |
+
* @access private
|
72 |
+
* @since 1.0
|
73 |
+
* @static
|
74 |
+
*/
|
75 |
+
public function registerScripts() {
|
76 |
+
|
77 |
+
wp_register_script( 'cn_toc_admin_script', EZ_TOC_URL . 'assets/js/admin.js', array( 'jquery', 'wp-color-picker' ), ezTOC::VERSION, true );
|
78 |
+
wp_register_style( 'cn_toc_admin_style', EZ_TOC_URL . 'assets/css/admin.css', array( 'wp-color-picker' ), ezTOC::VERSION );
|
79 |
+
}
|
80 |
+
|
81 |
+
/**
|
82 |
+
* Callback to add plugin as a submenu page of the Options page.
|
83 |
+
*
|
84 |
+
* This also adds the action to enqueue the scripts to be loaded on plugin's admin pages only.
|
85 |
+
*
|
86 |
+
* @access private
|
87 |
+
* @since 1.0
|
88 |
+
* @static
|
89 |
+
*/
|
90 |
+
public function menu() {
|
91 |
+
|
92 |
+
$page = add_submenu_page(
|
93 |
+
'options-general.php',
|
94 |
+
esc_html__( 'Table of Contents', 'easy-table-of-contents' ),
|
95 |
+
esc_html__( 'Table of Contents', 'easy-table-of-contents' ),
|
96 |
+
'manage_options',
|
97 |
+
'table-of-contents',
|
98 |
+
array( $this, 'page' )
|
99 |
+
);
|
100 |
+
|
101 |
+
add_action( 'admin_print_styles-' . $page, array( $this, 'enqueueScripts' ) );
|
102 |
+
}
|
103 |
+
|
104 |
+
/**
|
105 |
+
* Enqueue the scripts.
|
106 |
+
*
|
107 |
+
* @access private
|
108 |
+
* @since 1.0
|
109 |
+
* @static
|
110 |
+
*/
|
111 |
+
public function enqueueScripts() {
|
112 |
+
|
113 |
+
wp_enqueue_script( 'cn_toc_admin_script' );
|
114 |
+
wp_enqueue_style( 'cn_toc_admin_style' );
|
115 |
+
}
|
116 |
+
|
117 |
+
/**
|
118 |
+
* Callback to add the action which will register the table of contents post metaboxes.
|
119 |
+
*
|
120 |
+
* Metaboxes will only be registered for the post types per user preferences.
|
121 |
+
*
|
122 |
+
* @access private
|
123 |
+
* @since 1.0
|
124 |
+
* @static
|
125 |
+
*/
|
126 |
+
public function registerMetaboxes() {
|
127 |
+
|
128 |
+
foreach ( get_post_types() as $type ) {
|
129 |
+
|
130 |
+
if ( in_array( $type, ezTOC_Option::get( 'enabled_post_types', array() ) ) ) {
|
131 |
+
|
132 |
+
add_action( "add_meta_boxes_$type", array( $this, 'metabox' ) );
|
133 |
+
add_action( "save_post_$type", array( $this, 'save' ), 10, 3 );
|
134 |
+
}
|
135 |
+
}
|
136 |
+
}
|
137 |
+
|
138 |
+
/**
|
139 |
+
* Callback to register the table of contents metaboxes.
|
140 |
+
*
|
141 |
+
* @access private
|
142 |
+
* @since 1.0
|
143 |
+
* @static
|
144 |
+
*/
|
145 |
+
public function metabox() {
|
146 |
+
|
147 |
+
add_meta_box( 'ez-toc', esc_html__( 'Table of Contents', 'ez-toc' ), array( $this, 'displayMetabox' ) );
|
148 |
+
}
|
149 |
+
|
150 |
+
/**
|
151 |
+
* Callback to render the content of the table of contents metaboxes.
|
152 |
+
*
|
153 |
+
* @access private
|
154 |
+
* @since 1.0
|
155 |
+
* @static
|
156 |
+
*
|
157 |
+
* @param object $post The post object.
|
158 |
+
* @param $atts
|
159 |
+
*/
|
160 |
+
public function displayMetabox( $post, $atts ) {
|
161 |
+
|
162 |
+
// Add an nonce field so we can check for it on save.
|
163 |
+
wp_nonce_field( 'ez_toc_save', '_ez_toc_nonce' );
|
164 |
+
|
165 |
+
$suppress = get_post_meta( $post->ID, '_ez-toc-disabled', true ) == 1 ? true : false;
|
166 |
+
$insert = get_post_meta( $post->ID, '_ez-toc-insert', true ) == 1 ? true : false;
|
167 |
+
$headings = get_post_meta( $post->ID, '_ez-toc-heading-levels', true );
|
168 |
+
$exclude = get_post_meta( $post->ID, '_ez-toc-exclude', true );
|
169 |
+
$altText = get_post_meta( $post->ID, '_ez-toc-alttext', true );
|
170 |
+
|
171 |
+
if ( ! is_array( $headings ) ) {
|
172 |
+
|
173 |
+
$headings = array();
|
174 |
+
}
|
175 |
+
?>
|
176 |
+
|
177 |
+
<table class="form-table">
|
178 |
+
|
179 |
+
<tbody>
|
180 |
+
|
181 |
+
<tr>
|
182 |
+
<th scope="row"></th>
|
183 |
+
<td>
|
184 |
+
|
185 |
+
<?php if ( in_array( get_post_type( $post ), ezTOC_Option::get( 'auto_insert_post_types', array() ) ) ) :
|
186 |
+
|
187 |
+
ezTOC_Option::checkbox(
|
188 |
+
array(
|
189 |
+
'id' => 'disabled-toc',
|
190 |
+
'desc' => esc_html__( 'Disable the automatic insertion of the table of contents.', 'easy-table-of-contents' ),
|
191 |
+
'default' => $suppress,
|
192 |
+
),
|
193 |
+
$suppress
|
194 |
+
);
|
195 |
+
|
196 |
+
elseif( in_array( get_post_type( $post ), ezTOC_Option::get( 'enabled_post_types', array() ) ) ):
|
197 |
+
|
198 |
+
ezTOC_Option::checkbox(
|
199 |
+
array(
|
200 |
+
'id' => 'insert-toc',
|
201 |
+
'desc' => esc_html__( 'Insert table of contents.', 'easy-table-of-contents' ),
|
202 |
+
'default' => $insert,
|
203 |
+
),
|
204 |
+
$insert
|
205 |
+
);
|
206 |
+
|
207 |
+
endif; ?>
|
208 |
+
|
209 |
+
</td>
|
210 |
+
</tr>
|
211 |
+
|
212 |
+
<tr>
|
213 |
+
<th scope="row"><?php esc_html_e( 'Advanced:', 'easy-table-of-contents' ); ?></th>
|
214 |
+
<td>
|
215 |
+
<?php
|
216 |
+
ezTOC_Option::descriptive_text(
|
217 |
+
array(
|
218 |
+
'id' => 'exclude-desc',
|
219 |
+
'name' => '',
|
220 |
+
'desc' => '<p><strong>' . esc_html__( 'NOTE:', 'easy-table-of-contents' ) . '</strong></p>' .
|
221 |
+
'<ul>' .
|
222 |
+
'<li>' . esc_html__( 'Using the advanced options below will override the global advanced settings.', 'easy-table-of-contents' ) . '</li>' .
|
223 |
+
'</ul>',
|
224 |
+
)
|
225 |
+
);
|
226 |
+
?>
|
227 |
+
</td>
|
228 |
+
</tr>
|
229 |
+
|
230 |
+
<tr>
|
231 |
+
<th scope="row"><?php esc_html_e( 'Headings:', 'easy-table-of-contents' ); ?></th>
|
232 |
+
<td>
|
233 |
+
<?php
|
234 |
+
ezTOC_Option::checkboxgroup(
|
235 |
+
array(
|
236 |
+
'id' => 'heading-levels',
|
237 |
+
'desc' => esc_html__( 'Select the heading to consider when generating the table of contents. Deselecting a heading will exclude it.', 'easy-table-of-contents' ),
|
238 |
+
'options' => array(
|
239 |
+
'1' => __( 'Heading 1 (h1)', 'easy-table-of-contents' ),
|
240 |
+
'2' => __( 'Heading 2 (h2)', 'easy-table-of-contents' ),
|
241 |
+
'3' => __( 'Heading 3 (h3)', 'easy-table-of-contents' ),
|
242 |
+
'4' => __( 'Heading 4 (h4)', 'easy-table-of-contents' ),
|
243 |
+
'5' => __( 'Heading 5 (h5)', 'easy-table-of-contents' ),
|
244 |
+
'6' => __( 'Heading 6 (h6)', 'easy-table-of-contents' ),
|
245 |
+
),
|
246 |
+
'default' => array(),
|
247 |
+
),
|
248 |
+
array_map( 'absint', $headings )
|
249 |
+
);
|
250 |
+
?>
|
251 |
+
</td>
|
252 |
+
</tr>
|
253 |
+
<tr>
|
254 |
+
<th scope="row"><?php esc_html_e( 'Alternate Headings', 'easy-table-of-contents' ); ?></th>
|
255 |
+
<td>
|
256 |
+
<?php
|
257 |
+
ezTOC_Option::textarea(
|
258 |
+
array(
|
259 |
+
'id' => 'alttext',
|
260 |
+
'desc' => __( 'Specify alternate table of contents header string. Add the header to be replaced and the alternate header on a single line separated with a pipe <code>|</code>. Put each additional original and alternate header on its own line.', 'easy-table-of-contents' ),
|
261 |
+
'size' => 'large',
|
262 |
+
'default' => '',
|
263 |
+
),
|
264 |
+
$altText
|
265 |
+
);
|
266 |
+
?>
|
267 |
+
</td>
|
268 |
+
</tr>
|
269 |
+
<tr>
|
270 |
+
<th scope="row"></th>
|
271 |
+
<td>
|
272 |
+
<?php
|
273 |
+
ezTOC_Option::descriptive_text(
|
274 |
+
array(
|
275 |
+
'id' => 'alttext-desc',
|
276 |
+
'name' => '',
|
277 |
+
'desc' => '<p><strong>' . esc_html__( 'Examples:', 'easy-table-of-contents' ) . '</strong></p>' .
|
278 |
+
'<ul>' .
|
279 |
+
'<li>' . __( '<code>Level [1.1]|Alternate TOC Header</code> Replaces Level [1.1] in the table of contents with Alternate TOC Header.', 'easy-table-of-contents' ) . '</li>' .
|
280 |
+
'</ul>' .
|
281 |
+
'<p>' . __( '<strong>Note:</strong> This is case sensitive.', 'easy-table-of-contents' ) . '</p>',
|
282 |
+
)
|
283 |
+
);
|
284 |
+
?>
|
285 |
+
</td>
|
286 |
+
</tr>
|
287 |
+
<tr>
|
288 |
+
<th scope="row"><?php esc_html_e( 'Exclude Headings', 'easy-table-of-contents' ); ?></th>
|
289 |
+
<td>
|
290 |
+
<?php
|
291 |
+
ezTOC_Option::text(
|
292 |
+
array(
|
293 |
+
'id' => 'exclude',
|
294 |
+
'desc' => __( 'Specify headings to be excluded from appearing in the table of contents. Separate multiple headings with a pipe <code>|</code>. Use an asterisk <code>*</code> as a wildcard to match other text.', 'easy-table-of-contents' ),
|
295 |
+
'size' => 'large',
|
296 |
+
'default' => '',
|
297 |
+
),
|
298 |
+
$exclude
|
299 |
+
);
|
300 |
+
?>
|
301 |
+
</td>
|
302 |
+
</tr>
|
303 |
+
<tr>
|
304 |
+
<th scope="row"></th>
|
305 |
+
<td>
|
306 |
+
<?php
|
307 |
+
ezTOC_Option::descriptive_text(
|
308 |
+
array(
|
309 |
+
'id' => 'exclude-desc',
|
310 |
+
'name' => '',
|
311 |
+
'desc' => '<p><strong>' . esc_html__( 'Examples:', 'easy-table-of-contents' ) . '</strong></p>' .
|
312 |
+
'<ul>' .
|
313 |
+
'<li>' . __( '<code>Fruit*</code> Ignore headings starting with "Fruit".', 'easy-table-of-contents' ) . '</li>' .
|
314 |
+
'<li>' . __( '<code>*Fruit Diet*</code> Ignore headings with "Fruit Diet" somewhere in the heading.', 'easy-table-of-contents' ) . '</li>' .
|
315 |
+
'<li>' . __( '<code>Apple Tree|Oranges|Yellow Bananas</code> Ignore headings that are exactly "Apple Tree", "Oranges" or "Yellow Bananas".', 'easy-table-of-contents' ) . '</li>' .
|
316 |
+
'</ul>' .
|
317 |
+
'<p>' . __( '<strong>Note:</strong> This is not case sensitive.', 'easy-table-of-contents' ) . '</p>',
|
318 |
+
)
|
319 |
+
);
|
320 |
+
?>
|
321 |
+
</td>
|
322 |
+
</tr>
|
323 |
+
</tbody>
|
324 |
+
</table>
|
325 |
+
|
326 |
+
<?php
|
327 |
+
}
|
328 |
+
|
329 |
+
/**
|
330 |
+
* Callback which saves the user preferences from the table of contents metaboxes.
|
331 |
+
*
|
332 |
+
* @access private
|
333 |
+
* @since 1.0
|
334 |
+
* @static
|
335 |
+
*
|
336 |
+
* @param int $post_id The post ID.
|
337 |
+
* @param object $post The post object.
|
338 |
+
* @param bool $update Whether this is an existing post being updated or not.
|
339 |
+
*/
|
340 |
+
public function save( $post_id, $post, $update ) {
|
341 |
+
|
342 |
+
if ( current_user_can( 'edit_post', $post_id ) &&
|
343 |
+
isset( $_REQUEST['_ez_toc_nonce'] ) &&
|
344 |
+
wp_verify_nonce( $_REQUEST['_ez_toc_nonce'], 'ez_toc_save' )
|
345 |
+
) {
|
346 |
+
|
347 |
+
// Checkboxes are present if checked, absent if not.
|
348 |
+
if ( isset( $_REQUEST['ez-toc-settings']['disabled-toc'] ) ) {
|
349 |
+
|
350 |
+
update_post_meta( $post_id, '_ez-toc-disabled', true );
|
351 |
+
|
352 |
+
} else {
|
353 |
+
|
354 |
+
update_post_meta( $post_id, '_ez-toc-disabled', false );
|
355 |
+
|
356 |
+
}
|
357 |
+
|
358 |
+
if ( isset( $_REQUEST['ez-toc-settings']['insert-toc'] ) ) {
|
359 |
+
|
360 |
+
update_post_meta( $post_id, '_ez-toc-insert', true );
|
361 |
+
|
362 |
+
} else {
|
363 |
+
|
364 |
+
update_post_meta( $post_id, '_ez-toc-insert', false );
|
365 |
+
}
|
366 |
+
|
367 |
+
if ( isset( $_REQUEST['ez-toc-settings']['heading-levels'] ) && ! empty( $_REQUEST['ez-toc-settings']['heading-levels'] ) ) {
|
368 |
+
|
369 |
+
if ( is_array( $_REQUEST['ez-toc-settings']['heading-levels'] ) ) {
|
370 |
+
|
371 |
+
$headings = array_map( 'absint', $_REQUEST['ez-toc-settings']['heading-levels'] );
|
372 |
+
|
373 |
+
} else {
|
374 |
+
|
375 |
+
$headings = array();
|
376 |
+
}
|
377 |
+
|
378 |
+
update_post_meta( $post_id, '_ez-toc-heading-levels', $headings );
|
379 |
+
|
380 |
+
} else {
|
381 |
+
|
382 |
+
update_post_meta( $post_id, '_ez-toc-heading-levels', array() );
|
383 |
+
}
|
384 |
+
|
385 |
+
if ( isset( $_REQUEST['ez-toc-settings']['alttext'] ) && ! empty( $_REQUEST['ez-toc-settings']['alttext'] ) ) {
|
386 |
+
|
387 |
+
if ( is_string( $_REQUEST['ez-toc-settings']['alttext'] ) ) {
|
388 |
+
|
389 |
+
$alttext = trim( $_REQUEST['ez-toc-settings']['alttext'] );
|
390 |
+
|
391 |
+
} else {
|
392 |
+
|
393 |
+
$alttext = '';
|
394 |
+
}
|
395 |
+
|
396 |
+
/*
|
397 |
+
* This is basically `esc_html()` but does not encode quotes.
|
398 |
+
* This is to allow angle brackets and such which `wp_kses_post` would strip as "evil" scripts.
|
399 |
+
*/
|
400 |
+
$alttext = wp_check_invalid_utf8( $alttext );
|
401 |
+
$alttext = _wp_specialchars( $alttext, ENT_NOQUOTES );
|
402 |
+
|
403 |
+
update_post_meta( $post_id, '_ez-toc-alttext', wp_kses_post( $alttext ) );
|
404 |
+
|
405 |
+
} else {
|
406 |
+
|
407 |
+
update_post_meta( $post_id, '_ez-toc-alttext', '' );
|
408 |
+
}
|
409 |
+
|
410 |
+
if ( isset( $_REQUEST['ez-toc-settings']['exclude'] ) && ! empty( $_REQUEST['ez-toc-settings']['exclude'] ) ) {
|
411 |
+
|
412 |
+
if ( is_string( $_REQUEST['ez-toc-settings']['exclude'] ) ) {
|
413 |
+
|
414 |
+
$exclude = trim( $_REQUEST['ez-toc-settings']['exclude'] );
|
415 |
+
|
416 |
+
} else {
|
417 |
+
|
418 |
+
$exclude = '';
|
419 |
+
}
|
420 |
+
|
421 |
+
/*
|
422 |
+
* This is basically `esc_html()` but does not encode quotes.
|
423 |
+
* This is to allow angle brackets and such which `wp_kses_post` would strip as "evil" scripts.
|
424 |
+
*/
|
425 |
+
$exclude = wp_check_invalid_utf8( $exclude );
|
426 |
+
$exclude = _wp_specialchars( $exclude, ENT_NOQUOTES );
|
427 |
+
|
428 |
+
update_post_meta( $post_id, '_ez-toc-exclude', wp_kses_post( $exclude ) );
|
429 |
+
|
430 |
+
} else {
|
431 |
+
|
432 |
+
update_post_meta( $post_id, '_ez-toc-exclude', '' );
|
433 |
+
}
|
434 |
+
|
435 |
+
}
|
436 |
+
|
437 |
+
}
|
438 |
+
|
439 |
+
|
440 |
+
/**
|
441 |
+
* Enqueue Admin js scripts
|
442 |
+
*
|
443 |
+
*/
|
444 |
+
public function load_scripts($pagenow){
|
445 |
+
|
446 |
+
if (isset($pagenow) && $pagenow != 'settings_page_table-of-contents' && strpos($pagenow, 'table-of-contents') == false) {
|
447 |
+
|
448 |
+
return false;
|
449 |
+
}
|
450 |
+
|
451 |
+
wp_enqueue_script( 'eztoc-admin-js', EZ_TOC_URL . 'assets/js/eztoc-admin.js',array('jquery'), ezTOC::VERSION,true );
|
452 |
+
|
453 |
+
$data = array(
|
454 |
+
'ajax_url' => admin_url( 'admin-ajax.php' ),
|
455 |
+
'eztoc_security_nonce' => wp_create_nonce('eztoc_ajax_check_nonce'),
|
456 |
+
);
|
457 |
+
|
458 |
+
$data = apply_filters('eztoc_localize_filter',$data,'eztoc_admin_data');
|
459 |
+
|
460 |
+
wp_localize_script( 'eztoc-admin-js', 'eztoc_admin_data', $data );
|
461 |
+
}
|
462 |
+
|
463 |
+
/**
|
464 |
+
* This is a ajax handler function for sending email from user admin panel to us.
|
465 |
+
* @return type json string
|
466 |
+
*/
|
467 |
+
|
468 |
+
public function eztoc_send_query_message(){
|
469 |
+
|
470 |
+
if ( ! isset( $_POST['eztoc_security_nonce'] ) ){
|
471 |
+
return;
|
472 |
+
}
|
473 |
+
if ( !wp_verify_nonce( $_POST['eztoc_security_nonce'], 'eztoc_ajax_check_nonce' ) ){
|
474 |
+
return;
|
475 |
+
}
|
476 |
+
$message = $this->eztoc_sanitize_textarea_field($_POST['message']);
|
477 |
+
$email = $this->eztoc_sanitize_textarea_field($_POST['email']);
|
478 |
+
|
479 |
+
if(function_exists('wp_get_current_user')){
|
480 |
+
|
481 |
+
$user = wp_get_current_user();
|
482 |
+
|
483 |
+
|
484 |
+
$message = '<p>'.$message.'</p><br><br>'.'Query from Easy Table of Content plugin support tab';
|
485 |
+
|
486 |
+
$user_data = $user->data;
|
487 |
+
$user_email = $user_data->user_email;
|
488 |
+
|
489 |
+
if($email){
|
490 |
+
$user_email = $email;
|
491 |
+
}
|
492 |
+
//php mailer variables
|
493 |
+
$sendto = 'team@magazine3.in';
|
494 |
+
$subject = "Easy Table of Content Query";
|
495 |
+
|
496 |
+
$headers[] = 'Content-Type: text/html; charset=UTF-8';
|
497 |
+
$headers[] = 'From: '. esc_attr($user_email);
|
498 |
+
$headers[] = 'Reply-To: ' . esc_attr($user_email);
|
499 |
+
// Load WP components, no themes.
|
500 |
+
|
501 |
+
$sent = wp_mail($sendto, $subject, $message, $headers);
|
502 |
+
|
503 |
+
if($sent){
|
504 |
+
|
505 |
+
echo json_encode(array('status'=>'t'));
|
506 |
+
|
507 |
+
}else{
|
508 |
+
|
509 |
+
echo json_encode(array('status'=>'f'));
|
510 |
+
|
511 |
+
}
|
512 |
+
|
513 |
+
}
|
514 |
+
|
515 |
+
wp_die();
|
516 |
+
}
|
517 |
+
|
518 |
+
public function eztoc_sanitize_textarea_field( $str ) {
|
519 |
+
|
520 |
+
if ( is_object( $str ) || is_array( $str ) ) {
|
521 |
+
return '';
|
522 |
+
}
|
523 |
+
|
524 |
+
$str = (string) $str;
|
525 |
+
|
526 |
+
$filtered = wp_check_invalid_utf8( $str );
|
527 |
+
|
528 |
+
if ( strpos( $filtered, '<' ) !== false ) {
|
529 |
+
$filtered = wp_pre_kses_less_than( $filtered );
|
530 |
+
// This will strip extra whitespace for us.
|
531 |
+
$filtered = wp_strip_all_tags( $filtered, false );
|
532 |
+
|
533 |
+
// Use HTML entities in a special case to make sure no later
|
534 |
+
// newline stripping stage could lead to a functional tag.
|
535 |
+
$filtered = str_replace( "<\n", "<\n", $filtered );
|
536 |
+
}
|
537 |
+
|
538 |
+
$filtered = trim( $filtered );
|
539 |
+
|
540 |
+
$found = false;
|
541 |
+
while ( preg_match( '/%[a-f0-9]{2}/i', $filtered, $match ) ) {
|
542 |
+
$filtered = str_replace( $match[0], '', $filtered );
|
543 |
+
$found = true;
|
544 |
+
}
|
545 |
+
|
546 |
+
if ( $found ) {
|
547 |
+
// Strip out the whitespace that may now exist after removing the octets.
|
548 |
+
$filtered = trim( preg_replace( '/ +/', ' ', $filtered ) );
|
549 |
+
}
|
550 |
+
|
551 |
+
return $filtered;
|
552 |
+
}
|
553 |
+
|
554 |
+
/**
|
555 |
+
* Callback used to render the admin options page.
|
556 |
+
*
|
557 |
+
* @access private
|
558 |
+
* @since 1.0
|
559 |
+
* @static
|
560 |
+
*/
|
561 |
+
public function page() {
|
562 |
+
|
563 |
+
include EZ_TOC_PATH . '/includes/inc.admin-options-page.php';
|
564 |
+
}
|
565 |
+
}
|
566 |
+
|
567 |
+
new ezTOC_Admin();
|
568 |
+
|
569 |
+
}
|
includes/class.options.php
CHANGED
@@ -1,1281 +1,1294 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
// Exit if accessed directly
|
4 |
-
if ( ! defined( 'ABSPATH' ) ) exit;
|
5 |
-
|
6 |
-
if ( ! class_exists( 'ezTOC_Option' ) ) {
|
7 |
-
|
8 |
-
/**
|
9 |
-
* Class ezTOC_Option
|
10 |
-
*
|
11 |
-
* Credit: Adapted from Easy Digital Downloads.
|
12 |
-
*/
|
13 |
-
final class ezTOC_Option {
|
14 |
-
|
15 |
-
/**
|
16 |
-
* Register the plugins core settings and options.
|
17 |
-
*
|
18 |
-
* @access private
|
19 |
-
* @since 1.0
|
20 |
-
* @static
|
21 |
-
*/
|
22 |
-
public static function register() {
|
23 |
-
|
24 |
-
if ( false === get_option( 'ez-toc-settings' ) ) {
|
25 |
-
|
26 |
-
add_option( 'ez-toc-settings', self::getDefaults() );
|
27 |
-
}
|
28 |
-
|
29 |
-
foreach ( self::getRegistered() as $section => $settings ) {
|
30 |
-
|
31 |
-
add_settings_section(
|
32 |
-
'ez_toc_settings_' . $section,
|
33 |
-
__return_null(),
|
34 |
-
'__return_false',
|
35 |
-
'ez_toc_settings_' . $section
|
36 |
-
);
|
37 |
-
|
38 |
-
foreach ( $settings as $option ) {
|
39 |
-
|
40 |
-
$name = isset( $option['name'] ) ? $option['name'] : '';
|
41 |
-
|
42 |
-
add_settings_field(
|
43 |
-
'ez-toc-settings[' . $option['id'] . ']',
|
44 |
-
$name,
|
45 |
-
method_exists( __CLASS__, $option['type'] ) ? array( __CLASS__, $option['type'] ) : array( __CLASS__, 'missingCallback' ),
|
46 |
-
'ez_toc_settings_' . $section,
|
47 |
-
'ez_toc_settings_' . $section,
|
48 |
-
array(
|
49 |
-
'section' => $section,
|
50 |
-
'id' => isset( $option['id'] ) ? $option['id'] : null,
|
51 |
-
'desc' => ! empty( $option['desc'] ) ? $option['desc'] : '',
|
52 |
-
'name' => isset( $option['name'] ) ? $option['name'] : null,
|
53 |
-
'size' => isset( $option['size'] ) ? $option['size'] : null,
|
54 |
-
'options' => isset( $option['options'] ) ? $option['options'] : '',
|
55 |
-
'default' => isset( $option['default'] ) ? $option['default'] : '',
|
56 |
-
'min' => isset( $option['min'] ) ? $option['min'] : null,
|
57 |
-
'max' => isset( $option['max'] ) ? $option['max'] : null,
|
58 |
-
'step' => isset( $option['step'] ) ? $option['step'] : null,
|
59 |
-
'chosen' => isset( $option['chosen'] ) ? $option['chosen'] : null,
|
60 |
-
'placeholder' => isset( $option['placeholder'] ) ? $option['placeholder'] : null,
|
61 |
-
'allow_blank' => isset( $option['allow_blank'] ) ? $option['allow_blank'] : true,
|
62 |
-
'readonly' => isset( $option['readonly'] ) ? $option['readonly'] : false,
|
63 |
-
'faux' => isset( $option['faux'] ) ? $option['faux'] : false,
|
64 |
-
)
|
65 |
-
);
|
66 |
-
}
|
67 |
-
|
68 |
-
}
|
69 |
-
|
70 |
-
// Creates our settings in the options table
|
71 |
-
register_setting( 'ez-toc-settings', 'ez-toc-settings', array( __CLASS__, 'sanitize' ) );
|
72 |
-
}
|
73 |
-
|
74 |
-
/**
|
75 |
-
* Callback for settings sanitization.
|
76 |
-
*
|
77 |
-
* @access private
|
78 |
-
* @since 1.0
|
79 |
-
* @static
|
80 |
-
*
|
81 |
-
* @param array $input The value inputted in the field.
|
82 |
-
*
|
83 |
-
* @return string $input Sanitized value.
|
84 |
-
*/
|
85 |
-
public static function sanitize( $input = array() ) {
|
86 |
-
|
87 |
-
$options = self::getOptions();
|
88 |
-
|
89 |
-
if ( empty( $_POST['_wp_http_referer'] ) ) {
|
90 |
-
|
91 |
-
return $input;
|
92 |
-
}
|
93 |
-
|
94 |
-
$registered = self::getRegistered();
|
95 |
-
|
96 |
-
foreach ( $registered as $sectionID => $sectionOptions ) {
|
97 |
-
|
98 |
-
$input = $input ? $input : array();
|
99 |
-
$input = apply_filters( 'ez_toc_settings_' . $sectionID . '_sanitize', $input );
|
100 |
-
|
101 |
-
// Loop through each setting being saved and pass it through a sanitization filter
|
102 |
-
foreach ( $input as $key => $value ) {
|
103 |
-
|
104 |
-
// Get the setting type (checkbox, select, etc)
|
105 |
-
$type = isset( $registered[ $sectionID ][ $key ]['type'] ) ? $registered[ $sectionID ][ $key ]['type'] : false;
|
106 |
-
|
107 |
-
if ( $type ) {
|
108 |
-
|
109 |
-
// Field type specific filter
|
110 |
-
$input[ $key ] = apply_filters( 'ez_toc_settings_sanitize_' . $type, $value, $key );
|
111 |
-
}
|
112 |
-
|
113 |
-
// General filter
|
114 |
-
$input[ $key ] = apply_filters( 'ez_toc_settings_sanitize', $input[ $key ], $key );
|
115 |
-
}
|
116 |
-
|
117 |
-
// Loop through the registered options.
|
118 |
-
foreach ( $sectionOptions as $optionID => $optionProperties ) {
|
119 |
-
|
120 |
-
// Unset any that are empty for the section being saved.
|
121 |
-
if ( empty( $input[ $optionID ] ) ) {
|
122 |
-
|
123 |
-
unset( $options[ $optionID ] );
|
124 |
-
}
|
125 |
-
|
126 |
-
// Check for the checkbox option type.
|
127 |
-
if ( array_key_exists( 'type', $optionProperties ) && 'checkbox' == $optionProperties['type'] ) {
|
128 |
-
|
129 |
-
// If it does not exist in the options values being saved, add the option ID and set its value to `0`.
|
130 |
-
// This matches WP core behavior for saving checkbox option values.
|
131 |
-
if ( ! array_key_exists( $optionID, $input ) ) {
|
132 |
-
|
133 |
-
$input[ $optionID ] = '0';
|
134 |
-
}
|
135 |
-
}
|
136 |
-
}
|
137 |
-
|
138 |
-
}
|
139 |
-
|
140 |
-
// Merge our new settings with the existing
|
141 |
-
$output = array_merge( $options, $input );
|
142 |
-
|
143 |
-
return $output;
|
144 |
-
}
|
145 |
-
|
146 |
-
/**
|
147 |
-
* The core registered settings and options.
|
148 |
-
*
|
149 |
-
* @access private
|
150 |
-
* @since 1.0
|
151 |
-
* @static
|
152 |
-
*
|
153 |
-
* @return array
|
154 |
-
*/
|
155 |
-
private static function getRegistered() {
|
156 |
-
|
157 |
-
$options = array(
|
158 |
-
'general' => apply_filters(
|
159 |
-
'ez_toc_settings_general',
|
160 |
-
array(
|
161 |
-
'enabled_post_types' => array(
|
162 |
-
'id' => 'enabled_post_types',
|
163 |
-
'name' => __( 'Enable Support', 'easy-table-of-contents' ),
|
164 |
-
'desc' => __( 'Select the post types to enable the support for table of contents.', 'easy-table-of-contents' ),
|
165 |
-
'type' => 'checkboxgroup',
|
166 |
-
'options' => self::getPostTypes(),
|
167 |
-
'default' => array(),
|
168 |
-
),
|
169 |
-
'auto_insert_post_types' => array(
|
170 |
-
'id' => 'auto_insert_post_types',
|
171 |
-
'name' => __( 'Auto Insert', 'easy-table-of-contents' ),
|
172 |
-
'desc' => __( 'Select the post types which will have the table of contents automatically inserted.', 'easy-table-of-contents' ) .
|
173 |
-
'<br><span class="description">' . __( 'NOTE: The table of contents will only be automatically inserted on post types for which it has been enabled.', 'easy-table-of-contents' ) . '<span>',
|
174 |
-
'type' => 'checkboxgroup',
|
175 |
-
'options' => self::getPostTypes(),
|
176 |
-
'default' => array(),
|
177 |
-
),
|
178 |
-
'position' => array(
|
179 |
-
'id' => 'position',
|
180 |
-
'name' => __( 'Position', 'easy-table-of-contents' ),
|
181 |
-
'desc' => __( 'Choose where where you want to display the table of contents.', 'easy-table-of-contents' ),
|
182 |
-
'type' => 'select',
|
183 |
-
'options' => array(
|
184 |
-
'before' => __( 'Before first heading (default)', 'easy-table-of-contents' ),
|
185 |
-
'after' => __( 'After first heading', 'easy-table-of-contents' ),
|
186 |
-
'top' => __( 'Top', 'easy-table-of-contents' ),
|
187 |
-
'bottom' => __( 'Bottom', 'easy-table-of-contents' ),
|
188 |
-
//'placeholder' => __( 'Replace [toc] placeholder. For backwards compatibility with Table of Content Plus.', 'easy-table-of-contents' ),
|
189 |
-
),
|
190 |
-
'default' => 1,
|
191 |
-
),
|
192 |
-
'start' => array(
|
193 |
-
'id' => 'start',
|
194 |
-
'name' => __( 'Show when', 'easy-table-of-contents' ),
|
195 |
-
'desc' => __( 'or more headings are present', 'easy-table-of-contents' ),
|
196 |
-
'type' => 'select',
|
197 |
-
'options' => array_combine( range( 1, 10 ), range( 1, 10 ) ),
|
198 |
-
'default' => 4,
|
199 |
-
),
|
200 |
-
'show_heading_text' => array(
|
201 |
-
'id' => 'show_heading_text',
|
202 |
-
'name' => __( 'Display Header Label', 'easy-table-of-contents' ),
|
203 |
-
'desc' => __( 'Show header text above the table of contents.', 'easy-table-of-contents' ),
|
204 |
-
'type' => 'checkbox',
|
205 |
-
'default' => true,
|
206 |
-
),
|
207 |
-
'heading_text' => array(
|
208 |
-
'id' => 'heading_text',
|
209 |
-
'name' => __( 'Header Label', 'easy-table-of-contents' ),
|
210 |
-
'desc' => __( 'Eg: Contents, Table of Contents, Page Contents', 'easy-table-of-contents' ),
|
211 |
-
'type' => 'text',
|
212 |
-
'default' => __( 'Contents', 'easy-table-of-contents' ),
|
213 |
-
),
|
214 |
-
'visibility' => array(
|
215 |
-
'id' => 'visibility',
|
216 |
-
'name' => __( 'Toggle View', 'easy-table-of-contents' ),
|
217 |
-
'desc' => __( 'Allow the user to toggle the visibility of the table of contents.', 'easy-table-of-contents' ),
|
218 |
-
'type' => 'checkbox',
|
219 |
-
'default' => true,
|
220 |
-
),
|
221 |
-
//'visibility_show' => array(
|
222 |
-
// 'id' => 'visibility_show',
|
223 |
-
// 'name' => __( 'Show Label', 'easy-table-of-contents' ),
|
224 |
-
// 'desc' => __( 'Eg: show', 'easy-table-of-contents' ),
|
225 |
-
// 'type' => 'text',
|
226 |
-
// 'default' => __( 'show', 'easy-table-of-contents' ),
|
227 |
-
//),
|
228 |
-
//'visibility_hide' => array(
|
229 |
-
// 'id' => 'visibility_hide',
|
230 |
-
// 'name' => __( 'Hide Label', 'easy-table-of-contents' ),
|
231 |
-
// 'desc' => __( 'Eg: hide', 'easy-table-of-contents' ),
|
232 |
-
// 'type' => 'text',
|
233 |
-
// 'default' => __( 'hide', 'easy-table-of-contents' ),
|
234 |
-
//),
|
235 |
-
'visibility_hide_by_default' => array(
|
236 |
-
'id' => 'visibility_hide_by_default',
|
237 |
-
'name' => __( 'Initial View', 'easy-table-of-contents' ),
|
238 |
-
'desc' => __( 'Initially hide the table of contents.', 'easy-table-of-contents' ),
|
239 |
-
'type' => 'checkbox',
|
240 |
-
'default' => false,
|
241 |
-
),
|
242 |
-
'show_hierarchy' => array(
|
243 |
-
'id' => 'show_hierarchy',
|
244 |
-
'name' => __( 'Show as Hierarchy', 'easy-table-of-contents' ),
|
245 |
-
'desc' => '',
|
246 |
-
'type' => 'checkbox',
|
247 |
-
'default' => true,
|
248 |
-
),
|
249 |
-
'counter' => array(
|
250 |
-
'id' => 'counter',
|
251 |
-
'name' => __( 'Counter', 'easy-table-of-contents' ),
|
252 |
-
'desc' => '',
|
253 |
-
'type' => 'select',
|
254 |
-
'options' => array(
|
255 |
-
'decimal' => __( 'Decimal (default)', 'easy-table-of-contents' ),
|
256 |
-
'numeric' => __( 'Numeric', 'easy-table-of-contents' ),
|
257 |
-
'roman' => __( 'Roman', 'easy-table-of-contents' ),
|
258 |
-
'none' => __( 'None', 'easy-table-of-contents' ),
|
259 |
-
),
|
260 |
-
'default' => 'decimal',
|
261 |
-
),
|
262 |
-
'smooth_scroll' => array(
|
263 |
-
'id' => 'smooth_scroll',
|
264 |
-
'name' => __( 'Smooth Scroll', 'easy-table-of-contents' ),
|
265 |
-
'desc' => '',
|
266 |
-
'type' => 'checkbox',
|
267 |
-
'default' => true,
|
268 |
-
),
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
'
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
'
|
298 |
-
'
|
299 |
-
'
|
300 |
-
'
|
301 |
-
'
|
302 |
-
'
|
303 |
-
'
|
304 |
-
),
|
305 |
-
),
|
306 |
-
'
|
307 |
-
'name' => __( '
|
308 |
-
'options' => array(
|
309 |
-
'
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
'
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
'default' =>
|
333 |
-
),
|
334 |
-
'
|
335 |
-
'id' => '
|
336 |
-
'name' => __( '
|
337 |
-
'desc' => '',
|
338 |
-
'type' => '
|
339 |
-
'
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
'
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
'
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
'
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
'
|
380 |
-
|
381 |
-
|
382 |
-
'
|
383 |
-
'
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
'
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
'
|
396 |
-
'
|
397 |
-
'
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
'
|
403 |
-
'
|
404 |
-
'
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
'
|
410 |
-
'
|
411 |
-
'
|
412 |
-
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
'
|
417 |
-
'
|
418 |
-
'
|
419 |
-
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
'
|
424 |
-
'
|
425 |
-
'
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
'
|
435 |
-
'id' => '
|
436 |
-
'name' => __( '
|
437 |
-
'desc' =>
|
438 |
-
'type' => '
|
439 |
-
'default' =>
|
440 |
-
),
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
|
448 |
-
|
449 |
-
'
|
450 |
-
'
|
451 |
-
'
|
452 |
-
|
453 |
-
|
454 |
-
|
455 |
-
|
456 |
-
'
|
457 |
-
'
|
458 |
-
'
|
459 |
-
|
460 |
-
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
|
470 |
-
'
|
471 |
-
'
|
472 |
-
'
|
473 |
-
|
474 |
-
|
475 |
-
|
476 |
-
|
477 |
-
|
478 |
-
|
479 |
-
|
480 |
-
|
481 |
-
|
482 |
-
'
|
483 |
-
|
484 |
-
|
485 |
-
'
|
486 |
-
'
|
487 |
-
|
488 |
-
|
489 |
-
|
490 |
-
|
491 |
-
|
492 |
-
|
493 |
-
|
494 |
-
'
|
495 |
-
|
496 |
-
|
497 |
-
|
498 |
-
|
499 |
-
|
500 |
-
|
501 |
-
|
502 |
-
'
|
503 |
-
),
|
504 |
-
'
|
505 |
-
'id' => '
|
506 |
-
'name' =>
|
507 |
-
'desc' => '
|
508 |
-
|
509 |
-
|
510 |
-
|
511 |
-
|
512 |
-
|
513 |
-
|
514 |
-
'
|
515 |
-
|
516 |
-
|
517 |
-
'
|
518 |
-
'
|
519 |
-
|
520 |
-
|
521 |
-
'
|
522 |
-
'
|
523 |
-
|
524 |
-
|
525 |
-
'
|
526 |
-
|
527 |
-
|
528 |
-
'
|
529 |
-
'
|
530 |
-
'
|
531 |
-
|
532 |
-
|
533 |
-
'
|
534 |
-
'
|
535 |
-
|
536 |
-
|
537 |
-
'
|
538 |
-
|
539 |
-
|
540 |
-
|
541 |
-
|
542 |
-
'
|
543 |
-
|
544 |
-
|
545 |
-
|
546 |
-
|
547 |
-
|
548 |
-
|
549 |
-
|
550 |
-
|
551 |
-
|
552 |
-
|
553 |
-
|
554 |
-
|
555 |
-
|
556 |
-
|
557 |
-
|
558 |
-
|
559 |
-
|
560 |
-
|
561 |
-
|
562 |
-
|
563 |
-
|
564 |
-
|
565 |
-
|
566 |
-
|
567 |
-
|
568 |
-
|
569 |
-
|
570 |
-
|
571 |
-
|
572 |
-
|
573 |
-
|
574 |
-
|
575 |
-
|
576 |
-
'
|
577 |
-
|
578 |
-
|
579 |
-
'
|
580 |
-
'
|
581 |
-
'
|
582 |
-
'
|
583 |
-
'
|
584 |
-
'
|
585 |
-
'
|
586 |
-
'
|
587 |
-
'
|
588 |
-
'
|
589 |
-
'
|
590 |
-
'
|
591 |
-
'
|
592 |
-
'
|
593 |
-
'
|
594 |
-
'
|
595 |
-
'
|
596 |
-
'
|
597 |
-
'
|
598 |
-
|
599 |
-
'
|
600 |
-
'
|
601 |
-
'
|
602 |
-
'
|
603 |
-
'
|
604 |
-
'
|
605 |
-
|
606 |
-
|
607 |
-
'
|
608 |
-
|
609 |
-
|
610 |
-
|
611 |
-
|
612 |
-
|
613 |
-
|
614 |
-
|
615 |
-
|
616 |
-
|
617 |
-
|
618 |
-
|
619 |
-
|
620 |
-
|
621 |
-
|
622 |
-
|
623 |
-
|
624 |
-
|
625 |
-
|
626 |
-
|
627 |
-
|
628 |
-
|
629 |
-
|
630 |
-
|
631 |
-
|
632 |
-
*
|
633 |
-
*
|
634 |
-
|
635 |
-
|
636 |
-
|
637 |
-
|
638 |
-
|
639 |
-
|
640 |
-
|
641 |
-
|
642 |
-
|
643 |
-
|
644 |
-
|
645 |
-
|
646 |
-
|
647 |
-
|
648 |
-
|
649 |
-
|
650 |
-
|
651 |
-
|
652 |
-
|
653 |
-
|
654 |
-
*
|
655 |
-
|
656 |
-
|
657 |
-
|
658 |
-
|
659 |
-
|
660 |
-
|
661 |
-
|
662 |
-
|
663 |
-
|
664 |
-
|
665 |
-
|
666 |
-
|
667 |
-
|
668 |
-
|
669 |
-
|
670 |
-
|
671 |
-
|
672 |
-
|
673 |
-
|
674 |
-
|
675 |
-
|
676 |
-
|
677 |
-
|
678 |
-
|
679 |
-
|
680 |
-
|
681 |
-
|
682 |
-
|
683 |
-
|
684 |
-
|
685 |
-
|
686 |
-
|
687 |
-
|
688 |
-
|
689 |
-
|
690 |
-
|
691 |
-
|
692 |
-
|
693 |
-
|
694 |
-
|
695 |
-
|
696 |
-
|
697 |
-
|
698 |
-
|
699 |
-
|
700 |
-
|
701 |
-
|
702 |
-
|
703 |
-
|
704 |
-
|
705 |
-
|
706 |
-
|
707 |
-
|
708 |
-
|
709 |
-
|
710 |
-
|
711 |
-
|
712 |
-
|
713 |
-
|
714 |
-
|
715 |
-
|
716 |
-
|
717 |
-
|
718 |
-
|
719 |
-
|
720 |
-
|
721 |
-
|
722 |
-
|
723 |
-
|
724 |
-
|
725 |
-
|
726 |
-
|
727 |
-
|
728 |
-
|
729 |
-
|
730 |
-
|
731 |
-
|
732 |
-
|
733 |
-
|
734 |
-
|
735 |
-
|
736 |
-
|
737 |
-
|
738 |
-
|
739 |
-
|
740 |
-
|
741 |
-
|
742 |
-
|
743 |
-
|
744 |
-
|
745 |
-
|
746 |
-
|
747 |
-
|
748 |
-
|
749 |
-
|
750 |
-
|
751 |
-
|
752 |
-
|
753 |
-
|
754 |
-
|
755 |
-
|
756 |
-
|
757 |
-
|
758 |
-
|
759 |
-
|
760 |
-
|
761 |
-
|
762 |
-
|
763 |
-
|
764 |
-
|
765 |
-
|
766 |
-
|
767 |
-
|
768 |
-
|
769 |
-
|
770 |
-
|
771 |
-
|
772 |
-
|
773 |
-
|
774 |
-
|
775 |
-
|
776 |
-
|
777 |
-
|
778 |
-
|
779 |
-
|
780 |
-
|
781 |
-
|
782 |
-
|
783 |
-
|
784 |
-
|
785 |
-
|
786 |
-
|
787 |
-
|
788 |
-
|
789 |
-
|
790 |
-
|
791 |
-
|
792 |
-
|
793 |
-
|
794 |
-
|
795 |
-
|
796 |
-
|
797 |
-
|
798 |
-
|
799 |
-
*
|
800 |
-
*
|
801 |
-
*
|
802 |
-
|
803 |
-
|
804 |
-
|
805 |
-
|
806 |
-
|
807 |
-
|
808 |
-
|
809 |
-
|
810 |
-
|
811 |
-
|
812 |
-
|
813 |
-
|
814 |
-
|
815 |
-
|
816 |
-
|
817 |
-
|
818 |
-
|
819 |
-
|
820 |
-
|
821 |
-
|
822 |
-
|
823 |
-
|
824 |
-
|
825 |
-
|
826 |
-
|
827 |
-
|
828 |
-
|
829 |
-
|
830 |
-
|
831 |
-
|
832 |
-
|
833 |
-
|
834 |
-
|
835 |
-
|
836 |
-
}
|
837 |
-
|
838 |
-
|
839 |
-
|
840 |
-
|
841 |
-
|
842 |
-
|
843 |
-
|
844 |
-
|
845 |
-
|
846 |
-
|
847 |
-
|
848 |
-
|
849 |
-
|
850 |
-
|
851 |
-
|
852 |
-
|
853 |
-
|
854 |
-
|
855 |
-
|
856 |
-
|
857 |
-
|
858 |
-
|
859 |
-
|
860 |
-
|
861 |
-
|
862 |
-
|
863 |
-
|
864 |
-
|
865 |
-
|
866 |
-
|
867 |
-
|
868 |
-
|
869 |
-
|
870 |
-
|
871 |
-
|
872 |
-
|
873 |
-
|
874 |
-
|
875 |
-
|
876 |
-
|
877 |
-
|
878 |
-
$
|
879 |
-
|
880 |
-
|
881 |
-
|
882 |
-
|
883 |
-
|
884 |
-
|
885 |
-
|
886 |
-
|
887 |
-
|
888 |
-
|
889 |
-
|
890 |
-
|
891 |
-
|
892 |
-
|
893 |
-
|
894 |
-
|
895 |
-
|
896 |
-
|
897 |
-
|
898 |
-
|
899 |
-
|
900 |
-
|
901 |
-
|
902 |
-
|
903 |
-
|
904 |
-
|
905 |
-
|
906 |
-
|
907 |
-
|
908 |
-
|
909 |
-
|
910 |
-
|
911 |
-
|
912 |
-
$
|
913 |
-
|
914 |
-
|
915 |
-
|
916 |
-
|
917 |
-
|
918 |
-
|
919 |
-
|
920 |
-
}
|
921 |
-
|
922 |
-
|
923 |
-
|
924 |
-
|
925 |
-
|
926 |
-
|
927 |
-
|
928 |
-
|
929 |
-
|
930 |
-
|
931 |
-
|
932 |
-
|
933 |
-
|
934 |
-
|
935 |
-
|
936 |
-
|
937 |
-
|
938 |
-
|
939 |
-
|
940 |
-
|
941 |
-
|
942 |
-
|
943 |
-
|
944 |
-
|
945 |
-
|
946 |
-
|
947 |
-
|
948 |
-
|
949 |
-
|
950 |
-
|
951 |
-
|
952 |
-
|
953 |
-
|
954 |
-
|
955 |
-
|
956 |
-
|
957 |
-
if (
|
958 |
-
|
959 |
-
$
|
960 |
-
|
961 |
-
|
962 |
-
|
963 |
-
|
964 |
-
|
965 |
-
|
966 |
-
|
967 |
-
|
968 |
-
|
969 |
-
|
970 |
-
|
971 |
-
|
972 |
-
|
973 |
-
|
974 |
-
|
975 |
-
|
976 |
-
|
977 |
-
|
978 |
-
|
979 |
-
|
980 |
-
|
981 |
-
|
982 |
-
|
983 |
-
|
984 |
-
|
985 |
-
|
986 |
-
|
987 |
-
|
988 |
-
|
989 |
-
|
990 |
-
|
991 |
-
|
992 |
-
|
993 |
-
|
994 |
-
|
995 |
-
|
996 |
-
|
997 |
-
|
998 |
-
|
999 |
-
|
1000 |
-
|
1001 |
-
|
1002 |
-
|
1003 |
-
|
1004 |
-
|
1005 |
-
|
1006 |
-
|
1007 |
-
|
1008 |
-
|
1009 |
-
|
1010 |
-
|
1011 |
-
|
1012 |
-
|
1013 |
-
|
1014 |
-
|
1015 |
-
|
1016 |
-
|
1017 |
-
|
1018 |
-
|
1019 |
-
|
1020 |
-
|
1021 |
-
|
1022 |
-
|
1023 |
-
|
1024 |
-
|
1025 |
-
|
1026 |
-
|
1027 |
-
|
1028 |
-
|
1029 |
-
|
1030 |
-
|
1031 |
-
|
1032 |
-
|
1033 |
-
|
1034 |
-
|
1035 |
-
|
1036 |
-
|
1037 |
-
|
1038 |
-
|
1039 |
-
|
1040 |
-
|
1041 |
-
|
1042 |
-
|
1043 |
-
|
1044 |
-
|
1045 |
-
|
1046 |
-
|
1047 |
-
|
1048 |
-
|
1049 |
-
|
1050 |
-
|
1051 |
-
|
1052 |
-
|
1053 |
-
|
1054 |
-
|
1055 |
-
|
1056 |
-
|
1057 |
-
|
1058 |
-
|
1059 |
-
|
1060 |
-
|
1061 |
-
|
1062 |
-
|
1063 |
-
|
1064 |
-
|
1065 |
-
|
1066 |
-
|
1067 |
-
$
|
1068 |
-
}
|
1069 |
-
|
1070 |
-
|
1071 |
-
|
1072 |
-
|
1073 |
-
|
1074 |
-
|
1075 |
-
|
1076 |
-
|
1077 |
-
|
1078 |
-
|
1079 |
-
|
1080 |
-
|
1081 |
-
|
1082 |
-
|
1083 |
-
|
1084 |
-
|
1085 |
-
|
1086 |
-
|
1087 |
-
|
1088 |
-
|
1089 |
-
|
1090 |
-
|
1091 |
-
|
1092 |
-
|
1093 |
-
|
1094 |
-
|
1095 |
-
|
1096 |
-
|
1097 |
-
|
1098 |
-
|
1099 |
-
|
1100 |
-
|
1101 |
-
|
1102 |
-
|
1103 |
-
|
1104 |
-
|
1105 |
-
|
1106 |
-
|
1107 |
-
|
1108 |
-
|
1109 |
-
|
1110 |
-
|
1111 |
-
$
|
1112 |
-
|
1113 |
-
|
1114 |
-
|
1115 |
-
|
1116 |
-
|
1117 |
-
|
1118 |
-
|
1119 |
-
|
1120 |
-
|
1121 |
-
|
1122 |
-
|
1123 |
-
|
1124 |
-
|
1125 |
-
|
1126 |
-
|
1127 |
-
|
1128 |
-
|
1129 |
-
|
1130 |
-
|
1131 |
-
|
1132 |
-
|
1133 |
-
|
1134 |
-
|
1135 |
-
|
1136 |
-
|
1137 |
-
|
1138 |
-
|
1139 |
-
|
1140 |
-
|
1141 |
-
|
1142 |
-
|
1143 |
-
|
1144 |
-
|
1145 |
-
|
1146 |
-
|
1147 |
-
|
1148 |
-
|
1149 |
-
|
1150 |
-
|
1151 |
-
|
1152 |
-
|
1153 |
-
|
1154 |
-
*
|
1155 |
-
|
1156 |
-
|
1157 |
-
|
1158 |
-
|
1159 |
-
|
1160 |
-
|
1161 |
-
|
1162 |
-
|
1163 |
-
|
1164 |
-
|
1165 |
-
|
1166 |
-
|
1167 |
-
|
1168 |
-
|
1169 |
-
|
1170 |
-
*
|
1171 |
-
*
|
1172 |
-
*
|
1173 |
-
*
|
1174 |
-
*
|
1175 |
-
* @
|
1176 |
-
|
1177 |
-
|
1178 |
-
|
1179 |
-
|
1180 |
-
|
1181 |
-
|
1182 |
-
|
1183 |
-
|
1184 |
-
|
1185 |
-
|
1186 |
-
|
1187 |
-
|
1188 |
-
|
1189 |
-
|
1190 |
-
|
1191 |
-
|
1192 |
-
|
1193 |
-
|
1194 |
-
|
1195 |
-
|
1196 |
-
|
1197 |
-
|
1198 |
-
|
1199 |
-
|
1200 |
-
|
1201 |
-
|
1202 |
-
|
1203 |
-
|
1204 |
-
|
1205 |
-
|
1206 |
-
|
1207 |
-
|
1208 |
-
|
1209 |
-
|
1210 |
-
|
1211 |
-
|
1212 |
-
|
1213 |
-
|
1214 |
-
|
1215 |
-
|
1216 |
-
|
1217 |
-
|
1218 |
-
|
1219 |
-
|
1220 |
-
|
1221 |
-
|
1222 |
-
|
1223 |
-
|
1224 |
-
|
1225 |
-
|
1226 |
-
|
1227 |
-
'default' => '
|
1228 |
-
)
|
1229 |
-
);
|
1230 |
-
|
1231 |
-
|
1232 |
-
|
1233 |
-
|
1234 |
-
|
1235 |
-
|
1236 |
-
|
1237 |
-
|
1238 |
-
|
1239 |
-
|
1240 |
-
|
1241 |
-
|
1242 |
-
|
1243 |
-
|
1244 |
-
|
1245 |
-
|
1246 |
-
|
1247 |
-
|
1248 |
-
|
1249 |
-
|
1250 |
-
|
1251 |
-
|
1252 |
-
|
1253 |
-
|
1254 |
-
|
1255 |
-
|
1256 |
-
|
1257 |
-
|
1258 |
-
|
1259 |
-
|
1260 |
-
|
1261 |
-
|
1262 |
-
|
1263 |
-
|
1264 |
-
|
1265 |
-
|
1266 |
-
|
1267 |
-
|
1268 |
-
|
1269 |
-
|
1270 |
-
|
1271 |
-
|
1272 |
-
|
1273 |
-
|
1274 |
-
|
1275 |
-
|
1276 |
-
|
1277 |
-
|
1278 |
-
|
1279 |
-
|
1280 |
-
|
1281 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// Exit if accessed directly
|
4 |
+
if ( ! defined( 'ABSPATH' ) ) exit;
|
5 |
+
|
6 |
+
if ( ! class_exists( 'ezTOC_Option' ) ) {
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Class ezTOC_Option
|
10 |
+
*
|
11 |
+
* Credit: Adapted from Easy Digital Downloads.
|
12 |
+
*/
|
13 |
+
final class ezTOC_Option {
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Register the plugins core settings and options.
|
17 |
+
*
|
18 |
+
* @access private
|
19 |
+
* @since 1.0
|
20 |
+
* @static
|
21 |
+
*/
|
22 |
+
public static function register() {
|
23 |
+
|
24 |
+
if ( false === get_option( 'ez-toc-settings' ) ) {
|
25 |
+
|
26 |
+
add_option( 'ez-toc-settings', self::getDefaults() );
|
27 |
+
}
|
28 |
+
|
29 |
+
foreach ( self::getRegistered() as $section => $settings ) {
|
30 |
+
|
31 |
+
add_settings_section(
|
32 |
+
'ez_toc_settings_' . $section,
|
33 |
+
__return_null(),
|
34 |
+
'__return_false',
|
35 |
+
'ez_toc_settings_' . $section
|
36 |
+
);
|
37 |
+
|
38 |
+
foreach ( $settings as $option ) {
|
39 |
+
|
40 |
+
$name = isset( $option['name'] ) ? $option['name'] : '';
|
41 |
+
|
42 |
+
add_settings_field(
|
43 |
+
'ez-toc-settings[' . $option['id'] . ']',
|
44 |
+
$name,
|
45 |
+
method_exists( __CLASS__, $option['type'] ) ? array( __CLASS__, $option['type'] ) : array( __CLASS__, 'missingCallback' ),
|
46 |
+
'ez_toc_settings_' . $section,
|
47 |
+
'ez_toc_settings_' . $section,
|
48 |
+
array(
|
49 |
+
'section' => $section,
|
50 |
+
'id' => isset( $option['id'] ) ? $option['id'] : null,
|
51 |
+
'desc' => ! empty( $option['desc'] ) ? $option['desc'] : '',
|
52 |
+
'name' => isset( $option['name'] ) ? $option['name'] : null,
|
53 |
+
'size' => isset( $option['size'] ) ? $option['size'] : null,
|
54 |
+
'options' => isset( $option['options'] ) ? $option['options'] : '',
|
55 |
+
'default' => isset( $option['default'] ) ? $option['default'] : '',
|
56 |
+
'min' => isset( $option['min'] ) ? $option['min'] : null,
|
57 |
+
'max' => isset( $option['max'] ) ? $option['max'] : null,
|
58 |
+
'step' => isset( $option['step'] ) ? $option['step'] : null,
|
59 |
+
'chosen' => isset( $option['chosen'] ) ? $option['chosen'] : null,
|
60 |
+
'placeholder' => isset( $option['placeholder'] ) ? $option['placeholder'] : null,
|
61 |
+
'allow_blank' => isset( $option['allow_blank'] ) ? $option['allow_blank'] : true,
|
62 |
+
'readonly' => isset( $option['readonly'] ) ? $option['readonly'] : false,
|
63 |
+
'faux' => isset( $option['faux'] ) ? $option['faux'] : false,
|
64 |
+
)
|
65 |
+
);
|
66 |
+
}
|
67 |
+
|
68 |
+
}
|
69 |
+
|
70 |
+
// Creates our settings in the options table
|
71 |
+
register_setting( 'ez-toc-settings', 'ez-toc-settings', array( __CLASS__, 'sanitize' ) );
|
72 |
+
}
|
73 |
+
|
74 |
+
/**
|
75 |
+
* Callback for settings sanitization.
|
76 |
+
*
|
77 |
+
* @access private
|
78 |
+
* @since 1.0
|
79 |
+
* @static
|
80 |
+
*
|
81 |
+
* @param array $input The value inputted in the field.
|
82 |
+
*
|
83 |
+
* @return string $input Sanitized value.
|
84 |
+
*/
|
85 |
+
public static function sanitize( $input = array() ) {
|
86 |
+
|
87 |
+
$options = self::getOptions();
|
88 |
+
|
89 |
+
if ( empty( $_POST['_wp_http_referer'] ) ) {
|
90 |
+
|
91 |
+
return $input;
|
92 |
+
}
|
93 |
+
|
94 |
+
$registered = self::getRegistered();
|
95 |
+
|
96 |
+
foreach ( $registered as $sectionID => $sectionOptions ) {
|
97 |
+
|
98 |
+
$input = $input ? $input : array();
|
99 |
+
$input = apply_filters( 'ez_toc_settings_' . $sectionID . '_sanitize', $input );
|
100 |
+
|
101 |
+
// Loop through each setting being saved and pass it through a sanitization filter
|
102 |
+
foreach ( $input as $key => $value ) {
|
103 |
+
|
104 |
+
// Get the setting type (checkbox, select, etc)
|
105 |
+
$type = isset( $registered[ $sectionID ][ $key ]['type'] ) ? $registered[ $sectionID ][ $key ]['type'] : false;
|
106 |
+
|
107 |
+
if ( $type ) {
|
108 |
+
|
109 |
+
// Field type specific filter
|
110 |
+
$input[ $key ] = apply_filters( 'ez_toc_settings_sanitize_' . $type, $value, $key );
|
111 |
+
}
|
112 |
+
|
113 |
+
// General filter
|
114 |
+
$input[ $key ] = apply_filters( 'ez_toc_settings_sanitize', $input[ $key ], $key );
|
115 |
+
}
|
116 |
+
|
117 |
+
// Loop through the registered options.
|
118 |
+
foreach ( $sectionOptions as $optionID => $optionProperties ) {
|
119 |
+
|
120 |
+
// Unset any that are empty for the section being saved.
|
121 |
+
if ( empty( $input[ $optionID ] ) ) {
|
122 |
+
|
123 |
+
unset( $options[ $optionID ] );
|
124 |
+
}
|
125 |
+
|
126 |
+
// Check for the checkbox option type.
|
127 |
+
if ( array_key_exists( 'type', $optionProperties ) && 'checkbox' == $optionProperties['type'] ) {
|
128 |
+
|
129 |
+
// If it does not exist in the options values being saved, add the option ID and set its value to `0`.
|
130 |
+
// This matches WP core behavior for saving checkbox option values.
|
131 |
+
if ( ! array_key_exists( $optionID, $input ) ) {
|
132 |
+
|
133 |
+
$input[ $optionID ] = '0';
|
134 |
+
}
|
135 |
+
}
|
136 |
+
}
|
137 |
+
|
138 |
+
}
|
139 |
+
|
140 |
+
// Merge our new settings with the existing
|
141 |
+
$output = array_merge( $options, $input );
|
142 |
+
|
143 |
+
return $output;
|
144 |
+
}
|
145 |
+
|
146 |
+
/**
|
147 |
+
* The core registered settings and options.
|
148 |
+
*
|
149 |
+
* @access private
|
150 |
+
* @since 1.0
|
151 |
+
* @static
|
152 |
+
*
|
153 |
+
* @return array
|
154 |
+
*/
|
155 |
+
private static function getRegistered() {
|
156 |
+
|
157 |
+
$options = array(
|
158 |
+
'general' => apply_filters(
|
159 |
+
'ez_toc_settings_general',
|
160 |
+
array(
|
161 |
+
'enabled_post_types' => array(
|
162 |
+
'id' => 'enabled_post_types',
|
163 |
+
'name' => __( 'Enable Support', 'easy-table-of-contents' ),
|
164 |
+
'desc' => __( 'Select the post types to enable the support for table of contents.', 'easy-table-of-contents' ),
|
165 |
+
'type' => 'checkboxgroup',
|
166 |
+
'options' => self::getPostTypes(),
|
167 |
+
'default' => array(),
|
168 |
+
),
|
169 |
+
'auto_insert_post_types' => array(
|
170 |
+
'id' => 'auto_insert_post_types',
|
171 |
+
'name' => __( 'Auto Insert', 'easy-table-of-contents' ),
|
172 |
+
'desc' => __( 'Select the post types which will have the table of contents automatically inserted.', 'easy-table-of-contents' ) .
|
173 |
+
'<br><span class="description">' . __( 'NOTE: The table of contents will only be automatically inserted on post types for which it has been enabled.', 'easy-table-of-contents' ) . '<span>',
|
174 |
+
'type' => 'checkboxgroup',
|
175 |
+
'options' => self::getPostTypes(),
|
176 |
+
'default' => array(),
|
177 |
+
),
|
178 |
+
'position' => array(
|
179 |
+
'id' => 'position',
|
180 |
+
'name' => __( 'Position', 'easy-table-of-contents' ),
|
181 |
+
'desc' => __( 'Choose where where you want to display the table of contents.', 'easy-table-of-contents' ),
|
182 |
+
'type' => 'select',
|
183 |
+
'options' => array(
|
184 |
+
'before' => __( 'Before first heading (default)', 'easy-table-of-contents' ),
|
185 |
+
'after' => __( 'After first heading', 'easy-table-of-contents' ),
|
186 |
+
'top' => __( 'Top', 'easy-table-of-contents' ),
|
187 |
+
'bottom' => __( 'Bottom', 'easy-table-of-contents' ),
|
188 |
+
//'placeholder' => __( 'Replace [toc] placeholder. For backwards compatibility with Table of Content Plus.', 'easy-table-of-contents' ),
|
189 |
+
),
|
190 |
+
'default' => 1,
|
191 |
+
),
|
192 |
+
'start' => array(
|
193 |
+
'id' => 'start',
|
194 |
+
'name' => __( 'Show when', 'easy-table-of-contents' ),
|
195 |
+
'desc' => __( 'or more headings are present', 'easy-table-of-contents' ),
|
196 |
+
'type' => 'select',
|
197 |
+
'options' => array_combine( range( 1, 10 ), range( 1, 10 ) ),
|
198 |
+
'default' => 4,
|
199 |
+
),
|
200 |
+
'show_heading_text' => array(
|
201 |
+
'id' => 'show_heading_text',
|
202 |
+
'name' => __( 'Display Header Label', 'easy-table-of-contents' ),
|
203 |
+
'desc' => __( 'Show header text above the table of contents.', 'easy-table-of-contents' ),
|
204 |
+
'type' => 'checkbox',
|
205 |
+
'default' => true,
|
206 |
+
),
|
207 |
+
'heading_text' => array(
|
208 |
+
'id' => 'heading_text',
|
209 |
+
'name' => __( 'Header Label', 'easy-table-of-contents' ),
|
210 |
+
'desc' => __( 'Eg: Contents, Table of Contents, Page Contents', 'easy-table-of-contents' ),
|
211 |
+
'type' => 'text',
|
212 |
+
'default' => __( 'Contents', 'easy-table-of-contents' ),
|
213 |
+
),
|
214 |
+
'visibility' => array(
|
215 |
+
'id' => 'visibility',
|
216 |
+
'name' => __( 'Toggle View', 'easy-table-of-contents' ),
|
217 |
+
'desc' => __( 'Allow the user to toggle the visibility of the table of contents.', 'easy-table-of-contents' ),
|
218 |
+
'type' => 'checkbox',
|
219 |
+
'default' => true,
|
220 |
+
),
|
221 |
+
//'visibility_show' => array(
|
222 |
+
// 'id' => 'visibility_show',
|
223 |
+
// 'name' => __( 'Show Label', 'easy-table-of-contents' ),
|
224 |
+
// 'desc' => __( 'Eg: show', 'easy-table-of-contents' ),
|
225 |
+
// 'type' => 'text',
|
226 |
+
// 'default' => __( 'show', 'easy-table-of-contents' ),
|
227 |
+
//),
|
228 |
+
//'visibility_hide' => array(
|
229 |
+
// 'id' => 'visibility_hide',
|
230 |
+
// 'name' => __( 'Hide Label', 'easy-table-of-contents' ),
|
231 |
+
// 'desc' => __( 'Eg: hide', 'easy-table-of-contents' ),
|
232 |
+
// 'type' => 'text',
|
233 |
+
// 'default' => __( 'hide', 'easy-table-of-contents' ),
|
234 |
+
//),
|
235 |
+
'visibility_hide_by_default' => array(
|
236 |
+
'id' => 'visibility_hide_by_default',
|
237 |
+
'name' => __( 'Initial View', 'easy-table-of-contents' ),
|
238 |
+
'desc' => __( 'Initially hide the table of contents.', 'easy-table-of-contents' ),
|
239 |
+
'type' => 'checkbox',
|
240 |
+
'default' => false,
|
241 |
+
),
|
242 |
+
'show_hierarchy' => array(
|
243 |
+
'id' => 'show_hierarchy',
|
244 |
+
'name' => __( 'Show as Hierarchy', 'easy-table-of-contents' ),
|
245 |
+
'desc' => '',
|
246 |
+
'type' => 'checkbox',
|
247 |
+
'default' => true,
|
248 |
+
),
|
249 |
+
'counter' => array(
|
250 |
+
'id' => 'counter',
|
251 |
+
'name' => __( 'Counter', 'easy-table-of-contents' ),
|
252 |
+
'desc' => '',
|
253 |
+
'type' => 'select',
|
254 |
+
'options' => array(
|
255 |
+
'decimal' => __( 'Decimal (default)', 'easy-table-of-contents' ),
|
256 |
+
'numeric' => __( 'Numeric', 'easy-table-of-contents' ),
|
257 |
+
'roman' => __( 'Roman', 'easy-table-of-contents' ),
|
258 |
+
'none' => __( 'None', 'easy-table-of-contents' ),
|
259 |
+
),
|
260 |
+
'default' => 'decimal',
|
261 |
+
),
|
262 |
+
'smooth_scroll' => array(
|
263 |
+
'id' => 'smooth_scroll',
|
264 |
+
'name' => __( 'Smooth Scroll', 'easy-table-of-contents' ),
|
265 |
+
'desc' => '',
|
266 |
+
'type' => 'checkbox',
|
267 |
+
'default' => true,
|
268 |
+
),
|
269 |
+
'toc_loading' => array(
|
270 |
+
'id' => 'toc_loading',
|
271 |
+
'name' => __( 'TOC Loading Method', 'easy-table-of-contents' ),
|
272 |
+
'desc' => '',
|
273 |
+
'type' => 'select',
|
274 |
+
'options' => array(
|
275 |
+
'js' => __( 'JavaScript (default)', 'easy-table-of-contents' ),
|
276 |
+
'css' => __( 'Pure CSS', 'easy-table-of-contents' ),
|
277 |
+
|
278 |
+
),
|
279 |
+
'default' => 'js',
|
280 |
+
),
|
281 |
+
)
|
282 |
+
),
|
283 |
+
'appearance' => apply_filters(
|
284 |
+
'ez_toc_settings_appearance',
|
285 |
+
array(
|
286 |
+
'width' => array(
|
287 |
+
'id' => 'width',
|
288 |
+
'name' => __( 'Width', 'easy-table-of-contents' ),
|
289 |
+
'desc' => '',
|
290 |
+
'type' => 'selectgroup',
|
291 |
+
'options' => array(
|
292 |
+
'fixed' => array(
|
293 |
+
'name' => __( 'Fixed', 'easy-table-of-contents' ),
|
294 |
+
'options' => array(
|
295 |
+
'200px' => '200px',
|
296 |
+
'225px' => '225px',
|
297 |
+
'250px' => '250px',
|
298 |
+
'275px' => '275px',
|
299 |
+
'300px' => '300px',
|
300 |
+
'325px' => '325px',
|
301 |
+
'350px' => '350px',
|
302 |
+
'375px' => '375px',
|
303 |
+
'400px' => '400px',
|
304 |
+
),
|
305 |
+
),
|
306 |
+
'relative' => array(
|
307 |
+
'name' => __( 'Relative', 'easy-table-of-contents' ),
|
308 |
+
'options' => array(
|
309 |
+
'auto' => 'Auto',
|
310 |
+
'25%' => '25%',
|
311 |
+
'33%' => '33%',
|
312 |
+
'50%' => '50%',
|
313 |
+
'66%' => '66%',
|
314 |
+
'75%' => '75%',
|
315 |
+
'100%' => '100%',
|
316 |
+
),
|
317 |
+
),
|
318 |
+
'other' => array(
|
319 |
+
'name' => __( 'Custom', 'easy-table-of-contents' ),
|
320 |
+
'options' => array(
|
321 |
+
'custom' => __( 'User Defined', 'easy-table-of-contents' ),
|
322 |
+
),
|
323 |
+
),
|
324 |
+
),
|
325 |
+
'default' => 'auto',
|
326 |
+
),
|
327 |
+
'width_custom' => array(
|
328 |
+
'id' => 'width_custom',
|
329 |
+
'name' => __( 'Custom Width', 'easy-table-of-contents' ),
|
330 |
+
'desc' => __( 'Select the User Defined option from the Width option to utilitze the custom width.', 'easy-table-of-contents' ),
|
331 |
+
'type' => 'custom_width',
|
332 |
+
'default' => 275,
|
333 |
+
),
|
334 |
+
'wrapping' => array(
|
335 |
+
'id' => 'wrapping',
|
336 |
+
'name' => __( 'Float', 'easy-table-of-contents' ),
|
337 |
+
'desc' => '',
|
338 |
+
'type' => 'select',
|
339 |
+
'options' => array(
|
340 |
+
'none' => __( 'None (Default)', 'easy-table-of-contents' ),
|
341 |
+
'left' => __( 'Left', 'easy-table-of-contents' ),
|
342 |
+
'right' => __( 'Right', 'easy-table-of-contents' ),
|
343 |
+
),
|
344 |
+
'default' => 'none',
|
345 |
+
),
|
346 |
+
'title_font_size' => array(
|
347 |
+
'id' => 'title_font_size',
|
348 |
+
'name' => __( 'Title Font Size', 'easy-table-of-contents' ),
|
349 |
+
'desc' => '',
|
350 |
+
'type' => 'font_size',
|
351 |
+
'default' => 120,
|
352 |
+
),
|
353 |
+
'title_font_weight' => array(
|
354 |
+
'id' => 'title_font_weight',
|
355 |
+
'name' => __( 'Title Font Weight', 'easy-table-of-contents' ),
|
356 |
+
'desc' => '',
|
357 |
+
'type' => 'select',
|
358 |
+
'options' => array(
|
359 |
+
'100' => __( 'Thin', 'easy-table-of-contents' ),
|
360 |
+
'200' => __( 'Extra Light', 'easy-table-of-contents' ),
|
361 |
+
'300' => __( 'Light', 'easy-table-of-contents' ),
|
362 |
+
'400' => __( 'Normal', 'easy-table-of-contents' ),
|
363 |
+
'500' => __( 'Medium', 'easy-table-of-contents' ),
|
364 |
+
'600' => __( 'Semi Bold', 'easy-table-of-contents' ),
|
365 |
+
'700' => __( 'Bold', 'easy-table-of-contents' ),
|
366 |
+
'800' => __( 'Extra Bold', 'easy-table-of-contents' ),
|
367 |
+
'900' => __( 'Heavy', 'easy-table-of-contents' ),
|
368 |
+
),
|
369 |
+
'default' => '500',
|
370 |
+
),
|
371 |
+
'font_size' => array(
|
372 |
+
'id' => 'font_size',
|
373 |
+
'name' => __( 'Font Size', 'easy-table-of-contents' ),
|
374 |
+
'desc' => '',
|
375 |
+
'type' => 'font_size',
|
376 |
+
'default' => 95,
|
377 |
+
),
|
378 |
+
'theme' => array(
|
379 |
+
'id' => 'theme',
|
380 |
+
'name' => __( 'Theme', 'easy-table-of-contents' ),
|
381 |
+
'desc' => __( 'The theme is only applied to the table of contents which is auto inserted into the post. The Table of Contents widget will inherit the theme widget styles.', 'easy-table-of-contents' ),
|
382 |
+
'type' => 'radio',
|
383 |
+
'options' => array(
|
384 |
+
'grey' => __( 'Grey', 'easy-table-of-contents' ),
|
385 |
+
'light-blue' => __( 'Light Blue', 'easy-table-of-contents' ),
|
386 |
+
'white' => __( 'White', 'easy-table-of-contents' ),
|
387 |
+
'black' => __( 'Black', 'easy-table-of-contents' ),
|
388 |
+
'transparent' => __( 'Transparent', 'easy-table-of-contents' ),
|
389 |
+
'custom' => __( 'Custom', 'easy-table-of-contents' ),
|
390 |
+
),
|
391 |
+
'default' => 'grey',
|
392 |
+
),
|
393 |
+
'custom_theme_header' => array(
|
394 |
+
'id' => 'custom_theme_header',
|
395 |
+
'name' => '<strong>' . __( 'Custom Theme', 'easy-table-of-contents' ) . '</strong>',
|
396 |
+
'desc' => __( 'For the following settings to apply, select the Custom Theme option.', 'easy-table-of-contents' ),
|
397 |
+
'type' => 'header',
|
398 |
+
),
|
399 |
+
'custom_background_colour' => array(
|
400 |
+
'id' => 'custom_background_colour',
|
401 |
+
'name' => __( 'Background Color', 'easy-table-of-contents' ),
|
402 |
+
'desc' => '',
|
403 |
+
'type' => 'color',
|
404 |
+
'default' => '#fff',
|
405 |
+
),
|
406 |
+
'custom_border_colour' => array(
|
407 |
+
'id' => 'custom_border_colour',
|
408 |
+
'name' => __( 'Border Color', 'easy-table-of-contents' ),
|
409 |
+
'desc' => '',
|
410 |
+
'type' => 'color',
|
411 |
+
'default' => '#ddd',
|
412 |
+
),
|
413 |
+
'custom_title_colour' => array(
|
414 |
+
'id' => 'custom_title_colour',
|
415 |
+
'name' => __( 'Title Color', 'easy-table-of-contents' ),
|
416 |
+
'desc' => '',
|
417 |
+
'type' => 'color',
|
418 |
+
'default' => '#999',
|
419 |
+
),
|
420 |
+
'custom_link_colour' => array(
|
421 |
+
'id' => 'custom_link_colour',
|
422 |
+
'name' => __( 'Link Color', 'easy-table-of-contents' ),
|
423 |
+
'desc' => '',
|
424 |
+
'type' => 'color',
|
425 |
+
'default' => '#428bca',
|
426 |
+
),
|
427 |
+
'custom_link_hover_colour' => array(
|
428 |
+
'id' => 'custom_link_hover_colour',
|
429 |
+
'name' => __( 'Link Hover Color', 'easy-table-of-contents' ),
|
430 |
+
'desc' => '',
|
431 |
+
'type' => 'color',
|
432 |
+
'default' => '#2a6496',
|
433 |
+
),
|
434 |
+
'custom_link_visited_colour' => array(
|
435 |
+
'id' => 'custom_link_visited_colour',
|
436 |
+
'name' => __( 'Link Visited Color', 'easy-table-of-contents' ),
|
437 |
+
'desc' => '',
|
438 |
+
'type' => 'color',
|
439 |
+
'default' => '#428bca',
|
440 |
+
),
|
441 |
+
)
|
442 |
+
),
|
443 |
+
'advanced' => apply_filters(
|
444 |
+
'ez_toc_settings_advanced',
|
445 |
+
array(
|
446 |
+
'lowercase' => array(
|
447 |
+
'id' => 'lowercase',
|
448 |
+
'name' => __( 'Lowercase', 'easy-table-of-contents' ),
|
449 |
+
'desc' => __( 'Ensure anchors are in lowercase.', 'easy-table-of-contents' ),
|
450 |
+
'type' => 'checkbox',
|
451 |
+
'default' => false,
|
452 |
+
),
|
453 |
+
'hyphenate' => array(
|
454 |
+
'id' => 'hyphenate',
|
455 |
+
'name' => __( 'Hyphenate', 'easy-table-of-contents' ),
|
456 |
+
'desc' => __( 'Use - rather than _ in anchors.', 'easy-table-of-contents' ),
|
457 |
+
'type' => 'checkbox',
|
458 |
+
'default' => false,
|
459 |
+
),
|
460 |
+
'include_homepage' => array(
|
461 |
+
'id' => 'include_homepage',
|
462 |
+
'name' => __( 'Homepage', 'easy-table-of-contents' ),
|
463 |
+
'desc' => __( 'Show the table of contents for qualifying items on the homepage.', 'easy-table-of-contents' ),
|
464 |
+
'type' => 'checkbox',
|
465 |
+
'default' => false,
|
466 |
+
),
|
467 |
+
'exclude_css' => array(
|
468 |
+
'id' => 'exclude_css',
|
469 |
+
'name' => __( 'CSS', 'easy-table-of-contents' ),
|
470 |
+
'desc' => __( "Prevent the loading the core CSS styles. When selected, the appearance options from above will be ignored.", 'easy-table-of-contents' ),
|
471 |
+
'type' => 'checkbox',
|
472 |
+
'default' => false,
|
473 |
+
),
|
474 |
+
//'bullet_spacing' => array(
|
475 |
+
// 'id' => 'bullet_spacing',
|
476 |
+
// 'name' => __( 'Theme Bullets', 'easy-table-of-contents' ),
|
477 |
+
// 'desc' => __( 'If your theme includes background images for unordered list elements, enable this option to support them.', 'easy-table-of-contents' ),
|
478 |
+
// 'type' => 'checkbox',
|
479 |
+
// 'default' => false,
|
480 |
+
//),
|
481 |
+
'heading_levels' => array(
|
482 |
+
'id' => 'heading_levels',
|
483 |
+
'name' => __( 'Headings:', 'easy-table-of-contents' ),
|
484 |
+
'desc' => __( 'Select the heading to consider when generating the table of contents. Deselecting a heading will exclude it.', 'easy-table-of-contents' ),
|
485 |
+
'type' => 'checkboxgroup',
|
486 |
+
'options' => array(
|
487 |
+
'1' => __( 'Heading 1 (h1)', 'easy-table-of-contents' ),
|
488 |
+
'2' => __( 'Heading 2 (h2)', 'easy-table-of-contents' ),
|
489 |
+
'3' => __( 'Heading 3 (h3)', 'easy-table-of-contents' ),
|
490 |
+
'4' => __( 'Heading 4 (h4)', 'easy-table-of-contents' ),
|
491 |
+
'5' => __( 'Heading 5 (h5)', 'easy-table-of-contents' ),
|
492 |
+
'6' => __( 'Heading 6 (h6)', 'easy-table-of-contents' ),
|
493 |
+
),
|
494 |
+
'default' => array( '1', '2', '3', '4', '5', '6' ),
|
495 |
+
),
|
496 |
+
'exclude' => array(
|
497 |
+
'id' => 'exclude',
|
498 |
+
'name' => __( 'Exclude Headings', 'easy-table-of-contents' ),
|
499 |
+
'desc' => __( 'Specify headings to be excluded from appearing in the table of contents. Separate multiple headings with a pipe <code>|</code>. Use an asterisk <code>*</code> as a wildcard to match other text.', 'easy-table-of-contents' ),
|
500 |
+
'type' => 'text',
|
501 |
+
'size' => 'large',
|
502 |
+
'default' => '',
|
503 |
+
),
|
504 |
+
'exclude_desc' => array(
|
505 |
+
'id' => 'exclude_desc',
|
506 |
+
'name' => '',
|
507 |
+
'desc' => '<p><strong>' . __( 'Examples:', 'easy-table-of-contents' ) . '</strong></p>' .
|
508 |
+
'<ul>' .
|
509 |
+
'<li>' . __( '<code>Fruit*</code> Ignore headings starting with "Fruit".', 'easy-table-of-contents' ) . '</li>' .
|
510 |
+
'<li>' . __( '<code>*Fruit Diet*</code> Ignore headings with "Fruit Diet" somewhere in the heading.', 'easy-table-of-contents' ) . '</li>' .
|
511 |
+
'<li>' . __( '<code>Apple Tree|Oranges|Yellow Bananas</code> Ignore headings that are exactly "Apple Tree", "Oranges" or "Yellow Bananas".', 'easy-table-of-contents' ) . '</li>' .
|
512 |
+
'</ul>' .
|
513 |
+
'<p>' . __( '<strong>Note:</strong> This is not case sensitive.', 'easy-table-of-contents' ) . '</p>',
|
514 |
+
'type' => 'descriptive_text',
|
515 |
+
),
|
516 |
+
'smooth_scroll_offset' => array(
|
517 |
+
'id' => 'smooth_scroll_offset',
|
518 |
+
'name' => __( 'Smooth Scroll Offset', 'easy-table-of-contents' ),
|
519 |
+
'desc' => 'px<br/>' . __( 'If you have a consistent menu across the top of your site, you can adjust the top offset to stop the headings from appearing underneath the top menu. A setting of 30 accommodates the WordPress admin bar. This setting only has an effect after you have enabled Smooth Scroll option.', 'easy-table-of-contents' ),
|
520 |
+
'type' => 'number',
|
521 |
+
'size' => 'small',
|
522 |
+
'default' => 30
|
523 |
+
),
|
524 |
+
'mobile_smooth_scroll_offset' => array(
|
525 |
+
'id' => 'mobile_smooth_scroll_offset',
|
526 |
+
'name' => __( 'Mobile Smooth Scroll Offset', 'easy-table-of-contents' ),
|
527 |
+
'desc' => 'px<br/>' . __( 'This provides the same function as the Smooth Scroll Offset option above but applied when the user is visiting your site on a mobile device.', 'easy-table-of-contents' ),
|
528 |
+
'type' => 'number',
|
529 |
+
'size' => 'small',
|
530 |
+
'default' => 0
|
531 |
+
),
|
532 |
+
'restrict_path' => array(
|
533 |
+
'id' => 'restrict_path',
|
534 |
+
'name' => __( 'Limit Path', 'easy-table-of-contents' ),
|
535 |
+
'desc' => '<br/>' . __( 'Restrict generation of the table of contents to pages that match the required path. This path is from the root of your site and always begins with a forward slash.', 'easy-table-of-contents' ) .
|
536 |
+
'<br/><span class="description">' . __( 'Eg: /wiki/, /corporate/annual-reports/', 'easy-table-of-contents' ) . '</span>',
|
537 |
+
'type' => 'text',
|
538 |
+
),
|
539 |
+
'fragment_prefix' => array(
|
540 |
+
'id' => 'fragment_prefix',
|
541 |
+
'name' => __( 'Default Anchor Prefix', 'easy-table-of-contents' ),
|
542 |
+
'desc' => '<br/>' . __( 'Anchor targets are restricted to alphanumeric characters as per HTML specification (see readme for more detail). The default anchor prefix will be used when no characters qualify. When left blank, a number will be used instead.', 'easy-table-of-contents' ) .
|
543 |
+
'<br/>' . __( 'This option normally applies to content written in character sets other than ASCII.', 'easy-table-of-contents' ) .
|
544 |
+
'<br/><span class="description">' . __( 'Eg: i, toc_index, index, _', 'easy-table-of-contents' ) . '</span>',
|
545 |
+
'type' => 'text',
|
546 |
+
'default' => 'i',
|
547 |
+
),
|
548 |
+
'widget_affix_selector' => array(
|
549 |
+
'id' => 'widget_affix_selector',
|
550 |
+
'name' => __( 'Widget Affix Selector', 'easy-table-of-contents' ),
|
551 |
+
'desc' => '<br/>' . __( 'To enable the option to affix or pin the Table of Contents widget enter the theme\'s sidebar class or id.', 'easy-table-of-contents' ) .
|
552 |
+
'<br/>' . __( 'Since every theme is different, this can not be determined automatically. If you are unsure how to find the sidebar\'s class or id, please ask the theme\'s support persons.', 'easy-table-of-contents' ) .
|
553 |
+
'<br/><span class="description">' . __( 'Eg: .widget-area or #sidebar', 'easy-table-of-contents' ) . '</span>',
|
554 |
+
'type' => 'text',
|
555 |
+
'default' => '',
|
556 |
+
),
|
557 |
+
)
|
558 |
+
),
|
559 |
+
);
|
560 |
+
|
561 |
+
return apply_filters( 'ez_toc_registered_settings', $options );
|
562 |
+
}
|
563 |
+
|
564 |
+
/**
|
565 |
+
* The default values for the registered settings and options.
|
566 |
+
*
|
567 |
+
* @access private
|
568 |
+
* @since 1.0
|
569 |
+
* @static
|
570 |
+
*
|
571 |
+
* @return array
|
572 |
+
*/
|
573 |
+
private static function getDefaults() {
|
574 |
+
|
575 |
+
$defaults = array(
|
576 |
+
'fragment_prefix' => 'i',
|
577 |
+
'position' => 'before',
|
578 |
+
'start' => 4,
|
579 |
+
'show_heading_text' => true,
|
580 |
+
'heading_text' => 'Table of Contents',
|
581 |
+
'enabled_post_types' => array( 'page' ),
|
582 |
+
'auto_insert_post_types' => array(),
|
583 |
+
'show_hierarchy' => true,
|
584 |
+
'counter' => 'decimal',
|
585 |
+
'smooth_scroll' => true,
|
586 |
+
'smooth_scroll_offset' => 30,
|
587 |
+
'mobile_smooth_scroll_offset' => 0,
|
588 |
+
'visibility' => true,
|
589 |
+
'toc_loading' => 'js',
|
590 |
+
//'visibility_show' => 'show',
|
591 |
+
//'visibility_hide' => 'hide',
|
592 |
+
'visibility_hide_by_default' => false,
|
593 |
+
'width' => 'auto',
|
594 |
+
'width_custom' => 275,
|
595 |
+
'width_custom_units' => 'px',
|
596 |
+
'wrapping' => 'none',
|
597 |
+
'title_font_size' => 120,
|
598 |
+
'title_font_size_units' => '%',
|
599 |
+
'title_font_weight' => 500,
|
600 |
+
'font_size' => 95,
|
601 |
+
'font_size_units' => '%',
|
602 |
+
'theme' => 'grey',
|
603 |
+
'custom_background_colour' => '#fff',
|
604 |
+
'custom_border_colour' => '#ddd',
|
605 |
+
'custom_title_colour' => '#999',
|
606 |
+
'custom_link_colour' => '#428bca',
|
607 |
+
'custom_link_hover_colour' => '#2a6496',
|
608 |
+
'custom_link_visited_colour' => '#428bca',
|
609 |
+
'lowercase' => false,
|
610 |
+
'hyphenate' => false,
|
611 |
+
//'bullet_spacing' => false,
|
612 |
+
'include_homepage' => false,
|
613 |
+
'exclude_css' => false,
|
614 |
+
'exclude' => '',
|
615 |
+
'heading_levels' => array( '1', '2', '3', '4', '5', '6' ),
|
616 |
+
'restrict_path' => '',
|
617 |
+
'css_container_class' => '',
|
618 |
+
//'show_toc_in_widget_only' => false,
|
619 |
+
//'show_toc_in_widget_only_post_types' => array(),
|
620 |
+
'widget_affix_selector' => '',
|
621 |
+
);
|
622 |
+
|
623 |
+
return apply_filters( 'ez_toc_get_default_options', $defaults );
|
624 |
+
}
|
625 |
+
|
626 |
+
/**
|
627 |
+
* Get the default options array.
|
628 |
+
*
|
629 |
+
* @access private
|
630 |
+
* @since 1.0
|
631 |
+
* @static
|
632 |
+
*
|
633 |
+
* @return array
|
634 |
+
*/
|
635 |
+
private static function getOptions() {
|
636 |
+
|
637 |
+
$defaults = self::getDefaults();
|
638 |
+
$options = get_option( 'ez-toc-settings', $defaults );
|
639 |
+
|
640 |
+
//return apply_filters( 'ez_toc_get_options', wp_parse_args( $options, $defaults ) );
|
641 |
+
return apply_filters( 'ez_toc_get_options', $options );
|
642 |
+
}
|
643 |
+
|
644 |
+
/**
|
645 |
+
* Get option value by key name.
|
646 |
+
*
|
647 |
+
* @access public
|
648 |
+
* @since 1.0
|
649 |
+
* @static
|
650 |
+
*
|
651 |
+
* @param string $key
|
652 |
+
* @param bool|false $default
|
653 |
+
*
|
654 |
+
* @return mixed
|
655 |
+
*/
|
656 |
+
public static function get( $key, $default = false ) {
|
657 |
+
|
658 |
+
$options = self::getOptions();
|
659 |
+
|
660 |
+
$value = array_key_exists( $key, $options ) ? $options[ $key ] : $default;
|
661 |
+
$value = apply_filters( 'ez_toc_get_option', $value, $key, $default );
|
662 |
+
|
663 |
+
return apply_filters( 'ez_toc_get_option_' . $key, $value, $key, $default );
|
664 |
+
}
|
665 |
+
|
666 |
+
/**
|
667 |
+
* Set an option value by key name.
|
668 |
+
*
|
669 |
+
* @access public
|
670 |
+
* @since 1.0
|
671 |
+
* @static
|
672 |
+
*
|
673 |
+
* @param string $key
|
674 |
+
* @param bool|false $value
|
675 |
+
*
|
676 |
+
* @return bool
|
677 |
+
*/
|
678 |
+
public static function set( $key, $value = false ) {
|
679 |
+
|
680 |
+
if ( empty( $value ) ) {
|
681 |
+
|
682 |
+
$remove_option = self::delete( $key );
|
683 |
+
|
684 |
+
return $remove_option;
|
685 |
+
}
|
686 |
+
|
687 |
+
$options = self::getOptions();
|
688 |
+
|
689 |
+
$options[ $key ] = apply_filters( 'ez_toc_update_option', $value, $key );
|
690 |
+
|
691 |
+
return update_option( 'ez-toc-settings', $options );
|
692 |
+
}
|
693 |
+
|
694 |
+
/**
|
695 |
+
* Delete an option from the options table by option key name.
|
696 |
+
*
|
697 |
+
* @access public
|
698 |
+
* @since 1.0
|
699 |
+
* @static
|
700 |
+
*
|
701 |
+
* @param string $key
|
702 |
+
*
|
703 |
+
* @return bool
|
704 |
+
*/
|
705 |
+
public static function delete( $key ) {
|
706 |
+
|
707 |
+
// First let's grab the current settings
|
708 |
+
$options = get_option( 'ez-toc-settings' );
|
709 |
+
|
710 |
+
// Next let's try to update the value
|
711 |
+
if ( array_key_exists( $key, $options ) ) {
|
712 |
+
|
713 |
+
unset( $options[ $key ] );
|
714 |
+
}
|
715 |
+
|
716 |
+
return update_option( 'ez-toc-settings', $options );
|
717 |
+
}
|
718 |
+
|
719 |
+
/**
|
720 |
+
* Sanitize a hex color from user input.
|
721 |
+
*
|
722 |
+
* Tries to convert $string into a valid hex colour.
|
723 |
+
* Returns $default if $string is not a hex value, otherwise returns verified hex.
|
724 |
+
*
|
725 |
+
* @access private
|
726 |
+
* @since 1.0
|
727 |
+
* @static
|
728 |
+
*
|
729 |
+
* @param string $string
|
730 |
+
* @param string $default
|
731 |
+
*
|
732 |
+
* @return mixed|string
|
733 |
+
*/
|
734 |
+
private static function hex_value( $string = '', $default = '#' ) {
|
735 |
+
|
736 |
+
$return = $default;
|
737 |
+
|
738 |
+
if ( $string ) {
|
739 |
+
// strip out non hex chars
|
740 |
+
$return = preg_replace( '/[^a-fA-F0-9]*/', '', $string );
|
741 |
+
|
742 |
+
switch ( strlen( $return ) ) {
|
743 |
+
case 3: // do next
|
744 |
+
case 6:
|
745 |
+
$return = '#' . $return;
|
746 |
+
break;
|
747 |
+
|
748 |
+
default:
|
749 |
+
if ( strlen( $return ) > 6 ) {
|
750 |
+
$return = '#' . substr( $return, 0, 6 );
|
751 |
+
} // if > 6 chars, then take the first 6
|
752 |
+
elseif ( strlen( $return ) > 3 && strlen( $return ) < 6 ) {
|
753 |
+
$return = '#' . substr( $return, 0, 3 );
|
754 |
+
} // if between 3 and 6, then take first 3
|
755 |
+
else {
|
756 |
+
$return = $default;
|
757 |
+
} // not valid, return $default
|
758 |
+
}
|
759 |
+
}
|
760 |
+
|
761 |
+
return $return;
|
762 |
+
}
|
763 |
+
|
764 |
+
/**
|
765 |
+
* Get the registered post types minus excluded core types.
|
766 |
+
*
|
767 |
+
* @access public
|
768 |
+
* @since 1.0
|
769 |
+
* @static
|
770 |
+
*
|
771 |
+
* @return array
|
772 |
+
*/
|
773 |
+
public static function getPostTypes() {
|
774 |
+
|
775 |
+
$exclude = apply_filters( 'ez_toc_exclude_post_types', array( 'attachment', 'revision', 'nav_menu_item', 'safecss' ) );
|
776 |
+
$registered = get_post_types( array(), 'objects' );
|
777 |
+
$types = array();
|
778 |
+
|
779 |
+
foreach ( $registered as $post ) {
|
780 |
+
|
781 |
+
if ( in_array( $post->name, $exclude ) ) {
|
782 |
+
|
783 |
+
continue;
|
784 |
+
}
|
785 |
+
|
786 |
+
$types[ $post->name ] = $post->label;
|
787 |
+
}
|
788 |
+
|
789 |
+
return $types;
|
790 |
+
}
|
791 |
+
|
792 |
+
/**
|
793 |
+
* Missing Callback
|
794 |
+
*
|
795 |
+
* If a settings field type callback is not callable, alert the user.
|
796 |
+
*
|
797 |
+
* @access public
|
798 |
+
* @since 1.0
|
799 |
+
* @static
|
800 |
+
*
|
801 |
+
* @param array $args Arguments passed by the setting
|
802 |
+
*/
|
803 |
+
public static function missingCallback( $args ) {
|
804 |
+
|
805 |
+
printf(
|
806 |
+
__( 'The callback function used for the <strong>%s</strong> setting is missing.', 'easy-table-of-contents' ),
|
807 |
+
$args['id']
|
808 |
+
);
|
809 |
+
}
|
810 |
+
|
811 |
+
/**
|
812 |
+
* Text Callback
|
813 |
+
*
|
814 |
+
* Renders text fields.
|
815 |
+
*
|
816 |
+
* @access public
|
817 |
+
* @since 1.0
|
818 |
+
* @static
|
819 |
+
*
|
820 |
+
* @param array $args Arguments passed by the setting
|
821 |
+
* @param null $value
|
822 |
+
*/
|
823 |
+
public static function text( $args, $value = null ) {
|
824 |
+
|
825 |
+
if ( is_null( $value ) ) {
|
826 |
+
|
827 |
+
$value = self::get( $args['id'], $args['default'] );
|
828 |
+
}
|
829 |
+
|
830 |
+
if ( isset( $args['faux'] ) && true === $args['faux'] ) {
|
831 |
+
|
832 |
+
$args['readonly'] = true;
|
833 |
+
$value = isset( $args['default'] ) ? $args['default'] : '';
|
834 |
+
$name = '';
|
835 |
+
|
836 |
+
} else {
|
837 |
+
|
838 |
+
$name = ' name="ez-toc-settings[' . $args['id'] . ']"';
|
839 |
+
}
|
840 |
+
|
841 |
+
$readonly = isset( $args['readonly'] ) && $args['readonly'] === true ? ' readonly="readonly"' : '';
|
842 |
+
$size = isset( $args['size'] ) && ! is_null( $args['size'] ) ? $args['size'] : 'regular';
|
843 |
+
|
844 |
+
$html = '<input type="text" class="' . $size . '-text" id="ez-toc-settings[' . $args['id'] . ']"' . $name . ' value="' . esc_attr( stripslashes( $value ) ) . '"' . $readonly . '/>';
|
845 |
+
|
846 |
+
if ( 0 < strlen( $args['desc'] ) ) {
|
847 |
+
|
848 |
+
$html .= '<label for="ez-toc-settings[' . $args['id'] . ']"> ' . $args['desc'] . '</label>';
|
849 |
+
}
|
850 |
+
|
851 |
+
echo $html;
|
852 |
+
}
|
853 |
+
|
854 |
+
/**
|
855 |
+
* Textarea Callback.
|
856 |
+
*
|
857 |
+
* Renders a textarea.
|
858 |
+
*
|
859 |
+
* @access public
|
860 |
+
* @since 1.1
|
861 |
+
* @static
|
862 |
+
*
|
863 |
+
* @param array $args Arguments passed by the setting
|
864 |
+
* @param null $value
|
865 |
+
*/
|
866 |
+
public static function textarea( $args, $value = null ) {
|
867 |
+
|
868 |
+
$html = '';
|
869 |
+
|
870 |
+
if ( is_null( $value ) ) {
|
871 |
+
|
872 |
+
$value = self::get( $args['id'], $args['default'] );
|
873 |
+
}
|
874 |
+
|
875 |
+
if ( isset( $args['faux'] ) && true === $args['faux'] ) {
|
876 |
+
|
877 |
+
$args['readonly'] = true;
|
878 |
+
$value = isset( $args['default'] ) ? $args['default'] : '';
|
879 |
+
$name = '';
|
880 |
+
|
881 |
+
} else {
|
882 |
+
|
883 |
+
$name = ' name="ez-toc-settings[' . $args['id'] . ']"';
|
884 |
+
}
|
885 |
+
|
886 |
+
$readonly = isset( $args['readonly'] ) && $args['readonly'] === true ? ' readonly="readonly"' : '';
|
887 |
+
$size = isset( $args['size'] ) && ! is_null( $args['size'] ) ? $args['size'] : 'regular';
|
888 |
+
|
889 |
+
if ( 0 < strlen( $args['desc'] ) ) {
|
890 |
+
|
891 |
+
$html .= '<label for="ez-toc-settings[' . $args['id'] . ']"> ' . $args['desc'] . '</label>';
|
892 |
+
}
|
893 |
+
|
894 |
+
$html .= '<textarea rows="10" cols="50" class="' . $size . '-text" id="ez-toc-settings[' . $args['id'] . ']"' . $name . $readonly . '/>' . esc_textarea( $value ) . '</textarea>';
|
895 |
+
|
896 |
+
echo $html;
|
897 |
+
}
|
898 |
+
|
899 |
+
/**
|
900 |
+
* Number Callback
|
901 |
+
*
|
902 |
+
* Renders number fields.
|
903 |
+
*
|
904 |
+
* @access public
|
905 |
+
* @since 1.0
|
906 |
+
* @static
|
907 |
+
*
|
908 |
+
* @param array $args Arguments passed by the setting
|
909 |
+
*/
|
910 |
+
public static function number( $args ) {
|
911 |
+
|
912 |
+
$value = self::get( $args['id'], $args['default'] );
|
913 |
+
|
914 |
+
if ( isset( $args['faux'] ) && true === $args['faux'] ) {
|
915 |
+
|
916 |
+
$args['readonly'] = true;
|
917 |
+
$value = isset( $args['default'] ) ? $args['default'] : '';
|
918 |
+
$name = '';
|
919 |
+
|
920 |
+
} else {
|
921 |
+
|
922 |
+
$name = ' name="ez-toc-settings[' . $args['id'] . ']"';
|
923 |
+
}
|
924 |
+
|
925 |
+
$readonly = isset( $args['readonly'] ) && $args['readonly'] === true ? ' readonly="readonly"' : '';
|
926 |
+
$size = isset( $args['size'] ) && ! is_null( $args['size'] ) ? $args['size'] : 'regular';
|
927 |
+
|
928 |
+
$html = '<input type="number" class="' . $size . '-text" id="ez-toc-settings[' . $args['id'] . ']"' . $name . ' value="' . esc_attr( stripslashes( $value ) ) . '"' . $readonly . '/>';
|
929 |
+
|
930 |
+
if ( 0 < strlen( $args['desc'] ) ) {
|
931 |
+
|
932 |
+
$html .= '<label for="ez-toc-settings[' . $args['id'] . ']"> ' . $args['desc'] . '</label>';
|
933 |
+
}
|
934 |
+
|
935 |
+
echo $html;
|
936 |
+
}
|
937 |
+
|
938 |
+
/**
|
939 |
+
* Checkbox Callback
|
940 |
+
*
|
941 |
+
* Renders checkboxes.
|
942 |
+
*
|
943 |
+
* @access public
|
944 |
+
* @since 1.0
|
945 |
+
* @static
|
946 |
+
*
|
947 |
+
* @param array $args Arguments passed by the setting
|
948 |
+
* @param null $value
|
949 |
+
*/
|
950 |
+
public static function checkbox( $args, $value = null ) {
|
951 |
+
|
952 |
+
if ( is_null( $value ) ) {
|
953 |
+
|
954 |
+
$value = self::get( $args['id'], $args['default'] );
|
955 |
+
}
|
956 |
+
|
957 |
+
if ( isset( $args['faux'] ) && true === $args['faux'] ) {
|
958 |
+
|
959 |
+
$name = '';
|
960 |
+
|
961 |
+
} else {
|
962 |
+
|
963 |
+
$name = ' name="ez-toc-settings[' . $args['id'] . ']"';
|
964 |
+
}
|
965 |
+
|
966 |
+
$checked = $value ? checked( 1, $value, false ) : '';
|
967 |
+
|
968 |
+
$html = '<input type="checkbox" id="ez-toc-settings[' . $args['id'] . ']"' . $name . ' value="1" ' . $checked . '/>';
|
969 |
+
|
970 |
+
if ( 0 < strlen( $args['desc'] ) ) {
|
971 |
+
|
972 |
+
$html .= '<label for="ez-toc-settings[' . $args['id'] . ']"> ' . $args['desc'] . '</label>';
|
973 |
+
}
|
974 |
+
|
975 |
+
echo $html;
|
976 |
+
}
|
977 |
+
|
978 |
+
/**
|
979 |
+
* Multicheck Callback
|
980 |
+
*
|
981 |
+
* Renders multiple checkboxes.
|
982 |
+
*
|
983 |
+
* @access public
|
984 |
+
* @since 1.0
|
985 |
+
* @static
|
986 |
+
*
|
987 |
+
* @param array $args Arguments passed by the setting
|
988 |
+
* @param null $value
|
989 |
+
*/
|
990 |
+
public static function checkboxgroup( $args, $value = null ) {
|
991 |
+
|
992 |
+
if ( is_null( $value ) ) {
|
993 |
+
|
994 |
+
$value = self::get( $args['id'], $args['default'] );
|
995 |
+
}
|
996 |
+
|
997 |
+
if ( ! empty( $args['options'] ) ) {
|
998 |
+
|
999 |
+
foreach ( $args['options'] as $key => $option ):
|
1000 |
+
|
1001 |
+
if ( in_array( $key, $value ) ) {
|
1002 |
+
|
1003 |
+
$enabled = $option;
|
1004 |
+
|
1005 |
+
} else {
|
1006 |
+
|
1007 |
+
$enabled = null;
|
1008 |
+
}
|
1009 |
+
|
1010 |
+
echo '<input name="ez-toc-settings[' . $args['id'] . '][' . $key . ']" id="ez-toc-settings[' . $args['id'] . '][' . $key . ']" type="checkbox" value="' . $key . '" ' . checked( $option, $enabled, false ) . '/> ';
|
1011 |
+
echo '<label for="ez-toc-settings[' . $args['id'] . '][' . $key . ']">' . $option . '</label><br/>';
|
1012 |
+
|
1013 |
+
endforeach;
|
1014 |
+
|
1015 |
+
if ( 0 < strlen( $args['desc'] ) ) {
|
1016 |
+
|
1017 |
+
echo '<p class="description">' . $args['desc'] . '</p>';
|
1018 |
+
}
|
1019 |
+
}
|
1020 |
+
}
|
1021 |
+
|
1022 |
+
/**
|
1023 |
+
* Radio Callback
|
1024 |
+
*
|
1025 |
+
* Renders radio groups.
|
1026 |
+
*
|
1027 |
+
* @access public
|
1028 |
+
* @since 1.0
|
1029 |
+
* @static
|
1030 |
+
*
|
1031 |
+
* @param array $args Arguments passed by the setting
|
1032 |
+
*/
|
1033 |
+
public static function radio( $args ) {
|
1034 |
+
|
1035 |
+
$value = self::get( $args['id'], $args['default'] );
|
1036 |
+
|
1037 |
+
foreach ( $args['options'] as $key => $option ) {
|
1038 |
+
|
1039 |
+
echo '<input name="ez-toc-settings[' . $args['id'] . ']"" id="ez-toc-settings[' . $args['id'] . '][' . $key . ']" type="radio" value="' . $key . '" ' . checked( $key, $value, false ) . '/> ';
|
1040 |
+
echo '<label for="ez-toc-settings[' . $args['id'] . '][' . $key . ']">' . $option . '</label><br/>';
|
1041 |
+
}
|
1042 |
+
|
1043 |
+
if ( 0 < strlen( $args['desc'] ) ) {
|
1044 |
+
|
1045 |
+
echo '<p class="description">' . $args['desc'] . '</p>';
|
1046 |
+
}
|
1047 |
+
}
|
1048 |
+
|
1049 |
+
/**
|
1050 |
+
* Select Callback
|
1051 |
+
*
|
1052 |
+
* Renders select fields.
|
1053 |
+
*
|
1054 |
+
* @access public
|
1055 |
+
* @since 1.0
|
1056 |
+
* @static
|
1057 |
+
*
|
1058 |
+
* @param array $args Arguments passed by the setting.
|
1059 |
+
*/
|
1060 |
+
public static function select( $args ) {
|
1061 |
+
|
1062 |
+
$value = self::get( $args['id'], $args['default'] );
|
1063 |
+
|
1064 |
+
if ( isset( $args['placeholder'] ) ) {
|
1065 |
+
$placeholder = $args['placeholder'];
|
1066 |
+
} else {
|
1067 |
+
$placeholder = '';
|
1068 |
+
}
|
1069 |
+
|
1070 |
+
if ( isset( $args['chosen'] ) ) {
|
1071 |
+
$chosen = 'class="enhanced"';
|
1072 |
+
} else {
|
1073 |
+
$chosen = '';
|
1074 |
+
}
|
1075 |
+
|
1076 |
+
$html = '<select id="ez-toc-settings[' . $args['id'] . ']" name="ez-toc-settings[' . $args['id'] . ']" ' . $chosen . 'data-placeholder="' . $placeholder . '" />';
|
1077 |
+
|
1078 |
+
foreach ( $args['options'] as $option => $name ) {
|
1079 |
+
$selected = selected( $option, $value, false );
|
1080 |
+
$html .= '<option value="' . $option . '" ' . $selected . '>' . $name . '</option>';
|
1081 |
+
}
|
1082 |
+
|
1083 |
+
$html .= '</select>';
|
1084 |
+
|
1085 |
+
if ( 0 < strlen( $args['desc'] ) ) {
|
1086 |
+
|
1087 |
+
$html .= '<label for="ez-toc-settings[' . $args['id'] . ']"> ' . $args['desc'] . '</label>';
|
1088 |
+
}
|
1089 |
+
|
1090 |
+
echo $html;
|
1091 |
+
}
|
1092 |
+
|
1093 |
+
/**
|
1094 |
+
* Select Drop Down Callback
|
1095 |
+
*
|
1096 |
+
* Renders select with option group fields.
|
1097 |
+
*
|
1098 |
+
* @access public
|
1099 |
+
* @since 1.0
|
1100 |
+
* @static
|
1101 |
+
*
|
1102 |
+
* @param array $args Arguments passed by the setting.
|
1103 |
+
*/
|
1104 |
+
public static function selectgroup( $args ) {
|
1105 |
+
|
1106 |
+
$value = self::get( $args['id'], $args['default'] );
|
1107 |
+
|
1108 |
+
if ( isset( $args['placeholder'] ) ) {
|
1109 |
+
$placeholder = $args['placeholder'];
|
1110 |
+
} else {
|
1111 |
+
$placeholder = '';
|
1112 |
+
}
|
1113 |
+
|
1114 |
+
if ( isset( $args['chosen'] ) ) {
|
1115 |
+
$chosen = 'class="enhanced"';
|
1116 |
+
} else {
|
1117 |
+
$chosen = '';
|
1118 |
+
}
|
1119 |
+
|
1120 |
+
$html = '<select id="ez-toc-settings[' . $args['id'] . ']" name="ez-toc-settings[' . $args['id'] . ']" ' . $chosen . 'data-placeholder="' . $placeholder . '" />';
|
1121 |
+
|
1122 |
+
foreach ( $args['options'] as $group ) {
|
1123 |
+
|
1124 |
+
$html .= sprintf( '<optgroup label="%1$s">', $group['name'] );
|
1125 |
+
|
1126 |
+
foreach ( $group['options'] as $option => $name ) {
|
1127 |
+
|
1128 |
+
$selected = selected( $option, $value, false );
|
1129 |
+
$html .= '<option value="' . $option . '" ' . $selected . '>' . $name . '</option>';
|
1130 |
+
}
|
1131 |
+
|
1132 |
+
$html .= '</optgroup>';
|
1133 |
+
}
|
1134 |
+
|
1135 |
+
$html .= '</select>';
|
1136 |
+
|
1137 |
+
if ( 0 < strlen( $args['desc'] ) ) {
|
1138 |
+
|
1139 |
+
$html .= '<label for="ez-toc-settings[' . $args['id'] . ']"> ' . $args['desc'] . '</label>';
|
1140 |
+
}
|
1141 |
+
|
1142 |
+
echo $html;
|
1143 |
+
}
|
1144 |
+
|
1145 |
+
/**
|
1146 |
+
* Header Callback
|
1147 |
+
*
|
1148 |
+
* Renders the header.
|
1149 |
+
*
|
1150 |
+
* @access public
|
1151 |
+
* @since 1.0
|
1152 |
+
* @static
|
1153 |
+
*
|
1154 |
+
* @param array $args Arguments passed by the setting
|
1155 |
+
*/
|
1156 |
+
public static function header( $args ) {
|
1157 |
+
|
1158 |
+
echo '<hr/>';
|
1159 |
+
|
1160 |
+
if ( 0 < strlen( $args['desc'] ) ) {
|
1161 |
+
|
1162 |
+
echo '<p>' . wp_kses_post( $args['desc'] ) . '</p>';
|
1163 |
+
}
|
1164 |
+
}
|
1165 |
+
|
1166 |
+
/**
|
1167 |
+
* Descriptive text callback.
|
1168 |
+
*
|
1169 |
+
* Renders descriptive text onto the settings field.
|
1170 |
+
*
|
1171 |
+
* @access public
|
1172 |
+
* @since 1.0
|
1173 |
+
* @static
|
1174 |
+
*
|
1175 |
+
* @param array $args Arguments passed by the setting
|
1176 |
+
*/
|
1177 |
+
public static function descriptive_text( $args ) {
|
1178 |
+
|
1179 |
+
echo wp_kses_post( $args['desc'] );
|
1180 |
+
}
|
1181 |
+
|
1182 |
+
/**
|
1183 |
+
* Color picker Callback
|
1184 |
+
*
|
1185 |
+
* Renders color picker fields.
|
1186 |
+
*
|
1187 |
+
* @access public
|
1188 |
+
* @since 1.0
|
1189 |
+
* @static
|
1190 |
+
*
|
1191 |
+
* @param array $args Arguments passed by the setting
|
1192 |
+
*/
|
1193 |
+
public static function color( $args ) {
|
1194 |
+
|
1195 |
+
$value = self::get( $args['id'], $args['default'] );
|
1196 |
+
|
1197 |
+
$default = isset( $args['default'] ) ? $args['default'] : '';
|
1198 |
+
|
1199 |
+
$html = '<input type="text" class="ez-toc-color-picker" id="ez-toc-settings[' . $args['id'] . ']" name="ez-toc-settings[' . $args['id'] . ']" value="' . esc_attr( $value ) . '" data-default-color="' . esc_attr( $default ) . '" />';
|
1200 |
+
|
1201 |
+
if ( 0 < strlen( $args['desc'] ) ) {
|
1202 |
+
|
1203 |
+
echo '<label for="ez-toc-settings[' . $args['id'] . ']"> ' . $args['desc'] . '</label>';
|
1204 |
+
}
|
1205 |
+
|
1206 |
+
echo $html;
|
1207 |
+
}
|
1208 |
+
|
1209 |
+
/**
|
1210 |
+
* Custom table of contents width.
|
1211 |
+
*
|
1212 |
+
* @access public
|
1213 |
+
* @since 1.0
|
1214 |
+
* @static
|
1215 |
+
*
|
1216 |
+
* @param array $args
|
1217 |
+
*/
|
1218 |
+
public static function custom_width( $args ) {
|
1219 |
+
|
1220 |
+
//$value = self::get( $args['id'], $args['default'] );
|
1221 |
+
|
1222 |
+
self::text(
|
1223 |
+
array(
|
1224 |
+
'id' => $args['id'],
|
1225 |
+
'desc' => '',
|
1226 |
+
'size' => 'small',
|
1227 |
+
'default' => $args['default'],
|
1228 |
+
)
|
1229 |
+
);
|
1230 |
+
|
1231 |
+
self::select(
|
1232 |
+
array(
|
1233 |
+
'id' => $args['id'] . '_units',
|
1234 |
+
'desc' => '',
|
1235 |
+
'options' => array(
|
1236 |
+
'px' => 'px',
|
1237 |
+
'%' => '%',
|
1238 |
+
'em' => 'em',
|
1239 |
+
),
|
1240 |
+
'default' => 'px',
|
1241 |
+
)
|
1242 |
+
);
|
1243 |
+
|
1244 |
+
if ( 0 < strlen( $args['desc'] ) ) {
|
1245 |
+
|
1246 |
+
echo '<label for="ez-toc-settings[' . $args['id'] . ']"> ' . $args['desc'] . '</label>';
|
1247 |
+
}
|
1248 |
+
}
|
1249 |
+
|
1250 |
+
/**
|
1251 |
+
* Custom font size callback.
|
1252 |
+
*
|
1253 |
+
* @access public
|
1254 |
+
* @since 1.0
|
1255 |
+
* @static
|
1256 |
+
*
|
1257 |
+
* @param array $args
|
1258 |
+
*/
|
1259 |
+
public static function font_size( $args ) {
|
1260 |
+
|
1261 |
+
//$value = self::get( $args['id'], $args['default'] );
|
1262 |
+
|
1263 |
+
self::text(
|
1264 |
+
array(
|
1265 |
+
'id' => $args['id'],
|
1266 |
+
'desc' => '',
|
1267 |
+
'size' => 'small',
|
1268 |
+
'default' => $args['default'],
|
1269 |
+
)
|
1270 |
+
);
|
1271 |
+
|
1272 |
+
self::select(
|
1273 |
+
array(
|
1274 |
+
'id' => $args['id'] . '_units',
|
1275 |
+
'desc' => '',
|
1276 |
+
'options' => array(
|
1277 |
+
'pt' => 'pt',
|
1278 |
+
'px' => 'px',
|
1279 |
+
'%' => '%',
|
1280 |
+
'em' => 'em',
|
1281 |
+
),
|
1282 |
+
'default' => '%',
|
1283 |
+
)
|
1284 |
+
);
|
1285 |
+
|
1286 |
+
if ( 0 < strlen( $args['desc'] ) ) {
|
1287 |
+
|
1288 |
+
echo '<label for="ez-toc-settings[' . $args['id'] . ']"> ' . $args['desc'] . '</label>';
|
1289 |
+
}
|
1290 |
+
}
|
1291 |
+
}
|
1292 |
+
|
1293 |
+
add_action( 'admin_init', array( 'ezTOC_Option', 'register' ) );
|
1294 |
+
}
|
includes/class.post.php
CHANGED
@@ -1,1405 +1,1415 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
use function Easy_Plugins\Table_Of_Contents\String\br2;
|
4 |
-
|
5 |
-
class ezTOC_Post {
|
6 |
-
|
7 |
-
/**
|
8 |
-
* @since 2.0
|
9 |
-
* @var int
|
10 |
-
*/
|
11 |
-
private $queriedObjectID;
|
12 |
-
|
13 |
-
/**
|
14 |
-
* @since 2.0
|
15 |
-
* @var WP_Post
|
16 |
-
*/
|
17 |
-
private $post;
|
18 |
-
|
19 |
-
/**
|
20 |
-
* @since 2.0
|
21 |
-
* @var false|string
|
22 |
-
*/
|
23 |
-
private $permalink;
|
24 |
-
|
25 |
-
/**
|
26 |
-
* The post content broken into pages by user inserting `<!--nextpage-->` into the post content.
|
27 |
-
* @see ezTOC_Post::extractPages()
|
28 |
-
* @since 2.0
|
29 |
-
* @var array
|
30 |
-
*/
|
31 |
-
private $pages = array();
|
32 |
-
|
33 |
-
/**
|
34 |
-
* The user defined heading levels to be included in the TOC.
|
35 |
-
* @see ezTOC_Post::getHeadingLevels()
|
36 |
-
* @since 2.0
|
37 |
-
* @var array
|
38 |
-
*/
|
39 |
-
private $headingLevels = array();
|
40 |
-
|
41 |
-
/**
|
42 |
-
* Array of nodes that are excluded by class/id selector.
|
43 |
-
* @since 2.0
|
44 |
-
* @var string[]
|
45 |
-
*/
|
46 |
-
private $excludedNodes = array();
|
47 |
-
|
48 |
-
/**
|
49 |
-
* Keeps a track of used anchors for collision detecting.
|
50 |
-
* @see ezTOC_Post::generateHeadingIDFromTitle()
|
51 |
-
* @since 2.0
|
52 |
-
* @var array
|
53 |
-
*/
|
54 |
-
private $collision_collector = array();
|
55 |
-
|
56 |
-
/**
|
57 |
-
* @var bool
|
58 |
-
*/
|
59 |
-
private $hasTOCItems = false;
|
60 |
-
|
61 |
-
/**
|
62 |
-
* ezTOC_Post constructor.
|
63 |
-
*
|
64 |
-
* @since 2.0
|
65 |
-
*
|
66 |
-
* @param WP_Post $post
|
67 |
-
* @param bool $apply_content_filter Whether or not to apply the `the_content` filter on the post content.
|
68 |
-
*/
|
69 |
-
public function __construct( WP_Post $post, $apply_content_filter = true ) {
|
70 |
-
|
71 |
-
$this->post = $post;
|
72 |
-
$this->permalink = get_permalink( $post );
|
73 |
-
$this->queriedObjectID = get_queried_object_id();
|
74 |
-
|
75 |
-
if ( $apply_content_filter ) {
|
76 |
-
|
77 |
-
$this->applyContentFilter()->process();
|
78 |
-
|
79 |
-
} else {
|
80 |
-
|
81 |
-
$this->process();
|
82 |
-
}
|
83 |
-
}
|
84 |
-
|
85 |
-
/**
|
86 |
-
* @access public
|
87 |
-
* @since 2.0
|
88 |
-
*
|
89 |
-
* @param $id
|
90 |
-
*
|
91 |
-
* @return ezTOC_Post|null
|
92 |
-
*/
|
93 |
-
public static function get( $id ) {
|
94 |
-
|
95 |
-
$post = get_post( $id );
|
96 |
-
|
97 |
-
if ( ! $post instanceof WP_Post ) {
|
98 |
-
|
99 |
-
return null;
|
100 |
-
}
|
101 |
-
|
102 |
-
return new static( $post );
|
103 |
-
}
|
104 |
-
|
105 |
-
/**
|
106 |
-
* Process post content for headings.
|
107 |
-
*
|
108 |
-
* This must be run after object init or after @see ezTOC_Post::applyContentFilter().
|
109 |
-
*
|
110 |
-
* @since 2.0
|
111 |
-
*
|
112 |
-
* @return static
|
113 |
-
*/
|
114 |
-
private function process() {
|
115 |
-
|
116 |
-
$this->processPages();
|
117 |
-
|
118 |
-
return $this;
|
119 |
-
}
|
120 |
-
|
121 |
-
/**
|
122 |
-
* Apply `the_content` filter to the post content.
|
123 |
-
*
|
124 |
-
* @since 2.0
|
125 |
-
*
|
126 |
-
* @return static
|
127 |
-
*/
|
128 |
-
private function applyContentFilter() {
|
129 |
-
|
130 |
-
add_filter( 'strip_shortcodes_tagnames', array( __CLASS__, 'stripShortcodes' ), 10, 2 );
|
131 |
-
|
132 |
-
/*
|
133 |
-
* Ensure the ezTOC content filter is not applied when running `the_content` filter.
|
134 |
-
*/
|
135 |
-
remove_filter( 'the_content', array( 'ezTOC', 'the_content' ), 100 );
|
136 |
-
|
137 |
-
$this->post->post_content = apply_filters( 'the_content', strip_shortcodes( $this->post->post_content ) );
|
138 |
-
|
139 |
-
add_filter( 'the_content', array( 'ezTOC', 'the_content' ), 100 );
|
140 |
-
|
141 |
-
remove_filter( 'strip_shortcodes_tagnames', array( __CLASS__, 'stripShortcodes' ) );
|
142 |
-
|
143 |
-
return $this;
|
144 |
-
}
|
145 |
-
|
146 |
-
/**
|
147 |
-
* Callback for the `strip_shortcodes_tagnames` filter.
|
148 |
-
*
|
149 |
-
* Strip the shortcodes so their content is no processed for headings.
|
150 |
-
*
|
151 |
-
* @see ezTOC_Post::applyContentFilter()
|
152 |
-
*
|
153 |
-
* @since 2.0
|
154 |
-
*
|
155 |
-
* @param array $tags_to_remove Array of shortcode tags to remove.
|
156 |
-
* @param string $content Content shortcodes are being removed from.
|
157 |
-
*
|
158 |
-
* @return array
|
159 |
-
*/
|
160 |
-
public static function stripShortcodes( $tags_to_remove, $content ) {
|
161 |
-
|
162 |
-
//error_log( var_export( $tags_to_remove, true ) );
|
163 |
-
|
164 |
-
/*
|
165 |
-
* Ensure the ezTOC shortcodes are not processed when applying `the_content` filter
|
166 |
-
* otherwise an infinite loop may occur.
|
167 |
-
*/
|
168 |
-
$tags_to_remove = apply_filters(
|
169 |
-
'ez_toc_strip_shortcodes_tagnames',
|
170 |
-
array(
|
171 |
-
'ez-toc',
|
172 |
-
apply_filters( 'ez_toc_shortcode', 'toc' ),
|
173 |
-
),
|
174 |
-
$content
|
175 |
-
);
|
176 |
-
|
177 |
-
//error_log( var_export( $tags_to_remove, true ) );
|
178 |
-
|
179 |
-
return $tags_to_remove;
|
180 |
-
}
|
181 |
-
|
182 |
-
/**
|
183 |
-
* This is a work around for theme's and plugins
|
184 |
-
* which break the WordPress global $wp_query var by unsetting it
|
185 |
-
* or overwriting it which breaks the method call
|
186 |
-
* that `get_query_var()` uses to return the query variable.
|
187 |
-
*
|
188 |
-
* @access protected
|
189 |
-
* @since 2.0
|
190 |
-
*
|
191 |
-
* @return int
|
192 |
-
*/
|
193 |
-
protected function getCurrentPage() {
|
194 |
-
|
195 |
-
global $wp_query;
|
196 |
-
|
197 |
-
// Check to see if the global `$wp_query` var is an instance of WP_Query and that the get() method is callable.
|
198 |
-
// If it is then when can simply use the get_query_var() function.
|
199 |
-
if ( $wp_query instanceof WP_Query && is_callable( array( $wp_query, 'get' ) ) ) {
|
200 |
-
|
201 |
-
$page = get_query_var( 'page', 1 );
|
202 |
-
|
203 |
-
return 1 > $page ? 1 : $page;
|
204 |
-
|
205 |
-
// If a theme or plugin broke the global `$wp_query` var, check to see if the $var was parsed and saved in $GLOBALS['wp_query']->query_vars.
|
206 |
-
} elseif ( isset( $GLOBALS['wp_query']->query_vars[ 'page' ] ) ) {
|
207 |
-
|
208 |
-
return $GLOBALS['wp_query']->query_vars[ 'page' ];
|
209 |
-
|
210 |
-
// We should not reach this, but if we do, lets check the original parsed query vars in $GLOBALS['wp_the_query']->query_vars.
|
211 |
-
} elseif ( isset( $GLOBALS['wp_the_query']->query_vars[ 'page' ] ) ) {
|
212 |
-
|
213 |
-
return $GLOBALS['wp_the_query']->query_vars[ 'page' ];
|
214 |
-
|
215 |
-
// Ok, if all else fails, check the $_REQUEST super global.
|
216 |
-
} elseif ( isset( $_REQUEST[ 'page' ] ) ) {
|
217 |
-
|
218 |
-
return $_REQUEST[ 'page' ];
|
219 |
-
}
|
220 |
-
|
221 |
-
// Finally, return the $default if it was supplied.
|
222 |
-
return 1;
|
223 |
-
}
|
224 |
-
|
225 |
-
/**
|
226 |
-
* Get the number of page the post has.
|
227 |
-
*
|
228 |
-
* @access protected
|
229 |
-
* @since 2.0
|
230 |
-
*
|
231 |
-
* @return int
|
232 |
-
*/
|
233 |
-
protected function getNumberOfPages() {
|
234 |
-
|
235 |
-
return count( $this->pages );
|
236 |
-
}
|
237 |
-
|
238 |
-
/**
|
239 |
-
* Whether or not the post has multiple pages.
|
240 |
-
*
|
241 |
-
* @access protected
|
242 |
-
* @since 2.0
|
243 |
-
*
|
244 |
-
* @return bool
|
245 |
-
*/
|
246 |
-
protected function isMultipage() {
|
247 |
-
|
248 |
-
return 1 < $this->getNumberOfPages();
|
249 |
-
}
|
250 |
-
|
251 |
-
/**
|
252 |
-
* Parse the post content and headings.
|
253 |
-
*
|
254 |
-
* @access private
|
255 |
-
* @since 2.0
|
256 |
-
*/
|
257 |
-
private function processPages() {
|
258 |
-
|
259 |
-
//if ( ! class_exists( 'TagFilter' ) ) {
|
260 |
-
//
|
261 |
-
// require_once( EZ_TOC_PATH . '/includes/vendor/ultimate-web-scraper/tag_filter.php' );
|
262 |
-
//}
|
263 |
-
|
264 |
-
$split = preg_split( '/<!--nextpage-->/msuU', $this->post->post_content );
|
265 |
-
$pages = array();
|
266 |
-
|
267 |
-
if ( is_array( $split ) ) {
|
268 |
-
|
269 |
-
$page = 1;
|
270 |
-
|
271 |
-
//$tagFilterOptions = TagFilter::GetHTMLOptions();
|
272 |
-
|
273 |
-
//// Set custom TagFilter options.
|
274 |
-
//$tagFilterOptions['charset'] = get_option( 'blog_charset' );
|
275 |
-
////$tagFilterOptions['output_mode'] = 'xml';
|
276 |
-
|
277 |
-
foreach ( $split as $content ) {
|
278 |
-
|
279 |
-
//$html = TagFilter::Explode( $content, $tagFilterOptions );
|
280 |
-
//
|
281 |
-
///**
|
282 |
-
// * @since 2.0
|
283 |
-
// *
|
284 |
-
// * @param $selectors array Array of classes/id selector to exclude from TOC.
|
285 |
-
// * @param $content string Post content.
|
286 |
-
// */
|
287 |
-
//$selectors = apply_filters( 'ez_toc_exclude_by_selector', array(), $content );
|
288 |
-
//
|
289 |
-
//$nodes = $html->Find( implode( ',', $selectors ) );
|
290 |
-
//
|
291 |
-
//foreach ( $nodes['ids'] as $id ) {
|
292 |
-
//
|
293 |
-
// $html->Remove( $id );
|
294 |
-
//}
|
295 |
-
//
|
296 |
-
//$eligibleContent = $html->Implode( 0, $tagFilterOptions );
|
297 |
-
//
|
298 |
-
///**
|
299 |
-
// * TagFilter::Implode() writes br tags as `<br>` while WP normalizes to `<br />`.
|
300 |
-
// * Normalize `$eligibleContent` to match WP.
|
301 |
-
// *
|
302 |
-
// * @see wpautop()
|
303 |
-
// */
|
304 |
-
////$eligibleContent = str_replace( array( '<br>', '<br/>' ), array( '<br />' ), $eligibleContent );
|
305 |
-
//$eligibleContent = \Easy_Plugins\Table_Of_Contents\String\force_balance_tags( $eligibleContent );
|
306 |
-
|
307 |
-
$this->extractExcludedNodes( $page, $content );
|
308 |
-
|
309 |
-
$pages[ $page ] = array(
|
310 |
-
'headings' => $this->extractHeadings( $content ),
|
311 |
-
'content' => $content,
|
312 |
-
);
|
313 |
-
|
314 |
-
$page++;
|
315 |
-
}
|
316 |
-
|
317 |
-
}
|
318 |
-
|
319 |
-
$this->pages = $pages;
|
320 |
-
}
|
321 |
-
|
322 |
-
/**
|
323 |
-
* Get the post's parse content and headings.
|
324 |
-
*
|
325 |
-
* @access public
|
326 |
-
* @since 2.0
|
327 |
-
*
|
328 |
-
* @return array
|
329 |
-
*/
|
330 |
-
public function getPages() {
|
331 |
-
|
332 |
-
return $this->pages;
|
333 |
-
}
|
334 |
-
|
335 |
-
/**
|
336 |
-
* Extract nodes that heading are to be excluded.
|
337 |
-
*
|
338 |
-
* @since 2.0
|
339 |
-
*
|
340 |
-
* @param int $page
|
341 |
-
* @param string $content
|
342 |
-
*/
|
343 |
-
private function extractExcludedNodes( $page, $content ) {
|
344 |
-
|
345 |
-
if ( ! class_exists( 'TagFilter' ) ) {
|
346 |
-
|
347 |
-
require_once( EZ_TOC_PATH . '/includes/vendor/ultimate-web-scraper/tag_filter.php' );
|
348 |
-
}
|
349 |
-
|
350 |
-
$tagFilterOptions = TagFilter::GetHTMLOptions();
|
351 |
-
|
352 |
-
// Set custom TagFilter options.
|
353 |
-
$tagFilterOptions['charset'] = get_option( 'blog_charset' );
|
354 |
-
//$tagFilterOptions['output_mode'] = 'xml';
|
355 |
-
|
356 |
-
$html = TagFilter::Explode( $content, $tagFilterOptions );
|
357 |
-
|
358 |
-
/**
|
359 |
-
* @since 2.0
|
360 |
-
*
|
361 |
-
* @param $selectors array Array of classes/id selector to exclude from TOC.
|
362 |
-
* @param $content string Post content.
|
363 |
-
*/
|
364 |
-
$selectors = apply_filters( 'ez_toc_exclude_by_selector', array( '.ez-toc-exclude-headings' ), $content );
|
365 |
-
|
366 |
-
$nodes = $html->Find( implode( ',', $selectors ) );
|
367 |
-
|
368 |
-
foreach ( $nodes['ids'] as $id ) {
|
369 |
-
|
370 |
-
//$this->excludedNodes[ $page ][ $id ] = $html->Implode( $id, $tagFilterOptions );
|
371 |
-
array_push( $this->excludedNodes, $html->Implode( $id, $tagFilterOptions ) );
|
372 |
-
}
|
373 |
-
|
374 |
-
//$eligibleContent = $html->Implode( 0, $tagFilterOptions );
|
375 |
-
|
376 |
-
/**
|
377 |
-
* TagFilter::Implode() writes br tags as `<br>` while WP normalizes to `<br />`.
|
378 |
-
* Normalize `$eligibleContent` to match WP.
|
379 |
-
*
|
380 |
-
* @see wpautop()
|
381 |
-
*/
|
382 |
-
//$eligibleContent = \Easy_Plugins\Table_Of_Contents\String\force_balance_tags( $eligibleContent );
|
383 |
-
}
|
384 |
-
|
385 |
-
/**
|
386 |
-
* Extract the posts content for headings.
|
387 |
-
*
|
388 |
-
* @access private
|
389 |
-
* @since 2.0
|
390 |
-
*
|
391 |
-
* @param string $content
|
392 |
-
*
|
393 |
-
* @return array
|
394 |
-
*/
|
395 |
-
private function extractHeadings( $content ) {
|
396 |
-
|
397 |
-
$matches = array();
|
398 |
-
|
399 |
-
// reset the internal collision collection as the_content may have been triggered elsewhere
|
400 |
-
// eg by themes or other plugins that need to read in content such as metadata fields in
|
401 |
-
// the head html tag, or to provide descriptions to twitter/facebook
|
402 |
-
/** @todo does this need to be used??? */
|
403 |
-
//self::$collision_collector = array();
|
404 |
-
|
405 |
-
$content = apply_filters( 'ez_toc_extract_headings_content', wptexturize( $content ) );
|
406 |
-
|
407 |
-
// get all headings
|
408 |
-
// the html spec allows for a maximum of 6 heading depths
|
409 |
-
if ( preg_match_all( '/(<h([1-6]{1})[^>]*>)(.*)<\/h\2>/msuU', $content, $matches, PREG_SET_ORDER ) ) {
|
410 |
-
|
411 |
-
$minimum = absint( ezTOC_Option::get( 'start' ) );
|
412 |
-
|
413 |
-
$this->removeHeadingsFromExcludedNodes( $matches );
|
414 |
-
$this->removeHeadings( $matches );
|
415 |
-
$this->excludeHeadings( $matches );
|
416 |
-
$this->removeEmptyHeadings( $matches );
|
417 |
-
|
418 |
-
if ( count( $matches ) >= $minimum ) {
|
419 |
-
|
420 |
-
$this->alternateHeadings( $matches );
|
421 |
-
$this->headingIDs( $matches );
|
422 |
-
$this->hasTOCItems = true;
|
423 |
-
|
424 |
-
} else {
|
425 |
-
|
426 |
-
return array();
|
427 |
-
}
|
428 |
-
|
429 |
-
}
|
430 |
-
|
431 |
-
return array_values( $matches ); // Rest the array index.
|
432 |
-
}
|
433 |
-
|
434 |
-
/**
|
435 |
-
* Whether or not the string is in one of the excluded nodes.
|
436 |
-
*
|
437 |
-
* @since 2.0
|
438 |
-
*
|
439 |
-
* @param string $string
|
440 |
-
*
|
441 |
-
* @return bool
|
442 |
-
*/
|
443 |
-
private function inExcludedNode( $string ) {
|
444 |
-
|
445 |
-
foreach ( $this->excludedNodes as $node ) {
|
446 |
-
|
447 |
-
if ( empty( $node ) || empty( $string ) ) {
|
448 |
-
|
449 |
-
return false;
|
450 |
-
}
|
451 |
-
|
452 |
-
if ( false !== strpos( $node, $string ) ) {
|
453 |
-
|
454 |
-
return true;
|
455 |
-
}
|
456 |
-
}
|
457 |
-
|
458 |
-
return false;
|
459 |
-
}
|
460 |
-
|
461 |
-
/**
|
462 |
-
* Remove headings that are in excluded nodes.
|
463 |
-
*
|
464 |
-
* @since 2.0
|
465 |
-
*
|
466 |
-
* @param array $matches
|
467 |
-
*
|
468 |
-
* @return array
|
469 |
-
*/
|
470 |
-
private function removeHeadingsFromExcludedNodes( &$matches ) {
|
471 |
-
|
472 |
-
foreach ( $matches as $i => $match ) {
|
473 |
-
|
474 |
-
if ( $this->inExcludedNode( "{$match[3]}</h$match[2]>" ) ) {
|
475 |
-
|
476 |
-
unset( $matches[ $i ] );
|
477 |
-
}
|
478 |
-
}
|
479 |
-
|
480 |
-
return $matches;
|
481 |
-
}
|
482 |
-
|
483 |
-
/**
|
484 |
-
* Get the heading levels to be included in the TOC.
|
485 |
-
*
|
486 |
-
* @access private
|
487 |
-
* @since 2.0
|
488 |
-
*
|
489 |
-
* @return array
|
490 |
-
*/
|
491 |
-
private function getHeadingLevels() {
|
492 |
-
|
493 |
-
$levels = get_post_meta( $this->post->ID, '_ez-toc-heading-levels', true );
|
494 |
-
|
495 |
-
if ( ! is_array( $levels ) ) {
|
496 |
-
|
497 |
-
$levels = array();
|
498 |
-
}
|
499 |
-
|
500 |
-
if ( empty( $levels ) ) {
|
501 |
-
|
502 |
-
$levels = ezTOC_Option::get( 'heading_levels', array() );
|
503 |
-
}
|
504 |
-
|
505 |
-
$this->headingLevels = $levels;
|
506 |
-
|
507 |
-
return $this->headingLevels;
|
508 |
-
}
|
509 |
-
|
510 |
-
/**
|
511 |
-
* Remove the heading levels as defined by user settings from the TOC heading matches.
|
512 |
-
*
|
513 |
-
* @see ezTOC_Post::extractHeadings()
|
514 |
-
*
|
515 |
-
* @access private
|
516 |
-
* @since 2.0
|
517 |
-
*
|
518 |
-
* @param array $matches The heading from the post content extracted with preg_match_all().
|
519 |
-
*
|
520 |
-
* @return array
|
521 |
-
*/
|
522 |
-
private function removeHeadings( &$matches ) {
|
523 |
-
|
524 |
-
$levels = $this->getHeadingLevels();
|
525 |
-
|
526 |
-
if ( count( $levels ) != 6 ) {
|
527 |
-
|
528 |
-
$new_matches = array();
|
529 |
-
//$count = count( $matches );
|
530 |
-
|
531 |
-
//for ( $i = 0; $i < $count; $i++ ) {
|
532 |
-
foreach ( $matches as $i => $match ) {
|
533 |
-
|
534 |
-
if ( in_array( $matches[ $i ][2], $levels ) ) {
|
535 |
-
|
536 |
-
$new_matches[ $i ] = $matches[ $i ];
|
537 |
-
}
|
538 |
-
}
|
539 |
-
|
540 |
-
$matches = $new_matches;
|
541 |
-
}
|
542 |
-
|
543 |
-
return $matches;
|
544 |
-
}
|
545 |
-
|
546 |
-
/**
|
547 |
-
* Exclude the heading, by title, as defined by the user settings from the TOC matches.
|
548 |
-
*
|
549 |
-
* @see ezTOC_Post::extractHeadings()
|
550 |
-
*
|
551 |
-
* @access private
|
552 |
-
* @since 2.0
|
553 |
-
*
|
554 |
-
* @param array $matches The headings from the post content extracted with preg_match_all().
|
555 |
-
*
|
556 |
-
* @return array
|
557 |
-
*/
|
558 |
-
private function excludeHeadings( &$matches ) {
|
559 |
-
|
560 |
-
$exclude = get_post_meta( $this->post->ID, '_ez-toc-exclude', true );
|
561 |
-
|
562 |
-
if ( empty( $exclude ) ) {
|
563 |
-
|
564 |
-
$exclude = ezTOC_Option::get( 'exclude' );
|
565 |
-
}
|
566 |
-
|
567 |
-
if ( $exclude ) {
|
568 |
-
|
569 |
-
$excluded_headings = explode( '|', $exclude );
|
570 |
-
$excluded_count = count( $excluded_headings );
|
571 |
-
|
572 |
-
if ( $excluded_count > 0 ) {
|
573 |
-
|
574 |
-
for ( $j = 0; $j < $excluded_count; $j++ ) {
|
575 |
-
|
576 |
-
$excluded_headings[ $j ] = preg_quote( $excluded_headings[ $j ] );
|
577 |
-
|
578 |
-
// escape some regular expression characters
|
579 |
-
// others: http://www.php.net/manual/en/regexp.reference.meta.php
|
580 |
-
$excluded_headings[ $j ] = str_replace(
|
581 |
-
array( '\*', '/', '%' ),
|
582 |
-
array( '.*', '\/', '\%' ),
|
583 |
-
trim( $excluded_headings[ $j ] )
|
584 |
-
);
|
585 |
-
}
|
586 |
-
|
587 |
-
$new_matches = array();
|
588 |
-
//$count = count( $matches );
|
589 |
-
|
590 |
-
//for ( $i = 0; $i < $count; $i++ ) {
|
591 |
-
foreach ( $matches as $i => $match ) {
|
592 |
-
|
593 |
-
$found = false;
|
594 |
-
|
595 |
-
$against = html_entity_decode(
|
596 |
-
wptexturize( strip_tags( str_replace( array( "\r", "\n" ), ' ', $matches[ $i ][0] ) ) ),
|
597 |
-
ENT_NOQUOTES,
|
598 |
-
get_option( 'blog_charset' )
|
599 |
-
);
|
600 |
-
|
601 |
-
for ( $j = 0; $j < $excluded_count; $j++ ) {
|
602 |
-
|
603 |
-
// Since WP manipulates the post content it is required that the excluded header and
|
604 |
-
// the actual header be manipulated similarly so a match can be made.
|
605 |
-
$pattern = html_entity_decode(
|
606 |
-
wptexturize( $excluded_headings[ $j ] ),
|
607 |
-
ENT_NOQUOTES,
|
608 |
-
get_option( 'blog_charset' )
|
609 |
-
);
|
610 |
-
|
611 |
-
if ( @preg_match( '/^' . $pattern . '$/imU', $against ) ) {
|
612 |
-
|
613 |
-
$found = true;
|
614 |
-
break;
|
615 |
-
}
|
616 |
-
}
|
617 |
-
|
618 |
-
if ( ! $found ) {
|
619 |
-
|
620 |
-
$new_matches[ $i ] = $matches[ $i ];
|
621 |
-
}
|
622 |
-
}
|
623 |
-
|
624 |
-
//if ( count( $matches ) != count( $new_matches ) ) {
|
625 |
-
|
626 |
-
$matches = $new_matches;
|
627 |
-
//}
|
628 |
-
}
|
629 |
-
}
|
630 |
-
|
631 |
-
return $matches;
|
632 |
-
}
|
633 |
-
|
634 |
-
/**
|
635 |
-
* Return the alternate headings added by the user, saved in the post meta.
|
636 |
-
*
|
637 |
-
* The result is an associative array where the `key` is the original post heading
|
638 |
-
* and the `value` is the alternate heading.
|
639 |
-
*
|
640 |
-
* @access private
|
641 |
-
* @since 2.0
|
642 |
-
*
|
643 |
-
* @return array
|
644 |
-
*/
|
645 |
-
private function getAlternateHeadings() {
|
646 |
-
|
647 |
-
$alternates = array();
|
648 |
-
$value = get_post_meta( $this->post->ID, '_ez-toc-alttext', true );
|
649 |
-
|
650 |
-
if ( $value ) {
|
651 |
-
|
652 |
-
$headings = preg_split( '/\r\n|[\r\n]/', $value );
|
653 |
-
$count = count( $headings );
|
654 |
-
|
655 |
-
if ( $headings ) {
|
656 |
-
|
657 |
-
for ( $k = 0; $k < $count; $k++ ) {
|
658 |
-
|
659 |
-
$heading = explode( '|', $headings[ $k ] );
|
660 |
-
|
661 |
-
/**
|
662 |
-
* @link https://wordpress.org/support/topic/undefined-offset-1-home-blog-public-wp-content-plugins-easy-table-of-contents/
|
663 |
-
*/
|
664 |
-
if ( ! is_array( $heading) ||
|
665 |
-
! array_key_exists( 0, $heading ) ||
|
666 |
-
! array_key_exists( 1, $heading )
|
667 |
-
) {
|
668 |
-
continue;
|
669 |
-
}
|
670 |
-
|
671 |
-
if ( 0 < strlen( $heading[0] ) && 0 < strlen( $heading[1] ) ) {
|
672 |
-
|
673 |
-
$alternates[ $heading[0] ] = $heading[1];
|
674 |
-
}
|
675 |
-
}
|
676 |
-
|
677 |
-
}
|
678 |
-
|
679 |
-
}
|
680 |
-
|
681 |
-
return $alternates;
|
682 |
-
}
|
683 |
-
|
684 |
-
/**
|
685 |
-
* Add the alternate headings to the array.
|
686 |
-
*
|
687 |
-
* @see ezTOC_Post::extractHeadings()
|
688 |
-
*
|
689 |
-
* @access private
|
690 |
-
* @since 2.0
|
691 |
-
*
|
692 |
-
* @param array $matches The heading from the post content extracted with preg_match_all().
|
693 |
-
*
|
694 |
-
* @return array
|
695 |
-
*/
|
696 |
-
private function alternateHeadings( &$matches ) {
|
697 |
-
|
698 |
-
$alt_headings = $this->getAlternateHeadings();
|
699 |
-
//$count = count( $matches );
|
700 |
-
|
701 |
-
if ( 0 < count( $alt_headings ) ) {
|
702 |
-
|
703 |
-
//for ( $i = 0; $i < $count; $i++ ) {
|
704 |
-
foreach ( $matches as $i => $match ) {
|
705 |
-
|
706 |
-
foreach ( $alt_headings as $original_heading => $alt_heading ) {
|
707 |
-
|
708 |
-
// Cleanup and texturize so alt heading can match heading in post content.
|
709 |
-
$original_heading = wptexturize( trim( $original_heading ) );
|
710 |
-
|
711 |
-
// Deal with special characters such as non-breakable space.
|
712 |
-
$original_heading = str_replace(
|
713 |
-
array( "\xc2\xa0" ),
|
714 |
-
array( ' ' ),
|
715 |
-
$original_heading
|
716 |
-
);
|
717 |
-
|
718 |
-
// Escape for regular expression.
|
719 |
-
$original_heading = preg_quote( $original_heading );
|
720 |
-
|
721 |
-
// Escape for regular expression some other characters: http://www.php.net/manual/en/regexp.reference.meta.php
|
722 |
-
$original_heading = str_replace(
|
723 |
-
array( '\*', '/', '%' ),
|
724 |
-
array( '.*', '\/', '\%' ),
|
725 |
-
$original_heading
|
726 |
-
);
|
727 |
-
|
728 |
-
// Cleanup subject so alt heading can match heading in post content.
|
729 |
-
$subject = strip_tags( $matches[ $i ][0] );
|
730 |
-
|
731 |
-
// Deal with special characters such as non-breakable space.
|
732 |
-
$subject = str_replace(
|
733 |
-
array( "\xc2\xa0" ),
|
734 |
-
array( ' ' ),
|
735 |
-
$subject
|
736 |
-
);
|
737 |
-
|
738 |
-
if ( @preg_match( '/^' . $original_heading . '$/imU', $subject ) ) {
|
739 |
-
|
740 |
-
$matches[ $i ]['alternate'] = $alt_heading;
|
741 |
-
}
|
742 |
-
}
|
743 |
-
}
|
744 |
-
}
|
745 |
-
|
746 |
-
return $matches;
|
747 |
-
}
|
748 |
-
|
749 |
-
/**
|
750 |
-
* Add the heading `id` to the array.
|
751 |
-
*
|
752 |
-
* @see ezTOC_Post::extractHeadings()
|
753 |
-
*
|
754 |
-
* @access private
|
755 |
-
* @since 2.0
|
756 |
-
*
|
757 |
-
* @param array $matches The heading from the post content extracted with preg_match_all().
|
758 |
-
*
|
759 |
-
* @return mixed
|
760 |
-
*/
|
761 |
-
private function headingIDs( &$matches ) {
|
762 |
-
|
763 |
-
//$count = count( $matches );
|
764 |
-
|
765 |
-
//for ( $i = 0; $i < $count; $i++ ) {
|
766 |
-
foreach ( $matches as $i => $match ) {
|
767 |
-
|
768 |
-
$matches[ $i ]['id'] = $this->generateHeadingIDFromTitle( $matches[ $i ][0] );
|
769 |
-
}
|
770 |
-
|
771 |
-
return $matches;
|
772 |
-
}
|
773 |
-
|
774 |
-
/**
|
775 |
-
* Create unique heading ID from heading string.
|
776 |
-
*
|
777 |
-
* @access private
|
778 |
-
* @since 2.0
|
779 |
-
*
|
780 |
-
* @param string $heading
|
781 |
-
*
|
782 |
-
* @return bool|string
|
783 |
-
*/
|
784 |
-
private function generateHeadingIDFromTitle( $heading ) {
|
785 |
-
|
786 |
-
$return = false;
|
787 |
-
|
788 |
-
if ( $heading ) {
|
789 |
-
|
790 |
-
// WP entity encodes the post content.
|
791 |
-
$return = html_entity_decode( $heading, ENT_QUOTES, get_option( 'blog_charset' ) );
|
792 |
-
$return = br2( $return, ' ' );
|
793 |
-
$return = trim( strip_tags( $return ) );
|
794 |
-
|
795 |
-
// Convert accented characters to ASCII.
|
796 |
-
$return = remove_accents( $return );
|
797 |
-
|
798 |
-
// replace newlines with spaces (eg when headings are split over multiple lines)
|
799 |
-
$return = str_replace( array( "\r", "\n", "\n\r", "\r\n" ), ' ', $return );
|
800 |
-
|
801 |
-
// Remove `&` and ` ` NOTE: in order to strip "hidden" ` `,
|
802 |
-
// title needs to be converted to HTML entities.
|
803 |
-
// @link https://stackoverflow.com/a/21801444/5351316
|
804 |
-
$return = htmlentities2( $return );
|
805 |
-
$return = str_replace( array( '&', ' ' ), ' ', $return );
|
806 |
-
$return = html_entity_decode( $return, ENT_QUOTES, get_option( 'blog_charset' ) );
|
807 |
-
|
808 |
-
// remove non alphanumeric chars
|
809 |
-
//$return = preg_replace( '/[^a-zA-Z0-9 \-_]*/', '', $return );
|
810 |
-
$return = preg_replace( '/[\x00-\x1F\x7F]*/u', '', $return );
|
811 |
-
|
812 |
-
// Reserved Characters.
|
813 |
-
// * ' ( ) ; : @ & = + $ , / ? # [ ]
|
814 |
-
$return = str_replace(
|
815 |
-
array( '*', '\'', '(', ')', ';', '@', '&', '=', '+', '$', ',', '/', '?', '#', '[', ']' ),
|
816 |
-
'',
|
817 |
-
$return
|
818 |
-
);
|
819 |
-
|
820 |
-
// Unsafe Characters.
|
821 |
-
// % { } | \ ^ ~ [ ] `
|
822 |
-
$return = str_replace(
|
823 |
-
array( '%', '{', '}', '|', '\\', '^', '~', '[', ']', '`' ),
|
824 |
-
'',
|
825 |
-
$return
|
826 |
-
);
|
827 |
-
|
828 |
-
// Special Characters.
|
829 |
-
// $ - _ . + ! * ' ( ) ,
|
830 |
-
$return = str_replace(
|
831 |
-
array( '$', '.', '+', '!', '*', '\'', '(', ')', ',' ),
|
832 |
-
'',
|
833 |
-
$return
|
834 |
-
);
|
835 |
-
|
836 |
-
// Dashes
|
837 |
-
// Special Characters.
|
838 |
-
// - (minus) - (dash) – (en dash) — (em dash)
|
839 |
-
$return = str_replace(
|
840 |
-
array( '-', '-', '–', '—' ),
|
841 |
-
'-',
|
842 |
-
$return
|
843 |
-
);
|
844 |
-
|
845 |
-
// Curley quotes.
|
846 |
-
// ‘ (curly single open quote) ’ (curly single close quote) “ (curly double open quote) ” (curly double close quote)
|
847 |
-
$return = str_replace(
|
848 |
-
array( '‘', '’', '“', '”' ),
|
849 |
-
'',
|
850 |
-
$return
|
851 |
-
);
|
852 |
-
|
853 |
-
// AMP/Caching plugins seems to break URL with the following characters, so lets replace them.
|
854 |
-
$return = str_replace( array( ':' ), '_', $return );
|
855 |
-
|
856 |
-
// Convert space characters to an `_` (underscore).
|
857 |
-
$return = preg_replace( '/\s+/', '_', $return );
|
858 |
-
|
859 |
-
// Replace multiple `-` (hyphen) with a single `-` (hyphen).
|
860 |
-
$return = preg_replace( '/-+/', '-', $return );
|
861 |
-
|
862 |
-
// Replace multiple `_` (underscore) with a single `_` (underscore).
|
863 |
-
$return = preg_replace( '/_+/', '_', $return );
|
864 |
-
|
865 |
-
// Remove trailing `-` (hyphen) and `_` (underscore).
|
866 |
-
$return = rtrim( $return, '-_' );
|
867 |
-
|
868 |
-
/*
|
869 |
-
* Encode URI based on ECMA-262.
|
870 |
-
*
|
871 |
-
* Only required to support the jQuery smoothScroll library.
|
872 |
-
*
|
873 |
-
* @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURI#Description
|
874 |
-
* @link https://stackoverflow.com/a/19858404/5351316
|
875 |
-
*/
|
876 |
-
$return = preg_replace_callback(
|
877 |
-
"{[^0-9a-z_.!~*'();,/?:@&=+$#-]}i",
|
878 |
-
function( $m ) {
|
879 |
-
|
880 |
-
return sprintf( '%%%02X', ord( $m[0] ) );
|
881 |
-
},
|
882 |
-
$return
|
883 |
-
);
|
884 |
-
|
885 |
-
// lowercase everything?
|
886 |
-
if ( ezTOC_Option::get( 'lowercase' ) ) {
|
887 |
-
|
888 |
-
$return = strtolower( $return );
|
889 |
-
}
|
890 |
-
|
891 |
-
// if blank, then prepend with the fragment prefix
|
892 |
-
// blank anchors normally appear on sites that don't use the latin charset
|
893 |
-
if ( ! $return ) {
|
894 |
-
|
895 |
-
$return = ( ezTOC_Option::get( 'fragment_prefix' ) ) ? ezTOC_Option::get( 'fragment_prefix' ) : '_';
|
896 |
-
}
|
897 |
-
|
898 |
-
// hyphenate?
|
899 |
-
if ( ezTOC_Option::get( 'hyphenate' ) ) {
|
900 |
-
|
901 |
-
$return = str_replace( '_', '-', $return );
|
902 |
-
$return = preg_replace( '/-+/', '-', $return );
|
903 |
-
}
|
904 |
-
}
|
905 |
-
|
906 |
-
if ( array_key_exists( $return, $this->collision_collector ) ) {
|
907 |
-
|
908 |
-
$this->collision_collector[ $return ]++;
|
909 |
-
$return .= '-' . $this->collision_collector[ $return ];
|
910 |
-
|
911 |
-
} else {
|
912 |
-
|
913 |
-
$this->collision_collector[ $return ] = 1;
|
914 |
-
}
|
915 |
-
|
916 |
-
return apply_filters( 'ez_toc_url_anchor_target', $return, $heading );
|
917 |
-
}
|
918 |
-
|
919 |
-
/**
|
920 |
-
* Remove any empty headings from the TOC.
|
921 |
-
*
|
922 |
-
* @access private
|
923 |
-
* @since 2.0
|
924 |
-
*
|
925 |
-
* @param array $matches The heading from the post content extracted with preg_match_all().
|
926 |
-
*
|
927 |
-
* @return array
|
928 |
-
*/
|
929 |
-
private function removeEmptyHeadings( &$matches ) {
|
930 |
-
|
931 |
-
$new_matches = array();
|
932 |
-
//$count = count( $matches );
|
933 |
-
|
934 |
-
//for ( $i = 0; $i < $count; $i ++ ) {
|
935 |
-
foreach ( $matches as $i => $match ) {
|
936 |
-
|
937 |
-
if ( trim( strip_tags( $matches[ $i ][0] ) ) != false ) {
|
938 |
-
|
939 |
-
$new_matches[ $i ] = $matches[ $i ];
|
940 |
-
}
|
941 |
-
}
|
942 |
-
|
943 |
-
//if ( count( $matches ) != count( $new_matches ) ) {
|
944 |
-
|
945 |
-
$matches = $new_matches;
|
946 |
-
//}
|
947 |
-
|
948 |
-
return $matches;
|
949 |
-
}
|
950 |
-
|
951 |
-
/**
|
952 |
-
* Whether or not the post has TOC items.
|
953 |
-
*
|
954 |
-
* @see ezTOC_Post::extractHeadings()
|
955 |
-
*
|
956 |
-
* @access public
|
957 |
-
* @since 2.0
|
958 |
-
*
|
959 |
-
* @return bool
|
960 |
-
*/
|
961 |
-
public function hasTOCItems() {
|
962 |
-
|
963 |
-
return $this->hasTOCItems;
|
964 |
-
}
|
965 |
-
|
966 |
-
/**
|
967 |
-
* Get the headings of the current page of the post.
|
968 |
-
*
|
969 |
-
* @access public
|
970 |
-
* @since 2.0
|
971 |
-
*
|
972 |
-
* @param int|null $page
|
973 |
-
*
|
974 |
-
* @return array
|
975 |
-
*/
|
976 |
-
public function getHeadings( $page = null ) {
|
977 |
-
|
978 |
-
$headings = array();
|
979 |
-
|
980 |
-
if ( is_null( $page ) ) {
|
981 |
-
|
982 |
-
$page = $this->getCurrentPage();
|
983 |
-
}
|
984 |
-
|
985 |
-
if ( isset( $this->pages[ $page ] ) ) {
|
986 |
-
|
987 |
-
//$headings = wp_list_pluck( $this->pages[ $page ]['headings'], 0 );
|
988 |
-
|
989 |
-
$matches = $this->pages[ $page ]['headings'];
|
990 |
-
//$count = count( $matches );
|
991 |
-
|
992 |
-
//for ( $i = 0; $i < $count; $i++ ) {
|
993 |
-
foreach ( $matches as $i => $match ) {
|
994 |
-
|
995 |
-
//$anchor = $matches[ $i ]['id'];
|
996 |
-
$headings[] = str_replace(
|
997 |
-
array(
|
998 |
-
$matches[ $i ][1], // start of heading
|
999 |
-
'</h' . $matches[ $i ][2] . '>' // end of heading
|
1000 |
-
),
|
1001 |
-
array(
|
1002 |
-
'>',
|
1003 |
-
'</h' . $matches[ $i ][2] . '>'
|
1004 |
-
),
|
1005 |
-
$matches[ $i ][0]
|
1006 |
-
);
|
1007 |
-
}
|
1008 |
-
}
|
1009 |
-
|
1010 |
-
return $headings;
|
1011 |
-
}
|
1012 |
-
|
1013 |
-
/**
|
1014 |
-
* Get the heading with in page anchors of the current page of the post.
|
1015 |
-
*
|
1016 |
-
* @access public
|
1017 |
-
* @since 2.0
|
1018 |
-
*
|
1019 |
-
* @param int|null $page
|
1020 |
-
*
|
1021 |
-
* @return array
|
1022 |
-
*/
|
1023 |
-
public function getHeadingsWithAnchors( $page = null ) {
|
1024 |
-
|
1025 |
-
$headings = array();
|
1026 |
-
|
1027 |
-
if ( is_null( $page ) ) {
|
1028 |
-
|
1029 |
-
$page = $this->getCurrentPage();
|
1030 |
-
}
|
1031 |
-
|
1032 |
-
if ( isset( $this->pages[ $page ] ) ) {
|
1033 |
-
|
1034 |
-
$matches = $this->pages[ $page ]['headings'];
|
1035 |
-
//$count = count( $matches );
|
1036 |
-
|
1037 |
-
//for ( $i = 0; $i < $count; $i++ ) {
|
1038 |
-
foreach ( $matches as $i => $match ) {
|
1039 |
-
|
1040 |
-
$anchor = $matches[ $i ]['id'];
|
1041 |
-
$headings[] = str_replace(
|
1042 |
-
array(
|
1043 |
-
$matches[ $i ][1], // start of heading
|
1044 |
-
'</h' . $matches[ $i ][2] . '>' // end of heading
|
1045 |
-
),
|
1046 |
-
array(
|
1047 |
-
'><span class="ez-toc-section" id="' . $anchor . '"></span>',
|
1048 |
-
'<span class="ez-toc-section-end"></span></h' . $matches[ $i ][2] . '>'
|
1049 |
-
),
|
1050 |
-
$matches[ $i ][0]
|
1051 |
-
);
|
1052 |
-
}
|
1053 |
-
}
|
1054 |
-
|
1055 |
-
return $headings;
|
1056 |
-
}
|
1057 |
-
|
1058 |
-
/**
|
1059 |
-
* Get the post TOC list.
|
1060 |
-
*
|
1061 |
-
* @access public
|
1062 |
-
* @since 2.0
|
1063 |
-
*
|
1064 |
-
* @return string
|
1065 |
-
*/
|
1066 |
-
public function getTOCList() {
|
1067 |
-
|
1068 |
-
$html = '';
|
1069 |
-
|
1070 |
-
if ( $this->hasTOCItems ) {
|
1071 |
-
|
1072 |
-
foreach ( $this->pages as $page => $attribute ) {
|
1073 |
-
|
1074 |
-
$html .= $this->createTOC( $page, $attribute['headings'] );
|
1075 |
-
}
|
1076 |
-
|
1077 |
-
$html = '<ul class="ez-toc-list ez-toc-list-level-1">' . $html . '</ul>';
|
1078 |
-
}
|
1079 |
-
|
1080 |
-
return $html;
|
1081 |
-
}
|
1082 |
-
|
1083 |
-
/**
|
1084 |
-
* Get the post TOC content block.
|
1085 |
-
*
|
1086 |
-
* @access public
|
1087 |
-
* @since 2.0
|
1088 |
-
*
|
1089 |
-
* @return string
|
1090 |
-
*/
|
1091 |
-
public function getTOC() {
|
1092 |
-
|
1093 |
-
$class = array( 'ez-toc-v' . str_replace( '.', '_', ezTOC::VERSION ) );
|
1094 |
-
$html = '';
|
1095 |
-
|
1096 |
-
if ( $this->hasTOCItems() ) {
|
1097 |
-
|
1098 |
-
// wrapping css classes
|
1099 |
-
switch ( ezTOC_Option::get( 'wrapping' ) ) {
|
1100 |
-
|
1101 |
-
case 'left':
|
1102 |
-
$class[] = 'ez-toc-wrap-left';
|
1103 |
-
break;
|
1104 |
-
|
1105 |
-
case 'right':
|
1106 |
-
$class[] = 'ez-toc-wrap-right';
|
1107 |
-
break;
|
1108 |
-
|
1109 |
-
case 'none':
|
1110 |
-
default:
|
1111 |
-
// do nothing
|
1112 |
-
}
|
1113 |
-
|
1114 |
-
if ( ezTOC_Option::get( 'show_hierarchy' ) ) {
|
1115 |
-
|
1116 |
-
$class[] = 'counter-hierarchy';
|
1117 |
-
|
1118 |
-
} else {
|
1119 |
-
|
1120 |
-
$class[] .= 'counter-flat';
|
1121 |
-
}
|
1122 |
-
|
1123 |
-
switch ( ezTOC_Option::get( 'counter' ) ) {
|
1124 |
-
|
1125 |
-
case 'numeric':
|
1126 |
-
$class[] .= 'counter-numeric';
|
1127 |
-
break;
|
1128 |
-
|
1129 |
-
case 'roman':
|
1130 |
-
$class[] = 'counter-roman';
|
1131 |
-
break;
|
1132 |
-
|
1133 |
-
case 'decimal':
|
1134 |
-
$class[] = 'counter-decimal';
|
1135 |
-
break;
|
1136 |
-
}
|
1137 |
-
|
1138 |
-
// colour themes
|
1139 |
-
switch ( ezTOC_Option::get( 'theme' ) ) {
|
1140 |
-
|
1141 |
-
case 'light-blue':
|
1142 |
-
$class[] = 'ez-toc-light-blue';
|
1143 |
-
break;
|
1144 |
-
|
1145 |
-
case 'white':
|
1146 |
-
$class[] = 'ez-toc-white';
|
1147 |
-
break;
|
1148 |
-
|
1149 |
-
case 'black':
|
1150 |
-
$class[] = 'ez-toc-black';
|
1151 |
-
break;
|
1152 |
-
|
1153 |
-
case 'transparent':
|
1154 |
-
$class[] .= 'ez-toc-transparent';
|
1155 |
-
break;
|
1156 |
-
|
1157 |
-
case 'grey':
|
1158 |
-
$class[] = 'ez-toc-grey';
|
1159 |
-
break;
|
1160 |
-
}
|
1161 |
-
|
1162 |
-
$custom_classes = ezTOC_Option::get( 'css_container_class', '' );
|
1163 |
-
|
1164 |
-
if ( 0 < strlen( $custom_classes ) ) {
|
1165 |
-
|
1166 |
-
$custom_classes = explode( ' ', $custom_classes );
|
1167 |
-
$custom_classes = apply_filters( 'ez_toc_container_class', $custom_classes, $this );
|
1168 |
-
|
1169 |
-
if ( is_array( $custom_classes ) ) {
|
1170 |
-
|
1171 |
-
$class = array_merge( $class, $custom_classes );
|
1172 |
-
}
|
1173 |
-
}
|
1174 |
-
|
1175 |
-
$class = array_filter( $class );
|
1176 |
-
$class = array_map( 'trim', $class );
|
1177 |
-
$class = array_map( 'sanitize_html_class', $class );
|
1178 |
-
|
1179 |
-
$html .= '<div id="ez-toc-container" class="' . implode( ' ', $class ) . '">' . PHP_EOL;
|
1180 |
-
|
1181 |
-
if ( ezTOC_Option::get( 'show_heading_text' ) ) {
|
1182 |
-
|
1183 |
-
$toc_title = ezTOC_Option::get( 'heading_text' );
|
1184 |
-
|
1185 |
-
if ( strpos( $toc_title, '%PAGE_TITLE%' ) !== false ) {
|
1186 |
-
|
1187 |
-
$toc_title = str_replace( '%PAGE_TITLE%', get_the_title(), $toc_title );
|
1188 |
-
}
|
1189 |
-
|
1190 |
-
if ( strpos( $toc_title, '%PAGE_NAME%' ) !== false ) {
|
1191 |
-
|
1192 |
-
$toc_title = str_replace( '%PAGE_NAME%', get_the_title(), $toc_title );
|
1193 |
-
}
|
1194 |
-
|
1195 |
-
|
1196 |
-
|
1197 |
-
|
1198 |
-
|
1199 |
-
$html .= '<
|
1200 |
-
|
1201 |
-
if (
|
1202 |
-
|
1203 |
-
|
1204 |
-
|
1205 |
-
|
1206 |
-
|
1207 |
-
|
1208 |
-
|
1209 |
-
|
1210 |
-
|
1211 |
-
|
1212 |
-
|
1213 |
-
|
1214 |
-
|
1215 |
-
|
1216 |
-
|
1217 |
-
|
1218 |
-
|
1219 |
-
|
1220 |
-
|
1221 |
-
|
1222 |
-
|
1223 |
-
|
1224 |
-
|
1225 |
-
|
1226 |
-
|
1227 |
-
|
1228 |
-
|
1229 |
-
|
1230 |
-
|
1231 |
-
|
1232 |
-
|
1233 |
-
|
1234 |
-
|
1235 |
-
|
1236 |
-
|
1237 |
-
|
1238 |
-
|
1239 |
-
|
1240 |
-
|
1241 |
-
|
1242 |
-
*
|
1243 |
-
*
|
1244 |
-
* @
|
1245 |
-
|
1246 |
-
|
1247 |
-
|
1248 |
-
|
1249 |
-
|
1250 |
-
|
1251 |
-
|
1252 |
-
|
1253 |
-
|
1254 |
-
|
1255 |
-
|
1256 |
-
|
1257 |
-
|
1258 |
-
|
1259 |
-
|
1260 |
-
|
1261 |
-
|
1262 |
-
|
1263 |
-
|
1264 |
-
|
1265 |
-
|
1266 |
-
|
1267 |
-
|
1268 |
-
|
1269 |
-
|
1270 |
-
|
1271 |
-
|
1272 |
-
|
1273 |
-
|
1274 |
-
|
1275 |
-
|
1276 |
-
|
1277 |
-
|
1278 |
-
|
1279 |
-
//for ( $i = 0; $i < count( $matches ); $i ++ ) {
|
1280 |
-
foreach ( $matches as $i => $match ) {
|
1281 |
-
|
1282 |
-
|
1283 |
-
|
1284 |
-
|
1285 |
-
|
1286 |
-
|
1287 |
-
|
1288 |
-
|
1289 |
-
|
1290 |
-
|
1291 |
-
|
1292 |
-
|
1293 |
-
|
1294 |
-
|
1295 |
-
|
1296 |
-
|
1297 |
-
|
1298 |
-
}
|
1299 |
-
|
1300 |
-
|
1301 |
-
$
|
1302 |
-
|
1303 |
-
|
1304 |
-
|
1305 |
-
|
1306 |
-
|
1307 |
-
|
1308 |
-
|
1309 |
-
|
1310 |
-
|
1311 |
-
|
1312 |
-
|
1313 |
-
|
1314 |
-
|
1315 |
-
|
1316 |
-
|
1317 |
-
|
1318 |
-
|
1319 |
-
|
1320 |
-
|
1321 |
-
|
1322 |
-
|
1323 |
-
|
1324 |
-
|
1325 |
-
|
1326 |
-
|
1327 |
-
|
1328 |
-
|
1329 |
-
|
1330 |
-
|
1331 |
-
|
1332 |
-
|
1333 |
-
|
1334 |
-
|
1335 |
-
|
1336 |
-
|
1337 |
-
|
1338 |
-
|
1339 |
-
|
1340 |
-
|
1341 |
-
|
1342 |
-
|
1343 |
-
|
1344 |
-
|
1345 |
-
|
1346 |
-
|
1347 |
-
|
1348 |
-
|
1349 |
-
|
1350 |
-
|
1351 |
-
|
1352 |
-
|
1353 |
-
|
1354 |
-
|
1355 |
-
|
1356 |
-
|
1357 |
-
|
1358 |
-
|
1359 |
-
|
1360 |
-
|
1361 |
-
|
1362 |
-
|
1363 |
-
|
1364 |
-
|
1365 |
-
|
1366 |
-
|
1367 |
-
|
1368 |
-
|
1369 |
-
|
1370 |
-
|
1371 |
-
|
1372 |
-
|
1373 |
-
|
1374 |
-
|
1375 |
-
|
1376 |
-
|
1377 |
-
|
1378 |
-
|
1379 |
-
|
1380 |
-
|
1381 |
-
|
1382 |
-
|
1383 |
-
|
1384 |
-
|
1385 |
-
|
1386 |
-
|
1387 |
-
|
1388 |
-
|
1389 |
-
|
1390 |
-
|
1391 |
-
|
1392 |
-
|
1393 |
-
|
1394 |
-
|
1395 |
-
|
1396 |
-
|
1397 |
-
|
1398 |
-
|
1399 |
-
|
1400 |
-
|
1401 |
-
|
1402 |
-
|
1403 |
-
|
1404 |
-
|
1405 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
use function Easy_Plugins\Table_Of_Contents\String\br2;
|
4 |
+
|
5 |
+
class ezTOC_Post {
|
6 |
+
|
7 |
+
/**
|
8 |
+
* @since 2.0
|
9 |
+
* @var int
|
10 |
+
*/
|
11 |
+
private $queriedObjectID;
|
12 |
+
|
13 |
+
/**
|
14 |
+
* @since 2.0
|
15 |
+
* @var WP_Post
|
16 |
+
*/
|
17 |
+
private $post;
|
18 |
+
|
19 |
+
/**
|
20 |
+
* @since 2.0
|
21 |
+
* @var false|string
|
22 |
+
*/
|
23 |
+
private $permalink;
|
24 |
+
|
25 |
+
/**
|
26 |
+
* The post content broken into pages by user inserting `<!--nextpage-->` into the post content.
|
27 |
+
* @see ezTOC_Post::extractPages()
|
28 |
+
* @since 2.0
|
29 |
+
* @var array
|
30 |
+
*/
|
31 |
+
private $pages = array();
|
32 |
+
|
33 |
+
/**
|
34 |
+
* The user defined heading levels to be included in the TOC.
|
35 |
+
* @see ezTOC_Post::getHeadingLevels()
|
36 |
+
* @since 2.0
|
37 |
+
* @var array
|
38 |
+
*/
|
39 |
+
private $headingLevels = array();
|
40 |
+
|
41 |
+
/**
|
42 |
+
* Array of nodes that are excluded by class/id selector.
|
43 |
+
* @since 2.0
|
44 |
+
* @var string[]
|
45 |
+
*/
|
46 |
+
private $excludedNodes = array();
|
47 |
+
|
48 |
+
/**
|
49 |
+
* Keeps a track of used anchors for collision detecting.
|
50 |
+
* @see ezTOC_Post::generateHeadingIDFromTitle()
|
51 |
+
* @since 2.0
|
52 |
+
* @var array
|
53 |
+
*/
|
54 |
+
private $collision_collector = array();
|
55 |
+
|
56 |
+
/**
|
57 |
+
* @var bool
|
58 |
+
*/
|
59 |
+
private $hasTOCItems = false;
|
60 |
+
|
61 |
+
/**
|
62 |
+
* ezTOC_Post constructor.
|
63 |
+
*
|
64 |
+
* @since 2.0
|
65 |
+
*
|
66 |
+
* @param WP_Post $post
|
67 |
+
* @param bool $apply_content_filter Whether or not to apply the `the_content` filter on the post content.
|
68 |
+
*/
|
69 |
+
public function __construct( WP_Post $post, $apply_content_filter = true ) {
|
70 |
+
|
71 |
+
$this->post = $post;
|
72 |
+
$this->permalink = get_permalink( $post );
|
73 |
+
$this->queriedObjectID = get_queried_object_id();
|
74 |
+
|
75 |
+
if ( $apply_content_filter ) {
|
76 |
+
|
77 |
+
$this->applyContentFilter()->process();
|
78 |
+
|
79 |
+
} else {
|
80 |
+
|
81 |
+
$this->process();
|
82 |
+
}
|
83 |
+
}
|
84 |
+
|
85 |
+
/**
|
86 |
+
* @access public
|
87 |
+
* @since 2.0
|
88 |
+
*
|
89 |
+
* @param $id
|
90 |
+
*
|
91 |
+
* @return ezTOC_Post|null
|
92 |
+
*/
|
93 |
+
public static function get( $id ) {
|
94 |
+
|
95 |
+
$post = get_post( $id );
|
96 |
+
|
97 |
+
if ( ! $post instanceof WP_Post ) {
|
98 |
+
|
99 |
+
return null;
|
100 |
+
}
|
101 |
+
|
102 |
+
return new static( $post );
|
103 |
+
}
|
104 |
+
|
105 |
+
/**
|
106 |
+
* Process post content for headings.
|
107 |
+
*
|
108 |
+
* This must be run after object init or after @see ezTOC_Post::applyContentFilter().
|
109 |
+
*
|
110 |
+
* @since 2.0
|
111 |
+
*
|
112 |
+
* @return static
|
113 |
+
*/
|
114 |
+
private function process() {
|
115 |
+
|
116 |
+
$this->processPages();
|
117 |
+
|
118 |
+
return $this;
|
119 |
+
}
|
120 |
+
|
121 |
+
/**
|
122 |
+
* Apply `the_content` filter to the post content.
|
123 |
+
*
|
124 |
+
* @since 2.0
|
125 |
+
*
|
126 |
+
* @return static
|
127 |
+
*/
|
128 |
+
private function applyContentFilter() {
|
129 |
+
|
130 |
+
add_filter( 'strip_shortcodes_tagnames', array( __CLASS__, 'stripShortcodes' ), 10, 2 );
|
131 |
+
|
132 |
+
/*
|
133 |
+
* Ensure the ezTOC content filter is not applied when running `the_content` filter.
|
134 |
+
*/
|
135 |
+
remove_filter( 'the_content', array( 'ezTOC', 'the_content' ), 100 );
|
136 |
+
|
137 |
+
$this->post->post_content = apply_filters( 'the_content', strip_shortcodes( $this->post->post_content ) );
|
138 |
+
|
139 |
+
add_filter( 'the_content', array( 'ezTOC', 'the_content' ), 100 );
|
140 |
+
|
141 |
+
remove_filter( 'strip_shortcodes_tagnames', array( __CLASS__, 'stripShortcodes' ) );
|
142 |
+
|
143 |
+
return $this;
|
144 |
+
}
|
145 |
+
|
146 |
+
/**
|
147 |
+
* Callback for the `strip_shortcodes_tagnames` filter.
|
148 |
+
*
|
149 |
+
* Strip the shortcodes so their content is no processed for headings.
|
150 |
+
*
|
151 |
+
* @see ezTOC_Post::applyContentFilter()
|
152 |
+
*
|
153 |
+
* @since 2.0
|
154 |
+
*
|
155 |
+
* @param array $tags_to_remove Array of shortcode tags to remove.
|
156 |
+
* @param string $content Content shortcodes are being removed from.
|
157 |
+
*
|
158 |
+
* @return array
|
159 |
+
*/
|
160 |
+
public static function stripShortcodes( $tags_to_remove, $content ) {
|
161 |
+
|
162 |
+
//error_log( var_export( $tags_to_remove, true ) );
|
163 |
+
|
164 |
+
/*
|
165 |
+
* Ensure the ezTOC shortcodes are not processed when applying `the_content` filter
|
166 |
+
* otherwise an infinite loop may occur.
|
167 |
+
*/
|
168 |
+
$tags_to_remove = apply_filters(
|
169 |
+
'ez_toc_strip_shortcodes_tagnames',
|
170 |
+
array(
|
171 |
+
'ez-toc',
|
172 |
+
apply_filters( 'ez_toc_shortcode', 'toc' ),
|
173 |
+
),
|
174 |
+
$content
|
175 |
+
);
|
176 |
+
|
177 |
+
//error_log( var_export( $tags_to_remove, true ) );
|
178 |
+
|
179 |
+
return $tags_to_remove;
|
180 |
+
}
|
181 |
+
|
182 |
+
/**
|
183 |
+
* This is a work around for theme's and plugins
|
184 |
+
* which break the WordPress global $wp_query var by unsetting it
|
185 |
+
* or overwriting it which breaks the method call
|
186 |
+
* that `get_query_var()` uses to return the query variable.
|
187 |
+
*
|
188 |
+
* @access protected
|
189 |
+
* @since 2.0
|
190 |
+
*
|
191 |
+
* @return int
|
192 |
+
*/
|
193 |
+
protected function getCurrentPage() {
|
194 |
+
|
195 |
+
global $wp_query;
|
196 |
+
|
197 |
+
// Check to see if the global `$wp_query` var is an instance of WP_Query and that the get() method is callable.
|
198 |
+
// If it is then when can simply use the get_query_var() function.
|
199 |
+
if ( $wp_query instanceof WP_Query && is_callable( array( $wp_query, 'get' ) ) ) {
|
200 |
+
|
201 |
+
$page = get_query_var( 'page', 1 );
|
202 |
+
|
203 |
+
return 1 > $page ? 1 : $page;
|
204 |
+
|
205 |
+
// If a theme or plugin broke the global `$wp_query` var, check to see if the $var was parsed and saved in $GLOBALS['wp_query']->query_vars.
|
206 |
+
} elseif ( isset( $GLOBALS['wp_query']->query_vars[ 'page' ] ) ) {
|
207 |
+
|
208 |
+
return $GLOBALS['wp_query']->query_vars[ 'page' ];
|
209 |
+
|
210 |
+
// We should not reach this, but if we do, lets check the original parsed query vars in $GLOBALS['wp_the_query']->query_vars.
|
211 |
+
} elseif ( isset( $GLOBALS['wp_the_query']->query_vars[ 'page' ] ) ) {
|
212 |
+
|
213 |
+
return $GLOBALS['wp_the_query']->query_vars[ 'page' ];
|
214 |
+
|
215 |
+
// Ok, if all else fails, check the $_REQUEST super global.
|
216 |
+
} elseif ( isset( $_REQUEST[ 'page' ] ) ) {
|
217 |
+
|
218 |
+
return $_REQUEST[ 'page' ];
|
219 |
+
}
|
220 |
+
|
221 |
+
// Finally, return the $default if it was supplied.
|
222 |
+
return 1;
|
223 |
+
}
|
224 |
+
|
225 |
+
/**
|
226 |
+
* Get the number of page the post has.
|
227 |
+
*
|
228 |
+
* @access protected
|
229 |
+
* @since 2.0
|
230 |
+
*
|
231 |
+
* @return int
|
232 |
+
*/
|
233 |
+
protected function getNumberOfPages() {
|
234 |
+
|
235 |
+
return count( $this->pages );
|
236 |
+
}
|
237 |
+
|
238 |
+
/**
|
239 |
+
* Whether or not the post has multiple pages.
|
240 |
+
*
|
241 |
+
* @access protected
|
242 |
+
* @since 2.0
|
243 |
+
*
|
244 |
+
* @return bool
|
245 |
+
*/
|
246 |
+
protected function isMultipage() {
|
247 |
+
|
248 |
+
return 1 < $this->getNumberOfPages();
|
249 |
+
}
|
250 |
+
|
251 |
+
/**
|
252 |
+
* Parse the post content and headings.
|
253 |
+
*
|
254 |
+
* @access private
|
255 |
+
* @since 2.0
|
256 |
+
*/
|
257 |
+
private function processPages() {
|
258 |
+
|
259 |
+
//if ( ! class_exists( 'TagFilter' ) ) {
|
260 |
+
//
|
261 |
+
// require_once( EZ_TOC_PATH . '/includes/vendor/ultimate-web-scraper/tag_filter.php' );
|
262 |
+
//}
|
263 |
+
|
264 |
+
$split = preg_split( '/<!--nextpage-->/msuU', $this->post->post_content );
|
265 |
+
$pages = array();
|
266 |
+
|
267 |
+
if ( is_array( $split ) ) {
|
268 |
+
|
269 |
+
$page = 1;
|
270 |
+
|
271 |
+
//$tagFilterOptions = TagFilter::GetHTMLOptions();
|
272 |
+
|
273 |
+
//// Set custom TagFilter options.
|
274 |
+
//$tagFilterOptions['charset'] = get_option( 'blog_charset' );
|
275 |
+
////$tagFilterOptions['output_mode'] = 'xml';
|
276 |
+
|
277 |
+
foreach ( $split as $content ) {
|
278 |
+
|
279 |
+
//$html = TagFilter::Explode( $content, $tagFilterOptions );
|
280 |
+
//
|
281 |
+
///**
|
282 |
+
// * @since 2.0
|
283 |
+
// *
|
284 |
+
// * @param $selectors array Array of classes/id selector to exclude from TOC.
|
285 |
+
// * @param $content string Post content.
|
286 |
+
// */
|
287 |
+
//$selectors = apply_filters( 'ez_toc_exclude_by_selector', array(), $content );
|
288 |
+
//
|
289 |
+
//$nodes = $html->Find( implode( ',', $selectors ) );
|
290 |
+
//
|
291 |
+
//foreach ( $nodes['ids'] as $id ) {
|
292 |
+
//
|
293 |
+
// $html->Remove( $id );
|
294 |
+
//}
|
295 |
+
//
|
296 |
+
//$eligibleContent = $html->Implode( 0, $tagFilterOptions );
|
297 |
+
//
|
298 |
+
///**
|
299 |
+
// * TagFilter::Implode() writes br tags as `<br>` while WP normalizes to `<br />`.
|
300 |
+
// * Normalize `$eligibleContent` to match WP.
|
301 |
+
// *
|
302 |
+
// * @see wpautop()
|
303 |
+
// */
|
304 |
+
////$eligibleContent = str_replace( array( '<br>', '<br/>' ), array( '<br />' ), $eligibleContent );
|
305 |
+
//$eligibleContent = \Easy_Plugins\Table_Of_Contents\String\force_balance_tags( $eligibleContent );
|
306 |
+
|
307 |
+
$this->extractExcludedNodes( $page, $content );
|
308 |
+
|
309 |
+
$pages[ $page ] = array(
|
310 |
+
'headings' => $this->extractHeadings( $content ),
|
311 |
+
'content' => $content,
|
312 |
+
);
|
313 |
+
|
314 |
+
$page++;
|
315 |
+
}
|
316 |
+
|
317 |
+
}
|
318 |
+
|
319 |
+
$this->pages = $pages;
|
320 |
+
}
|
321 |
+
|
322 |
+
/**
|
323 |
+
* Get the post's parse content and headings.
|
324 |
+
*
|
325 |
+
* @access public
|
326 |
+
* @since 2.0
|
327 |
+
*
|
328 |
+
* @return array
|
329 |
+
*/
|
330 |
+
public function getPages() {
|
331 |
+
|
332 |
+
return $this->pages;
|
333 |
+
}
|
334 |
+
|
335 |
+
/**
|
336 |
+
* Extract nodes that heading are to be excluded.
|
337 |
+
*
|
338 |
+
* @since 2.0
|
339 |
+
*
|
340 |
+
* @param int $page
|
341 |
+
* @param string $content
|
342 |
+
*/
|
343 |
+
private function extractExcludedNodes( $page, $content ) {
|
344 |
+
|
345 |
+
if ( ! class_exists( 'TagFilter' ) ) {
|
346 |
+
|
347 |
+
require_once( EZ_TOC_PATH . '/includes/vendor/ultimate-web-scraper/tag_filter.php' );
|
348 |
+
}
|
349 |
+
|
350 |
+
$tagFilterOptions = TagFilter::GetHTMLOptions();
|
351 |
+
|
352 |
+
// Set custom TagFilter options.
|
353 |
+
$tagFilterOptions['charset'] = get_option( 'blog_charset' );
|
354 |
+
//$tagFilterOptions['output_mode'] = 'xml';
|
355 |
+
|
356 |
+
$html = TagFilter::Explode( $content, $tagFilterOptions );
|
357 |
+
|
358 |
+
/**
|
359 |
+
* @since 2.0
|
360 |
+
*
|
361 |
+
* @param $selectors array Array of classes/id selector to exclude from TOC.
|
362 |
+
* @param $content string Post content.
|
363 |
+
*/
|
364 |
+
$selectors = apply_filters( 'ez_toc_exclude_by_selector', array( '.ez-toc-exclude-headings' ), $content );
|
365 |
+
|
366 |
+
$nodes = $html->Find( implode( ',', $selectors ) );
|
367 |
+
|
368 |
+
foreach ( $nodes['ids'] as $id ) {
|
369 |
+
|
370 |
+
//$this->excludedNodes[ $page ][ $id ] = $html->Implode( $id, $tagFilterOptions );
|
371 |
+
array_push( $this->excludedNodes, $html->Implode( $id, $tagFilterOptions ) );
|
372 |
+
}
|
373 |
+
|
374 |
+
//$eligibleContent = $html->Implode( 0, $tagFilterOptions );
|
375 |
+
|
376 |
+
/**
|
377 |
+
* TagFilter::Implode() writes br tags as `<br>` while WP normalizes to `<br />`.
|
378 |
+
* Normalize `$eligibleContent` to match WP.
|
379 |
+
*
|
380 |
+
* @see wpautop()
|
381 |
+
*/
|
382 |
+
//$eligibleContent = \Easy_Plugins\Table_Of_Contents\String\force_balance_tags( $eligibleContent );
|
383 |
+
}
|
384 |
+
|
385 |
+
/**
|
386 |
+
* Extract the posts content for headings.
|
387 |
+
*
|
388 |
+
* @access private
|
389 |
+
* @since 2.0
|
390 |
+
*
|
391 |
+
* @param string $content
|
392 |
+
*
|
393 |
+
* @return array
|
394 |
+
*/
|
395 |
+
private function extractHeadings( $content ) {
|
396 |
+
|
397 |
+
$matches = array();
|
398 |
+
|
399 |
+
// reset the internal collision collection as the_content may have been triggered elsewhere
|
400 |
+
// eg by themes or other plugins that need to read in content such as metadata fields in
|
401 |
+
// the head html tag, or to provide descriptions to twitter/facebook
|
402 |
+
/** @todo does this need to be used??? */
|
403 |
+
//self::$collision_collector = array();
|
404 |
+
|
405 |
+
$content = apply_filters( 'ez_toc_extract_headings_content', wptexturize( $content ) );
|
406 |
+
|
407 |
+
// get all headings
|
408 |
+
// the html spec allows for a maximum of 6 heading depths
|
409 |
+
if ( preg_match_all( '/(<h([1-6]{1})[^>]*>)(.*)<\/h\2>/msuU', $content, $matches, PREG_SET_ORDER ) ) {
|
410 |
+
|
411 |
+
$minimum = absint( ezTOC_Option::get( 'start' ) );
|
412 |
+
|
413 |
+
$this->removeHeadingsFromExcludedNodes( $matches );
|
414 |
+
$this->removeHeadings( $matches );
|
415 |
+
$this->excludeHeadings( $matches );
|
416 |
+
$this->removeEmptyHeadings( $matches );
|
417 |
+
|
418 |
+
if ( count( $matches ) >= $minimum ) {
|
419 |
+
|
420 |
+
$this->alternateHeadings( $matches );
|
421 |
+
$this->headingIDs( $matches );
|
422 |
+
$this->hasTOCItems = true;
|
423 |
+
|
424 |
+
} else {
|
425 |
+
|
426 |
+
return array();
|
427 |
+
}
|
428 |
+
|
429 |
+
}
|
430 |
+
|
431 |
+
return array_values( $matches ); // Rest the array index.
|
432 |
+
}
|
433 |
+
|
434 |
+
/**
|
435 |
+
* Whether or not the string is in one of the excluded nodes.
|
436 |
+
*
|
437 |
+
* @since 2.0
|
438 |
+
*
|
439 |
+
* @param string $string
|
440 |
+
*
|
441 |
+
* @return bool
|
442 |
+
*/
|
443 |
+
private function inExcludedNode( $string ) {
|
444 |
+
|
445 |
+
foreach ( $this->excludedNodes as $node ) {
|
446 |
+
|
447 |
+
if ( empty( $node ) || empty( $string ) ) {
|
448 |
+
|
449 |
+
return false;
|
450 |
+
}
|
451 |
+
|
452 |
+
if ( false !== strpos( $node, $string ) ) {
|
453 |
+
|
454 |
+
return true;
|
455 |
+
}
|
456 |
+
}
|
457 |
+
|
458 |
+
return false;
|
459 |
+
}
|
460 |
+
|
461 |
+
/**
|
462 |
+
* Remove headings that are in excluded nodes.
|
463 |
+
*
|
464 |
+
* @since 2.0
|
465 |
+
*
|
466 |
+
* @param array $matches
|
467 |
+
*
|
468 |
+
* @return array
|
469 |
+
*/
|
470 |
+
private function removeHeadingsFromExcludedNodes( &$matches ) {
|
471 |
+
|
472 |
+
foreach ( $matches as $i => $match ) {
|
473 |
+
|
474 |
+
if ( $this->inExcludedNode( "{$match[3]}</h$match[2]>" ) ) {
|
475 |
+
|
476 |
+
unset( $matches[ $i ] );
|
477 |
+
}
|
478 |
+
}
|
479 |
+
|
480 |
+
return $matches;
|
481 |
+
}
|
482 |
+
|
483 |
+
/**
|
484 |
+
* Get the heading levels to be included in the TOC.
|
485 |
+
*
|
486 |
+
* @access private
|
487 |
+
* @since 2.0
|
488 |
+
*
|
489 |
+
* @return array
|
490 |
+
*/
|
491 |
+
private function getHeadingLevels() {
|
492 |
+
|
493 |
+
$levels = get_post_meta( $this->post->ID, '_ez-toc-heading-levels', true );
|
494 |
+
|
495 |
+
if ( ! is_array( $levels ) ) {
|
496 |
+
|
497 |
+
$levels = array();
|
498 |
+
}
|
499 |
+
|
500 |
+
if ( empty( $levels ) ) {
|
501 |
+
|
502 |
+
$levels = ezTOC_Option::get( 'heading_levels', array() );
|
503 |
+
}
|
504 |
+
|
505 |
+
$this->headingLevels = $levels;
|
506 |
+
|
507 |
+
return $this->headingLevels;
|
508 |
+
}
|
509 |
+
|
510 |
+
/**
|
511 |
+
* Remove the heading levels as defined by user settings from the TOC heading matches.
|
512 |
+
*
|
513 |
+
* @see ezTOC_Post::extractHeadings()
|
514 |
+
*
|
515 |
+
* @access private
|
516 |
+
* @since 2.0
|
517 |
+
*
|
518 |
+
* @param array $matches The heading from the post content extracted with preg_match_all().
|
519 |
+
*
|
520 |
+
* @return array
|
521 |
+
*/
|
522 |
+
private function removeHeadings( &$matches ) {
|
523 |
+
|
524 |
+
$levels = $this->getHeadingLevels();
|
525 |
+
|
526 |
+
if ( count( $levels ) != 6 ) {
|
527 |
+
|
528 |
+
$new_matches = array();
|
529 |
+
//$count = count( $matches );
|
530 |
+
|
531 |
+
//for ( $i = 0; $i < $count; $i++ ) {
|
532 |
+
foreach ( $matches as $i => $match ) {
|
533 |
+
|
534 |
+
if ( in_array( $matches[ $i ][2], $levels ) ) {
|
535 |
+
|
536 |
+
$new_matches[ $i ] = $matches[ $i ];
|
537 |
+
}
|
538 |
+
}
|
539 |
+
|
540 |
+
$matches = $new_matches;
|
541 |
+
}
|
542 |
+
|
543 |
+
return $matches;
|
544 |
+
}
|
545 |
+
|
546 |
+
/**
|
547 |
+
* Exclude the heading, by title, as defined by the user settings from the TOC matches.
|
548 |
+
*
|
549 |
+
* @see ezTOC_Post::extractHeadings()
|
550 |
+
*
|
551 |
+
* @access private
|
552 |
+
* @since 2.0
|
553 |
+
*
|
554 |
+
* @param array $matches The headings from the post content extracted with preg_match_all().
|
555 |
+
*
|
556 |
+
* @return array
|
557 |
+
*/
|
558 |
+
private function excludeHeadings( &$matches ) {
|
559 |
+
|
560 |
+
$exclude = get_post_meta( $this->post->ID, '_ez-toc-exclude', true );
|
561 |
+
|
562 |
+
if ( empty( $exclude ) ) {
|
563 |
+
|
564 |
+
$exclude = ezTOC_Option::get( 'exclude' );
|
565 |
+
}
|
566 |
+
|
567 |
+
if ( $exclude ) {
|
568 |
+
|
569 |
+
$excluded_headings = explode( '|', $exclude );
|
570 |
+
$excluded_count = count( $excluded_headings );
|
571 |
+
|
572 |
+
if ( $excluded_count > 0 ) {
|
573 |
+
|
574 |
+
for ( $j = 0; $j < $excluded_count; $j++ ) {
|
575 |
+
|
576 |
+
$excluded_headings[ $j ] = preg_quote( $excluded_headings[ $j ] );
|
577 |
+
|
578 |
+
// escape some regular expression characters
|
579 |
+
// others: http://www.php.net/manual/en/regexp.reference.meta.php
|
580 |
+
$excluded_headings[ $j ] = str_replace(
|
581 |
+
array( '\*', '/', '%' ),
|
582 |
+
array( '.*', '\/', '\%' ),
|
583 |
+
trim( $excluded_headings[ $j ] )
|
584 |
+
);
|
585 |
+
}
|
586 |
+
|
587 |
+
$new_matches = array();
|
588 |
+
//$count = count( $matches );
|
589 |
+
|
590 |
+
//for ( $i = 0; $i < $count; $i++ ) {
|
591 |
+
foreach ( $matches as $i => $match ) {
|
592 |
+
|
593 |
+
$found = false;
|
594 |
+
|
595 |
+
$against = html_entity_decode(
|
596 |
+
wptexturize( strip_tags( str_replace( array( "\r", "\n" ), ' ', $matches[ $i ][0] ) ) ),
|
597 |
+
ENT_NOQUOTES,
|
598 |
+
get_option( 'blog_charset' )
|
599 |
+
);
|
600 |
+
|
601 |
+
for ( $j = 0; $j < $excluded_count; $j++ ) {
|
602 |
+
|
603 |
+
// Since WP manipulates the post content it is required that the excluded header and
|
604 |
+
// the actual header be manipulated similarly so a match can be made.
|
605 |
+
$pattern = html_entity_decode(
|
606 |
+
wptexturize( $excluded_headings[ $j ] ),
|
607 |
+
ENT_NOQUOTES,
|
608 |
+
get_option( 'blog_charset' )
|
609 |
+
);
|
610 |
+
|
611 |
+
if ( @preg_match( '/^' . $pattern . '$/imU', $against ) ) {
|
612 |
+
|
613 |
+
$found = true;
|
614 |
+
break;
|
615 |
+
}
|
616 |
+
}
|
617 |
+
|
618 |
+
if ( ! $found ) {
|
619 |
+
|
620 |
+
$new_matches[ $i ] = $matches[ $i ];
|
621 |
+
}
|
622 |
+
}
|
623 |
+
|
624 |
+
//if ( count( $matches ) != count( $new_matches ) ) {
|
625 |
+
|
626 |
+
$matches = $new_matches;
|
627 |
+
//}
|
628 |
+
}
|
629 |
+
}
|
630 |
+
|
631 |
+
return $matches;
|
632 |
+
}
|
633 |
+
|
634 |
+
/**
|
635 |
+
* Return the alternate headings added by the user, saved in the post meta.
|
636 |
+
*
|
637 |
+
* The result is an associative array where the `key` is the original post heading
|
638 |
+
* and the `value` is the alternate heading.
|
639 |
+
*
|
640 |
+
* @access private
|
641 |
+
* @since 2.0
|
642 |
+
*
|
643 |
+
* @return array
|
644 |
+
*/
|
645 |
+
private function getAlternateHeadings() {
|
646 |
+
|
647 |
+
$alternates = array();
|
648 |
+
$value = get_post_meta( $this->post->ID, '_ez-toc-alttext', true );
|
649 |
+
|
650 |
+
if ( $value ) {
|
651 |
+
|
652 |
+
$headings = preg_split( '/\r\n|[\r\n]/', $value );
|
653 |
+
$count = count( $headings );
|
654 |
+
|
655 |
+
if ( $headings ) {
|
656 |
+
|
657 |
+
for ( $k = 0; $k < $count; $k++ ) {
|
658 |
+
|
659 |
+
$heading = explode( '|', $headings[ $k ] );
|
660 |
+
|
661 |
+
/**
|
662 |
+
* @link https://wordpress.org/support/topic/undefined-offset-1-home-blog-public-wp-content-plugins-easy-table-of-contents/
|
663 |
+
*/
|
664 |
+
if ( ! is_array( $heading) ||
|
665 |
+
! array_key_exists( 0, $heading ) ||
|
666 |
+
! array_key_exists( 1, $heading )
|
667 |
+
) {
|
668 |
+
continue;
|
669 |
+
}
|
670 |
+
|
671 |
+
if ( 0 < strlen( $heading[0] ) && 0 < strlen( $heading[1] ) ) {
|
672 |
+
|
673 |
+
$alternates[ $heading[0] ] = $heading[1];
|
674 |
+
}
|
675 |
+
}
|
676 |
+
|
677 |
+
}
|
678 |
+
|
679 |
+
}
|
680 |
+
|
681 |
+
return $alternates;
|
682 |
+
}
|
683 |
+
|
684 |
+
/**
|
685 |
+
* Add the alternate headings to the array.
|
686 |
+
*
|
687 |
+
* @see ezTOC_Post::extractHeadings()
|
688 |
+
*
|
689 |
+
* @access private
|
690 |
+
* @since 2.0
|
691 |
+
*
|
692 |
+
* @param array $matches The heading from the post content extracted with preg_match_all().
|
693 |
+
*
|
694 |
+
* @return array
|
695 |
+
*/
|
696 |
+
private function alternateHeadings( &$matches ) {
|
697 |
+
|
698 |
+
$alt_headings = $this->getAlternateHeadings();
|
699 |
+
//$count = count( $matches );
|
700 |
+
|
701 |
+
if ( 0 < count( $alt_headings ) ) {
|
702 |
+
|
703 |
+
//for ( $i = 0; $i < $count; $i++ ) {
|
704 |
+
foreach ( $matches as $i => $match ) {
|
705 |
+
|
706 |
+
foreach ( $alt_headings as $original_heading => $alt_heading ) {
|
707 |
+
|
708 |
+
// Cleanup and texturize so alt heading can match heading in post content.
|
709 |
+
$original_heading = wptexturize( trim( $original_heading ) );
|
710 |
+
|
711 |
+
// Deal with special characters such as non-breakable space.
|
712 |
+
$original_heading = str_replace(
|
713 |
+
array( "\xc2\xa0" ),
|
714 |
+
array( ' ' ),
|
715 |
+
$original_heading
|
716 |
+
);
|
717 |
+
|
718 |
+
// Escape for regular expression.
|
719 |
+
$original_heading = preg_quote( $original_heading );
|
720 |
+
|
721 |
+
// Escape for regular expression some other characters: http://www.php.net/manual/en/regexp.reference.meta.php
|
722 |
+
$original_heading = str_replace(
|
723 |
+
array( '\*', '/', '%' ),
|
724 |
+
array( '.*', '\/', '\%' ),
|
725 |
+
$original_heading
|
726 |
+
);
|
727 |
+
|
728 |
+
// Cleanup subject so alt heading can match heading in post content.
|
729 |
+
$subject = strip_tags( $matches[ $i ][0] );
|
730 |
+
|
731 |
+
// Deal with special characters such as non-breakable space.
|
732 |
+
$subject = str_replace(
|
733 |
+
array( "\xc2\xa0" ),
|
734 |
+
array( ' ' ),
|
735 |
+
$subject
|
736 |
+
);
|
737 |
+
|
738 |
+
if ( @preg_match( '/^' . $original_heading . '$/imU', $subject ) ) {
|
739 |
+
|
740 |
+
$matches[ $i ]['alternate'] = $alt_heading;
|
741 |
+
}
|
742 |
+
}
|
743 |
+
}
|
744 |
+
}
|
745 |
+
|
746 |
+
return $matches;
|
747 |
+
}
|
748 |
+
|
749 |
+
/**
|
750 |
+
* Add the heading `id` to the array.
|
751 |
+
*
|
752 |
+
* @see ezTOC_Post::extractHeadings()
|
753 |
+
*
|
754 |
+
* @access private
|
755 |
+
* @since 2.0
|
756 |
+
*
|
757 |
+
* @param array $matches The heading from the post content extracted with preg_match_all().
|
758 |
+
*
|
759 |
+
* @return mixed
|
760 |
+
*/
|
761 |
+
private function headingIDs( &$matches ) {
|
762 |
+
|
763 |
+
//$count = count( $matches );
|
764 |
+
|
765 |
+
//for ( $i = 0; $i < $count; $i++ ) {
|
766 |
+
foreach ( $matches as $i => $match ) {
|
767 |
+
|
768 |
+
$matches[ $i ]['id'] = $this->generateHeadingIDFromTitle( $matches[ $i ][0] );
|
769 |
+
}
|
770 |
+
|
771 |
+
return $matches;
|
772 |
+
}
|
773 |
+
|
774 |
+
/**
|
775 |
+
* Create unique heading ID from heading string.
|
776 |
+
*
|
777 |
+
* @access private
|
778 |
+
* @since 2.0
|
779 |
+
*
|
780 |
+
* @param string $heading
|
781 |
+
*
|
782 |
+
* @return bool|string
|
783 |
+
*/
|
784 |
+
private function generateHeadingIDFromTitle( $heading ) {
|
785 |
+
|
786 |
+
$return = false;
|
787 |
+
|
788 |
+
if ( $heading ) {
|
789 |
+
|
790 |
+
// WP entity encodes the post content.
|
791 |
+
$return = html_entity_decode( $heading, ENT_QUOTES, get_option( 'blog_charset' ) );
|
792 |
+
$return = br2( $return, ' ' );
|
793 |
+
$return = trim( strip_tags( $return ) );
|
794 |
+
|
795 |
+
// Convert accented characters to ASCII.
|
796 |
+
$return = remove_accents( $return );
|
797 |
+
|
798 |
+
// replace newlines with spaces (eg when headings are split over multiple lines)
|
799 |
+
$return = str_replace( array( "\r", "\n", "\n\r", "\r\n" ), ' ', $return );
|
800 |
+
|
801 |
+
// Remove `&` and ` ` NOTE: in order to strip "hidden" ` `,
|
802 |
+
// title needs to be converted to HTML entities.
|
803 |
+
// @link https://stackoverflow.com/a/21801444/5351316
|
804 |
+
$return = htmlentities2( $return );
|
805 |
+
$return = str_replace( array( '&', ' ' ), ' ', $return );
|
806 |
+
$return = html_entity_decode( $return, ENT_QUOTES, get_option( 'blog_charset' ) );
|
807 |
+
|
808 |
+
// remove non alphanumeric chars
|
809 |
+
//$return = preg_replace( '/[^a-zA-Z0-9 \-_]*/', '', $return );
|
810 |
+
$return = preg_replace( '/[\x00-\x1F\x7F]*/u', '', $return );
|
811 |
+
|
812 |
+
// Reserved Characters.
|
813 |
+
// * ' ( ) ; : @ & = + $ , / ? # [ ]
|
814 |
+
$return = str_replace(
|
815 |
+
array( '*', '\'', '(', ')', ';', '@', '&', '=', '+', '$', ',', '/', '?', '#', '[', ']' ),
|
816 |
+
'',
|
817 |
+
$return
|
818 |
+
);
|
819 |
+
|
820 |
+
// Unsafe Characters.
|
821 |
+
// % { } | \ ^ ~ [ ] `
|
822 |
+
$return = str_replace(
|
823 |
+
array( '%', '{', '}', '|', '\\', '^', '~', '[', ']', '`' ),
|
824 |
+
'',
|
825 |
+
$return
|
826 |
+
);
|
827 |
+
|
828 |
+
// Special Characters.
|
829 |
+
// $ - _ . + ! * ' ( ) ,
|
830 |
+
$return = str_replace(
|
831 |
+
array( '$', '.', '+', '!', '*', '\'', '(', ')', ',' ),
|
832 |
+
'',
|
833 |
+
$return
|
834 |
+
);
|
835 |
+
|
836 |
+
// Dashes
|
837 |
+
// Special Characters.
|
838 |
+
// - (minus) - (dash) – (en dash) — (em dash)
|
839 |
+
$return = str_replace(
|
840 |
+
array( '-', '-', '–', '—' ),
|
841 |
+
'-',
|
842 |
+
$return
|
843 |
+
);
|
844 |
+
|
845 |
+
// Curley quotes.
|
846 |
+
// ‘ (curly single open quote) ’ (curly single close quote) “ (curly double open quote) ” (curly double close quote)
|
847 |
+
$return = str_replace(
|
848 |
+
array( '‘', '’', '“', '”' ),
|
849 |
+
'',
|
850 |
+
$return
|
851 |
+
);
|
852 |
+
|
853 |
+
// AMP/Caching plugins seems to break URL with the following characters, so lets replace them.
|
854 |
+
$return = str_replace( array( ':' ), '_', $return );
|
855 |
+
|
856 |
+
// Convert space characters to an `_` (underscore).
|
857 |
+
$return = preg_replace( '/\s+/', '_', $return );
|
858 |
+
|
859 |
+
// Replace multiple `-` (hyphen) with a single `-` (hyphen).
|
860 |
+
$return = preg_replace( '/-+/', '-', $return );
|
861 |
+
|
862 |
+
// Replace multiple `_` (underscore) with a single `_` (underscore).
|
863 |
+
$return = preg_replace( '/_+/', '_', $return );
|
864 |
+
|
865 |
+
// Remove trailing `-` (hyphen) and `_` (underscore).
|
866 |
+
$return = rtrim( $return, '-_' );
|
867 |
+
|
868 |
+
/*
|
869 |
+
* Encode URI based on ECMA-262.
|
870 |
+
*
|
871 |
+
* Only required to support the jQuery smoothScroll library.
|
872 |
+
*
|
873 |
+
* @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURI#Description
|
874 |
+
* @link https://stackoverflow.com/a/19858404/5351316
|
875 |
+
*/
|
876 |
+
$return = preg_replace_callback(
|
877 |
+
"{[^0-9a-z_.!~*'();,/?:@&=+$#-]}i",
|
878 |
+
function( $m ) {
|
879 |
+
|
880 |
+
return sprintf( '%%%02X', ord( $m[0] ) );
|
881 |
+
},
|
882 |
+
$return
|
883 |
+
);
|
884 |
+
|
885 |
+
// lowercase everything?
|
886 |
+
if ( ezTOC_Option::get( 'lowercase' ) ) {
|
887 |
+
|
888 |
+
$return = strtolower( $return );
|
889 |
+
}
|
890 |
+
|
891 |
+
// if blank, then prepend with the fragment prefix
|
892 |
+
// blank anchors normally appear on sites that don't use the latin charset
|
893 |
+
if ( ! $return ) {
|
894 |
+
|
895 |
+
$return = ( ezTOC_Option::get( 'fragment_prefix' ) ) ? ezTOC_Option::get( 'fragment_prefix' ) : '_';
|
896 |
+
}
|
897 |
+
|
898 |
+
// hyphenate?
|
899 |
+
if ( ezTOC_Option::get( 'hyphenate' ) ) {
|
900 |
+
|
901 |
+
$return = str_replace( '_', '-', $return );
|
902 |
+
$return = preg_replace( '/-+/', '-', $return );
|
903 |
+
}
|
904 |
+
}
|
905 |
+
|
906 |
+
if ( array_key_exists( $return, $this->collision_collector ) ) {
|
907 |
+
|
908 |
+
$this->collision_collector[ $return ]++;
|
909 |
+
$return .= '-' . $this->collision_collector[ $return ];
|
910 |
+
|
911 |
+
} else {
|
912 |
+
|
913 |
+
$this->collision_collector[ $return ] = 1;
|
914 |
+
}
|
915 |
+
|
916 |
+
return apply_filters( 'ez_toc_url_anchor_target', $return, $heading );
|
917 |
+
}
|
918 |
+
|
919 |
+
/**
|
920 |
+
* Remove any empty headings from the TOC.
|
921 |
+
*
|
922 |
+
* @access private
|
923 |
+
* @since 2.0
|
924 |
+
*
|
925 |
+
* @param array $matches The heading from the post content extracted with preg_match_all().
|
926 |
+
*
|
927 |
+
* @return array
|
928 |
+
*/
|
929 |
+
private function removeEmptyHeadings( &$matches ) {
|
930 |
+
|
931 |
+
$new_matches = array();
|
932 |
+
//$count = count( $matches );
|
933 |
+
|
934 |
+
//for ( $i = 0; $i < $count; $i ++ ) {
|
935 |
+
foreach ( $matches as $i => $match ) {
|
936 |
+
|
937 |
+
if ( trim( strip_tags( $matches[ $i ][0] ) ) != false ) {
|
938 |
+
|
939 |
+
$new_matches[ $i ] = $matches[ $i ];
|
940 |
+
}
|
941 |
+
}
|
942 |
+
|
943 |
+
//if ( count( $matches ) != count( $new_matches ) ) {
|
944 |
+
|
945 |
+
$matches = $new_matches;
|
946 |
+
//}
|
947 |
+
|
948 |
+
return $matches;
|
949 |
+
}
|
950 |
+
|
951 |
+
/**
|
952 |
+
* Whether or not the post has TOC items.
|
953 |
+
*
|
954 |
+
* @see ezTOC_Post::extractHeadings()
|
955 |
+
*
|
956 |
+
* @access public
|
957 |
+
* @since 2.0
|
958 |
+
*
|
959 |
+
* @return bool
|
960 |
+
*/
|
961 |
+
public function hasTOCItems() {
|
962 |
+
|
963 |
+
return $this->hasTOCItems;
|
964 |
+
}
|
965 |
+
|
966 |
+
/**
|
967 |
+
* Get the headings of the current page of the post.
|
968 |
+
*
|
969 |
+
* @access public
|
970 |
+
* @since 2.0
|
971 |
+
*
|
972 |
+
* @param int|null $page
|
973 |
+
*
|
974 |
+
* @return array
|
975 |
+
*/
|
976 |
+
public function getHeadings( $page = null ) {
|
977 |
+
|
978 |
+
$headings = array();
|
979 |
+
|
980 |
+
if ( is_null( $page ) ) {
|
981 |
+
|
982 |
+
$page = $this->getCurrentPage();
|
983 |
+
}
|
984 |
+
|
985 |
+
if ( isset( $this->pages[ $page ] ) ) {
|
986 |
+
|
987 |
+
//$headings = wp_list_pluck( $this->pages[ $page ]['headings'], 0 );
|
988 |
+
|
989 |
+
$matches = $this->pages[ $page ]['headings'];
|
990 |
+
//$count = count( $matches );
|
991 |
+
|
992 |
+
//for ( $i = 0; $i < $count; $i++ ) {
|
993 |
+
foreach ( $matches as $i => $match ) {
|
994 |
+
|
995 |
+
//$anchor = $matches[ $i ]['id'];
|
996 |
+
$headings[] = str_replace(
|
997 |
+
array(
|
998 |
+
$matches[ $i ][1], // start of heading
|
999 |
+
'</h' . $matches[ $i ][2] . '>' // end of heading
|
1000 |
+
),
|
1001 |
+
array(
|
1002 |
+
'>',
|
1003 |
+
'</h' . $matches[ $i ][2] . '>'
|
1004 |
+
),
|
1005 |
+
$matches[ $i ][0]
|
1006 |
+
);
|
1007 |
+
}
|
1008 |
+
}
|
1009 |
+
|
1010 |
+
return $headings;
|
1011 |
+
}
|
1012 |
+
|
1013 |
+
/**
|
1014 |
+
* Get the heading with in page anchors of the current page of the post.
|
1015 |
+
*
|
1016 |
+
* @access public
|
1017 |
+
* @since 2.0
|
1018 |
+
*
|
1019 |
+
* @param int|null $page
|
1020 |
+
*
|
1021 |
+
* @return array
|
1022 |
+
*/
|
1023 |
+
public function getHeadingsWithAnchors( $page = null ) {
|
1024 |
+
|
1025 |
+
$headings = array();
|
1026 |
+
|
1027 |
+
if ( is_null( $page ) ) {
|
1028 |
+
|
1029 |
+
$page = $this->getCurrentPage();
|
1030 |
+
}
|
1031 |
+
|
1032 |
+
if ( isset( $this->pages[ $page ] ) ) {
|
1033 |
+
|
1034 |
+
$matches = $this->pages[ $page ]['headings'];
|
1035 |
+
//$count = count( $matches );
|
1036 |
+
|
1037 |
+
//for ( $i = 0; $i < $count; $i++ ) {
|
1038 |
+
foreach ( $matches as $i => $match ) {
|
1039 |
+
|
1040 |
+
$anchor = $matches[ $i ]['id'];
|
1041 |
+
$headings[] = str_replace(
|
1042 |
+
array(
|
1043 |
+
$matches[ $i ][1], // start of heading
|
1044 |
+
'</h' . $matches[ $i ][2] . '>' // end of heading
|
1045 |
+
),
|
1046 |
+
array(
|
1047 |
+
'><span class="ez-toc-section" id="' . $anchor . '"></span>',
|
1048 |
+
'<span class="ez-toc-section-end"></span></h' . $matches[ $i ][2] . '>'
|
1049 |
+
),
|
1050 |
+
$matches[ $i ][0]
|
1051 |
+
);
|
1052 |
+
}
|
1053 |
+
}
|
1054 |
+
|
1055 |
+
return $headings;
|
1056 |
+
}
|
1057 |
+
|
1058 |
+
/**
|
1059 |
+
* Get the post TOC list.
|
1060 |
+
*
|
1061 |
+
* @access public
|
1062 |
+
* @since 2.0
|
1063 |
+
*
|
1064 |
+
* @return string
|
1065 |
+
*/
|
1066 |
+
public function getTOCList() {
|
1067 |
+
|
1068 |
+
$html = '';
|
1069 |
+
|
1070 |
+
if ( $this->hasTOCItems ) {
|
1071 |
+
|
1072 |
+
foreach ( $this->pages as $page => $attribute ) {
|
1073 |
+
|
1074 |
+
$html .= $this->createTOC( $page, $attribute['headings'] );
|
1075 |
+
}
|
1076 |
+
|
1077 |
+
$html = '<ul class="ez-toc-list ez-toc-list-level-1">' . $html . '</ul>';
|
1078 |
+
}
|
1079 |
+
|
1080 |
+
return $html;
|
1081 |
+
}
|
1082 |
+
|
1083 |
+
/**
|
1084 |
+
* Get the post TOC content block.
|
1085 |
+
*
|
1086 |
+
* @access public
|
1087 |
+
* @since 2.0
|
1088 |
+
*
|
1089 |
+
* @return string
|
1090 |
+
*/
|
1091 |
+
public function getTOC() {
|
1092 |
+
|
1093 |
+
$class = array( 'ez-toc-v' . str_replace( '.', '_', ezTOC::VERSION ) );
|
1094 |
+
$html = '';
|
1095 |
+
|
1096 |
+
if ( $this->hasTOCItems() ) {
|
1097 |
+
|
1098 |
+
// wrapping css classes
|
1099 |
+
switch ( ezTOC_Option::get( 'wrapping' ) ) {
|
1100 |
+
|
1101 |
+
case 'left':
|
1102 |
+
$class[] = 'ez-toc-wrap-left';
|
1103 |
+
break;
|
1104 |
+
|
1105 |
+
case 'right':
|
1106 |
+
$class[] = 'ez-toc-wrap-right';
|
1107 |
+
break;
|
1108 |
+
|
1109 |
+
case 'none':
|
1110 |
+
default:
|
1111 |
+
// do nothing
|
1112 |
+
}
|
1113 |
+
|
1114 |
+
if ( ezTOC_Option::get( 'show_hierarchy' ) ) {
|
1115 |
+
|
1116 |
+
$class[] = 'counter-hierarchy';
|
1117 |
+
|
1118 |
+
} else {
|
1119 |
+
|
1120 |
+
$class[] .= 'counter-flat';
|
1121 |
+
}
|
1122 |
+
|
1123 |
+
switch ( ezTOC_Option::get( 'counter' ) ) {
|
1124 |
+
|
1125 |
+
case 'numeric':
|
1126 |
+
$class[] .= 'counter-numeric';
|
1127 |
+
break;
|
1128 |
+
|
1129 |
+
case 'roman':
|
1130 |
+
$class[] = 'counter-roman';
|
1131 |
+
break;
|
1132 |
+
|
1133 |
+
case 'decimal':
|
1134 |
+
$class[] = 'counter-decimal';
|
1135 |
+
break;
|
1136 |
+
}
|
1137 |
+
|
1138 |
+
// colour themes
|
1139 |
+
switch ( ezTOC_Option::get( 'theme' ) ) {
|
1140 |
+
|
1141 |
+
case 'light-blue':
|
1142 |
+
$class[] = 'ez-toc-light-blue';
|
1143 |
+
break;
|
1144 |
+
|
1145 |
+
case 'white':
|
1146 |
+
$class[] = 'ez-toc-white';
|
1147 |
+
break;
|
1148 |
+
|
1149 |
+
case 'black':
|
1150 |
+
$class[] = 'ez-toc-black';
|
1151 |
+
break;
|
1152 |
+
|
1153 |
+
case 'transparent':
|
1154 |
+
$class[] .= 'ez-toc-transparent';
|
1155 |
+
break;
|
1156 |
+
|
1157 |
+
case 'grey':
|
1158 |
+
$class[] = 'ez-toc-grey';
|
1159 |
+
break;
|
1160 |
+
}
|
1161 |
+
|
1162 |
+
$custom_classes = ezTOC_Option::get( 'css_container_class', '' );
|
1163 |
+
|
1164 |
+
if ( 0 < strlen( $custom_classes ) ) {
|
1165 |
+
|
1166 |
+
$custom_classes = explode( ' ', $custom_classes );
|
1167 |
+
$custom_classes = apply_filters( 'ez_toc_container_class', $custom_classes, $this );
|
1168 |
+
|
1169 |
+
if ( is_array( $custom_classes ) ) {
|
1170 |
+
|
1171 |
+
$class = array_merge( $class, $custom_classes );
|
1172 |
+
}
|
1173 |
+
}
|
1174 |
+
|
1175 |
+
$class = array_filter( $class );
|
1176 |
+
$class = array_map( 'trim', $class );
|
1177 |
+
$class = array_map( 'sanitize_html_class', $class );
|
1178 |
+
|
1179 |
+
$html .= '<div id="ez-toc-container" class="' . implode( ' ', $class ) . '">' . PHP_EOL;
|
1180 |
+
|
1181 |
+
if ( ezTOC_Option::get( 'show_heading_text' ) ) {
|
1182 |
+
|
1183 |
+
$toc_title = ezTOC_Option::get( 'heading_text' );
|
1184 |
+
|
1185 |
+
if ( strpos( $toc_title, '%PAGE_TITLE%' ) !== false ) {
|
1186 |
+
|
1187 |
+
$toc_title = str_replace( '%PAGE_TITLE%', get_the_title(), $toc_title );
|
1188 |
+
}
|
1189 |
+
|
1190 |
+
if ( strpos( $toc_title, '%PAGE_NAME%' ) !== false ) {
|
1191 |
+
|
1192 |
+
$toc_title = str_replace( '%PAGE_NAME%', get_the_title(), $toc_title );
|
1193 |
+
}
|
1194 |
+
|
1195 |
+
if (ezTOC_Option::get( 'toc_loading' ) != 'css') {
|
1196 |
+
$html .= '<div class="ez-toc-title-container">' . PHP_EOL;
|
1197 |
+
}
|
1198 |
+
|
1199 |
+
$html .= '<p class="ez-toc-title">' . esc_html__( htmlentities( $toc_title, ENT_COMPAT, 'UTF-8' ), 'easy-table-of-contents' ). '</p>' . PHP_EOL;
|
1200 |
+
|
1201 |
+
if (ezTOC_Option::get( 'toc_loading' ) != 'css') {
|
1202 |
+
$html .= '<span class="ez-toc-title-toggle">';
|
1203 |
+
}
|
1204 |
+
|
1205 |
+
if ( ezTOC_Option::get( 'visibility' ) ) {
|
1206 |
+
if (ezTOC_Option::get( 'toc_loading' ) != 'css') {
|
1207 |
+
$html .= '<a class="ez-toc-pull-right ez-toc-btn ez-toc-btn-xs ez-toc-btn-default ez-toc-toggle" style="display: none;"><i class="ez-toc-glyphicon ez-toc-icon-toggle"></i></a>';
|
1208 |
+
}else{
|
1209 |
+
$html .= '<label for="item"><i class="ez-toc-glyphicon ez-toc-icon-toggle"></i></label><input type="checkbox" id="item">';
|
1210 |
+
}
|
1211 |
+
}
|
1212 |
+
|
1213 |
+
if (ezTOC_Option::get( 'toc_loading' ) != 'css') {
|
1214 |
+
$html .= '</span>';
|
1215 |
+
}
|
1216 |
+
if (ezTOC_Option::get( 'toc_loading' ) != 'css') {
|
1217 |
+
$html .= '</div>' . PHP_EOL;
|
1218 |
+
}
|
1219 |
+
}
|
1220 |
+
|
1221 |
+
ob_start();
|
1222 |
+
do_action( 'ez_toc_before' );
|
1223 |
+
$html .= ob_get_clean();
|
1224 |
+
|
1225 |
+
$html .= '<nav>' . $this->getTOCList() . '</nav>';
|
1226 |
+
|
1227 |
+
ob_start();
|
1228 |
+
do_action( 'ez_toc_after' );
|
1229 |
+
$html .= ob_get_clean();
|
1230 |
+
|
1231 |
+
$html .= '</div>' . PHP_EOL;
|
1232 |
+
|
1233 |
+
// Enqueue the script.
|
1234 |
+
wp_enqueue_script( 'ez-toc-js' );
|
1235 |
+
}
|
1236 |
+
|
1237 |
+
return $html;
|
1238 |
+
}
|
1239 |
+
|
1240 |
+
/**
|
1241 |
+
* Displays the post's TOC.
|
1242 |
+
*
|
1243 |
+
* @access public
|
1244 |
+
* @since 2.0
|
1245 |
+
*/
|
1246 |
+
public function toc() {
|
1247 |
+
|
1248 |
+
echo $this->getTOC();
|
1249 |
+
}
|
1250 |
+
|
1251 |
+
/**
|
1252 |
+
* Generate the TOC list items for a given page within a post.
|
1253 |
+
*
|
1254 |
+
* @access private
|
1255 |
+
* @since 2.0
|
1256 |
+
*
|
1257 |
+
* @param int $page The page of the post to create the TOC items for.
|
1258 |
+
* @param array $matches The heading from the post content extracted with preg_match_all().
|
1259 |
+
*
|
1260 |
+
* @return string The HTML list of TOC items.
|
1261 |
+
*/
|
1262 |
+
private function createTOC( $page, $matches ) {
|
1263 |
+
|
1264 |
+
// Whether or not the TOC should be built flat or hierarchical.
|
1265 |
+
$hierarchical = ezTOC_Option::get( 'show_hierarchy' );
|
1266 |
+
$html = '';
|
1267 |
+
|
1268 |
+
if ( $hierarchical ) {
|
1269 |
+
|
1270 |
+
$current_depth = 100; // headings can't be larger than h6 but 100 as a default to be sure
|
1271 |
+
$numbered_items = array();
|
1272 |
+
$numbered_items_min = null;
|
1273 |
+
|
1274 |
+
// reset the internal collision collection
|
1275 |
+
/** @todo does this need to be used??? */
|
1276 |
+
//self::$collision_collector = array();
|
1277 |
+
|
1278 |
+
// find the minimum heading to establish our baseline
|
1279 |
+
//for ( $i = 0; $i < count( $matches ); $i ++ ) {
|
1280 |
+
foreach ( $matches as $i => $match ) {
|
1281 |
+
if ( $current_depth > $matches[ $i ][2] ) {
|
1282 |
+
$current_depth = (int) $matches[ $i ][2];
|
1283 |
+
}
|
1284 |
+
}
|
1285 |
+
|
1286 |
+
$numbered_items[ $current_depth ] = 0;
|
1287 |
+
$numbered_items_min = $current_depth;
|
1288 |
+
|
1289 |
+
//for ( $i = 0; $i < count( $matches ); $i ++ ) {
|
1290 |
+
foreach ( $matches as $i => $match ) {
|
1291 |
+
|
1292 |
+
$level = $matches[ $i ][2];
|
1293 |
+
$count = $i + 1;
|
1294 |
+
|
1295 |
+
if ( $current_depth == (int) $matches[ $i ][2] ) {
|
1296 |
+
|
1297 |
+
$html .= '<li class="ez-toc-page-' . $page . ' ez-toc-heading-level-' . $current_depth . '">';
|
1298 |
+
}
|
1299 |
+
|
1300 |
+
// start lists
|
1301 |
+
if ( $current_depth != (int) $matches[ $i ][2] ) {
|
1302 |
+
|
1303 |
+
for ( $current_depth; $current_depth < (int) $matches[ $i ][2]; $current_depth++ ) {
|
1304 |
+
|
1305 |
+
$numbered_items[ $current_depth + 1 ] = 0;
|
1306 |
+
$html .= '<ul class="ez-toc-list-level-' . $level . '"><li class="ez-toc-heading-level-' . $level . '">';
|
1307 |
+
}
|
1308 |
+
}
|
1309 |
+
|
1310 |
+
$title = isset( $matches[ $i ]['alternate'] ) ? $matches[ $i ]['alternate'] : $matches[ $i ][0];
|
1311 |
+
$title = br2( $title, ' ' );
|
1312 |
+
$title = strip_tags( apply_filters( 'ez_toc_title', $title ), apply_filters( 'ez_toc_title_allowable_tags', '' ) );
|
1313 |
+
|
1314 |
+
$html .= $this->createTOCItemAnchor( $page, $matches[ $i ]['id'], $title, $count );
|
1315 |
+
|
1316 |
+
// end lists
|
1317 |
+
if ( $i != count( $matches ) - 1 ) {
|
1318 |
+
|
1319 |
+
if ( $current_depth > (int) $matches[ $i + 1 ][2] ) {
|
1320 |
+
|
1321 |
+
for ( $current_depth; $current_depth > (int) $matches[ $i + 1 ][2]; $current_depth-- ) {
|
1322 |
+
|
1323 |
+
$html .= '</li></ul>';
|
1324 |
+
$numbered_items[ $current_depth ] = 0;
|
1325 |
+
}
|
1326 |
+
}
|
1327 |
+
|
1328 |
+
if ( $current_depth == (int) @$matches[ $i + 1 ][2] ) {
|
1329 |
+
|
1330 |
+
$html .= '</li>';
|
1331 |
+
}
|
1332 |
+
|
1333 |
+
} else {
|
1334 |
+
|
1335 |
+
// this is the last item, make sure we close off all tags
|
1336 |
+
for ( $current_depth; $current_depth >= $numbered_items_min; $current_depth-- ) {
|
1337 |
+
|
1338 |
+
$html .= '</li>';
|
1339 |
+
|
1340 |
+
if ( $current_depth != $numbered_items_min ) {
|
1341 |
+
$html .= '</ul>';
|
1342 |
+
}
|
1343 |
+
}
|
1344 |
+
}
|
1345 |
+
}
|
1346 |
+
|
1347 |
+
} else {
|
1348 |
+
|
1349 |
+
//for ( $i = 0; $i < count( $matches ); $i++ ) {
|
1350 |
+
foreach ( $matches as $i => $match ) {
|
1351 |
+
|
1352 |
+
$count = $i + 1;
|
1353 |
+
|
1354 |
+
$title = isset( $matches[ $i ]['alternate'] ) ? $matches[ $i ]['alternate'] : $matches[ $i ][0];
|
1355 |
+
$title = strip_tags( apply_filters( 'ez_toc_title', $title ), apply_filters( 'ez_toc_title_allowable_tags', '' ) );
|
1356 |
+
|
1357 |
+
$html .= '<li class="ez-toc-page-' . $page . '">';
|
1358 |
+
|
1359 |
+
$html .= $this->createTOCItemAnchor( $page, $matches[ $i ]['id'], $title, $count );
|
1360 |
+
|
1361 |
+
$html .= '</li>';
|
1362 |
+
}
|
1363 |
+
}
|
1364 |
+
|
1365 |
+
return $html;
|
1366 |
+
}
|
1367 |
+
|
1368 |
+
/**
|
1369 |
+
* @access private
|
1370 |
+
* @since 2.0
|
1371 |
+
*
|
1372 |
+
* @param int $page
|
1373 |
+
* @param string $id
|
1374 |
+
* @param string $title
|
1375 |
+
* @param int $count
|
1376 |
+
*
|
1377 |
+
* @return string
|
1378 |
+
*/
|
1379 |
+
private function createTOCItemAnchor( $page, $id, $title, $count ) {
|
1380 |
+
|
1381 |
+
return sprintf(
|
1382 |
+
'<a class="ez-toc-link ez-toc-heading-' . $count . '" href="%1$s" title="%2$s">%3$s</a>',
|
1383 |
+
esc_attr( $this->createTOCItemURL( $id, $page ) ),
|
1384 |
+
esc_attr( strip_tags( $title ) ),
|
1385 |
+
$title
|
1386 |
+
);
|
1387 |
+
}
|
1388 |
+
|
1389 |
+
/**
|
1390 |
+
* @access private
|
1391 |
+
* @since 2.0
|
1392 |
+
*
|
1393 |
+
* @param string $id
|
1394 |
+
* @param int $page
|
1395 |
+
*
|
1396 |
+
* @return string
|
1397 |
+
*/
|
1398 |
+
private function createTOCItemURL( $id, $page ) {
|
1399 |
+
|
1400 |
+
$current_post = $this->post->ID === $this->queriedObjectID;
|
1401 |
+
$current_page = $this->getCurrentPage();
|
1402 |
+
|
1403 |
+
if ( $page === $current_page && $current_post ) {
|
1404 |
+
|
1405 |
+
return '#' . $id;
|
1406 |
+
|
1407 |
+
} elseif ( 1 === $page ) {
|
1408 |
+
|
1409 |
+
return trailingslashit( $this->permalink ) . '#' . $id;
|
1410 |
+
|
1411 |
+
}
|
1412 |
+
|
1413 |
+
return trailingslashit( $this->permalink ) . $page . '/#' . $id;
|
1414 |
+
}
|
1415 |
+
}
|
includes/inc.admin-options-page.php
CHANGED
@@ -1,92 +1,92 @@
|
|
1 |
-
<div id='toc' class='wrap'>
|
2 |
-
<h1><?php _e( 'Table of Contents', 'easy-table-of-contents' ); ?></h1>
|
3 |
-
<div class="toc-tab-panel">
|
4 |
-
<a id="eztoc-default" class="eztoc-tablinks" data-href="no" href="#general-settings" onclick="tabToggle(event, 'general')">General</a>
|
5 |
-
<a class="eztoc-tablinks" id="eztoc-technical" href="#technical-support" onclick="tabToggle(event, 'technical')" data-href="no">Technical Support</a>
|
6 |
-
</div><!-- /.Tab panel -->
|
7 |
-
|
8 |
-
<div class="eztoc-tabcontent" id="general">
|
9 |
-
<form method="post" action="<?php echo esc_url( self_admin_url( 'options.php' ) ); ?>">
|
10 |
-
|
11 |
-
<div class="metabox-holder">
|
12 |
-
|
13 |
-
<div class="postbox" id="eztoc-general">
|
14 |
-
<h3><span><?php _e( 'General', 'easy-table-of-contents' ); ?></span></h3>
|
15 |
-
|
16 |
-
<div class="inside">
|
17 |
-
|
18 |
-
<table class="form-table">
|
19 |
-
|
20 |
-
<?php do_settings_fields( 'ez_toc_settings_general', 'ez_toc_settings_general' ); ?>
|
21 |
-
|
22 |
-
</table>
|
23 |
-
|
24 |
-
</div><!-- /.inside -->
|
25 |
-
</div><!-- /.postbox -->
|
26 |
-
|
27 |
-
</div><!-- /.metabox-holder -->
|
28 |
-
|
29 |
-
<div class="metabox-holder">
|
30 |
-
|
31 |
-
<div class="postbox" id="eztoc-appearance">
|
32 |
-
<h3><span><?php _e( 'Appearance', 'easy-table-of-contents' ); ?></span></h3>
|
33 |
-
|
34 |
-
<div class="inside">
|
35 |
-
|
36 |
-
<table class="form-table">
|
37 |
-
|
38 |
-
<?php do_settings_fields( 'ez_toc_settings_appearance', 'ez_toc_settings_appearance' ); ?>
|
39 |
-
|
40 |
-
</table>
|
41 |
-
|
42 |
-
</div><!-- /.inside -->
|
43 |
-
</div><!-- /.postbox -->
|
44 |
-
|
45 |
-
</div><!-- /.metabox-holder -->
|
46 |
-
|
47 |
-
<div class="metabox-holder">
|
48 |
-
|
49 |
-
<div class="postbox" id="eztoc-advanced">
|
50 |
-
<h3><span><?php _e( 'Advanced', 'easy-table-of-contents' ); ?></span></h3>
|
51 |
-
|
52 |
-
<div class="inside">
|
53 |
-
|
54 |
-
<table class="form-table">
|
55 |
-
|
56 |
-
<?php do_settings_fields( 'ez_toc_settings_advanced', 'ez_toc_settings_advanced' ); ?>
|
57 |
-
|
58 |
-
</table>
|
59 |
-
|
60 |
-
</div><!-- /.inside -->
|
61 |
-
</div><!-- /.postbox -->
|
62 |
-
|
63 |
-
</div><!-- /.metabox-holder -->
|
64 |
-
|
65 |
-
<?php settings_fields( 'ez-toc-settings' ); ?>
|
66 |
-
<?php submit_button( __( 'Save Changes', 'easy-table-of-contents' ) ); ?>
|
67 |
-
</form>
|
68 |
-
</div><!-- /.General Settings ended -->
|
69 |
-
|
70 |
-
<div class="eztoc_support_div eztoc-tabcontent" id="technical">
|
71 |
-
<strong><?php echo esc_html__('If you have any query, please write the query in below box or email us at','easy-table-of-contents') ?> <a href="mailto:
|
72 |
-
|
73 |
-
<ul>
|
74 |
-
<li>
|
75 |
-
<label class="support-label">Email<span class="star-mark">*</span></label>
|
76 |
-
<div class="support-input">
|
77 |
-
<input type="text" id="eztoc_query_email" name="eztoc_query_email" placeholder="email" required>
|
78 |
-
</div>
|
79 |
-
</li>
|
80 |
-
<li>
|
81 |
-
<label class="support-label">Query<span class="star-mark">*</span></label>
|
82 |
-
<div class="support-input"><textarea rows="5" cols="60" id="eztoc_query_message" name="eztoc_query_message" placeholder="Write your query"></textarea>
|
83 |
-
</div>
|
84 |
-
<div class="clear"> </div>
|
85 |
-
<span class="eztoc-query-success eztoc-result eztoc_hide"><?php echo esc_html__('Message sent successfully, Please wait we will get back to you shortly','easy-table-of-contents'); ?></span>
|
86 |
-
<span class="eztoc-query-error eztoc-result eztoc_hide"><?php echo esc_html__('Message not sent. please check your network connection','easy-table-of-contents'); ?></span>
|
87 |
-
</li>
|
88 |
-
<li><button class="button eztoc-send-query"><?php echo esc_html__('Send Message','easy-table-of-contents'); ?></button></li>
|
89 |
-
</ul>
|
90 |
-
|
91 |
-
</div><!-- /.Technical support div ended -->
|
92 |
-
</div>
|
1 |
+
<div id='toc' class='wrap'>
|
2 |
+
<h1><?php _e( 'Table of Contents', 'easy-table-of-contents' ); ?></h1>
|
3 |
+
<div class="toc-tab-panel">
|
4 |
+
<a id="eztoc-default" class="eztoc-tablinks" data-href="no" href="#general-settings" onclick="tabToggle(event, 'general')">General</a>
|
5 |
+
<a class="eztoc-tablinks" id="eztoc-technical" href="#technical-support" onclick="tabToggle(event, 'technical')" data-href="no">Technical Support</a>
|
6 |
+
</div><!-- /.Tab panel -->
|
7 |
+
|
8 |
+
<div class="eztoc-tabcontent" id="general">
|
9 |
+
<form method="post" action="<?php echo esc_url( self_admin_url( 'options.php' ) ); ?>">
|
10 |
+
|
11 |
+
<div class="metabox-holder">
|
12 |
+
|
13 |
+
<div class="postbox" id="eztoc-general">
|
14 |
+
<h3><span><?php _e( 'General', 'easy-table-of-contents' ); ?></span></h3>
|
15 |
+
|
16 |
+
<div class="inside">
|
17 |
+
|
18 |
+
<table class="form-table">
|
19 |
+
|
20 |
+
<?php do_settings_fields( 'ez_toc_settings_general', 'ez_toc_settings_general' ); ?>
|
21 |
+
|
22 |
+
</table>
|
23 |
+
|
24 |
+
</div><!-- /.inside -->
|
25 |
+
</div><!-- /.postbox -->
|
26 |
+
|
27 |
+
</div><!-- /.metabox-holder -->
|
28 |
+
|
29 |
+
<div class="metabox-holder">
|
30 |
+
|
31 |
+
<div class="postbox" id="eztoc-appearance">
|
32 |
+
<h3><span><?php _e( 'Appearance', 'easy-table-of-contents' ); ?></span></h3>
|
33 |
+
|
34 |
+
<div class="inside">
|
35 |
+
|
36 |
+
<table class="form-table">
|
37 |
+
|
38 |
+
<?php do_settings_fields( 'ez_toc_settings_appearance', 'ez_toc_settings_appearance' ); ?>
|
39 |
+
|
40 |
+
</table>
|
41 |
+
|
42 |
+
</div><!-- /.inside -->
|
43 |
+
</div><!-- /.postbox -->
|
44 |
+
|
45 |
+
</div><!-- /.metabox-holder -->
|
46 |
+
|
47 |
+
<div class="metabox-holder">
|
48 |
+
|
49 |
+
<div class="postbox" id="eztoc-advanced">
|
50 |
+
<h3><span><?php _e( 'Advanced', 'easy-table-of-contents' ); ?></span></h3>
|
51 |
+
|
52 |
+
<div class="inside">
|
53 |
+
|
54 |
+
<table class="form-table">
|
55 |
+
|
56 |
+
<?php do_settings_fields( 'ez_toc_settings_advanced', 'ez_toc_settings_advanced' ); ?>
|
57 |
+
|
58 |
+
</table>
|
59 |
+
|
60 |
+
</div><!-- /.inside -->
|
61 |
+
</div><!-- /.postbox -->
|
62 |
+
|
63 |
+
</div><!-- /.metabox-holder -->
|
64 |
+
|
65 |
+
<?php settings_fields( 'ez-toc-settings' ); ?>
|
66 |
+
<?php submit_button( __( 'Save Changes', 'easy-table-of-contents' ) ); ?>
|
67 |
+
</form>
|
68 |
+
</div><!-- /.General Settings ended -->
|
69 |
+
|
70 |
+
<div class="eztoc_support_div eztoc-tabcontent" id="technical">
|
71 |
+
<strong><?php echo esc_html__('If you have any query, please write the query in below box or email us at','easy-table-of-contents') ?> <a href="mailto:team@magazine3.in">team@magazine3.in</a> <?php echo esc_html__('we will reply to your email address shortly.','easy-table-of-contents') ?></strong>
|
72 |
+
|
73 |
+
<ul>
|
74 |
+
<li>
|
75 |
+
<label class="support-label">Email<span class="star-mark">*</span></label>
|
76 |
+
<div class="support-input">
|
77 |
+
<input type="text" id="eztoc_query_email" name="eztoc_query_email" placeholder="email" required>
|
78 |
+
</div>
|
79 |
+
</li>
|
80 |
+
<li>
|
81 |
+
<label class="support-label">Query<span class="star-mark">*</span></label>
|
82 |
+
<div class="support-input"><textarea rows="5" cols="60" id="eztoc_query_message" name="eztoc_query_message" placeholder="Write your query"></textarea>
|
83 |
+
</div>
|
84 |
+
<div class="clear"> </div>
|
85 |
+
<span class="eztoc-query-success eztoc-result eztoc_hide"><?php echo esc_html__('Message sent successfully, Please wait we will get back to you shortly','easy-table-of-contents'); ?></span>
|
86 |
+
<span class="eztoc-query-error eztoc-result eztoc_hide"><?php echo esc_html__('Message not sent. please check your network connection','easy-table-of-contents'); ?></span>
|
87 |
+
</li>
|
88 |
+
<li><button class="button eztoc-send-query"><?php echo esc_html__('Send Message','easy-table-of-contents'); ?></button></li>
|
89 |
+
</ul>
|
90 |
+
|
91 |
+
</div><!-- /.Technical support div ended -->
|
92 |
+
</div>
|
includes/inc.string-functions.php
CHANGED
@@ -1,344 +1,344 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace Easy_Plugins\Table_Of_Contents\String;
|
4 |
-
|
5 |
-
/**
|
6 |
-
* Replace `<br />` tags with parameter.
|
7 |
-
*
|
8 |
-
* @since 2.0.8
|
9 |
-
*
|
10 |
-
* @param string $string
|
11 |
-
* @param string $to
|
12 |
-
*
|
13 |
-
* @return string
|
14 |
-
*/
|
15 |
-
function br2( $string, $to = "\r\n" ) {
|
16 |
-
|
17 |
-
$string = preg_replace( '`<br[/\s]*>`i', $to, $string );
|
18 |
-
|
19 |
-
return $string;
|
20 |
-
}
|
21 |
-
|
22 |
-
/**
|
23 |
-
* Replace `<br />` tags with new lines.
|
24 |
-
*
|
25 |
-
* @link https://stackoverflow.com/a/27509016/5351316
|
26 |
-
*
|
27 |
-
* @since 2.0.8
|
28 |
-
*
|
29 |
-
* @param string $string
|
30 |
-
*
|
31 |
-
* @return string
|
32 |
-
*/
|
33 |
-
function br2nl( $string ) {
|
34 |
-
|
35 |
-
return br2( $string );
|
36 |
-
}
|
37 |
-
|
38 |
-
/**
|
39 |
-
* Pulled from WordPress formatting functions.
|
40 |
-
*
|
41 |
-
* Edited to add space before self closing tags.
|
42 |
-
*
|
43 |
-
* @since 2.0
|
44 |
-
*
|
45 |
-
* @param string $text
|
46 |
-
*
|
47 |
-
* @return string|string[]
|
48 |
-
*/
|
49 |
-
function force_balance_tags( $text ) {
|
50 |
-
$tagstack = array();
|
51 |
-
$stacksize = 0;
|
52 |
-
$tagqueue = '';
|
53 |
-
$newtext = '';
|
54 |
-
// Known single-entity/self-closing tags
|
55 |
-
$single_tags = array( 'area', 'base', 'basefont', 'br', 'col', 'command', 'embed', 'frame', 'hr', 'img', 'input', 'isindex', 'link', 'meta', 'param', 'source' );
|
56 |
-
// Tags that can be immediately nested within themselves
|
57 |
-
$nestable_tags = array( 'blockquote', 'div', 'object', 'q', 'span' );
|
58 |
-
|
59 |
-
// WP bug fix for comments - in case you REALLY meant to type '< !--'
|
60 |
-
$text = str_replace( '< !--', '< !--', $text );
|
61 |
-
// WP bug fix for LOVE <3 (and other situations with '<' before a number)
|
62 |
-
$text = preg_replace( '#<([0-9]{1})#', '<$1', $text );
|
63 |
-
|
64 |
-
/**
|
65 |
-
* Matches supported tags.
|
66 |
-
*
|
67 |
-
* To get the pattern as a string without the comments paste into a PHP
|
68 |
-
* REPL like `php -a`.
|
69 |
-
*
|
70 |
-
* @see https://html.spec.whatwg.org/#elements-2
|
71 |
-
* @see https://w3c.github.io/webcomponents/spec/custom/#valid-custom-element-name
|
72 |
-
*
|
73 |
-
* @example
|
74 |
-
* ~# php -a
|
75 |
-
* php > $s = [paste copied contents of expression below including parentheses];
|
76 |
-
* php > echo $s;
|
77 |
-
*/
|
78 |
-
$tag_pattern = (
|
79 |
-
'#<' . // Start with an opening bracket.
|
80 |
-
'(/?)' . // Group 1 - If it's a closing tag it'll have a leading slash.
|
81 |
-
'(' . // Group 2 - Tag name.
|
82 |
-
// Custom element tags have more lenient rules than HTML tag names.
|
83 |
-
'(?:[a-z](?:[a-z0-9._]*)-(?:[a-z0-9._-]+)+)' .
|
84 |
-
'|' .
|
85 |
-
// Traditional tag rules approximate HTML tag names.
|
86 |
-
'(?:[\w:]+)' .
|
87 |
-
')' .
|
88 |
-
'(?:' .
|
89 |
-
// We either immediately close the tag with its '>' and have nothing here.
|
90 |
-
'\s*' .
|
91 |
-
'(/?)' . // Group 3 - "attributes" for empty tag.
|
92 |
-
'|' .
|
93 |
-
// Or we must start with space characters to separate the tag name from the attributes (or whitespace).
|
94 |
-
'(\s+)' . // Group 4 - Pre-attribute whitespace.
|
95 |
-
'([^>]*)' . // Group 5 - Attributes.
|
96 |
-
')' .
|
97 |
-
'>#' // End with a closing bracket.
|
98 |
-
);
|
99 |
-
|
100 |
-
while ( preg_match( $tag_pattern, $text, $regex ) ) {
|
101 |
-
$full_match = $regex[0];
|
102 |
-
$has_leading_slash = ! empty( $regex[1] );
|
103 |
-
$tag_name = $regex[2];
|
104 |
-
$tag = strtolower( $tag_name );
|
105 |
-
$is_single_tag = in_array( $tag, $single_tags, true );
|
106 |
-
$pre_attribute_ws = isset( $regex[4] ) ? $regex[4] : '';
|
107 |
-
$attributes = trim( isset( $regex[5] ) ? $regex[5] : $regex[3] );
|
108 |
-
$has_self_closer = '/' === substr( $attributes, -1 );
|
109 |
-
|
110 |
-
$newtext .= $tagqueue;
|
111 |
-
|
112 |
-
$i = strpos( $text, $full_match );
|
113 |
-
$l = strlen( $full_match );
|
114 |
-
|
115 |
-
// Clear the shifter.
|
116 |
-
$tagqueue = '';
|
117 |
-
if ( $has_leading_slash ) { // End Tag.
|
118 |
-
// If too many closing tags.
|
119 |
-
if ( $stacksize <= 0 ) {
|
120 |
-
$tag = '';
|
121 |
-
// Or close to be safe $tag = '/' . $tag.
|
122 |
-
|
123 |
-
// If stacktop value = tag close value, then pop.
|
124 |
-
} elseif ( $tagstack[ $stacksize - 1 ] === $tag ) { // Found closing tag.
|
125 |
-
$tag = '</' . $tag . '>'; // Close Tag.
|
126 |
-
array_pop( $tagstack );
|
127 |
-
$stacksize--;
|
128 |
-
} else { // Closing tag not at top, search for it.
|
129 |
-
for ( $j = $stacksize - 1; $j >= 0; $j-- ) {
|
130 |
-
if ( $tagstack[ $j ] === $tag ) {
|
131 |
-
// Add tag to tagqueue.
|
132 |
-
for ( $k = $stacksize - 1; $k >= $j; $k-- ) {
|
133 |
-
$tagqueue .= '</' . array_pop( $tagstack ) . '>';
|
134 |
-
$stacksize--;
|
135 |
-
}
|
136 |
-
break;
|
137 |
-
}
|
138 |
-
}
|
139 |
-
$tag = '';
|
140 |
-
}
|
141 |
-
} else { // Begin Tag.
|
142 |
-
if ( $has_self_closer ) { // If it presents itself as a self-closing tag...
|
143 |
-
// ...but it isn't a known single-entity self-closing tag, then don't let it be treated as such and
|
144 |
-
// immediately close it with a closing tag (the tag will encapsulate no text as a result)
|
145 |
-
if ( ! $is_single_tag ) {
|
146 |
-
$attributes = trim( substr( $attributes, 0, -1 ) ) . "></$tag";
|
147 |
-
}
|
148 |
-
} elseif ( $is_single_tag ) { // ElseIf it's a known single-entity tag but it doesn't close itself, do so
|
149 |
-
$pre_attribute_ws = ' ';
|
150 |
-
$attributes .= 0 < strlen( $attributes ) ? ' /' : '/'; // EDIT: If there are attributes, add space before closing tag to match how WP insert br, hr and img tags.
|
151 |
-
} else { // It's not a single-entity tag.
|
152 |
-
// If the top of the stack is the same as the tag we want to push, close previous tag.
|
153 |
-
if ( $stacksize > 0 && ! in_array( $tag, $nestable_tags, true ) && $tagstack[ $stacksize - 1 ] === $tag ) {
|
154 |
-
$tagqueue = '</' . array_pop( $tagstack ) . '>';
|
155 |
-
$stacksize--;
|
156 |
-
}
|
157 |
-
$stacksize = array_push( $tagstack, $tag );
|
158 |
-
}
|
159 |
-
|
160 |
-
// Attributes.
|
161 |
-
if ( $has_self_closer && $is_single_tag ) {
|
162 |
-
// We need some space - avoid <br/> and prefer <br />.
|
163 |
-
$pre_attribute_ws = ' ';
|
164 |
-
}
|
165 |
-
|
166 |
-
$tag = '<' . $tag . $pre_attribute_ws . $attributes . '>';
|
167 |
-
// If already queuing a close tag, then put this tag on too.
|
168 |
-
if ( ! empty( $tagqueue ) ) {
|
169 |
-
$tagqueue .= $tag;
|
170 |
-
$tag = '';
|
171 |
-
}
|
172 |
-
}
|
173 |
-
$newtext .= substr( $text, 0, $i ) . $tag;
|
174 |
-
$text = substr( $text, $i + $l );
|
175 |
-
}
|
176 |
-
|
177 |
-
// Clear Tag Queue.
|
178 |
-
$newtext .= $tagqueue;
|
179 |
-
|
180 |
-
// Add remaining text.
|
181 |
-
$newtext .= $text;
|
182 |
-
|
183 |
-
while ( $x = array_pop( $tagstack ) ) {
|
184 |
-
$newtext .= '</' . $x . '>'; // Add remaining tags to close.
|
185 |
-
}
|
186 |
-
|
187 |
-
// WP fix for the bug with HTML comments.
|
188 |
-
$newtext = str_replace( '< !--', '<!--', $newtext );
|
189 |
-
$newtext = str_replace( '< !--', '< !--', $newtext );
|
190 |
-
|
191 |
-
return $newtext;
|
192 |
-
}
|
193 |
-
|
194 |
-
/**
|
195 |
-
* Multibyte substr_replace(). The mbstring library does not come with a multibyte equivalent of substr_replace().
|
196 |
-
* This function behaves exactly like substr_replace() even when the arguments are arrays.
|
197 |
-
*
|
198 |
-
* @link https://gist.github.com/stemar/8287074
|
199 |
-
*
|
200 |
-
* @since 2.0
|
201 |
-
*
|
202 |
-
* @param $string
|
203 |
-
* @param $replacement
|
204 |
-
* @param $start
|
205 |
-
* @param null $length
|
206 |
-
*
|
207 |
-
* @return array|string
|
208 |
-
*/
|
209 |
-
function mb_substr_replace( $string, $replacement, $start, $length = null ) {
|
210 |
-
|
211 |
-
if ( is_array( $string ) ) {
|
212 |
-
|
213 |
-
$num = count( $string );
|
214 |
-
|
215 |
-
// $replacement
|
216 |
-
$replacement = is_array( $replacement ) ? array_slice( $replacement, 0, $num ) : array_pad( array( $replacement ), $num, $replacement );
|
217 |
-
|
218 |
-
// $start
|
219 |
-
if ( is_array( $start ) ) {
|
220 |
-
$start = array_slice( $start, 0, $num );
|
221 |
-
foreach ( $start as $key => $value ) {
|
222 |
-
$start[ $key ] = is_int( $value ) ? $value : 0;
|
223 |
-
}
|
224 |
-
} else {
|
225 |
-
$start = array_pad( array( $start ), $num, $start );
|
226 |
-
}
|
227 |
-
|
228 |
-
// $length
|
229 |
-
if ( ! isset( $length ) ) {
|
230 |
-
$length = array_fill( 0, $num, 0 );
|
231 |
-
} elseif ( is_array( $length ) ) {
|
232 |
-
$length = array_slice( $length, 0, $num );
|
233 |
-
foreach ( $length as $key => $value ) {
|
234 |
-
$length[ $key ] = isset( $value ) ? ( is_int( $value ) ? $value : $num ) : 0;
|
235 |
-
}
|
236 |
-
} else {
|
237 |
-
$length = array_pad( array( $length ), $num, $length );
|
238 |
-
}
|
239 |
-
|
240 |
-
// Recursive call
|
241 |
-
return array_map( __FUNCTION__, $string, $replacement, $start, $length );
|
242 |
-
}
|
243 |
-
|
244 |
-
preg_match_all( '/./us', (string) $string, $smatches );
|
245 |
-
preg_match_all( '/./us', (string) $replacement, $rmatches );
|
246 |
-
|
247 |
-
if ( $length === null ) {
|
248 |
-
|
249 |
-
$length = mb_strlen( $string );
|
250 |
-
}
|
251 |
-
|
252 |
-
array_splice( $smatches[0], $start, $length, $rmatches[0] );
|
253 |
-
|
254 |
-
return join( $smatches[0] );
|
255 |
-
}
|
256 |
-
|
257 |
-
/**
|
258 |
-
* Returns a string with all items from the $find array replaced with their matching
|
259 |
-
* items in the $replace array. This does a one to one replacement (rather than globally).
|
260 |
-
*
|
261 |
-
* This function is multibyte safe.
|
262 |
-
*
|
263 |
-
* $find and $replace are arrays, $string is the haystack. All variables are passed by reference.
|
264 |
-
*
|
265 |
-
* @since 1.0
|
266 |
-
*
|
267 |
-
* @param bool $find
|
268 |
-
* @param bool $replace
|
269 |
-
* @param string $string
|
270 |
-
*
|
271 |
-
* @return mixed|string
|
272 |
-
*/
|
273 |
-
function mb_find_replace( &$find = false, &$replace = false, &$string = '' ) {
|
274 |
-
|
275 |
-
if ( is_array( $find ) && is_array( $replace ) && $string ) {
|
276 |
-
|
277 |
-
// check if multibyte strings are supported
|
278 |
-
if ( function_exists( 'mb_strpos' ) ) {
|
279 |
-
|
280 |
-
//for ( $i = 0; $i < count( $find ); $i ++ ) {
|
281 |
-
//
|
282 |
-
// $string = mb_substr(
|
283 |
-
// $string,
|
284 |
-
// 0,
|
285 |
-
// mb_strpos( $string, $find[ $i ] )
|
286 |
-
// ) . // everything before $find
|
287 |
-
// $replace[ $i ] . // its replacement
|
288 |
-
// mb_substr(
|
289 |
-
// $string,
|
290 |
-
// mb_strpos( $string, $find[ $i ] ) + mb_strlen( $find[ $i ] )
|
291 |
-
// ) // everything after $find
|
292 |
-
// ;
|
293 |
-
//}
|
294 |
-
|
295 |
-
for ( $i = 0; $i < count( $find ); $i ++ ) {
|
296 |
-
|
297 |
-
$needle = $find[ $i ];
|
298 |
-
$start = mb_strpos( $string, $needle );
|
299 |
-
|
300 |
-
// If heading can not be found, let try decoding entities to see if it can be found.
|
301 |
-
if ( false === $start ) {
|
302 |
-
|
303 |
-
$needle = html_entity_decode(
|
304 |
-
$needle,
|
305 |
-
ENT_QUOTES,
|
306 |
-
get_option( 'blog_charset' )
|
307 |
-
);
|
308 |
-
|
309 |
-
$needle = str_replace(array('’','“','”'), array('\'','"','"'), $needle);
|
310 |
-
|
311 |
-
$start = mb_strpos( $string, $needle );
|
312 |
-
}
|
313 |
-
|
314 |
-
/*
|
315 |
-
* `mb_strpos()` can return `false`. Only process `mb_substr_replace()` if position in string is found.
|
316 |
-
*/
|
317 |
-
if ( is_int( $start ) ) {
|
318 |
-
|
319 |
-
$length = mb_strlen( $needle );
|
320 |
-
$string = mb_substr_replace( $string, $replace[ $i ], $start, $length );
|
321 |
-
}
|
322 |
-
|
323 |
-
}
|
324 |
-
|
325 |
-
} else {
|
326 |
-
|
327 |
-
for ( $i = 0; $i < count( $find ); $i ++ ) {
|
328 |
-
|
329 |
-
$start = strpos( $string, $find[ $i ] );
|
330 |
-
$length = strlen( $find[ $i ] );
|
331 |
-
|
332 |
-
/*
|
333 |
-
* `strpos()` can return `false`. Only process `substr_replace()` if position in string is found.
|
334 |
-
*/
|
335 |
-
if ( is_int( $start ) ) {
|
336 |
-
|
337 |
-
$string = substr_replace( $string, $replace[ $i ], $start, $length );
|
338 |
-
}
|
339 |
-
}
|
340 |
-
}
|
341 |
-
}
|
342 |
-
|
343 |
-
return $string;
|
344 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace Easy_Plugins\Table_Of_Contents\String;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Replace `<br />` tags with parameter.
|
7 |
+
*
|
8 |
+
* @since 2.0.8
|
9 |
+
*
|
10 |
+
* @param string $string
|
11 |
+
* @param string $to
|
12 |
+
*
|
13 |
+
* @return string
|
14 |
+
*/
|
15 |
+
function br2( $string, $to = "\r\n" ) {
|
16 |
+
|
17 |
+
$string = preg_replace( '`<br[/\s]*>`i', $to, $string );
|
18 |
+
|
19 |
+
return $string;
|
20 |
+
}
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Replace `<br />` tags with new lines.
|
24 |
+
*
|
25 |
+
* @link https://stackoverflow.com/a/27509016/5351316
|
26 |
+
*
|
27 |
+
* @since 2.0.8
|
28 |
+
*
|
29 |
+
* @param string $string
|
30 |
+
*
|
31 |
+
* @return string
|
32 |
+
*/
|
33 |
+
function br2nl( $string ) {
|
34 |
+
|
35 |
+
return br2( $string );
|
36 |
+
}
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Pulled from WordPress formatting functions.
|
40 |
+
*
|
41 |
+
* Edited to add space before self closing tags.
|
42 |
+
*
|
43 |
+
* @since 2.0
|
44 |
+
*
|
45 |
+
* @param string $text
|
46 |
+
*
|
47 |
+
* @return string|string[]
|
48 |
+
*/
|
49 |
+
function force_balance_tags( $text ) {
|
50 |
+
$tagstack = array();
|
51 |
+
$stacksize = 0;
|
52 |
+
$tagqueue = '';
|
53 |
+
$newtext = '';
|
54 |
+
// Known single-entity/self-closing tags
|
55 |
+
$single_tags = array( 'area', 'base', 'basefont', 'br', 'col', 'command', 'embed', 'frame', 'hr', 'img', 'input', 'isindex', 'link', 'meta', 'param', 'source' );
|
56 |
+
// Tags that can be immediately nested within themselves
|
57 |
+
$nestable_tags = array( 'blockquote', 'div', 'object', 'q', 'span' );
|
58 |
+
|
59 |
+
// WP bug fix for comments - in case you REALLY meant to type '< !--'
|
60 |
+
$text = str_replace( '< !--', '< !--', $text );
|
61 |
+
// WP bug fix for LOVE <3 (and other situations with '<' before a number)
|
62 |
+
$text = preg_replace( '#<([0-9]{1})#', '<$1', $text );
|
63 |
+
|
64 |
+
/**
|
65 |
+
* Matches supported tags.
|
66 |
+
*
|
67 |
+
* To get the pattern as a string without the comments paste into a PHP
|
68 |
+
* REPL like `php -a`.
|
69 |
+
*
|
70 |
+
* @see https://html.spec.whatwg.org/#elements-2
|
71 |
+
* @see https://w3c.github.io/webcomponents/spec/custom/#valid-custom-element-name
|
72 |
+
*
|
73 |
+
* @example
|
74 |
+
* ~# php -a
|
75 |
+
* php > $s = [paste copied contents of expression below including parentheses];
|
76 |
+
* php > echo $s;
|
77 |
+
*/
|
78 |
+
$tag_pattern = (
|
79 |
+
'#<' . // Start with an opening bracket.
|
80 |
+
'(/?)' . // Group 1 - If it's a closing tag it'll have a leading slash.
|
81 |
+
'(' . // Group 2 - Tag name.
|
82 |
+
// Custom element tags have more lenient rules than HTML tag names.
|
83 |
+
'(?:[a-z](?:[a-z0-9._]*)-(?:[a-z0-9._-]+)+)' .
|
84 |
+
'|' .
|
85 |
+
// Traditional tag rules approximate HTML tag names.
|
86 |
+
'(?:[\w:]+)' .
|
87 |
+
')' .
|
88 |
+
'(?:' .
|
89 |
+
// We either immediately close the tag with its '>' and have nothing here.
|
90 |
+
'\s*' .
|
91 |
+
'(/?)' . // Group 3 - "attributes" for empty tag.
|
92 |
+
'|' .
|
93 |
+
// Or we must start with space characters to separate the tag name from the attributes (or whitespace).
|
94 |
+
'(\s+)' . // Group 4 - Pre-attribute whitespace.
|
95 |
+
'([^>]*)' . // Group 5 - Attributes.
|
96 |
+
')' .
|
97 |
+
'>#' // End with a closing bracket.
|
98 |
+
);
|
99 |
+
|
100 |
+
while ( preg_match( $tag_pattern, $text, $regex ) ) {
|
101 |
+
$full_match = $regex[0];
|
102 |
+
$has_leading_slash = ! empty( $regex[1] );
|
103 |
+
$tag_name = $regex[2];
|
104 |
+
$tag = strtolower( $tag_name );
|
105 |
+
$is_single_tag = in_array( $tag, $single_tags, true );
|
106 |
+
$pre_attribute_ws = isset( $regex[4] ) ? $regex[4] : '';
|
107 |
+
$attributes = trim( isset( $regex[5] ) ? $regex[5] : $regex[3] );
|
108 |
+
$has_self_closer = '/' === substr( $attributes, -1 );
|
109 |
+
|
110 |
+
$newtext .= $tagqueue;
|
111 |
+
|
112 |
+
$i = strpos( $text, $full_match );
|
113 |
+
$l = strlen( $full_match );
|
114 |
+
|
115 |
+
// Clear the shifter.
|
116 |
+
$tagqueue = '';
|
117 |
+
if ( $has_leading_slash ) { // End Tag.
|
118 |
+
// If too many closing tags.
|
119 |
+
if ( $stacksize <= 0 ) {
|
120 |
+
$tag = '';
|
121 |
+
// Or close to be safe $tag = '/' . $tag.
|
122 |
+
|
123 |
+
// If stacktop value = tag close value, then pop.
|
124 |
+
} elseif ( $tagstack[ $stacksize - 1 ] === $tag ) { // Found closing tag.
|
125 |
+
$tag = '</' . $tag . '>'; // Close Tag.
|
126 |
+
array_pop( $tagstack );
|
127 |
+
$stacksize--;
|
128 |
+
} else { // Closing tag not at top, search for it.
|
129 |
+
for ( $j = $stacksize - 1; $j >= 0; $j-- ) {
|
130 |
+
if ( $tagstack[ $j ] === $tag ) {
|
131 |
+
// Add tag to tagqueue.
|
132 |
+
for ( $k = $stacksize - 1; $k >= $j; $k-- ) {
|
133 |
+
$tagqueue .= '</' . array_pop( $tagstack ) . '>';
|
134 |
+
$stacksize--;
|
135 |
+
}
|
136 |
+
break;
|
137 |
+
}
|
138 |
+
}
|
139 |
+
$tag = '';
|
140 |
+
}
|
141 |
+
} else { // Begin Tag.
|
142 |
+
if ( $has_self_closer ) { // If it presents itself as a self-closing tag...
|
143 |
+
// ...but it isn't a known single-entity self-closing tag, then don't let it be treated as such and
|
144 |
+
// immediately close it with a closing tag (the tag will encapsulate no text as a result)
|
145 |
+
if ( ! $is_single_tag ) {
|
146 |
+
$attributes = trim( substr( $attributes, 0, -1 ) ) . "></$tag";
|
147 |
+
}
|
148 |
+
} elseif ( $is_single_tag ) { // ElseIf it's a known single-entity tag but it doesn't close itself, do so
|
149 |
+
$pre_attribute_ws = ' ';
|
150 |
+
$attributes .= 0 < strlen( $attributes ) ? ' /' : '/'; // EDIT: If there are attributes, add space before closing tag to match how WP insert br, hr and img tags.
|
151 |
+
} else { // It's not a single-entity tag.
|
152 |
+
// If the top of the stack is the same as the tag we want to push, close previous tag.
|
153 |
+
if ( $stacksize > 0 && ! in_array( $tag, $nestable_tags, true ) && $tagstack[ $stacksize - 1 ] === $tag ) {
|
154 |
+
$tagqueue = '</' . array_pop( $tagstack ) . '>';
|
155 |
+
$stacksize--;
|
156 |
+
}
|
157 |
+
$stacksize = array_push( $tagstack, $tag );
|
158 |
+
}
|
159 |
+
|
160 |
+
// Attributes.
|
161 |
+
if ( $has_self_closer && $is_single_tag ) {
|
162 |
+
// We need some space - avoid <br/> and prefer <br />.
|
163 |
+
$pre_attribute_ws = ' ';
|
164 |
+
}
|
165 |
+
|
166 |
+
$tag = '<' . $tag . $pre_attribute_ws . $attributes . '>';
|
167 |
+
// If already queuing a close tag, then put this tag on too.
|
168 |
+
if ( ! empty( $tagqueue ) ) {
|
169 |
+
$tagqueue .= $tag;
|
170 |
+
$tag = '';
|
171 |
+
}
|
172 |
+
}
|
173 |
+
$newtext .= substr( $text, 0, $i ) . $tag;
|
174 |
+
$text = substr( $text, $i + $l );
|
175 |
+
}
|
176 |
+
|
177 |
+
// Clear Tag Queue.
|
178 |
+
$newtext .= $tagqueue;
|
179 |
+
|
180 |
+
// Add remaining text.
|
181 |
+
$newtext .= $text;
|
182 |
+
|
183 |
+
while ( $x = array_pop( $tagstack ) ) {
|
184 |
+
$newtext .= '</' . $x . '>'; // Add remaining tags to close.
|
185 |
+
}
|
186 |
+
|
187 |
+
// WP fix for the bug with HTML comments.
|
188 |
+
$newtext = str_replace( '< !--', '<!--', $newtext );
|
189 |
+
$newtext = str_replace( '< !--', '< !--', $newtext );
|
190 |
+
|
191 |
+
return $newtext;
|
192 |
+
}
|
193 |
+
|
194 |
+
/**
|
195 |
+
* Multibyte substr_replace(). The mbstring library does not come with a multibyte equivalent of substr_replace().
|
196 |
+
* This function behaves exactly like substr_replace() even when the arguments are arrays.
|
197 |
+
*
|
198 |
+
* @link https://gist.github.com/stemar/8287074
|
199 |
+
*
|
200 |
+
* @since 2.0
|
201 |
+
*
|
202 |
+
* @param $string
|
203 |
+
* @param $replacement
|
204 |
+
* @param $start
|
205 |
+
* @param null $length
|
206 |
+
*
|
207 |
+
* @return array|string
|
208 |
+
*/
|
209 |
+
function mb_substr_replace( $string, $replacement, $start, $length = null ) {
|
210 |
+
|
211 |
+
if ( is_array( $string ) ) {
|
212 |
+
|
213 |
+
$num = count( $string );
|
214 |
+
|
215 |
+
// $replacement
|
216 |
+
$replacement = is_array( $replacement ) ? array_slice( $replacement, 0, $num ) : array_pad( array( $replacement ), $num, $replacement );
|
217 |
+
|
218 |
+
// $start
|
219 |
+
if ( is_array( $start ) ) {
|
220 |
+
$start = array_slice( $start, 0, $num );
|
221 |
+
foreach ( $start as $key => $value ) {
|
222 |
+
$start[ $key ] = is_int( $value ) ? $value : 0;
|
223 |
+
}
|
224 |
+
} else {
|
225 |
+
$start = array_pad( array( $start ), $num, $start );
|
226 |
+
}
|
227 |
+
|
228 |
+
// $length
|
229 |
+
if ( ! isset( $length ) ) {
|
230 |
+
$length = array_fill( 0, $num, 0 );
|
231 |
+
} elseif ( is_array( $length ) ) {
|
232 |
+
$length = array_slice( $length, 0, $num );
|
233 |
+
foreach ( $length as $key => $value ) {
|
234 |
+
$length[ $key ] = isset( $value ) ? ( is_int( $value ) ? $value : $num ) : 0;
|
235 |
+
}
|
236 |
+
} else {
|
237 |
+
$length = array_pad( array( $length ), $num, $length );
|
238 |
+
}
|
239 |
+
|
240 |
+
// Recursive call
|
241 |
+
return array_map( __FUNCTION__, $string, $replacement, $start, $length );
|
242 |
+
}
|
243 |
+
|
244 |
+
preg_match_all( '/./us', (string) $string, $smatches );
|
245 |
+
preg_match_all( '/./us', (string) $replacement, $rmatches );
|
246 |
+
|
247 |
+
if ( $length === null ) {
|
248 |
+
|
249 |
+
$length = mb_strlen( $string );
|
250 |
+
}
|
251 |
+
|
252 |
+
array_splice( $smatches[0], $start, $length, $rmatches[0] );
|
253 |
+
|
254 |
+
return join( $smatches[0] );
|
255 |
+
}
|
256 |
+
|
257 |
+
/**
|
258 |
+
* Returns a string with all items from the $find array replaced with their matching
|
259 |
+
* items in the $replace array. This does a one to one replacement (rather than globally).
|
260 |
+
*
|
261 |
+
* This function is multibyte safe.
|
262 |
+
*
|
263 |
+
* $find and $replace are arrays, $string is the haystack. All variables are passed by reference.
|
264 |
+
*
|
265 |
+
* @since 1.0
|
266 |
+
*
|
267 |
+
* @param bool $find
|
268 |
+
* @param bool $replace
|
269 |
+
* @param string $string
|
270 |
+
*
|
271 |
+
* @return mixed|string
|
272 |
+
*/
|
273 |
+
function mb_find_replace( &$find = false, &$replace = false, &$string = '' ) {
|
274 |
+
|
275 |
+
if ( is_array( $find ) && is_array( $replace ) && $string ) {
|
276 |
+
|
277 |
+
// check if multibyte strings are supported
|
278 |
+
if ( function_exists( 'mb_strpos' ) ) {
|
279 |
+
|
280 |
+
//for ( $i = 0; $i < count( $find ); $i ++ ) {
|
281 |
+
//
|
282 |
+
// $string = mb_substr(
|
283 |
+
// $string,
|
284 |
+
// 0,
|
285 |
+
// mb_strpos( $string, $find[ $i ] )
|
286 |
+
// ) . // everything before $find
|
287 |
+
// $replace[ $i ] . // its replacement
|
288 |
+
// mb_substr(
|
289 |
+
// $string,
|
290 |
+
// mb_strpos( $string, $find[ $i ] ) + mb_strlen( $find[ $i ] )
|
291 |
+
// ) // everything after $find
|
292 |
+
// ;
|
293 |
+
//}
|
294 |
+
|
295 |
+
for ( $i = 0; $i < count( $find ); $i ++ ) {
|
296 |
+
|
297 |
+
$needle = $find[ $i ];
|
298 |
+
$start = mb_strpos( $string, $needle );
|
299 |
+
|
300 |
+
// If heading can not be found, let try decoding entities to see if it can be found.
|
301 |
+
if ( false === $start ) {
|
302 |
+
|
303 |
+
$needle = html_entity_decode(
|
304 |
+
$needle,
|
305 |
+
ENT_QUOTES,
|
306 |
+
get_option( 'blog_charset' )
|
307 |
+
);
|
308 |
+
|
309 |
+
$needle = str_replace(array('’','“','”'), array('\'','"','"'), $needle);
|
310 |
+
|
311 |
+
$start = mb_strpos( $string, $needle );
|
312 |
+
}
|
313 |
+
|
314 |
+
/*
|
315 |
+
* `mb_strpos()` can return `false`. Only process `mb_substr_replace()` if position in string is found.
|
316 |
+
*/
|
317 |
+
if ( is_int( $start ) ) {
|
318 |
+
|
319 |
+
$length = mb_strlen( $needle );
|
320 |
+
$string = mb_substr_replace( $string, $replace[ $i ], $start, $length );
|
321 |
+
}
|
322 |
+
|
323 |
+
}
|
324 |
+
|
325 |
+
} else {
|
326 |
+
|
327 |
+
for ( $i = 0; $i < count( $find ); $i ++ ) {
|
328 |
+
|
329 |
+
$start = strpos( $string, $find[ $i ] );
|
330 |
+
$length = strlen( $find[ $i ] );
|
331 |
+
|
332 |
+
/*
|
333 |
+
* `strpos()` can return `false`. Only process `substr_replace()` if position in string is found.
|
334 |
+
*/
|
335 |
+
if ( is_int( $start ) ) {
|
336 |
+
|
337 |
+
$string = substr_replace( $string, $replace[ $i ], $start, $length );
|
338 |
+
}
|
339 |
+
}
|
340 |
+
}
|
341 |
+
}
|
342 |
+
|
343 |
+
return $string;
|
344 |
+
}
|