@oat-sa/tao-core-ui 1.58.1 → 1.58.2

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.
Files changed (233) hide show
  1. package/dist/actionbar.js +386 -395
  2. package/dist/adder.js +21 -19
  3. package/dist/animable/absorbable/absorbable.js +204 -213
  4. package/dist/animable/absorbable/css/absorb.css +1 -0
  5. package/dist/animable/absorbable/css/absorb.css.map +1 -1
  6. package/dist/animable/pulsable/pulsable.js +168 -177
  7. package/dist/autocomplete/css/autocomplete.css +1 -0
  8. package/dist/autocomplete/css/autocomplete.css.map +1 -1
  9. package/dist/autocomplete.js +68 -66
  10. package/dist/badge/badge.js +188 -197
  11. package/dist/badge/css/badge.css +1 -0
  12. package/dist/badge/css/badge.css.map +1 -1
  13. package/dist/breadcrumbs.js +275 -284
  14. package/dist/btngrouper.js +5 -5
  15. package/dist/bulkActionPopup.js +490 -495
  16. package/dist/button.js +283 -291
  17. package/dist/cascadingComboBox.js +249 -258
  18. package/dist/ckeditor/ckConfigurator.js +26 -19
  19. package/dist/ckeditor/dtdHandler.js +11 -9
  20. package/dist/class/selector.js +441 -450
  21. package/dist/component/resizable.js +1 -1
  22. package/dist/component/windowed.js +285 -294
  23. package/dist/component.js +419 -428
  24. package/dist/contextualPopup.js +417 -426
  25. package/dist/dashboard.js +300 -309
  26. package/dist/datalist.js +753 -762
  27. package/dist/datatable/filterStrategy/multiple.js +1 -1
  28. package/dist/datatable/filterStrategy/single.js +1 -1
  29. package/dist/datatable.js +1527 -1550
  30. package/dist/dateRange/dateRange.js +393 -402
  31. package/dist/datetime/picker.js +665 -672
  32. package/dist/deleter.js +368 -377
  33. package/dist/destination/selector.js +286 -295
  34. package/dist/dialog/alert.js +3 -3
  35. package/dist/dialog/confirm.js +1 -1
  36. package/dist/dialog/confirmDelete.js +216 -225
  37. package/dist/dialog.js +650 -654
  38. package/dist/disabler.js +8 -8
  39. package/dist/documentViewer/providers/pdfViewer/fallback/viewer.js +166 -175
  40. package/dist/documentViewer/providers/pdfViewer/pdfjs/findBar.js +518 -527
  41. package/dist/documentViewer/providers/pdfViewer/pdfjs/pageView.js +380 -389
  42. package/dist/documentViewer/providers/pdfViewer/pdfjs/searchEngine.js +539 -548
  43. package/dist/documentViewer/providers/pdfViewer/pdfjs/viewer.js +369 -378
  44. package/dist/documentViewer/providers/pdfViewer.js +184 -193
  45. package/dist/documentViewer.js +292 -301
  46. package/dist/dropdown.js +383 -392
  47. package/dist/durationer.js +5 -5
  48. package/dist/dynamicComponent.js +597 -598
  49. package/dist/feedback.js +356 -362
  50. package/dist/figure/FigureStateActive.js +117 -108
  51. package/dist/filesender.js +2 -2
  52. package/dist/filter.js +230 -239
  53. package/dist/form/dropdownForm.js +355 -357
  54. package/dist/form/form.js +919 -690
  55. package/dist/form/simpleForm.js +1 -1
  56. package/dist/form/validator/renderer.js +233 -235
  57. package/dist/form/validator/validator.js +257 -189
  58. package/dist/form/widget/definitions.js +1 -1
  59. package/dist/form/widget/providers/checkBox.js +254 -259
  60. package/dist/form/widget/providers/comboBox.js +187 -192
  61. package/dist/form/widget/providers/default.js +8 -9
  62. package/dist/form/widget/providers/hidden.js +170 -179
  63. package/dist/form/widget/providers/hiddenBox.js +262 -267
  64. package/dist/form/widget/providers/radioBox.js +216 -225
  65. package/dist/form/widget/providers/textArea.js +187 -196
  66. package/dist/form/widget/providers/textBox.js +2 -3
  67. package/dist/form/widget/widget.js +473 -475
  68. package/dist/formValidator/formValidator.js +1 -1
  69. package/dist/formValidator/highlighters/message.js +1 -1
  70. package/dist/generis/form/form.js +314 -323
  71. package/dist/generis/validator/validator.js +209 -218
  72. package/dist/generis/widget/checkBox/checkBox.js +218 -227
  73. package/dist/generis/widget/comboBox/comboBox.js +179 -188
  74. package/dist/generis/widget/hiddenBox/hiddenBox.js +220 -229
  75. package/dist/generis/widget/textBox/textBox.js +169 -178
  76. package/dist/generis/widget/widget.js +246 -255
  77. package/dist/groupedComboBox.js +222 -231
  78. package/dist/groupvalidator.js +2 -2
  79. package/dist/highlighter.js +967 -958
  80. package/dist/image/ImgStateActive/helper.js +7 -5
  81. package/dist/image/ImgStateActive/initHelper.js +49 -43
  82. package/dist/image/ImgStateActive/initMediaEditor.js +24 -20
  83. package/dist/image/ImgStateActive/mediaSizer.js +14 -12
  84. package/dist/image/ImgStateActive.js +72 -70
  85. package/dist/incrementer.js +6 -6
  86. package/dist/inplacer.js +6 -6
  87. package/dist/itemButtonList/css/item-button-list.css +1 -0
  88. package/dist/itemButtonList/css/item-button-list.css.map +1 -1
  89. package/dist/itemButtonList.js +439 -435
  90. package/dist/keyNavigation/navigableDomElement.js +51 -38
  91. package/dist/keyNavigation/navigator.js +85 -70
  92. package/dist/listbox.js +460 -469
  93. package/dist/liststyler.js +8 -8
  94. package/dist/loadingButton/loadingButton.js +209 -218
  95. package/dist/lock.js +476 -485
  96. package/dist/login/login.js +475 -484
  97. package/dist/maths/calculator/basicCalculator.js +235 -244
  98. package/dist/maths/calculator/calculatorComponent.js +3 -3
  99. package/dist/maths/calculator/core/board.js +772 -781
  100. package/dist/maths/calculator/core/expression.js +476 -485
  101. package/dist/maths/calculator/core/labels.js +228 -237
  102. package/dist/maths/calculator/core/tokenizer.js +1 -1
  103. package/dist/maths/calculator/core/tokens.js +163 -170
  104. package/dist/maths/calculator/plugins/keyboard/templateKeyboard/templateKeyboard.js +244 -253
  105. package/dist/maths/calculator/plugins/screen/simpleScreen/simpleScreen.js +279 -288
  106. package/dist/maths/calculator/scientificCalculator.js +327 -336
  107. package/dist/mediaEditor/mediaEditorComponent.js +238 -245
  108. package/dist/mediaEditor/plugins/mediaAlignment/helper.js +7 -7
  109. package/dist/mediaEditor/plugins/mediaAlignment/mediaAlignmentComponent.js +229 -235
  110. package/dist/mediaEditor/plugins/mediaDimension/mediaDimensionComponent.js +580 -589
  111. package/dist/mediaplayer/players/html5.js +666 -675
  112. package/dist/mediaplayer/players/youtube.js +419 -424
  113. package/dist/mediaplayer/support.js +11 -10
  114. package/dist/mediaplayer/utils/reminder.js +14 -13
  115. package/dist/mediaplayer/utils/timeObserver.js +10 -11
  116. package/dist/mediaplayer/youtubeManager.js +164 -145
  117. package/dist/mediaplayer.js +1565 -1520
  118. package/dist/mediasizer.js +669 -678
  119. package/dist/modal.js +10 -17
  120. package/dist/pageSizeSelector.js +219 -228
  121. package/dist/pagination/providers/pages.js +280 -289
  122. package/dist/pagination/providers/simple.js +192 -201
  123. package/dist/previewer.js +30 -30
  124. package/dist/progressbar.js +4 -4
  125. package/dist/report.js +347 -356
  126. package/dist/resource/filters.js +271 -280
  127. package/dist/resource/list.js +1264 -1273
  128. package/dist/resource/selector.js +865 -874
  129. package/dist/resource/tree.js +1483 -1492
  130. package/dist/resourcemgr/fileBrowser.js +564 -569
  131. package/dist/resourcemgr/filePreview.js +16 -16
  132. package/dist/resourcemgr/fileSelector.js +515 -524
  133. package/dist/resourcemgr/util/updatePermissions.js +2 -2
  134. package/dist/resourcemgr.js +306 -315
  135. package/dist/searchModal/advancedSearch.js +796 -767
  136. package/dist/searchModal.js +114 -91
  137. package/dist/switch/switch.js +298 -307
  138. package/dist/tabs.js +598 -575
  139. package/dist/taskQueue/status.js +312 -321
  140. package/dist/taskQueue/table.js +375 -384
  141. package/dist/taskQueue/taskQueueModel.js +488 -472
  142. package/dist/taskQueueButton/taskable.js +264 -273
  143. package/dist/taskQueueButton/treeButton.js +189 -198
  144. package/dist/themeLoader.js +24 -23
  145. package/dist/themes.js +1 -1
  146. package/dist/toggler.js +3 -3
  147. package/dist/tooltip.js +295 -304
  148. package/dist/transformer.js +2 -2
  149. package/dist/tristateCheckboxGroup.js +311 -320
  150. package/dist/uploader.js +687 -696
  151. package/dist/validator/Report.js +1 -1
  152. package/dist/validator/Validator.js +3 -3
  153. package/dist/validator/validators.js +9 -9
  154. package/dist/validator.js +240 -230
  155. package/dist/waitForMedia.js +1 -1
  156. package/package.json +3 -3
  157. package/src/animable/absorbable/css/absorb.css +1 -0
  158. package/src/animable/absorbable/css/absorb.css.map +1 -1
  159. package/src/autocomplete/css/autocomplete.css +1 -0
  160. package/src/autocomplete/css/autocomplete.css.map +1 -1
  161. package/src/badge/css/badge.css +1 -0
  162. package/src/badge/css/badge.css.map +1 -1
  163. package/src/ckeditor/ckConfigurator.js +4 -0
  164. package/src/itemButtonList/css/item-button-list.css +1 -0
  165. package/src/itemButtonList/css/item-button-list.css.map +1 -1
  166. package/src/.DS_Store +0 -0
  167. package/src/css/basic.css +0 -7826
  168. package/src/css/basic.css.map +0 -1
  169. package/src/css/ckeditor/skins/tao/css/dialog.css +0 -950
  170. package/src/css/ckeditor/skins/tao/css/dialog.css.map +0 -1
  171. package/src/css/ckeditor/skins/tao/css/editor.css +0 -1850
  172. package/src/css/ckeditor/skins/tao/css/editor.css.map +0 -1
  173. package/src/scss/.DS_Store +0 -0
  174. package/src/scss/basic.scss +0 -16
  175. package/src/scss/ckeditor/skins/tao/scss/dialog.scss +0 -763
  176. package/src/scss/ckeditor/skins/tao/scss/editor.scss +0 -111
  177. package/src/scss/ckeditor/skins/tao/scss/inc/_ck-icons.scss +0 -59
  178. package/src/scss/ckeditor/skins/tao/scss/inc/_colorpanel.scss +0 -118
  179. package/src/scss/ckeditor/skins/tao/scss/inc/_elementspath.scss +0 -69
  180. package/src/scss/ckeditor/skins/tao/scss/inc/_mainui.scss +0 -194
  181. package/src/scss/ckeditor/skins/tao/scss/inc/_menu.scss +0 -181
  182. package/src/scss/ckeditor/skins/tao/scss/inc/_panel.scss +0 -200
  183. package/src/scss/ckeditor/skins/tao/scss/inc/_presets.scss +0 -32
  184. package/src/scss/ckeditor/skins/tao/scss/inc/_reset.scss +0 -101
  185. package/src/scss/ckeditor/skins/tao/scss/inc/_richcombo.scss +0 -213
  186. package/src/scss/ckeditor/skins/tao/scss/inc/_tao.scss +0 -59
  187. package/src/scss/ckeditor/skins/tao/scss/inc/_toolbar.scss +0 -301
  188. package/src/scss/font/source-sans-pro/source-sans-pro-italic.eot +0 -0
  189. package/src/scss/font/source-sans-pro/source-sans-pro-italic.eot.b64 +0 -1
  190. package/src/scss/font/source-sans-pro/source-sans-pro-italic.woff +0 -0
  191. package/src/scss/font/source-sans-pro/source-sans-pro-italic.woff.b64 +0 -1
  192. package/src/scss/font/source-sans-pro/source-sans-pro-regular.eot +0 -0
  193. package/src/scss/font/source-sans-pro/source-sans-pro-regular.eot.b64 +0 -1
  194. package/src/scss/font/source-sans-pro/source-sans-pro-regular.woff +0 -0
  195. package/src/scss/font/source-sans-pro/source-sans-pro-regular.woff.b64 +0 -1
  196. package/src/scss/font/source-sans-pro/source-sans-pro-semibold-italic.eot +0 -0
  197. package/src/scss/font/source-sans-pro/source-sans-pro-semibold-italic.eot.b64 +0 -1
  198. package/src/scss/font/source-sans-pro/source-sans-pro-semibold-italic.woff +0 -0
  199. package/src/scss/font/source-sans-pro/source-sans-pro-semibold-italic.woff.b64 +0 -1
  200. package/src/scss/font/source-sans-pro/source-sans-pro-semibold.eot +0 -0
  201. package/src/scss/font/source-sans-pro/source-sans-pro-semibold.eot.b64 +0 -1
  202. package/src/scss/font/source-sans-pro/source-sans-pro-semibold.woff +0 -0
  203. package/src/scss/font/source-sans-pro/source-sans-pro-semibold.woff.b64 +0 -1
  204. package/src/scss/font/tao/tao.eot +0 -0
  205. package/src/scss/font/tao/tao.svg +0 -235
  206. package/src/scss/font/tao/tao.ttf +0 -0
  207. package/src/scss/font/tao/tao.woff +0 -0
  208. package/src/scss/inc/_base.scss +0 -496
  209. package/src/scss/inc/_bootstrap.scss +0 -6
  210. package/src/scss/inc/_buttons.scss +0 -114
  211. package/src/scss/inc/_colors.scss +0 -88
  212. package/src/scss/inc/_feedback.scss +0 -150
  213. package/src/scss/inc/_flex-grid.scss +0 -15
  214. package/src/scss/inc/_fonts.scss +0 -4
  215. package/src/scss/inc/_forms.scss +0 -827
  216. package/src/scss/inc/_functions.scss +0 -283
  217. package/src/scss/inc/_grid.scss +0 -66
  218. package/src/scss/inc/_jquery.nouislider.scss +0 -254
  219. package/src/scss/inc/_normalize.scss +0 -528
  220. package/src/scss/inc/_report.scss +0 -68
  221. package/src/scss/inc/_secondary-properties.scss +0 -89
  222. package/src/scss/inc/_select2.scss +0 -634
  223. package/src/scss/inc/_toolbars.scss +0 -155
  224. package/src/scss/inc/_tooltip.scss +0 -312
  225. package/src/scss/inc/_variables.scss +0 -21
  226. package/src/scss/inc/base/_highlight.scss +0 -5
  227. package/src/scss/inc/base/_list-style.scss +0 -59
  228. package/src/scss/inc/base/_svg.scss +0 -3
  229. package/src/scss/inc/base/_table.scss +0 -63
  230. package/src/scss/inc/fonts/_source-sans-pro.scss +0 -29
  231. package/src/scss/inc/fonts/_tao-icon-classes.scss +0 -226
  232. package/src/scss/inc/fonts/_tao-icon-def.scss +0 -12
  233. package/src/scss/inc/fonts/_tao-icon-vars.scss +0 -240
@@ -1,1895 +1,1886 @@
1
1
  define(['jquery', 'lodash', 'ui/component', 'ui/resource/selectable', 'ui/hider', 'handlebars', 'i18n', 'lib/dompurify/purify'], function ($$1, _, component, selectable, hider, Handlebars, __, DOMPurify) { 'use strict';
2
2
 
3
- $$1 = $$1 && Object.prototype.hasOwnProperty.call($$1, 'default') ? $$1['default'] : $$1;
4
- _ = _ && Object.prototype.hasOwnProperty.call(_, 'default') ? _['default'] : _;
5
- component = component && Object.prototype.hasOwnProperty.call(component, 'default') ? component['default'] : component;
6
- selectable = selectable && Object.prototype.hasOwnProperty.call(selectable, 'default') ? selectable['default'] : selectable;
7
- hider = hider && Object.prototype.hasOwnProperty.call(hider, 'default') ? hider['default'] : hider;
8
- Handlebars = Handlebars && Object.prototype.hasOwnProperty.call(Handlebars, 'default') ? Handlebars['default'] : Handlebars;
9
- __ = __ && Object.prototype.hasOwnProperty.call(__, 'default') ? __['default'] : __;
10
- DOMPurify = DOMPurify && Object.prototype.hasOwnProperty.call(DOMPurify, 'default') ? DOMPurify['default'] : DOMPurify;
11
-
3
+ $$1 = $$1 && Object.prototype.hasOwnProperty.call($$1, 'default') ? $$1['default'] : $$1;
4
+ _ = _ && Object.prototype.hasOwnProperty.call(_, 'default') ? _['default'] : _;
5
+ component = component && Object.prototype.hasOwnProperty.call(component, 'default') ? component['default'] : component;
6
+ selectable = selectable && Object.prototype.hasOwnProperty.call(selectable, 'default') ? selectable['default'] : selectable;
7
+ hider = hider && Object.prototype.hasOwnProperty.call(hider, 'default') ? hider['default'] : hider;
8
+ Handlebars = Handlebars && Object.prototype.hasOwnProperty.call(Handlebars, 'default') ? Handlebars['default'] : Handlebars;
9
+ __ = __ && Object.prototype.hasOwnProperty.call(__, 'default') ? __['default'] : __;
10
+ DOMPurify = DOMPurify && Object.prototype.hasOwnProperty.call(DOMPurify, 'default') ? DOMPurify['default'] : DOMPurify;
11
+
12
+ function _typeof(obj) {
13
+ "@babel/helpers - typeof";
14
+
15
+ return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) {
16
+ return typeof obj;
17
+ } : function (obj) {
18
+ return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
19
+ }, _typeof(obj);
20
+ }
21
+
22
+ function Helpers0 (hb) {
23
+ //register a i18n helper
24
+ hb.registerHelper('__', function (key) {
25
+ return __(key);
26
+ });
12
27
  /**
13
- * This program is free software; you can redistribute it and/or
14
- * modify it under the terms of the GNU General Public License
15
- * as published by the Free Software Foundation; under version 2
16
- * of the License (non-upgradable).
17
- *
18
- * This program is distributed in the hope that it will be useful,
19
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
20
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21
- * GNU General Public License for more details.
22
- *
23
- * You should have received a copy of the GNU General Public License
24
- * along with this program; if not, write to the Free Software
25
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26
- *
27
- * Copyright (c) 2013-2019 (original work) Open Assessment Technologies SA (under the project TAO-PRODUCT);
28
- *
28
+ * Register dompurify helper
29
29
  *
30
+ * https://github.com/cure53/DOMPurify
31
+ * with config SAFE_FOR_TEMPLATES: true
32
+ * to make output safe for template systems
30
33
  */
31
- function Helpers0 (hb) {
32
- //register a i18n helper
33
- hb.registerHelper('__', function (key) {
34
- return __(key);
35
- });
36
- /**
37
- * Register dompurify helper
38
- *
39
- * https://github.com/cure53/DOMPurify
40
- * with config SAFE_FOR_TEMPLATES: true
41
- * to make output safe for template systems
42
- */
43
34
 
44
- hb.registerHelper('dompurify', function (context) {
45
- return DOMPurify.sanitize(context);
46
- });
47
- /**
48
- * Register join helper
49
- *
50
- * Example :
51
- * var values = {a:v1, b:v2, c:v3};
52
- * Using {{{join attributes '=' ' ' '"'}}} will return : a="v1" b="v2" c="v3"
53
- * Using {{{join values null ' or ' '*'}}} will return : *v1* or *v2* or *v3*
54
- */
55
-
56
- hb.registerHelper('join', function (arr, keyValueGlue, fragmentGlue, wrapper) {
57
- var fragments = [];
58
- keyValueGlue = typeof keyValueGlue === 'string' ? keyValueGlue : undefined;
59
- fragmentGlue = typeof fragmentGlue === 'string' ? fragmentGlue : ' ';
60
- wrapper = typeof wrapper === 'string' ? wrapper : '"';
35
+ hb.registerHelper('dompurify', function (context) {
36
+ return DOMPurify.sanitize(context);
37
+ });
38
+ /**
39
+ * Register join helper
40
+ *
41
+ * Example :
42
+ * var values = {a:v1, b:v2, c:v3};
43
+ * Using {{{join attributes '=' ' ' '"'}}} will return : a="v1" b="v2" c="v3"
44
+ * Using {{{join values null ' or ' '*'}}} will return : *v1* or *v2* or *v3*
45
+ */
61
46
 
62
- _.forIn(arr, function (value, key) {
63
- var fragment = '';
47
+ hb.registerHelper('join', function (arr, keyValueGlue, fragmentGlue, wrapper) {
48
+ var fragments = [];
49
+ keyValueGlue = typeof keyValueGlue === 'string' ? keyValueGlue : undefined;
50
+ fragmentGlue = typeof fragmentGlue === 'string' ? fragmentGlue : ' ';
51
+ wrapper = typeof wrapper === 'string' ? wrapper : '"';
64
52
 
65
- if (value !== null || value !== undefined) {
66
- if (typeof value === 'boolean') {
67
- value = value ? 'true' : 'false';
68
- } else if (typeof value === 'object') {
69
- value = _.values(value).join(' ');
70
- }
71
- } else {
72
- value = '';
73
- }
53
+ _.forIn(arr, function (value, key) {
54
+ var fragment = '';
74
55
 
75
- if (keyValueGlue !== undefined) {
76
- fragment += key + keyValueGlue;
56
+ if (value !== null || value !== undefined) {
57
+ if (typeof value === 'boolean') {
58
+ value = value ? 'true' : 'false';
59
+ } else if (_typeof(value) === 'object') {
60
+ value = _.values(value).join(' ');
77
61
  }
78
-
79
- fragment += wrapper + value + wrapper;
80
- fragments.push(fragment);
81
- });
82
-
83
- return fragments.join(fragmentGlue);
84
- }); //register a classic "for loop" helper
85
- //it also adds a local variable "i" as the index in each iteration loop
86
-
87
- hb.registerHelper('for', function (startIndex, stopIndex, increment, options) {
88
- var ret = '';
89
- startIndex = parseInt(startIndex);
90
- stopIndex = parseInt(stopIndex);
91
- increment = parseInt(increment);
92
-
93
- for (var i = startIndex; i < stopIndex; i += increment) {
94
- ret += options.fn(_.extend({}, this, {
95
- i: i
96
- }));
97
- }
98
-
99
- return ret;
100
- });
101
- hb.registerHelper('equal', function (var1, var2, options) {
102
- if (var1 == var2) {
103
- return options.fn(this);
104
62
  } else {
105
- return options.inverse(this);
63
+ value = '';
106
64
  }
107
- }); // register a "get property" helper
108
- // it gets the named property from the provided context
109
-
110
- hb.registerHelper('property', function (name, context) {
111
- return context[name] || '';
112
- }); // register an 'includes' helper
113
- // it checks if value is in array
114
65
 
115
- hb.registerHelper('includes', function (haystack, needle, options) {
116
- if (_.contains(haystack, needle)) {
117
- return options.fn(this);
66
+ if (keyValueGlue !== undefined) {
67
+ fragment += key + keyValueGlue;
118
68
  }
69
+
70
+ fragment += wrapper + value + wrapper;
71
+ fragments.push(fragment);
119
72
  });
120
- }
121
73
 
122
- if (!Helpers0.__initialized) {
123
- Helpers0(Handlebars);
124
- Helpers0.__initialized = true;
125
- }
126
- var Template = Handlebars.template(function (Handlebars,depth0,helpers,partials,data) {
127
- this.compilerInfo = [4,'>= 1.0.0'];
128
- helpers = this.merge(helpers, Handlebars.helpers); data = data || {};
129
- var buffer = "", stack1, self=this;
130
-
131
- function program1(depth0,data) {
132
-
133
-
134
- return "multiple";
135
- }
74
+ return fragments.join(fragmentGlue);
75
+ }); //register a classic "for loop" helper
76
+ //it also adds a local variable "i" as the index in each iteration loop
136
77
 
137
- buffer += "<div class=\"resource-tree ";
138
- stack1 = helpers['if'].call(depth0, (depth0 && depth0.multiple), {hash:{},inverse:self.noop,fn:self.program(1, program1, data),data:data});
139
- if(stack1 || stack1 === 0) { buffer += stack1; }
140
- buffer += "\">\n <ul></ul>\n</div>\n\n";
141
- return buffer;
142
- });
143
- function treeTpl(data, options, asString) {
144
- var html = Template(data, options);
145
- return (asString || true) ? html : $(html);
146
- }
78
+ hb.registerHelper('for', function (startIndex, stopIndex, increment, options) {
79
+ var ret = '';
80
+ startIndex = parseInt(startIndex);
81
+ stopIndex = parseInt(stopIndex);
82
+ increment = parseInt(increment);
147
83
 
148
- if (!Helpers0.__initialized) {
149
- Helpers0(Handlebars);
150
- Helpers0.__initialized = true;
151
- }
152
- var Template$1 = Handlebars.template(function (Handlebars,depth0,helpers,partials,data) {
153
- this.compilerInfo = [4,'>= 1.0.0'];
154
- helpers = this.merge(helpers, Handlebars.helpers); data = data || {};
155
- var buffer = "", stack1, helper, options, functionType="function", escapeExpression=this.escapeExpression, self=this, helperMissing=helpers.helperMissing;
156
-
157
- function program1(depth0,data) {
158
-
159
- var buffer = "", stack1, helper, options;
160
- buffer += "\n<li data-uri=\"";
161
- if (helper = helpers.uri) { stack1 = helper.call(depth0, {hash:{},data:data}); }
162
- else { helper = (depth0 && depth0.uri); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
163
- buffer += escapeExpression(stack1)
164
- + "\" class=\"class";
165
- stack1 = helpers['if'].call(depth0, (depth0 && depth0.selectable), {hash:{},inverse:self.noop,fn:self.program(2, program2, data),data:data});
166
- if(stack1 || stack1 === 0) { buffer += stack1; }
167
- buffer += " ";
168
- if (helper = helpers.state) { stack1 = helper.call(depth0, {hash:{},data:data}); }
169
- else { helper = (depth0 && depth0.state); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
170
- buffer += escapeExpression(stack1)
171
- + "\" data-count=\"";
172
- if (helper = helpers.count) { stack1 = helper.call(depth0, {hash:{},data:data}); }
173
- else { helper = (depth0 && depth0.count); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
174
- buffer += escapeExpression(stack1)
175
- + "\" ";
176
- stack1 = helpers['if'].call(depth0, (depth0 && depth0.accessMode), {hash:{},inverse:self.noop,fn:self.program(4, program4, data),data:data});
177
- if(stack1 || stack1 === 0) { buffer += stack1; }
178
- buffer += ">\n <a href=\"#\" title=\"";
179
- if (helper = helpers.label) { stack1 = helper.call(depth0, {hash:{},data:data}); }
180
- else { helper = (depth0 && depth0.label); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
181
- if(stack1 || stack1 === 0) { buffer += stack1; }
182
- buffer += "\">\n <span class=\"class-toggler clickable\" tabindex=\"0\"></span>\n <span class=\"icon-folder\"></span>\n ";
183
- if (helper = helpers.label) { stack1 = helper.call(depth0, {hash:{},data:data}); }
184
- else { helper = (depth0 && depth0.label); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
185
- if(stack1 || stack1 === 0) { buffer += stack1; }
186
- buffer += "\n <span class=\"selector clickable\" tabindex=\"0\"></span>\n </a>\n <ul>\n ";
187
- stack1 = helpers['if'].call(depth0, (depth0 && depth0.childList), {hash:{},inverse:self.noop,fn:self.program(6, program6, data),data:data});
188
- if(stack1 || stack1 === 0) { buffer += stack1; }
189
- buffer += "\n </ul>\n <div class=\"more hidden\">\n <a href=\"#\" class=\"btn-info small\"><span class=\"icon-download\"></span> "
190
- + escapeExpression((helper = helpers.__ || (depth0 && depth0.__),options={hash:{},data:data},helper ? helper.call(depth0, "Load more", options) : helperMissing.call(depth0, "__", "Load more", options)))
191
- + "</a>\n </div>\n</li>\n";
192
- return buffer;
193
- }
194
- function program2(depth0,data) {
195
-
196
-
197
- return " selectable";
84
+ for (var i = startIndex; i < stopIndex; i += increment) {
85
+ ret += options.fn(_.extend({}, this, {
86
+ i: i
87
+ }));
198
88
  }
199
89
 
200
- function program4(depth0,data) {
201
-
202
- var buffer = "", stack1, helper;
203
- buffer += "data-access=\"";
204
- if (helper = helpers.accessMode) { stack1 = helper.call(depth0, {hash:{},data:data}); }
205
- else { helper = (depth0 && depth0.accessMode); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
206
- buffer += escapeExpression(stack1)
207
- + "\"";
208
- return buffer;
90
+ return ret;
91
+ });
92
+ hb.registerHelper('equal', function (var1, var2, options) {
93
+ if (var1 == var2) {
94
+ return options.fn(this);
95
+ } else {
96
+ return options.inverse(this);
209
97
  }
98
+ }); // register a "get property" helper
99
+ // it gets the named property from the provided context
210
100
 
211
- function program6(depth0,data) {
212
-
213
- var buffer = "", stack1, helper;
214
- buffer += "\n ";
215
- if (helper = helpers.childList) { stack1 = helper.call(depth0, {hash:{},data:data}); }
216
- else { helper = (depth0 && depth0.childList); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
217
- if(stack1 || stack1 === 0) { buffer += stack1; }
218
- buffer += "\n ";
219
- return buffer;
220
- }
101
+ hb.registerHelper('property', function (name, context) {
102
+ return context[name] || '';
103
+ }); // register an 'includes' helper
104
+ // it checks if value is in array
221
105
 
222
- function program8(depth0,data) {
223
-
224
- var buffer = "", stack1, helper;
225
- buffer += "\n<li data-uri=\"";
226
- if (helper = helpers.uri) { stack1 = helper.call(depth0, {hash:{},data:data}); }
227
- else { helper = (depth0 && depth0.uri); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
228
- buffer += escapeExpression(stack1)
229
- + "\" class=\"instance";
230
- stack1 = helpers['if'].call(depth0, (depth0 && depth0.selectable), {hash:{},inverse:self.noop,fn:self.program(2, program2, data),data:data});
231
- if(stack1 || stack1 === 0) { buffer += stack1; }
232
- buffer += " ";
233
- if (helper = helpers.state) { stack1 = helper.call(depth0, {hash:{},data:data}); }
234
- else { helper = (depth0 && depth0.state); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
235
- buffer += escapeExpression(stack1)
236
- + "\" ";
237
- stack1 = helpers['if'].call(depth0, (depth0 && depth0.accessMode), {hash:{},inverse:self.noop,fn:self.program(4, program4, data),data:data});
238
- if(stack1 || stack1 === 0) { buffer += stack1; }
239
- buffer += ">\n <a href=\"#\" title=\"";
240
- if (helper = helpers.label) { stack1 = helper.call(depth0, {hash:{},data:data}); }
241
- else { helper = (depth0 && depth0.label); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
242
- if(stack1 || stack1 === 0) { buffer += stack1; }
243
- buffer += "\">\n <span class=\"icon-";
244
- if (helper = helpers.icon) { stack1 = helper.call(depth0, {hash:{},data:data}); }
245
- else { helper = (depth0 && depth0.icon); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
246
- buffer += escapeExpression(stack1)
247
- + "\"></span>\n ";
248
- if (helper = helpers.label) { stack1 = helper.call(depth0, {hash:{},data:data}); }
249
- else { helper = (depth0 && depth0.label); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
250
- if(stack1 || stack1 === 0) { buffer += stack1; }
251
- buffer += "\n <span class=\"selector clickable\" tabindex=\"0\"></span>\n </a>\n</li>\n";
252
- return buffer;
106
+ hb.registerHelper('includes', function (haystack, needle, options) {
107
+ if (_.contains(haystack, needle)) {
108
+ return options.fn(this);
253
109
  }
110
+ });
111
+ }
112
+
113
+ if (!Helpers0.__initialized) {
114
+ Helpers0(Handlebars);
115
+ Helpers0.__initialized = true;
116
+ }
117
+ var Template = Handlebars.template(function (Handlebars,depth0,helpers,partials,data) {
118
+ this.compilerInfo = [4,'>= 1.0.0'];
119
+ helpers = this.merge(helpers, Handlebars.helpers); data = data || {};
120
+ var buffer = "", stack1, self=this;
121
+
122
+ function program1(depth0,data) {
123
+
124
+
125
+ return "multiple";
126
+ }
254
127
 
255
- stack1 = (helper = helpers.equal || (depth0 && depth0.equal),options={hash:{},inverse:self.noop,fn:self.program(1, program1, data),data:data},helper ? helper.call(depth0, (depth0 && depth0.type), "class", options) : helperMissing.call(depth0, "equal", (depth0 && depth0.type), "class", options));
256
- if(stack1 || stack1 === 0) { buffer += stack1; }
257
- buffer += "\n\n";
258
- stack1 = (helper = helpers.equal || (depth0 && depth0.equal),options={hash:{},inverse:self.noop,fn:self.program(8, program8, data),data:data},helper ? helper.call(depth0, (depth0 && depth0.type), "instance", options) : helperMissing.call(depth0, "equal", (depth0 && depth0.type), "instance", options));
259
- if(stack1 || stack1 === 0) { buffer += stack1; }
260
- buffer += "\n\n\n";
261
- return buffer;
262
- });
263
- function treeNodeTpl(data, options, asString) {
264
- var html = Template$1(data, options);
265
- return (asString || true) ? html : $(html);
128
+ buffer += "<div class=\"resource-tree ";
129
+ stack1 = helpers['if'].call(depth0, (depth0 && depth0.multiple), {hash:{},inverse:self.noop,fn:self.program(1, program1, data),data:data});
130
+ if(stack1 || stack1 === 0) { buffer += stack1; }
131
+ buffer += "\">\n <ul></ul>\n</div>\n\n";
132
+ return buffer;
133
+ });
134
+ function treeTpl(data, options, asString) {
135
+ var html = Template(data, options);
136
+ return (asString || true) ? html : $(html);
137
+ }
138
+
139
+ if (!Helpers0.__initialized) {
140
+ Helpers0(Handlebars);
141
+ Helpers0.__initialized = true;
142
+ }
143
+ var Template$1 = Handlebars.template(function (Handlebars,depth0,helpers,partials,data) {
144
+ this.compilerInfo = [4,'>= 1.0.0'];
145
+ helpers = this.merge(helpers, Handlebars.helpers); data = data || {};
146
+ var buffer = "", stack1, helper, options, functionType="function", escapeExpression=this.escapeExpression, self=this, helperMissing=helpers.helperMissing;
147
+
148
+ function program1(depth0,data) {
149
+
150
+ var buffer = "", stack1, helper, options;
151
+ buffer += "\n<li data-uri=\"";
152
+ if (helper = helpers.uri) { stack1 = helper.call(depth0, {hash:{},data:data}); }
153
+ else { helper = (depth0 && depth0.uri); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
154
+ buffer += escapeExpression(stack1)
155
+ + "\" class=\"class";
156
+ stack1 = helpers['if'].call(depth0, (depth0 && depth0.selectable), {hash:{},inverse:self.noop,fn:self.program(2, program2, data),data:data});
157
+ if(stack1 || stack1 === 0) { buffer += stack1; }
158
+ buffer += " ";
159
+ if (helper = helpers.state) { stack1 = helper.call(depth0, {hash:{},data:data}); }
160
+ else { helper = (depth0 && depth0.state); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
161
+ buffer += escapeExpression(stack1)
162
+ + "\" data-count=\"";
163
+ if (helper = helpers.count) { stack1 = helper.call(depth0, {hash:{},data:data}); }
164
+ else { helper = (depth0 && depth0.count); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
165
+ buffer += escapeExpression(stack1)
166
+ + "\" ";
167
+ stack1 = helpers['if'].call(depth0, (depth0 && depth0.accessMode), {hash:{},inverse:self.noop,fn:self.program(4, program4, data),data:data});
168
+ if(stack1 || stack1 === 0) { buffer += stack1; }
169
+ buffer += ">\n <a href=\"#\" title=\"";
170
+ if (helper = helpers.label) { stack1 = helper.call(depth0, {hash:{},data:data}); }
171
+ else { helper = (depth0 && depth0.label); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
172
+ if(stack1 || stack1 === 0) { buffer += stack1; }
173
+ buffer += "\">\n <span class=\"class-toggler clickable\" tabindex=\"0\"></span>\n <span class=\"icon-folder\"></span>\n ";
174
+ if (helper = helpers.label) { stack1 = helper.call(depth0, {hash:{},data:data}); }
175
+ else { helper = (depth0 && depth0.label); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
176
+ if(stack1 || stack1 === 0) { buffer += stack1; }
177
+ buffer += "\n <span class=\"selector clickable\" tabindex=\"0\"></span>\n </a>\n <ul>\n ";
178
+ stack1 = helpers['if'].call(depth0, (depth0 && depth0.childList), {hash:{},inverse:self.noop,fn:self.program(6, program6, data),data:data});
179
+ if(stack1 || stack1 === 0) { buffer += stack1; }
180
+ buffer += "\n </ul>\n <div class=\"more hidden\">\n <a href=\"#\" class=\"btn-info small\"><span class=\"icon-download\"></span> "
181
+ + escapeExpression((helper = helpers.__ || (depth0 && depth0.__),options={hash:{},data:data},helper ? helper.call(depth0, "Load more", options) : helperMissing.call(depth0, "__", "Load more", options)))
182
+ + "</a>\n </div>\n</li>\n";
183
+ return buffer;
184
+ }
185
+ function program2(depth0,data) {
186
+
187
+
188
+ return " selectable";
266
189
  }
267
190
 
268
- var freeze$1 = Object.freeze || function (x) {
269
- return x;
270
- };
191
+ function program4(depth0,data) {
192
+
193
+ var buffer = "", stack1, helper;
194
+ buffer += "data-access=\"";
195
+ if (helper = helpers.accessMode) { stack1 = helper.call(depth0, {hash:{},data:data}); }
196
+ else { helper = (depth0 && depth0.accessMode); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
197
+ buffer += escapeExpression(stack1)
198
+ + "\"";
199
+ return buffer;
200
+ }
271
201
 
272
- var html = freeze$1(['a', 'abbr', 'acronym', 'address', 'area', 'article', 'aside', 'audio', 'b', 'bdi', 'bdo', 'big', 'blink', 'blockquote', 'body', 'br', 'button', 'canvas', 'caption', 'center', 'cite', 'code', 'col', 'colgroup', 'content', 'data', 'datalist', 'dd', 'decorator', 'del', 'details', 'dfn', 'dir', 'div', 'dl', 'dt', 'element', 'em', 'fieldset', 'figcaption', 'figure', 'font', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr', 'html', 'i', 'img', 'input', 'ins', 'kbd', 'label', 'legend', 'li', 'main', 'map', 'mark', 'marquee', 'menu', 'menuitem', 'meter', 'nav', 'nobr', 'ol', 'optgroup', 'option', 'output', 'p', 'pre', 'progress', 'q', 'rp', 'rt', 'ruby', 's', 'samp', 'section', 'select', 'shadow', 'small', 'source', 'spacer', 'span', 'strike', 'strong', 'style', 'sub', 'summary', 'sup', 'table', 'tbody', 'td', 'template', 'textarea', 'tfoot', 'th', 'thead', 'time', 'tr', 'track', 'tt', 'u', 'ul', 'var', 'video', 'wbr']); // SVG
202
+ function program6(depth0,data) {
203
+
204
+ var buffer = "", stack1, helper;
205
+ buffer += "\n ";
206
+ if (helper = helpers.childList) { stack1 = helper.call(depth0, {hash:{},data:data}); }
207
+ else { helper = (depth0 && depth0.childList); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
208
+ if(stack1 || stack1 === 0) { buffer += stack1; }
209
+ buffer += "\n ";
210
+ return buffer;
211
+ }
273
212
 
274
- var svg = freeze$1(['svg', 'a', 'altglyph', 'altglyphdef', 'altglyphitem', 'animatecolor', 'animatemotion', 'animatetransform', 'audio', 'canvas', 'circle', 'clippath', 'defs', 'desc', 'ellipse', 'filter', 'font', 'g', 'glyph', 'glyphref', 'hkern', 'image', 'line', 'lineargradient', 'marker', 'mask', 'metadata', 'mpath', 'path', 'pattern', 'polygon', 'polyline', 'radialgradient', 'rect', 'stop', 'style', 'switch', 'symbol', 'text', 'textpath', 'title', 'tref', 'tspan', 'video', 'view', 'vkern']);
275
- var svgFilters = freeze$1(['feBlend', 'feColorMatrix', 'feComponentTransfer', 'feComposite', 'feConvolveMatrix', 'feDiffuseLighting', 'feDisplacementMap', 'feDistantLight', 'feFlood', 'feFuncA', 'feFuncB', 'feFuncG', 'feFuncR', 'feGaussianBlur', 'feMerge', 'feMergeNode', 'feMorphology', 'feOffset', 'fePointLight', 'feSpecularLighting', 'feSpotLight', 'feTile', 'feTurbulence']);
276
- var mathMl = freeze$1(['math', 'menclose', 'merror', 'mfenced', 'mfrac', 'mglyph', 'mi', 'mlabeledtr', 'mmultiscripts', 'mn', 'mo', 'mover', 'mpadded', 'mphantom', 'mroot', 'mrow', 'ms', 'mspace', 'msqrt', 'mstyle', 'msub', 'msup', 'msubsup', 'mtable', 'mtd', 'mtext', 'mtr', 'munder', 'munderover']);
277
- var text = freeze$1(['#text']);
213
+ function program8(depth0,data) {
214
+
215
+ var buffer = "", stack1, helper;
216
+ buffer += "\n<li data-uri=\"";
217
+ if (helper = helpers.uri) { stack1 = helper.call(depth0, {hash:{},data:data}); }
218
+ else { helper = (depth0 && depth0.uri); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
219
+ buffer += escapeExpression(stack1)
220
+ + "\" class=\"instance";
221
+ stack1 = helpers['if'].call(depth0, (depth0 && depth0.selectable), {hash:{},inverse:self.noop,fn:self.program(2, program2, data),data:data});
222
+ if(stack1 || stack1 === 0) { buffer += stack1; }
223
+ buffer += " ";
224
+ if (helper = helpers.state) { stack1 = helper.call(depth0, {hash:{},data:data}); }
225
+ else { helper = (depth0 && depth0.state); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
226
+ buffer += escapeExpression(stack1)
227
+ + "\" ";
228
+ stack1 = helpers['if'].call(depth0, (depth0 && depth0.accessMode), {hash:{},inverse:self.noop,fn:self.program(4, program4, data),data:data});
229
+ if(stack1 || stack1 === 0) { buffer += stack1; }
230
+ buffer += ">\n <a href=\"#\" title=\"";
231
+ if (helper = helpers.label) { stack1 = helper.call(depth0, {hash:{},data:data}); }
232
+ else { helper = (depth0 && depth0.label); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
233
+ if(stack1 || stack1 === 0) { buffer += stack1; }
234
+ buffer += "\">\n <span class=\"icon-";
235
+ if (helper = helpers.icon) { stack1 = helper.call(depth0, {hash:{},data:data}); }
236
+ else { helper = (depth0 && depth0.icon); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
237
+ buffer += escapeExpression(stack1)
238
+ + "\"></span>\n ";
239
+ if (helper = helpers.label) { stack1 = helper.call(depth0, {hash:{},data:data}); }
240
+ else { helper = (depth0 && depth0.label); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
241
+ if(stack1 || stack1 === 0) { buffer += stack1; }
242
+ buffer += "\n <span class=\"selector clickable\" tabindex=\"0\"></span>\n </a>\n</li>\n";
243
+ return buffer;
244
+ }
278
245
 
279
- var freeze$2 = Object.freeze || function (x) {
280
- return x;
246
+ stack1 = (helper = helpers.equal || (depth0 && depth0.equal),options={hash:{},inverse:self.noop,fn:self.program(1, program1, data),data:data},helper ? helper.call(depth0, (depth0 && depth0.type), "class", options) : helperMissing.call(depth0, "equal", (depth0 && depth0.type), "class", options));
247
+ if(stack1 || stack1 === 0) { buffer += stack1; }
248
+ buffer += "\n\n";
249
+ stack1 = (helper = helpers.equal || (depth0 && depth0.equal),options={hash:{},inverse:self.noop,fn:self.program(8, program8, data),data:data},helper ? helper.call(depth0, (depth0 && depth0.type), "instance", options) : helperMissing.call(depth0, "equal", (depth0 && depth0.type), "instance", options));
250
+ if(stack1 || stack1 === 0) { buffer += stack1; }
251
+ buffer += "\n\n\n";
252
+ return buffer;
253
+ });
254
+ function treeNodeTpl(data, options, asString) {
255
+ var html = Template$1(data, options);
256
+ return (asString || true) ? html : $(html);
257
+ }
258
+
259
+ var freeze$1 = Object.freeze || function (x) {
260
+ return x;
261
+ };
262
+
263
+ var html = freeze$1(['a', 'abbr', 'acronym', 'address', 'area', 'article', 'aside', 'audio', 'b', 'bdi', 'bdo', 'big', 'blink', 'blockquote', 'body', 'br', 'button', 'canvas', 'caption', 'center', 'cite', 'code', 'col', 'colgroup', 'content', 'data', 'datalist', 'dd', 'decorator', 'del', 'details', 'dfn', 'dir', 'div', 'dl', 'dt', 'element', 'em', 'fieldset', 'figcaption', 'figure', 'font', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr', 'html', 'i', 'img', 'input', 'ins', 'kbd', 'label', 'legend', 'li', 'main', 'map', 'mark', 'marquee', 'menu', 'menuitem', 'meter', 'nav', 'nobr', 'ol', 'optgroup', 'option', 'output', 'p', 'pre', 'progress', 'q', 'rp', 'rt', 'ruby', 's', 'samp', 'section', 'select', 'shadow', 'small', 'source', 'spacer', 'span', 'strike', 'strong', 'style', 'sub', 'summary', 'sup', 'table', 'tbody', 'td', 'template', 'textarea', 'tfoot', 'th', 'thead', 'time', 'tr', 'track', 'tt', 'u', 'ul', 'var', 'video', 'wbr']); // SVG
264
+
265
+ var svg = freeze$1(['svg', 'a', 'altglyph', 'altglyphdef', 'altglyphitem', 'animatecolor', 'animatemotion', 'animatetransform', 'audio', 'canvas', 'circle', 'clippath', 'defs', 'desc', 'ellipse', 'filter', 'font', 'g', 'glyph', 'glyphref', 'hkern', 'image', 'line', 'lineargradient', 'marker', 'mask', 'metadata', 'mpath', 'path', 'pattern', 'polygon', 'polyline', 'radialgradient', 'rect', 'stop', 'style', 'switch', 'symbol', 'text', 'textpath', 'title', 'tref', 'tspan', 'video', 'view', 'vkern']);
266
+ var svgFilters = freeze$1(['feBlend', 'feColorMatrix', 'feComponentTransfer', 'feComposite', 'feConvolveMatrix', 'feDiffuseLighting', 'feDisplacementMap', 'feDistantLight', 'feFlood', 'feFuncA', 'feFuncB', 'feFuncG', 'feFuncR', 'feGaussianBlur', 'feMerge', 'feMergeNode', 'feMorphology', 'feOffset', 'fePointLight', 'feSpecularLighting', 'feSpotLight', 'feTile', 'feTurbulence']);
267
+ var mathMl = freeze$1(['math', 'menclose', 'merror', 'mfenced', 'mfrac', 'mglyph', 'mi', 'mlabeledtr', 'mmultiscripts', 'mn', 'mo', 'mover', 'mpadded', 'mphantom', 'mroot', 'mrow', 'ms', 'mspace', 'msqrt', 'mstyle', 'msub', 'msup', 'msubsup', 'mtable', 'mtd', 'mtext', 'mtr', 'munder', 'munderover']);
268
+ var text = freeze$1(['#text']);
269
+
270
+ var freeze$2 = Object.freeze || function (x) {
271
+ return x;
272
+ };
273
+
274
+ var html$1 = freeze$2(['accept', 'action', 'align', 'alt', 'autocomplete', 'background', 'bgcolor', 'border', 'cellpadding', 'cellspacing', 'checked', 'cite', 'class', 'clear', 'color', 'cols', 'colspan', 'controls', 'coords', 'crossorigin', 'datetime', 'default', 'dir', 'disabled', 'download', 'enctype', 'face', 'for', 'headers', 'height', 'hidden', 'high', 'href', 'hreflang', 'id', 'integrity', 'ismap', 'label', 'lang', 'list', 'loop', 'low', 'max', 'maxlength', 'media', 'method', 'min', 'multiple', 'name', 'noshade', 'novalidate', 'nowrap', 'open', 'optimum', 'pattern', 'placeholder', 'poster', 'preload', 'pubdate', 'radiogroup', 'readonly', 'rel', 'required', 'rev', 'reversed', 'role', 'rows', 'rowspan', 'spellcheck', 'scope', 'selected', 'shape', 'size', 'sizes', 'span', 'srclang', 'start', 'src', 'srcset', 'step', 'style', 'summary', 'tabindex', 'title', 'type', 'usemap', 'valign', 'value', 'width', 'xmlns']);
275
+ var svg$1 = freeze$2(['accent-height', 'accumulate', 'additive', 'alignment-baseline', 'ascent', 'attributename', 'attributetype', 'azimuth', 'basefrequency', 'baseline-shift', 'begin', 'bias', 'by', 'class', 'clip', 'clip-path', 'clip-rule', 'color', 'color-interpolation', 'color-interpolation-filters', 'color-profile', 'color-rendering', 'cx', 'cy', 'd', 'dx', 'dy', 'diffuseconstant', 'direction', 'display', 'divisor', 'dur', 'edgemode', 'elevation', 'end', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'filterunits', 'flood-color', 'flood-opacity', 'font-family', 'font-size', 'font-size-adjust', 'font-stretch', 'font-style', 'font-variant', 'font-weight', 'fx', 'fy', 'g1', 'g2', 'glyph-name', 'glyphref', 'gradientunits', 'gradienttransform', 'height', 'href', 'id', 'image-rendering', 'in', 'in2', 'k', 'k1', 'k2', 'k3', 'k4', 'kerning', 'keypoints', 'keysplines', 'keytimes', 'lang', 'lengthadjust', 'letter-spacing', 'kernelmatrix', 'kernelunitlength', 'lighting-color', 'local', 'marker-end', 'marker-mid', 'marker-start', 'markerheight', 'markerunits', 'markerwidth', 'maskcontentunits', 'maskunits', 'max', 'mask', 'media', 'method', 'mode', 'min', 'name', 'numoctaves', 'offset', 'operator', 'opacity', 'order', 'orient', 'orientation', 'origin', 'overflow', 'paint-order', 'path', 'pathlength', 'patterncontentunits', 'patterntransform', 'patternunits', 'points', 'preservealpha', 'preserveaspectratio', 'primitiveunits', 'r', 'rx', 'ry', 'radius', 'refx', 'refy', 'repeatcount', 'repeatdur', 'restart', 'result', 'rotate', 'scale', 'seed', 'shape-rendering', 'specularconstant', 'specularexponent', 'spreadmethod', 'stddeviation', 'stitchtiles', 'stop-color', 'stop-opacity', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke', 'stroke-width', 'style', 'surfacescale', 'tabindex', 'targetx', 'targety', 'transform', 'text-anchor', 'text-decoration', 'text-rendering', 'textlength', 'type', 'u1', 'u2', 'unicode', 'values', 'viewbox', 'visibility', 'version', 'vert-adv-y', 'vert-origin-x', 'vert-origin-y', 'width', 'word-spacing', 'wrap', 'writing-mode', 'xchannelselector', 'ychannelselector', 'x', 'x1', 'x2', 'xmlns', 'y', 'y1', 'y2', 'z', 'zoomandpan']);
276
+ var mathMl$1 = freeze$2(['accent', 'accentunder', 'align', 'bevelled', 'close', 'columnsalign', 'columnlines', 'columnspan', 'denomalign', 'depth', 'dir', 'display', 'displaystyle', 'fence', 'frame', 'height', 'href', 'id', 'largeop', 'length', 'linethickness', 'lspace', 'lquote', 'mathbackground', 'mathcolor', 'mathsize', 'mathvariant', 'maxsize', 'minsize', 'movablelimits', 'notation', 'numalign', 'open', 'rowalign', 'rowlines', 'rowspacing', 'rowspan', 'rspace', 'rquote', 'scriptlevel', 'scriptminsize', 'scriptsizemultiplier', 'selection', 'separator', 'separators', 'stretchy', 'subscriptshift', 'supscriptshift', 'symmetric', 'voffset', 'width', 'xmlns']);
277
+ var xml = freeze$2(['xlink:href', 'xml:id', 'xlink:title', 'xml:space', 'xmlns:xlink']);
278
+ var hasOwnProperty = Object.hasOwnProperty;
279
+ var setPrototypeOf = Object.setPrototypeOf;
280
+
281
+ var _ref$1 = typeof Reflect !== 'undefined' && Reflect;
282
+
283
+ var apply$1 = _ref$1.apply;
284
+
285
+ if (!apply$1) {
286
+ apply$1 = function apply(fun, thisValue, args) {
287
+ return fun.apply(thisValue, args);
281
288
  };
289
+ }
290
+ /* Add properties to a lookup table */
282
291
 
283
- var html$1 = freeze$2(['accept', 'action', 'align', 'alt', 'autocomplete', 'background', 'bgcolor', 'border', 'cellpadding', 'cellspacing', 'checked', 'cite', 'class', 'clear', 'color', 'cols', 'colspan', 'controls', 'coords', 'crossorigin', 'datetime', 'default', 'dir', 'disabled', 'download', 'enctype', 'face', 'for', 'headers', 'height', 'hidden', 'high', 'href', 'hreflang', 'id', 'integrity', 'ismap', 'label', 'lang', 'list', 'loop', 'low', 'max', 'maxlength', 'media', 'method', 'min', 'multiple', 'name', 'noshade', 'novalidate', 'nowrap', 'open', 'optimum', 'pattern', 'placeholder', 'poster', 'preload', 'pubdate', 'radiogroup', 'readonly', 'rel', 'required', 'rev', 'reversed', 'role', 'rows', 'rowspan', 'spellcheck', 'scope', 'selected', 'shape', 'size', 'sizes', 'span', 'srclang', 'start', 'src', 'srcset', 'step', 'style', 'summary', 'tabindex', 'title', 'type', 'usemap', 'valign', 'value', 'width', 'xmlns']);
284
- var svg$1 = freeze$2(['accent-height', 'accumulate', 'additive', 'alignment-baseline', 'ascent', 'attributename', 'attributetype', 'azimuth', 'basefrequency', 'baseline-shift', 'begin', 'bias', 'by', 'class', 'clip', 'clip-path', 'clip-rule', 'color', 'color-interpolation', 'color-interpolation-filters', 'color-profile', 'color-rendering', 'cx', 'cy', 'd', 'dx', 'dy', 'diffuseconstant', 'direction', 'display', 'divisor', 'dur', 'edgemode', 'elevation', 'end', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'filterunits', 'flood-color', 'flood-opacity', 'font-family', 'font-size', 'font-size-adjust', 'font-stretch', 'font-style', 'font-variant', 'font-weight', 'fx', 'fy', 'g1', 'g2', 'glyph-name', 'glyphref', 'gradientunits', 'gradienttransform', 'height', 'href', 'id', 'image-rendering', 'in', 'in2', 'k', 'k1', 'k2', 'k3', 'k4', 'kerning', 'keypoints', 'keysplines', 'keytimes', 'lang', 'lengthadjust', 'letter-spacing', 'kernelmatrix', 'kernelunitlength', 'lighting-color', 'local', 'marker-end', 'marker-mid', 'marker-start', 'markerheight', 'markerunits', 'markerwidth', 'maskcontentunits', 'maskunits', 'max', 'mask', 'media', 'method', 'mode', 'min', 'name', 'numoctaves', 'offset', 'operator', 'opacity', 'order', 'orient', 'orientation', 'origin', 'overflow', 'paint-order', 'path', 'pathlength', 'patterncontentunits', 'patterntransform', 'patternunits', 'points', 'preservealpha', 'preserveaspectratio', 'primitiveunits', 'r', 'rx', 'ry', 'radius', 'refx', 'refy', 'repeatcount', 'repeatdur', 'restart', 'result', 'rotate', 'scale', 'seed', 'shape-rendering', 'specularconstant', 'specularexponent', 'spreadmethod', 'stddeviation', 'stitchtiles', 'stop-color', 'stop-opacity', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke', 'stroke-width', 'style', 'surfacescale', 'tabindex', 'targetx', 'targety', 'transform', 'text-anchor', 'text-decoration', 'text-rendering', 'textlength', 'type', 'u1', 'u2', 'unicode', 'values', 'viewbox', 'visibility', 'version', 'vert-adv-y', 'vert-origin-x', 'vert-origin-y', 'width', 'word-spacing', 'wrap', 'writing-mode', 'xchannelselector', 'ychannelselector', 'x', 'x1', 'x2', 'xmlns', 'y', 'y1', 'y2', 'z', 'zoomandpan']);
285
- var mathMl$1 = freeze$2(['accent', 'accentunder', 'align', 'bevelled', 'close', 'columnsalign', 'columnlines', 'columnspan', 'denomalign', 'depth', 'dir', 'display', 'displaystyle', 'fence', 'frame', 'height', 'href', 'id', 'largeop', 'length', 'linethickness', 'lspace', 'lquote', 'mathbackground', 'mathcolor', 'mathsize', 'mathvariant', 'maxsize', 'minsize', 'movablelimits', 'notation', 'numalign', 'open', 'rowalign', 'rowlines', 'rowspacing', 'rowspan', 'rspace', 'rquote', 'scriptlevel', 'scriptminsize', 'scriptsizemultiplier', 'selection', 'separator', 'separators', 'stretchy', 'subscriptshift', 'supscriptshift', 'symmetric', 'voffset', 'width', 'xmlns']);
286
- var xml = freeze$2(['xlink:href', 'xml:id', 'xlink:title', 'xml:space', 'xmlns:xlink']);
287
- var hasOwnProperty = Object.hasOwnProperty;
288
- var setPrototypeOf = Object.setPrototypeOf;
289
-
290
- var _ref$1 = typeof Reflect !== 'undefined' && Reflect;
291
-
292
- var apply$1 = _ref$1.apply;
293
292
 
294
- if (!apply$1) {
295
- apply$1 = function apply(fun, thisValue, args) {
296
- return fun.apply(thisValue, args);
297
- };
293
+ function addToSet(set, array) {
294
+ if (setPrototypeOf) {
295
+ // Make 'in' and truthy checks like Boolean(set.constructor)
296
+ // independent of any properties defined on Object.prototype.
297
+ // Prevent prototype setters from intercepting set as a this value.
298
+ setPrototypeOf(set, null);
298
299
  }
299
- /* Add properties to a lookup table */
300
-
301
-
302
- function addToSet(set, array) {
303
- if (setPrototypeOf) {
304
- // Make 'in' and truthy checks like Boolean(set.constructor)
305
- // independent of any properties defined on Object.prototype.
306
- // Prevent prototype setters from intercepting set as a this value.
307
- setPrototypeOf(set, null);
308
- }
309
-
310
- var l = array.length;
311
300
 
312
- while (l--) {
313
- var element = array[l];
301
+ var l = array.length;
314
302
 
315
- if (typeof element === 'string') {
316
- var lcElement = element.toLowerCase();
303
+ while (l--) {
304
+ var element = array[l];
317
305
 
318
- if (lcElement !== element) {
319
- // Config presets (e.g. tags.js, attrs.js) are immutable.
320
- if (!Object.isFrozen(array)) {
321
- array[l] = lcElement;
322
- }
306
+ if (typeof element === 'string') {
307
+ var lcElement = element.toLowerCase();
323
308
 
324
- element = lcElement;
309
+ if (lcElement !== element) {
310
+ // Config presets (e.g. tags.js, attrs.js) are immutable.
311
+ if (!Object.isFrozen(array)) {
312
+ array[l] = lcElement;
325
313
  }
326
- }
327
314
 
328
- set[element] = true;
315
+ element = lcElement;
316
+ }
329
317
  }
330
318
 
331
- return set;
319
+ set[element] = true;
332
320
  }
333
- /* Shallow clone an object */
334
321
 
322
+ return set;
323
+ }
324
+ /* Shallow clone an object */
335
325
 
336
- function clone(object) {
337
- var newObject = {};
338
- var property = void 0;
339
326
 
340
- for (property in object) {
341
- if (apply$1(hasOwnProperty, object, [property])) {
342
- newObject[property] = object[property];
343
- }
344
- }
327
+ function clone(object) {
328
+ var newObject = {};
329
+ var property = void 0;
345
330
 
346
- return newObject;
331
+ for (property in object) {
332
+ if (apply$1(hasOwnProperty, object, [property])) {
333
+ newObject[property] = object[property];
334
+ }
347
335
  }
348
336
 
349
- var seal = Object.seal || function (x) {
350
- return x;
351
- };
337
+ return newObject;
338
+ }
352
339
 
353
- var MUSTACHE_EXPR = seal(/\{\{[\s\S]*|[\s\S]*\}\}/gm); // Specify template detection regex for SAFE_FOR_TEMPLATES mode
340
+ var seal = Object.seal || function (x) {
341
+ return x;
342
+ };
354
343
 
355
- var ERB_EXPR = seal(/<%[\s\S]*|[\s\S]*%>/gm);
356
- var DATA_ATTR = seal(/^data-[\-\w.\u00B7-\uFFFF]/); // eslint-disable-line no-useless-escape
344
+ var MUSTACHE_EXPR = seal(/\{\{[\s\S]*|[\s\S]*\}\}/gm); // Specify template detection regex for SAFE_FOR_TEMPLATES mode
357
345
 
358
- var ARIA_ATTR = seal(/^aria-[\-\w]+$/); // eslint-disable-line no-useless-escape
346
+ var ERB_EXPR = seal(/<%[\s\S]*|[\s\S]*%>/gm);
347
+ var DATA_ATTR = seal(/^data-[\-\w.\u00B7-\uFFFF]/); // eslint-disable-line no-useless-escape
359
348
 
360
- var IS_ALLOWED_URI = seal(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i // eslint-disable-line no-useless-escape
361
- );
362
- var IS_SCRIPT_OR_DATA = seal(/^(?:\w+script|data):/i);
363
- var ATTR_WHITESPACE = seal(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205f\u3000]/g // eslint-disable-line no-control-regex
364
- );
349
+ var ARIA_ATTR = seal(/^aria-[\-\w]+$/); // eslint-disable-line no-useless-escape
365
350
 
366
- var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {
367
- return typeof obj;
368
- } : function (obj) {
369
- return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
370
- };
351
+ var IS_ALLOWED_URI = seal(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i // eslint-disable-line no-useless-escape
352
+ );
353
+ var IS_SCRIPT_OR_DATA = seal(/^(?:\w+script|data):/i);
354
+ var ATTR_WHITESPACE = seal(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205f\u3000]/g // eslint-disable-line no-control-regex
355
+ );
371
356
 
372
- function _toConsumableArray(arr) {
373
- if (Array.isArray(arr)) {
374
- for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) {
375
- arr2[i] = arr[i];
376
- }
357
+ var _typeof$1 = typeof Symbol === "function" && _typeof(Symbol.iterator) === "symbol" ? function (obj) {
358
+ return _typeof(obj);
359
+ } : function (obj) {
360
+ return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : _typeof(obj);
361
+ };
377
362
 
378
- return arr2;
379
- } else {
380
- return Array.from(arr);
363
+ function _toConsumableArray(arr) {
364
+ if (Array.isArray(arr)) {
365
+ for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) {
366
+ arr2[i] = arr[i];
381
367
  }
368
+
369
+ return arr2;
370
+ } else {
371
+ return Array.from(arr);
382
372
  }
373
+ }
383
374
 
384
- var _ref = typeof Reflect !== 'undefined' && Reflect;
375
+ var _ref = typeof Reflect !== 'undefined' && Reflect;
385
376
 
386
- var apply = _ref.apply;
387
- var arraySlice = Array.prototype.slice;
388
- var freeze = Object.freeze;
377
+ var apply = _ref.apply;
378
+ var arraySlice = Array.prototype.slice;
379
+ var freeze = Object.freeze;
389
380
 
390
- var getGlobal = function getGlobal() {
391
- return typeof window === 'undefined' ? null : window;
392
- };
381
+ var getGlobal = function getGlobal() {
382
+ return typeof window === 'undefined' ? null : window;
383
+ };
393
384
 
394
- if (!apply) {
395
- apply = function apply(fun, thisValue, args) {
396
- return fun.apply(thisValue, args);
397
- };
385
+ if (!apply) {
386
+ apply = function apply(fun, thisValue, args) {
387
+ return fun.apply(thisValue, args);
388
+ };
389
+ }
390
+ /**
391
+ * Creates a no-op policy for internal use only.
392
+ * Don't export this function outside this module!
393
+ * @param {?TrustedTypePolicyFactory} trustedTypes The policy factory.
394
+ * @param {Document} document The document object (to determine policy name suffix)
395
+ * @return {?TrustedTypePolicy} The policy created (or null, if Trusted Types
396
+ * are not supported).
397
+ */
398
+
399
+
400
+ var _createTrustedTypesPolicy = function _createTrustedTypesPolicy(trustedTypes, document) {
401
+ if ((typeof trustedTypes === 'undefined' ? 'undefined' : _typeof$1(trustedTypes)) !== 'object' || typeof trustedTypes.createPolicy !== 'function') {
402
+ return null;
403
+ } // Allow the callers to control the unique policy name
404
+ // by adding a data-tt-policy-suffix to the script element with the DOMPurify.
405
+ // Policy creation with duplicate names throws in Trusted Types.
406
+
407
+
408
+ var suffix = null;
409
+ var ATTR_NAME = 'data-tt-policy-suffix';
410
+
411
+ if (document.currentScript && document.currentScript.hasAttribute(ATTR_NAME)) {
412
+ suffix = document.currentScript.getAttribute(ATTR_NAME);
398
413
  }
399
- /**
400
- * Creates a no-op policy for internal use only.
401
- * Don't export this function outside this module!
402
- * @param {?TrustedTypePolicyFactory} trustedTypes The policy factory.
403
- * @param {Document} document The document object (to determine policy name suffix)
404
- * @return {?TrustedTypePolicy} The policy created (or null, if Trusted Types
405
- * are not supported).
406
- */
407
-
408
414
 
409
- var _createTrustedTypesPolicy = function _createTrustedTypesPolicy(trustedTypes, document) {
410
- if ((typeof trustedTypes === 'undefined' ? 'undefined' : _typeof(trustedTypes)) !== 'object' || typeof trustedTypes.createPolicy !== 'function') {
411
- return null;
412
- } // Allow the callers to control the unique policy name
413
- // by adding a data-tt-policy-suffix to the script element with the DOMPurify.
414
- // Policy creation with duplicate names throws in Trusted Types.
415
+ var policyName = 'dompurify' + (suffix ? '#' + suffix : '');
415
416
 
417
+ try {
418
+ return trustedTypes.createPolicy(policyName, {
419
+ createHTML: function createHTML(html$$1) {
420
+ return html$$1;
421
+ }
422
+ });
423
+ } catch (error) {
424
+ // Policy creation failed (most likely another DOMPurify script has
425
+ // already run). Skip creating the policy, as this will only cause errors
426
+ // if TT are enforced.
427
+ console.warn('TrustedTypes policy ' + policyName + ' could not be created.');
428
+ return null;
429
+ }
430
+ };
416
431
 
417
- var suffix = null;
418
- var ATTR_NAME = 'data-tt-policy-suffix';
419
-
420
- if (document.currentScript && document.currentScript.hasAttribute(ATTR_NAME)) {
421
- suffix = document.currentScript.getAttribute(ATTR_NAME);
422
- }
423
-
424
- var policyName = 'dompurify' + (suffix ? '#' + suffix : '');
432
+ function createDOMPurify() {
433
+ var window = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getGlobal();
425
434
 
426
- try {
427
- return trustedTypes.createPolicy(policyName, {
428
- createHTML: function createHTML(html$$1) {
429
- return html$$1;
430
- }
431
- });
432
- } catch (error) {
433
- // Policy creation failed (most likely another DOMPurify script has
434
- // already run). Skip creating the policy, as this will only cause errors
435
- // if TT are enforced.
436
- console.warn('TrustedTypes policy ' + policyName + ' could not be created.');
437
- return null;
438
- }
435
+ var DOMPurify = function DOMPurify(root) {
436
+ return createDOMPurify(root);
439
437
  };
440
-
441
- function createDOMPurify() {
442
- var window = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getGlobal();
443
-
444
- var DOMPurify = function DOMPurify(root) {
445
- return createDOMPurify(root);
446
- };
447
- /**
448
- * Version label, exposed for easier checks
449
- * if DOMPurify is up to date or not
450
- */
438
+ /**
439
+ * Version label, exposed for easier checks
440
+ * if DOMPurify is up to date or not
441
+ */
451
442
 
452
443
 
453
- DOMPurify.version = '1.0.11';
454
- /**
455
- * Array of elements that DOMPurify removed during sanitation.
456
- * Empty if nothing was removed.
457
- */
444
+ DOMPurify.version = '1.0.11';
445
+ /**
446
+ * Array of elements that DOMPurify removed during sanitation.
447
+ * Empty if nothing was removed.
448
+ */
458
449
 
459
- DOMPurify.removed = [];
450
+ DOMPurify.removed = [];
460
451
 
461
- if (!window || !window.document || window.document.nodeType !== 9) {
462
- // Not running in a browser, provide a factory function
463
- // so that you can pass your own Window
464
- DOMPurify.isSupported = false;
465
- return DOMPurify;
466
- }
452
+ if (!window || !window.document || window.document.nodeType !== 9) {
453
+ // Not running in a browser, provide a factory function
454
+ // so that you can pass your own Window
455
+ DOMPurify.isSupported = false;
456
+ return DOMPurify;
457
+ }
467
458
 
468
- var originalDocument = window.document;
469
- var useDOMParser = false;
470
- var removeTitle = false;
471
- var document = window.document;
472
- var DocumentFragment = window.DocumentFragment,
473
- HTMLTemplateElement = window.HTMLTemplateElement,
474
- Node = window.Node,
475
- NodeFilter = window.NodeFilter,
476
- _window$NamedNodeMap = window.NamedNodeMap,
477
- NamedNodeMap = _window$NamedNodeMap === undefined ? window.NamedNodeMap || window.MozNamedAttrMap : _window$NamedNodeMap,
478
- Text = window.Text,
479
- Comment = window.Comment,
480
- DOMParser = window.DOMParser,
481
- TrustedTypes = window.TrustedTypes; // As per issue #47, the web-components registry is inherited by a
482
- // new document created via createHTMLDocument. As per the spec
483
- // (http://w3c.github.io/webcomponents/spec/custom/#creating-and-passing-registries)
484
- // a new empty registry is used when creating a template contents owner
485
- // document, so we use that as our parent document to ensure nothing
486
- // is inherited.
487
-
488
- if (typeof HTMLTemplateElement === 'function') {
489
- var template = document.createElement('template');
490
-
491
- if (template.content && template.content.ownerDocument) {
492
- document = template.content.ownerDocument;
493
- }
459
+ var originalDocument = window.document;
460
+ var useDOMParser = false;
461
+ var removeTitle = false;
462
+ var document = window.document;
463
+ var DocumentFragment = window.DocumentFragment,
464
+ HTMLTemplateElement = window.HTMLTemplateElement,
465
+ Node = window.Node,
466
+ NodeFilter = window.NodeFilter,
467
+ _window$NamedNodeMap = window.NamedNodeMap,
468
+ NamedNodeMap = _window$NamedNodeMap === undefined ? window.NamedNodeMap || window.MozNamedAttrMap : _window$NamedNodeMap,
469
+ Text = window.Text,
470
+ Comment = window.Comment,
471
+ DOMParser = window.DOMParser,
472
+ TrustedTypes = window.TrustedTypes; // As per issue #47, the web-components registry is inherited by a
473
+ // new document created via createHTMLDocument. As per the spec
474
+ // (http://w3c.github.io/webcomponents/spec/custom/#creating-and-passing-registries)
475
+ // a new empty registry is used when creating a template contents owner
476
+ // document, so we use that as our parent document to ensure nothing
477
+ // is inherited.
478
+
479
+ if (typeof HTMLTemplateElement === 'function') {
480
+ var template = document.createElement('template');
481
+
482
+ if (template.content && template.content.ownerDocument) {
483
+ document = template.content.ownerDocument;
494
484
  }
485
+ }
495
486
 
496
- var trustedTypesPolicy = _createTrustedTypesPolicy(TrustedTypes, originalDocument);
497
-
498
- var emptyHTML = trustedTypesPolicy ? trustedTypesPolicy.createHTML('') : '';
499
- var _document = document,
500
- implementation = _document.implementation,
501
- createNodeIterator = _document.createNodeIterator,
502
- getElementsByTagName = _document.getElementsByTagName,
503
- createDocumentFragment = _document.createDocumentFragment;
504
- var importNode = originalDocument.importNode;
505
- var hooks = {};
506
- /**
507
- * Expose whether this browser supports running the full DOMPurify.
508
- */
509
-
510
- DOMPurify.isSupported = implementation && typeof implementation.createHTMLDocument !== 'undefined' && document.documentMode !== 9;
511
- var MUSTACHE_EXPR$$1 = MUSTACHE_EXPR,
512
- ERB_EXPR$$1 = ERB_EXPR,
513
- DATA_ATTR$$1 = DATA_ATTR,
514
- ARIA_ATTR$$1 = ARIA_ATTR,
515
- IS_SCRIPT_OR_DATA$$1 = IS_SCRIPT_OR_DATA,
516
- ATTR_WHITESPACE$$1 = ATTR_WHITESPACE;
517
- var IS_ALLOWED_URI$$1 = IS_ALLOWED_URI;
518
- /**
519
- * We consider the elements and attributes below to be safe. Ideally
520
- * don't add any new ones but feel free to remove unwanted ones.
521
- */
522
-
523
- /* allowed element names */
487
+ var trustedTypesPolicy = _createTrustedTypesPolicy(TrustedTypes, originalDocument);
524
488
 
525
- var ALLOWED_TAGS = null;
526
- var DEFAULT_ALLOWED_TAGS = addToSet({}, [].concat(_toConsumableArray(html), _toConsumableArray(svg), _toConsumableArray(svgFilters), _toConsumableArray(mathMl), _toConsumableArray(text)));
527
- /* Allowed attribute names */
489
+ var emptyHTML = trustedTypesPolicy ? trustedTypesPolicy.createHTML('') : '';
490
+ var _document = document,
491
+ implementation = _document.implementation,
492
+ createNodeIterator = _document.createNodeIterator,
493
+ getElementsByTagName = _document.getElementsByTagName,
494
+ createDocumentFragment = _document.createDocumentFragment;
495
+ var importNode = originalDocument.importNode;
496
+ var hooks = {};
497
+ /**
498
+ * Expose whether this browser supports running the full DOMPurify.
499
+ */
528
500
 
529
- var ALLOWED_ATTR = null;
530
- var DEFAULT_ALLOWED_ATTR = addToSet({}, [].concat(_toConsumableArray(html$1), _toConsumableArray(svg$1), _toConsumableArray(mathMl$1), _toConsumableArray(xml)));
531
- /* Explicitly forbidden tags (overrides ALLOWED_TAGS/ADD_TAGS) */
501
+ DOMPurify.isSupported = implementation && typeof implementation.createHTMLDocument !== 'undefined' && document.documentMode !== 9;
502
+ var MUSTACHE_EXPR$$1 = MUSTACHE_EXPR,
503
+ ERB_EXPR$$1 = ERB_EXPR,
504
+ DATA_ATTR$$1 = DATA_ATTR,
505
+ ARIA_ATTR$$1 = ARIA_ATTR,
506
+ IS_SCRIPT_OR_DATA$$1 = IS_SCRIPT_OR_DATA,
507
+ ATTR_WHITESPACE$$1 = ATTR_WHITESPACE;
508
+ var IS_ALLOWED_URI$$1 = IS_ALLOWED_URI;
509
+ /**
510
+ * We consider the elements and attributes below to be safe. Ideally
511
+ * don't add any new ones but feel free to remove unwanted ones.
512
+ */
532
513
 
533
- var FORBID_TAGS = null;
534
- /* Explicitly forbidden attributes (overrides ALLOWED_ATTR/ADD_ATTR) */
514
+ /* allowed element names */
535
515
 
536
- var FORBID_ATTR = null;
537
- /* Decide if ARIA attributes are okay */
516
+ var ALLOWED_TAGS = null;
517
+ var DEFAULT_ALLOWED_TAGS = addToSet({}, [].concat(_toConsumableArray(html), _toConsumableArray(svg), _toConsumableArray(svgFilters), _toConsumableArray(mathMl), _toConsumableArray(text)));
518
+ /* Allowed attribute names */
538
519
 
539
- var ALLOW_ARIA_ATTR = true;
540
- /* Decide if custom data attributes are okay */
520
+ var ALLOWED_ATTR = null;
521
+ var DEFAULT_ALLOWED_ATTR = addToSet({}, [].concat(_toConsumableArray(html$1), _toConsumableArray(svg$1), _toConsumableArray(mathMl$1), _toConsumableArray(xml)));
522
+ /* Explicitly forbidden tags (overrides ALLOWED_TAGS/ADD_TAGS) */
541
523
 
542
- var ALLOW_DATA_ATTR = true;
543
- /* Decide if unknown protocols are okay */
524
+ var FORBID_TAGS = null;
525
+ /* Explicitly forbidden attributes (overrides ALLOWED_ATTR/ADD_ATTR) */
544
526
 
545
- var ALLOW_UNKNOWN_PROTOCOLS = false;
546
- /* Output should be safe for jQuery's $() factory? */
527
+ var FORBID_ATTR = null;
528
+ /* Decide if ARIA attributes are okay */
547
529
 
548
- var SAFE_FOR_JQUERY = false;
549
- /* Output should be safe for common template engines.
550
- * This means, DOMPurify removes data attributes, mustaches and ERB
551
- */
530
+ var ALLOW_ARIA_ATTR = true;
531
+ /* Decide if custom data attributes are okay */
552
532
 
553
- var SAFE_FOR_TEMPLATES = false;
554
- /* Decide if document with <html>... should be returned */
533
+ var ALLOW_DATA_ATTR = true;
534
+ /* Decide if unknown protocols are okay */
555
535
 
556
- var WHOLE_DOCUMENT = false;
557
- /* Track whether config is already set on this instance of DOMPurify. */
536
+ var ALLOW_UNKNOWN_PROTOCOLS = false;
537
+ /* Output should be safe for jQuery's $() factory? */
558
538
 
559
- var SET_CONFIG = false;
560
- /* Decide if all elements (e.g. style, script) must be children of
561
- * document.body. By default, browsers might move them to document.head */
539
+ var SAFE_FOR_JQUERY = false;
540
+ /* Output should be safe for common template engines.
541
+ * This means, DOMPurify removes data attributes, mustaches and ERB
542
+ */
562
543
 
563
- var FORCE_BODY = false;
564
- /* Decide if a DOM `HTMLBodyElement` should be returned, instead of a html
565
- * string (or a TrustedHTML object if Trusted Types are supported).
566
- * If `WHOLE_DOCUMENT` is enabled a `HTMLHtmlElement` will be returned instead
567
- */
544
+ var SAFE_FOR_TEMPLATES = false;
545
+ /* Decide if document with <html>... should be returned */
568
546
 
569
- var RETURN_DOM = false;
570
- /* Decide if a DOM `DocumentFragment` should be returned, instead of a html
571
- * string (or a TrustedHTML object if Trusted Types are supported) */
547
+ var WHOLE_DOCUMENT = false;
548
+ /* Track whether config is already set on this instance of DOMPurify. */
572
549
 
573
- var RETURN_DOM_FRAGMENT = false;
574
- /* If `RETURN_DOM` or `RETURN_DOM_FRAGMENT` is enabled, decide if the returned DOM
575
- * `Node` is imported into the current `Document`. If this flag is not enabled the
576
- * `Node` will belong (its ownerDocument) to a fresh `HTMLDocument`, created by
577
- * DOMPurify. */
550
+ var SET_CONFIG = false;
551
+ /* Decide if all elements (e.g. style, script) must be children of
552
+ * document.body. By default, browsers might move them to document.head */
578
553
 
579
- var RETURN_DOM_IMPORT = false;
580
- /* Output should be free from DOM clobbering attacks? */
554
+ var FORCE_BODY = false;
555
+ /* Decide if a DOM `HTMLBodyElement` should be returned, instead of a html
556
+ * string (or a TrustedHTML object if Trusted Types are supported).
557
+ * If `WHOLE_DOCUMENT` is enabled a `HTMLHtmlElement` will be returned instead
558
+ */
581
559
 
582
- var SANITIZE_DOM = true;
583
- /* Keep element content when removing element? */
560
+ var RETURN_DOM = false;
561
+ /* Decide if a DOM `DocumentFragment` should be returned, instead of a html
562
+ * string (or a TrustedHTML object if Trusted Types are supported) */
584
563
 
585
- var KEEP_CONTENT = true;
586
- /* If a `Node` is passed to sanitize(), then performs sanitization in-place instead
587
- * of importing it into a new Document and returning a sanitized copy */
564
+ var RETURN_DOM_FRAGMENT = false;
565
+ /* If `RETURN_DOM` or `RETURN_DOM_FRAGMENT` is enabled, decide if the returned DOM
566
+ * `Node` is imported into the current `Document`. If this flag is not enabled the
567
+ * `Node` will belong (its ownerDocument) to a fresh `HTMLDocument`, created by
568
+ * DOMPurify. */
588
569
 
589
- var IN_PLACE = false;
590
- /* Allow usage of profiles like html, svg and mathMl */
570
+ var RETURN_DOM_IMPORT = false;
571
+ /* Output should be free from DOM clobbering attacks? */
591
572
 
592
- var USE_PROFILES = {};
593
- /* Tags to ignore content of when KEEP_CONTENT is true */
573
+ var SANITIZE_DOM = true;
574
+ /* Keep element content when removing element? */
594
575
 
595
- var FORBID_CONTENTS = addToSet({}, ['audio', 'head', 'math', 'script', 'style', 'template', 'svg', 'video']);
596
- /* Tags that are safe for data: URIs */
576
+ var KEEP_CONTENT = true;
577
+ /* If a `Node` is passed to sanitize(), then performs sanitization in-place instead
578
+ * of importing it into a new Document and returning a sanitized copy */
597
579
 
598
- var DATA_URI_TAGS = addToSet({}, ['audio', 'video', 'img', 'source', 'image']);
599
- /* Attributes safe for values like "javascript:" */
580
+ var IN_PLACE = false;
581
+ /* Allow usage of profiles like html, svg and mathMl */
600
582
 
601
- var URI_SAFE_ATTRIBUTES = null;
602
- var DEFAULT_URI_SAFE_ATTRIBUTES = addToSet({}, ['alt', 'class', 'for', 'id', 'label', 'name', 'pattern', 'placeholder', 'summary', 'title', 'value', 'style', 'xmlns']);
603
- /* Keep a reference to config to pass to hooks */
583
+ var USE_PROFILES = {};
584
+ /* Tags to ignore content of when KEEP_CONTENT is true */
604
585
 
605
- var CONFIG = null;
606
- /* Ideally, do not touch anything below this line */
586
+ var FORBID_CONTENTS = addToSet({}, ['audio', 'head', 'math', 'script', 'style', 'template', 'svg', 'video']);
587
+ /* Tags that are safe for data: URIs */
607
588
 
608
- /* ______________________________________________ */
589
+ var DATA_URI_TAGS = addToSet({}, ['audio', 'video', 'img', 'source', 'image']);
590
+ /* Attributes safe for values like "javascript:" */
609
591
 
610
- var formElement = document.createElement('form');
611
- /**
612
- * _parseConfig
613
- *
614
- * @param {Object} cfg optional config literal
615
- */
616
- // eslint-disable-next-line complexity
592
+ var URI_SAFE_ATTRIBUTES = null;
593
+ var DEFAULT_URI_SAFE_ATTRIBUTES = addToSet({}, ['alt', 'class', 'for', 'id', 'label', 'name', 'pattern', 'placeholder', 'summary', 'title', 'value', 'style', 'xmlns']);
594
+ /* Keep a reference to config to pass to hooks */
617
595
 
618
- var _parseConfig = function _parseConfig(cfg) {
619
- if (CONFIG && CONFIG === cfg) {
620
- return;
621
- }
622
- /* Shield configuration object from tampering */
596
+ var CONFIG = null;
597
+ /* Ideally, do not touch anything below this line */
623
598
 
599
+ /* ______________________________________________ */
624
600
 
625
- if (!cfg || (typeof cfg === 'undefined' ? 'undefined' : _typeof(cfg)) !== 'object') {
626
- cfg = {};
627
- }
628
- /* Set configuration parameters */
601
+ var formElement = document.createElement('form');
602
+ /**
603
+ * _parseConfig
604
+ *
605
+ * @param {Object} cfg optional config literal
606
+ */
607
+ // eslint-disable-next-line complexity
629
608
 
609
+ var _parseConfig = function _parseConfig(cfg) {
610
+ if (CONFIG && CONFIG === cfg) {
611
+ return;
612
+ }
613
+ /* Shield configuration object from tampering */
630
614
 
631
- ALLOWED_TAGS = 'ALLOWED_TAGS' in cfg ? addToSet({}, cfg.ALLOWED_TAGS) : DEFAULT_ALLOWED_TAGS;
632
- ALLOWED_ATTR = 'ALLOWED_ATTR' in cfg ? addToSet({}, cfg.ALLOWED_ATTR) : DEFAULT_ALLOWED_ATTR;
633
- URI_SAFE_ATTRIBUTES = 'ADD_URI_SAFE_ATTR' in cfg ? addToSet({}, cfg.ADD_URI_SAFE_ATTR) : DEFAULT_URI_SAFE_ATTRIBUTES;
634
- FORBID_TAGS = 'FORBID_TAGS' in cfg ? addToSet({}, cfg.FORBID_TAGS) : {};
635
- FORBID_ATTR = 'FORBID_ATTR' in cfg ? addToSet({}, cfg.FORBID_ATTR) : {};
636
- USE_PROFILES = 'USE_PROFILES' in cfg ? cfg.USE_PROFILES : false;
637
- ALLOW_ARIA_ATTR = cfg.ALLOW_ARIA_ATTR !== false; // Default true
638
615
 
639
- ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false; // Default true
616
+ if (!cfg || (typeof cfg === 'undefined' ? 'undefined' : _typeof$1(cfg)) !== 'object') {
617
+ cfg = {};
618
+ }
619
+ /* Set configuration parameters */
640
620
 
641
- ALLOW_UNKNOWN_PROTOCOLS = cfg.ALLOW_UNKNOWN_PROTOCOLS || false; // Default false
642
621
 
643
- SAFE_FOR_JQUERY = cfg.SAFE_FOR_JQUERY || false; // Default false
622
+ ALLOWED_TAGS = 'ALLOWED_TAGS' in cfg ? addToSet({}, cfg.ALLOWED_TAGS) : DEFAULT_ALLOWED_TAGS;
623
+ ALLOWED_ATTR = 'ALLOWED_ATTR' in cfg ? addToSet({}, cfg.ALLOWED_ATTR) : DEFAULT_ALLOWED_ATTR;
624
+ URI_SAFE_ATTRIBUTES = 'ADD_URI_SAFE_ATTR' in cfg ? addToSet({}, cfg.ADD_URI_SAFE_ATTR) : DEFAULT_URI_SAFE_ATTRIBUTES;
625
+ FORBID_TAGS = 'FORBID_TAGS' in cfg ? addToSet({}, cfg.FORBID_TAGS) : {};
626
+ FORBID_ATTR = 'FORBID_ATTR' in cfg ? addToSet({}, cfg.FORBID_ATTR) : {};
627
+ USE_PROFILES = 'USE_PROFILES' in cfg ? cfg.USE_PROFILES : false;
628
+ ALLOW_ARIA_ATTR = cfg.ALLOW_ARIA_ATTR !== false; // Default true
644
629
 
645
- SAFE_FOR_TEMPLATES = cfg.SAFE_FOR_TEMPLATES || false; // Default false
630
+ ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false; // Default true
646
631
 
647
- WHOLE_DOCUMENT = cfg.WHOLE_DOCUMENT || false; // Default false
632
+ ALLOW_UNKNOWN_PROTOCOLS = cfg.ALLOW_UNKNOWN_PROTOCOLS || false; // Default false
648
633
 
649
- RETURN_DOM = cfg.RETURN_DOM || false; // Default false
634
+ SAFE_FOR_JQUERY = cfg.SAFE_FOR_JQUERY || false; // Default false
650
635
 
651
- RETURN_DOM_FRAGMENT = cfg.RETURN_DOM_FRAGMENT || false; // Default false
636
+ SAFE_FOR_TEMPLATES = cfg.SAFE_FOR_TEMPLATES || false; // Default false
652
637
 
653
- RETURN_DOM_IMPORT = cfg.RETURN_DOM_IMPORT || false; // Default false
638
+ WHOLE_DOCUMENT = cfg.WHOLE_DOCUMENT || false; // Default false
654
639
 
655
- FORCE_BODY = cfg.FORCE_BODY || false; // Default false
640
+ RETURN_DOM = cfg.RETURN_DOM || false; // Default false
656
641
 
657
- SANITIZE_DOM = cfg.SANITIZE_DOM !== false; // Default true
642
+ RETURN_DOM_FRAGMENT = cfg.RETURN_DOM_FRAGMENT || false; // Default false
658
643
 
659
- KEEP_CONTENT = cfg.KEEP_CONTENT !== false; // Default true
644
+ RETURN_DOM_IMPORT = cfg.RETURN_DOM_IMPORT || false; // Default false
660
645
 
661
- IN_PLACE = cfg.IN_PLACE || false; // Default false
646
+ FORCE_BODY = cfg.FORCE_BODY || false; // Default false
662
647
 
663
- IS_ALLOWED_URI$$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI$$1;
648
+ SANITIZE_DOM = cfg.SANITIZE_DOM !== false; // Default true
664
649
 
665
- if (SAFE_FOR_TEMPLATES) {
666
- ALLOW_DATA_ATTR = false;
667
- }
650
+ KEEP_CONTENT = cfg.KEEP_CONTENT !== false; // Default true
668
651
 
669
- if (RETURN_DOM_FRAGMENT) {
670
- RETURN_DOM = true;
671
- }
672
- /* Parse profile info */
652
+ IN_PLACE = cfg.IN_PLACE || false; // Default false
673
653
 
654
+ IS_ALLOWED_URI$$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI$$1;
674
655
 
675
- if (USE_PROFILES) {
676
- ALLOWED_TAGS = addToSet({}, [].concat(_toConsumableArray(text)));
677
- ALLOWED_ATTR = [];
656
+ if (SAFE_FOR_TEMPLATES) {
657
+ ALLOW_DATA_ATTR = false;
658
+ }
678
659
 
679
- if (USE_PROFILES.html === true) {
680
- addToSet(ALLOWED_TAGS, html);
681
- addToSet(ALLOWED_ATTR, html$1);
682
- }
660
+ if (RETURN_DOM_FRAGMENT) {
661
+ RETURN_DOM = true;
662
+ }
663
+ /* Parse profile info */
683
664
 
684
- if (USE_PROFILES.svg === true) {
685
- addToSet(ALLOWED_TAGS, svg);
686
- addToSet(ALLOWED_ATTR, svg$1);
687
- addToSet(ALLOWED_ATTR, xml);
688
- }
689
665
 
690
- if (USE_PROFILES.svgFilters === true) {
691
- addToSet(ALLOWED_TAGS, svgFilters);
692
- addToSet(ALLOWED_ATTR, svg$1);
693
- addToSet(ALLOWED_ATTR, xml);
694
- }
666
+ if (USE_PROFILES) {
667
+ ALLOWED_TAGS = addToSet({}, [].concat(_toConsumableArray(text)));
668
+ ALLOWED_ATTR = [];
695
669
 
696
- if (USE_PROFILES.mathMl === true) {
697
- addToSet(ALLOWED_TAGS, mathMl);
698
- addToSet(ALLOWED_ATTR, mathMl$1);
699
- addToSet(ALLOWED_ATTR, xml);
700
- }
670
+ if (USE_PROFILES.html === true) {
671
+ addToSet(ALLOWED_TAGS, html);
672
+ addToSet(ALLOWED_ATTR, html$1);
701
673
  }
702
- /* Merge configuration parameters */
703
-
704
674
 
705
- if (cfg.ADD_TAGS) {
706
- if (ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) {
707
- ALLOWED_TAGS = clone(ALLOWED_TAGS);
708
- }
709
-
710
- addToSet(ALLOWED_TAGS, cfg.ADD_TAGS);
675
+ if (USE_PROFILES.svg === true) {
676
+ addToSet(ALLOWED_TAGS, svg);
677
+ addToSet(ALLOWED_ATTR, svg$1);
678
+ addToSet(ALLOWED_ATTR, xml);
711
679
  }
712
680
 
713
- if (cfg.ADD_ATTR) {
714
- if (ALLOWED_ATTR === DEFAULT_ALLOWED_ATTR) {
715
- ALLOWED_ATTR = clone(ALLOWED_ATTR);
716
- }
717
-
718
- addToSet(ALLOWED_ATTR, cfg.ADD_ATTR);
681
+ if (USE_PROFILES.svgFilters === true) {
682
+ addToSet(ALLOWED_TAGS, svgFilters);
683
+ addToSet(ALLOWED_ATTR, svg$1);
684
+ addToSet(ALLOWED_ATTR, xml);
719
685
  }
720
686
 
721
- if (cfg.ADD_URI_SAFE_ATTR) {
722
- addToSet(URI_SAFE_ATTRIBUTES, cfg.ADD_URI_SAFE_ATTR);
687
+ if (USE_PROFILES.mathMl === true) {
688
+ addToSet(ALLOWED_TAGS, mathMl);
689
+ addToSet(ALLOWED_ATTR, mathMl$1);
690
+ addToSet(ALLOWED_ATTR, xml);
723
691
  }
724
- /* Add #text in case KEEP_CONTENT is set to true */
692
+ }
693
+ /* Merge configuration parameters */
725
694
 
726
695
 
727
- if (KEEP_CONTENT) {
728
- ALLOWED_TAGS['#text'] = true;
696
+ if (cfg.ADD_TAGS) {
697
+ if (ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) {
698
+ ALLOWED_TAGS = clone(ALLOWED_TAGS);
729
699
  }
730
- /* Add html, head and body to ALLOWED_TAGS in case WHOLE_DOCUMENT is true */
731
700
 
701
+ addToSet(ALLOWED_TAGS, cfg.ADD_TAGS);
702
+ }
732
703
 
733
- if (WHOLE_DOCUMENT) {
734
- addToSet(ALLOWED_TAGS, ['html', 'head', 'body']);
704
+ if (cfg.ADD_ATTR) {
705
+ if (ALLOWED_ATTR === DEFAULT_ALLOWED_ATTR) {
706
+ ALLOWED_ATTR = clone(ALLOWED_ATTR);
735
707
  }
736
- /* Add tbody to ALLOWED_TAGS in case tables are permitted, see #286 */
737
708
 
709
+ addToSet(ALLOWED_ATTR, cfg.ADD_ATTR);
710
+ }
738
711
 
739
- if (ALLOWED_TAGS.table) {
740
- addToSet(ALLOWED_TAGS, ['tbody']);
741
- } // Prevent further manipulation of configuration.
742
- // Not available in IE8, Safari 5, etc.
712
+ if (cfg.ADD_URI_SAFE_ATTR) {
713
+ addToSet(URI_SAFE_ATTRIBUTES, cfg.ADD_URI_SAFE_ATTR);
714
+ }
715
+ /* Add #text in case KEEP_CONTENT is set to true */
743
716
 
744
717
 
745
- if (freeze) {
746
- freeze(cfg);
747
- }
718
+ if (KEEP_CONTENT) {
719
+ ALLOWED_TAGS['#text'] = true;
720
+ }
721
+ /* Add html, head and body to ALLOWED_TAGS in case WHOLE_DOCUMENT is true */
748
722
 
749
- CONFIG = cfg;
750
- };
751
- /**
752
- * _forceRemove
753
- *
754
- * @param {Node} node a DOM node
755
- */
756
723
 
724
+ if (WHOLE_DOCUMENT) {
725
+ addToSet(ALLOWED_TAGS, ['html', 'head', 'body']);
726
+ }
727
+ /* Add tbody to ALLOWED_TAGS in case tables are permitted, see #286 */
757
728
 
758
- var _forceRemove = function _forceRemove(node) {
759
- DOMPurify.removed.push({
760
- element: node
761
- });
762
-
763
- try {
764
- node.parentNode.removeChild(node);
765
- } catch (error) {
766
- node.outerHTML = emptyHTML;
767
- }
768
- };
769
- /**
770
- * _removeAttribute
771
- *
772
- * @param {String} name an Attribute name
773
- * @param {Node} node a DOM node
774
- */
775
729
 
730
+ if (ALLOWED_TAGS.table) {
731
+ addToSet(ALLOWED_TAGS, ['tbody']);
732
+ } // Prevent further manipulation of configuration.
733
+ // Not available in IE8, Safari 5, etc.
776
734
 
777
- var _removeAttribute = function _removeAttribute(name, node) {
778
- try {
779
- DOMPurify.removed.push({
780
- attribute: node.getAttributeNode(name),
781
- from: node
782
- });
783
- } catch (error) {
784
- DOMPurify.removed.push({
785
- attribute: null,
786
- from: node
787
- });
788
- }
789
735
 
790
- node.removeAttribute(name);
791
- };
792
- /**
793
- * _initDocument
794
- *
795
- * @param {String} dirty a string of dirty markup
796
- * @return {Document} a DOM, filled with the dirty markup
797
- */
736
+ if (freeze) {
737
+ freeze(cfg);
738
+ }
798
739
 
740
+ CONFIG = cfg;
741
+ };
742
+ /**
743
+ * _forceRemove
744
+ *
745
+ * @param {Node} node a DOM node
746
+ */
799
747
 
800
- var _initDocument = function _initDocument(dirty) {
801
- /* Create a HTML document */
802
- var doc = void 0;
803
- var leadingWhitespace = void 0;
804
748
 
805
- if (FORCE_BODY) {
806
- dirty = '<remove></remove>' + dirty;
807
- } else {
808
- /* If FORCE_BODY isn't used, leading whitespace needs to be preserved manually */
809
- var matches = dirty.match(/^[\s]+/);
810
- leadingWhitespace = matches && matches[0];
749
+ var _forceRemove = function _forceRemove(node) {
750
+ DOMPurify.removed.push({
751
+ element: node
752
+ });
811
753
 
812
- if (leadingWhitespace) {
813
- dirty = dirty.slice(leadingWhitespace.length);
814
- }
815
- }
816
- /* Use DOMParser to workaround Firefox bug (see comment below) */
754
+ try {
755
+ node.parentNode.removeChild(node);
756
+ } catch (error) {
757
+ node.outerHTML = emptyHTML;
758
+ }
759
+ };
760
+ /**
761
+ * _removeAttribute
762
+ *
763
+ * @param {String} name an Attribute name
764
+ * @param {Node} node a DOM node
765
+ */
817
766
 
818
767
 
819
- if (useDOMParser) {
820
- try {
821
- doc = new DOMParser().parseFromString(dirty, 'text/html');
822
- } catch (error) {}
823
- }
824
- /* Remove title to fix a mXSS bug in older MS Edge */
768
+ var _removeAttribute = function _removeAttribute(name, node) {
769
+ try {
770
+ DOMPurify.removed.push({
771
+ attribute: node.getAttributeNode(name),
772
+ from: node
773
+ });
774
+ } catch (error) {
775
+ DOMPurify.removed.push({
776
+ attribute: null,
777
+ from: node
778
+ });
779
+ }
825
780
 
781
+ node.removeAttribute(name);
782
+ };
783
+ /**
784
+ * _initDocument
785
+ *
786
+ * @param {String} dirty a string of dirty markup
787
+ * @return {Document} a DOM, filled with the dirty markup
788
+ */
826
789
 
827
- if (removeTitle) {
828
- addToSet(FORBID_TAGS, ['title']);
829
- }
830
- /* Otherwise use createHTMLDocument, because DOMParser is unsafe in
831
- Safari (see comment below) */
832
790
 
791
+ var _initDocument = function _initDocument(dirty) {
792
+ /* Create a HTML document */
793
+ var doc = void 0;
794
+ var leadingWhitespace = void 0;
833
795
 
834
- if (!doc || !doc.documentElement) {
835
- doc = implementation.createHTMLDocument('');
836
- var _doc = doc,
837
- body = _doc.body;
838
- body.parentNode.removeChild(body.parentNode.firstElementChild);
839
- body.outerHTML = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;
840
- }
796
+ if (FORCE_BODY) {
797
+ dirty = '<remove></remove>' + dirty;
798
+ } else {
799
+ /* If FORCE_BODY isn't used, leading whitespace needs to be preserved manually */
800
+ var matches = dirty.match(/^[\s]+/);
801
+ leadingWhitespace = matches && matches[0];
841
802
 
842
803
  if (leadingWhitespace) {
843
- doc.body.insertBefore(document.createTextNode(leadingWhitespace), doc.body.childNodes[0] || null);
804
+ dirty = dirty.slice(leadingWhitespace.length);
844
805
  }
845
- /* Work on whole document or just its body */
846
-
847
-
848
- return getElementsByTagName.call(doc, WHOLE_DOCUMENT ? 'html' : 'body')[0];
849
- }; // Firefox uses a different parser for innerHTML rather than
850
- // DOMParser (see https://bugzilla.mozilla.org/show_bug.cgi?id=1205631)
851
- // which means that you *must* use DOMParser, otherwise the output may
852
- // not be safe if used in a document.write context later.
853
- //
854
- // So we feature detect the Firefox bug and use the DOMParser if necessary.
855
- //
856
- // MS Edge, in older versions, is affected by an mXSS behavior. The second
857
- // check tests for the behavior and fixes it if necessary.
858
-
806
+ }
807
+ /* Use DOMParser to workaround Firefox bug (see comment below) */
859
808
 
860
- if (DOMPurify.isSupported) {
861
- (function () {
862
- try {
863
- var doc = _initDocument('<svg><p><style><img src="</style><img src=x onerror=1//">');
864
809
 
865
- if (doc.querySelector('svg img')) {
866
- useDOMParser = true;
867
- }
868
- } catch (error) {}
869
- })();
810
+ if (useDOMParser) {
811
+ try {
812
+ doc = new DOMParser().parseFromString(dirty, 'text/html');
813
+ } catch (error) {}
814
+ }
815
+ /* Remove title to fix a mXSS bug in older MS Edge */
870
816
 
871
- (function () {
872
- try {
873
- var doc = _initDocument('<x/><title>&lt;/title&gt;&lt;img&gt;');
874
817
 
875
- if (doc.querySelector('title').innerHTML.match(/<\/title/)) {
876
- removeTitle = true;
877
- }
878
- } catch (error) {}
879
- })();
818
+ if (removeTitle) {
819
+ addToSet(FORBID_TAGS, ['title']);
880
820
  }
881
- /**
882
- * _createIterator
883
- *
884
- * @param {Document} root document/fragment to create iterator for
885
- * @return {Iterator} iterator instance
886
- */
821
+ /* Otherwise use createHTMLDocument, because DOMParser is unsafe in
822
+ Safari (see comment below) */
887
823
 
888
824
 
889
- var _createIterator = function _createIterator(root) {
890
- return createNodeIterator.call(root.ownerDocument || root, root, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT, function () {
891
- return NodeFilter.FILTER_ACCEPT;
892
- }, false);
893
- };
894
- /**
895
- * _isClobbered
896
- *
897
- * @param {Node} elm element to check for clobbering attacks
898
- * @return {Boolean} true if clobbered, false if safe
899
- */
825
+ if (!doc || !doc.documentElement) {
826
+ doc = implementation.createHTMLDocument('');
827
+ var _doc = doc,
828
+ body = _doc.body;
829
+ body.parentNode.removeChild(body.parentNode.firstElementChild);
830
+ body.outerHTML = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;
831
+ }
900
832
 
833
+ if (leadingWhitespace) {
834
+ doc.body.insertBefore(document.createTextNode(leadingWhitespace), doc.body.childNodes[0] || null);
835
+ }
836
+ /* Work on whole document or just its body */
901
837
 
902
- var _isClobbered = function _isClobbered(elm) {
903
- if (elm instanceof Text || elm instanceof Comment) {
904
- return false;
905
- }
906
838
 
907
- if (typeof elm.nodeName !== 'string' || typeof elm.textContent !== 'string' || typeof elm.removeChild !== 'function' || !(elm.attributes instanceof NamedNodeMap) || typeof elm.removeAttribute !== 'function' || typeof elm.setAttribute !== 'function') {
908
- return true;
909
- }
839
+ return getElementsByTagName.call(doc, WHOLE_DOCUMENT ? 'html' : 'body')[0];
840
+ }; // Firefox uses a different parser for innerHTML rather than
841
+ // DOMParser (see https://bugzilla.mozilla.org/show_bug.cgi?id=1205631)
842
+ // which means that you *must* use DOMParser, otherwise the output may
843
+ // not be safe if used in a document.write context later.
844
+ //
845
+ // So we feature detect the Firefox bug and use the DOMParser if necessary.
846
+ //
847
+ // MS Edge, in older versions, is affected by an mXSS behavior. The second
848
+ // check tests for the behavior and fixes it if necessary.
910
849
 
911
- return false;
912
- };
913
- /**
914
- * _isNode
915
- *
916
- * @param {Node} obj object to check whether it's a DOM node
917
- * @return {Boolean} true is object is a DOM node
918
- */
919
850
 
851
+ if (DOMPurify.isSupported) {
852
+ (function () {
853
+ try {
854
+ var doc = _initDocument('<svg><p><style><img src="</style><img src=x onerror=1//">');
920
855
 
921
- var _isNode = function _isNode(obj) {
922
- return (typeof Node === 'undefined' ? 'undefined' : _typeof(Node)) === 'object' ? obj instanceof Node : obj && (typeof obj === 'undefined' ? 'undefined' : _typeof(obj)) === 'object' && typeof obj.nodeType === 'number' && typeof obj.nodeName === 'string';
923
- };
924
- /**
925
- * _executeHook
926
- * Execute user configurable hooks
927
- *
928
- * @param {String} entryPoint Name of the hook's entry point
929
- * @param {Node} currentNode node to work on with the hook
930
- * @param {Object} data additional hook parameters
931
- */
856
+ if (doc.querySelector('svg img')) {
857
+ useDOMParser = true;
858
+ }
859
+ } catch (error) {}
860
+ })();
932
861
 
862
+ (function () {
863
+ try {
864
+ var doc = _initDocument('<x/><title>&lt;/title&gt;&lt;img&gt;');
933
865
 
934
- var _executeHook = function _executeHook(entryPoint, currentNode, data) {
935
- if (!hooks[entryPoint]) {
936
- return;
937
- }
866
+ if (doc.querySelector('title').innerHTML.match(/<\/title/)) {
867
+ removeTitle = true;
868
+ }
869
+ } catch (error) {}
870
+ })();
871
+ }
872
+ /**
873
+ * _createIterator
874
+ *
875
+ * @param {Document} root document/fragment to create iterator for
876
+ * @return {Iterator} iterator instance
877
+ */
938
878
 
939
- hooks[entryPoint].forEach(function (hook) {
940
- hook.call(DOMPurify, currentNode, data, CONFIG);
941
- });
942
- };
943
- /**
944
- * _sanitizeElements
945
- *
946
- * @protect nodeName
947
- * @protect textContent
948
- * @protect removeChild
949
- *
950
- * @param {Node} currentNode to check for permission to exist
951
- * @return {Boolean} true if node was killed, false if left alive
952
- */
953
- // eslint-disable-next-line complexity
954
879
 
880
+ var _createIterator = function _createIterator(root) {
881
+ return createNodeIterator.call(root.ownerDocument || root, root, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT, function () {
882
+ return NodeFilter.FILTER_ACCEPT;
883
+ }, false);
884
+ };
885
+ /**
886
+ * _isClobbered
887
+ *
888
+ * @param {Node} elm element to check for clobbering attacks
889
+ * @return {Boolean} true if clobbered, false if safe
890
+ */
955
891
 
956
- var _sanitizeElements = function _sanitizeElements(currentNode) {
957
- var content = void 0;
958
- /* Execute a hook if present */
959
892
 
960
- _executeHook('beforeSanitizeElements', currentNode, null);
961
- /* Check if element is clobbered or can clobber */
893
+ var _isClobbered = function _isClobbered(elm) {
894
+ if (elm instanceof Text || elm instanceof Comment) {
895
+ return false;
896
+ }
962
897
 
898
+ if (typeof elm.nodeName !== 'string' || typeof elm.textContent !== 'string' || typeof elm.removeChild !== 'function' || !(elm.attributes instanceof NamedNodeMap) || typeof elm.removeAttribute !== 'function' || typeof elm.setAttribute !== 'function') {
899
+ return true;
900
+ }
963
901
 
964
- if (_isClobbered(currentNode)) {
965
- _forceRemove(currentNode);
902
+ return false;
903
+ };
904
+ /**
905
+ * _isNode
906
+ *
907
+ * @param {Node} obj object to check whether it's a DOM node
908
+ * @return {Boolean} true is object is a DOM node
909
+ */
966
910
 
967
- return true;
968
- }
969
- /* Now let's check the element's type and name */
970
911
 
912
+ var _isNode = function _isNode(obj) {
913
+ return (typeof Node === 'undefined' ? 'undefined' : _typeof$1(Node)) === 'object' ? obj instanceof Node : obj && (typeof obj === 'undefined' ? 'undefined' : _typeof$1(obj)) === 'object' && typeof obj.nodeType === 'number' && typeof obj.nodeName === 'string';
914
+ };
915
+ /**
916
+ * _executeHook
917
+ * Execute user configurable hooks
918
+ *
919
+ * @param {String} entryPoint Name of the hook's entry point
920
+ * @param {Node} currentNode node to work on with the hook
921
+ * @param {Object} data additional hook parameters
922
+ */
971
923
 
972
- var tagName = currentNode.nodeName.toLowerCase();
973
- /* Execute a hook if present */
974
924
 
975
- _executeHook('uponSanitizeElement', currentNode, {
976
- tagName: tagName,
977
- allowedTags: ALLOWED_TAGS
978
- });
979
- /* Remove element if anything forbids its presence */
925
+ var _executeHook = function _executeHook(entryPoint, currentNode, data) {
926
+ if (!hooks[entryPoint]) {
927
+ return;
928
+ }
980
929
 
930
+ hooks[entryPoint].forEach(function (hook) {
931
+ hook.call(DOMPurify, currentNode, data, CONFIG);
932
+ });
933
+ };
934
+ /**
935
+ * _sanitizeElements
936
+ *
937
+ * @protect nodeName
938
+ * @protect textContent
939
+ * @protect removeChild
940
+ *
941
+ * @param {Node} currentNode to check for permission to exist
942
+ * @return {Boolean} true if node was killed, false if left alive
943
+ */
944
+ // eslint-disable-next-line complexity
981
945
 
982
- if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
983
- /* Keep content except for black-listed elements */
984
- if (KEEP_CONTENT && !FORBID_CONTENTS[tagName] && typeof currentNode.insertAdjacentHTML === 'function') {
985
- try {
986
- var htmlToInsert = currentNode.innerHTML;
987
- currentNode.insertAdjacentHTML('AfterEnd', trustedTypesPolicy ? trustedTypesPolicy.createHTML(htmlToInsert) : htmlToInsert);
988
- } catch (error) {}
989
- }
990
946
 
991
- _forceRemove(currentNode);
947
+ var _sanitizeElements = function _sanitizeElements(currentNode) {
948
+ var content = void 0;
949
+ /* Execute a hook if present */
992
950
 
993
- return true;
994
- }
995
- /* Remove in case a noscript/noembed XSS is suspected */
951
+ _executeHook('beforeSanitizeElements', currentNode, null);
952
+ /* Check if element is clobbered or can clobber */
996
953
 
997
954
 
998
- if (tagName === 'noscript' && currentNode.innerHTML.match(/<\/noscript/i)) {
999
- _forceRemove(currentNode);
955
+ if (_isClobbered(currentNode)) {
956
+ _forceRemove(currentNode);
1000
957
 
1001
- return true;
1002
- }
958
+ return true;
959
+ }
960
+ /* Now let's check the element's type and name */
1003
961
 
1004
- if (tagName === 'noembed' && currentNode.innerHTML.match(/<\/noembed/i)) {
1005
- _forceRemove(currentNode);
1006
962
 
1007
- return true;
1008
- }
1009
- /* Convert markup to cover jQuery behavior */
963
+ var tagName = currentNode.nodeName.toLowerCase();
964
+ /* Execute a hook if present */
1010
965
 
966
+ _executeHook('uponSanitizeElement', currentNode, {
967
+ tagName: tagName,
968
+ allowedTags: ALLOWED_TAGS
969
+ });
970
+ /* Remove element if anything forbids its presence */
1011
971
 
1012
- if (SAFE_FOR_JQUERY && !currentNode.firstElementChild && (!currentNode.content || !currentNode.content.firstElementChild) && /</g.test(currentNode.textContent)) {
1013
- DOMPurify.removed.push({
1014
- element: currentNode.cloneNode()
1015
- });
1016
972
 
1017
- if (currentNode.innerHTML) {
1018
- currentNode.innerHTML = currentNode.innerHTML.replace(/</g, '&lt;');
1019
- } else {
1020
- currentNode.innerHTML = currentNode.textContent.replace(/</g, '&lt;');
1021
- }
973
+ if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
974
+ /* Keep content except for black-listed elements */
975
+ if (KEEP_CONTENT && !FORBID_CONTENTS[tagName] && typeof currentNode.insertAdjacentHTML === 'function') {
976
+ try {
977
+ var htmlToInsert = currentNode.innerHTML;
978
+ currentNode.insertAdjacentHTML('AfterEnd', trustedTypesPolicy ? trustedTypesPolicy.createHTML(htmlToInsert) : htmlToInsert);
979
+ } catch (error) {}
1022
980
  }
1023
- /* Sanitize element content to be template-safe */
1024
981
 
982
+ _forceRemove(currentNode);
1025
983
 
1026
- if (SAFE_FOR_TEMPLATES && currentNode.nodeType === 3) {
1027
- /* Get the element's text content */
1028
- content = currentNode.textContent;
1029
- content = content.replace(MUSTACHE_EXPR$$1, ' ');
1030
- content = content.replace(ERB_EXPR$$1, ' ');
984
+ return true;
985
+ }
986
+ /* Remove in case a noscript/noembed XSS is suspected */
1031
987
 
1032
- if (currentNode.textContent !== content) {
1033
- DOMPurify.removed.push({
1034
- element: currentNode.cloneNode()
1035
- });
1036
- currentNode.textContent = content;
1037
- }
1038
- }
1039
- /* Execute a hook if present */
1040
988
 
989
+ if (tagName === 'noscript' && currentNode.innerHTML.match(/<\/noscript/i)) {
990
+ _forceRemove(currentNode);
1041
991
 
1042
- _executeHook('afterSanitizeElements', currentNode, null);
992
+ return true;
993
+ }
1043
994
 
1044
- return false;
1045
- };
1046
- /**
1047
- * _isValidAttribute
1048
- *
1049
- * @param {string} lcTag Lowercase tag name of containing element.
1050
- * @param {string} lcName Lowercase attribute name.
1051
- * @param {string} value Attribute value.
1052
- * @return {Boolean} Returns true if `value` is valid, otherwise false.
1053
- */
1054
- // eslint-disable-next-line complexity
995
+ if (tagName === 'noembed' && currentNode.innerHTML.match(/<\/noembed/i)) {
996
+ _forceRemove(currentNode);
1055
997
 
998
+ return true;
999
+ }
1000
+ /* Convert markup to cover jQuery behavior */
1056
1001
 
1057
- var _isValidAttribute = function _isValidAttribute(lcTag, lcName, value) {
1058
- /* Make sure attribute cannot clobber */
1059
- if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in document || value in formElement)) {
1060
- return false;
1061
- }
1062
- /* Allow valid data-* attributes: At least one character after "-"
1063
- (https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes)
1064
- XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804)
1065
- We don't need to check the value; it's always URI safe. */
1066
1002
 
1003
+ if (SAFE_FOR_JQUERY && !currentNode.firstElementChild && (!currentNode.content || !currentNode.content.firstElementChild) && /</g.test(currentNode.textContent)) {
1004
+ DOMPurify.removed.push({
1005
+ element: currentNode.cloneNode()
1006
+ });
1067
1007
 
1068
- if (ALLOW_DATA_ATTR && DATA_ATTR$$1.test(lcName)) ; else if (ALLOW_ARIA_ATTR && ARIA_ATTR$$1.test(lcName)) ; else if (!ALLOWED_ATTR[lcName] || FORBID_ATTR[lcName]) {
1069
- return false;
1070
- /* Check value is safe. First, is attr inert? If so, is safe */
1071
- } else if (URI_SAFE_ATTRIBUTES[lcName]) ; else if (IS_ALLOWED_URI$$1.test(value.replace(ATTR_WHITESPACE$$1, ''))) ; else if ((lcName === 'src' || lcName === 'xlink:href') && lcTag !== 'script' && value.indexOf('data:') === 0 && DATA_URI_TAGS[lcTag]) ; else if (ALLOW_UNKNOWN_PROTOCOLS && !IS_SCRIPT_OR_DATA$$1.test(value.replace(ATTR_WHITESPACE$$1, ''))) ; else if (!value) ; else {
1072
- return false;
1008
+ if (currentNode.innerHTML) {
1009
+ currentNode.innerHTML = currentNode.innerHTML.replace(/</g, '&lt;');
1010
+ } else {
1011
+ currentNode.innerHTML = currentNode.textContent.replace(/</g, '&lt;');
1073
1012
  }
1013
+ }
1014
+ /* Sanitize element content to be template-safe */
1074
1015
 
1075
- return true;
1076
- };
1077
- /**
1078
- * _sanitizeAttributes
1079
- *
1080
- * @protect attributes
1081
- * @protect nodeName
1082
- * @protect removeAttribute
1083
- * @protect setAttribute
1084
- *
1085
- * @param {Node} currentNode to sanitize
1086
- */
1087
-
1088
-
1089
- var _sanitizeAttributes = function _sanitizeAttributes(currentNode) {
1090
- var attr = void 0;
1091
- var value = void 0;
1092
- var lcName = void 0;
1093
- var idAttr = void 0;
1094
- var l = void 0;
1095
- /* Execute a hook if present */
1096
-
1097
- _executeHook('beforeSanitizeAttributes', currentNode, null);
1098
1016
 
1099
- var attributes = currentNode.attributes;
1100
- /* Check if we have attributes; if not we might have a text node */
1017
+ if (SAFE_FOR_TEMPLATES && currentNode.nodeType === 3) {
1018
+ /* Get the element's text content */
1019
+ content = currentNode.textContent;
1020
+ content = content.replace(MUSTACHE_EXPR$$1, ' ');
1021
+ content = content.replace(ERB_EXPR$$1, ' ');
1101
1022
 
1102
- if (!attributes) {
1103
- return;
1023
+ if (currentNode.textContent !== content) {
1024
+ DOMPurify.removed.push({
1025
+ element: currentNode.cloneNode()
1026
+ });
1027
+ currentNode.textContent = content;
1104
1028
  }
1029
+ }
1030
+ /* Execute a hook if present */
1105
1031
 
1106
- var hookEvent = {
1107
- attrName: '',
1108
- attrValue: '',
1109
- keepAttr: true,
1110
- allowedAttributes: ALLOWED_ATTR
1111
- };
1112
- l = attributes.length;
1113
- /* Go backwards over all attributes; safely remove bad ones */
1114
-
1115
- while (l--) {
1116
- attr = attributes[l];
1117
- var _attr = attr,
1118
- name = _attr.name,
1119
- namespaceURI = _attr.namespaceURI;
1120
- value = attr.value.trim();
1121
- lcName = name.toLowerCase();
1122
- /* Execute a hook if present */
1123
-
1124
- hookEvent.attrName = lcName;
1125
- hookEvent.attrValue = value;
1126
- hookEvent.keepAttr = true;
1127
-
1128
- _executeHook('uponSanitizeAttribute', currentNode, hookEvent);
1129
-
1130
- value = hookEvent.attrValue;
1131
- /* Remove attribute */
1132
- // Safari (iOS + Mac), last tested v8.0.5, crashes if you try to
1133
- // remove a "name" attribute from an <img> tag that has an "id"
1134
- // attribute at the time.
1135
-
1136
- if (lcName === 'name' && currentNode.nodeName === 'IMG' && attributes.id) {
1137
- idAttr = attributes.id;
1138
- attributes = apply(arraySlice, attributes, []);
1139
-
1140
- _removeAttribute('id', currentNode);
1141
-
1142
- _removeAttribute(name, currentNode);
1143
-
1144
- if (attributes.indexOf(idAttr) > l) {
1145
- currentNode.setAttribute('id', idAttr.value);
1146
- }
1147
- } else if ( // This works around a bug in Safari, where input[type=file]
1148
- // cannot be dynamically set after type has been removed
1149
- currentNode.nodeName === 'INPUT' && lcName === 'type' && value === 'file' && hookEvent.keepAttr && (ALLOWED_ATTR[lcName] || !FORBID_ATTR[lcName])) {
1150
- continue;
1151
- } else {
1152
- // This avoids a crash in Safari v9.0 with double-ids.
1153
- // The trick is to first set the id to be empty and then to
1154
- // remove the attribute
1155
- if (name === 'id') {
1156
- currentNode.setAttribute(name, '');
1157
- }
1158
1032
 
1159
- _removeAttribute(name, currentNode);
1160
- }
1161
- /* Did the hooks approve of the attribute? */
1033
+ _executeHook('afterSanitizeElements', currentNode, null);
1162
1034
 
1035
+ return false;
1036
+ };
1037
+ /**
1038
+ * _isValidAttribute
1039
+ *
1040
+ * @param {string} lcTag Lowercase tag name of containing element.
1041
+ * @param {string} lcName Lowercase attribute name.
1042
+ * @param {string} value Attribute value.
1043
+ * @return {Boolean} Returns true if `value` is valid, otherwise false.
1044
+ */
1045
+ // eslint-disable-next-line complexity
1163
1046
 
1164
- if (!hookEvent.keepAttr) {
1165
- continue;
1166
- }
1167
- /* Sanitize attribute content to be template-safe */
1168
1047
 
1048
+ var _isValidAttribute = function _isValidAttribute(lcTag, lcName, value) {
1049
+ /* Make sure attribute cannot clobber */
1050
+ if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in document || value in formElement)) {
1051
+ return false;
1052
+ }
1053
+ /* Allow valid data-* attributes: At least one character after "-"
1054
+ (https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes)
1055
+ XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804)
1056
+ We don't need to check the value; it's always URI safe. */
1169
1057
 
1170
- if (SAFE_FOR_TEMPLATES) {
1171
- value = value.replace(MUSTACHE_EXPR$$1, ' ');
1172
- value = value.replace(ERB_EXPR$$1, ' ');
1173
- }
1174
- /* Is `value` valid for this attribute? */
1175
1058
 
1059
+ if (ALLOW_DATA_ATTR && DATA_ATTR$$1.test(lcName)) ; else if (ALLOW_ARIA_ATTR && ARIA_ATTR$$1.test(lcName)) ; else if (!ALLOWED_ATTR[lcName] || FORBID_ATTR[lcName]) {
1060
+ return false;
1061
+ /* Check value is safe. First, is attr inert? If so, is safe */
1062
+ } else if (URI_SAFE_ATTRIBUTES[lcName]) ; else if (IS_ALLOWED_URI$$1.test(value.replace(ATTR_WHITESPACE$$1, ''))) ; else if ((lcName === 'src' || lcName === 'xlink:href') && lcTag !== 'script' && value.indexOf('data:') === 0 && DATA_URI_TAGS[lcTag]) ; else if (ALLOW_UNKNOWN_PROTOCOLS && !IS_SCRIPT_OR_DATA$$1.test(value.replace(ATTR_WHITESPACE$$1, ''))) ; else if (!value) ; else {
1063
+ return false;
1064
+ }
1176
1065
 
1177
- var lcTag = currentNode.nodeName.toLowerCase();
1066
+ return true;
1067
+ };
1068
+ /**
1069
+ * _sanitizeAttributes
1070
+ *
1071
+ * @protect attributes
1072
+ * @protect nodeName
1073
+ * @protect removeAttribute
1074
+ * @protect setAttribute
1075
+ *
1076
+ * @param {Node} currentNode to sanitize
1077
+ */
1178
1078
 
1179
- if (!_isValidAttribute(lcTag, lcName, value)) {
1180
- continue;
1181
- }
1182
- /* Handle invalid data-* attribute set by try-catching it */
1183
1079
 
1080
+ var _sanitizeAttributes = function _sanitizeAttributes(currentNode) {
1081
+ var attr = void 0;
1082
+ var value = void 0;
1083
+ var lcName = void 0;
1084
+ var idAttr = void 0;
1085
+ var l = void 0;
1086
+ /* Execute a hook if present */
1184
1087
 
1185
- try {
1186
- if (namespaceURI) {
1187
- currentNode.setAttributeNS(namespaceURI, name, value);
1188
- } else {
1189
- /* Fallback to setAttribute() for browser-unrecognized namespaces e.g. "x-schema". */
1190
- currentNode.setAttribute(name, value);
1191
- }
1088
+ _executeHook('beforeSanitizeAttributes', currentNode, null);
1192
1089
 
1193
- DOMPurify.removed.pop();
1194
- } catch (error) {}
1195
- }
1196
- /* Execute a hook if present */
1090
+ var attributes = currentNode.attributes;
1091
+ /* Check if we have attributes; if not we might have a text node */
1197
1092
 
1093
+ if (!attributes) {
1094
+ return;
1095
+ }
1198
1096
 
1199
- _executeHook('afterSanitizeAttributes', currentNode, null);
1097
+ var hookEvent = {
1098
+ attrName: '',
1099
+ attrValue: '',
1100
+ keepAttr: true,
1101
+ allowedAttributes: ALLOWED_ATTR
1200
1102
  };
1201
- /**
1202
- * _sanitizeShadowDOM
1203
- *
1204
- * @param {DocumentFragment} fragment to iterate over recursively
1205
- */
1206
-
1103
+ l = attributes.length;
1104
+ /* Go backwards over all attributes; safely remove bad ones */
1207
1105
 
1208
- var _sanitizeShadowDOM = function _sanitizeShadowDOM(fragment) {
1209
- var shadowNode = void 0;
1210
-
1211
- var shadowIterator = _createIterator(fragment);
1106
+ while (l--) {
1107
+ attr = attributes[l];
1108
+ var _attr = attr,
1109
+ name = _attr.name,
1110
+ namespaceURI = _attr.namespaceURI;
1111
+ value = attr.value.trim();
1112
+ lcName = name.toLowerCase();
1212
1113
  /* Execute a hook if present */
1213
1114
 
1115
+ hookEvent.attrName = lcName;
1116
+ hookEvent.attrValue = value;
1117
+ hookEvent.keepAttr = true;
1214
1118
 
1215
- _executeHook('beforeSanitizeShadowDOM', fragment, null);
1119
+ _executeHook('uponSanitizeAttribute', currentNode, hookEvent);
1216
1120
 
1217
- while (shadowNode = shadowIterator.nextNode()) {
1218
- /* Execute a hook if present */
1219
- _executeHook('uponSanitizeShadowNode', shadowNode, null);
1220
- /* Sanitize tags and elements */
1121
+ value = hookEvent.attrValue;
1122
+ /* Remove attribute */
1123
+ // Safari (iOS + Mac), last tested v8.0.5, crashes if you try to
1124
+ // remove a "name" attribute from an <img> tag that has an "id"
1125
+ // attribute at the time.
1221
1126
 
1127
+ if (lcName === 'name' && currentNode.nodeName === 'IMG' && attributes.id) {
1128
+ idAttr = attributes.id;
1129
+ attributes = apply(arraySlice, attributes, []);
1222
1130
 
1223
- if (_sanitizeElements(shadowNode)) {
1224
- continue;
1225
- }
1226
- /* Deep shadow DOM detected */
1131
+ _removeAttribute('id', currentNode);
1227
1132
 
1133
+ _removeAttribute(name, currentNode);
1228
1134
 
1229
- if (shadowNode.content instanceof DocumentFragment) {
1230
- _sanitizeShadowDOM(shadowNode.content);
1135
+ if (attributes.indexOf(idAttr) > l) {
1136
+ currentNode.setAttribute('id', idAttr.value);
1137
+ }
1138
+ } else if ( // This works around a bug in Safari, where input[type=file]
1139
+ // cannot be dynamically set after type has been removed
1140
+ currentNode.nodeName === 'INPUT' && lcName === 'type' && value === 'file' && hookEvent.keepAttr && (ALLOWED_ATTR[lcName] || !FORBID_ATTR[lcName])) {
1141
+ continue;
1142
+ } else {
1143
+ // This avoids a crash in Safari v9.0 with double-ids.
1144
+ // The trick is to first set the id to be empty and then to
1145
+ // remove the attribute
1146
+ if (name === 'id') {
1147
+ currentNode.setAttribute(name, '');
1231
1148
  }
1232
- /* Check attributes, sanitize if necessary */
1149
+
1150
+ _removeAttribute(name, currentNode);
1151
+ }
1152
+ /* Did the hooks approve of the attribute? */
1233
1153
 
1234
1154
 
1235
- _sanitizeAttributes(shadowNode);
1155
+ if (!hookEvent.keepAttr) {
1156
+ continue;
1236
1157
  }
1237
- /* Execute a hook if present */
1158
+ /* Sanitize attribute content to be template-safe */
1238
1159
 
1239
1160
 
1240
- _executeHook('afterSanitizeShadowDOM', fragment, null);
1241
- };
1242
- /**
1243
- * Sanitize
1244
- * Public method providing core sanitation functionality
1245
- *
1246
- * @param {String|Node} dirty string or DOM node
1247
- * @param {Object} configuration object
1248
- */
1249
- // eslint-disable-next-line complexity
1161
+ if (SAFE_FOR_TEMPLATES) {
1162
+ value = value.replace(MUSTACHE_EXPR$$1, ' ');
1163
+ value = value.replace(ERB_EXPR$$1, ' ');
1164
+ }
1165
+ /* Is `value` valid for this attribute? */
1250
1166
 
1251
1167
 
1252
- DOMPurify.sanitize = function (dirty, cfg) {
1253
- var body = void 0;
1254
- var importedNode = void 0;
1255
- var currentNode = void 0;
1256
- var oldNode = void 0;
1257
- var returnNode = void 0;
1258
- /* Make sure we have a string to sanitize.
1259
- DO NOT return early, as this will return the wrong type if
1260
- the user has requested a DOM object rather than a string */
1168
+ var lcTag = currentNode.nodeName.toLowerCase();
1261
1169
 
1262
- if (!dirty) {
1263
- dirty = '<!-->';
1170
+ if (!_isValidAttribute(lcTag, lcName, value)) {
1171
+ continue;
1264
1172
  }
1265
- /* Stringify, in case dirty is an object */
1173
+ /* Handle invalid data-* attribute set by try-catching it */
1266
1174
 
1267
1175
 
1268
- if (typeof dirty !== 'string' && !_isNode(dirty)) {
1269
- // eslint-disable-next-line no-negated-condition
1270
- if (typeof dirty.toString !== 'function') {
1271
- throw new TypeError('toString is not a function');
1176
+ try {
1177
+ if (namespaceURI) {
1178
+ currentNode.setAttributeNS(namespaceURI, name, value);
1272
1179
  } else {
1273
- dirty = dirty.toString();
1274
-
1275
- if (typeof dirty !== 'string') {
1276
- throw new TypeError('dirty is not a string, aborting');
1277
- }
1180
+ /* Fallback to setAttribute() for browser-unrecognized namespaces e.g. "x-schema". */
1181
+ currentNode.setAttribute(name, value);
1278
1182
  }
1279
- }
1280
- /* Check we can run. Otherwise fall back or ignore */
1281
1183
 
1184
+ DOMPurify.removed.pop();
1185
+ } catch (error) {}
1186
+ }
1187
+ /* Execute a hook if present */
1282
1188
 
1283
- if (!DOMPurify.isSupported) {
1284
- if (_typeof(window.toStaticHTML) === 'object' || typeof window.toStaticHTML === 'function') {
1285
- if (typeof dirty === 'string') {
1286
- return window.toStaticHTML(dirty);
1287
- }
1288
1189
 
1289
- if (_isNode(dirty)) {
1290
- return window.toStaticHTML(dirty.outerHTML);
1291
- }
1292
- }
1190
+ _executeHook('afterSanitizeAttributes', currentNode, null);
1191
+ };
1192
+ /**
1193
+ * _sanitizeShadowDOM
1194
+ *
1195
+ * @param {DocumentFragment} fragment to iterate over recursively
1196
+ */
1293
1197
 
1294
- return dirty;
1295
- }
1296
- /* Assign config vars */
1297
1198
 
1199
+ var _sanitizeShadowDOM = function _sanitizeShadowDOM(fragment) {
1200
+ var shadowNode = void 0;
1298
1201
 
1299
- if (!SET_CONFIG) {
1300
- _parseConfig(cfg);
1301
- }
1302
- /* Clean up removed elements */
1202
+ var shadowIterator = _createIterator(fragment);
1203
+ /* Execute a hook if present */
1303
1204
 
1304
1205
 
1305
- DOMPurify.removed = [];
1206
+ _executeHook('beforeSanitizeShadowDOM', fragment, null);
1306
1207
 
1307
- if (IN_PLACE) ; else if (dirty instanceof Node) {
1308
- /* If dirty is a DOM element, append to an empty document to avoid
1309
- elements being stripped by the parser */
1310
- body = _initDocument('<!-->');
1311
- importedNode = body.ownerDocument.importNode(dirty, true);
1208
+ while (shadowNode = shadowIterator.nextNode()) {
1209
+ /* Execute a hook if present */
1210
+ _executeHook('uponSanitizeShadowNode', shadowNode, null);
1211
+ /* Sanitize tags and elements */
1312
1212
 
1313
- if (importedNode.nodeType === 1 && importedNode.nodeName === 'BODY') {
1314
- /* Node is already a body, use as is */
1315
- body = importedNode;
1316
- } else if (importedNode.nodeName === 'HTML') {
1317
- body = importedNode;
1318
- } else {
1319
- // eslint-disable-next-line unicorn/prefer-node-append
1320
- body.appendChild(importedNode);
1321
- }
1322
- } else {
1323
- /* Exit directly if we have nothing to do */
1324
- if (!RETURN_DOM && !SAFE_FOR_TEMPLATES && !WHOLE_DOCUMENT && dirty.indexOf('<') === -1) {
1325
- return trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;
1326
- }
1327
- /* Initialize the document to work on */
1328
1213
 
1214
+ if (_sanitizeElements(shadowNode)) {
1215
+ continue;
1216
+ }
1217
+ /* Deep shadow DOM detected */
1329
1218
 
1330
- body = _initDocument(dirty);
1331
- /* Check we have a DOM node from the data */
1332
1219
 
1333
- if (!body) {
1334
- return RETURN_DOM ? null : emptyHTML;
1335
- }
1220
+ if (shadowNode.content instanceof DocumentFragment) {
1221
+ _sanitizeShadowDOM(shadowNode.content);
1336
1222
  }
1337
- /* Remove first element node (ours) if FORCE_BODY is set */
1223
+ /* Check attributes, sanitize if necessary */
1338
1224
 
1339
1225
 
1340
- if (body && FORCE_BODY) {
1341
- _forceRemove(body.firstChild);
1342
- }
1343
- /* Get node iterator */
1226
+ _sanitizeAttributes(shadowNode);
1227
+ }
1228
+ /* Execute a hook if present */
1344
1229
 
1345
1230
 
1346
- var nodeIterator = _createIterator(IN_PLACE ? dirty : body);
1347
- /* Now start iterating over the created document */
1231
+ _executeHook('afterSanitizeShadowDOM', fragment, null);
1232
+ };
1233
+ /**
1234
+ * Sanitize
1235
+ * Public method providing core sanitation functionality
1236
+ *
1237
+ * @param {String|Node} dirty string or DOM node
1238
+ * @param {Object} configuration object
1239
+ */
1240
+ // eslint-disable-next-line complexity
1348
1241
 
1349
1242
 
1350
- while (currentNode = nodeIterator.nextNode()) {
1351
- /* Fix IE's strange behavior with manipulated textNodes #89 */
1352
- if (currentNode.nodeType === 3 && currentNode === oldNode) {
1353
- continue;
1354
- }
1355
- /* Sanitize tags and elements */
1243
+ DOMPurify.sanitize = function (dirty, cfg) {
1244
+ var body = void 0;
1245
+ var importedNode = void 0;
1246
+ var currentNode = void 0;
1247
+ var oldNode = void 0;
1248
+ var returnNode = void 0;
1249
+ /* Make sure we have a string to sanitize.
1250
+ DO NOT return early, as this will return the wrong type if
1251
+ the user has requested a DOM object rather than a string */
1356
1252
 
1253
+ if (!dirty) {
1254
+ dirty = '<!-->';
1255
+ }
1256
+ /* Stringify, in case dirty is an object */
1357
1257
 
1358
- if (_sanitizeElements(currentNode)) {
1359
- continue;
1360
- }
1361
- /* Shadow DOM detected, sanitize it */
1362
1258
 
1259
+ if (typeof dirty !== 'string' && !_isNode(dirty)) {
1260
+ // eslint-disable-next-line no-negated-condition
1261
+ if (typeof dirty.toString !== 'function') {
1262
+ throw new TypeError('toString is not a function');
1263
+ } else {
1264
+ dirty = dirty.toString();
1363
1265
 
1364
- if (currentNode.content instanceof DocumentFragment) {
1365
- _sanitizeShadowDOM(currentNode.content);
1266
+ if (typeof dirty !== 'string') {
1267
+ throw new TypeError('dirty is not a string, aborting');
1366
1268
  }
1367
- /* Check attributes, sanitize if necessary */
1269
+ }
1270
+ }
1271
+ /* Check we can run. Otherwise fall back or ignore */
1368
1272
 
1369
1273
 
1370
- _sanitizeAttributes(currentNode);
1274
+ if (!DOMPurify.isSupported) {
1275
+ if (_typeof$1(window.toStaticHTML) === 'object' || typeof window.toStaticHTML === 'function') {
1276
+ if (typeof dirty === 'string') {
1277
+ return window.toStaticHTML(dirty);
1278
+ }
1371
1279
 
1372
- oldNode = currentNode;
1280
+ if (_isNode(dirty)) {
1281
+ return window.toStaticHTML(dirty.outerHTML);
1282
+ }
1373
1283
  }
1374
1284
 
1375
- oldNode = null;
1376
- /* If we sanitized `dirty` in-place, return it. */
1377
-
1378
- if (IN_PLACE) {
1379
- return dirty;
1380
- }
1381
- /* Return sanitized string or DOM */
1285
+ return dirty;
1286
+ }
1287
+ /* Assign config vars */
1382
1288
 
1383
1289
 
1384
- if (RETURN_DOM) {
1385
- if (RETURN_DOM_FRAGMENT) {
1386
- returnNode = createDocumentFragment.call(body.ownerDocument);
1290
+ if (!SET_CONFIG) {
1291
+ _parseConfig(cfg);
1292
+ }
1293
+ /* Clean up removed elements */
1387
1294
 
1388
- while (body.firstChild) {
1389
- // eslint-disable-next-line unicorn/prefer-node-append
1390
- returnNode.appendChild(body.firstChild);
1391
- }
1392
- } else {
1393
- returnNode = body;
1394
- }
1395
1295
 
1396
- if (RETURN_DOM_IMPORT) {
1397
- /* AdoptNode() is not used because internal state is not reset
1398
- (e.g. the past names map of a HTMLFormElement), this is safe
1399
- in theory but we would rather not risk another attack vector.
1400
- The state that is cloned by importNode() is explicitly defined
1401
- by the specs. */
1402
- returnNode = importNode.call(originalDocument, returnNode, true);
1403
- }
1296
+ DOMPurify.removed = [];
1404
1297
 
1405
- return returnNode;
1298
+ if (IN_PLACE) ; else if (dirty instanceof Node) {
1299
+ /* If dirty is a DOM element, append to an empty document to avoid
1300
+ elements being stripped by the parser */
1301
+ body = _initDocument('<!-->');
1302
+ importedNode = body.ownerDocument.importNode(dirty, true);
1303
+
1304
+ if (importedNode.nodeType === 1 && importedNode.nodeName === 'BODY') {
1305
+ /* Node is already a body, use as is */
1306
+ body = importedNode;
1307
+ } else if (importedNode.nodeName === 'HTML') {
1308
+ body = importedNode;
1309
+ } else {
1310
+ // eslint-disable-next-line unicorn/prefer-node-append
1311
+ body.appendChild(importedNode);
1406
1312
  }
1313
+ } else {
1314
+ /* Exit directly if we have nothing to do */
1315
+ if (!RETURN_DOM && !SAFE_FOR_TEMPLATES && !WHOLE_DOCUMENT && dirty.indexOf('<') === -1) {
1316
+ return trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;
1317
+ }
1318
+ /* Initialize the document to work on */
1407
1319
 
1408
- var serializedHTML = WHOLE_DOCUMENT ? body.outerHTML : body.innerHTML;
1409
- /* Sanitize final string template-safe */
1410
1320
 
1411
- if (SAFE_FOR_TEMPLATES) {
1412
- serializedHTML = serializedHTML.replace(MUSTACHE_EXPR$$1, ' ');
1413
- serializedHTML = serializedHTML.replace(ERB_EXPR$$1, ' ');
1321
+ body = _initDocument(dirty);
1322
+ /* Check we have a DOM node from the data */
1323
+
1324
+ if (!body) {
1325
+ return RETURN_DOM ? null : emptyHTML;
1414
1326
  }
1327
+ }
1328
+ /* Remove first element node (ours) if FORCE_BODY is set */
1415
1329
 
1416
- return trustedTypesPolicy ? trustedTypesPolicy.createHTML(serializedHTML) : serializedHTML;
1417
- };
1418
- /**
1419
- * Public method to set the configuration once
1420
- * setConfig
1421
- *
1422
- * @param {Object} cfg configuration object
1423
- */
1424
1330
 
1331
+ if (body && FORCE_BODY) {
1332
+ _forceRemove(body.firstChild);
1333
+ }
1334
+ /* Get node iterator */
1425
1335
 
1426
- DOMPurify.setConfig = function (cfg) {
1427
- _parseConfig(cfg);
1428
1336
 
1429
- SET_CONFIG = true;
1430
- };
1431
- /**
1432
- * Public method to remove the configuration
1433
- * clearConfig
1434
- *
1435
- */
1337
+ var nodeIterator = _createIterator(IN_PLACE ? dirty : body);
1338
+ /* Now start iterating over the created document */
1436
1339
 
1437
1340
 
1438
- DOMPurify.clearConfig = function () {
1439
- CONFIG = null;
1440
- SET_CONFIG = false;
1441
- };
1442
- /**
1443
- * Public method to check if an attribute value is valid.
1444
- * Uses last set config, if any. Otherwise, uses config defaults.
1445
- * isValidAttribute
1446
- *
1447
- * @param {string} tag Tag name of containing element.
1448
- * @param {string} attr Attribute name.
1449
- * @param {string} value Attribute value.
1450
- * @return {Boolean} Returns true if `value` is valid. Otherwise, returns false.
1451
- */
1341
+ while (currentNode = nodeIterator.nextNode()) {
1342
+ /* Fix IE's strange behavior with manipulated textNodes #89 */
1343
+ if (currentNode.nodeType === 3 && currentNode === oldNode) {
1344
+ continue;
1345
+ }
1346
+ /* Sanitize tags and elements */
1452
1347
 
1453
1348
 
1454
- DOMPurify.isValidAttribute = function (tag, attr, value) {
1455
- /* Initialize shared config vars if necessary. */
1456
- if (!CONFIG) {
1457
- _parseConfig({});
1349
+ if (_sanitizeElements(currentNode)) {
1350
+ continue;
1458
1351
  }
1459
-
1460
- var lcTag = tag.toLowerCase();
1461
- var lcName = attr.toLowerCase();
1462
- return _isValidAttribute(lcTag, lcName, value);
1463
- };
1464
- /**
1465
- * AddHook
1466
- * Public method to add DOMPurify hooks
1467
- *
1468
- * @param {String} entryPoint entry point for the hook to add
1469
- * @param {Function} hookFunction function to execute
1470
- */
1352
+ /* Shadow DOM detected, sanitize it */
1471
1353
 
1472
1354
 
1473
- DOMPurify.addHook = function (entryPoint, hookFunction) {
1474
- if (typeof hookFunction !== 'function') {
1475
- return;
1355
+ if (currentNode.content instanceof DocumentFragment) {
1356
+ _sanitizeShadowDOM(currentNode.content);
1476
1357
  }
1358
+ /* Check attributes, sanitize if necessary */
1477
1359
 
1478
- hooks[entryPoint] = hooks[entryPoint] || [];
1479
- hooks[entryPoint].push(hookFunction);
1480
- };
1481
- /**
1482
- * RemoveHook
1483
- * Public method to remove a DOMPurify hook at a given entryPoint
1484
- * (pops it from the stack of hooks if more are present)
1485
- *
1486
- * @param {String} entryPoint entry point for the hook to remove
1487
- */
1488
1360
 
1361
+ _sanitizeAttributes(currentNode);
1489
1362
 
1490
- DOMPurify.removeHook = function (entryPoint) {
1491
- if (hooks[entryPoint]) {
1492
- hooks[entryPoint].pop();
1493
- }
1494
- };
1495
- /**
1496
- * RemoveHooks
1497
- * Public method to remove all DOMPurify hooks at a given entryPoint
1498
- *
1499
- * @param {String} entryPoint entry point for the hooks to remove
1500
- */
1363
+ oldNode = currentNode;
1364
+ }
1365
+
1366
+ oldNode = null;
1367
+ /* If we sanitized `dirty` in-place, return it. */
1368
+
1369
+ if (IN_PLACE) {
1370
+ return dirty;
1371
+ }
1372
+ /* Return sanitized string or DOM */
1501
1373
 
1502
1374
 
1503
- DOMPurify.removeHooks = function (entryPoint) {
1504
- if (hooks[entryPoint]) {
1505
- hooks[entryPoint] = [];
1375
+ if (RETURN_DOM) {
1376
+ if (RETURN_DOM_FRAGMENT) {
1377
+ returnNode = createDocumentFragment.call(body.ownerDocument);
1378
+
1379
+ while (body.firstChild) {
1380
+ // eslint-disable-next-line unicorn/prefer-node-append
1381
+ returnNode.appendChild(body.firstChild);
1382
+ }
1383
+ } else {
1384
+ returnNode = body;
1506
1385
  }
1507
- };
1508
- /**
1509
- * RemoveAllHooks
1510
- * Public method to remove all DOMPurify hooks
1511
- *
1512
- */
1513
1386
 
1387
+ if (RETURN_DOM_IMPORT) {
1388
+ /* AdoptNode() is not used because internal state is not reset
1389
+ (e.g. the past names map of a HTMLFormElement), this is safe
1390
+ in theory but we would rather not risk another attack vector.
1391
+ The state that is cloned by importNode() is explicitly defined
1392
+ by the specs. */
1393
+ returnNode = importNode.call(originalDocument, returnNode, true);
1394
+ }
1514
1395
 
1515
- DOMPurify.removeAllHooks = function () {
1516
- hooks = {};
1517
- };
1396
+ return returnNode;
1397
+ }
1518
1398
 
1519
- return DOMPurify;
1520
- }
1399
+ var serializedHTML = WHOLE_DOCUMENT ? body.outerHTML : body.innerHTML;
1400
+ /* Sanitize final string template-safe */
1521
1401
 
1522
- var purify = createDOMPurify();
1402
+ if (SAFE_FOR_TEMPLATES) {
1403
+ serializedHTML = serializedHTML.replace(MUSTACHE_EXPR$$1, ' ');
1404
+ serializedHTML = serializedHTML.replace(ERB_EXPR$$1, ' ');
1405
+ }
1523
1406
 
1407
+ return trustedTypesPolicy ? trustedTypesPolicy.createHTML(serializedHTML) : serializedHTML;
1408
+ };
1524
1409
  /**
1525
- * This program is free software; you can redistribute it and/or
1526
- * modify it under the terms of the GNU General Public License
1527
- * as published by the Free Software Foundation; under version 2
1528
- * of the License (non-upgradable).
1529
- *
1530
- * This program is distributed in the hope that it will be useful,
1531
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
1532
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1533
- * GNU General Public License for more details.
1410
+ * Public method to set the configuration once
1411
+ * setConfig
1534
1412
  *
1535
- * You should have received a copy of the GNU General Public License
1536
- * along with this program; if not, write to the Free Software
1537
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
1413
+ * @param {Object} cfg configuration object
1414
+ */
1415
+
1416
+
1417
+ DOMPurify.setConfig = function (cfg) {
1418
+ _parseConfig(cfg);
1419
+
1420
+ SET_CONFIG = true;
1421
+ };
1422
+ /**
1423
+ * Public method to remove the configuration
1424
+ * clearConfig
1538
1425
  *
1539
- * Copyright (c) 2017-2019 (original work) Open Assessment Technologies SA ;
1540
1426
  */
1541
1427
 
1542
- var indentStep = 15;
1543
- var defaultConfig = {
1544
- multiple: true
1428
+
1429
+ DOMPurify.clearConfig = function () {
1430
+ CONFIG = null;
1431
+ SET_CONFIG = false;
1545
1432
  };
1546
1433
  /**
1547
- * The actual CSS suffers from a limitation,
1548
- * this function is used to fix the nested indents.
1549
- * @param {jQueryElement} $list - the list element
1550
- * @param {Number} level - the nesting level
1434
+ * Public method to check if an attribute value is valid.
1435
+ * Uses last set config, if any. Otherwise, uses config defaults.
1436
+ * isValidAttribute
1437
+ *
1438
+ * @param {string} tag Tag name of containing element.
1439
+ * @param {string} attr Attribute name.
1440
+ * @param {string} value Attribute value.
1441
+ * @return {Boolean} Returns true if `value` is valid. Otherwise, returns false.
1551
1442
  */
1552
1443
 
1553
- var indentChildren = function indentChildren($list, level) {
1554
- var indent;
1555
1444
 
1556
- if ($list.length) {
1557
- indent = level * indentStep;
1558
- level++;
1559
- $list.children('li').each(function () {
1560
- var $target = $$1(this);
1561
- $target.children('a').css('padding-left', indent + 'px');
1562
- indentChildren($target.children('ul'), level);
1563
- });
1564
- $list.siblings('.more').css('padding-left', indent + 'px');
1445
+ DOMPurify.isValidAttribute = function (tag, attr, value) {
1446
+ /* Initialize shared config vars if necessary. */
1447
+ if (!CONFIG) {
1448
+ _parseConfig({});
1565
1449
  }
1450
+
1451
+ var lcTag = tag.toLowerCase();
1452
+ var lcName = attr.toLowerCase();
1453
+ return _isValidAttribute(lcTag, lcName, value);
1566
1454
  };
1567
1455
  /**
1568
- * Toggle the "more" button if the node is incomplete.
1569
- * Parse the whole tree from the given node.
1570
- * @param {jQueryElement} $node - the class node
1456
+ * AddHook
1457
+ * Public method to add DOMPurify hooks
1458
+ *
1459
+ * @param {String} entryPoint entry point for the hook to add
1460
+ * @param {Function} hookFunction function to execute
1571
1461
  */
1572
1462
 
1573
1463
 
1574
- var needMore = function needMore($node) {
1575
- var $more = $node.children('.more');
1576
- var totalCount = $node.data('count');
1577
- var instancesCount = $node.children('ul').children('.instance').length;
1578
-
1579
- if (totalCount > 0 && instancesCount > 0 && instancesCount < totalCount) {
1580
- hider.show($more);
1581
- } else {
1582
- hider.hide($more);
1464
+ DOMPurify.addHook = function (entryPoint, hookFunction) {
1465
+ if (typeof hookFunction !== 'function') {
1466
+ return;
1583
1467
  }
1584
1468
 
1585
- $node.children('ul').find('.class').each(function () {
1586
- needMore($$1(this));
1587
- });
1469
+ hooks[entryPoint] = hooks[entryPoint] || [];
1470
+ hooks[entryPoint].push(hookFunction);
1588
1471
  };
1589
1472
  /**
1590
- * Manually update the count value of a class node.
1591
- * useful when the nodes are added or removed directly.
1592
- * @param {jQueryElement} $classNode - the node to update
1593
- * @param {Number} update - the value to add to the count
1473
+ * RemoveHook
1474
+ * Public method to remove a DOMPurify hook at a given entryPoint
1475
+ * (pops it from the stack of hooks if more are present)
1476
+ *
1477
+ * @param {String} entryPoint entry point for the hook to remove
1594
1478
  */
1595
1479
 
1596
1480
 
1597
- var updateCount = function updateCount($classNode, update) {
1598
- var count = 0;
1599
-
1600
- if ($classNode && $classNode.length && $classNode.hasClass('class')) {
1601
- count = $classNode.data('count');
1602
- count += update;
1481
+ DOMPurify.removeHook = function (entryPoint) {
1482
+ if (hooks[entryPoint]) {
1483
+ hooks[entryPoint].pop();
1484
+ }
1485
+ };
1486
+ /**
1487
+ * RemoveHooks
1488
+ * Public method to remove all DOMPurify hooks at a given entryPoint
1489
+ *
1490
+ * @param {String} entryPoint entry point for the hooks to remove
1491
+ */
1603
1492
 
1604
- if (count < 0) {
1605
- count = 0;
1606
- }
1607
1493
 
1608
- $classNode.attr('data-count', count).data('count', count);
1494
+ DOMPurify.removeHooks = function (entryPoint) {
1495
+ if (hooks[entryPoint]) {
1496
+ hooks[entryPoint] = [];
1609
1497
  }
1610
1498
  };
1611
1499
  /**
1612
- * The factory that creates the resource tree component
1500
+ * RemoveAllHooks
1501
+ * Public method to remove all DOMPurify hooks
1613
1502
  *
1614
- * @param {jQueryElement} $container - where to append the component
1615
- * @param {Object} config - the component config
1616
- * @param {String} config.classUri - the root Class URI
1617
- * @param {Object[]} [config.nodes] - the nodes to preload
1618
- * @param {String} [config.icon] - the icon class to show close to the resources
1619
- * @param {Boolean} [config.multiple = true] - multiple vs unique selection
1620
- * @returns {resourceTree} the component
1621
1503
  */
1622
1504
 
1623
1505
 
1624
- function resourceTreeFactory($container, config) {
1506
+ DOMPurify.removeAllHooks = function () {
1507
+ hooks = {};
1508
+ };
1509
+
1510
+ return DOMPurify;
1511
+ }
1512
+
1513
+ var purify = createDOMPurify();
1514
+
1515
+ /**
1516
+ * This program is free software; you can redistribute it and/or
1517
+ * modify it under the terms of the GNU General Public License
1518
+ * as published by the Free Software Foundation; under version 2
1519
+ * of the License (non-upgradable).
1520
+ *
1521
+ * This program is distributed in the hope that it will be useful,
1522
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1523
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1524
+ * GNU General Public License for more details.
1525
+ *
1526
+ * You should have received a copy of the GNU General Public License
1527
+ * along with this program; if not, write to the Free Software
1528
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
1529
+ *
1530
+ * Copyright (c) 2017-2019 (original work) Open Assessment Technologies SA ;
1531
+ */
1532
+
1533
+ var indentStep = 15;
1534
+ var defaultConfig = {
1535
+ multiple: true
1536
+ };
1537
+ /**
1538
+ * The actual CSS suffers from a limitation,
1539
+ * this function is used to fix the nested indents.
1540
+ * @param {jQueryElement} $list - the list element
1541
+ * @param {Number} level - the nesting level
1542
+ */
1543
+
1544
+ var indentChildren = function indentChildren($list, level) {
1545
+ var indent;
1546
+
1547
+ if ($list.length) {
1548
+ indent = level * indentStep;
1549
+ level++;
1550
+ $list.children('li').each(function () {
1551
+ var $target = $$1(this);
1552
+ $target.children('a').css('padding-left', indent + 'px');
1553
+ indentChildren($target.children('ul'), level);
1554
+ });
1555
+ $list.siblings('.more').css('padding-left', indent + 'px');
1556
+ }
1557
+ };
1558
+ /**
1559
+ * Toggle the "more" button if the node is incomplete.
1560
+ * Parse the whole tree from the given node.
1561
+ * @param {jQueryElement} $node - the class node
1562
+ */
1563
+
1564
+
1565
+ var needMore = function needMore($node) {
1566
+ var $more = $node.children('.more');
1567
+ var totalCount = $node.data('count');
1568
+ var instancesCount = $node.children('ul').children('.instance').length;
1569
+
1570
+ if (totalCount > 0 && instancesCount > 0 && instancesCount < totalCount) {
1571
+ hider.show($more);
1572
+ } else {
1573
+ hider.hide($more);
1574
+ }
1575
+
1576
+ $node.children('ul').find('.class').each(function () {
1577
+ needMore($$1(this));
1578
+ });
1579
+ };
1580
+ /**
1581
+ * Manually update the count value of a class node.
1582
+ * useful when the nodes are added or removed directly.
1583
+ * @param {jQueryElement} $classNode - the node to update
1584
+ * @param {Number} update - the value to add to the count
1585
+ */
1586
+
1587
+
1588
+ var updateCount = function updateCount($classNode, update) {
1589
+ var count = 0;
1590
+
1591
+ if ($classNode && $classNode.length && $classNode.hasClass('class')) {
1592
+ count = $classNode.data('count');
1593
+ count += update;
1594
+
1595
+ if (count < 0) {
1596
+ count = 0;
1597
+ }
1598
+
1599
+ $classNode.attr('data-count', count).data('count', count);
1600
+ }
1601
+ };
1602
+ /**
1603
+ * The factory that creates the resource tree component
1604
+ *
1605
+ * @param {jQueryElement} $container - where to append the component
1606
+ * @param {Object} config - the component config
1607
+ * @param {String} config.classUri - the root Class URI
1608
+ * @param {Object[]} [config.nodes] - the nodes to preload
1609
+ * @param {String} [config.icon] - the icon class to show close to the resources
1610
+ * @param {Boolean} [config.multiple = true] - multiple vs unique selection
1611
+ * @returns {resourceTree} the component
1612
+ */
1613
+
1614
+
1615
+ function resourceTreeFactory($container, config) {
1616
+ /**
1617
+ * A selectable component
1618
+ * @typedef {ui/component} resourceTree
1619
+ * @augments {ui/resource/selectable}
1620
+ */
1621
+ var resourceTree = selectable(component({
1625
1622
  /**
1626
- * A selectable component
1627
- * @typedef {ui/component} resourceTree
1628
- * @augments {ui/resource/selectable}
1623
+ * Ask for a query (forward the event)
1624
+ * @param {Object} [params] - the query parameters
1625
+ * @param {String} [params.classUri] - the current node class URI
1626
+ * @param {Number} [params.offset = 0] - for paging
1627
+ * @param {Number} [params.limit] - for paging
1628
+ * @returns {resourceTree} chains
1629
+ * @fires resourceTree#query
1629
1630
  */
1630
- var resourceTree = selectable(component({
1631
- /**
1632
- * Ask for a query (forward the event)
1633
- * @param {Object} [params] - the query parameters
1634
- * @param {String} [params.classUri] - the current node class URI
1635
- * @param {Number} [params.offset = 0] - for paging
1636
- * @param {Number} [params.limit] - for paging
1637
- * @returns {resourceTree} chains
1638
- * @fires resourceTree#query
1639
- */
1640
- query: function query(params) {
1641
- if (!this.is('loading')) {
1642
- /**
1643
- * Formulate the query
1644
- * @event resourceTree#query
1645
- * @param {Object} params - see format above
1646
- */
1647
- this.trigger('query', _.defaults(params || {}, {
1648
- classUri: this.classUri
1649
- }));
1650
- }
1631
+ query: function query(params) {
1632
+ if (!this.is('loading')) {
1633
+ /**
1634
+ * Formulate the query
1635
+ * @event resourceTree#query
1636
+ * @param {Object} params - see format above
1637
+ */
1638
+ this.trigger('query', _.defaults(params || {}, {
1639
+ classUri: this.classUri
1640
+ }));
1641
+ }
1651
1642
 
1652
- return this;
1653
- },
1654
-
1655
- /**
1656
- * Update the component with the given nodes
1657
- * @param {Object[]} nodes - the tree nodes, with at least a URI as key and as property
1658
- * @param {Object} params - the query parameters
1659
- * @param {Number|false} params.updateCount - force the update of the parent class count
1660
- * @returns {resourceTree} chains
1661
- * @fires resourceTree#update
1662
- */
1663
- update: function update(nodes, params) {
1664
- var self = this;
1665
- var $root;
1666
- var $component;
1667
-
1668
- function reduceNode(acc, node) {
1669
- node.selectable = false;
1670
- node.label = purify.sanitize(node.label); //filter already added nodes or classes when loading "more"
1671
-
1672
- if (self.hasNode(node.uri) || params && params.offset > 0 && node.type === 'class' || node.type === 'class' && !node.state && !self.config.selectClass) {
1673
- return acc;
1674
- }
1643
+ return this;
1644
+ },
1675
1645
 
1676
- if (node.type === 'class' && self.config.selectClass) {
1677
- node.classUri = node.uri;
1678
- node.selectable = true;
1646
+ /**
1647
+ * Update the component with the given nodes
1648
+ * @param {Object[]} nodes - the tree nodes, with at least a URI as key and as property
1649
+ * @param {Object} params - the query parameters
1650
+ * @param {Number|false} params.updateCount - force the update of the parent class count
1651
+ * @returns {resourceTree} chains
1652
+ * @fires resourceTree#update
1653
+ */
1654
+ update: function update(nodes, params) {
1655
+ var self = this;
1656
+ var $root;
1657
+ var $component;
1679
1658
 
1680
- if (!node.state) {
1681
- node.state = 'empty';
1682
- }
1659
+ function reduceNode(acc, node) {
1660
+ node.selectable = false;
1661
+ node.label = purify.sanitize(node.label); //filter already added nodes or classes when loading "more"
1683
1662
 
1684
- self.addNode(node.uri, _.omit(node, ['count', 'children']));
1685
- }
1663
+ if (self.hasNode(node.uri) || params && params.offset > 0 && node.type === 'class' || node.type === 'class' && !node.state && !self.config.selectClass) {
1664
+ return acc;
1665
+ }
1686
1666
 
1687
- if (node.type === 'instance') {
1688
- node.selectable = true;
1689
- self.addNode(node.uri, _.omit(node, ['count', 'children']));
1690
- node.icon = config.icon;
1691
- }
1667
+ if (node.type === 'class' && self.config.selectClass) {
1668
+ node.classUri = node.uri;
1669
+ node.selectable = true;
1692
1670
 
1693
- if (node.children && node.children.length) {
1694
- node.childList = reduceNodes(node.children);
1671
+ if (!node.state) {
1672
+ node.state = 'empty';
1695
1673
  }
1696
1674
 
1697
- acc += treeNodeTpl(node);
1698
- return acc;
1675
+ self.addNode(node.uri, _.omit(node, ['count', 'children']));
1699
1676
  }
1700
1677
 
1701
- function reduceNodes(nodeList) {
1702
- return _.sortBy(nodeList, function (a, b) {
1703
- return b.label - a.label;
1704
- }).reduce(reduceNode, '');
1678
+ if (node.type === 'instance') {
1679
+ node.selectable = true;
1680
+ self.addNode(node.uri, _.omit(node, ['count', 'children']));
1681
+ node.icon = config.icon;
1705
1682
  }
1706
1683
 
1707
- if (this.is('rendered')) {
1708
- $component = this.getElement();
1684
+ if (node.children && node.children.length) {
1685
+ node.childList = reduceNodes(node.children);
1686
+ }
1709
1687
 
1710
- if (params && params.classUri) {
1711
- $root = $$1('.class[data-uri="' + params.classUri + '"]', $component);
1712
- }
1688
+ acc += treeNodeTpl(node);
1689
+ return acc;
1690
+ }
1713
1691
 
1714
- if (!$root || !$root.length) {
1715
- $root = $component;
1716
- }
1692
+ function reduceNodes(nodeList) {
1693
+ return _.sortBy(nodeList, function (a, b) {
1694
+ return b.label - a.label;
1695
+ }).reduce(reduceNode, '');
1696
+ }
1717
1697
 
1718
- if (nodes[0].uri === $root.data('uri')) {
1719
- nodes = nodes[0].children || [];
1720
- }
1698
+ if (this.is('rendered')) {
1699
+ $component = this.getElement();
1700
+
1701
+ if (params && params.classUri) {
1702
+ $root = $$1('.class[data-uri="' + params.classUri + '"]', $component);
1703
+ }
1721
1704
 
1722
- $root.children('ul').append(reduceNodes(nodes));
1705
+ if (!$root || !$root.length) {
1706
+ $root = $component;
1707
+ }
1723
1708
 
1724
- if (params && _.isNumber(params.updateCount)) {
1725
- updateCount($root, params.updateCount);
1726
- }
1709
+ if (nodes[0].uri === $root.data('uri')) {
1710
+ nodes = nodes[0].children || [];
1711
+ }
1727
1712
 
1728
- needMore($root);
1729
- indentChildren($component.children('ul'), 0);
1730
- $root.removeClass('closed').toggleClass('empty', !$root.children('ul').children('li').length);
1731
- /**
1732
- * The tree has been updated
1733
- * @event resourceTree#update
1734
- */
1713
+ $root.children('ul').append(reduceNodes(nodes));
1735
1714
 
1736
- this.trigger('update');
1715
+ if (params && _.isNumber(params.updateCount)) {
1716
+ updateCount($root, params.updateCount);
1737
1717
  }
1738
1718
 
1739
- return this;
1719
+ needMore($root);
1720
+ indentChildren($component.children('ul'), 0);
1721
+ $root.removeClass('closed').toggleClass('empty', !$root.children('ul').children('li').length);
1722
+ /**
1723
+ * The tree has been updated
1724
+ * @event resourceTree#update
1725
+ */
1726
+
1727
+ this.trigger('update');
1740
1728
  }
1741
- }, defaultConfig));
1742
- resourceTree.setTemplate(treeTpl).on('init', function () {
1743
- this.classUri = this.config.classUri;
1744
- this.setState('multiple', !!this.config.multiple);
1745
- this.render($container);
1746
- }).on('render', function () {
1747
- var self = this;
1748
- var $component = this.getElement();
1749
- /**
1750
- * Open a class node
1751
- * @param {jQueryElement} $class
1752
- */
1753
-
1754
- var openClass = function openClass($class) {
1755
- var node = self.getNode($class.data('uri'));
1756
-
1757
- if (!$class.children('ul').children('li').length) {
1758
- self.query({
1759
- classUri: $class.data('uri')
1760
- });
1761
- }
1762
1729
 
1763
- if (node) {
1764
- node.state = 'open';
1765
- }
1730
+ return this;
1731
+ }
1732
+ }, defaultConfig));
1733
+ resourceTree.setTemplate(treeTpl).on('init', function () {
1734
+ this.classUri = this.config.classUri;
1735
+ this.setState('multiple', !!this.config.multiple);
1736
+ this.render($container);
1737
+ }).on('render', function () {
1738
+ var self = this;
1739
+ var $component = this.getElement();
1740
+ /**
1741
+ * Open a class node
1742
+ * @param {jQueryElement} $class
1743
+ */
1766
1744
 
1767
- $class.addClass('open').removeClass('closed');
1768
- };
1769
- /**
1770
- * Close a class node
1771
- * @param {jQueryElement} $class
1772
- */
1745
+ var openClass = function openClass($class) {
1746
+ var node = self.getNode($class.data('uri'));
1773
1747
 
1748
+ if (!$class.children('ul').children('li').length) {
1749
+ self.query({
1750
+ classUri: $class.data('uri')
1751
+ });
1752
+ }
1774
1753
 
1775
- var closeClass = function closeClass($class) {
1776
- var node = self.getNode($class.data('uri'));
1754
+ if (node) {
1755
+ node.state = 'open';
1756
+ }
1777
1757
 
1778
- if (node) {
1779
- node.state = 'closed';
1780
- }
1758
+ $class.addClass('open').removeClass('closed');
1759
+ };
1760
+ /**
1761
+ * Close a class node
1762
+ * @param {jQueryElement} $class
1763
+ */
1781
1764
 
1782
- $class.removeClass('open').addClass('closed');
1783
- };
1784
- /**
1785
- * Toggle a class node
1786
- * @param {jQueryElement} $class
1787
- */
1788
1765
 
1766
+ var closeClass = function closeClass($class) {
1767
+ var node = self.getNode($class.data('uri'));
1789
1768
 
1790
- var toggleClass = function toggleClass($class) {
1791
- if (!$class.hasClass('closed')) {
1792
- closeClass($class);
1793
- } else {
1794
- openClass($class);
1795
- }
1796
- }; //Browse hierarchy
1797
-
1798
-
1799
- if (self.config.selectClass) {
1800
- //if we can
1801
- $component.on('click', '.class', function (e) {
1802
- const $class = $$1(e.currentTarget);
1803
- e.preventDefault();
1804
- e.stopPropagation();
1805
-
1806
- if ($$1(e.target).hasClass('class-toggler')) {
1807
- if (!$class.hasClass('empty')) {
1808
- toggleClass($class);
1809
- }
1810
- } else {
1811
- if ($class.hasClass('selected')) {
1812
- self.unselect($class.data('uri'));
1813
- } else if ($class.data('access') !== 'denied') {
1814
- self.select($class.data('uri'), !self.is('multiple'), false, true); // include children
1815
- }
1816
- }
1817
- });
1818
- } else {
1819
- $component.on('click', '.class', function (e) {
1820
- const $class = $$1(e.currentTarget);
1821
- e.preventDefault();
1822
- e.stopPropagation();
1769
+ if (node) {
1770
+ node.state = 'closed';
1771
+ }
1823
1772
 
1824
- if (!$class.hasClass('empty')) {
1825
- toggleClass($class);
1826
- }
1827
- });
1828
- } //selection
1773
+ $class.removeClass('open').addClass('closed');
1774
+ };
1775
+ /**
1776
+ * Toggle a class node
1777
+ * @param {jQueryElement} $class
1778
+ */
1829
1779
 
1830
1780
 
1831
- $component.on('click', '.instance', function (e) {
1832
- const $instance = $$1(e.currentTarget); // all instances should be not clickable because in the tree if it is child node - it will close
1833
- // parent node
1781
+ var toggleClass = function toggleClass($class) {
1782
+ if (!$class.hasClass('closed')) {
1783
+ closeClass($class);
1784
+ } else {
1785
+ openClass($class);
1786
+ }
1787
+ }; //Browse hierarchy
1834
1788
 
1789
+
1790
+ if (self.config.selectClass) {
1791
+ //if we can
1792
+ $component.on('click', '.class', function (e) {
1793
+ var $class = $$1(e.currentTarget);
1835
1794
  e.preventDefault();
1836
1795
  e.stopPropagation();
1837
1796
 
1838
- if ($instance.data('access') !== 'denied') {
1839
- if ($instance.hasClass('selected')) {
1840
- self.unselect($instance.data('uri'));
1841
- } else {
1842
- self.select($instance.data('uri'), !self.is('multiple'));
1797
+ if ($$1(e.target).hasClass('class-toggler')) {
1798
+ if (!$class.hasClass('empty')) {
1799
+ toggleClass($class);
1800
+ }
1801
+ } else {
1802
+ if ($class.hasClass('selected')) {
1803
+ self.unselect($class.data('uri'));
1804
+ } else if ($class.data('access') !== 'denied') {
1805
+ self.select($class.data('uri'), !self.is('multiple'), false, true); // include children
1843
1806
  }
1844
1807
  }
1845
1808
  });
1846
- $component.on('click', '.more', function (e) {
1847
- var $root = $$1(e.currentTarget).parent('.class');
1809
+ } else {
1810
+ $component.on('click', '.class', function (e) {
1811
+ var $class = $$1(e.currentTarget);
1848
1812
  e.preventDefault();
1849
1813
  e.stopPropagation();
1850
- self.query({
1851
- classUri: $root.data('uri'),
1852
- offset: $root.children('ul').children('.instance').length
1853
- });
1854
- }); //initial data loading
1855
1814
 
1856
- if (this.config.nodes) {
1857
- this.update(this.config.nodes);
1858
- } else {
1859
- this.query();
1860
- }
1861
- }).on('query', function () {
1862
- this.setState('loading', true);
1863
- }).on('update', function () {
1864
- this.setState('loading', false);
1865
- }).on('remove', function (uri) {
1866
- var $node, $parents, $parent;
1867
-
1868
- if (this.is('rendered') && uri) {
1869
- $node = $$1('[data-uri="' + uri + '"]', this.getElement());
1870
- $parents = $node.parents('.class');
1871
-
1872
- if ($node.hasClass('instance')) {
1873
- updateCount($parents, -1);
1815
+ if (!$class.hasClass('empty')) {
1816
+ toggleClass($class);
1874
1817
  }
1818
+ });
1819
+ } //selection
1820
+
1875
1821
 
1876
- $parent = $parents.first();
1822
+ $component.on('click', '.instance', function (e) {
1823
+ var $instance = $$1(e.currentTarget); // all instances should be not clickable because in the tree if it is child node - it will close
1824
+ // parent node
1877
1825
 
1878
- if ($parent.children('ul').children('li').length === 1) {
1879
- $parent.removeClass('closed').addClass('empty');
1826
+ e.preventDefault();
1827
+ e.stopPropagation();
1828
+
1829
+ if ($instance.data('access') !== 'denied') {
1830
+ if ($instance.hasClass('selected')) {
1831
+ self.unselect($instance.data('uri'));
1832
+ } else {
1833
+ self.select($instance.data('uri'), !self.is('multiple'));
1880
1834
  }
1835
+ }
1836
+ });
1837
+ $component.on('click', '.more', function (e) {
1838
+ var $root = $$1(e.currentTarget).parent('.class');
1839
+ e.preventDefault();
1840
+ e.stopPropagation();
1841
+ self.query({
1842
+ classUri: $root.data('uri'),
1843
+ offset: $root.children('ul').children('.instance').length
1844
+ });
1845
+ }); //initial data loading
1846
+
1847
+ if (this.config.nodes) {
1848
+ this.update(this.config.nodes);
1849
+ } else {
1850
+ this.query();
1851
+ }
1852
+ }).on('query', function () {
1853
+ this.setState('loading', true);
1854
+ }).on('update', function () {
1855
+ this.setState('loading', false);
1856
+ }).on('remove', function (uri) {
1857
+ var $node, $parents, $parent;
1858
+
1859
+ if (this.is('rendered') && uri) {
1860
+ $node = $$1('[data-uri="' + uri + '"]', this.getElement());
1861
+ $parents = $node.parents('.class');
1862
+
1863
+ if ($node.hasClass('instance')) {
1864
+ updateCount($parents, -1);
1865
+ }
1866
+
1867
+ $parent = $parents.first();
1881
1868
 
1882
- $node.remove();
1869
+ if ($parent.children('ul').children('li').length === 1) {
1870
+ $parent.removeClass('closed').addClass('empty');
1883
1871
  }
1884
- }); //always defer the initialization to let consumers listen for init and render events.
1885
1872
 
1886
- _.defer(function () {
1887
- resourceTree.init(config);
1888
- });
1873
+ $node.remove();
1874
+ }
1875
+ }); //always defer the initialization to let consumers listen for init and render events.
1889
1876
 
1890
- return resourceTree;
1891
- }
1877
+ _.defer(function () {
1878
+ resourceTree.init(config);
1879
+ });
1880
+
1881
+ return resourceTree;
1882
+ }
1892
1883
 
1893
- return resourceTreeFactory;
1884
+ return resourceTreeFactory;
1894
1885
 
1895
1886
  });