|
@@ -1,686 +0,0 @@
|
1
|
|
-<?php
|
2
|
|
-
|
3
|
|
-#
|
4
|
|
-#
|
5
|
|
-# Parsedown Extra
|
6
|
|
-# https://github.com/erusev/parsedown-extra
|
7
|
|
-#
|
8
|
|
-# (c) Emanuil Rusev
|
9
|
|
-# http://erusev.com
|
10
|
|
-#
|
11
|
|
-# For the full license information, view the LICENSE file that was distributed
|
12
|
|
-# with this source code.
|
13
|
|
-#
|
14
|
|
-#
|
15
|
|
-
|
16
|
|
-class ParsedownExtra extends Parsedown
|
17
|
|
-{
|
18
|
|
- # ~
|
19
|
|
-
|
20
|
|
- const version = '0.8.0';
|
21
|
|
-
|
22
|
|
- # ~
|
23
|
|
-
|
24
|
|
- function __construct()
|
25
|
|
- {
|
26
|
|
- if (version_compare(parent::version, '1.7.1') < 0)
|
27
|
|
- {
|
28
|
|
- throw new Exception('ParsedownExtra requires a later version of Parsedown');
|
29
|
|
- }
|
30
|
|
-
|
31
|
|
- $this->BlockTypes[':'] []= 'DefinitionList';
|
32
|
|
- $this->BlockTypes['*'] []= 'Abbreviation';
|
33
|
|
-
|
34
|
|
- # identify footnote definitions before reference definitions
|
35
|
|
- array_unshift($this->BlockTypes['['], 'Footnote');
|
36
|
|
-
|
37
|
|
- # identify footnote markers before before links
|
38
|
|
- array_unshift($this->InlineTypes['['], 'FootnoteMarker');
|
39
|
|
- }
|
40
|
|
-
|
41
|
|
- #
|
42
|
|
- # ~
|
43
|
|
-
|
44
|
|
- function text($text)
|
45
|
|
- {
|
46
|
|
- $Elements = $this->textElements($text);
|
47
|
|
-
|
48
|
|
- # convert to markup
|
49
|
|
- $markup = $this->elements($Elements);
|
50
|
|
-
|
51
|
|
- # trim line breaks
|
52
|
|
- $markup = trim($markup, "\n");
|
53
|
|
-
|
54
|
|
- # merge consecutive dl elements
|
55
|
|
-
|
56
|
|
- $markup = preg_replace('/<\/dl>\s+<dl>\s+/', '', $markup);
|
57
|
|
-
|
58
|
|
- # add footnotes
|
59
|
|
-
|
60
|
|
- if (isset($this->DefinitionData['Footnote']))
|
61
|
|
- {
|
62
|
|
- $Element = $this->buildFootnoteElement();
|
63
|
|
-
|
64
|
|
- $markup .= "\n" . $this->element($Element);
|
65
|
|
- }
|
66
|
|
-
|
67
|
|
- return $markup;
|
68
|
|
- }
|
69
|
|
-
|
70
|
|
- #
|
71
|
|
- # Blocks
|
72
|
|
- #
|
73
|
|
-
|
74
|
|
- #
|
75
|
|
- # Abbreviation
|
76
|
|
-
|
77
|
|
- protected function blockAbbreviation($Line)
|
78
|
|
- {
|
79
|
|
- if (preg_match('/^\*\[(.+?)\]:[ ]*(.+?)[ ]*$/', $Line['text'], $matches))
|
80
|
|
- {
|
81
|
|
- $this->DefinitionData['Abbreviation'][$matches[1]] = $matches[2];
|
82
|
|
-
|
83
|
|
- $Block = array(
|
84
|
|
- 'hidden' => true,
|
85
|
|
- );
|
86
|
|
-
|
87
|
|
- return $Block;
|
88
|
|
- }
|
89
|
|
- }
|
90
|
|
-
|
91
|
|
- #
|
92
|
|
- # Footnote
|
93
|
|
-
|
94
|
|
- protected function blockFootnote($Line)
|
95
|
|
- {
|
96
|
|
- if (preg_match('/^\[\^(.+?)\]:[ ]?(.*)$/', $Line['text'], $matches))
|
97
|
|
- {
|
98
|
|
- $Block = array(
|
99
|
|
- 'label' => $matches[1],
|
100
|
|
- 'text' => $matches[2],
|
101
|
|
- 'hidden' => true,
|
102
|
|
- );
|
103
|
|
-
|
104
|
|
- return $Block;
|
105
|
|
- }
|
106
|
|
- }
|
107
|
|
-
|
108
|
|
- protected function blockFootnoteContinue($Line, $Block)
|
109
|
|
- {
|
110
|
|
- if ($Line['text'][0] === '[' and preg_match('/^\[\^(.+?)\]:/', $Line['text']))
|
111
|
|
- {
|
112
|
|
- return;
|
113
|
|
- }
|
114
|
|
-
|
115
|
|
- if (isset($Block['interrupted']))
|
116
|
|
- {
|
117
|
|
- if ($Line['indent'] >= 4)
|
118
|
|
- {
|
119
|
|
- $Block['text'] .= "\n\n" . $Line['text'];
|
120
|
|
-
|
121
|
|
- return $Block;
|
122
|
|
- }
|
123
|
|
- }
|
124
|
|
- else
|
125
|
|
- {
|
126
|
|
- $Block['text'] .= "\n" . $Line['text'];
|
127
|
|
-
|
128
|
|
- return $Block;
|
129
|
|
- }
|
130
|
|
- }
|
131
|
|
-
|
132
|
|
- protected function blockFootnoteComplete($Block)
|
133
|
|
- {
|
134
|
|
- $this->DefinitionData['Footnote'][$Block['label']] = array(
|
135
|
|
- 'text' => $Block['text'],
|
136
|
|
- 'count' => null,
|
137
|
|
- 'number' => null,
|
138
|
|
- );
|
139
|
|
-
|
140
|
|
- return $Block;
|
141
|
|
- }
|
142
|
|
-
|
143
|
|
- #
|
144
|
|
- # Definition List
|
145
|
|
-
|
146
|
|
- protected function blockDefinitionList($Line, $Block)
|
147
|
|
- {
|
148
|
|
- if ( ! isset($Block) or $Block['type'] !== 'Paragraph')
|
149
|
|
- {
|
150
|
|
- return;
|
151
|
|
- }
|
152
|
|
-
|
153
|
|
- $Element = array(
|
154
|
|
- 'name' => 'dl',
|
155
|
|
- 'elements' => array(),
|
156
|
|
- );
|
157
|
|
-
|
158
|
|
- $terms = explode("\n", $Block['element']['handler']['argument']);
|
159
|
|
-
|
160
|
|
- foreach ($terms as $term)
|
161
|
|
- {
|
162
|
|
- $Element['elements'] []= array(
|
163
|
|
- 'name' => 'dt',
|
164
|
|
- 'handler' => array(
|
165
|
|
- 'function' => 'lineElements',
|
166
|
|
- 'argument' => $term,
|
167
|
|
- 'destination' => 'elements'
|
168
|
|
- ),
|
169
|
|
- );
|
170
|
|
- }
|
171
|
|
-
|
172
|
|
- $Block['element'] = $Element;
|
173
|
|
-
|
174
|
|
- $Block = $this->addDdElement($Line, $Block);
|
175
|
|
-
|
176
|
|
- return $Block;
|
177
|
|
- }
|
178
|
|
-
|
179
|
|
- protected function blockDefinitionListContinue($Line, array $Block)
|
180
|
|
- {
|
181
|
|
- if ($Line['text'][0] === ':')
|
182
|
|
- {
|
183
|
|
- $Block = $this->addDdElement($Line, $Block);
|
184
|
|
-
|
185
|
|
- return $Block;
|
186
|
|
- }
|
187
|
|
- else
|
188
|
|
- {
|
189
|
|
- if (isset($Block['interrupted']) and $Line['indent'] === 0)
|
190
|
|
- {
|
191
|
|
- return;
|
192
|
|
- }
|
193
|
|
-
|
194
|
|
- if (isset($Block['interrupted']))
|
195
|
|
- {
|
196
|
|
- $Block['dd']['handler']['function'] = 'textElements';
|
197
|
|
- $Block['dd']['handler']['argument'] .= "\n\n";
|
198
|
|
-
|
199
|
|
- $Block['dd']['handler']['destination'] = 'elements';
|
200
|
|
-
|
201
|
|
- unset($Block['interrupted']);
|
202
|
|
- }
|
203
|
|
-
|
204
|
|
- $text = substr($Line['body'], min($Line['indent'], 4));
|
205
|
|
-
|
206
|
|
- $Block['dd']['handler']['argument'] .= "\n" . $text;
|
207
|
|
-
|
208
|
|
- return $Block;
|
209
|
|
- }
|
210
|
|
- }
|
211
|
|
-
|
212
|
|
- #
|
213
|
|
- # Header
|
214
|
|
-
|
215
|
|
- protected function blockHeader($Line)
|
216
|
|
- {
|
217
|
|
- $Block = parent::blockHeader($Line);
|
218
|
|
-
|
219
|
|
- if ($Block !== null && preg_match('/[ #]*{('.$this->regexAttribute.'+)}[ ]*$/', $Block['element']['handler']['argument'], $matches, PREG_OFFSET_CAPTURE))
|
220
|
|
- {
|
221
|
|
- $attributeString = $matches[1][0];
|
222
|
|
-
|
223
|
|
- $Block['element']['attributes'] = $this->parseAttributeData($attributeString);
|
224
|
|
-
|
225
|
|
- $Block['element']['handler']['argument'] = substr($Block['element']['handler']['argument'], 0, $matches[0][1]);
|
226
|
|
- }
|
227
|
|
-
|
228
|
|
- return $Block;
|
229
|
|
- }
|
230
|
|
-
|
231
|
|
- #
|
232
|
|
- # Markup
|
233
|
|
-
|
234
|
|
- protected function blockMarkup($Line)
|
235
|
|
- {
|
236
|
|
- if ($this->markupEscaped or $this->safeMode)
|
237
|
|
- {
|
238
|
|
- return;
|
239
|
|
- }
|
240
|
|
-
|
241
|
|
- if (preg_match('/^<(\w[\w-]*)(?:[ ]*'.$this->regexHtmlAttribute.')*[ ]*(\/)?>/', $Line['text'], $matches))
|
242
|
|
- {
|
243
|
|
- $element = strtolower($matches[1]);
|
244
|
|
-
|
245
|
|
- if (in_array($element, $this->textLevelElements))
|
246
|
|
- {
|
247
|
|
- return;
|
248
|
|
- }
|
249
|
|
-
|
250
|
|
- $Block = array(
|
251
|
|
- 'name' => $matches[1],
|
252
|
|
- 'depth' => 0,
|
253
|
|
- 'element' => array(
|
254
|
|
- 'rawHtml' => $Line['text'],
|
255
|
|
- 'autobreak' => true,
|
256
|
|
- ),
|
257
|
|
- );
|
258
|
|
-
|
259
|
|
- $length = strlen($matches[0]);
|
260
|
|
- $remainder = substr($Line['text'], $length);
|
261
|
|
-
|
262
|
|
- if (trim($remainder) === '')
|
263
|
|
- {
|
264
|
|
- if (isset($matches[2]) or in_array($matches[1], $this->voidElements))
|
265
|
|
- {
|
266
|
|
- $Block['closed'] = true;
|
267
|
|
- $Block['void'] = true;
|
268
|
|
- }
|
269
|
|
- }
|
270
|
|
- else
|
271
|
|
- {
|
272
|
|
- if (isset($matches[2]) or in_array($matches[1], $this->voidElements))
|
273
|
|
- {
|
274
|
|
- return;
|
275
|
|
- }
|
276
|
|
- if (preg_match('/<\/'.$matches[1].'>[ ]*$/i', $remainder))
|
277
|
|
- {
|
278
|
|
- $Block['closed'] = true;
|
279
|
|
- }
|
280
|
|
- }
|
281
|
|
-
|
282
|
|
- return $Block;
|
283
|
|
- }
|
284
|
|
- }
|
285
|
|
-
|
286
|
|
- protected function blockMarkupContinue($Line, array $Block)
|
287
|
|
- {
|
288
|
|
- if (isset($Block['closed']))
|
289
|
|
- {
|
290
|
|
- return;
|
291
|
|
- }
|
292
|
|
-
|
293
|
|
- if (preg_match('/^<'.$Block['name'].'(?:[ ]*'.$this->regexHtmlAttribute.')*[ ]*>/i', $Line['text'])) # open
|
294
|
|
- {
|
295
|
|
- $Block['depth'] ++;
|
296
|
|
- }
|
297
|
|
-
|
298
|
|
- if (preg_match('/(.*?)<\/'.$Block['name'].'>[ ]*$/i', $Line['text'], $matches)) # close
|
299
|
|
- {
|
300
|
|
- if ($Block['depth'] > 0)
|
301
|
|
- {
|
302
|
|
- $Block['depth'] --;
|
303
|
|
- }
|
304
|
|
- else
|
305
|
|
- {
|
306
|
|
- $Block['closed'] = true;
|
307
|
|
- }
|
308
|
|
- }
|
309
|
|
-
|
310
|
|
- if (isset($Block['interrupted']))
|
311
|
|
- {
|
312
|
|
- $Block['element']['rawHtml'] .= "\n";
|
313
|
|
- unset($Block['interrupted']);
|
314
|
|
- }
|
315
|
|
-
|
316
|
|
- $Block['element']['rawHtml'] .= "\n".$Line['body'];
|
317
|
|
-
|
318
|
|
- return $Block;
|
319
|
|
- }
|
320
|
|
-
|
321
|
|
- protected function blockMarkupComplete($Block)
|
322
|
|
- {
|
323
|
|
- if ( ! isset($Block['void']))
|
324
|
|
- {
|
325
|
|
- $Block['element']['rawHtml'] = $this->processTag($Block['element']['rawHtml']);
|
326
|
|
- }
|
327
|
|
-
|
328
|
|
- return $Block;
|
329
|
|
- }
|
330
|
|
-
|
331
|
|
- #
|
332
|
|
- # Setext
|
333
|
|
-
|
334
|
|
- protected function blockSetextHeader($Line, array $Block = null)
|
335
|
|
- {
|
336
|
|
- $Block = parent::blockSetextHeader($Line, $Block);
|
337
|
|
-
|
338
|
|
- if ($Block !== null && preg_match('/[ ]*{('.$this->regexAttribute.'+)}[ ]*$/', $Block['element']['handler']['argument'], $matches, PREG_OFFSET_CAPTURE))
|
339
|
|
- {
|
340
|
|
- $attributeString = $matches[1][0];
|
341
|
|
-
|
342
|
|
- $Block['element']['attributes'] = $this->parseAttributeData($attributeString);
|
343
|
|
-
|
344
|
|
- $Block['element']['handler']['argument'] = substr($Block['element']['handler']['argument'], 0, $matches[0][1]);
|
345
|
|
- }
|
346
|
|
-
|
347
|
|
- return $Block;
|
348
|
|
- }
|
349
|
|
-
|
350
|
|
- #
|
351
|
|
- # Inline Elements
|
352
|
|
- #
|
353
|
|
-
|
354
|
|
- #
|
355
|
|
- # Footnote Marker
|
356
|
|
-
|
357
|
|
- protected function inlineFootnoteMarker($Excerpt)
|
358
|
|
- {
|
359
|
|
- if (preg_match('/^\[\^(.+?)\]/', $Excerpt['text'], $matches))
|
360
|
|
- {
|
361
|
|
- $name = $matches[1];
|
362
|
|
-
|
363
|
|
- if ( ! isset($this->DefinitionData['Footnote'][$name]))
|
364
|
|
- {
|
365
|
|
- return;
|
366
|
|
- }
|
367
|
|
-
|
368
|
|
- $this->DefinitionData['Footnote'][$name]['count'] ++;
|
369
|
|
-
|
370
|
|
- if ( ! isset($this->DefinitionData['Footnote'][$name]['number']))
|
371
|
|
- {
|
372
|
|
- $this->DefinitionData['Footnote'][$name]['number'] = ++ $this->footnoteCount; # » &
|
373
|
|
- }
|
374
|
|
-
|
375
|
|
- $Element = array(
|
376
|
|
- 'name' => 'sup',
|
377
|
|
- 'attributes' => array('id' => 'fnref'.$this->DefinitionData['Footnote'][$name]['count'].':'.$name),
|
378
|
|
- 'element' => array(
|
379
|
|
- 'name' => 'a',
|
380
|
|
- 'attributes' => array('href' => '#fn:'.$name, 'class' => 'footnote-ref'),
|
381
|
|
- 'text' => $this->DefinitionData['Footnote'][$name]['number'],
|
382
|
|
- ),
|
383
|
|
- );
|
384
|
|
-
|
385
|
|
- return array(
|
386
|
|
- 'extent' => strlen($matches[0]),
|
387
|
|
- 'element' => $Element,
|
388
|
|
- );
|
389
|
|
- }
|
390
|
|
- }
|
391
|
|
-
|
392
|
|
- private $footnoteCount = 0;
|
393
|
|
-
|
394
|
|
- #
|
395
|
|
- # Link
|
396
|
|
-
|
397
|
|
- protected function inlineLink($Excerpt)
|
398
|
|
- {
|
399
|
|
- $Link = parent::inlineLink($Excerpt);
|
400
|
|
-
|
401
|
|
- $remainder = $Link !== null ? substr($Excerpt['text'], $Link['extent']) : '';
|
402
|
|
-
|
403
|
|
- if (preg_match('/^[ ]*{('.$this->regexAttribute.'+)}/', $remainder, $matches))
|
404
|
|
- {
|
405
|
|
- $Link['element']['attributes'] += $this->parseAttributeData($matches[1]);
|
406
|
|
-
|
407
|
|
- $Link['extent'] += strlen($matches[0]);
|
408
|
|
- }
|
409
|
|
-
|
410
|
|
- return $Link;
|
411
|
|
- }
|
412
|
|
-
|
413
|
|
- #
|
414
|
|
- # ~
|
415
|
|
- #
|
416
|
|
-
|
417
|
|
- private $currentAbreviation;
|
418
|
|
- private $currentMeaning;
|
419
|
|
-
|
420
|
|
- protected function insertAbreviation(array $Element)
|
421
|
|
- {
|
422
|
|
- if (isset($Element['text']))
|
423
|
|
- {
|
424
|
|
- $Element['elements'] = self::pregReplaceElements(
|
425
|
|
- '/\b'.preg_quote($this->currentAbreviation, '/').'\b/',
|
426
|
|
- array(
|
427
|
|
- array(
|
428
|
|
- 'name' => 'abbr',
|
429
|
|
- 'attributes' => array(
|
430
|
|
- 'title' => $this->currentMeaning,
|
431
|
|
- ),
|
432
|
|
- 'text' => $this->currentAbreviation,
|
433
|
|
- )
|
434
|
|
- ),
|
435
|
|
- $Element['text']
|
436
|
|
- );
|
437
|
|
-
|
438
|
|
- unset($Element['text']);
|
439
|
|
- }
|
440
|
|
-
|
441
|
|
- return $Element;
|
442
|
|
- }
|
443
|
|
-
|
444
|
|
- protected function inlineText($text)
|
445
|
|
- {
|
446
|
|
- $Inline = parent::inlineText($text);
|
447
|
|
-
|
448
|
|
- if (isset($this->DefinitionData['Abbreviation']))
|
449
|
|
- {
|
450
|
|
- foreach ($this->DefinitionData['Abbreviation'] as $abbreviation => $meaning)
|
451
|
|
- {
|
452
|
|
- $this->currentAbreviation = $abbreviation;
|
453
|
|
- $this->currentMeaning = $meaning;
|
454
|
|
-
|
455
|
|
- $Inline['element'] = $this->elementApplyRecursiveDepthFirst(
|
456
|
|
- array($this, 'insertAbreviation'),
|
457
|
|
- $Inline['element']
|
458
|
|
- );
|
459
|
|
- }
|
460
|
|
- }
|
461
|
|
-
|
462
|
|
- return $Inline;
|
463
|
|
- }
|
464
|
|
-
|
465
|
|
- #
|
466
|
|
- # Util Methods
|
467
|
|
- #
|
468
|
|
-
|
469
|
|
- protected function addDdElement(array $Line, array $Block)
|
470
|
|
- {
|
471
|
|
- $text = substr($Line['text'], 1);
|
472
|
|
- $text = trim($text);
|
473
|
|
-
|
474
|
|
- unset($Block['dd']);
|
475
|
|
-
|
476
|
|
- $Block['dd'] = array(
|
477
|
|
- 'name' => 'dd',
|
478
|
|
- 'handler' => array(
|
479
|
|
- 'function' => 'lineElements',
|
480
|
|
- 'argument' => $text,
|
481
|
|
- 'destination' => 'elements'
|
482
|
|
- ),
|
483
|
|
- );
|
484
|
|
-
|
485
|
|
- if (isset($Block['interrupted']))
|
486
|
|
- {
|
487
|
|
- $Block['dd']['handler']['function'] = 'textElements';
|
488
|
|
-
|
489
|
|
- unset($Block['interrupted']);
|
490
|
|
- }
|
491
|
|
-
|
492
|
|
- $Block['element']['elements'] []= & $Block['dd'];
|
493
|
|
-
|
494
|
|
- return $Block;
|
495
|
|
- }
|
496
|
|
-
|
497
|
|
- protected function buildFootnoteElement()
|
498
|
|
- {
|
499
|
|
- $Element = array(
|
500
|
|
- 'name' => 'div',
|
501
|
|
- 'attributes' => array('class' => 'footnotes'),
|
502
|
|
- 'elements' => array(
|
503
|
|
- array('name' => 'hr'),
|
504
|
|
- array(
|
505
|
|
- 'name' => 'ol',
|
506
|
|
- 'elements' => array(),
|
507
|
|
- ),
|
508
|
|
- ),
|
509
|
|
- );
|
510
|
|
-
|
511
|
|
- uasort($this->DefinitionData['Footnote'], 'self::sortFootnotes');
|
512
|
|
-
|
513
|
|
- foreach ($this->DefinitionData['Footnote'] as $definitionId => $DefinitionData)
|
514
|
|
- {
|
515
|
|
- if ( ! isset($DefinitionData['number']))
|
516
|
|
- {
|
517
|
|
- continue;
|
518
|
|
- }
|
519
|
|
-
|
520
|
|
- $text = $DefinitionData['text'];
|
521
|
|
-
|
522
|
|
- $textElements = parent::textElements($text);
|
523
|
|
-
|
524
|
|
- $numbers = range(1, $DefinitionData['count']);
|
525
|
|
-
|
526
|
|
- $backLinkElements = array();
|
527
|
|
-
|
528
|
|
- foreach ($numbers as $number)
|
529
|
|
- {
|
530
|
|
- $backLinkElements[] = array('text' => ' ');
|
531
|
|
- $backLinkElements[] = array(
|
532
|
|
- 'name' => 'a',
|
533
|
|
- 'attributes' => array(
|
534
|
|
- 'href' => "#fnref$number:$definitionId",
|
535
|
|
- 'rev' => 'footnote',
|
536
|
|
- 'class' => 'footnote-backref',
|
537
|
|
- ),
|
538
|
|
- 'rawHtml' => '↩',
|
539
|
|
- 'allowRawHtmlInSafeMode' => true,
|
540
|
|
- 'autobreak' => false,
|
541
|
|
- );
|
542
|
|
- }
|
543
|
|
-
|
544
|
|
- unset($backLinkElements[0]);
|
545
|
|
-
|
546
|
|
- $n = count($textElements) -1;
|
547
|
|
-
|
548
|
|
- if ($textElements[$n]['name'] === 'p')
|
549
|
|
- {
|
550
|
|
- $backLinkElements = array_merge(
|
551
|
|
- array(
|
552
|
|
- array(
|
553
|
|
- 'rawHtml' => ' ',
|
554
|
|
- 'allowRawHtmlInSafeMode' => true,
|
555
|
|
- ),
|
556
|
|
- ),
|
557
|
|
- $backLinkElements
|
558
|
|
- );
|
559
|
|
-
|
560
|
|
- unset($textElements[$n]['name']);
|
561
|
|
-
|
562
|
|
- $textElements[$n] = array(
|
563
|
|
- 'name' => 'p',
|
564
|
|
- 'elements' => array_merge(
|
565
|
|
- array($textElements[$n]),
|
566
|
|
- $backLinkElements
|
567
|
|
- ),
|
568
|
|
- );
|
569
|
|
- }
|
570
|
|
- else
|
571
|
|
- {
|
572
|
|
- $textElements[] = array(
|
573
|
|
- 'name' => 'p',
|
574
|
|
- 'elements' => $backLinkElements
|
575
|
|
- );
|
576
|
|
- }
|
577
|
|
-
|
578
|
|
- $Element['elements'][1]['elements'] []= array(
|
579
|
|
- 'name' => 'li',
|
580
|
|
- 'attributes' => array('id' => 'fn:'.$definitionId),
|
581
|
|
- 'elements' => array_merge(
|
582
|
|
- $textElements
|
583
|
|
- ),
|
584
|
|
- );
|
585
|
|
- }
|
586
|
|
-
|
587
|
|
- return $Element;
|
588
|
|
- }
|
589
|
|
-
|
590
|
|
- # ~
|
591
|
|
-
|
592
|
|
- protected function parseAttributeData($attributeString)
|
593
|
|
- {
|
594
|
|
- $Data = array();
|
595
|
|
-
|
596
|
|
- $attributes = preg_split('/[ ]+/', $attributeString, - 1, PREG_SPLIT_NO_EMPTY);
|
597
|
|
-
|
598
|
|
- foreach ($attributes as $attribute)
|
599
|
|
- {
|
600
|
|
- if ($attribute[0] === '#')
|
601
|
|
- {
|
602
|
|
- $Data['id'] = substr($attribute, 1);
|
603
|
|
- }
|
604
|
|
- else # "."
|
605
|
|
- {
|
606
|
|
- $classes []= substr($attribute, 1);
|
607
|
|
- }
|
608
|
|
- }
|
609
|
|
-
|
610
|
|
- if (isset($classes))
|
611
|
|
- {
|
612
|
|
- $Data['class'] = implode(' ', $classes);
|
613
|
|
- }
|
614
|
|
-
|
615
|
|
- return $Data;
|
616
|
|
- }
|
617
|
|
-
|
618
|
|
- # ~
|
619
|
|
-
|
620
|
|
- protected function processTag($elementMarkup) # recursive
|
621
|
|
- {
|
622
|
|
- # http://stackoverflow.com/q/1148928/200145
|
623
|
|
- libxml_use_internal_errors(true);
|
624
|
|
-
|
625
|
|
- $DOMDocument = new DOMDocument;
|
626
|
|
-
|
627
|
|
- # http://stackoverflow.com/q/11309194/200145
|
628
|
|
- $elementMarkup = mb_convert_encoding($elementMarkup, 'HTML-ENTITIES', 'UTF-8');
|
629
|
|
-
|
630
|
|
- # http://stackoverflow.com/q/4879946/200145
|
631
|
|
- $DOMDocument->loadHTML($elementMarkup);
|
632
|
|
- $DOMDocument->removeChild($DOMDocument->doctype);
|
633
|
|
- $DOMDocument->replaceChild($DOMDocument->firstChild->firstChild->firstChild, $DOMDocument->firstChild);
|
634
|
|
-
|
635
|
|
- $elementText = '';
|
636
|
|
-
|
637
|
|
- if ($DOMDocument->documentElement->getAttribute('markdown') === '1')
|
638
|
|
- {
|
639
|
|
- foreach ($DOMDocument->documentElement->childNodes as $Node)
|
640
|
|
- {
|
641
|
|
- $elementText .= $DOMDocument->saveHTML($Node);
|
642
|
|
- }
|
643
|
|
-
|
644
|
|
- $DOMDocument->documentElement->removeAttribute('markdown');
|
645
|
|
-
|
646
|
|
- $elementText = "\n".$this->text($elementText)."\n";
|
647
|
|
- }
|
648
|
|
- else
|
649
|
|
- {
|
650
|
|
- foreach ($DOMDocument->documentElement->childNodes as $Node)
|
651
|
|
- {
|
652
|
|
- $nodeMarkup = $DOMDocument->saveHTML($Node);
|
653
|
|
-
|
654
|
|
- if ($Node instanceof DOMElement and ! in_array($Node->nodeName, $this->textLevelElements))
|
655
|
|
- {
|
656
|
|
- $elementText .= $this->processTag($nodeMarkup);
|
657
|
|
- }
|
658
|
|
- else
|
659
|
|
- {
|
660
|
|
- $elementText .= $nodeMarkup;
|
661
|
|
- }
|
662
|
|
- }
|
663
|
|
- }
|
664
|
|
-
|
665
|
|
- # because we don't want for markup to get encoded
|
666
|
|
- $DOMDocument->documentElement->nodeValue = 'placeholder\x1A';
|
667
|
|
-
|
668
|
|
- $markup = $DOMDocument->saveHTML($DOMDocument->documentElement);
|
669
|
|
- $markup = str_replace('placeholder\x1A', $elementText, $markup);
|
670
|
|
-
|
671
|
|
- return $markup;
|
672
|
|
- }
|
673
|
|
-
|
674
|
|
- # ~
|
675
|
|
-
|
676
|
|
- protected function sortFootnotes($A, $B) # callback
|
677
|
|
- {
|
678
|
|
- return $A['number'] - $B['number'];
|
679
|
|
- }
|
680
|
|
-
|
681
|
|
- #
|
682
|
|
- # Fields
|
683
|
|
- #
|
684
|
|
-
|
685
|
|
- protected $regexAttribute = '(?:[#.][-\w]+[ ]*)';
|
686
|
|
-}
|