dompurify 2.2.9 → 2.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -3
- package/dist/purify.cjs.js +54 -12
- package/dist/purify.cjs.js.map +1 -1
- package/dist/purify.es.js +54 -12
- package/dist/purify.es.js.map +1 -1
- package/dist/purify.js +54 -12
- package/dist/purify.js.map +1 -1
- package/dist/purify.min.js +2 -2
- package/dist/purify.min.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -6,11 +6,11 @@
|
|
|
6
6
|
|
|
7
7
|
DOMPurify is a DOM-only, super-fast, uber-tolerant XSS sanitizer for HTML, MathML and SVG.
|
|
8
8
|
|
|
9
|
-
It's also very simple to use and get started with. DOMPurify was [started in February 2014](https://github.com/cure53/DOMPurify/commit/a630922616927373485e0e787ab19e73e3691b2b) and, meanwhile, has reached version 2.
|
|
9
|
+
It's also very simple to use and get started with. DOMPurify was [started in February 2014](https://github.com/cure53/DOMPurify/commit/a630922616927373485e0e787ab19e73e3691b2b) and, meanwhile, has reached version 2.3.3.
|
|
10
10
|
|
|
11
11
|
DOMPurify is written in JavaScript and works in all modern browsers (Safari (10+), Opera (15+), Internet Explorer (10+), Edge, Firefox and Chrome - as well as almost anything else using Blink or WebKit). It doesn't break on MSIE6 or other legacy browsers. It either uses [a fall-back](#what-about-older-browsers-like-msie8) or simply does nothing.
|
|
12
12
|
|
|
13
|
-
Our automated tests cover [
|
|
13
|
+
Our automated tests cover [17 different browsers](https://github.com/cure53/DOMPurify/blob/main/test/karma.custom-launchers.config.js#L5) right now, more to come. We also cover Node.js v14.15.1, v15.4.0, running DOMPurify on [jsdom](https://github.com/tmpvar/jsdom). Older Node.js versions are known to work as well.
|
|
14
14
|
|
|
15
15
|
DOMPurify is written by security people who have vast background in web attacks and XSS. Fear not. For more details please also read about our [Security Goals & Threat Model](https://github.com/cure53/DOMPurify/wiki/Security-Goals-&-Threat-Model). Please, read it. Like, really.
|
|
16
16
|
|
|
@@ -246,6 +246,9 @@ var clean = DOMPurify.sanitize(dirty, {KEEP_CONTENT: false});
|
|
|
246
246
|
// glue elements like style, script or others to document.body and prevent unintuitive browser behavior in several edge-cases (default is false)
|
|
247
247
|
var clean = DOMPurify.sanitize(dirty, {FORCE_BODY: true});
|
|
248
248
|
|
|
249
|
+
// change the parser type so sanitized data is treated as XML and not as HTML, which is the default
|
|
250
|
+
var clean = DOMPurify.sanitize(dirty, {PARSER_MEDIA_TYPE: 'application/xhtml+xml'});
|
|
251
|
+
|
|
249
252
|
/**
|
|
250
253
|
* Influence where we sanitize
|
|
251
254
|
*/
|
|
@@ -337,7 +340,7 @@ Feature releases will not be announced to this list.
|
|
|
337
340
|
|
|
338
341
|
Many people helped and help DOMPurify become what it is and need to be acknowledged here!
|
|
339
342
|
|
|
340
|
-
[granlem 💸](https://twitter.com/MaximeVeit), [oreoshake 💸](https://github.com/oreoshake), [dcramer 💸](https://github.com/dcramer),[tdeekens ❤️](https://github.com/tdeekens), [peernohell ❤️](https://github.com/peernohell), [NateScarlet](https://github.com/NateScarlet), [neilj](https://github.com/neilj), [fhemberger](https://github.com/fhemberger), [Joris-van-der-Wel](https://github.com/Joris-van-der-Wel), [ydaniv](https://github.com/ydaniv), [terjanq](https://twitter.com/terjanq), [filedescriptor](https://github.com/filedescriptor), [ConradIrwin](https://github.com/ConradIrwin), [gibson042](https://github.com/gibson042), [choumx](https://github.com/choumx), [0xSobky](https://github.com/0xSobky), [styfle](https://github.com/styfle), [koto](https://github.com/koto), [tlau88](https://github.com/tlau88), [strugee](https://github.com/strugee), [oparoz](https://github.com/oparoz), [mathiasbynens](https://github.com/mathiasbynens), [edg2s](https://github.com/edg2s), [dnkolegov](https://github.com/dnkolegov), [dhardtke](https://github.com/dhardtke), [wirehead](https://github.com/wirehead), [thorn0](https://github.com/thorn0), [styu](https://github.com/styu), [mozfreddyb](https://github.com/mozfreddyb), [mikesamuel](https://github.com/mikesamuel), [jorangreef](https://github.com/jorangreef), [jimmyhchan](https://github.com/jimmyhchan), [jameydeorio](https://github.com/jameydeorio), [jameskraus](https://github.com/jameskraus), [hyderali](https://github.com/hyderali), [hansottowirtz](https://github.com/hansottowirtz), [hackvertor](https://github.com/hackvertor), [freddyb](https://github.com/freddyb), [flavorjones](https://github.com/flavorjones), [djfarrelly](https://github.com/djfarrelly), [devd](https://github.com/devd), [camerondunford](https://github.com/camerondunford), [buu700](https://github.com/buu700), [buildog](https://github.com/buildog), [alabiaga](https://github.com/alabiaga), [Vector919](https://github.com/Vector919), [Robbert](https://github.com/Robbert), [GreLI](https://github.com/GreLI), [FuzzySockets](https://github.com/FuzzySockets), [ArtemBernatskyy](https://github.com/ArtemBernatskyy), [@garethheyes](https://twitter.com/garethheyes), [@shafigullin](https://twitter.com/shafigullin), [@mmrupp](https://twitter.com/mmrupp), [@irsdl](https://twitter.com/irsdl),[ShikariSenpai](https://github.com/ShikariSenpai), [ansjdnakjdnajkd](https://github.com/ansjdnakjdnajkd), [@asutherland](https://twitter.com/asutherland), [@mathias](https://twitter.com/mathias), [@cgvwzq](https://twitter.com/cgvwzq), [@robbertatwork](https://twitter.com/robbertatwork), [@giutro](https://twitter.com/giutro), [@CmdEngineer_](https://twitter.com/CmdEngineer_), [@avr4mit](https://twitter.com/avr4mit) and especially [@securitymb ❤️](https://twitter.com/securitymb) & [@masatokinugawa ❤️](https://twitter.com/masatokinugawa)
|
|
343
|
+
[GrantGryczan 💸](https://github.com/GrantGryczan), [lowdefy 💸](https://twitter.com/lowdefy), [granlem 💸](https://twitter.com/MaximeVeit), [oreoshake 💸](https://github.com/oreoshake), [dcramer 💸](https://github.com/dcramer),[tdeekens ❤️](https://github.com/tdeekens), [peernohell ❤️](https://github.com/peernohell), [NateScarlet](https://github.com/NateScarlet), [neilj](https://github.com/neilj), [fhemberger](https://github.com/fhemberger), [Joris-van-der-Wel](https://github.com/Joris-van-der-Wel), [ydaniv](https://github.com/ydaniv), [terjanq](https://twitter.com/terjanq), [filedescriptor](https://github.com/filedescriptor), [ConradIrwin](https://github.com/ConradIrwin), [gibson042](https://github.com/gibson042), [choumx](https://github.com/choumx), [0xSobky](https://github.com/0xSobky), [styfle](https://github.com/styfle), [koto](https://github.com/koto), [tlau88](https://github.com/tlau88), [strugee](https://github.com/strugee), [oparoz](https://github.com/oparoz), [mathiasbynens](https://github.com/mathiasbynens), [edg2s](https://github.com/edg2s), [dnkolegov](https://github.com/dnkolegov), [dhardtke](https://github.com/dhardtke), [wirehead](https://github.com/wirehead), [thorn0](https://github.com/thorn0), [styu](https://github.com/styu), [mozfreddyb](https://github.com/mozfreddyb), [mikesamuel](https://github.com/mikesamuel), [jorangreef](https://github.com/jorangreef), [jimmyhchan](https://github.com/jimmyhchan), [jameydeorio](https://github.com/jameydeorio), [jameskraus](https://github.com/jameskraus), [hyderali](https://github.com/hyderali), [hansottowirtz](https://github.com/hansottowirtz), [hackvertor](https://github.com/hackvertor), [freddyb](https://github.com/freddyb), [flavorjones](https://github.com/flavorjones), [djfarrelly](https://github.com/djfarrelly), [devd](https://github.com/devd), [camerondunford](https://github.com/camerondunford), [buu700](https://github.com/buu700), [buildog](https://github.com/buildog), [alabiaga](https://github.com/alabiaga), [Vector919](https://github.com/Vector919), [Robbert](https://github.com/Robbert), [GreLI](https://github.com/GreLI), [FuzzySockets](https://github.com/FuzzySockets), [ArtemBernatskyy](https://github.com/ArtemBernatskyy), [@garethheyes](https://twitter.com/garethheyes), [@shafigullin](https://twitter.com/shafigullin), [@mmrupp](https://twitter.com/mmrupp), [@irsdl](https://twitter.com/irsdl),[ShikariSenpai](https://github.com/ShikariSenpai), [ansjdnakjdnajkd](https://github.com/ansjdnakjdnajkd), [@asutherland](https://twitter.com/asutherland), [@mathias](https://twitter.com/mathias), [@cgvwzq](https://twitter.com/cgvwzq), [@robbertatwork](https://twitter.com/robbertatwork), [@giutro](https://twitter.com/giutro), [@CmdEngineer_](https://twitter.com/CmdEngineer_), [@avr4mit](https://twitter.com/avr4mit) and especially [@securitymb ❤️](https://twitter.com/securitymb) & [@masatokinugawa ❤️](https://twitter.com/masatokinugawa)
|
|
341
344
|
|
|
342
345
|
## Testing powered by
|
|
343
346
|
<a target="_blank" href="https://www.browserstack.com/"><img width="200" src="https://www.browserstack.com/images/layout/browserstack-logo-600x315.png"></a><br>
|
package/dist/purify.cjs.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! @license DOMPurify | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/2.
|
|
1
|
+
/*! @license DOMPurify 2.3.3 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/2.3.3/LICENSE */
|
|
2
2
|
|
|
3
3
|
'use strict';
|
|
4
4
|
|
|
@@ -245,7 +245,7 @@ function createDOMPurify() {
|
|
|
245
245
|
* Version label, exposed for easier checks
|
|
246
246
|
* if DOMPurify is up to date or not
|
|
247
247
|
*/
|
|
248
|
-
DOMPurify.version = '2.
|
|
248
|
+
DOMPurify.version = '2.3.3';
|
|
249
249
|
|
|
250
250
|
/**
|
|
251
251
|
* Array of elements that DOMPurify removed during sanitation.
|
|
@@ -303,7 +303,8 @@ function createDOMPurify() {
|
|
|
303
303
|
var _document = document,
|
|
304
304
|
implementation = _document.implementation,
|
|
305
305
|
createNodeIterator = _document.createNodeIterator,
|
|
306
|
-
createDocumentFragment = _document.createDocumentFragment
|
|
306
|
+
createDocumentFragment = _document.createDocumentFragment,
|
|
307
|
+
getElementsByTagName = _document.getElementsByTagName;
|
|
307
308
|
var importNode = originalDocument.importNode;
|
|
308
309
|
|
|
309
310
|
|
|
@@ -410,7 +411,8 @@ function createDOMPurify() {
|
|
|
410
411
|
var USE_PROFILES = {};
|
|
411
412
|
|
|
412
413
|
/* Tags to ignore content of when KEEP_CONTENT is true */
|
|
413
|
-
var FORBID_CONTENTS =
|
|
414
|
+
var FORBID_CONTENTS = null;
|
|
415
|
+
var DEFAULT_FORBID_CONTENTS = addToSet({}, ['annotation-xml', 'audio', 'colgroup', 'desc', 'foreignobject', 'head', 'iframe', 'math', 'mi', 'mn', 'mo', 'ms', 'mtext', 'noembed', 'noframes', 'noscript', 'plaintext', 'script', 'style', 'svg', 'template', 'thead', 'title', 'video', 'xmp']);
|
|
414
416
|
|
|
415
417
|
/* Tags that are safe for data: URIs */
|
|
416
418
|
var DATA_URI_TAGS = null;
|
|
@@ -418,7 +420,7 @@ function createDOMPurify() {
|
|
|
418
420
|
|
|
419
421
|
/* Attributes safe for values like "javascript:" */
|
|
420
422
|
var URI_SAFE_ATTRIBUTES = null;
|
|
421
|
-
var DEFAULT_URI_SAFE_ATTRIBUTES = addToSet({}, ['alt', 'class', 'for', 'id', 'label', 'name', 'pattern', 'placeholder', 'summary', 'title', 'value', 'style', 'xmlns']);
|
|
423
|
+
var DEFAULT_URI_SAFE_ATTRIBUTES = addToSet({}, ['alt', 'class', 'for', 'id', 'label', 'name', 'pattern', 'placeholder', 'role', 'summary', 'title', 'value', 'style', 'xmlns']);
|
|
422
424
|
|
|
423
425
|
var MATHML_NAMESPACE = 'http://www.w3.org/1998/Math/MathML';
|
|
424
426
|
var SVG_NAMESPACE = 'http://www.w3.org/2000/svg';
|
|
@@ -427,6 +429,12 @@ function createDOMPurify() {
|
|
|
427
429
|
var NAMESPACE = HTML_NAMESPACE;
|
|
428
430
|
var IS_EMPTY_INPUT = false;
|
|
429
431
|
|
|
432
|
+
/* Parsing of strict XHTML documents */
|
|
433
|
+
var PARSER_MEDIA_TYPE = void 0;
|
|
434
|
+
var SUPPORTED_PARSER_MEDIA_TYPES = ['application/xhtml+xml', 'text/html'];
|
|
435
|
+
var DEFAULT_PARSER_MEDIA_TYPE = 'text/html';
|
|
436
|
+
var transformCaseFunc = void 0;
|
|
437
|
+
|
|
430
438
|
/* Keep a reference to config to pass to hooks */
|
|
431
439
|
var CONFIG = null;
|
|
432
440
|
|
|
@@ -459,6 +467,7 @@ function createDOMPurify() {
|
|
|
459
467
|
ALLOWED_ATTR = 'ALLOWED_ATTR' in cfg ? addToSet({}, cfg.ALLOWED_ATTR) : DEFAULT_ALLOWED_ATTR;
|
|
460
468
|
URI_SAFE_ATTRIBUTES = 'ADD_URI_SAFE_ATTR' in cfg ? addToSet(clone(DEFAULT_URI_SAFE_ATTRIBUTES), cfg.ADD_URI_SAFE_ATTR) : DEFAULT_URI_SAFE_ATTRIBUTES;
|
|
461
469
|
DATA_URI_TAGS = 'ADD_DATA_URI_TAGS' in cfg ? addToSet(clone(DEFAULT_DATA_URI_TAGS), cfg.ADD_DATA_URI_TAGS) : DEFAULT_DATA_URI_TAGS;
|
|
470
|
+
FORBID_CONTENTS = 'FORBID_CONTENTS' in cfg ? addToSet({}, cfg.FORBID_CONTENTS) : DEFAULT_FORBID_CONTENTS;
|
|
462
471
|
FORBID_TAGS = 'FORBID_TAGS' in cfg ? addToSet({}, cfg.FORBID_TAGS) : {};
|
|
463
472
|
FORBID_ATTR = 'FORBID_ATTR' in cfg ? addToSet({}, cfg.FORBID_ATTR) : {};
|
|
464
473
|
USE_PROFILES = 'USE_PROFILES' in cfg ? cfg.USE_PROFILES : false;
|
|
@@ -477,6 +486,16 @@ function createDOMPurify() {
|
|
|
477
486
|
IN_PLACE = cfg.IN_PLACE || false; // Default false
|
|
478
487
|
IS_ALLOWED_URI$$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI$$1;
|
|
479
488
|
NAMESPACE = cfg.NAMESPACE || HTML_NAMESPACE;
|
|
489
|
+
|
|
490
|
+
PARSER_MEDIA_TYPE =
|
|
491
|
+
// eslint-disable-next-line unicorn/prefer-includes
|
|
492
|
+
SUPPORTED_PARSER_MEDIA_TYPES.indexOf(cfg.PARSER_MEDIA_TYPE) === -1 ? PARSER_MEDIA_TYPE = DEFAULT_PARSER_MEDIA_TYPE : PARSER_MEDIA_TYPE = cfg.PARSER_MEDIA_TYPE;
|
|
493
|
+
|
|
494
|
+
// HTML tags and attributes are not case-sensitive, converting to lowercase. Keeping XHTML as is.
|
|
495
|
+
transformCaseFunc = PARSER_MEDIA_TYPE === 'application/xhtml+xml' ? function (x) {
|
|
496
|
+
return x;
|
|
497
|
+
} : stringToLowerCase;
|
|
498
|
+
|
|
480
499
|
if (SAFE_FOR_TEMPLATES) {
|
|
481
500
|
ALLOW_DATA_ATTR = false;
|
|
482
501
|
}
|
|
@@ -534,6 +553,14 @@ function createDOMPurify() {
|
|
|
534
553
|
addToSet(URI_SAFE_ATTRIBUTES, cfg.ADD_URI_SAFE_ATTR);
|
|
535
554
|
}
|
|
536
555
|
|
|
556
|
+
if (cfg.FORBID_CONTENTS) {
|
|
557
|
+
if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) {
|
|
558
|
+
FORBID_CONTENTS = clone(FORBID_CONTENTS);
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
addToSet(FORBID_CONTENTS, cfg.FORBID_CONTENTS);
|
|
562
|
+
}
|
|
563
|
+
|
|
537
564
|
/* Add #text in case KEEP_CONTENT is set to true */
|
|
538
565
|
if (KEEP_CONTENT) {
|
|
539
566
|
ALLOWED_TAGS['#text'] = true;
|
|
@@ -737,6 +764,11 @@ function createDOMPurify() {
|
|
|
737
764
|
leadingWhitespace = matches && matches[0];
|
|
738
765
|
}
|
|
739
766
|
|
|
767
|
+
if (PARSER_MEDIA_TYPE === 'application/xhtml+xml') {
|
|
768
|
+
// Root of XHTML doc must contain xmlns declaration (see https://www.w3.org/TR/xhtml1/normative.html#strict)
|
|
769
|
+
dirty = '<html xmlns="http://www.w3.org/1999/xhtml"><head></head><body>' + dirty + '</body></html>';
|
|
770
|
+
}
|
|
771
|
+
|
|
740
772
|
var dirtyPayload = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;
|
|
741
773
|
/*
|
|
742
774
|
* Use the DOMParser API by default, fallback later if needs be
|
|
@@ -744,7 +776,7 @@ function createDOMPurify() {
|
|
|
744
776
|
*/
|
|
745
777
|
if (NAMESPACE === HTML_NAMESPACE) {
|
|
746
778
|
try {
|
|
747
|
-
doc = new DOMParser().parseFromString(dirtyPayload,
|
|
779
|
+
doc = new DOMParser().parseFromString(dirtyPayload, PARSER_MEDIA_TYPE);
|
|
748
780
|
} catch (_) {}
|
|
749
781
|
}
|
|
750
782
|
|
|
@@ -765,6 +797,10 @@ function createDOMPurify() {
|
|
|
765
797
|
}
|
|
766
798
|
|
|
767
799
|
/* Work on whole document or just its body */
|
|
800
|
+
if (NAMESPACE === HTML_NAMESPACE) {
|
|
801
|
+
return getElementsByTagName.call(doc, WHOLE_DOCUMENT ? 'html' : 'body')[0];
|
|
802
|
+
}
|
|
803
|
+
|
|
768
804
|
return WHOLE_DOCUMENT ? doc.documentElement : body;
|
|
769
805
|
};
|
|
770
806
|
|
|
@@ -853,7 +889,7 @@ function createDOMPurify() {
|
|
|
853
889
|
}
|
|
854
890
|
|
|
855
891
|
/* Now let's check the element's type and name */
|
|
856
|
-
var tagName =
|
|
892
|
+
var tagName = transformCaseFunc(currentNode.nodeName);
|
|
857
893
|
|
|
858
894
|
/* Execute a hook if present */
|
|
859
895
|
_executeHook('uponSanitizeElement', currentNode, {
|
|
@@ -867,6 +903,12 @@ function createDOMPurify() {
|
|
|
867
903
|
return true;
|
|
868
904
|
}
|
|
869
905
|
|
|
906
|
+
/* Mitigate a problem with templates inside select */
|
|
907
|
+
if (tagName === 'select' && regExpTest(/<template/i, currentNode.innerHTML)) {
|
|
908
|
+
_forceRemove(currentNode);
|
|
909
|
+
return true;
|
|
910
|
+
}
|
|
911
|
+
|
|
870
912
|
/* Remove element if anything forbids its presence */
|
|
871
913
|
if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
|
|
872
914
|
/* Keep content except for bad-listed elements */
|
|
@@ -935,7 +977,7 @@ function createDOMPurify() {
|
|
|
935
977
|
(https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes)
|
|
936
978
|
XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804)
|
|
937
979
|
We don't need to check the value; it's always URI safe. */
|
|
938
|
-
if (ALLOW_DATA_ATTR && regExpTest(DATA_ATTR$$1, lcName)) ; else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR$$1, lcName)) ; else if (!ALLOWED_ATTR[lcName] || FORBID_ATTR[lcName]) {
|
|
980
|
+
if (ALLOW_DATA_ATTR && !FORBID_ATTR[lcName] && regExpTest(DATA_ATTR$$1, lcName)) ; else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR$$1, lcName)) ; else if (!ALLOWED_ATTR[lcName] || FORBID_ATTR[lcName]) {
|
|
939
981
|
return false;
|
|
940
982
|
|
|
941
983
|
/* Check value is safe. First, is attr inert? If so, is safe */
|
|
@@ -988,7 +1030,7 @@ function createDOMPurify() {
|
|
|
988
1030
|
namespaceURI = _attr.namespaceURI;
|
|
989
1031
|
|
|
990
1032
|
value = stringTrim(attr.value);
|
|
991
|
-
lcName =
|
|
1033
|
+
lcName = transformCaseFunc(name);
|
|
992
1034
|
|
|
993
1035
|
/* Execute a hook if present */
|
|
994
1036
|
hookEvent.attrName = lcName;
|
|
@@ -1023,7 +1065,7 @@ function createDOMPurify() {
|
|
|
1023
1065
|
}
|
|
1024
1066
|
|
|
1025
1067
|
/* Is `value` valid for this attribute? */
|
|
1026
|
-
var lcTag = currentNode.nodeName
|
|
1068
|
+
var lcTag = transformCaseFunc(currentNode.nodeName);
|
|
1027
1069
|
if (!_isValidAttribute(lcTag, lcName, value)) {
|
|
1028
1070
|
continue;
|
|
1029
1071
|
}
|
|
@@ -1286,8 +1328,8 @@ function createDOMPurify() {
|
|
|
1286
1328
|
_parseConfig({});
|
|
1287
1329
|
}
|
|
1288
1330
|
|
|
1289
|
-
var lcTag =
|
|
1290
|
-
var lcName =
|
|
1331
|
+
var lcTag = transformCaseFunc(tag);
|
|
1332
|
+
var lcName = transformCaseFunc(attr);
|
|
1291
1333
|
return _isValidAttribute(lcTag, lcName, value);
|
|
1292
1334
|
};
|
|
1293
1335
|
|