-
Notifications
You must be signed in to change notification settings - Fork 1
/
syntax.php
178 lines (155 loc) · 7.61 KB
/
syntax.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
<?php
/**
* DokuWiki Plugin autonumbering (Syntax Component)
*
* @description : This plugin allows the use of multiples counters
* with multiples levels, within the same page.
*
* @syntax (Base) : ~~#~~
* --> Where ~~#~~ will be replaced by a number,
* auto incremented, and saved in a common
* counter.
* @syntax (ID) : ~~#@COUNTERID~~
* --> Where COUNTERID is an alphanumeric
* identificator, including unserscore,
* and starting with a @. This allows
* the use of multiple counters.
* @syntax (forced) : ~~#NUM~~
* --> Where NUM is a positive number that will
* be the begining of the auto incrementation
* from there.
* @syntax (multilevel) : ~~#.#~~
* --> Where .# represent a sublevel and can be
* repeated as much as needed.
*
* @syntax (text) : ~~REPORT.EXAMPLE.#~~
* --> Where only the third level will be an auto
* incremented number. The first level will
* be a repeated text. Here it will be REPORT.
* Samething for the second level with EXAMPLE.
* When using text in a level, it will be
* implicitly used as counter ID if no counter
* ID have been set with @COUNTERID.
*
* @example : ~~Test.#4.#6@CTR_ONE~~
* --> Where the number will have three levels.
* First level will be the text « Test ».
* Second level will be an auto incremented
* number starting at 4. Third level will be
* an auto incremented number starting at 6.
* All this will be save in the counter
* « CTR_ONE ».
*
* @license : GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
*/
// must be run within DokuWiki
if (!defined('DOKU_INC')) die();
if (!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
require_once(DOKU_PLUGIN.'syntax.php');
class syntax_plugin_autonumbering extends DokuWiki_Syntax_Plugin {
var $PLUGIN_PATTERN = "~~[a-zA-Z0-9_\.#@]*#[a-zA-Z0-9_\.#@]*~~";
var $NUMBER_PATTERN = "[0-9]+";
var $COUNTER_ID_PATTERN = "[a-zA-Z0-9_]+";
public function getType() {
return 'substition';
}
public function getPType() {
return 'normal';
}
public function getSort() {
return 45;
}
public function connectTo($mode) {
$this->Lexer->addSpecialPattern($this->PLUGIN_PATTERN, $mode, 'plugin_autonumbering');
}
public function handle($match, $state, $pos, Doku_Handler $handler){
global $COUNTER;
$counterID = '';
$class = 'autonumberingAll autonumbering';
switch ($state) {
case DOKU_LEXER_SPECIAL :
if (preg_match('/~~(.*?)~~/', $match, $matches)) {
$data = $matches[1];
if (!empty($data)) {
// Search for EXPLICIT counter ID
if (preg_match('/@(' . $this->COUNTER_ID_PATTERN . ')/', $data, $matches)) {
$counterID = $matches[1];
// Remove counter ID from $data
$data = str_replace('@' . $counterID, '', $data);
} else { // Search for IMPLICIT counter ID
$alpha = preg_replace('/[^a-zA-Z]/', '', $data);
if (!empty($alpha))
$counterID = $alpha;
}
// Separate levels
$dataTab = explode('.', $data);
// Get levels quantity
$levelsQty = count($dataTab);
$currentLevel = $levelsQty - 1;
// Check if parent level exist
for ($i = 0; $i < $levelsQty; ++$i) {
// Check if level contain text
if (ctype_alpha($dataTab[$i])) {
$COUNTER[$counterID][$i] = $dataTab[$i];
$class .= '_' . $dataTab[$i];
// Search for a forced value
} else if (preg_match('/(' . $this->NUMBER_PATTERN . ')/', $dataTab[$i], $matches))
if ($i == $currentLevel)
$COUNTER[$counterID][$i] = $matches[1]-1;
else
$COUNTER[$counterID][$i] = $matches[1];
// initialize if needed
else if ((!isset($COUNTER[$counterID][$i])) || ($COUNTER[$counterID][$i] == 0))
if ($i == $currentLevel)
$COUNTER[$counterID][$i] = 0;
else
$COUNTER[$counterID][$i] = 1;
}
// Check if child level exist, and initialize
$counter_levelsQty = count($COUNTER[$counterID]);
for ($i = $currentLevel+1; $i < $counter_levelsQty; ++$i)
$COUNTER[$counterID][$i] = 0;
// Increment current level
++$COUNTER[$counterID][$currentLevel];
// Return the number, according the level asked
$number = "<span class=\"$class\">";
$period = '';
for ($i = 0; $i < $levelsQty; ++$i) {
$number .= $period . $COUNTER[$counterID][$i];
if (ctype_alpha($COUNTER[$counterID][$i])) {
if ($period != '.')
$period = ' ';
} else
$period = '.';
}
$number .= '</span>';
return array($number, NULL);
} else {
return array($match, NULL);
}
}
break;
}
return array();
}
public function render($mode, Doku_Renderer $renderer, $data) {
if(($mode == 'xhtml') && (!empty($data))) {
list($number, $null) = $data;
$renderer->doc .= $number;
return true;
}
return false;
}
// To work with the plugin « reproduce », who needs to do
// the numbering prior to reproducing the code.
public function doNumbering($pageContent){
$qtyOccurrences = preg_match_all('/~~(.*?)~~/', $pageContent, $matches);
if ($qtyOccurrences > 0) {
for ($i = 0; $i < $qtyOccurrences; $i++) {
list($number, $null) = $this->handle($matches[0][$i], DOKU_LEXER_SPECIAL, NULL, $handler);
$pageContent = preg_replace('(' . $matches[0][$i] . ')', $number, $pageContent, 1);
}
}
return $pageContent;
}
}