LuckyWP Table of Contents - Version 1.2.0

Version Description

  • Added float options: "Center" and "Right without flow".
  • Added setting "Hash Format".
  • In anchors instead "name" attribute used "id".
  • Minor enhancements in CSS for more compatible with themes.
Download this release

Release Info

Developer theluckywp
Plugin Icon 128x128 LuckyWP Table of Contents
Version 1.2.0
Comparing to
See all releases

Code changes from version 1.1.1 to 1.2.0

config/settings.php CHANGED
@@ -314,6 +314,15 @@ return [
314
  'sections' => [
315
  'main' => [
316
  'fields' => [
 
 
 
 
 
 
 
 
 
317
  'wrapNoindex' => [
318
  'label' => '',
319
  'widget' => 'checkbox',
314
  'sections' => [
315
  'main' => [
316
  'fields' => [
317
+ 'hashFormat' => [
318
+ 'label' => esc_html__('Hash Format', 'lwptoc'),
319
+ 'widget' => 'select',
320
+ 'params' => [
321
+ 'items' => Core::$plugin->getHashFormatsList(),
322
+ ],
323
+ 'default' => 'asheading',
324
+ ],
325
+
326
  'wrapNoindex' => [
327
  'label' => '',
328
  'widget' => 'checkbox',
front/assets/main.min.css CHANGED
@@ -1 +1 @@
1
- .lwptoc{margin:32px 0}.lwptoc:first-child{margin-top:16px}.lwptoc_i{padding:14px 18px 18px}.lwptoc_i DIV A{box-shadow:none!important;border:none!important;text-decoration:none!important}.lwptoc_i DIV A:active,.lwptoc_i DIV A:focus,.lwptoc_i DIV A:hover{box-shadow:none!important;border:none!important;text-decoration:none!important}.lwptoc_i DIV A:hover{border-bottom:1px dotted!important}.lwptoc_header{margin-bottom:6px}.lwptoc_toggle{margin-left:4px;font-size:80%}.lwptoc_toggle:before{content:'['}.lwptoc_toggle:after{content:']'}.lwptoc_toggle_label{margin:0 1px}.lwptoc_item_number{margin-right:2px}.lwptoc UL{list-style:none;padding:0;margin:0}.lwptoc UL UL{margin:2px 0 0 14px}.lwptoc LI{margin:2px 0 0 0;padding:0}.lwptoc LI:first-child{margin-top:0}.lwptoc-autoWidth .lwptoc_i{display:inline-block}.lwptoc-left{float:left;margin-top:0;margin-right:32px}.lwptoc-right{float:right;margin-top:0;margin-left:32px}.lwptoc-baseItems .lwptoc_items{font-size:90%}.lwptoc-light .lwptoc_i{color:#333;background:#fafafa}.lwptoc-light .lwptoc_i A{color:#3175e4}.lwptoc-light .lwptoc_i A:active,.lwptoc-light .lwptoc_i A:focus,.lwptoc-light .lwptoc_i A:hover{color:#3175e4;border-color:#3175e4}.lwptoc-light .lwptoc_items A:visited{color:#000394}.lwptoc-dark .lwptoc_i{color:#d3d5d8;background:#2b2b2b}.lwptoc-dark .lwptoc_i A{color:#96c6ff}.lwptoc-dark .lwptoc_i A:active,.lwptoc-dark .lwptoc_i A:focus,.lwptoc-dark .lwptoc_i A:hover{color:#96c6ff;border-color:#71b2ff}.lwptoc-dark .lwptoc_items A:visited{color:#53a1ff}.lwptoc-white .lwptoc_i{color:#333;background:#fff}.lwptoc-white .lwptoc_i A{color:#3175e4}.lwptoc-white .lwptoc_i A:active,.lwptoc-white .lwptoc_i A:focus,.lwptoc-white .lwptoc_i A:hover{color:#3175e4;border-color:#3175e4}.lwptoc-white .lwptoc_items A:visited{color:#000394}.lwptoc-transparent .lwptoc_i{border:1px solid #eee}
1
+ .lwptoc{margin:32px 0}.lwptoc:first-child{margin-top:16px}.lwptoc_i{padding:14px 18px 18px;text-align:left}.lwptoc_i DIV A{box-shadow:none!important;border:none!important;text-decoration:none!important}.lwptoc_i DIV A:active,.lwptoc_i DIV A:focus,.lwptoc_i DIV A:hover{box-shadow:none!important;border:none!important;text-decoration:none!important}.lwptoc_i DIV A:hover{border-bottom:1px dotted!important}.lwptoc_header{margin-bottom:6px}.lwptoc_toggle{margin-left:4px;font-size:80%}.lwptoc_toggle:before{content:'['}.lwptoc_toggle:after{content:']'}.lwptoc_toggle_label{margin:0 1px}.lwptoc_item_number{margin-right:2px}.lwptoc UL{list-style:none!important;padding:0!important;margin:0!important}.lwptoc UL UL{padding:0!important;margin:2px 0 0 14px!important}.lwptoc LI{list-style:none;margin:2px 0 0 0!important;padding:0!important}.lwptoc LI:first-child{margin-top:0!important}.lwptoc-autoWidth .lwptoc_i{display:inline-block}.lwptoc-left{float:left;margin-top:0;margin-right:32px}.lwptoc-right{float:right;margin-top:0;margin-left:32px}.lwptoc-rightwithoutflow{text-align:right}.lwptoc-rightwithoutflow .lwptoc_i{display:inline-block}.lwptoc-center{text-align:center}.lwptoc-center .lwptoc_i{margin-left:auto;margin-right:auto}.lwptoc-baseItems .lwptoc_items{font-size:90%}.lwptoc-light .lwptoc_i{color:#333;background:#fafafa}.lwptoc-light .lwptoc_i A{color:#3175e4}.lwptoc-light .lwptoc_i A:active,.lwptoc-light .lwptoc_i A:focus,.lwptoc-light .lwptoc_i A:hover{color:#3175e4;border-color:#3175e4}.lwptoc-light .lwptoc_items A:visited{color:#000394}.lwptoc-dark .lwptoc_i{color:#d3d5d8;background:#2b2b2b}.lwptoc-dark .lwptoc_i A{color:#96c6ff}.lwptoc-dark .lwptoc_i A:active,.lwptoc-dark .lwptoc_i A:focus,.lwptoc-dark .lwptoc_i A:hover{color:#96c6ff;border-color:#71b2ff}.lwptoc-dark .lwptoc_items A:visited{color:#53a1ff}.lwptoc-white .lwptoc_i{color:#333;background:#fff}.lwptoc-white .lwptoc_i A{color:#3175e4}.lwptoc-white .lwptoc_i A:active,.lwptoc-white .lwptoc_i A:focus,.lwptoc-white .lwptoc_i A:hover{color:#3175e4;border-color:#3175e4}.lwptoc-white .lwptoc_items A:visited{color:#000394}.lwptoc-transparent .lwptoc_i{border:1px solid #eee}
front/assets/main.min.js CHANGED
@@ -1 +1 @@
1
- !function(a){var t=function(t){t.each(function(){var i=a(this);i.data("smoothScroll")&&i.find(".lwptoc_items").on("click",'A[href^="#"]',function(t){t.preventDefault();var l=a("A[name="+this.hash.slice(1)+"]");if(l.length){var o=a(this).attr("href"),n=l.offset().top-i.data("smoothScrollOffset");a("html, body").animate({scrollTop:n<0?0:n},500,function(){if(l.focus(),l.is(":focus"))return!1;l.attr("tabindex","-1"),l.focus(),window.history.pushState&&window.history.pushState(null,null,o)})}})}),t.find(".lwptoc_toggle_label").click(function(){var t=a(this),l=t.closest(".lwptoc").find(".lwptoc_items"),o=t.data("label");return"none"==l.css("display")?(l.stop(!0).slideDown(300),t.data("label",t.html()).html(o)):l.stop(!0).slideUp(300,function(){t.data("label",t.html()).html(o)}),!1})};a(function(){t(a(".lwptoc"))})}(jQuery);
1
+ !function(a){var t=function(t){t.each(function(){var n=a(this);n.data("smoothScroll")&&n.find(".lwptoc_items").on("click",'A[href^="#"]',function(t){t.preventDefault();var l=a("A[id="+this.hash.slice(1)+"]");if(l.length){var o=a(this).attr("href"),i=l.offset().top-n.data("smoothScrollOffset");a("html, body").animate({scrollTop:i<0?0:i},500,function(){if(l.focus(),l.is(":focus"))return!1;l.attr("tabindex","-1"),l.focus(),window.history.pushState&&window.history.pushState(null,null,o)})}})}),t.find(".lwptoc_toggle_label").click(function(){var t=a(this),l=t.closest(".lwptoc").find(".lwptoc_items"),o=t.data("label");return"none"==l.css("display")?(l.stop(!0).slideDown(300),t.data("label",t.html()).html(o)):l.stop(!0).slideUp(300,function(){t.data("label",t.html()).html(o)}),!1})};a(function(){t(a(".lwptoc"))})}(jQuery);
front/views/body.php CHANGED
@@ -6,6 +6,7 @@
6
  * @var $labelHide string
7
  * @var $hideItems bool
8
  * @var $containerOptions array
 
9
  * @var $headerStyles array
10
  * @var $titleStyles array
11
  * @var $itemsStyles array
@@ -16,21 +17,19 @@
16
 
17
  use luckywp\tableOfContents\core\helpers\Html;
18
 
19
- echo $before . Html::beginTag('div', $containerOptions);
20
  ?>
21
- <div class="lwptoc_i">
22
- <?php if ($toggle || $title) { ?>
23
- <div class="lwptoc_header"<?= $headerStyles ? ' style="' . implode('', $headerStyles) . '"' : '' ?>>
24
- <?= $title ? '<b class="lwptoc_title"' . ($titleStyles ? ' style="' . implode('', $titleStyles) . '"' : '') . '>' . $title . '</b>' : '' ?>
25
- <?php if ($toggle) { ?>
26
- <span class="lwptoc_toggle">
27
  <a href="#" class="lwptoc_toggle_label" data-label="<?= $hideItems ? $labelHide : $labelShow ?>"><?= $hideItems ? $labelShow : $labelHide ?></a>
28
  </span>
29
- <?php } ?>
30
- </div>
31
- <?php } ?>
32
- <div class="lwptoc_items"<?= $itemsStyles ? ' style="' . implode('', $itemsStyles) . '"' : '' ?>>
33
- <?php lwptoc_items($items) ?>
34
  </div>
 
 
 
35
  </div>
36
- <?= '</div>' . $after ?>
6
  * @var $labelHide string
7
  * @var $hideItems bool
8
  * @var $containerOptions array
9
+ * @var $innerContainerOptions array
10
  * @var $headerStyles array
11
  * @var $titleStyles array
12
  * @var $itemsStyles array
17
 
18
  use luckywp\tableOfContents\core\helpers\Html;
19
 
20
+ echo $before . Html::beginTag('div', $containerOptions) . Html::beginTag('div', $innerContainerOptions);
21
  ?>
22
+ <?php if ($toggle || $title) { ?>
23
+ <div class="lwptoc_header"<?= $headerStyles ? ' style="' . implode('', $headerStyles) . '"' : '' ?>>
24
+ <?= $title ? '<b class="lwptoc_title"' . ($titleStyles ? ' style="' . implode('', $titleStyles) . '"' : '') . '>' . $title . '</b>' : '' ?>
25
+ <?php if ($toggle) { ?>
26
+ <span class="lwptoc_toggle">
 
27
  <a href="#" class="lwptoc_toggle_label" data-label="<?= $hideItems ? $labelHide : $labelShow ?>"><?= $hideItems ? $labelShow : $labelHide ?></a>
28
  </span>
29
+ <?php } ?>
 
 
 
 
30
  </div>
31
+ <?php } ?>
32
+ <div class="lwptoc_items"<?= $itemsStyles ? ' style="' . implode('', $itemsStyles) . '"' : '' ?>>
33
+ <?php lwptoc_items($items) ?>
34
  </div>
35
+ <?= '</div></div>' . $after ?>
languages/lwptoc-ru_RU.mo CHANGED
Binary file
languages/lwptoc.pot CHANGED
@@ -1,8 +1,8 @@
1
  msgid ""
2
  msgstr ""
3
  "Project-Id-Version: \n"
4
- "POT-Creation-Date: 2019-04-15 09:59+0300\n"
5
- "PO-Revision-Date: 2019-04-15 10:02+0300\n"
6
  "Last-Translator: \n"
7
  "Language-Team: \n"
8
  "Language: ru_RU\n"
@@ -140,7 +140,7 @@ msgid "Color Scheme"
140
  msgstr ""
141
 
142
  #: admin/Admin.php:193 admin/widgets/customizeModal/views/modal.php:490
143
- #: config/settings.php:322
144
  msgid "Wrap table of contents with <!--noindex--> tag"
145
  msgstr ""
146
 
@@ -257,11 +257,11 @@ msgstr ""
257
  msgid "Saved!"
258
  msgstr ""
259
 
260
- #: admin/widgets/fontSizeField/views/widget.php:16 plugin/Plugin.php:226
261
  msgid "Default"
262
  msgstr ""
263
 
264
- #: admin/widgets/fontSizeField/views/widget.php:17 plugin/Plugin.php:191
265
  msgid "Custom Value"
266
  msgstr ""
267
 
@@ -349,6 +349,10 @@ msgstr ""
349
  msgid "Post Types"
350
  msgstr ""
351
 
 
 
 
 
352
  #: core/admin/AdminController.php:46
353
  msgid "Sorry, you are not allowed to access this page."
354
  msgstr ""
@@ -453,31 +457,47 @@ msgstr ""
453
  msgid "Right"
454
  msgstr ""
455
 
456
- #: plugin/Plugin.php:175
 
 
 
 
 
 
 
 
457
  msgid "Light Colors"
458
  msgstr ""
459
 
460
- #: plugin/Plugin.php:176
461
  msgid "Dark Colors"
462
  msgstr ""
463
 
464
- #: plugin/Plugin.php:177
465
  msgid "White"
466
  msgstr ""
467
 
468
- #: plugin/Plugin.php:178
469
  msgid "Transparent"
470
  msgstr ""
471
 
472
- #: plugin/Plugin.php:189
 
 
 
 
 
 
 
 
473
  msgid "Auto"
474
  msgstr ""
475
 
476
- #: plugin/Plugin.php:190
477
  msgid "Full Width"
478
  msgstr ""
479
 
480
- #: plugin/Plugin.php:231
481
  msgid ""
482
  "Creates a table of contents for your posts/pages. Works automatically or "
483
  "manually (via shortcode or Gutenberg block)."
1
  msgid ""
2
  msgstr ""
3
  "Project-Id-Version: \n"
4
+ "POT-Creation-Date: 2019-04-23 17:49+0300\n"
5
+ "PO-Revision-Date: 2019-04-23 17:51+0300\n"
6
  "Last-Translator: \n"
7
  "Language-Team: \n"
8
  "Language: ru_RU\n"
140
  msgstr ""
141
 
142
  #: admin/Admin.php:193 admin/widgets/customizeModal/views/modal.php:490
143
+ #: config/settings.php:331
144
  msgid "Wrap table of contents with <!--noindex--> tag"
145
  msgstr ""
146
 
257
  msgid "Saved!"
258
  msgstr ""
259
 
260
+ #: admin/widgets/fontSizeField/views/widget.php:16 plugin/Plugin.php:239
261
  msgid "Default"
262
  msgstr ""
263
 
264
+ #: admin/widgets/fontSizeField/views/widget.php:17 plugin/Plugin.php:204
265
  msgid "Custom Value"
266
  msgstr ""
267
 
349
  msgid "Post Types"
350
  msgstr ""
351
 
352
+ #: config/settings.php:318
353
+ msgid "Hash Format"
354
+ msgstr ""
355
+
356
  #: core/admin/AdminController.php:46
357
  msgid "Sorry, you are not allowed to access this page."
358
  msgstr ""
457
  msgid "Right"
458
  msgstr ""
459
 
460
+ #: plugin/Plugin.php:166
461
+ msgid "Right without flow"
462
+ msgstr ""
463
+
464
+ #: plugin/Plugin.php:167
465
+ msgid "Center"
466
+ msgstr ""
467
+
468
+ #: plugin/Plugin.php:177
469
  msgid "Light Colors"
470
  msgstr ""
471
 
472
+ #: plugin/Plugin.php:178
473
  msgid "Dark Colors"
474
  msgstr ""
475
 
476
+ #: plugin/Plugin.php:179
477
  msgid "White"
478
  msgstr ""
479
 
480
+ #: plugin/Plugin.php:180
481
  msgid "Transparent"
482
  msgstr ""
483
 
484
+ #: plugin/Plugin.php:190
485
+ msgid "As heading (#Example_Heading_Text)"
486
+ msgstr ""
487
+
488
+ #: plugin/Plugin.php:191
489
+ msgid "Counter (#lpwtoc1, #lwptoc2, …)"
490
+ msgstr ""
491
+
492
+ #: plugin/Plugin.php:202
493
  msgid "Auto"
494
  msgstr ""
495
 
496
+ #: plugin/Plugin.php:203
497
  msgid "Full Width"
498
  msgstr ""
499
 
500
+ #: plugin/Plugin.php:244
501
  msgid ""
502
  "Creates a table of contents for your posts/pages. Works automatically or "
503
  "manually (via shortcode or Gutenberg block)."
luckywp-table-of-contents.php CHANGED
@@ -3,7 +3,7 @@
3
  Plugin Name: LuckyWP Table of Contents
4
  Plugin URI: https://theluckywp.com/product/table-of-contents/
5
  Description: Creates a table of contents for your posts/pages. Works automatically or manually (via shortcode or Gutenberg block).
6
- Version: 1.1.1
7
  Author: LuckyWP
8
  Author URI: https://theluckywp.com/
9
  Text Domain: lwptoc
@@ -29,6 +29,6 @@ $lwptocAutoloader->register();
29
  $lwptocAutoloader->addNamespace('luckywp\tableOfContents', __DIR__);
30
 
31
  $config = require(__DIR__ . '/config/plugin.php');
32
- (new \luckywp\tableOfContents\plugin\Plugin($config))->run('1.1.1', __FILE__, 'lwptoc_');
33
 
34
  require_once __DIR__ . '/functions.php';
3
  Plugin Name: LuckyWP Table of Contents
4
  Plugin URI: https://theluckywp.com/product/table-of-contents/
5
  Description: Creates a table of contents for your posts/pages. Works automatically or manually (via shortcode or Gutenberg block).
6
+ Version: 1.2.0
7
  Author: LuckyWP
8
  Author URI: https://theluckywp.com/
9
  Text Domain: lwptoc
29
  $lwptocAutoloader->addNamespace('luckywp\tableOfContents', __DIR__);
30
 
31
  $config = require(__DIR__ . '/config/plugin.php');
32
+ (new \luckywp\tableOfContents\plugin\Plugin($config))->run('1.2.0', __FILE__, 'lwptoc_');
33
 
34
  require_once __DIR__ . '/functions.php';
plugin/Plugin.php CHANGED
@@ -163,6 +163,8 @@ class Plugin extends BasePlugin
163
  'none' => esc_html__('None', 'lwptoc'),
164
  'left' => esc_html__('Left', 'lwptoc'),
165
  'right' => esc_html__('Right', 'lwptoc'),
 
 
166
  ];
167
  }
168
 
@@ -179,6 +181,17 @@ class Plugin extends BasePlugin
179
  ];
180
  }
181
 
 
 
 
 
 
 
 
 
 
 
 
182
  /**
183
  * @param bool $withCustom
184
  * @return array
163
  'none' => esc_html__('None', 'lwptoc'),
164
  'left' => esc_html__('Left', 'lwptoc'),
165
  'right' => esc_html__('Right', 'lwptoc'),
166
+ 'rightwithoutflow' => esc_html__('Right without flow', 'lwptoc'),
167
+ 'center' => esc_html__('Center', 'lwptoc'),
168
  ];
169
  }
170
 
181
  ];
182
  }
183
 
184
+ /**
185
+ * @return array
186
+ */
187
+ public function getHashFormatsList()
188
+ {
189
+ return [
190
+ 'asheading' => esc_html__('As heading (#Example_Heading_Text)', 'lwptoc'),
191
+ 'counter' => esc_html__('Counter (#lpwtoc1, #lwptoc2, …)', 'lwptoc'),
192
+ ];
193
+ }
194
+
195
  /**
196
  * @param bool $withCustom
197
  * @return array
plugin/Settings.php CHANGED
@@ -272,6 +272,18 @@ class Settings extends \luckywp\tableOfContents\core\wp\Settings
272
  return is_array($postTypes) ? $postTypes : [];
273
  }
274
 
 
 
 
 
 
 
 
 
 
 
 
 
275
  /**
276
  * @return bool
277
  */
272
  return is_array($postTypes) ? $postTypes : [];
273
  }
274
 
275
+ /**
276
+ * @return string
277
+ */
278
+ public function getMiscHashFormat()
279
+ {
280
+ $hashFormat = $this->getValue('misc', 'hashFormat');
281
+ if (!array_key_exists($hashFormat, Core::$plugin->getHashFormatsList())) {
282
+ $hashFormat = 'asheading';
283
+ }
284
+ return $hashFormat;
285
+ }
286
+
287
  /**
288
  * @return bool
289
  */
plugin/Shortcode.php CHANGED
@@ -19,6 +19,11 @@ class Shortcode extends BaseObject
19
  */
20
  protected $idCounter;
21
 
 
 
 
 
 
22
  /**
23
  * @var array
24
  */
@@ -115,6 +120,7 @@ class Shortcode extends BaseObject
115
  {
116
  if ($this->needToc($content)) {
117
  $this->idCounter = 0;
 
118
  $this->headers = [];
119
  $content = preg_replace_callback('#<h([1-6])(.*?)>(.*?)</h\d>#', [$this, 'processHeaders'], $content);
120
  $content = preg_replace_callback('/' . get_shortcode_regex() . '/s', [$this, 'doShortcode'], $content);
@@ -140,8 +146,25 @@ class Shortcode extends BaseObject
140
  */
141
  public function processHeaders($m)
142
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
143
  $header = [
144
- 'id' => 'lwptoc' . ++$this->idCounter,
145
  'index' => (int)$m[1],
146
  'label' => strip_tags($m[3]),
147
  ];
@@ -149,13 +172,32 @@ class Shortcode extends BaseObject
149
 
150
  $content = '';
151
  $htmlOptions = [
152
- 'name' => $header['id'],
153
  ];
154
  $anchor = Html::a($content, null, $htmlOptions);
155
 
156
  return $anchor . $m[0];
157
  }
158
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
159
  /**
160
  * Заменить шорткод на блок с содержанием
161
  * @param array $m
@@ -298,6 +340,9 @@ class Shortcode extends BaseObject
298
  'class' => ['lwptoc'],
299
  'data' => [],
300
  ];
 
 
 
301
 
302
  // Плавная прокрутка
303
  $smoothScroll = $this->assertBool(ArrayHelper::getValue($attrs, 'smoothscroll', Core::$plugin->settings->generalSmoothScroll));
@@ -306,6 +351,10 @@ class Shortcode extends BaseObject
306
  $containerOptions['data']['smooth-scroll-offset'] = (int)ArrayHelper::getValue($attrs, 'smoothscrolloffset', Core::$plugin->settings->generalSmoothScrollOffset);
307
  }
308
 
 
 
 
 
309
  // Ширина
310
  $width = ArrayHelper::getValue($attrs, 'width');
311
  if ($width === null) {
@@ -313,21 +362,24 @@ class Shortcode extends BaseObject
313
  } else {
314
  $width = Settings::sanitizeWidth($width);
315
  }
 
 
 
 
 
 
316
  if ($width != 'full') {
317
  if ($width == 'auto') {
318
  $containerOptions['class'][] = 'lwptoc-autoWidth';
319
  } else {
320
- $containerOptions['style'] = 'width:' . $width;
 
 
 
 
321
  }
322
  }
323
 
324
- // Выравнивание
325
- $float = ArrayHelper::getValue($attrs, 'float', Core::$plugin->settings->appearanceFloat);
326
- $float = strtolower($float);
327
- if (in_array($float, ['left', 'right'])) {
328
- $containerOptions['class'][] = 'lwptoc-' . $float;
329
- }
330
-
331
  // Размер шрифта заголовка
332
  $titleFontSize = ArrayHelper::getValue($attrs, 'titlefontsize');
333
  if ($titleFontSize === null) {
@@ -400,6 +452,7 @@ class Shortcode extends BaseObject
400
  'labelHide' => $labelHide,
401
  'hideItems' => $hideItems,
402
  'containerOptions' => $containerOptions,
 
403
  'headerStyles' => $headerStyles,
404
  'titleStyles' => $titleStyles,
405
  'itemsStyles' => $itemsStyles,
19
  */
20
  protected $idCounter;
21
 
22
+ /**
23
+ * @var array
24
+ */
25
+ protected $ids;
26
+
27
  /**
28
  * @var array
29
  */
120
  {
121
  if ($this->needToc($content)) {
122
  $this->idCounter = 0;
123
+ $this->ids = [];
124
  $this->headers = [];
125
  $content = preg_replace_callback('#<h([1-6])(.*?)>(.*?)</h\d>#', [$this, 'processHeaders'], $content);
126
  $content = preg_replace_callback('/' . get_shortcode_regex() . '/s', [$this, 'doShortcode'], $content);
146
  */
147
  public function processHeaders($m)
148
  {
149
+ switch (Core::$plugin->settings->getMiscHashFormat()) {
150
+ case 'counter':
151
+ $id = 'lwptoc' . ++$this->idCounter;
152
+ break;
153
+
154
+ case 'asheading':
155
+ default:
156
+ $id = $baseId = $this->makeId($m[3]);
157
+ $c = 0;
158
+ while (in_array($id, $this->ids)) {
159
+ $c++;
160
+ $id = $baseId . $c;
161
+ }
162
+ $this->ids[] = $id;
163
+ break;
164
+ }
165
+
166
  $header = [
167
+ 'id' => $id,
168
  'index' => (int)$m[1],
169
  'label' => strip_tags($m[3]),
170
  ];
172
 
173
  $content = '';
174
  $htmlOptions = [
175
+ 'id' => $header['id'],
176
  ];
177
  $anchor = Html::a($content, null, $htmlOptions);
178
 
179
  return $anchor . $m[0];
180
  }
181
 
182
+ /**
183
+ * @param string $label
184
+ * @return string
185
+ */
186
+ protected function makeId($label)
187
+ {
188
+ $id = strip_tags($label);
189
+ $id = html_entity_decode($id, ENT_QUOTES, get_option('blog_charset'));
190
+ if (function_exists('transliterator_transliterate')) {
191
+ $id = transliterator_transliterate('Any-Latin; Latin-ASCII;', $id);
192
+ }
193
+ $id = preg_replace('/[^\d-_A-Za-z ]+/', '', $id);
194
+ $id = preg_replace('/ +/', ' ', $id);
195
+ $id = trim($id);
196
+ $id = str_replace(' ', '_', $id);
197
+ $id = preg_replace('/__+/', '_', $id);
198
+ return $id ? $id : 'lwptoc';
199
+ }
200
+
201
  /**
202
  * Заменить шорткод на блок с содержанием
203
  * @param array $m
340
  'class' => ['lwptoc'],
341
  'data' => [],
342
  ];
343
+ $innerContainerOptions = [
344
+ 'class' => ['lwptoc_i'],
345
+ ];
346
 
347
  // Плавная прокрутка
348
  $smoothScroll = $this->assertBool(ArrayHelper::getValue($attrs, 'smoothscroll', Core::$plugin->settings->generalSmoothScroll));
351
  $containerOptions['data']['smooth-scroll-offset'] = (int)ArrayHelper::getValue($attrs, 'smoothscrolloffset', Core::$plugin->settings->generalSmoothScrollOffset);
352
  }
353
 
354
+ // Выравнивание
355
+ $float = ArrayHelper::getValue($attrs, 'float', Core::$plugin->settings->appearanceFloat);
356
+ $float = strtolower($float);
357
+
358
  // Ширина
359
  $width = ArrayHelper::getValue($attrs, 'width');
360
  if ($width === null) {
362
  } else {
363
  $width = Settings::sanitizeWidth($width);
364
  }
365
+
366
+ // Опции для выравнивания и ширины
367
+ if (in_array($float, ['left', 'right', 'center', 'rightwithoutflow']) &&
368
+ (!in_array($float, ['left', 'right', 'rightwithoutflow']) || $width != 'full')) {
369
+ $containerOptions['class'][] = 'lwptoc-' . $float;
370
+ }
371
  if ($width != 'full') {
372
  if ($width == 'auto') {
373
  $containerOptions['class'][] = 'lwptoc-autoWidth';
374
  } else {
375
+ if (in_array($float, ['left', 'right'])) {
376
+ $containerOptions['style'] = 'width:' . $width;
377
+ } else {
378
+ $innerContainerOptions['style'] = 'width:' . $width;
379
+ }
380
  }
381
  }
382
 
 
 
 
 
 
 
 
383
  // Размер шрифта заголовка
384
  $titleFontSize = ArrayHelper::getValue($attrs, 'titlefontsize');
385
  if ($titleFontSize === null) {
452
  'labelHide' => $labelHide,
453
  'hideItems' => $hideItems,
454
  'containerOptions' => $containerOptions,
455
+ 'innerContainerOptions' => $innerContainerOptions,
456
  'headerStyles' => $headerStyles,
457
  'titleStyles' => $titleStyles,
458
  'itemsStyles' => $itemsStyles,
readme.txt CHANGED
@@ -4,7 +4,7 @@ Donate link: https://theluckywp.com/product/table-of-contents/
4
  Tags: table of contents, toc, navigation, links, heading
5
  Requires at least: 4.7
6
  Tested up to: 5.1.1
7
- Stable tag: 1.1.1
8
  Requires PHP: 5.6.20
9
  License: GPLv2 or later
10
  License URI: https://www.gnu.org/licenses/gpl-2.0.html
@@ -32,6 +32,7 @@ Creates a table of contents for your posts, pages or custom post types. Great cu
32
  * Smooth scroll (optionally).
33
  * Setting offset top for smooth scroll.
34
  * Wrap table of contents with &lt;!--noindex--&gt; tag (optionally).
 
35
  * Available override global settings for a particular post.
36
  * Highly compatible with WordPress themes and plugins.
37
 
@@ -49,6 +50,12 @@ Supported positions:
49
 
50
  You can also select post types to which the table of contents will be automatically added.
51
 
 
 
 
 
 
 
52
  ### Hooks
53
 
54
  #### Filters `lwptoc_before`, `lwptoc_after`
@@ -96,9 +103,13 @@ Example:
96
  ### After activation
97
 
98
  Into classic editor will appear button "Table of Contents" (available on edit post/page screen).
 
99
  Into Gutenberg editor will appear block "Table of Contents" (see "Common Blocks").
 
100
  The menu item "Table of Contents" will appear in the menu "Settings" of the WordPress control panel.
101
 
 
 
102
  == Screenshots ==
103
 
104
  1. Table of Contents
@@ -113,6 +124,12 @@ The menu item "Table of Contents" will appear in the menu "Settings" of the Word
113
 
114
  == Changelog ==
115
 
 
 
 
 
 
 
116
  = 1.1.1 =
117
  * Tag &lt;noindex&gt; replaced to &lt;!--noindex--&gt;.
118
 
4
  Tags: table of contents, toc, navigation, links, heading
5
  Requires at least: 4.7
6
  Tested up to: 5.1.1
7
+ Stable tag: 1.2.0
8
  Requires PHP: 5.6.20
9
  License: GPLv2 or later
10
  License URI: https://www.gnu.org/licenses/gpl-2.0.html
32
  * Smooth scroll (optionally).
33
  * Setting offset top for smooth scroll.
34
  * Wrap table of contents with &lt;!--noindex--&gt; tag (optionally).
35
+ * Pretty hash in URL (like `example.com/faq/#how_do_this`).
36
  * Available override global settings for a particular post.
37
  * Highly compatible with WordPress themes and plugins.
38
 
50
 
51
  You can also select post types to which the table of contents will be automatically added.
52
 
53
+ #### Pretty hash in URL
54
+
55
+ By default, hash generated as heading text (for example, `#How_Do_This`). You can change hash format in global settings, tab "Misc.".
56
+
57
+ For non-English websites it is recommended to enable the `Intl` PHP extension.
58
+
59
  ### Hooks
60
 
61
  #### Filters `lwptoc_before`, `lwptoc_after`
103
  ### After activation
104
 
105
  Into classic editor will appear button "Table of Contents" (available on edit post/page screen).
106
+
107
  Into Gutenberg editor will appear block "Table of Contents" (see "Common Blocks").
108
+
109
  The menu item "Table of Contents" will appear in the menu "Settings" of the WordPress control panel.
110
 
111
+ For non-English websites it is recommended to enable the `Intl` PHP extension.
112
+
113
  == Screenshots ==
114
 
115
  1. Table of Contents
124
 
125
  == Changelog ==
126
 
127
+ = 1.2.0 =
128
+ + Added float options: "Center" and "Right without flow".
129
+ + Added setting "Hash Format".
130
+ * In anchors instead "name" attribute used "id".
131
+ * Minor enhancements in CSS for more compatible with themes.
132
+
133
  = 1.1.1 =
134
  * Tag &lt;noindex&gt; replaced to &lt;!--noindex--&gt;.
135