ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
Html.php
Go to the documentation of this file.
1 <?php
2 
4 
5 use DOMDocument;
6 use DOMElement;
7 use DOMNode;
8 use DOMText;
12 
13 class Html
14 {
15  protected static $colourMap = [
16  'aliceblue' => 'f0f8ff',
17  'antiquewhite' => 'faebd7',
18  'antiquewhite1' => 'ffefdb',
19  'antiquewhite2' => 'eedfcc',
20  'antiquewhite3' => 'cdc0b0',
21  'antiquewhite4' => '8b8378',
22  'aqua' => '00ffff',
23  'aquamarine1' => '7fffd4',
24  'aquamarine2' => '76eec6',
25  'aquamarine4' => '458b74',
26  'azure1' => 'f0ffff',
27  'azure2' => 'e0eeee',
28  'azure3' => 'c1cdcd',
29  'azure4' => '838b8b',
30  'beige' => 'f5f5dc',
31  'bisque1' => 'ffe4c4',
32  'bisque2' => 'eed5b7',
33  'bisque3' => 'cdb79e',
34  'bisque4' => '8b7d6b',
35  'black' => '000000',
36  'blanchedalmond' => 'ffebcd',
37  'blue' => '0000ff',
38  'blue1' => '0000ff',
39  'blue2' => '0000ee',
40  'blue4' => '00008b',
41  'blueviolet' => '8a2be2',
42  'brown' => 'a52a2a',
43  'brown1' => 'ff4040',
44  'brown2' => 'ee3b3b',
45  'brown3' => 'cd3333',
46  'brown4' => '8b2323',
47  'burlywood' => 'deb887',
48  'burlywood1' => 'ffd39b',
49  'burlywood2' => 'eec591',
50  'burlywood3' => 'cdaa7d',
51  'burlywood4' => '8b7355',
52  'cadetblue' => '5f9ea0',
53  'cadetblue1' => '98f5ff',
54  'cadetblue2' => '8ee5ee',
55  'cadetblue3' => '7ac5cd',
56  'cadetblue4' => '53868b',
57  'chartreuse1' => '7fff00',
58  'chartreuse2' => '76ee00',
59  'chartreuse3' => '66cd00',
60  'chartreuse4' => '458b00',
61  'chocolate' => 'd2691e',
62  'chocolate1' => 'ff7f24',
63  'chocolate2' => 'ee7621',
64  'chocolate3' => 'cd661d',
65  'coral' => 'ff7f50',
66  'coral1' => 'ff7256',
67  'coral2' => 'ee6a50',
68  'coral3' => 'cd5b45',
69  'coral4' => '8b3e2f',
70  'cornflowerblue' => '6495ed',
71  'cornsilk1' => 'fff8dc',
72  'cornsilk2' => 'eee8cd',
73  'cornsilk3' => 'cdc8b1',
74  'cornsilk4' => '8b8878',
75  'cyan1' => '00ffff',
76  'cyan2' => '00eeee',
77  'cyan3' => '00cdcd',
78  'cyan4' => '008b8b',
79  'darkgoldenrod' => 'b8860b',
80  'darkgoldenrod1' => 'ffb90f',
81  'darkgoldenrod2' => 'eead0e',
82  'darkgoldenrod3' => 'cd950c',
83  'darkgoldenrod4' => '8b6508',
84  'darkgreen' => '006400',
85  'darkkhaki' => 'bdb76b',
86  'darkolivegreen' => '556b2f',
87  'darkolivegreen1' => 'caff70',
88  'darkolivegreen2' => 'bcee68',
89  'darkolivegreen3' => 'a2cd5a',
90  'darkolivegreen4' => '6e8b3d',
91  'darkorange' => 'ff8c00',
92  'darkorange1' => 'ff7f00',
93  'darkorange2' => 'ee7600',
94  'darkorange3' => 'cd6600',
95  'darkorange4' => '8b4500',
96  'darkorchid' => '9932cc',
97  'darkorchid1' => 'bf3eff',
98  'darkorchid2' => 'b23aee',
99  'darkorchid3' => '9a32cd',
100  'darkorchid4' => '68228b',
101  'darksalmon' => 'e9967a',
102  'darkseagreen' => '8fbc8f',
103  'darkseagreen1' => 'c1ffc1',
104  'darkseagreen2' => 'b4eeb4',
105  'darkseagreen3' => '9bcd9b',
106  'darkseagreen4' => '698b69',
107  'darkslateblue' => '483d8b',
108  'darkslategray' => '2f4f4f',
109  'darkslategray1' => '97ffff',
110  'darkslategray2' => '8deeee',
111  'darkslategray3' => '79cdcd',
112  'darkslategray4' => '528b8b',
113  'darkturquoise' => '00ced1',
114  'darkviolet' => '9400d3',
115  'deeppink1' => 'ff1493',
116  'deeppink2' => 'ee1289',
117  'deeppink3' => 'cd1076',
118  'deeppink4' => '8b0a50',
119  'deepskyblue1' => '00bfff',
120  'deepskyblue2' => '00b2ee',
121  'deepskyblue3' => '009acd',
122  'deepskyblue4' => '00688b',
123  'dimgray' => '696969',
124  'dodgerblue1' => '1e90ff',
125  'dodgerblue2' => '1c86ee',
126  'dodgerblue3' => '1874cd',
127  'dodgerblue4' => '104e8b',
128  'firebrick' => 'b22222',
129  'firebrick1' => 'ff3030',
130  'firebrick2' => 'ee2c2c',
131  'firebrick3' => 'cd2626',
132  'firebrick4' => '8b1a1a',
133  'floralwhite' => 'fffaf0',
134  'forestgreen' => '228b22',
135  'fuchsia' => 'ff00ff',
136  'gainsboro' => 'dcdcdc',
137  'ghostwhite' => 'f8f8ff',
138  'gold1' => 'ffd700',
139  'gold2' => 'eec900',
140  'gold3' => 'cdad00',
141  'gold4' => '8b7500',
142  'goldenrod' => 'daa520',
143  'goldenrod1' => 'ffc125',
144  'goldenrod2' => 'eeb422',
145  'goldenrod3' => 'cd9b1d',
146  'goldenrod4' => '8b6914',
147  'gray' => 'bebebe',
148  'gray1' => '030303',
149  'gray10' => '1a1a1a',
150  'gray11' => '1c1c1c',
151  'gray12' => '1f1f1f',
152  'gray13' => '212121',
153  'gray14' => '242424',
154  'gray15' => '262626',
155  'gray16' => '292929',
156  'gray17' => '2b2b2b',
157  'gray18' => '2e2e2e',
158  'gray19' => '303030',
159  'gray2' => '050505',
160  'gray20' => '333333',
161  'gray21' => '363636',
162  'gray22' => '383838',
163  'gray23' => '3b3b3b',
164  'gray24' => '3d3d3d',
165  'gray25' => '404040',
166  'gray26' => '424242',
167  'gray27' => '454545',
168  'gray28' => '474747',
169  'gray29' => '4a4a4a',
170  'gray3' => '080808',
171  'gray30' => '4d4d4d',
172  'gray31' => '4f4f4f',
173  'gray32' => '525252',
174  'gray33' => '545454',
175  'gray34' => '575757',
176  'gray35' => '595959',
177  'gray36' => '5c5c5c',
178  'gray37' => '5e5e5e',
179  'gray38' => '616161',
180  'gray39' => '636363',
181  'gray4' => '0a0a0a',
182  'gray40' => '666666',
183  'gray41' => '696969',
184  'gray42' => '6b6b6b',
185  'gray43' => '6e6e6e',
186  'gray44' => '707070',
187  'gray45' => '737373',
188  'gray46' => '757575',
189  'gray47' => '787878',
190  'gray48' => '7a7a7a',
191  'gray49' => '7d7d7d',
192  'gray5' => '0d0d0d',
193  'gray50' => '7f7f7f',
194  'gray51' => '828282',
195  'gray52' => '858585',
196  'gray53' => '878787',
197  'gray54' => '8a8a8a',
198  'gray55' => '8c8c8c',
199  'gray56' => '8f8f8f',
200  'gray57' => '919191',
201  'gray58' => '949494',
202  'gray59' => '969696',
203  'gray6' => '0f0f0f',
204  'gray60' => '999999',
205  'gray61' => '9c9c9c',
206  'gray62' => '9e9e9e',
207  'gray63' => 'a1a1a1',
208  'gray64' => 'a3a3a3',
209  'gray65' => 'a6a6a6',
210  'gray66' => 'a8a8a8',
211  'gray67' => 'ababab',
212  'gray68' => 'adadad',
213  'gray69' => 'b0b0b0',
214  'gray7' => '121212',
215  'gray70' => 'b3b3b3',
216  'gray71' => 'b5b5b5',
217  'gray72' => 'b8b8b8',
218  'gray73' => 'bababa',
219  'gray74' => 'bdbdbd',
220  'gray75' => 'bfbfbf',
221  'gray76' => 'c2c2c2',
222  'gray77' => 'c4c4c4',
223  'gray78' => 'c7c7c7',
224  'gray79' => 'c9c9c9',
225  'gray8' => '141414',
226  'gray80' => 'cccccc',
227  'gray81' => 'cfcfcf',
228  'gray82' => 'd1d1d1',
229  'gray83' => 'd4d4d4',
230  'gray84' => 'd6d6d6',
231  'gray85' => 'd9d9d9',
232  'gray86' => 'dbdbdb',
233  'gray87' => 'dedede',
234  'gray88' => 'e0e0e0',
235  'gray89' => 'e3e3e3',
236  'gray9' => '171717',
237  'gray90' => 'e5e5e5',
238  'gray91' => 'e8e8e8',
239  'gray92' => 'ebebeb',
240  'gray93' => 'ededed',
241  'gray94' => 'f0f0f0',
242  'gray95' => 'f2f2f2',
243  'gray97' => 'f7f7f7',
244  'gray98' => 'fafafa',
245  'gray99' => 'fcfcfc',
246  'green' => '00ff00',
247  'green1' => '00ff00',
248  'green2' => '00ee00',
249  'green3' => '00cd00',
250  'green4' => '008b00',
251  'greenyellow' => 'adff2f',
252  'honeydew1' => 'f0fff0',
253  'honeydew2' => 'e0eee0',
254  'honeydew3' => 'c1cdc1',
255  'honeydew4' => '838b83',
256  'hotpink' => 'ff69b4',
257  'hotpink1' => 'ff6eb4',
258  'hotpink2' => 'ee6aa7',
259  'hotpink3' => 'cd6090',
260  'hotpink4' => '8b3a62',
261  'indianred' => 'cd5c5c',
262  'indianred1' => 'ff6a6a',
263  'indianred2' => 'ee6363',
264  'indianred3' => 'cd5555',
265  'indianred4' => '8b3a3a',
266  'ivory1' => 'fffff0',
267  'ivory2' => 'eeeee0',
268  'ivory3' => 'cdcdc1',
269  'ivory4' => '8b8b83',
270  'khaki' => 'f0e68c',
271  'khaki1' => 'fff68f',
272  'khaki2' => 'eee685',
273  'khaki3' => 'cdc673',
274  'khaki4' => '8b864e',
275  'lavender' => 'e6e6fa',
276  'lavenderblush1' => 'fff0f5',
277  'lavenderblush2' => 'eee0e5',
278  'lavenderblush3' => 'cdc1c5',
279  'lavenderblush4' => '8b8386',
280  'lawngreen' => '7cfc00',
281  'lemonchiffon1' => 'fffacd',
282  'lemonchiffon2' => 'eee9bf',
283  'lemonchiffon3' => 'cdc9a5',
284  'lemonchiffon4' => '8b8970',
285  'light' => 'eedd82',
286  'lightblue' => 'add8e6',
287  'lightblue1' => 'bfefff',
288  'lightblue2' => 'b2dfee',
289  'lightblue3' => '9ac0cd',
290  'lightblue4' => '68838b',
291  'lightcoral' => 'f08080',
292  'lightcyan1' => 'e0ffff',
293  'lightcyan2' => 'd1eeee',
294  'lightcyan3' => 'b4cdcd',
295  'lightcyan4' => '7a8b8b',
296  'lightgoldenrod1' => 'ffec8b',
297  'lightgoldenrod2' => 'eedc82',
298  'lightgoldenrod3' => 'cdbe70',
299  'lightgoldenrod4' => '8b814c',
300  'lightgoldenrodyellow' => 'fafad2',
301  'lightgray' => 'd3d3d3',
302  'lightpink' => 'ffb6c1',
303  'lightpink1' => 'ffaeb9',
304  'lightpink2' => 'eea2ad',
305  'lightpink3' => 'cd8c95',
306  'lightpink4' => '8b5f65',
307  'lightsalmon1' => 'ffa07a',
308  'lightsalmon2' => 'ee9572',
309  'lightsalmon3' => 'cd8162',
310  'lightsalmon4' => '8b5742',
311  'lightseagreen' => '20b2aa',
312  'lightskyblue' => '87cefa',
313  'lightskyblue1' => 'b0e2ff',
314  'lightskyblue2' => 'a4d3ee',
315  'lightskyblue3' => '8db6cd',
316  'lightskyblue4' => '607b8b',
317  'lightslateblue' => '8470ff',
318  'lightslategray' => '778899',
319  'lightsteelblue' => 'b0c4de',
320  'lightsteelblue1' => 'cae1ff',
321  'lightsteelblue2' => 'bcd2ee',
322  'lightsteelblue3' => 'a2b5cd',
323  'lightsteelblue4' => '6e7b8b',
324  'lightyellow1' => 'ffffe0',
325  'lightyellow2' => 'eeeed1',
326  'lightyellow3' => 'cdcdb4',
327  'lightyellow4' => '8b8b7a',
328  'lime' => '00ff00',
329  'limegreen' => '32cd32',
330  'linen' => 'faf0e6',
331  'magenta' => 'ff00ff',
332  'magenta2' => 'ee00ee',
333  'magenta3' => 'cd00cd',
334  'magenta4' => '8b008b',
335  'maroon' => 'b03060',
336  'maroon1' => 'ff34b3',
337  'maroon2' => 'ee30a7',
338  'maroon3' => 'cd2990',
339  'maroon4' => '8b1c62',
340  'medium' => '66cdaa',
341  'mediumaquamarine' => '66cdaa',
342  'mediumblue' => '0000cd',
343  'mediumorchid' => 'ba55d3',
344  'mediumorchid1' => 'e066ff',
345  'mediumorchid2' => 'd15fee',
346  'mediumorchid3' => 'b452cd',
347  'mediumorchid4' => '7a378b',
348  'mediumpurple' => '9370db',
349  'mediumpurple1' => 'ab82ff',
350  'mediumpurple2' => '9f79ee',
351  'mediumpurple3' => '8968cd',
352  'mediumpurple4' => '5d478b',
353  'mediumseagreen' => '3cb371',
354  'mediumslateblue' => '7b68ee',
355  'mediumspringgreen' => '00fa9a',
356  'mediumturquoise' => '48d1cc',
357  'mediumvioletred' => 'c71585',
358  'midnightblue' => '191970',
359  'mintcream' => 'f5fffa',
360  'mistyrose1' => 'ffe4e1',
361  'mistyrose2' => 'eed5d2',
362  'mistyrose3' => 'cdb7b5',
363  'mistyrose4' => '8b7d7b',
364  'moccasin' => 'ffe4b5',
365  'navajowhite1' => 'ffdead',
366  'navajowhite2' => 'eecfa1',
367  'navajowhite3' => 'cdb38b',
368  'navajowhite4' => '8b795e',
369  'navy' => '000080',
370  'navyblue' => '000080',
371  'oldlace' => 'fdf5e6',
372  'olive' => '808000',
373  'olivedrab' => '6b8e23',
374  'olivedrab1' => 'c0ff3e',
375  'olivedrab2' => 'b3ee3a',
376  'olivedrab4' => '698b22',
377  'orange' => 'ffa500',
378  'orange1' => 'ffa500',
379  'orange2' => 'ee9a00',
380  'orange3' => 'cd8500',
381  'orange4' => '8b5a00',
382  'orangered1' => 'ff4500',
383  'orangered2' => 'ee4000',
384  'orangered3' => 'cd3700',
385  'orangered4' => '8b2500',
386  'orchid' => 'da70d6',
387  'orchid1' => 'ff83fa',
388  'orchid2' => 'ee7ae9',
389  'orchid3' => 'cd69c9',
390  'orchid4' => '8b4789',
391  'pale' => 'db7093',
392  'palegoldenrod' => 'eee8aa',
393  'palegreen' => '98fb98',
394  'palegreen1' => '9aff9a',
395  'palegreen2' => '90ee90',
396  'palegreen3' => '7ccd7c',
397  'palegreen4' => '548b54',
398  'paleturquoise' => 'afeeee',
399  'paleturquoise1' => 'bbffff',
400  'paleturquoise2' => 'aeeeee',
401  'paleturquoise3' => '96cdcd',
402  'paleturquoise4' => '668b8b',
403  'palevioletred' => 'db7093',
404  'palevioletred1' => 'ff82ab',
405  'palevioletred2' => 'ee799f',
406  'palevioletred3' => 'cd6889',
407  'palevioletred4' => '8b475d',
408  'papayawhip' => 'ffefd5',
409  'peachpuff1' => 'ffdab9',
410  'peachpuff2' => 'eecbad',
411  'peachpuff3' => 'cdaf95',
412  'peachpuff4' => '8b7765',
413  'pink' => 'ffc0cb',
414  'pink1' => 'ffb5c5',
415  'pink2' => 'eea9b8',
416  'pink3' => 'cd919e',
417  'pink4' => '8b636c',
418  'plum' => 'dda0dd',
419  'plum1' => 'ffbbff',
420  'plum2' => 'eeaeee',
421  'plum3' => 'cd96cd',
422  'plum4' => '8b668b',
423  'powderblue' => 'b0e0e6',
424  'purple' => 'a020f0',
425  'rebeccapurple' => '663399',
426  'purple1' => '9b30ff',
427  'purple2' => '912cee',
428  'purple3' => '7d26cd',
429  'purple4' => '551a8b',
430  'red' => 'ff0000',
431  'red1' => 'ff0000',
432  'red2' => 'ee0000',
433  'red3' => 'cd0000',
434  'red4' => '8b0000',
435  'rosybrown' => 'bc8f8f',
436  'rosybrown1' => 'ffc1c1',
437  'rosybrown2' => 'eeb4b4',
438  'rosybrown3' => 'cd9b9b',
439  'rosybrown4' => '8b6969',
440  'royalblue' => '4169e1',
441  'royalblue1' => '4876ff',
442  'royalblue2' => '436eee',
443  'royalblue3' => '3a5fcd',
444  'royalblue4' => '27408b',
445  'saddlebrown' => '8b4513',
446  'salmon' => 'fa8072',
447  'salmon1' => 'ff8c69',
448  'salmon2' => 'ee8262',
449  'salmon3' => 'cd7054',
450  'salmon4' => '8b4c39',
451  'sandybrown' => 'f4a460',
452  'seagreen1' => '54ff9f',
453  'seagreen2' => '4eee94',
454  'seagreen3' => '43cd80',
455  'seagreen4' => '2e8b57',
456  'seashell1' => 'fff5ee',
457  'seashell2' => 'eee5de',
458  'seashell3' => 'cdc5bf',
459  'seashell4' => '8b8682',
460  'sienna' => 'a0522d',
461  'sienna1' => 'ff8247',
462  'sienna2' => 'ee7942',
463  'sienna3' => 'cd6839',
464  'sienna4' => '8b4726',
465  'silver' => 'c0c0c0',
466  'skyblue' => '87ceeb',
467  'skyblue1' => '87ceff',
468  'skyblue2' => '7ec0ee',
469  'skyblue3' => '6ca6cd',
470  'skyblue4' => '4a708b',
471  'slateblue' => '6a5acd',
472  'slateblue1' => '836fff',
473  'slateblue2' => '7a67ee',
474  'slateblue3' => '6959cd',
475  'slateblue4' => '473c8b',
476  'slategray' => '708090',
477  'slategray1' => 'c6e2ff',
478  'slategray2' => 'b9d3ee',
479  'slategray3' => '9fb6cd',
480  'slategray4' => '6c7b8b',
481  'snow1' => 'fffafa',
482  'snow2' => 'eee9e9',
483  'snow3' => 'cdc9c9',
484  'snow4' => '8b8989',
485  'springgreen1' => '00ff7f',
486  'springgreen2' => '00ee76',
487  'springgreen3' => '00cd66',
488  'springgreen4' => '008b45',
489  'steelblue' => '4682b4',
490  'steelblue1' => '63b8ff',
491  'steelblue2' => '5cacee',
492  'steelblue3' => '4f94cd',
493  'steelblue4' => '36648b',
494  'tan' => 'd2b48c',
495  'tan1' => 'ffa54f',
496  'tan2' => 'ee9a49',
497  'tan3' => 'cd853f',
498  'tan4' => '8b5a2b',
499  'teal' => '008080',
500  'thistle' => 'd8bfd8',
501  'thistle1' => 'ffe1ff',
502  'thistle2' => 'eed2ee',
503  'thistle3' => 'cdb5cd',
504  'thistle4' => '8b7b8b',
505  'tomato1' => 'ff6347',
506  'tomato2' => 'ee5c42',
507  'tomato3' => 'cd4f39',
508  'tomato4' => '8b3626',
509  'turquoise' => '40e0d0',
510  'turquoise1' => '00f5ff',
511  'turquoise2' => '00e5ee',
512  'turquoise3' => '00c5cd',
513  'turquoise4' => '00868b',
514  'violet' => 'ee82ee',
515  'violetred' => 'd02090',
516  'violetred1' => 'ff3e96',
517  'violetred2' => 'ee3a8c',
518  'violetred3' => 'cd3278',
519  'violetred4' => '8b2252',
520  'wheat' => 'f5deb3',
521  'wheat1' => 'ffe7ba',
522  'wheat2' => 'eed8ae',
523  'wheat3' => 'cdba96',
524  'wheat4' => '8b7e66',
525  'white' => 'ffffff',
526  'whitesmoke' => 'f5f5f5',
527  'yellow' => 'ffff00',
528  'yellow1' => 'ffff00',
529  'yellow2' => 'eeee00',
530  'yellow3' => 'cdcd00',
531  'yellow4' => '8b8b00',
532  'yellowgreen' => '9acd32',
533  ];
534 
535  protected $face;
536 
537  protected $size;
538 
539  protected $color;
540 
541  protected $bold = false;
542 
543  protected $italic = false;
544 
545  protected $underline = false;
546 
547  protected $superscript = false;
548 
549  protected $subscript = false;
550 
551  protected $strikethrough = false;
552 
553  protected $startTagCallbacks = [
554  'font' => 'startFontTag',
555  'b' => 'startBoldTag',
556  'strong' => 'startBoldTag',
557  'i' => 'startItalicTag',
558  'em' => 'startItalicTag',
559  'u' => 'startUnderlineTag',
560  'ins' => 'startUnderlineTag',
561  'del' => 'startStrikethruTag',
562  'sup' => 'startSuperscriptTag',
563  'sub' => 'startSubscriptTag',
564  ];
565 
566  protected $endTagCallbacks = [
567  'font' => 'endFontTag',
568  'b' => 'endBoldTag',
569  'strong' => 'endBoldTag',
570  'i' => 'endItalicTag',
571  'em' => 'endItalicTag',
572  'u' => 'endUnderlineTag',
573  'ins' => 'endUnderlineTag',
574  'del' => 'endStrikethruTag',
575  'sup' => 'endSuperscriptTag',
576  'sub' => 'endSubscriptTag',
577  'br' => 'breakTag',
578  'p' => 'breakTag',
579  'h1' => 'breakTag',
580  'h2' => 'breakTag',
581  'h3' => 'breakTag',
582  'h4' => 'breakTag',
583  'h5' => 'breakTag',
584  'h6' => 'breakTag',
585  ];
586 
587  protected $stack = [];
588 
589  protected $stringData = '';
590 
594  protected $richTextObject;
595 
596  protected function initialise(): void
597  {
598  $this->face = $this->size = $this->color = null;
599  $this->bold = $this->italic = $this->underline = $this->superscript = $this->subscript = $this->strikethrough = false;
600 
601  $this->stack = [];
602 
603  $this->stringData = '';
604  }
605 
613  public function toRichTextObject($html)
614  {
615  $this->initialise();
616 
617  // Create a new DOM object
618  $dom = new DOMDocument();
619  // Load the HTML file into the DOM object
620  // Note the use of error suppression, because typically this will be an html fragment, so not fully valid markup
621  $prefix = '<?xml encoding="UTF-8">';
622  @$dom->loadHTML($prefix . $html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
623  // Discard excess white space
624  $dom->preserveWhiteSpace = false;
625 
626  $this->richTextObject = new RichText();
627  $this->parseElements($dom);
628 
629  // Clean any further spurious whitespace
630  $this->cleanWhitespace();
631 
632  return $this->richTextObject;
633  }
634 
635  protected function cleanWhitespace(): void
636  {
637  foreach ($this->richTextObject->getRichTextElements() as $key => $element) {
638  $text = $element->getText();
639  // Trim any leading spaces on the first run
640  if ($key == 0) {
641  $text = ltrim($text);
642  }
643  // Trim any spaces immediately after a line break
644  $text = preg_replace('/\n */mu', "\n", $text);
645  $element->setText($text);
646  }
647  }
648 
649  protected function buildTextRun(): void
650  {
652  if (trim($text) === '') {
653  return;
654  }
655 
656  $richtextRun = $this->richTextObject->createTextRun($this->stringData);
657  if ($this->face) {
658  $richtextRun->getFont()->setName($this->face);
659  }
660  if ($this->size) {
661  $richtextRun->getFont()->setSize($this->size);
662  }
663  if ($this->color) {
664  $richtextRun->getFont()->setColor(new Color('ff' . $this->color));
665  }
666  if ($this->bold) {
667  $richtextRun->getFont()->setBold(true);
668  }
669  if ($this->italic) {
670  $richtextRun->getFont()->setItalic(true);
671  }
672  if ($this->underline) {
673  $richtextRun->getFont()->setUnderline(Font::UNDERLINE_SINGLE);
674  }
675  if ($this->superscript) {
676  $richtextRun->getFont()->setSuperscript(true);
677  }
678  if ($this->subscript) {
679  $richtextRun->getFont()->setSubscript(true);
680  }
681  if ($this->strikethrough) {
682  $richtextRun->getFont()->setStrikethrough(true);
683  }
684  $this->stringData = '';
685  }
686 
687  protected function rgbToColour($rgb)
688  {
689  preg_match_all('/\d+/', $rgb, $values);
690  foreach ($values[0] as &$value) {
691  $value = str_pad(dechex($value), 2, '0', STR_PAD_LEFT);
692  }
693 
694  return implode('', $values[0]);
695  }
696 
697  public static function colourNameLookup(string $rgb): string
698  {
699  return self::$colourMap[$rgb] ?? '';
700  }
701 
702  protected function startFontTag($tag): void
703  {
704  foreach ($tag->attributes as $attribute) {
705  $attributeName = strtolower($attribute->name);
706  $attributeValue = $attribute->value;
707 
708  if ($attributeName == 'color') {
709  if (preg_match('/rgb\s*\(/', $attributeValue)) {
710  $this->$attributeName = $this->rgbToColour($attributeValue);
711  } elseif (strpos(trim($attributeValue), '#') === 0) {
712  $this->$attributeName = ltrim($attributeValue, '#');
713  } else {
714  $this->$attributeName = static::colourNameLookup($attributeValue);
715  }
716  } else {
717  $this->$attributeName = $attributeValue;
718  }
719  }
720  }
721 
722  protected function endFontTag(): void
723  {
724  $this->face = $this->size = $this->color = null;
725  }
726 
727  protected function startBoldTag(): void
728  {
729  $this->bold = true;
730  }
731 
732  protected function endBoldTag(): void
733  {
734  $this->bold = false;
735  }
736 
737  protected function startItalicTag(): void
738  {
739  $this->italic = true;
740  }
741 
742  protected function endItalicTag(): void
743  {
744  $this->italic = false;
745  }
746 
747  protected function startUnderlineTag(): void
748  {
749  $this->underline = true;
750  }
751 
752  protected function endUnderlineTag(): void
753  {
754  $this->underline = false;
755  }
756 
757  protected function startSubscriptTag(): void
758  {
759  $this->subscript = true;
760  }
761 
762  protected function endSubscriptTag(): void
763  {
764  $this->subscript = false;
765  }
766 
767  protected function startSuperscriptTag(): void
768  {
769  $this->superscript = true;
770  }
771 
772  protected function endSuperscriptTag(): void
773  {
774  $this->superscript = false;
775  }
776 
777  protected function startStrikethruTag(): void
778  {
779  $this->strikethrough = true;
780  }
781 
782  protected function endStrikethruTag(): void
783  {
784  $this->strikethrough = false;
785  }
786 
787  protected function breakTag(): void
788  {
789  $this->stringData .= "\n";
790  }
791 
792  protected function parseTextNode(DOMText $textNode): void
793  {
794  $domText = preg_replace(
795  '/\s+/u',
796  ' ',
797  str_replace(["\r", "\n"], ' ', $textNode->nodeValue)
798  );
799  $this->stringData .= $domText;
800  $this->buildTextRun();
801  }
802 
806  protected function handleCallback(DOMElement $element, $callbackTag, array $callbacks): void
807  {
808  if (isset($callbacks[$callbackTag])) {
809  $elementHandler = $callbacks[$callbackTag];
810  if (method_exists($this, $elementHandler)) {
811  call_user_func([$this, $elementHandler], $element);
812  }
813  }
814  }
815 
816  protected function parseElementNode(DOMElement $element): void
817  {
818  $callbackTag = strtolower($element->nodeName);
819  $this->stack[] = $callbackTag;
820 
821  $this->handleCallback($element, $callbackTag, $this->startTagCallbacks);
822 
823  $this->parseElements($element);
824  array_pop($this->stack);
825 
826  $this->handleCallback($element, $callbackTag, $this->endTagCallbacks);
827  }
828 
829  protected function parseElements(DOMNode $element): void
830  {
831  foreach ($element->childNodes as $child) {
832  if ($child instanceof DOMText) {
833  $this->parseTextNode($child);
834  } elseif ($child instanceof DOMElement) {
835  $this->parseElementNode($child);
836  }
837  }
838  }
839 }
if(PHP_SAPI !='cli') color
Definition: langcheck.php:120
parseElements(DOMNode $element)
Definition: Html.php:829
toRichTextObject($html)
Parse HTML formatting and return the resulting RichText.
Definition: Html.php:613
handleCallback(DOMElement $element, $callbackTag, array $callbacks)
Definition: Html.php:806
parseTextNode(DOMText $textNode)
Definition: Html.php:792
$values
$text
Definition: errorreport.php:18
font size
Definition: langcheck.php:162
$key
Definition: croninfo.php:18
$html
Definition: example_001.php:87
if(function_exists('posix_getuid') &&posix_getuid()===0) if(!array_key_exists('t', $options)) $tag
Definition: cron.php:35
static colourNameLookup(string $rgb)
Definition: Html.php:697
parseElementNode(DOMElement $element)
Definition: Html.php:816