Skip to content

Commit 480fd0c

Browse files
authored
Merge pull request #34 from KEINOS/feat-21-get-toc-in-array
closes #21
2 parents 2f3e5c5 + ec44a1b commit 480fd0c

File tree

4 files changed

+189
-20
lines changed

4 files changed

+189
-20
lines changed

Extension.php

Lines changed: 70 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,65 @@ public function __construct()
101101
* ========================================================================
102102
*/
103103

104+
/**
105+
* Build hierarchical ToC from a flat toc array.
106+
*
107+
* @param array $flatToc Flat list of toc entries.
108+
* @return array Hierarchical toc as nested array.
109+
*/
110+
protected function buildNestedToc(array $flatToc)
111+
{
112+
$hierarchy = [];
113+
$stack = [];
114+
115+
foreach ($flatToc as $item) {
116+
$level = (int) substr($item['level'], 1); // 'h1' -> 1, etc.
117+
$entry = [
118+
'text' => $item['text'],
119+
'id' => $item['id'],
120+
'level' => $item['level'], // keep the original level as reference
121+
'children' => []
122+
];
123+
124+
// If no parent exists, add as top-level entry
125+
if (empty($stack)) {
126+
$hierarchy[] = $entry;
127+
$stack[] = ['level' => $level, 'ref' => &$hierarchy[count($hierarchy) - 1]];
128+
129+
continue;
130+
}
131+
132+
// If deeper than last, add as child
133+
if ($level > $stack[count($stack) - 1]['level']) {
134+
$parent = &$stack[count($stack) - 1]['ref'];
135+
$parent['children'][] = $entry;
136+
$stack[] = ['level' => $level, 'ref' => &$parent['children'][count($parent['children']) - 1]];
137+
138+
continue;
139+
}
140+
141+
// Pop until we find a shallower level
142+
while (!empty($stack) && $stack[count($stack) - 1]['level'] >= $level) {
143+
array_pop($stack);
144+
}
145+
146+
// If stack empty, add as top-level entry
147+
if (empty($stack)) {
148+
$hierarchy[] = $entry;
149+
$stack[] = ['level' => $level, 'ref' => &$hierarchy[count($hierarchy) - 1]];
150+
151+
continue;
152+
}
153+
154+
// Else, add as sibling child
155+
$parent = &$stack[count($stack) - 1]['ref'];
156+
$parent['children'][] = $entry;
157+
$stack[] = ['level' => $level, 'ref' => &$parent['children'][count($parent['children']) - 1]];
158+
}
159+
160+
return $hierarchy;
161+
}
162+
104163
/**
105164
* Heading process. It retruns the heading block element if the given $Line
106165
* is a heading element.
@@ -206,9 +265,9 @@ public function body($text, $omit_toc_tag = false)
206265
* Returns the parsed ToC.
207266
* If the arg is "string" then it returns the ToC in HTML string.
208267
*
209-
* @param string $type_return Type of the return format. "string" or "json".
268+
* @param string $type_return Type of the return format. "string", "json", "flatarray" and "nestedarray".
210269
*
211-
* @return false|string HTML/JSON string of ToC.
270+
* @return false|string|array HTML/JSON string of ToC.
212271
*/
213272
public function contentsList($type_return = 'string')
214273
{
@@ -226,6 +285,14 @@ public function contentsList($type_return = 'string')
226285
return json_encode($this->contentsListArray);
227286
}
228287

288+
if ('flatarray' === strtolower($type_return)) {
289+
return $this->contentsListArray;
290+
}
291+
292+
if ('nestedarray' === strtolower($type_return)) {
293+
return $this->buildNestedToc($this->contentsListArray);
294+
}
295+
229296
// Log the error and forces to return ToC as "string"
230297
error_log(
231298
'Unknown return type given while parsing ToC.'
@@ -344,7 +411,7 @@ protected function getSalt()
344411
return "$salt";
345412
}
346413

347-
$salt = hash('md5', date('dmYHis', time()));
414+
$salt = hash('md5', time());
348415

349416
return "$salt";
350417
}

examples/get_only_toc/README.md

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,40 @@
11
# Get Only The Table of Contents (ToC) in HTML and JSON
22

3-
Once parsed by `text()` or `body()` method, you can retrieve only the table of contents (ToC) in HTML and JSON using `contentsList()` method.
3+
Once parsed by `text()` or `body()` method, you can retrieve only the table of contents (ToC) in various format using `contentsList()` method.
44

55
This is useful if you want to display the ToC separately or use it in a different context.
66

7-
## Retrieving the ToC in HTML
7+
The method `contentsList()` accepts a parameter that defines the format of the output. The available formats are:
88

9-
```php
10-
// Instanciate the Parsedown with ToC extension
11-
$Parsedown = new ParsedownToc();
9+
- `"string"`: Returns the ToC in HTML format.
10+
- `"json"`: Returns the ToC in JSON format.
11+
- `"flatArray"`: Returns the ToC in one dimensional array format.
12+
- `"nestedArray"`: Returns the ToC in array format with nested structure.
1213

13-
// Parse the Markdown
14-
$html = $Parsedown->text($textMarkdown);
14+
## Retrieving the ToC in HTML
1515

16+
```php
1617
// Get the Table of Contents in HTML
1718
$tocHTML = $Parsedown->contentsList('string');
1819
```
1920

2021
## Retrieving the ToC in JSON
2122

2223
```php
23-
// Instanciate the Parsedown with ToC extension
24-
$Parsedown = new ParsedownToc();
25-
26-
// Parse the Markdown
27-
$html = $Parsedown->text($textMarkdown);
28-
2924
// Get the Table of Contents in JSON
3025
$tocJSON = $Parsedown->contentsList('json');
3126
```
27+
28+
## Retrieving the ToC in Flat Array
29+
30+
```php
31+
// Get the Table of Contents in Flat Array
32+
$tocFlatArray = $Parsedown->contentsList('flatArray');
33+
```
34+
35+
## Retrieving the ToC in Nested Array
36+
37+
```php
38+
// Get the Table of Contents in Nested Array
39+
$tocNestedArray = $Parsedown->contentsList('nestedArray');
40+
```

examples/get_only_toc/expected_out.txt

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,85 @@
1212

1313
* JSON:
1414
[{"text":"Head1","id":"Head1","level":"h1"},{"text":"Head1-1","id":"Head1-1","level":"h2"},{"text":"Head2","id":"Head2","level":"h1"},{"text":"\u898b\u51fa\u30572-1","id":"%E8%A6%8B%E5%87%BA%E3%81%972-1","level":"h2"}]
15+
16+
* Flat array:
17+
Array
18+
(
19+
[0] => Array
20+
(
21+
[text] => Head1
22+
[id] => Head1
23+
[level] => h1
24+
)
25+
26+
[1] => Array
27+
(
28+
[text] => Head1-1
29+
[id] => Head1-1
30+
[level] => h2
31+
)
32+
33+
[2] => Array
34+
(
35+
[text] => Head2
36+
[id] => Head2
37+
[level] => h1
38+
)
39+
40+
[3] => Array
41+
(
42+
[text] => 見出し2-1
43+
[id] => %E8%A6%8B%E5%87%BA%E3%81%972-1
44+
[level] => h2
45+
)
46+
47+
)
48+
49+
* Nested array:
50+
Array
51+
(
52+
[0] => Array
53+
(
54+
[text] => Head1
55+
[id] => Head1
56+
[level] => h1
57+
[children] => Array
58+
(
59+
[0] => Array
60+
(
61+
[text] => Head1-1
62+
[id] => Head1-1
63+
[level] => h2
64+
[children] => Array
65+
(
66+
)
67+
68+
)
69+
70+
)
71+
72+
)
73+
74+
[1] => Array
75+
(
76+
[text] => Head2
77+
[id] => Head2
78+
[level] => h1
79+
[children] => Array
80+
(
81+
[0] => Array
82+
(
83+
[text] => 見出し2-1
84+
[id] => %E8%A6%8B%E5%87%BA%E3%81%972-1
85+
[level] => h2
86+
[children] => Array
87+
(
88+
)
89+
90+
)
91+
92+
)
93+
94+
)
95+
96+
)

examples/get_only_toc/index.php

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,25 @@
2121
// Parse the Markdown
2222
$html = $Parsedown->body($textMarkdown);
2323

24-
// Get the Table of Contents in HTML and JSON format
24+
// Get the Table of Contents in HTML format
2525
$tocHTML = $Parsedown->contentsList('string');
26-
$tocJSON = $Parsedown->contentsList('json');
27-
2826
echo '* HTML:' . PHP_EOL;
2927
echo $tocHTML . PHP_EOL;
30-
3128
echo PHP_EOL;
3229

30+
// Get the Table of Contents in JSON format
31+
$tocJSON = $Parsedown->contentsList('json');
3332
echo '* JSON:' . PHP_EOL;
3433
echo $tocJSON . PHP_EOL;
34+
echo PHP_EOL;
35+
36+
// Get the Table of Contents in flat array format
37+
$flatToC = $Parsedown->contentsList("flatArray");
38+
echo '* Flat array:' . PHP_EOL;
39+
print_r($flatToC);
40+
echo PHP_EOL;
41+
42+
// Get the Table of Contents in nested array format
43+
$nestedToC = $Parsedown->contentsList("nestedArray");
44+
echo '* Nested array:' . PHP_EOL;
45+
print_r($nestedToC);

0 commit comments

Comments
 (0)