-
Notifications
You must be signed in to change notification settings - Fork 0
/
bbcode.ts
2745 lines (2735 loc) · 110 KB
/
bbcode.ts
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
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
import BBCodeLibrary from "./bbcodelibrary";
import BBCodeLexer from "./bbcodelexer";
import Debugger from "./debugger";
import EmailAddressValidator from "./emailaddressvalidator";
import {version} from '../package.json';
//Modules
import preg_split, { PREG_SPLIT_DELIM_CAPTURE, PREG_SPLIT_NO_EMPTY } from "../modules/preg_split";
import filter_var from "../modules/filter_var";
import { htmlEncode, htmlDecode } from '../modules/html_entities';
import strip_tags from '../modules/strip_tags';
import basename from '../modules/basename';
import parse_url from "../modules/parse_url";
//Types
import { BBStack, BBToken, BBMode, BBType, BBAction, DebugLevel } from '../@types/enums';
import { ClassType, Param, StackType, TagRules, TagType } from "../@types/dataTypes";
/**
* This is the BBCode Library class, it is responsible for most of the internal parsing
* of the input into HTML.
*/
export default class BBCode {
/**
* Current version number
*/
static BBCODE_VERSION = version;
/**
* Current release date
*/
static BBCODE_RELEASE = '2023-08-16';
//-----------------------------------------------------------------------------
// Instance variables. Do not change any of these directly! Use the
// access methods provided below.
/**
* List of tag rules currently in use.
*/
protected tagRules: Record<string, TagRules>;
/**
* The standard library (an instance of class BBCodeLibrary).
*/
protected defaults: BBCodeLibrary;
/**
* The current class (auto-computed).
*/
protected currentClass: ClassType;
/**
* The root container class.
*/
protected rootClass: ClassType;
/**
* For repair when tags are badly mis-nested.
*/
protected lostStartTags: Record<string, number>;
/**
* An associative array of locations of start tags on the stack.
*/
protected startTags: Record<string, number[]>;
/**
* If true, we use String.replaceAll() instead of htmlEncode().
*/
protected allowAmpersand: boolean;
/**
* Set to '[', '<', '{', or '('.
*/
protected tagMarker: string;
/**
* If true, newlines will be treated as normal whitespace.
*/
protected ignoreNewlines;
/**
* Don't output tags: Just output text/whitespace/newlines only.
*/
protected plainMode: boolean;
/**
* Should we audo-detect URLs and convert them to links?
*/
protected detectURLs: boolean;
/**
* What to convert auto-detected URLs into.
*/
protected urlPattern: string;
/**
* The maximum number of text characters to output.
*/
protected outputLimit: number;
/**
* The number of text characters output so far.
*/
protected textLength: number;
/**
* Set to true if the output was cut off.
*/
protected wasLimited: boolean;
/**
* What to add if the output is cut off.
*/
protected limitTail: string;
/**
* How accurate should we be if we're cutting off text?
*/
protected limitPrecision: number;
/**
* The host filesystem path to emoji (should be an absolute path).
*/
protected emojiDir: string;
/**
* The URL path to emoji (possibly a relative path).
*/
protected emojiUrl: string;
/**
* The current list of emoji.
*/
protected emoji;
/**
* This is a regex, precomputed from the list of emoji above.
*/
protected emojiRegex;
/**
* Whether or not to perform emoji-parsing.
*/
protected emojiEnabled: boolean;
/**
* URL prefix used for [[wiki]] links.
*/
protected wikiUrl: string;
/**
* The host filesystem path to local images (should be an absolute path).
*/
protected localImgDir: string;
/**
* The URL path to local images (possibly a relative path).
*/
protected localImgUrl: string;
/**
* If true, [url] tags can accept a target="..." parameter.
*/
protected urlTargetable: boolean;
/**
* If non-false, [url] tags will use this target and no other.
*/
protected urlTarget: boolean | string;
/**
* The default template used with the default [url] tag.
*/
protected urlTemplate: string;
/**
* The default template used with the default [quote] tag.
*/
protected quoteTemplate: string;
/**
* The default template used when rendering wiki links.
*/
protected wikiUrlTemplate: string;
/**
* The default template used with the default [email] tag.
*/
protected emailTemplate: string;
/**
* The default HTML to output for a [rule] tag.
*/
protected ruleHtml;
/**
* How to trim the whitespace at the start of the input.
*/
protected preTrim: string;
/**
* How to trim the whitespace at the end of the input.
*/
protected postTrim: string;
/**
* Enable debugging mode
*/
public debug: boolean;
/**
* Maximum number of emoji that can be used in parse
*/
protected maxEmoji: number;
/**
* Encode HTML. POTENTIALLY DANGEROUS IF DISABLED. ONLY DISABLE IF YOU KNOW WHAT YOURE DOING.
*/
protected escapeContent: boolean;
/**
* The token stack is used to perform a document-tree walk
*/
protected stack: StackType[];
/**
* BBCodeLexer created when calling parse
*/
protected lexer: BBCodeLexer;
/**
* Whether to allow Escape Characters in parsing to prevent parsing specific tags or not
*/
protected allowEscape: boolean;
/**
* Initialize a new instance of the {@link BBCode} class.
*
* @param library The BBCode Library Class, It's possible to create your own via extending BBCodeLibrary
*/
public constructor(library?: BBCodeLibrary) {
this.defaults = library ? library : new BBCodeLibrary();
this.tagRules = this.defaults.defaultTagRules;
this.emoji = this.defaults.defaultEmoji;
this.emojiEnabled = true;
this.emojiRegex = false;
this.emojiDir = this.getDefaultEmojiDir();
this.emojiUrl = this.getDefaultEmojiURL();
this.wikiUrl = this.getDefaultWikiURL();
this.localImgDir = this.getDefaultLocalImgDir();
this.localImgUrl = this.getDefaultLocalImgURL();
this.ruleHtml = this.getDefaultRuleHTML();
this.preTrim = "";
this.postTrim = "";
this.rootClass = 'block';
this.lostStartTags = {};
this.startTags = {};
this.tagMarker = '[';
this.allowAmpersand = false;
this.currentClass = this.rootClass;
this.debug = false;
this.ignoreNewlines = false;
this.outputLimit = 0;
this.plainMode = false;
this.wasLimited = false;
this.limitTail = "...";
this.limitPrecision = 0.15;
this.detectURLs = false;
this.urlPattern = '<a href="{$url/h}">{$text/h}</a>';
this.urlTargetable = false;
this.urlTarget = false;
this.urlTemplate = '<a href="{$url/h}" class="bbcode_url"{$target/v}>{$content/v}</a>';
this.quoteTemplate = "\n" + '<div class="bbcode_quote">' + "\n" + '<div class="bbcode_quote_head">{$title/v}</div>' + "\n";
this.quoteTemplate += '<div class="bbcode_quote_body">{$content/v}</div>' + "\n</div>\n";
this.wikiUrlTemplate = '<a href="{$wikiURL/v}{$name/v}" class="bbcode_wiki">{$title/h}</a>';
this.emailTemplate = '<a href="mailto:{$email/h}" class="bbcode_email">{$content/v}</a>';
this.maxEmoji = -1;
this.escapeContent = true;
this.stack = [];
this.allowEscape = true;
}
//-----------------------------------------------------------------------------
// State control.
/**
* Controls how (non-newline) whitespace and newlines are treated when placed in proximity to this tag or to its end tag. For each setting, you use a simple pattern comprised of the following characters to describe what to remove:
* - s: Remove any non-newline whitespace found.
* - n: Remove a single newline, if one exists.
* - a: Remove as many spaces and newlines as are found.
*
* Common Examples:
* - s: Remove all non-newline whitespace
* - sn: Remove all non-newline whitespace, then a single newline if it exists.
* - ns: Remove a single newline if it exists, then all non-newline whitespace.
* - sns: Remove all non-newline whitespace, then a single newline if it exists, then any non-newline whitespace found past that newline.
*/
public setPreTrim(trim = "a") {
this.preTrim = trim;
return this;
}
/**
* Get the current preTrim value, see {@link setPreTrim}
*/
public getPreTrim() {
return this.preTrim;
}
/**
* Controls how (non-newline) whitespace and newlines are treated when placed in proximity to this tag or to its end tag. For each setting, you use a simple pattern comprised of the following characters to describe what to remove:
* - s: Remove any non-newline whitespace found.
* - n: Remove a single newline, if one exists.
* - a: Remove as many spaces and newlines as are found.
*
* Common Examples:
* - s: Remove all non-newline whitespace
* - sn: Remove all non-newline whitespace, then a single newline if it exists.
* - ns: Remove a single newline if it exists, then all non-newline whitespace.
* - sns: Remove all non-newline whitespace, then a single newline if it exists, then any non-newline whitespace found past that newline.
*/
public setPostTrim(trim = "a") {
this.postTrim = trim;
return this;
}
/**
* Get the current preTrim value, see {@link setPostTrim}
*/
public getPostTrim() {
return this.postTrim;
}
/**
* Sets {@link rootClass}; see {@link ClassType}
* @returns {this}
*/
public setRoot(rootclass: ClassType = 'block') {
this.rootClass = rootclass;
return this;
}
/**
* Sets {@link rootClass} to inline; see {@link ClassType}
* @returns {this}
*/
public setRootInline() {
this.rootClass = 'inline';
return this;
}
/**
* Sets {@link rootClass} to block; see {@link ClassType}
* @returns {this}
*/
public setRootBlock() {
this.rootClass = 'block';
return this;
}
/**
* Gets {@link rootClass}
*/
public getRoot() {
return this.rootClass;
}
/**
* Set Debug mode, if enabled it will log debug events.
* @default true
* @param enable Whether to enable debug mode or not
* @returns {this}
*/
public setDebug(enable: boolean = true) {
this.debug = enable;
if (this.debug)
Debugger.level = DebugLevel.all;
else
Debugger.level = DebugLevel.error;
return this;
}
/**
* Get if Debug mode is enabled
*/
public getDebug() {
return this.debug;
}
/**
* Set Log Level,
* 0 is all
* 1 is debug
* 2 is info
* 3 is warn (default)
* 4 is error
* 5 is none
* @param level {@link DebugLevel}
*/
public setLogLevel(level: DebugLevel) {
Debugger.level = level;
}
public getLogLevel() {
return Debugger.level;
}
/**
* Set if the parser should allow Ampersand or not.
* @param enable
*/
public setAllowAmpersand(enable = true) {
this.allowAmpersand = enable;
return this;
}
/**
* Get if Ampersand should be allowed or not.
*/
public getAllowAmpersand() {
return this.allowAmpersand;
}
/**
* Set the Tag Marker the parser should use, see {@link tagMarker}
* @param marker The marker
* @returns {this}
*/
public setTagMarker(marker = '[') {
this.tagMarker = marker;
return this;
}
/**
* Get the current Tag Marker
*/
public getTagMarker() {
return this.tagMarker;
}
/**
* Sets whether the parser should ignore newlines or not.
* @param ignore Whether to ignore newlines
* @returns {this}
*/
public setIgnoreNewlines(ignore = true) {
this.ignoreNewlines = ignore;
return this;
}
/**
* Get if newlines are ignored.
*/
public getIgnoreNewlines() {
return this.ignoreNewlines;
}
/**
* Set the maximum amount of output characters before the output gets cut off
* @param limit maximum characters
*/
public setLimit(limit = 0) {
this.outputLimit = limit;
return this;
}
/**
* Get the current maximum output limit.
*/
public getLimit() {
return this.outputLimit;
}
/**
* Set what gets appended to the end of a string when the string is too long.
* @param tail What to append
*/
public setLimitTail(tail = "...") {
this.limitTail = tail;
return this;
}
/**
* Get the current Limit Tail
*/
public getLimitTail() {
return this.limitTail;
}
/**
* Set how precise {@link BBCodeLexer.guessTextLength} should be
* @param prec Precision
*/
public setLimitPrecision(prec = 0.15) {
this.limitPrecision = prec;
return this;
}
/**
* Get how precise {@link BBCodeLexer.guessTextLength} should be
* @param prec Precision
*/
public getLimitPrecision() {
return this.limitPrecision;
}
/**
* If plain mode is enabled, it will only output the values as defined in the
* plain_start and plain_end in the Tag Library, see {@link TagRules}
* @default true
* @param enable Enable or Disable Plain Mode
* @returns {this}
*/
public setPlainMode(enable = true) {
this.plainMode = enable;
return this;
}
/**
* Get if plain mode is enabled
* @returns {boolean}
*/
public getPlainMode() {
return this.plainMode;
}
/**
* Sets if URL detection should be abled, if enabled
* it will automatically convert urls into <a> tags in html
* @default true
* @param enable If auto URL detection should be enabled
* @returns {this}
*/
public setDetectURLs(enable = true) {
this.detectURLs = enable;
return this;
}
/**
* Get if URL Detection is enabled
* @returns {boolean}
*/
public getDetectURLs() {
return this.detectURLs;
}
/**
* Sets the URL pattern for a URL, example:
* `<a href="{$url/h}" class="bbcode_url"{$target/v}>{$content/v}</a>`
* @param pattern The HTML pattern for a URL
* @returns {this}
*/
public setURLPattern(pattern) {
this.urlPattern = pattern;
return this;
}
/**
* Get the current URL Pattern
*/
public getURLPattern() {
return this.urlPattern;
}
/**
* If true, [url] tags can accept a target="..." parameter.
* @param enable
*/
public setURLTargetable(enable: boolean) {
this.urlTargetable = enable;
return this;
}
/**
* Whether [url] tags acan accept a target="..." parameter
*/
public getURLTargetable() {
return this.urlTargetable;
}
/**
* If non-false, [url] tags will use this target and no other.
* @param target
*/
public setURLTarget(target) {
this.urlTarget = target;
return this;
}
/**
* Get the current forced url target
*/
public getURLTarget() {
return this.urlTarget;
}
/**
* Set the template to use for URL tags
* @param template
* @returns {this}
*/
public setURLTemplate(template: string) {
this.urlTemplate = template;
return this;
}
/**
* Get the current URL Template
*/
public getURLTemplate() {
return this.urlTemplate;
}
/**
* Whether to allow BBCode to be escaped or not.
*/
public setAllowEscape(bool: boolean) {
this.allowEscape = bool;
return this;
}
/**
* Get if escape characters are allowed
*/
public getAllowEscape() {
return this.allowEscape;
}
/**
* Set the template to use for quote tags
* @param template
* @returns {this}
*/
public setQuoteTemplate(template: string) {
this.quoteTemplate = template;
return this;
}
/**
* Get the current template to use for quote tags
*/
public getQuoteTemplate() {
return this.quoteTemplate;
}
/**
* Set the the default template used when rendering wiki links.
* @param template
* @returns {this}
*/
public setWikiURLTemplate(template: string) {
this.wikiUrlTemplate = template;
return this;
}
/**
* Get the current wiki template
*/
public getWikiURLTemplate() {
return this.wikiUrlTemplate;
}
/**
* Set the template to use for emails
* @param template template html
*/
public setEmailTemplate(template: string) {
this.emailTemplate = template;
return this;
}
/**
* Get the current email template
*/
public getEmailTemplate() {
return this.emailTemplate;
}
/**
* Set whether content should be escaped or not. POTENTIALLY DANGEROUS IF DISABLED. ONLY DISABLE IF YOU KNOW WHAT YOURE DOING.
*
* @param escapeContent
* @return {this}
*/
public setEscapeContent(escapeContent: boolean) {
this.escapeContent = escapeContent;
return this;
}
/**
* Get the current value of escapeContent.
*
* @return {boolean}
*/
public getEscapeContent() {
return this.escapeContent;
}
//-----------------------------------------------------------------------------
// Rule-management: You can add your own custom tag rules, or use the defaults.
// These are basically getter/setter functions that exist for convenience.
/**
* Adds a rule to the BBCode parser
* @param name The name of the rule to add
* @param rule The actual rule to add, see {@link TagRules}
* @returns {this}
*/
public addRule(name: string, rule: TagRules) {
this.tagRules[name] = rule;
return this;
}
/**
* Removes a {@link TagRules} by name.
* @param name The name of the rule to remove
* @returns
*/
public removeRule(name: string) {
delete this.tagRules[name];
return this;
}
/**
* Get a {@link TagRules} by name, returns false if no rule found.
*/
public getRule(name: string) {
return this.tagRules[name] ? this.tagRules[name] : false;
}
/**
* Clears all {@link TagRules} from the parser, this is useful
* if you plan to replace all the rules with custom ones.
* @returns {this}
*/
public clearRules() {
this.tagRules = {};
return this;
}
/**
* Gets a rule from the default rules list
* @param name Rule to get from the defaults
* @returns
*/
public getDefaultRule(name: string) {
return this.defaults.defaultTagRules[name] ? this.defaults.defaultTagRules[name] : false;
}
/**
* Resets a rule by name from the default tag rules.
* @param name Rule to change to default
*/
public setDefaultRule(name: string) {
if (this.defaults.defaultTagRules[name]) {
this.addRule(name, this.defaults.defaultTagRules[name]);
} else {
this.removeRule(name);
}
}
/**
* Returns the list of Default Tag Rules.
*/
public getDefaultRules() {
return this.defaults.defaultTagRules;
}
/**
* Resets all tag rules to default.
*/
public setDefaultRules() {
this.tagRules = this.defaults.defaultTagRules;
return this;
}
//-----------------------------------------------------------------------------
// Handling for [[wiki]] and [[wiki|Wiki]] links and other replaced items.
// These are basically getter/setter functions that exist for convenience.
/**
* Get the wiki URL use for wiki tags and replacements
* @param url URL to use for wikis
* @returns {this}
*/
public setWikiURL(url: string) {
this.wikiUrl = url;
return this;
}
/**
* Get the current Wiki URL
*/
public getWikiURL() {
return this.wikiUrl;
}
/**
* Get the default wiki URL
*/
public getDefaultWikiURL() {
return '/?page=';
}
/**
* Set the directory path to local images
* @param path directory path
*/
public setLocalImgDir(path: string) {
this.localImgDir = path;
return this;
}
/**
* Get the current local image directory
*/
public getLocalImgDir() {
return this.localImgDir;
}
/**
* Get the default local image Directory
*/
public getDefaultLocalImgDir() {
return "img";
}
/**
* Set the URL path to use for local images
* @param path url path
* @returns {this}
*/
public setLocalImgURL(path: string) {
this.localImgUrl = path.replace(/\/+$/, '');
return this;
}
/**
* Get the current local img URL
*/
public getLocalImgURL() {
return this.localImgUrl;
}
/**
* Get the default local img URL
*/
public getDefaultLocalImgURL() {
return "img";
}
/**
* Sets the HTML to use when converting a rule tag
* @param html HTML for Rule tag
* @returns
*/
public setRuleHTML(html) {
this.ruleHtml = html;
return this;
}
/**
* Returns the current Rule HTML
*/
public getRuleHTML() {
return this.ruleHtml;
}
/**
* Gets the default Rule HTML
*/
public getDefaultRuleHTML() {
return "\n<hr class=\"bbcode_rule\" />\n";
}
//-----------------------------------------------------------------------------
// Emoji management. You can use the default emoji, or add your own.
// These are *mostly* getter/setter functions, but they also affect the
// caching of the emoji-processing rules.
/**
* Adds an emoji to the parser
* @param code Name for the Emoji
* @param image Image file
* @returns {this}
*/
public addEmoji(code: string, image: string) {
this.emoji[code] = image;
this.emojiRegex = false;
return this;
}
/**
* Removes an Emoji from the parser
* @param code Emoji Name
* @returns {this}
*/
public removeEmoji(code: string) {
delete this.emoji[code];
this.emojiRegex = false;
return this;
}
/**
* Get an Emoji from the defined emoji, returns false if nothing found.
* @param code Emoji Name
*/
public getEmoji(code: string) {
return this.emoji[code] ? this.emoji[code] : false;
}
/**
* Clears all emoji from the parser.
* @returns {this}
*/
public clearEmoji() {
this.emoji = {};
this.emojiRegex = false;
return this;
}
/**
* Get an Emoji from the Default Emoji List.
* @param code Emoji Name
*/
public getDefaultEmoji(code: string) {
return this.defaults.defaultEmoji[code] ? this.defaults.defaultEmoji[code] : false;
}
/**
* Reset an emoji from the defaultEmoji list.
* @param code Emoji Name
* @returns {this}
*/
public setDefaultEmoji(code: string) {
if (this.defaults.defaultEmoji[code]) {
this.emoji[code] = this.defaults.defaultEmoji[code];
}
this.emojiRegex = false;
return this;
}
/**
* Get the list of the default Emoji.
*/
public getDefaultEmojis() {
return this.defaults.defaultEmoji;
}
/**
* Reset all emoji back to default.
* @returns {this}
*/
public setDefaultEmojis() {
this.emoji = this.defaults.defaultEmoji;
this.emojiRegex = false;
return this;
}
/**
* Set the Emoji Directory
* @param path Emoji Name
* @returns {this}
*/
public setEmojiDir(path) {
this.emojiDir = path;
return this;
}
/**
* Get the current Emoji Directory
*/
public getEmojiDir() {
return this.emojiDir;
}
/**
* Get the default emoji directory
*/
public getDefaultEmojiDir() {
return "emoji";
}
/**
* The URL Path to the Emoji on your Website
* @param path URL Path
*/
public setEmojiURL(path) {
this.emojiUrl = path;
return this;
}
/**
* Get the current Emoji URL
*/
public getEmojiURL() {
return this.emojiUrl;
}
/**
* Get the default emoji URL
*/
public getDefaultEmojiURL() {
return "emoji";
}
/**
* Sets whether emoji should be enabled, when enabled emoji like ":)" will be turned
* into an HTML image.
* @default true
* @param enable Whether emoji should be enabled
* @returns {this}
*/
public setEnableEmoji(enable = true) {
this.emojiEnabled = enable;
return this;
}
/**
* Get if Emoji parsing is enabled.
*/
public getEnableEmoji(): boolean {
return this.emojiEnabled;
}
/**
* Set the maximum amount of emoji that can be parsed in a single string.
* @param count Maximum Emoji
* @returns
*/
public setMaxEmoji(count: number) {
this.maxEmoji = count;
if (this.maxEmoji < -1) {
this.maxEmoji = -1;
}
return this;
}
/**
* Get the Max Emoji amount.
*/
public getMaxEmoji(): number {
return this.maxEmoji;
}
//-----------------------------------------------------------------------------
// Emoji, URL, and HTML-conversion support routines.
/**
* Converts Windows, Unix, or Mac newlines to a <br>, and regularizes the
* output to just use Unix-style newlines to boot.
*/
public nl2br(string: string): string {
return string.replace(/\x0A|\x0D|\x0A\x0D|\x0D\x0A/g, "<br>\n");
}
/**
* This function comes from the html_entities module
* @param string The string to be decoded
*/
public unHTMLEncode(string: string): string {
return htmlDecode(string);
}
/**
* This takes an arbitrary string and makes it a wiki-safe string: It converts
* all characters to be within [a-zA-Z0-9'",.:_-] by converting everything else to
* _ characters, compacts multiple _ characters together, and trims initial and
* trailing _ characters. So, for example, [[Washington, D.C.]] would become
* "Washington_D.C+", safe to pass through a URL or anywhere else. All characters
* in the extended-character range (0x7F-0xFF) will be URL-encoded.
*/
public wikify(string: string): string {
if (!string) return string;
return encodeURIComponent(string.replace(/[!?;@#$%^&*<>=+`~\x00-\x20_-]+/g, " ").trim().replaceAll(" ", "_"));
}
/**
* Returns true if the given string is a valid URL.
*
* If {@link emailToo} is false, this checks for:
*
* ```
* http :// domain [:port] [/] [any single-line string]
* https :// domain [:port] [/] [any single-line string]
* ftp :// domain [:port] [/] [any single-line string]
* ```
*
* If {@link emailToo} is true (the default), this also allows the mailto protocol:
*
* ```
* mailto : name @ domain
* ```
*
* @param string The URL to validate.
* @param emailToo Whether or not a **mailto:** link is also valid.
* @return Returns **true** if {@link string} is a valid URL or **false** otherwise.
*/
public isValidURL(string: string, emailToo: boolean = true): boolean {
//string.match(/^[^:]+(?=:\/\/)/)[0]
// Validate using PHP's fast filter method.
if (filter_var(string, 'FILTER_VALIDATE_URL') !== false &&
['http', 'https', 'ftp'].includes(parse_url(string)["scheme"])) {
return true;
}
// Check for anything that does *not* have a colon in it before the first
// slash or question mark or #; that indicates a local file relative to us.
if (/^[^:]+([\\/\\\\?#][^\\r\\n]*)?$/.test(string)) {
return true;
}
// Match mail addresses.
if (emailToo && string.slice(0, 7) === "mailto:") {
return this.isValidEmail(string.slice(7));
}
return false;
}
/**
* Returns true if the given string is a valid e-mail address.
*
* This allows everything that RFC821 allows, including e-mail addresses that make no sense.
* @param string The email address to validate.
* @return Returns **true** if {@link string} is an email address or **false** otherwise.
*/
public isValidEmail(string: string): boolean {
const validator = new EmailAddressValidator();
return validator.check_email_address(string);
}
/**
* Escape HTML characters.
*
* This function is used to wrap around calls to htmlEncode() for
* plain text so that you can add your own text-evaluation code if you want.