silverstripe-autotoc 

silverstripe-autotoc Commit Details

Date:2017-12-29 00:47:59 (3 years 21 days ago)
Author:Nicola Fontana
Branch:dev, master
Commit:ce1f91c36c41c22623bc92bcbc67808c506a13fd
Parents: b2314120e104a262f7fc2d431ed8d9fb23aae6c1
Message:Major refactoring for SS4

Changes:
Dsrc/AutotocExtension.php (full)
Asrc/Autotoc.php (full)
Asrc/Hacks.php (full)
Atests/AutotocTest.php (full)
Atests/TestObject.php (full)
MCONTRIBUTING.md (1 diff)
MREADME.md (1 diff)
M_config/autotoc.yml (1 diff)
Mdocs/en/format.md (2 diffs)
Mdocs/en/usage.md (4 diffs)
Msrc/Tocifier.php (2 diffs)
Mtests/TocifierTest.php (3 diffs)

File differences

CONTRIBUTING.md
44
55
66
7
8
9
7
8
9
10
can participate by sharing code, ideas, or simply helping others. No
matter what your skill level is, every contribution counts.
The main development happens into the `dev` branch, so pull requests are
expected to be done against `dev`. Anyway the project is so small that
contributions in master will not be surely rejected.
The main developement is done in `dev`: that is merged into `master` when
considered stable enough. When this happens, an appropriate release is tagged.
`dev` and `master` branches are compatibles with SilverStripe 4. For
SilverStripe 3 you should take a look at the `ss3` branch.
README.md
1111
1212
1313
14
15
16
1714
1815
19
20
21
16
2217
2318
2419
2520
2621
2722
28
29
30
31
32
33
23
3424
35
25
26
3627
3728
3829
Installation
------------
If you use [composer](https://getcomposer.org/), you could just run the
following command:
composer require entidi/silverstripe-autotoc
To manually install it you should unpack or copy `silverstripe-autotoc`
into your SilverStripe root directory, rename it to `autotoc` and do a
`?flush`.
Manual installation is probably possible but not really tested.
This module can be used without the CMS.
Testing
-------
Part of this project (the _Tocifier_ class) is intentionally decoupled
from SilverStripe so it can be tested without pulling in all the
framework.
From the module root directory you can trigger the testing by calling
`phpunit` (that must be previously installed on your system):
Basically it boils down to the following commands:
phpunit --bootstrap tests/Bootstrap.php tests/
composer update
vendor/bin/phpunit
Other documentation
-------------------
_config/autotoc.yml
11
22
33
4
5
4
5
66
77
88
99
1010
1111
12
12
---
Name: autotoc
---
eNTiDi\Autotoc\AutotocExtension:
augment_callback: [ eNTiDi\Autotoc\Tocifier, SetId ]
eNTiDi\Autotoc\Autotoc:
augment_callback: eNTiDi\Autotoc\Tocifier::SetId
---
Only:
classexists: SilverStripe\CMS\Controllers\ContentController
---
SilverStripe\CMS\Controllers\ContentController:
extensions:
- eNTiDi\Autotoc\AutotocExtension
- eNTiDi\Autotoc\Autotoc
docs/en/format.md
88
99
1010
11
11
1212
1313
1414
......
1616
1717
1818
19
20
21
19
20
21
2222
2323
2424
<CHILDREN> = ArrayList( <ITEM> )
<ITEM> = ArrayData( $Id, $Title [, $Children <- <CHILDREN> ] )
In a more SilverStripe template way, this can be seen as:
In a more SilverStripe way, this can be seen as:
$Autotoc
$Children[]
$Title
$Children[]
The `Autotoc.ss` and `AutotocItem.ss` show a way to represent the whole
table of content tree in a recursive way. The format used there is
intentionally compatible with the
`Autotoc.ss` and `AutotocItem.ss` show a way to render the whole table of
contents by leveraging mutual recursion between two templates. The format used
there is intentionally compatible with the
[Bootstrap navlist](http://getbootstrap.com/components/#nav) component,
so it can be used and it will be properly handled by the
[Silverstrap](http://dev.entidi.com/p/silverstrap/) theme.
docs/en/usage.md
11
22
33
4
4
55
6
6
77
88
99
10
10
1111
12
13
14
15
16
12
13
14
15
16
17
18
19
20
21
1722
1823
1924
......
2126
2227
2328
29
30
31
2432
25
33
2634
2735
2836
......
3442
3543
3644
45
46
47
3748
3849
3950
......
4354
4455
4556
46
47
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
4877
49
78
79
80
81
Usage
-----
`silverstripe-autotoc` is basically a [SilverStripe 3](http://www.silverstripe.org/)
`silverstripe-autotoc` is basically a [SilverStripe 4](http://www.silverstripe.org/)
module that extends a controller (if the CMS is present the
[ContentController](http://api.silverstripe.org/3.0/class-ContentController.html)
[ContentController](http://api.silverstripe.org/4/SilverStripe/CMS/Controllers/ContentController.html)
will be extended out of the box) to provide:
* the *$Autotoc* tag, containing the table of contents dynamically
created from the content of the current page. The tree is provided as
generated from the content of the current page. The tree is provided as
a mixture of
[ArrayData](http://api.silverstripe.org/3.0/class-ArrayData.html) and
[ArrayList](http://api.silverstripe.org/3.0/class-ArrayList.html),
ready to be consumed by templates.
* the override of the subject field (i.e. *$Content* by default) that
will be augmented to add proper destinations for the links.
[ArrayData](http://api.silverstripe.org/4/SilverStripe/View/ArrayData.html) and
[ArrayList](http://api.silverstripe.org/4/SilverStripe/ORM/ArrayList.html),
ready to be consumed by templates;
* the *$ContentField* tag, containing the HTML content properly augmented with
the destinations of the TOC links;
* the *$OriginalContentField* tag, for accessing the original (non-augmented)
content field;
* an automatic override of the value of the content field (*$Content* by
default): accessing that field will automatically return the augmented HTML.
Use *$OriginalContentField* to access the non-augmented content, if needed.
You will need to modify your templates for embedding the *$Autotoc* tag
(see [AutoTOC format](format.md) for the gory details) or directly
<% include Autotoc %>
Specifying the content field
----------------------------
If you want to tocify a field different from *Content*, set the desired
name in the `content_field` property of a YAML config file, e.g.:
name in the `content_field` property, e.g.:
ContentController:
content_field: 'Content' # Bogus: this is the default
The *$Autotoc* tag will automatically become available in the above
controllers.
Augmenting algorithm
--------------------
By default the HTML is augmented by setting the _id_ attribute directly on the
destination element (see `Tocifier::setId` for the exact implementation). Any
preexisting _id_ will be overwritten.
possible to enable it by changing the augment callback to
`Tocifier::prependAnchor`. Just add the following to your YAML config:
Tocifier:
augment_callback: [ Tocifier, prependAnchor ]
eNTiDi\Autotoc\Autotoc:
augment_callback: eNTiDi\Autotoc\Tocifier::prependAnchor
You can leverage this option to run your own callbacks too, e.g.:
eNTiDi\Autotoc\Autotoc:
augment_callback: 'Page::defaultCallback'
Page:
augment_callback: 'Page::specificCallback'
The callback receives three arguments: the main
[DOMDocument](http://php.net/manual/en/class.domdocument.php) instance, the
[DOMElement](http://php.net/manual/en/class.domelement.php) to augment and a
string with the ID the element must refer to.
Excluding items from the TOC
----------------------------
If for some reasons you **do not** want to include some sections in the TOC,
just specify the `data-hide-from-toc` attribute, e.g.:
You can leverage this option to enable your own callbacks too.
<h2>First section</h2>
<h2>Second section</h2>
<h2 data-hide-from-toc>This section will be skipped</h2>
<h2>Last section</h2>
src/Autotoc.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
<?php
namespace eNTiDi\Autotoc;
use eNTiDi\Autotoc\Hacks;
use SilverStripe\Core\Config\Config;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\ORM\ArrayList;
use SilverStripe\ORM\DataExtension;
use SilverStripe\View\ArrayData;
use SplObjectStorage;
class Autotoc extends DataExtension
{
/**
* @config
* Callable to be used for augmenting a DOMElement: specify as a
* string in the format "class::method". `Tocifier::prependAnchor`
* and `Tocifier::setId` are two valid callbacks.
*/
private static $augment_callback;
protected static $tocifiers;
/**
* Initialize the Autotoc extension.
*
* Creates an internal SplObjectStorage where caching the table of
* contents.
*/
public function __construct()
{
parent::__construct();
if (empty(self::$tocifiers)) {
self::$tocifiers = new SplObjectStorage();
}
}
private static function convertNode($node)
{
$data = new ArrayData([
'Id' => $node['id'],
'Title' => $node['title']
]);
if (isset($node['children'])) {
$data->setField('Children', self::convertChildren($node['children']));
}
return $data;
}
private static function convertChildren($children)
{
$list = new ArrayList();
foreach ($children as $child) {
$list->push(self::convertNode($child));
}
return $list;
}
/**
* Get the field name to be used as content.
* @return string
*/
private function contentField()
{
$field = $this->owner->config()->get('content_field');
return $field ? $field : 'Content';
}
/**
* Provide content_field customization on a class basis.
*
* Override the default setOwner() method so, when valorized, I can
* enhance the (possibly custom) content field with anchors. I did
* not find a better way to override a field other than directly
* substituting it with setField().
*
* @param Object $owner
*/
public function setOwner($owner)
{
parent::setOwner($owner);
if ($owner) {
Hacks::addCallbackMethodToInstance(
$owner,
'getContent',
function () use ($owner) {
return $owner->getContentField();
}
);
}
}
/**
* Return the internal Tocifier instance bound to $owner.
*
* If not present, try to create and execute a new one. On failure
* (e.g. because of malformed content) no further attempts will be
* made.
*
* @param DataObject $owner
* @return Tocifier|false|null
*/
private static function getTocifier($owner)
{
if (!$owner) {
$tocifier = null;
} elseif (isset(self::$tocifiers[$owner])) {
$tocifier = self::$tocifiers[$owner];
} else {
$tocifier = Injector::inst()->create(
'eNTiDi\Autotoc\Tocifier',
$owner->getOriginalContentField()
);
$callback = $owner->config()->get('augment_callback');
if (empty($callback)) {
$callback = Config::inst()->get(self::class, 'augment_callback');
}
$tocifier->setAugmentCallback(explode('::', $callback));
if (! $tocifier->process()) {
$tocifier = false;
}
self::$tocifiers[$owner] = $tocifier;
}
return $tocifier;
}
/**
* Clear the internal Autotoc cache.
*
* The TOC is usually cached the first time you call (directly or
* indirectly) getAutotoc() or getContentField(). This method allows
* to clear the internal cache to force a recomputation.
*/
public function clearAutotoc()
{
unset(self::$tocifiers[$this->owner]);
}
/**
* Get the automatically generated table of contents.
* @return ArrayData|null
*/
public function getAutotoc()
{
$tocifier = self::getTocifier($this->owner);
if (! $tocifier) {
return null;
}
$toc = $tocifier->getTOC();
if (empty($toc)) {
return null;
}
return new ArrayData([
'Children' => self::convertChildren($toc)
]);
}
/**
* Get the non-augmented content field.
* @return string
*/
public function getOriginalContentField()
{
$model = $this->owner->getCustomisedObj();
if (! $model) {
$model = $this->owner->data();
}
if (! $model) {
return null;
}
$field = $this->contentField();
if (! $model->hasField($field)) {
return null;
}
return $model->getField($field);
return $model->obj($field)->forTemplate();
}
/**
* Get the augmented content field.
* @return string
*/
public function getContentField()
{
$tocifier = self::getTocifier($this->owner);
if (!$tocifier) {
return $this->getOriginalContentField();
}
return $tocifier->getHTML();
}
/**
* I don't remember what the hell is this...
* @return string
*/
public function getBodyAutotoc()
{
return ' data-spy="scroll" data-target=".toc"';
}
}
src/AutotocExtension.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
<?php
namespace eNTiDi\Autotoc;
use SilverStripe\Core\Config\Config;
use SilverStripe\Core\Extension;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\ORM\ArrayList;
use SilverStripe\View\ArrayData;
class AutotocExtension extends Extension
{
/**
* @config
* Callable to be used for augmenting a DOMElement.
* Look at Tocifier::prependAnchor and Tocifier::setId as
* implementation samples.
*/
private static $augment_callback;
private $tocifier;
private static function convertNode($node)
{
$data = new ArrayData([
'Id' => $node['id'],
'Title' => $node['title']
]);
if (isset($node['children'])) {
$data->setField('Children', self::convertChildren($node['children']));
}
return $data;
}
private static function convertChildren($children)
{
$list = new ArrayList();
foreach ($children as $child) {
$list->push(self::convertNode($child));
}
return $list;
}
/**
* Get the field name to be used as content.
* @return string
*/
private function contentField()
{
$field = $this->owner->config()->get('content_field');
return $field ? $field : 'Content';
}
/**
* Provide content_field customization on a class basis.
*
* Override the default setOwner() method so, when valorized, I can
* enhance the (possibly custom) content field with anchors. I did
* not find a better way to override a field other than directly
* substituting it with setField().
*
* @param Object $owner The owner instance
* @param string|null $base_class The name of the base class this
* extension is applied to
*/
public function setOwner($owner, $base_class = null)
{
parent::setOwner($owner, $base_class);
if ($owner) {
$tocifier = $this->getTocifier();
$content = $tocifier ? $tocifier->getHtml() : $this->getHtml();
$owner->setField($this->contentField(), $content);
}
}
/**
* @return string
*/
private function getHtml()
{
$c = $this->owner;
$model = $c->customisedObject ? $c->customisedObject : $c->data();
if (! $model) {
return null;
}
$field = $this->contentField();
if (! $model->hasField($field)) {
return null;
}
return $model->obj($field)->forTemplate();
}
/**
* Return the internal Tocifier instance bound to this Autotoc.
*
* If not preset, try to create and execute a new one. On failure
* (e.g. because of malformed content) no further attempts will be
* made.
*
* @return Tocifier|false
*/
private function getTocifier()
{
if (is_null($this->tocifier)) {
$tocifier = Injector::inst()->create(
'eNTiDi\Autotoc\Tocifier',
$this->getHtml()
);
// TODO: not sure this is the best approach... maybe I
// should look to $this->owner->dataRecord before
$config = Config::inst()->get(__CLASS__, 'augment_callback');
// Take only the first two, because SilverStripe merges
// arrays with the same key instead of overwriting them
$tocifier->setAugmentCallback(array_slice($config, 0, 2));
$this->tocifier = $tocifier->process() ? $tocifier : false;
}
return $this->tocifier;
}
public function getAutotoc()
{
$tocifier = $this->getTocifier();
if (! $tocifier) {
return null;
}
$toc = $tocifier->getTOC();
if (empty($toc)) {
return '';
}
return new ArrayData([
'Children' => self::convertChildren($toc)
]);
}
/**
* @return string
*/
public function getBodyAutotoc()
{
return ' data-spy="scroll" data-target=".toc"';
}
}
src/Hacks.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<?php
namespace eNTiDi\Autotoc;
use SilverStripe\View\ViewableData;
class Hacks extends ViewableData
{
/**
* Add a new wrapper method.
*
* Similar to addWrapperMethod() but made public and working on
* custom instances to allow to inject custom wrappers.
*
* @param string $instance
* @param string $method
* @param string $wrap
*/
public static function addWrapperMethodToInstance($instance, $method, $wrap)
{
// hasMethod() trigger the population of $extra_methods
$instance->hasMethod('UnexistentMethod');
self::$extra_methods[get_class($instance)][strtolower($method)] = [
'wrap' => $wrap,
'method' => $method,
];
}
public static function addCallbackMethodToInstance($instance, $method, $callback)
{
// hasMethod() trigger the population of $extra_methods
$instance->hasMethod('UnexistentMethod');
self::$extra_methods[get_class($instance)][strtolower($method)] = [
'callback' => $callback,
];
}
}
src/Tocifier.php
126126
127127
128128
129
129
130130
131131
132132
......
165165
166166
167167
168
169
168
170169
171170
172171
}
$body = $doc->getElementsByTagName('body')->item(0);
$this->html = str_replace(array("<body>\n", '</body>'), '', $doc->saveHTML($body));
$this->html = str_replace(array("<body>\n", '<body>', '</body>'), '', $doc->saveHTML($body));
}
/**
public function __construct($html)
{
$this->raw_html = $html;
// Default augmenting method (kept for backward compatibility)
$this->setAugmentCallback(array(__CLASS__, 'prependAnchor'));
$this->setAugmentCallback(array(static::class, 'setId'));
}
/**
tests/AutotocTest.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
<?php
namespace eNTiDi\Autotoc\Tests;
use eNTiDi\Autotoc\Autotoc;
use eNTiDi\Autotoc\Tests\TestObject;
use SilverStripe\Core\Config\Config;
use SilverStripe\Dev\SapphireTest;
use SilverStripe\View\ArrayData;
class AutotocTest extends SapphireTest
{
public function setUp()
{
parent::setUp();
// Enable the Autotoc extension on TestObject
TestObject::add_extension('eNTiDi\Autotoc\Autotoc');
}
private function emptyTestObject()
{
$obj = new TestObject;
$obj->Content = '';
$obj->Test2 = '';
return $obj;
}
private function populatedTestObject()
{
$obj = new TestObject;
$obj->Content = file_get_contents(__DIR__ . '/test1');
$obj->Test2 = file_get_contents(__DIR__ . '/test2');
return $obj;
}
public function testBodyAutotoc()
{
$obj = new TestObject;
$this->assertEquals(' data-spy="scroll" data-target=".toc"', $obj->getBodyAutotoc());
}
public function testContentField()
{
$obj = new TestObject;
$obj->Content = '<p>Content</p>';
$obj->Test2 = '<p>Test2</p>';
// Check the default content field is Content
$this->assertEquals('<p>Content</p>', $obj->OriginalContentField);
// Try to change the content field
$obj->config()->update('content_field', 'Test2');
$this->assertEquals('<p>Test2</p>', $obj->OriginalContentField);
// Change it again
$obj->config()->update('content_field', 'Unexistent');
$this->assertEquals('', $obj->OriginalContentField);
// Restore original value
$obj->config()->update('content_field', 'Content');
}
public function testGetAutotoc()
{
$obj = new TestObject;
$toc = $obj->getAutotoc();
$this->assertNull($toc);
$obj->Content = file_get_contents(__DIR__ . '/test1');
$obj->Test2 = file_get_contents(__DIR__ . '/test2');
// Old TOC should still be cached
$toc = $obj->getAutotoc();
$this->assertNull($toc);
$obj->clearAutotoc();
$toc = $obj->getAutotoc();
$this->assertTrue($toc instanceof ArrayData);
$this->assertEquals(5, $toc->Children->count());
$this->assertStringEqualsFile(__DIR__ . '/test1', $obj->OriginalContentField);
$this->assertStringEqualsFile(__DIR__ . '/html2', $obj->ContentField);
$this->assertStringEqualsFile(__DIR__ . '/html2', $obj->Content);
// Change the content field
$obj->config()->update('content_field', 'Test2');
$obj->clearAutotoc();
$toc = $obj->getAutotoc();
$this->assertNull($toc);
$this->assertStringEqualsFile(__DIR__ . '/test2', $obj->OriginalContentField);
$this->assertStringEqualsFile(__DIR__ . '/test2', $obj->ContentField);
}
public function testAugmentCallback()
{
$obj = new TestObject;
$obj->Content = file_get_contents(__DIR__ . '/test1');
$obj->Test2 = file_get_contents(__DIR__ . '/test2');
// Change the augmenter at class level
Config::inst()->update(
get_class($obj),
'augment_callback',
'eNTiDi\Autotoc\Tocifier::prependAnchor'
);
$obj->clearAutotoc();
$toc = $obj->getAutotoc();
$this->assertEquals(5, $toc->Children->count());
$this->assertStringEqualsFile(__DIR__ . '/html1', $obj->Content);
// Change the augmenter at install level: should have higher
// precedence
$obj->config()->update(
'augment_callback',
'eNTiDi\Autotoc\Tocifier::setId'
);
$obj->clearAutotoc();
$toc = $obj->getAutotoc();
$this->assertEquals(5, $toc->Children->count());
$this->assertStringEqualsFile(__DIR__ . '/html2', $obj->Content);
}
}
tests/TestObject.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
namespace eNTiDi\Autotoc\Tests;
use SilverStripe\ORM\DataObject;
use SilverStripe\Dev\TestOnly;
class TestObject extends DataObject implements TestOnly
{
private static $db = [
'Content' => 'HTMLText',
'Test2' => 'HTMLText',
];
}
tests/TocifierTest.php
2828
2929
3030
31
32
31
3332
34
33
34
3535
3636
3737
3838
3939
4040
41
42
41
42
43
4344
4445
4546
......
4748
4849
4950
50
51
5152
5253
5354
......
6061
6162
6263
63
64
6465
6566
6667
public function testPrependAnchor()
{
$tocifier = new Tocifier(file_get_contents(__DIR__ . '/test1'));
$this->assertEquals($tocifier->getHtml(), '');
$this->assertTrue($tocifier->process());
$this->assertEquals('', $tocifier->getHtml());
// The default augmenting method should already be prependAnchor
$tocifier->setAugmentCallback(array('\eNTiDi\Autotoc\Tocifier', 'prependAnchor'));
$this->assertTrue($tocifier->process());
$this->assertStringEqualsFile(__DIR__ . '/html1', $tocifier->getHtml());
}
public function testSetId()
{
$tocifier = new Tocifier(file_get_contents(__DIR__ . '/test1'));
$tocifier->setAugmentCallback(array('\eNTiDi\Autotoc\Tocifier', 'setId'));
$this->assertEquals($tocifier->getHtml(), '');
$this->assertEquals('', $tocifier->getHtml());
// The default augmenting method should already be setId
$this->assertTrue($tocifier->process());
$this->assertStringEqualsFile(__DIR__ . '/html2', $tocifier->getHtml());
}
public function testTOC()
{
$tocifier = new Tocifier(file_get_contents(__DIR__ . '/test1'));
$this->assertEquals($tocifier->getTOC(), array());
$this->assertEquals(array(), $tocifier->getTOC());
$this->assertTrue($tocifier->process());
$this->assertNotNull($tocifier->getTOC());
public function testDataHideFromTOC()
{
$tocifier = new Tocifier(file_get_contents(__DIR__ . '/test2'));
$this->assertEquals($tocifier->getHtml(), '');
$this->assertEquals('', $tocifier->getHtml());
$this->assertTrue($tocifier->process());
// Check the augmented HTML is equal to the original one

Archive Download the corresponding diff file