@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,1618 +1,1609 @@
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
+ * Register dompurify helper
28
29
  *
30
+ * https://github.com/cure53/DOMPurify
31
+ * with config SAFE_FOR_TEMPLATES: true
32
+ * to make output safe for template systems
33
+ */
34
+
35
+ hb.registerHelper('dompurify', function (context) {
36
+ return DOMPurify.sanitize(context);
37
+ });
38
+ /**
39
+ * Register join helper
29
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*
30
45
  */
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
46
 
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
- */
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 : '"';
55
52
 
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 : '"';
61
-
62
- _.forIn(arr, function (value, key) {
63
- var fragment = '';
64
-
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
65
 
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
-
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, helper, options, self=this, helperMissing=helpers.helperMissing, escapeExpression=this.escapeExpression;
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-list ";
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 class=\"more hidden\">\n <a href=\"#\" class=\"btn-info small\"><span class=\"icon-download\"></span> "
141
- + escapeExpression((helper = helpers.__ || (depth0 && depth0.__),options={hash:{},data:data},helper ? helper.call(depth0, "Load more", options) : helperMissing.call(depth0, "__", "Load more", options)))
142
- + "</a>\n </div>\n</div>\n\n";
143
- return buffer;
144
- });
145
- function listTpl(data, options, asString) {
146
- var html = Template(data, options);
147
- return (asString || true) ? html : $(html);
148
- }
78
+ hb.registerHelper('for', function (startIndex, stopIndex, increment, options) {
79
+ var ret = '';
80
+ startIndex = parseInt(startIndex);
81
+ stopIndex = parseInt(stopIndex);
82
+ increment = parseInt(increment);
149
83
 
150
- if (!Helpers0.__initialized) {
151
- Helpers0(Handlebars);
152
- Helpers0.__initialized = true;
153
- }
154
- var Template$1 = Handlebars.template(function (Handlebars,depth0,helpers,partials,data) {
155
- this.compilerInfo = [4,'>= 1.0.0'];
156
- helpers = this.merge(helpers, Handlebars.helpers); data = data || {};
157
- var buffer = "", stack1, helper, functionType="function", escapeExpression=this.escapeExpression, self=this;
158
-
159
- function program1(depth0,data) {
160
-
161
-
162
- return "class=\"selected\"";
84
+ for (var i = startIndex; i < stopIndex; i += increment) {
85
+ ret += options.fn(_.extend({}, this, {
86
+ i: i
87
+ }));
163
88
  }
164
89
 
165
- function program3(depth0,data) {
166
-
167
- var buffer = "", stack1, helper;
168
- buffer += "data-access=\"";
169
- if (helper = helpers.accessMode) { stack1 = helper.call(depth0, {hash:{},data:data}); }
170
- else { helper = (depth0 && depth0.accessMode); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
171
- buffer += escapeExpression(stack1)
172
- + "\"";
173
- 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);
174
97
  }
98
+ }); // register a "get property" helper
99
+ // it gets the named property from the provided context
175
100
 
176
- buffer += "<li data-uri=\"";
177
- if (helper = helpers.uri) { stack1 = helper.call(depth0, {hash:{},data:data}); }
178
- else { helper = (depth0 && depth0.uri); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
179
- buffer += escapeExpression(stack1)
180
- + "\" ";
181
- stack1 = helpers['if'].call(depth0, (depth0 && depth0.selected), {hash:{},inverse:self.noop,fn:self.program(1, program1, data),data:data});
182
- if(stack1 || stack1 === 0) { buffer += stack1; }
183
- buffer += " class=\"";
184
- if (helper = helpers.state) { stack1 = helper.call(depth0, {hash:{},data:data}); }
185
- else { helper = (depth0 && depth0.state); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
186
- buffer += escapeExpression(stack1)
187
- + "\" ";
188
- stack1 = helpers['if'].call(depth0, (depth0 && depth0.accessMode), {hash:{},inverse:self.noop,fn:self.program(3, program3, data),data:data});
189
- if(stack1 || stack1 === 0) { buffer += stack1; }
190
- buffer += ">\n <a href=\"#\" title=\"";
191
- if (helper = helpers.label) { stack1 = helper.call(depth0, {hash:{},data:data}); }
192
- else { helper = (depth0 && depth0.label); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
193
- if(stack1 || stack1 === 0) { buffer += stack1; }
194
- buffer += "\"><span class=\"icon-";
195
- if (helper = helpers.icon) { stack1 = helper.call(depth0, {hash:{},data:data}); }
196
- else { helper = (depth0 && depth0.icon); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
197
- buffer += escapeExpression(stack1)
198
- + "\"></span>";
199
- if (helper = helpers.label) { stack1 = helper.call(depth0, {hash:{},data:data}); }
200
- else { helper = (depth0 && depth0.label); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
201
- if(stack1 || stack1 === 0) { buffer += stack1; }
202
- buffer += "</a>\n</li>\n\n";
203
- return buffer;
204
- });
205
- function listNodeTpl(data, options, asString) {
206
- var html = Template$1(data, options);
207
- return (asString || true) ? html : $(html);
208
- }
101
+ hb.registerHelper('property', function (name, context) {
102
+ return context[name] || '';
103
+ }); // register an 'includes' helper
104
+ // it checks if value is in array
209
105
 
210
- var freeze$1 = Object.freeze || function (x) {
211
- return x;
212
- };
106
+ hb.registerHelper('includes', function (haystack, needle, options) {
107
+ if (_.contains(haystack, needle)) {
108
+ return options.fn(this);
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, helper, options, self=this, helperMissing=helpers.helperMissing, escapeExpression=this.escapeExpression;
121
+
122
+ function program1(depth0,data) {
123
+
124
+
125
+ return "multiple";
126
+ }
213
127
 
214
- 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
128
+ buffer += "<div class=\"resource-list ";
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 class=\"more hidden\">\n <a href=\"#\" class=\"btn-info small\"><span class=\"icon-download\"></span> "
132
+ + escapeExpression((helper = helpers.__ || (depth0 && depth0.__),options={hash:{},data:data},helper ? helper.call(depth0, "Load more", options) : helperMissing.call(depth0, "__", "Load more", options)))
133
+ + "</a>\n </div>\n</div>\n\n";
134
+ return buffer;
135
+ });
136
+ function listTpl(data, options, asString) {
137
+ var html = Template(data, options);
138
+ return (asString || true) ? html : $(html);
139
+ }
140
+
141
+ if (!Helpers0.__initialized) {
142
+ Helpers0(Handlebars);
143
+ Helpers0.__initialized = true;
144
+ }
145
+ var Template$1 = Handlebars.template(function (Handlebars,depth0,helpers,partials,data) {
146
+ this.compilerInfo = [4,'>= 1.0.0'];
147
+ helpers = this.merge(helpers, Handlebars.helpers); data = data || {};
148
+ var buffer = "", stack1, helper, functionType="function", escapeExpression=this.escapeExpression, self=this;
149
+
150
+ function program1(depth0,data) {
151
+
152
+
153
+ return "class=\"selected\"";
154
+ }
215
155
 
216
- 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']);
217
- 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']);
218
- 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']);
219
- var text = freeze$1(['#text']);
156
+ function program3(depth0,data) {
157
+
158
+ var buffer = "", stack1, helper;
159
+ buffer += "data-access=\"";
160
+ if (helper = helpers.accessMode) { stack1 = helper.call(depth0, {hash:{},data:data}); }
161
+ else { helper = (depth0 && depth0.accessMode); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
162
+ buffer += escapeExpression(stack1)
163
+ + "\"";
164
+ return buffer;
165
+ }
220
166
 
221
- var freeze$2 = Object.freeze || function (x) {
222
- return x;
167
+ buffer += "<li data-uri=\"";
168
+ if (helper = helpers.uri) { stack1 = helper.call(depth0, {hash:{},data:data}); }
169
+ else { helper = (depth0 && depth0.uri); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
170
+ buffer += escapeExpression(stack1)
171
+ + "\" ";
172
+ stack1 = helpers['if'].call(depth0, (depth0 && depth0.selected), {hash:{},inverse:self.noop,fn:self.program(1, program1, data),data:data});
173
+ if(stack1 || stack1 === 0) { buffer += stack1; }
174
+ buffer += " class=\"";
175
+ if (helper = helpers.state) { stack1 = helper.call(depth0, {hash:{},data:data}); }
176
+ else { helper = (depth0 && depth0.state); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
177
+ buffer += escapeExpression(stack1)
178
+ + "\" ";
179
+ stack1 = helpers['if'].call(depth0, (depth0 && depth0.accessMode), {hash:{},inverse:self.noop,fn:self.program(3, program3, data),data:data});
180
+ if(stack1 || stack1 === 0) { buffer += stack1; }
181
+ buffer += ">\n <a href=\"#\" title=\"";
182
+ if (helper = helpers.label) { stack1 = helper.call(depth0, {hash:{},data:data}); }
183
+ else { helper = (depth0 && depth0.label); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
184
+ if(stack1 || stack1 === 0) { buffer += stack1; }
185
+ buffer += "\"><span class=\"icon-";
186
+ if (helper = helpers.icon) { stack1 = helper.call(depth0, {hash:{},data:data}); }
187
+ else { helper = (depth0 && depth0.icon); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
188
+ buffer += escapeExpression(stack1)
189
+ + "\"></span>";
190
+ if (helper = helpers.label) { stack1 = helper.call(depth0, {hash:{},data:data}); }
191
+ else { helper = (depth0 && depth0.label); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
192
+ if(stack1 || stack1 === 0) { buffer += stack1; }
193
+ buffer += "</a>\n</li>\n\n";
194
+ return buffer;
195
+ });
196
+ function listNodeTpl(data, options, asString) {
197
+ var html = Template$1(data, options);
198
+ return (asString || true) ? html : $(html);
199
+ }
200
+
201
+ var freeze$1 = Object.freeze || function (x) {
202
+ return x;
203
+ };
204
+
205
+ 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
206
+
207
+ 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']);
208
+ 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']);
209
+ 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']);
210
+ var text = freeze$1(['#text']);
211
+
212
+ var freeze$2 = Object.freeze || function (x) {
213
+ return x;
214
+ };
215
+
216
+ 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']);
217
+ 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']);
218
+ 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']);
219
+ var xml = freeze$2(['xlink:href', 'xml:id', 'xlink:title', 'xml:space', 'xmlns:xlink']);
220
+ var hasOwnProperty = Object.hasOwnProperty;
221
+ var setPrototypeOf = Object.setPrototypeOf;
222
+
223
+ var _ref$1 = typeof Reflect !== 'undefined' && Reflect;
224
+
225
+ var apply$1 = _ref$1.apply;
226
+
227
+ if (!apply$1) {
228
+ apply$1 = function apply(fun, thisValue, args) {
229
+ return fun.apply(thisValue, args);
223
230
  };
231
+ }
232
+ /* Add properties to a lookup table */
224
233
 
225
- 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']);
226
- 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']);
227
- 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']);
228
- var xml = freeze$2(['xlink:href', 'xml:id', 'xlink:title', 'xml:space', 'xmlns:xlink']);
229
- var hasOwnProperty = Object.hasOwnProperty;
230
- var setPrototypeOf = Object.setPrototypeOf;
231
-
232
- var _ref$1 = typeof Reflect !== 'undefined' && Reflect;
233
234
 
234
- var apply$1 = _ref$1.apply;
235
-
236
- if (!apply$1) {
237
- apply$1 = function apply(fun, thisValue, args) {
238
- return fun.apply(thisValue, args);
239
- };
235
+ function addToSet(set, array) {
236
+ if (setPrototypeOf) {
237
+ // Make 'in' and truthy checks like Boolean(set.constructor)
238
+ // independent of any properties defined on Object.prototype.
239
+ // Prevent prototype setters from intercepting set as a this value.
240
+ setPrototypeOf(set, null);
240
241
  }
241
- /* Add properties to a lookup table */
242
-
243
242
 
244
- function addToSet(set, array) {
245
- if (setPrototypeOf) {
246
- // Make 'in' and truthy checks like Boolean(set.constructor)
247
- // independent of any properties defined on Object.prototype.
248
- // Prevent prototype setters from intercepting set as a this value.
249
- setPrototypeOf(set, null);
250
- }
251
-
252
- var l = array.length;
253
-
254
- while (l--) {
255
- var element = array[l];
243
+ var l = array.length;
256
244
 
257
- if (typeof element === 'string') {
258
- var lcElement = element.toLowerCase();
245
+ while (l--) {
246
+ var element = array[l];
259
247
 
260
- if (lcElement !== element) {
261
- // Config presets (e.g. tags.js, attrs.js) are immutable.
262
- if (!Object.isFrozen(array)) {
263
- array[l] = lcElement;
264
- }
248
+ if (typeof element === 'string') {
249
+ var lcElement = element.toLowerCase();
265
250
 
266
- element = lcElement;
251
+ if (lcElement !== element) {
252
+ // Config presets (e.g. tags.js, attrs.js) are immutable.
253
+ if (!Object.isFrozen(array)) {
254
+ array[l] = lcElement;
267
255
  }
268
- }
269
256
 
270
- set[element] = true;
257
+ element = lcElement;
258
+ }
271
259
  }
272
260
 
273
- return set;
261
+ set[element] = true;
274
262
  }
275
- /* Shallow clone an object */
276
263
 
264
+ return set;
265
+ }
266
+ /* Shallow clone an object */
277
267
 
278
- function clone(object) {
279
- var newObject = {};
280
- var property = void 0;
281
268
 
282
- for (property in object) {
283
- if (apply$1(hasOwnProperty, object, [property])) {
284
- newObject[property] = object[property];
285
- }
286
- }
269
+ function clone(object) {
270
+ var newObject = {};
271
+ var property = void 0;
287
272
 
288
- return newObject;
273
+ for (property in object) {
274
+ if (apply$1(hasOwnProperty, object, [property])) {
275
+ newObject[property] = object[property];
276
+ }
289
277
  }
290
278
 
291
- var seal = Object.seal || function (x) {
292
- return x;
293
- };
279
+ return newObject;
280
+ }
294
281
 
295
- var MUSTACHE_EXPR = seal(/\{\{[\s\S]*|[\s\S]*\}\}/gm); // Specify template detection regex for SAFE_FOR_TEMPLATES mode
282
+ var seal = Object.seal || function (x) {
283
+ return x;
284
+ };
296
285
 
297
- var ERB_EXPR = seal(/<%[\s\S]*|[\s\S]*%>/gm);
298
- var DATA_ATTR = seal(/^data-[\-\w.\u00B7-\uFFFF]/); // eslint-disable-line no-useless-escape
286
+ var MUSTACHE_EXPR = seal(/\{\{[\s\S]*|[\s\S]*\}\}/gm); // Specify template detection regex for SAFE_FOR_TEMPLATES mode
299
287
 
300
- var ARIA_ATTR = seal(/^aria-[\-\w]+$/); // eslint-disable-line no-useless-escape
288
+ var ERB_EXPR = seal(/<%[\s\S]*|[\s\S]*%>/gm);
289
+ var DATA_ATTR = seal(/^data-[\-\w.\u00B7-\uFFFF]/); // eslint-disable-line no-useless-escape
301
290
 
302
- 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
303
- );
304
- var IS_SCRIPT_OR_DATA = seal(/^(?:\w+script|data):/i);
305
- var ATTR_WHITESPACE = seal(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205f\u3000]/g // eslint-disable-line no-control-regex
306
- );
291
+ var ARIA_ATTR = seal(/^aria-[\-\w]+$/); // eslint-disable-line no-useless-escape
307
292
 
308
- var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {
309
- return typeof obj;
310
- } : function (obj) {
311
- return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
312
- };
293
+ 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
294
+ );
295
+ var IS_SCRIPT_OR_DATA = seal(/^(?:\w+script|data):/i);
296
+ var ATTR_WHITESPACE = seal(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205f\u3000]/g // eslint-disable-line no-control-regex
297
+ );
313
298
 
314
- function _toConsumableArray(arr) {
315
- if (Array.isArray(arr)) {
316
- for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) {
317
- arr2[i] = arr[i];
318
- }
299
+ var _typeof$1 = typeof Symbol === "function" && _typeof(Symbol.iterator) === "symbol" ? function (obj) {
300
+ return _typeof(obj);
301
+ } : function (obj) {
302
+ return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : _typeof(obj);
303
+ };
319
304
 
320
- return arr2;
321
- } else {
322
- return Array.from(arr);
305
+ function _toConsumableArray(arr) {
306
+ if (Array.isArray(arr)) {
307
+ for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) {
308
+ arr2[i] = arr[i];
323
309
  }
310
+
311
+ return arr2;
312
+ } else {
313
+ return Array.from(arr);
324
314
  }
315
+ }
325
316
 
326
- var _ref = typeof Reflect !== 'undefined' && Reflect;
317
+ var _ref = typeof Reflect !== 'undefined' && Reflect;
327
318
 
328
- var apply = _ref.apply;
329
- var arraySlice = Array.prototype.slice;
330
- var freeze = Object.freeze;
319
+ var apply = _ref.apply;
320
+ var arraySlice = Array.prototype.slice;
321
+ var freeze = Object.freeze;
331
322
 
332
- var getGlobal = function getGlobal() {
333
- return typeof window === 'undefined' ? null : window;
334
- };
323
+ var getGlobal = function getGlobal() {
324
+ return typeof window === 'undefined' ? null : window;
325
+ };
335
326
 
336
- if (!apply) {
337
- apply = function apply(fun, thisValue, args) {
338
- return fun.apply(thisValue, args);
339
- };
327
+ if (!apply) {
328
+ apply = function apply(fun, thisValue, args) {
329
+ return fun.apply(thisValue, args);
330
+ };
331
+ }
332
+ /**
333
+ * Creates a no-op policy for internal use only.
334
+ * Don't export this function outside this module!
335
+ * @param {?TrustedTypePolicyFactory} trustedTypes The policy factory.
336
+ * @param {Document} document The document object (to determine policy name suffix)
337
+ * @return {?TrustedTypePolicy} The policy created (or null, if Trusted Types
338
+ * are not supported).
339
+ */
340
+
341
+
342
+ var _createTrustedTypesPolicy = function _createTrustedTypesPolicy(trustedTypes, document) {
343
+ if ((typeof trustedTypes === 'undefined' ? 'undefined' : _typeof$1(trustedTypes)) !== 'object' || typeof trustedTypes.createPolicy !== 'function') {
344
+ return null;
345
+ } // Allow the callers to control the unique policy name
346
+ // by adding a data-tt-policy-suffix to the script element with the DOMPurify.
347
+ // Policy creation with duplicate names throws in Trusted Types.
348
+
349
+
350
+ var suffix = null;
351
+ var ATTR_NAME = 'data-tt-policy-suffix';
352
+
353
+ if (document.currentScript && document.currentScript.hasAttribute(ATTR_NAME)) {
354
+ suffix = document.currentScript.getAttribute(ATTR_NAME);
340
355
  }
341
- /**
342
- * Creates a no-op policy for internal use only.
343
- * Don't export this function outside this module!
344
- * @param {?TrustedTypePolicyFactory} trustedTypes The policy factory.
345
- * @param {Document} document The document object (to determine policy name suffix)
346
- * @return {?TrustedTypePolicy} The policy created (or null, if Trusted Types
347
- * are not supported).
348
- */
349
356
 
357
+ var policyName = 'dompurify' + (suffix ? '#' + suffix : '');
350
358
 
351
- var _createTrustedTypesPolicy = function _createTrustedTypesPolicy(trustedTypes, document) {
352
- if ((typeof trustedTypes === 'undefined' ? 'undefined' : _typeof(trustedTypes)) !== 'object' || typeof trustedTypes.createPolicy !== 'function') {
353
- return null;
354
- } // Allow the callers to control the unique policy name
355
- // by adding a data-tt-policy-suffix to the script element with the DOMPurify.
356
- // Policy creation with duplicate names throws in Trusted Types.
357
-
359
+ try {
360
+ return trustedTypes.createPolicy(policyName, {
361
+ createHTML: function createHTML(html$$1) {
362
+ return html$$1;
363
+ }
364
+ });
365
+ } catch (error) {
366
+ // Policy creation failed (most likely another DOMPurify script has
367
+ // already run). Skip creating the policy, as this will only cause errors
368
+ // if TT are enforced.
369
+ console.warn('TrustedTypes policy ' + policyName + ' could not be created.');
370
+ return null;
371
+ }
372
+ };
358
373
 
359
- var suffix = null;
360
- var ATTR_NAME = 'data-tt-policy-suffix';
374
+ function createDOMPurify() {
375
+ var window = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getGlobal();
361
376
 
362
- if (document.currentScript && document.currentScript.hasAttribute(ATTR_NAME)) {
363
- suffix = document.currentScript.getAttribute(ATTR_NAME);
364
- }
377
+ var DOMPurify = function DOMPurify(root) {
378
+ return createDOMPurify(root);
379
+ };
380
+ /**
381
+ * Version label, exposed for easier checks
382
+ * if DOMPurify is up to date or not
383
+ */
365
384
 
366
- var policyName = 'dompurify' + (suffix ? '#' + suffix : '');
367
385
 
368
- try {
369
- return trustedTypes.createPolicy(policyName, {
370
- createHTML: function createHTML(html$$1) {
371
- return html$$1;
372
- }
373
- });
374
- } catch (error) {
375
- // Policy creation failed (most likely another DOMPurify script has
376
- // already run). Skip creating the policy, as this will only cause errors
377
- // if TT are enforced.
378
- console.warn('TrustedTypes policy ' + policyName + ' could not be created.');
379
- return null;
380
- }
381
- };
386
+ DOMPurify.version = '1.0.11';
387
+ /**
388
+ * Array of elements that DOMPurify removed during sanitation.
389
+ * Empty if nothing was removed.
390
+ */
382
391
 
383
- function createDOMPurify() {
384
- var window = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getGlobal();
392
+ DOMPurify.removed = [];
385
393
 
386
- var DOMPurify = function DOMPurify(root) {
387
- return createDOMPurify(root);
388
- };
389
- /**
390
- * Version label, exposed for easier checks
391
- * if DOMPurify is up to date or not
392
- */
394
+ if (!window || !window.document || window.document.nodeType !== 9) {
395
+ // Not running in a browser, provide a factory function
396
+ // so that you can pass your own Window
397
+ DOMPurify.isSupported = false;
398
+ return DOMPurify;
399
+ }
393
400
 
401
+ var originalDocument = window.document;
402
+ var useDOMParser = false;
403
+ var removeTitle = false;
404
+ var document = window.document;
405
+ var DocumentFragment = window.DocumentFragment,
406
+ HTMLTemplateElement = window.HTMLTemplateElement,
407
+ Node = window.Node,
408
+ NodeFilter = window.NodeFilter,
409
+ _window$NamedNodeMap = window.NamedNodeMap,
410
+ NamedNodeMap = _window$NamedNodeMap === undefined ? window.NamedNodeMap || window.MozNamedAttrMap : _window$NamedNodeMap,
411
+ Text = window.Text,
412
+ Comment = window.Comment,
413
+ DOMParser = window.DOMParser,
414
+ TrustedTypes = window.TrustedTypes; // As per issue #47, the web-components registry is inherited by a
415
+ // new document created via createHTMLDocument. As per the spec
416
+ // (http://w3c.github.io/webcomponents/spec/custom/#creating-and-passing-registries)
417
+ // a new empty registry is used when creating a template contents owner
418
+ // document, so we use that as our parent document to ensure nothing
419
+ // is inherited.
420
+
421
+ if (typeof HTMLTemplateElement === 'function') {
422
+ var template = document.createElement('template');
423
+
424
+ if (template.content && template.content.ownerDocument) {
425
+ document = template.content.ownerDocument;
426
+ }
427
+ }
394
428
 
395
- DOMPurify.version = '1.0.11';
396
- /**
397
- * Array of elements that DOMPurify removed during sanitation.
398
- * Empty if nothing was removed.
399
- */
429
+ var trustedTypesPolicy = _createTrustedTypesPolicy(TrustedTypes, originalDocument);
400
430
 
401
- DOMPurify.removed = [];
431
+ var emptyHTML = trustedTypesPolicy ? trustedTypesPolicy.createHTML('') : '';
432
+ var _document = document,
433
+ implementation = _document.implementation,
434
+ createNodeIterator = _document.createNodeIterator,
435
+ getElementsByTagName = _document.getElementsByTagName,
436
+ createDocumentFragment = _document.createDocumentFragment;
437
+ var importNode = originalDocument.importNode;
438
+ var hooks = {};
439
+ /**
440
+ * Expose whether this browser supports running the full DOMPurify.
441
+ */
402
442
 
403
- if (!window || !window.document || window.document.nodeType !== 9) {
404
- // Not running in a browser, provide a factory function
405
- // so that you can pass your own Window
406
- DOMPurify.isSupported = false;
407
- return DOMPurify;
408
- }
443
+ DOMPurify.isSupported = implementation && typeof implementation.createHTMLDocument !== 'undefined' && document.documentMode !== 9;
444
+ var MUSTACHE_EXPR$$1 = MUSTACHE_EXPR,
445
+ ERB_EXPR$$1 = ERB_EXPR,
446
+ DATA_ATTR$$1 = DATA_ATTR,
447
+ ARIA_ATTR$$1 = ARIA_ATTR,
448
+ IS_SCRIPT_OR_DATA$$1 = IS_SCRIPT_OR_DATA,
449
+ ATTR_WHITESPACE$$1 = ATTR_WHITESPACE;
450
+ var IS_ALLOWED_URI$$1 = IS_ALLOWED_URI;
451
+ /**
452
+ * We consider the elements and attributes below to be safe. Ideally
453
+ * don't add any new ones but feel free to remove unwanted ones.
454
+ */
409
455
 
410
- var originalDocument = window.document;
411
- var useDOMParser = false;
412
- var removeTitle = false;
413
- var document = window.document;
414
- var DocumentFragment = window.DocumentFragment,
415
- HTMLTemplateElement = window.HTMLTemplateElement,
416
- Node = window.Node,
417
- NodeFilter = window.NodeFilter,
418
- _window$NamedNodeMap = window.NamedNodeMap,
419
- NamedNodeMap = _window$NamedNodeMap === undefined ? window.NamedNodeMap || window.MozNamedAttrMap : _window$NamedNodeMap,
420
- Text = window.Text,
421
- Comment = window.Comment,
422
- DOMParser = window.DOMParser,
423
- TrustedTypes = window.TrustedTypes; // As per issue #47, the web-components registry is inherited by a
424
- // new document created via createHTMLDocument. As per the spec
425
- // (http://w3c.github.io/webcomponents/spec/custom/#creating-and-passing-registries)
426
- // a new empty registry is used when creating a template contents owner
427
- // document, so we use that as our parent document to ensure nothing
428
- // is inherited.
429
-
430
- if (typeof HTMLTemplateElement === 'function') {
431
- var template = document.createElement('template');
432
-
433
- if (template.content && template.content.ownerDocument) {
434
- document = template.content.ownerDocument;
435
- }
436
- }
456
+ /* allowed element names */
437
457
 
438
- var trustedTypesPolicy = _createTrustedTypesPolicy(TrustedTypes, originalDocument);
458
+ var ALLOWED_TAGS = null;
459
+ var DEFAULT_ALLOWED_TAGS = addToSet({}, [].concat(_toConsumableArray(html), _toConsumableArray(svg), _toConsumableArray(svgFilters), _toConsumableArray(mathMl), _toConsumableArray(text)));
460
+ /* Allowed attribute names */
439
461
 
440
- var emptyHTML = trustedTypesPolicy ? trustedTypesPolicy.createHTML('') : '';
441
- var _document = document,
442
- implementation = _document.implementation,
443
- createNodeIterator = _document.createNodeIterator,
444
- getElementsByTagName = _document.getElementsByTagName,
445
- createDocumentFragment = _document.createDocumentFragment;
446
- var importNode = originalDocument.importNode;
447
- var hooks = {};
448
- /**
449
- * Expose whether this browser supports running the full DOMPurify.
450
- */
462
+ var ALLOWED_ATTR = null;
463
+ var DEFAULT_ALLOWED_ATTR = addToSet({}, [].concat(_toConsumableArray(html$1), _toConsumableArray(svg$1), _toConsumableArray(mathMl$1), _toConsumableArray(xml)));
464
+ /* Explicitly forbidden tags (overrides ALLOWED_TAGS/ADD_TAGS) */
451
465
 
452
- DOMPurify.isSupported = implementation && typeof implementation.createHTMLDocument !== 'undefined' && document.documentMode !== 9;
453
- var MUSTACHE_EXPR$$1 = MUSTACHE_EXPR,
454
- ERB_EXPR$$1 = ERB_EXPR,
455
- DATA_ATTR$$1 = DATA_ATTR,
456
- ARIA_ATTR$$1 = ARIA_ATTR,
457
- IS_SCRIPT_OR_DATA$$1 = IS_SCRIPT_OR_DATA,
458
- ATTR_WHITESPACE$$1 = ATTR_WHITESPACE;
459
- var IS_ALLOWED_URI$$1 = IS_ALLOWED_URI;
460
- /**
461
- * We consider the elements and attributes below to be safe. Ideally
462
- * don't add any new ones but feel free to remove unwanted ones.
463
- */
466
+ var FORBID_TAGS = null;
467
+ /* Explicitly forbidden attributes (overrides ALLOWED_ATTR/ADD_ATTR) */
464
468
 
465
- /* allowed element names */
469
+ var FORBID_ATTR = null;
470
+ /* Decide if ARIA attributes are okay */
466
471
 
467
- var ALLOWED_TAGS = null;
468
- var DEFAULT_ALLOWED_TAGS = addToSet({}, [].concat(_toConsumableArray(html), _toConsumableArray(svg), _toConsumableArray(svgFilters), _toConsumableArray(mathMl), _toConsumableArray(text)));
469
- /* Allowed attribute names */
472
+ var ALLOW_ARIA_ATTR = true;
473
+ /* Decide if custom data attributes are okay */
470
474
 
471
- var ALLOWED_ATTR = null;
472
- var DEFAULT_ALLOWED_ATTR = addToSet({}, [].concat(_toConsumableArray(html$1), _toConsumableArray(svg$1), _toConsumableArray(mathMl$1), _toConsumableArray(xml)));
473
- /* Explicitly forbidden tags (overrides ALLOWED_TAGS/ADD_TAGS) */
475
+ var ALLOW_DATA_ATTR = true;
476
+ /* Decide if unknown protocols are okay */
474
477
 
475
- var FORBID_TAGS = null;
476
- /* Explicitly forbidden attributes (overrides ALLOWED_ATTR/ADD_ATTR) */
478
+ var ALLOW_UNKNOWN_PROTOCOLS = false;
479
+ /* Output should be safe for jQuery's $() factory? */
477
480
 
478
- var FORBID_ATTR = null;
479
- /* Decide if ARIA attributes are okay */
481
+ var SAFE_FOR_JQUERY = false;
482
+ /* Output should be safe for common template engines.
483
+ * This means, DOMPurify removes data attributes, mustaches and ERB
484
+ */
480
485
 
481
- var ALLOW_ARIA_ATTR = true;
482
- /* Decide if custom data attributes are okay */
486
+ var SAFE_FOR_TEMPLATES = false;
487
+ /* Decide if document with <html>... should be returned */
483
488
 
484
- var ALLOW_DATA_ATTR = true;
485
- /* Decide if unknown protocols are okay */
489
+ var WHOLE_DOCUMENT = false;
490
+ /* Track whether config is already set on this instance of DOMPurify. */
486
491
 
487
- var ALLOW_UNKNOWN_PROTOCOLS = false;
488
- /* Output should be safe for jQuery's $() factory? */
492
+ var SET_CONFIG = false;
493
+ /* Decide if all elements (e.g. style, script) must be children of
494
+ * document.body. By default, browsers might move them to document.head */
489
495
 
490
- var SAFE_FOR_JQUERY = false;
491
- /* Output should be safe for common template engines.
492
- * This means, DOMPurify removes data attributes, mustaches and ERB
493
- */
496
+ var FORCE_BODY = false;
497
+ /* Decide if a DOM `HTMLBodyElement` should be returned, instead of a html
498
+ * string (or a TrustedHTML object if Trusted Types are supported).
499
+ * If `WHOLE_DOCUMENT` is enabled a `HTMLHtmlElement` will be returned instead
500
+ */
494
501
 
495
- var SAFE_FOR_TEMPLATES = false;
496
- /* Decide if document with <html>... should be returned */
502
+ var RETURN_DOM = false;
503
+ /* Decide if a DOM `DocumentFragment` should be returned, instead of a html
504
+ * string (or a TrustedHTML object if Trusted Types are supported) */
497
505
 
498
- var WHOLE_DOCUMENT = false;
499
- /* Track whether config is already set on this instance of DOMPurify. */
506
+ var RETURN_DOM_FRAGMENT = false;
507
+ /* If `RETURN_DOM` or `RETURN_DOM_FRAGMENT` is enabled, decide if the returned DOM
508
+ * `Node` is imported into the current `Document`. If this flag is not enabled the
509
+ * `Node` will belong (its ownerDocument) to a fresh `HTMLDocument`, created by
510
+ * DOMPurify. */
500
511
 
501
- var SET_CONFIG = false;
502
- /* Decide if all elements (e.g. style, script) must be children of
503
- * document.body. By default, browsers might move them to document.head */
512
+ var RETURN_DOM_IMPORT = false;
513
+ /* Output should be free from DOM clobbering attacks? */
504
514
 
505
- var FORCE_BODY = false;
506
- /* Decide if a DOM `HTMLBodyElement` should be returned, instead of a html
507
- * string (or a TrustedHTML object if Trusted Types are supported).
508
- * If `WHOLE_DOCUMENT` is enabled a `HTMLHtmlElement` will be returned instead
509
- */
515
+ var SANITIZE_DOM = true;
516
+ /* Keep element content when removing element? */
510
517
 
511
- var RETURN_DOM = false;
512
- /* Decide if a DOM `DocumentFragment` should be returned, instead of a html
513
- * string (or a TrustedHTML object if Trusted Types are supported) */
518
+ var KEEP_CONTENT = true;
519
+ /* If a `Node` is passed to sanitize(), then performs sanitization in-place instead
520
+ * of importing it into a new Document and returning a sanitized copy */
514
521
 
515
- var RETURN_DOM_FRAGMENT = false;
516
- /* If `RETURN_DOM` or `RETURN_DOM_FRAGMENT` is enabled, decide if the returned DOM
517
- * `Node` is imported into the current `Document`. If this flag is not enabled the
518
- * `Node` will belong (its ownerDocument) to a fresh `HTMLDocument`, created by
519
- * DOMPurify. */
522
+ var IN_PLACE = false;
523
+ /* Allow usage of profiles like html, svg and mathMl */
520
524
 
521
- var RETURN_DOM_IMPORT = false;
522
- /* Output should be free from DOM clobbering attacks? */
525
+ var USE_PROFILES = {};
526
+ /* Tags to ignore content of when KEEP_CONTENT is true */
523
527
 
524
- var SANITIZE_DOM = true;
525
- /* Keep element content when removing element? */
528
+ var FORBID_CONTENTS = addToSet({}, ['audio', 'head', 'math', 'script', 'style', 'template', 'svg', 'video']);
529
+ /* Tags that are safe for data: URIs */
526
530
 
527
- var KEEP_CONTENT = true;
528
- /* If a `Node` is passed to sanitize(), then performs sanitization in-place instead
529
- * of importing it into a new Document and returning a sanitized copy */
531
+ var DATA_URI_TAGS = addToSet({}, ['audio', 'video', 'img', 'source', 'image']);
532
+ /* Attributes safe for values like "javascript:" */
530
533
 
531
- var IN_PLACE = false;
532
- /* Allow usage of profiles like html, svg and mathMl */
534
+ var URI_SAFE_ATTRIBUTES = null;
535
+ var DEFAULT_URI_SAFE_ATTRIBUTES = addToSet({}, ['alt', 'class', 'for', 'id', 'label', 'name', 'pattern', 'placeholder', 'summary', 'title', 'value', 'style', 'xmlns']);
536
+ /* Keep a reference to config to pass to hooks */
533
537
 
534
- var USE_PROFILES = {};
535
- /* Tags to ignore content of when KEEP_CONTENT is true */
538
+ var CONFIG = null;
539
+ /* Ideally, do not touch anything below this line */
536
540
 
537
- var FORBID_CONTENTS = addToSet({}, ['audio', 'head', 'math', 'script', 'style', 'template', 'svg', 'video']);
538
- /* Tags that are safe for data: URIs */
541
+ /* ______________________________________________ */
539
542
 
540
- var DATA_URI_TAGS = addToSet({}, ['audio', 'video', 'img', 'source', 'image']);
541
- /* Attributes safe for values like "javascript:" */
543
+ var formElement = document.createElement('form');
544
+ /**
545
+ * _parseConfig
546
+ *
547
+ * @param {Object} cfg optional config literal
548
+ */
549
+ // eslint-disable-next-line complexity
542
550
 
543
- var URI_SAFE_ATTRIBUTES = null;
544
- var DEFAULT_URI_SAFE_ATTRIBUTES = addToSet({}, ['alt', 'class', 'for', 'id', 'label', 'name', 'pattern', 'placeholder', 'summary', 'title', 'value', 'style', 'xmlns']);
545
- /* Keep a reference to config to pass to hooks */
551
+ var _parseConfig = function _parseConfig(cfg) {
552
+ if (CONFIG && CONFIG === cfg) {
553
+ return;
554
+ }
555
+ /* Shield configuration object from tampering */
546
556
 
547
- var CONFIG = null;
548
- /* Ideally, do not touch anything below this line */
549
557
 
550
- /* ______________________________________________ */
558
+ if (!cfg || (typeof cfg === 'undefined' ? 'undefined' : _typeof$1(cfg)) !== 'object') {
559
+ cfg = {};
560
+ }
561
+ /* Set configuration parameters */
551
562
 
552
- var formElement = document.createElement('form');
553
- /**
554
- * _parseConfig
555
- *
556
- * @param {Object} cfg optional config literal
557
- */
558
- // eslint-disable-next-line complexity
559
563
 
560
- var _parseConfig = function _parseConfig(cfg) {
561
- if (CONFIG && CONFIG === cfg) {
562
- return;
563
- }
564
- /* Shield configuration object from tampering */
564
+ ALLOWED_TAGS = 'ALLOWED_TAGS' in cfg ? addToSet({}, cfg.ALLOWED_TAGS) : DEFAULT_ALLOWED_TAGS;
565
+ ALLOWED_ATTR = 'ALLOWED_ATTR' in cfg ? addToSet({}, cfg.ALLOWED_ATTR) : DEFAULT_ALLOWED_ATTR;
566
+ URI_SAFE_ATTRIBUTES = 'ADD_URI_SAFE_ATTR' in cfg ? addToSet({}, cfg.ADD_URI_SAFE_ATTR) : DEFAULT_URI_SAFE_ATTRIBUTES;
567
+ FORBID_TAGS = 'FORBID_TAGS' in cfg ? addToSet({}, cfg.FORBID_TAGS) : {};
568
+ FORBID_ATTR = 'FORBID_ATTR' in cfg ? addToSet({}, cfg.FORBID_ATTR) : {};
569
+ USE_PROFILES = 'USE_PROFILES' in cfg ? cfg.USE_PROFILES : false;
570
+ ALLOW_ARIA_ATTR = cfg.ALLOW_ARIA_ATTR !== false; // Default true
565
571
 
572
+ ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false; // Default true
566
573
 
567
- if (!cfg || (typeof cfg === 'undefined' ? 'undefined' : _typeof(cfg)) !== 'object') {
568
- cfg = {};
569
- }
570
- /* Set configuration parameters */
574
+ ALLOW_UNKNOWN_PROTOCOLS = cfg.ALLOW_UNKNOWN_PROTOCOLS || false; // Default false
571
575
 
576
+ SAFE_FOR_JQUERY = cfg.SAFE_FOR_JQUERY || false; // Default false
572
577
 
573
- ALLOWED_TAGS = 'ALLOWED_TAGS' in cfg ? addToSet({}, cfg.ALLOWED_TAGS) : DEFAULT_ALLOWED_TAGS;
574
- ALLOWED_ATTR = 'ALLOWED_ATTR' in cfg ? addToSet({}, cfg.ALLOWED_ATTR) : DEFAULT_ALLOWED_ATTR;
575
- URI_SAFE_ATTRIBUTES = 'ADD_URI_SAFE_ATTR' in cfg ? addToSet({}, cfg.ADD_URI_SAFE_ATTR) : DEFAULT_URI_SAFE_ATTRIBUTES;
576
- FORBID_TAGS = 'FORBID_TAGS' in cfg ? addToSet({}, cfg.FORBID_TAGS) : {};
577
- FORBID_ATTR = 'FORBID_ATTR' in cfg ? addToSet({}, cfg.FORBID_ATTR) : {};
578
- USE_PROFILES = 'USE_PROFILES' in cfg ? cfg.USE_PROFILES : false;
579
- ALLOW_ARIA_ATTR = cfg.ALLOW_ARIA_ATTR !== false; // Default true
578
+ SAFE_FOR_TEMPLATES = cfg.SAFE_FOR_TEMPLATES || false; // Default false
580
579
 
581
- ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false; // Default true
580
+ WHOLE_DOCUMENT = cfg.WHOLE_DOCUMENT || false; // Default false
582
581
 
583
- ALLOW_UNKNOWN_PROTOCOLS = cfg.ALLOW_UNKNOWN_PROTOCOLS || false; // Default false
582
+ RETURN_DOM = cfg.RETURN_DOM || false; // Default false
584
583
 
585
- SAFE_FOR_JQUERY = cfg.SAFE_FOR_JQUERY || false; // Default false
584
+ RETURN_DOM_FRAGMENT = cfg.RETURN_DOM_FRAGMENT || false; // Default false
586
585
 
587
- SAFE_FOR_TEMPLATES = cfg.SAFE_FOR_TEMPLATES || false; // Default false
586
+ RETURN_DOM_IMPORT = cfg.RETURN_DOM_IMPORT || false; // Default false
588
587
 
589
- WHOLE_DOCUMENT = cfg.WHOLE_DOCUMENT || false; // Default false
588
+ FORCE_BODY = cfg.FORCE_BODY || false; // Default false
590
589
 
591
- RETURN_DOM = cfg.RETURN_DOM || false; // Default false
590
+ SANITIZE_DOM = cfg.SANITIZE_DOM !== false; // Default true
592
591
 
593
- RETURN_DOM_FRAGMENT = cfg.RETURN_DOM_FRAGMENT || false; // Default false
592
+ KEEP_CONTENT = cfg.KEEP_CONTENT !== false; // Default true
594
593
 
595
- RETURN_DOM_IMPORT = cfg.RETURN_DOM_IMPORT || false; // Default false
594
+ IN_PLACE = cfg.IN_PLACE || false; // Default false
596
595
 
597
- FORCE_BODY = cfg.FORCE_BODY || false; // Default false
596
+ IS_ALLOWED_URI$$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI$$1;
598
597
 
599
- SANITIZE_DOM = cfg.SANITIZE_DOM !== false; // Default true
598
+ if (SAFE_FOR_TEMPLATES) {
599
+ ALLOW_DATA_ATTR = false;
600
+ }
600
601
 
601
- KEEP_CONTENT = cfg.KEEP_CONTENT !== false; // Default true
602
+ if (RETURN_DOM_FRAGMENT) {
603
+ RETURN_DOM = true;
604
+ }
605
+ /* Parse profile info */
602
606
 
603
- IN_PLACE = cfg.IN_PLACE || false; // Default false
604
607
 
605
- IS_ALLOWED_URI$$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI$$1;
608
+ if (USE_PROFILES) {
609
+ ALLOWED_TAGS = addToSet({}, [].concat(_toConsumableArray(text)));
610
+ ALLOWED_ATTR = [];
606
611
 
607
- if (SAFE_FOR_TEMPLATES) {
608
- ALLOW_DATA_ATTR = false;
612
+ if (USE_PROFILES.html === true) {
613
+ addToSet(ALLOWED_TAGS, html);
614
+ addToSet(ALLOWED_ATTR, html$1);
609
615
  }
610
616
 
611
- if (RETURN_DOM_FRAGMENT) {
612
- RETURN_DOM = true;
617
+ if (USE_PROFILES.svg === true) {
618
+ addToSet(ALLOWED_TAGS, svg);
619
+ addToSet(ALLOWED_ATTR, svg$1);
620
+ addToSet(ALLOWED_ATTR, xml);
613
621
  }
614
- /* Parse profile info */
615
622
 
623
+ if (USE_PROFILES.svgFilters === true) {
624
+ addToSet(ALLOWED_TAGS, svgFilters);
625
+ addToSet(ALLOWED_ATTR, svg$1);
626
+ addToSet(ALLOWED_ATTR, xml);
627
+ }
616
628
 
617
- if (USE_PROFILES) {
618
- ALLOWED_TAGS = addToSet({}, [].concat(_toConsumableArray(text)));
619
- ALLOWED_ATTR = [];
629
+ if (USE_PROFILES.mathMl === true) {
630
+ addToSet(ALLOWED_TAGS, mathMl);
631
+ addToSet(ALLOWED_ATTR, mathMl$1);
632
+ addToSet(ALLOWED_ATTR, xml);
633
+ }
634
+ }
635
+ /* Merge configuration parameters */
620
636
 
621
- if (USE_PROFILES.html === true) {
622
- addToSet(ALLOWED_TAGS, html);
623
- addToSet(ALLOWED_ATTR, html$1);
624
- }
625
637
 
626
- if (USE_PROFILES.svg === true) {
627
- addToSet(ALLOWED_TAGS, svg);
628
- addToSet(ALLOWED_ATTR, svg$1);
629
- addToSet(ALLOWED_ATTR, xml);
630
- }
638
+ if (cfg.ADD_TAGS) {
639
+ if (ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) {
640
+ ALLOWED_TAGS = clone(ALLOWED_TAGS);
641
+ }
631
642
 
632
- if (USE_PROFILES.svgFilters === true) {
633
- addToSet(ALLOWED_TAGS, svgFilters);
634
- addToSet(ALLOWED_ATTR, svg$1);
635
- addToSet(ALLOWED_ATTR, xml);
636
- }
643
+ addToSet(ALLOWED_TAGS, cfg.ADD_TAGS);
644
+ }
637
645
 
638
- if (USE_PROFILES.mathMl === true) {
639
- addToSet(ALLOWED_TAGS, mathMl);
640
- addToSet(ALLOWED_ATTR, mathMl$1);
641
- addToSet(ALLOWED_ATTR, xml);
642
- }
646
+ if (cfg.ADD_ATTR) {
647
+ if (ALLOWED_ATTR === DEFAULT_ALLOWED_ATTR) {
648
+ ALLOWED_ATTR = clone(ALLOWED_ATTR);
643
649
  }
644
- /* Merge configuration parameters */
645
-
646
650
 
647
- if (cfg.ADD_TAGS) {
648
- if (ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) {
649
- ALLOWED_TAGS = clone(ALLOWED_TAGS);
650
- }
651
+ addToSet(ALLOWED_ATTR, cfg.ADD_ATTR);
652
+ }
651
653
 
652
- addToSet(ALLOWED_TAGS, cfg.ADD_TAGS);
653
- }
654
+ if (cfg.ADD_URI_SAFE_ATTR) {
655
+ addToSet(URI_SAFE_ATTRIBUTES, cfg.ADD_URI_SAFE_ATTR);
656
+ }
657
+ /* Add #text in case KEEP_CONTENT is set to true */
654
658
 
655
- if (cfg.ADD_ATTR) {
656
- if (ALLOWED_ATTR === DEFAULT_ALLOWED_ATTR) {
657
- ALLOWED_ATTR = clone(ALLOWED_ATTR);
658
- }
659
659
 
660
- addToSet(ALLOWED_ATTR, cfg.ADD_ATTR);
661
- }
660
+ if (KEEP_CONTENT) {
661
+ ALLOWED_TAGS['#text'] = true;
662
+ }
663
+ /* Add html, head and body to ALLOWED_TAGS in case WHOLE_DOCUMENT is true */
662
664
 
663
- if (cfg.ADD_URI_SAFE_ATTR) {
664
- addToSet(URI_SAFE_ATTRIBUTES, cfg.ADD_URI_SAFE_ATTR);
665
- }
666
- /* Add #text in case KEEP_CONTENT is set to true */
667
665
 
666
+ if (WHOLE_DOCUMENT) {
667
+ addToSet(ALLOWED_TAGS, ['html', 'head', 'body']);
668
+ }
669
+ /* Add tbody to ALLOWED_TAGS in case tables are permitted, see #286 */
668
670
 
669
- if (KEEP_CONTENT) {
670
- ALLOWED_TAGS['#text'] = true;
671
- }
672
- /* Add html, head and body to ALLOWED_TAGS in case WHOLE_DOCUMENT is true */
673
671
 
672
+ if (ALLOWED_TAGS.table) {
673
+ addToSet(ALLOWED_TAGS, ['tbody']);
674
+ } // Prevent further manipulation of configuration.
675
+ // Not available in IE8, Safari 5, etc.
674
676
 
675
- if (WHOLE_DOCUMENT) {
676
- addToSet(ALLOWED_TAGS, ['html', 'head', 'body']);
677
- }
678
- /* Add tbody to ALLOWED_TAGS in case tables are permitted, see #286 */
679
677
 
678
+ if (freeze) {
679
+ freeze(cfg);
680
+ }
680
681
 
681
- if (ALLOWED_TAGS.table) {
682
- addToSet(ALLOWED_TAGS, ['tbody']);
683
- } // Prevent further manipulation of configuration.
684
- // Not available in IE8, Safari 5, etc.
682
+ CONFIG = cfg;
683
+ };
684
+ /**
685
+ * _forceRemove
686
+ *
687
+ * @param {Node} node a DOM node
688
+ */
685
689
 
686
690
 
687
- if (freeze) {
688
- freeze(cfg);
689
- }
691
+ var _forceRemove = function _forceRemove(node) {
692
+ DOMPurify.removed.push({
693
+ element: node
694
+ });
690
695
 
691
- CONFIG = cfg;
692
- };
693
- /**
694
- * _forceRemove
695
- *
696
- * @param {Node} node a DOM node
697
- */
696
+ try {
697
+ node.parentNode.removeChild(node);
698
+ } catch (error) {
699
+ node.outerHTML = emptyHTML;
700
+ }
701
+ };
702
+ /**
703
+ * _removeAttribute
704
+ *
705
+ * @param {String} name an Attribute name
706
+ * @param {Node} node a DOM node
707
+ */
698
708
 
699
709
 
700
- var _forceRemove = function _forceRemove(node) {
710
+ var _removeAttribute = function _removeAttribute(name, node) {
711
+ try {
701
712
  DOMPurify.removed.push({
702
- element: node
713
+ attribute: node.getAttributeNode(name),
714
+ from: node
703
715
  });
716
+ } catch (error) {
717
+ DOMPurify.removed.push({
718
+ attribute: null,
719
+ from: node
720
+ });
721
+ }
704
722
 
705
- try {
706
- node.parentNode.removeChild(node);
707
- } catch (error) {
708
- node.outerHTML = emptyHTML;
709
- }
710
- };
711
- /**
712
- * _removeAttribute
713
- *
714
- * @param {String} name an Attribute name
715
- * @param {Node} node a DOM node
716
- */
723
+ node.removeAttribute(name);
724
+ };
725
+ /**
726
+ * _initDocument
727
+ *
728
+ * @param {String} dirty a string of dirty markup
729
+ * @return {Document} a DOM, filled with the dirty markup
730
+ */
717
731
 
718
732
 
719
- var _removeAttribute = function _removeAttribute(name, node) {
720
- try {
721
- DOMPurify.removed.push({
722
- attribute: node.getAttributeNode(name),
723
- from: node
724
- });
725
- } catch (error) {
726
- DOMPurify.removed.push({
727
- attribute: null,
728
- from: node
729
- });
733
+ var _initDocument = function _initDocument(dirty) {
734
+ /* Create a HTML document */
735
+ var doc = void 0;
736
+ var leadingWhitespace = void 0;
737
+
738
+ if (FORCE_BODY) {
739
+ dirty = '<remove></remove>' + dirty;
740
+ } else {
741
+ /* If FORCE_BODY isn't used, leading whitespace needs to be preserved manually */
742
+ var matches = dirty.match(/^[\s]+/);
743
+ leadingWhitespace = matches && matches[0];
744
+
745
+ if (leadingWhitespace) {
746
+ dirty = dirty.slice(leadingWhitespace.length);
730
747
  }
748
+ }
749
+ /* Use DOMParser to workaround Firefox bug (see comment below) */
731
750
 
732
- node.removeAttribute(name);
733
- };
734
- /**
735
- * _initDocument
736
- *
737
- * @param {String} dirty a string of dirty markup
738
- * @return {Document} a DOM, filled with the dirty markup
739
- */
740
751
 
752
+ if (useDOMParser) {
753
+ try {
754
+ doc = new DOMParser().parseFromString(dirty, 'text/html');
755
+ } catch (error) {}
756
+ }
757
+ /* Remove title to fix a mXSS bug in older MS Edge */
741
758
 
742
- var _initDocument = function _initDocument(dirty) {
743
- /* Create a HTML document */
744
- var doc = void 0;
745
- var leadingWhitespace = void 0;
746
759
 
747
- if (FORCE_BODY) {
748
- dirty = '<remove></remove>' + dirty;
749
- } else {
750
- /* If FORCE_BODY isn't used, leading whitespace needs to be preserved manually */
751
- var matches = dirty.match(/^[\s]+/);
752
- leadingWhitespace = matches && matches[0];
760
+ if (removeTitle) {
761
+ addToSet(FORBID_TAGS, ['title']);
762
+ }
763
+ /* Otherwise use createHTMLDocument, because DOMParser is unsafe in
764
+ Safari (see comment below) */
753
765
 
754
- if (leadingWhitespace) {
755
- dirty = dirty.slice(leadingWhitespace.length);
756
- }
757
- }
758
- /* Use DOMParser to workaround Firefox bug (see comment below) */
759
766
 
767
+ if (!doc || !doc.documentElement) {
768
+ doc = implementation.createHTMLDocument('');
769
+ var _doc = doc,
770
+ body = _doc.body;
771
+ body.parentNode.removeChild(body.parentNode.firstElementChild);
772
+ body.outerHTML = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;
773
+ }
760
774
 
761
- if (useDOMParser) {
762
- try {
763
- doc = new DOMParser().parseFromString(dirty, 'text/html');
764
- } catch (error) {}
765
- }
766
- /* Remove title to fix a mXSS bug in older MS Edge */
775
+ if (leadingWhitespace) {
776
+ doc.body.insertBefore(document.createTextNode(leadingWhitespace), doc.body.childNodes[0] || null);
777
+ }
778
+ /* Work on whole document or just its body */
767
779
 
768
780
 
769
- if (removeTitle) {
770
- addToSet(FORBID_TAGS, ['title']);
771
- }
772
- /* Otherwise use createHTMLDocument, because DOMParser is unsafe in
773
- Safari (see comment below) */
781
+ return getElementsByTagName.call(doc, WHOLE_DOCUMENT ? 'html' : 'body')[0];
782
+ }; // Firefox uses a different parser for innerHTML rather than
783
+ // DOMParser (see https://bugzilla.mozilla.org/show_bug.cgi?id=1205631)
784
+ // which means that you *must* use DOMParser, otherwise the output may
785
+ // not be safe if used in a document.write context later.
786
+ //
787
+ // So we feature detect the Firefox bug and use the DOMParser if necessary.
788
+ //
789
+ // MS Edge, in older versions, is affected by an mXSS behavior. The second
790
+ // check tests for the behavior and fixes it if necessary.
774
791
 
775
792
 
776
- if (!doc || !doc.documentElement) {
777
- doc = implementation.createHTMLDocument('');
778
- var _doc = doc,
779
- body = _doc.body;
780
- body.parentNode.removeChild(body.parentNode.firstElementChild);
781
- body.outerHTML = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;
782
- }
793
+ if (DOMPurify.isSupported) {
794
+ (function () {
795
+ try {
796
+ var doc = _initDocument('<svg><p><style><img src="</style><img src=x onerror=1//">');
783
797
 
784
- if (leadingWhitespace) {
785
- doc.body.insertBefore(document.createTextNode(leadingWhitespace), doc.body.childNodes[0] || null);
786
- }
787
- /* Work on whole document or just its body */
798
+ if (doc.querySelector('svg img')) {
799
+ useDOMParser = true;
800
+ }
801
+ } catch (error) {}
802
+ })();
788
803
 
804
+ (function () {
805
+ try {
806
+ var doc = _initDocument('<x/><title>&lt;/title&gt;&lt;img&gt;');
789
807
 
790
- return getElementsByTagName.call(doc, WHOLE_DOCUMENT ? 'html' : 'body')[0];
791
- }; // Firefox uses a different parser for innerHTML rather than
792
- // DOMParser (see https://bugzilla.mozilla.org/show_bug.cgi?id=1205631)
793
- // which means that you *must* use DOMParser, otherwise the output may
794
- // not be safe if used in a document.write context later.
795
- //
796
- // So we feature detect the Firefox bug and use the DOMParser if necessary.
797
- //
798
- // MS Edge, in older versions, is affected by an mXSS behavior. The second
799
- // check tests for the behavior and fixes it if necessary.
808
+ if (doc.querySelector('title').innerHTML.match(/<\/title/)) {
809
+ removeTitle = true;
810
+ }
811
+ } catch (error) {}
812
+ })();
813
+ }
814
+ /**
815
+ * _createIterator
816
+ *
817
+ * @param {Document} root document/fragment to create iterator for
818
+ * @return {Iterator} iterator instance
819
+ */
800
820
 
801
821
 
802
- if (DOMPurify.isSupported) {
803
- (function () {
804
- try {
805
- var doc = _initDocument('<svg><p><style><img src="</style><img src=x onerror=1//">');
822
+ var _createIterator = function _createIterator(root) {
823
+ return createNodeIterator.call(root.ownerDocument || root, root, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT, function () {
824
+ return NodeFilter.FILTER_ACCEPT;
825
+ }, false);
826
+ };
827
+ /**
828
+ * _isClobbered
829
+ *
830
+ * @param {Node} elm element to check for clobbering attacks
831
+ * @return {Boolean} true if clobbered, false if safe
832
+ */
806
833
 
807
- if (doc.querySelector('svg img')) {
808
- useDOMParser = true;
809
- }
810
- } catch (error) {}
811
- })();
812
834
 
813
- (function () {
814
- try {
815
- var doc = _initDocument('<x/><title>&lt;/title&gt;&lt;img&gt;');
835
+ var _isClobbered = function _isClobbered(elm) {
836
+ if (elm instanceof Text || elm instanceof Comment) {
837
+ return false;
838
+ }
816
839
 
817
- if (doc.querySelector('title').innerHTML.match(/<\/title/)) {
818
- removeTitle = true;
819
- }
820
- } catch (error) {}
821
- })();
840
+ 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') {
841
+ return true;
822
842
  }
823
- /**
824
- * _createIterator
825
- *
826
- * @param {Document} root document/fragment to create iterator for
827
- * @return {Iterator} iterator instance
828
- */
829
843
 
844
+ return false;
845
+ };
846
+ /**
847
+ * _isNode
848
+ *
849
+ * @param {Node} obj object to check whether it's a DOM node
850
+ * @return {Boolean} true is object is a DOM node
851
+ */
830
852
 
831
- var _createIterator = function _createIterator(root) {
832
- return createNodeIterator.call(root.ownerDocument || root, root, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT, function () {
833
- return NodeFilter.FILTER_ACCEPT;
834
- }, false);
835
- };
836
- /**
837
- * _isClobbered
838
- *
839
- * @param {Node} elm element to check for clobbering attacks
840
- * @return {Boolean} true if clobbered, false if safe
841
- */
842
853
 
854
+ var _isNode = function _isNode(obj) {
855
+ 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';
856
+ };
857
+ /**
858
+ * _executeHook
859
+ * Execute user configurable hooks
860
+ *
861
+ * @param {String} entryPoint Name of the hook's entry point
862
+ * @param {Node} currentNode node to work on with the hook
863
+ * @param {Object} data additional hook parameters
864
+ */
843
865
 
844
- var _isClobbered = function _isClobbered(elm) {
845
- if (elm instanceof Text || elm instanceof Comment) {
846
- return false;
847
- }
848
866
 
849
- 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') {
850
- return true;
851
- }
867
+ var _executeHook = function _executeHook(entryPoint, currentNode, data) {
868
+ if (!hooks[entryPoint]) {
869
+ return;
870
+ }
852
871
 
853
- return false;
854
- };
855
- /**
856
- * _isNode
857
- *
858
- * @param {Node} obj object to check whether it's a DOM node
859
- * @return {Boolean} true is object is a DOM node
860
- */
872
+ hooks[entryPoint].forEach(function (hook) {
873
+ hook.call(DOMPurify, currentNode, data, CONFIG);
874
+ });
875
+ };
876
+ /**
877
+ * _sanitizeElements
878
+ *
879
+ * @protect nodeName
880
+ * @protect textContent
881
+ * @protect removeChild
882
+ *
883
+ * @param {Node} currentNode to check for permission to exist
884
+ * @return {Boolean} true if node was killed, false if left alive
885
+ */
886
+ // eslint-disable-next-line complexity
861
887
 
862
888
 
863
- var _isNode = function _isNode(obj) {
864
- 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';
865
- };
866
- /**
867
- * _executeHook
868
- * Execute user configurable hooks
869
- *
870
- * @param {String} entryPoint Name of the hook's entry point
871
- * @param {Node} currentNode node to work on with the hook
872
- * @param {Object} data additional hook parameters
873
- */
889
+ var _sanitizeElements = function _sanitizeElements(currentNode) {
890
+ var content = void 0;
891
+ /* Execute a hook if present */
874
892
 
893
+ _executeHook('beforeSanitizeElements', currentNode, null);
894
+ /* Check if element is clobbered or can clobber */
875
895
 
876
- var _executeHook = function _executeHook(entryPoint, currentNode, data) {
877
- if (!hooks[entryPoint]) {
878
- return;
879
- }
880
896
 
881
- hooks[entryPoint].forEach(function (hook) {
882
- hook.call(DOMPurify, currentNode, data, CONFIG);
883
- });
884
- };
885
- /**
886
- * _sanitizeElements
887
- *
888
- * @protect nodeName
889
- * @protect textContent
890
- * @protect removeChild
891
- *
892
- * @param {Node} currentNode to check for permission to exist
893
- * @return {Boolean} true if node was killed, false if left alive
894
- */
895
- // eslint-disable-next-line complexity
897
+ if (_isClobbered(currentNode)) {
898
+ _forceRemove(currentNode);
896
899
 
900
+ return true;
901
+ }
902
+ /* Now let's check the element's type and name */
897
903
 
898
- var _sanitizeElements = function _sanitizeElements(currentNode) {
899
- var content = void 0;
900
- /* Execute a hook if present */
901
904
 
902
- _executeHook('beforeSanitizeElements', currentNode, null);
903
- /* Check if element is clobbered or can clobber */
905
+ var tagName = currentNode.nodeName.toLowerCase();
906
+ /* Execute a hook if present */
904
907
 
908
+ _executeHook('uponSanitizeElement', currentNode, {
909
+ tagName: tagName,
910
+ allowedTags: ALLOWED_TAGS
911
+ });
912
+ /* Remove element if anything forbids its presence */
905
913
 
906
- if (_isClobbered(currentNode)) {
907
- _forceRemove(currentNode);
908
914
 
909
- return true;
915
+ if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
916
+ /* Keep content except for black-listed elements */
917
+ if (KEEP_CONTENT && !FORBID_CONTENTS[tagName] && typeof currentNode.insertAdjacentHTML === 'function') {
918
+ try {
919
+ var htmlToInsert = currentNode.innerHTML;
920
+ currentNode.insertAdjacentHTML('AfterEnd', trustedTypesPolicy ? trustedTypesPolicy.createHTML(htmlToInsert) : htmlToInsert);
921
+ } catch (error) {}
910
922
  }
911
- /* Now let's check the element's type and name */
912
923
 
924
+ _forceRemove(currentNode);
913
925
 
914
- var tagName = currentNode.nodeName.toLowerCase();
915
- /* Execute a hook if present */
926
+ return true;
927
+ }
928
+ /* Remove in case a noscript/noembed XSS is suspected */
916
929
 
917
- _executeHook('uponSanitizeElement', currentNode, {
918
- tagName: tagName,
919
- allowedTags: ALLOWED_TAGS
920
- });
921
- /* Remove element if anything forbids its presence */
922
930
 
931
+ if (tagName === 'noscript' && currentNode.innerHTML.match(/<\/noscript/i)) {
932
+ _forceRemove(currentNode);
923
933
 
924
- if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
925
- /* Keep content except for black-listed elements */
926
- if (KEEP_CONTENT && !FORBID_CONTENTS[tagName] && typeof currentNode.insertAdjacentHTML === 'function') {
927
- try {
928
- var htmlToInsert = currentNode.innerHTML;
929
- currentNode.insertAdjacentHTML('AfterEnd', trustedTypesPolicy ? trustedTypesPolicy.createHTML(htmlToInsert) : htmlToInsert);
930
- } catch (error) {}
931
- }
934
+ return true;
935
+ }
932
936
 
933
- _forceRemove(currentNode);
937
+ if (tagName === 'noembed' && currentNode.innerHTML.match(/<\/noembed/i)) {
938
+ _forceRemove(currentNode);
934
939
 
935
- return true;
936
- }
937
- /* Remove in case a noscript/noembed XSS is suspected */
940
+ return true;
941
+ }
942
+ /* Convert markup to cover jQuery behavior */
938
943
 
939
944
 
940
- if (tagName === 'noscript' && currentNode.innerHTML.match(/<\/noscript/i)) {
941
- _forceRemove(currentNode);
945
+ if (SAFE_FOR_JQUERY && !currentNode.firstElementChild && (!currentNode.content || !currentNode.content.firstElementChild) && /</g.test(currentNode.textContent)) {
946
+ DOMPurify.removed.push({
947
+ element: currentNode.cloneNode()
948
+ });
942
949
 
943
- return true;
950
+ if (currentNode.innerHTML) {
951
+ currentNode.innerHTML = currentNode.innerHTML.replace(/</g, '&lt;');
952
+ } else {
953
+ currentNode.innerHTML = currentNode.textContent.replace(/</g, '&lt;');
944
954
  }
955
+ }
956
+ /* Sanitize element content to be template-safe */
945
957
 
946
- if (tagName === 'noembed' && currentNode.innerHTML.match(/<\/noembed/i)) {
947
- _forceRemove(currentNode);
948
-
949
- return true;
950
- }
951
- /* Convert markup to cover jQuery behavior */
952
958
 
959
+ if (SAFE_FOR_TEMPLATES && currentNode.nodeType === 3) {
960
+ /* Get the element's text content */
961
+ content = currentNode.textContent;
962
+ content = content.replace(MUSTACHE_EXPR$$1, ' ');
963
+ content = content.replace(ERB_EXPR$$1, ' ');
953
964
 
954
- if (SAFE_FOR_JQUERY && !currentNode.firstElementChild && (!currentNode.content || !currentNode.content.firstElementChild) && /</g.test(currentNode.textContent)) {
965
+ if (currentNode.textContent !== content) {
955
966
  DOMPurify.removed.push({
956
967
  element: currentNode.cloneNode()
957
968
  });
958
-
959
- if (currentNode.innerHTML) {
960
- currentNode.innerHTML = currentNode.innerHTML.replace(/</g, '&lt;');
961
- } else {
962
- currentNode.innerHTML = currentNode.textContent.replace(/</g, '&lt;');
963
- }
969
+ currentNode.textContent = content;
964
970
  }
965
- /* Sanitize element content to be template-safe */
971
+ }
972
+ /* Execute a hook if present */
966
973
 
967
974
 
968
- if (SAFE_FOR_TEMPLATES && currentNode.nodeType === 3) {
969
- /* Get the element's text content */
970
- content = currentNode.textContent;
971
- content = content.replace(MUSTACHE_EXPR$$1, ' ');
972
- content = content.replace(ERB_EXPR$$1, ' ');
975
+ _executeHook('afterSanitizeElements', currentNode, null);
976
+
977
+ return false;
978
+ };
979
+ /**
980
+ * _isValidAttribute
981
+ *
982
+ * @param {string} lcTag Lowercase tag name of containing element.
983
+ * @param {string} lcName Lowercase attribute name.
984
+ * @param {string} value Attribute value.
985
+ * @return {Boolean} Returns true if `value` is valid, otherwise false.
986
+ */
987
+ // eslint-disable-next-line complexity
973
988
 
974
- if (currentNode.textContent !== content) {
975
- DOMPurify.removed.push({
976
- element: currentNode.cloneNode()
977
- });
978
- currentNode.textContent = content;
979
- }
980
- }
981
- /* Execute a hook if present */
982
989
 
990
+ var _isValidAttribute = function _isValidAttribute(lcTag, lcName, value) {
991
+ /* Make sure attribute cannot clobber */
992
+ if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in document || value in formElement)) {
993
+ return false;
994
+ }
995
+ /* Allow valid data-* attributes: At least one character after "-"
996
+ (https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes)
997
+ XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804)
998
+ We don't need to check the value; it's always URI safe. */
983
999
 
984
- _executeHook('afterSanitizeElements', currentNode, null);
985
1000
 
1001
+ 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]) {
986
1002
  return false;
987
- };
988
- /**
989
- * _isValidAttribute
990
- *
991
- * @param {string} lcTag Lowercase tag name of containing element.
992
- * @param {string} lcName Lowercase attribute name.
993
- * @param {string} value Attribute value.
994
- * @return {Boolean} Returns true if `value` is valid, otherwise false.
995
- */
996
- // eslint-disable-next-line complexity
1003
+ /* Check value is safe. First, is attr inert? If so, is safe */
1004
+ } 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 {
1005
+ return false;
1006
+ }
997
1007
 
1008
+ return true;
1009
+ };
1010
+ /**
1011
+ * _sanitizeAttributes
1012
+ *
1013
+ * @protect attributes
1014
+ * @protect nodeName
1015
+ * @protect removeAttribute
1016
+ * @protect setAttribute
1017
+ *
1018
+ * @param {Node} currentNode to sanitize
1019
+ */
998
1020
 
999
- var _isValidAttribute = function _isValidAttribute(lcTag, lcName, value) {
1000
- /* Make sure attribute cannot clobber */
1001
- if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in document || value in formElement)) {
1002
- return false;
1003
- }
1004
- /* Allow valid data-* attributes: At least one character after "-"
1005
- (https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes)
1006
- XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804)
1007
- We don't need to check the value; it's always URI safe. */
1008
1021
 
1022
+ var _sanitizeAttributes = function _sanitizeAttributes(currentNode) {
1023
+ var attr = void 0;
1024
+ var value = void 0;
1025
+ var lcName = void 0;
1026
+ var idAttr = void 0;
1027
+ var l = void 0;
1028
+ /* Execute a hook if present */
1009
1029
 
1010
- 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]) {
1011
- return false;
1012
- /* Check value is safe. First, is attr inert? If so, is safe */
1013
- } 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 {
1014
- return false;
1015
- }
1030
+ _executeHook('beforeSanitizeAttributes', currentNode, null);
1016
1031
 
1017
- return true;
1018
- };
1019
- /**
1020
- * _sanitizeAttributes
1021
- *
1022
- * @protect attributes
1023
- * @protect nodeName
1024
- * @protect removeAttribute
1025
- * @protect setAttribute
1026
- *
1027
- * @param {Node} currentNode to sanitize
1028
- */
1032
+ var attributes = currentNode.attributes;
1033
+ /* Check if we have attributes; if not we might have a text node */
1034
+
1035
+ if (!attributes) {
1036
+ return;
1037
+ }
1029
1038
 
1039
+ var hookEvent = {
1040
+ attrName: '',
1041
+ attrValue: '',
1042
+ keepAttr: true,
1043
+ allowedAttributes: ALLOWED_ATTR
1044
+ };
1045
+ l = attributes.length;
1046
+ /* Go backwards over all attributes; safely remove bad ones */
1030
1047
 
1031
- var _sanitizeAttributes = function _sanitizeAttributes(currentNode) {
1032
- var attr = void 0;
1033
- var value = void 0;
1034
- var lcName = void 0;
1035
- var idAttr = void 0;
1036
- var l = void 0;
1048
+ while (l--) {
1049
+ attr = attributes[l];
1050
+ var _attr = attr,
1051
+ name = _attr.name,
1052
+ namespaceURI = _attr.namespaceURI;
1053
+ value = attr.value.trim();
1054
+ lcName = name.toLowerCase();
1037
1055
  /* Execute a hook if present */
1038
1056
 
1039
- _executeHook('beforeSanitizeAttributes', currentNode, null);
1057
+ hookEvent.attrName = lcName;
1058
+ hookEvent.attrValue = value;
1059
+ hookEvent.keepAttr = true;
1040
1060
 
1041
- var attributes = currentNode.attributes;
1042
- /* Check if we have attributes; if not we might have a text node */
1061
+ _executeHook('uponSanitizeAttribute', currentNode, hookEvent);
1043
1062
 
1044
- if (!attributes) {
1045
- return;
1046
- }
1063
+ value = hookEvent.attrValue;
1064
+ /* Remove attribute */
1065
+ // Safari (iOS + Mac), last tested v8.0.5, crashes if you try to
1066
+ // remove a "name" attribute from an <img> tag that has an "id"
1067
+ // attribute at the time.
1047
1068
 
1048
- var hookEvent = {
1049
- attrName: '',
1050
- attrValue: '',
1051
- keepAttr: true,
1052
- allowedAttributes: ALLOWED_ATTR
1053
- };
1054
- l = attributes.length;
1055
- /* Go backwards over all attributes; safely remove bad ones */
1056
-
1057
- while (l--) {
1058
- attr = attributes[l];
1059
- var _attr = attr,
1060
- name = _attr.name,
1061
- namespaceURI = _attr.namespaceURI;
1062
- value = attr.value.trim();
1063
- lcName = name.toLowerCase();
1064
- /* Execute a hook if present */
1065
-
1066
- hookEvent.attrName = lcName;
1067
- hookEvent.attrValue = value;
1068
- hookEvent.keepAttr = true;
1069
-
1070
- _executeHook('uponSanitizeAttribute', currentNode, hookEvent);
1071
-
1072
- value = hookEvent.attrValue;
1073
- /* Remove attribute */
1074
- // Safari (iOS + Mac), last tested v8.0.5, crashes if you try to
1075
- // remove a "name" attribute from an <img> tag that has an "id"
1076
- // attribute at the time.
1077
-
1078
- if (lcName === 'name' && currentNode.nodeName === 'IMG' && attributes.id) {
1079
- idAttr = attributes.id;
1080
- attributes = apply(arraySlice, attributes, []);
1081
-
1082
- _removeAttribute('id', currentNode);
1083
-
1084
- _removeAttribute(name, currentNode);
1085
-
1086
- if (attributes.indexOf(idAttr) > l) {
1087
- currentNode.setAttribute('id', idAttr.value);
1088
- }
1089
- } else if ( // This works around a bug in Safari, where input[type=file]
1090
- // cannot be dynamically set after type has been removed
1091
- currentNode.nodeName === 'INPUT' && lcName === 'type' && value === 'file' && hookEvent.keepAttr && (ALLOWED_ATTR[lcName] || !FORBID_ATTR[lcName])) {
1092
- continue;
1093
- } else {
1094
- // This avoids a crash in Safari v9.0 with double-ids.
1095
- // The trick is to first set the id to be empty and then to
1096
- // remove the attribute
1097
- if (name === 'id') {
1098
- currentNode.setAttribute(name, '');
1099
- }
1100
-
1101
- _removeAttribute(name, currentNode);
1102
- }
1103
- /* Did the hooks approve of the attribute? */
1069
+ if (lcName === 'name' && currentNode.nodeName === 'IMG' && attributes.id) {
1070
+ idAttr = attributes.id;
1071
+ attributes = apply(arraySlice, attributes, []);
1104
1072
 
1073
+ _removeAttribute('id', currentNode);
1105
1074
 
1106
- if (!hookEvent.keepAttr) {
1107
- continue;
1108
- }
1109
- /* Sanitize attribute content to be template-safe */
1110
-
1075
+ _removeAttribute(name, currentNode);
1111
1076
 
1112
- if (SAFE_FOR_TEMPLATES) {
1113
- value = value.replace(MUSTACHE_EXPR$$1, ' ');
1114
- value = value.replace(ERB_EXPR$$1, ' ');
1077
+ if (attributes.indexOf(idAttr) > l) {
1078
+ currentNode.setAttribute('id', idAttr.value);
1079
+ }
1080
+ } else if ( // This works around a bug in Safari, where input[type=file]
1081
+ // cannot be dynamically set after type has been removed
1082
+ currentNode.nodeName === 'INPUT' && lcName === 'type' && value === 'file' && hookEvent.keepAttr && (ALLOWED_ATTR[lcName] || !FORBID_ATTR[lcName])) {
1083
+ continue;
1084
+ } else {
1085
+ // This avoids a crash in Safari v9.0 with double-ids.
1086
+ // The trick is to first set the id to be empty and then to
1087
+ // remove the attribute
1088
+ if (name === 'id') {
1089
+ currentNode.setAttribute(name, '');
1115
1090
  }
1116
- /* Is `value` valid for this attribute? */
1117
1091
 
1092
+ _removeAttribute(name, currentNode);
1093
+ }
1094
+ /* Did the hooks approve of the attribute? */
1118
1095
 
1119
- var lcTag = currentNode.nodeName.toLowerCase();
1120
1096
 
1121
- if (!_isValidAttribute(lcTag, lcName, value)) {
1122
- continue;
1123
- }
1124
- /* Handle invalid data-* attribute set by try-catching it */
1097
+ if (!hookEvent.keepAttr) {
1098
+ continue;
1099
+ }
1100
+ /* Sanitize attribute content to be template-safe */
1125
1101
 
1126
1102
 
1127
- try {
1128
- if (namespaceURI) {
1129
- currentNode.setAttributeNS(namespaceURI, name, value);
1130
- } else {
1131
- /* Fallback to setAttribute() for browser-unrecognized namespaces e.g. "x-schema". */
1132
- currentNode.setAttribute(name, value);
1133
- }
1134
-
1135
- DOMPurify.removed.pop();
1136
- } catch (error) {}
1103
+ if (SAFE_FOR_TEMPLATES) {
1104
+ value = value.replace(MUSTACHE_EXPR$$1, ' ');
1105
+ value = value.replace(ERB_EXPR$$1, ' ');
1137
1106
  }
1138
- /* Execute a hook if present */
1107
+ /* Is `value` valid for this attribute? */
1139
1108
 
1140
1109
 
1141
- _executeHook('afterSanitizeAttributes', currentNode, null);
1142
- };
1143
- /**
1144
- * _sanitizeShadowDOM
1145
- *
1146
- * @param {DocumentFragment} fragment to iterate over recursively
1147
- */
1110
+ var lcTag = currentNode.nodeName.toLowerCase();
1148
1111
 
1112
+ if (!_isValidAttribute(lcTag, lcName, value)) {
1113
+ continue;
1114
+ }
1115
+ /* Handle invalid data-* attribute set by try-catching it */
1149
1116
 
1150
- var _sanitizeShadowDOM = function _sanitizeShadowDOM(fragment) {
1151
- var shadowNode = void 0;
1152
1117
 
1153
- var shadowIterator = _createIterator(fragment);
1154
- /* Execute a hook if present */
1118
+ try {
1119
+ if (namespaceURI) {
1120
+ currentNode.setAttributeNS(namespaceURI, name, value);
1121
+ } else {
1122
+ /* Fallback to setAttribute() for browser-unrecognized namespaces e.g. "x-schema". */
1123
+ currentNode.setAttribute(name, value);
1124
+ }
1155
1125
 
1126
+ DOMPurify.removed.pop();
1127
+ } catch (error) {}
1128
+ }
1129
+ /* Execute a hook if present */
1156
1130
 
1157
- _executeHook('beforeSanitizeShadowDOM', fragment, null);
1158
1131
 
1159
- while (shadowNode = shadowIterator.nextNode()) {
1160
- /* Execute a hook if present */
1161
- _executeHook('uponSanitizeShadowNode', shadowNode, null);
1162
- /* Sanitize tags and elements */
1132
+ _executeHook('afterSanitizeAttributes', currentNode, null);
1133
+ };
1134
+ /**
1135
+ * _sanitizeShadowDOM
1136
+ *
1137
+ * @param {DocumentFragment} fragment to iterate over recursively
1138
+ */
1163
1139
 
1164
1140
 
1165
- if (_sanitizeElements(shadowNode)) {
1166
- continue;
1167
- }
1168
- /* Deep shadow DOM detected */
1141
+ var _sanitizeShadowDOM = function _sanitizeShadowDOM(fragment) {
1142
+ var shadowNode = void 0;
1169
1143
 
1144
+ var shadowIterator = _createIterator(fragment);
1145
+ /* Execute a hook if present */
1170
1146
 
1171
- if (shadowNode.content instanceof DocumentFragment) {
1172
- _sanitizeShadowDOM(shadowNode.content);
1173
- }
1174
- /* Check attributes, sanitize if necessary */
1175
1147
 
1148
+ _executeHook('beforeSanitizeShadowDOM', fragment, null);
1176
1149
 
1177
- _sanitizeAttributes(shadowNode);
1178
- }
1150
+ while (shadowNode = shadowIterator.nextNode()) {
1179
1151
  /* Execute a hook if present */
1152
+ _executeHook('uponSanitizeShadowNode', shadowNode, null);
1153
+ /* Sanitize tags and elements */
1180
1154
 
1181
1155
 
1182
- _executeHook('afterSanitizeShadowDOM', fragment, null);
1183
- };
1184
- /**
1185
- * Sanitize
1186
- * Public method providing core sanitation functionality
1187
- *
1188
- * @param {String|Node} dirty string or DOM node
1189
- * @param {Object} configuration object
1190
- */
1191
- // eslint-disable-next-line complexity
1192
-
1193
-
1194
- DOMPurify.sanitize = function (dirty, cfg) {
1195
- var body = void 0;
1196
- var importedNode = void 0;
1197
- var currentNode = void 0;
1198
- var oldNode = void 0;
1199
- var returnNode = void 0;
1200
- /* Make sure we have a string to sanitize.
1201
- DO NOT return early, as this will return the wrong type if
1202
- the user has requested a DOM object rather than a string */
1203
-
1204
- if (!dirty) {
1205
- dirty = '<!-->';
1156
+ if (_sanitizeElements(shadowNode)) {
1157
+ continue;
1206
1158
  }
1207
- /* Stringify, in case dirty is an object */
1208
-
1159
+ /* Deep shadow DOM detected */
1209
1160
 
1210
- if (typeof dirty !== 'string' && !_isNode(dirty)) {
1211
- // eslint-disable-next-line no-negated-condition
1212
- if (typeof dirty.toString !== 'function') {
1213
- throw new TypeError('toString is not a function');
1214
- } else {
1215
- dirty = dirty.toString();
1216
1161
 
1217
- if (typeof dirty !== 'string') {
1218
- throw new TypeError('dirty is not a string, aborting');
1219
- }
1220
- }
1162
+ if (shadowNode.content instanceof DocumentFragment) {
1163
+ _sanitizeShadowDOM(shadowNode.content);
1221
1164
  }
1222
- /* Check we can run. Otherwise fall back or ignore */
1223
-
1165
+ /* Check attributes, sanitize if necessary */
1224
1166
 
1225
- if (!DOMPurify.isSupported) {
1226
- if (_typeof(window.toStaticHTML) === 'object' || typeof window.toStaticHTML === 'function') {
1227
- if (typeof dirty === 'string') {
1228
- return window.toStaticHTML(dirty);
1229
- }
1230
1167
 
1231
- if (_isNode(dirty)) {
1232
- return window.toStaticHTML(dirty.outerHTML);
1233
- }
1234
- }
1168
+ _sanitizeAttributes(shadowNode);
1169
+ }
1170
+ /* Execute a hook if present */
1235
1171
 
1236
- return dirty;
1237
- }
1238
- /* Assign config vars */
1239
1172
 
1173
+ _executeHook('afterSanitizeShadowDOM', fragment, null);
1174
+ };
1175
+ /**
1176
+ * Sanitize
1177
+ * Public method providing core sanitation functionality
1178
+ *
1179
+ * @param {String|Node} dirty string or DOM node
1180
+ * @param {Object} configuration object
1181
+ */
1182
+ // eslint-disable-next-line complexity
1240
1183
 
1241
- if (!SET_CONFIG) {
1242
- _parseConfig(cfg);
1243
- }
1244
- /* Clean up removed elements */
1245
1184
 
1185
+ DOMPurify.sanitize = function (dirty, cfg) {
1186
+ var body = void 0;
1187
+ var importedNode = void 0;
1188
+ var currentNode = void 0;
1189
+ var oldNode = void 0;
1190
+ var returnNode = void 0;
1191
+ /* Make sure we have a string to sanitize.
1192
+ DO NOT return early, as this will return the wrong type if
1193
+ the user has requested a DOM object rather than a string */
1246
1194
 
1247
- DOMPurify.removed = [];
1195
+ if (!dirty) {
1196
+ dirty = '<!-->';
1197
+ }
1198
+ /* Stringify, in case dirty is an object */
1248
1199
 
1249
- if (IN_PLACE) ; else if (dirty instanceof Node) {
1250
- /* If dirty is a DOM element, append to an empty document to avoid
1251
- elements being stripped by the parser */
1252
- body = _initDocument('<!-->');
1253
- importedNode = body.ownerDocument.importNode(dirty, true);
1254
1200
 
1255
- if (importedNode.nodeType === 1 && importedNode.nodeName === 'BODY') {
1256
- /* Node is already a body, use as is */
1257
- body = importedNode;
1258
- } else if (importedNode.nodeName === 'HTML') {
1259
- body = importedNode;
1260
- } else {
1261
- // eslint-disable-next-line unicorn/prefer-node-append
1262
- body.appendChild(importedNode);
1263
- }
1201
+ if (typeof dirty !== 'string' && !_isNode(dirty)) {
1202
+ // eslint-disable-next-line no-negated-condition
1203
+ if (typeof dirty.toString !== 'function') {
1204
+ throw new TypeError('toString is not a function');
1264
1205
  } else {
1265
- /* Exit directly if we have nothing to do */
1266
- if (!RETURN_DOM && !SAFE_FOR_TEMPLATES && !WHOLE_DOCUMENT && dirty.indexOf('<') === -1) {
1267
- return trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;
1206
+ dirty = dirty.toString();
1207
+
1208
+ if (typeof dirty !== 'string') {
1209
+ throw new TypeError('dirty is not a string, aborting');
1268
1210
  }
1269
- /* Initialize the document to work on */
1211
+ }
1212
+ }
1213
+ /* Check we can run. Otherwise fall back or ignore */
1270
1214
 
1271
1215
 
1272
- body = _initDocument(dirty);
1273
- /* Check we have a DOM node from the data */
1216
+ if (!DOMPurify.isSupported) {
1217
+ if (_typeof$1(window.toStaticHTML) === 'object' || typeof window.toStaticHTML === 'function') {
1218
+ if (typeof dirty === 'string') {
1219
+ return window.toStaticHTML(dirty);
1220
+ }
1274
1221
 
1275
- if (!body) {
1276
- return RETURN_DOM ? null : emptyHTML;
1222
+ if (_isNode(dirty)) {
1223
+ return window.toStaticHTML(dirty.outerHTML);
1277
1224
  }
1278
1225
  }
1279
- /* Remove first element node (ours) if FORCE_BODY is set */
1280
1226
 
1227
+ return dirty;
1228
+ }
1229
+ /* Assign config vars */
1281
1230
 
1282
- if (body && FORCE_BODY) {
1283
- _forceRemove(body.firstChild);
1284
- }
1285
- /* Get node iterator */
1286
1231
 
1232
+ if (!SET_CONFIG) {
1233
+ _parseConfig(cfg);
1234
+ }
1235
+ /* Clean up removed elements */
1287
1236
 
1288
- var nodeIterator = _createIterator(IN_PLACE ? dirty : body);
1289
- /* Now start iterating over the created document */
1290
1237
 
1238
+ DOMPurify.removed = [];
1291
1239
 
1292
- while (currentNode = nodeIterator.nextNode()) {
1293
- /* Fix IE's strange behavior with manipulated textNodes #89 */
1294
- if (currentNode.nodeType === 3 && currentNode === oldNode) {
1295
- continue;
1296
- }
1297
- /* Sanitize tags and elements */
1240
+ if (IN_PLACE) ; else if (dirty instanceof Node) {
1241
+ /* If dirty is a DOM element, append to an empty document to avoid
1242
+ elements being stripped by the parser */
1243
+ body = _initDocument('<!-->');
1244
+ importedNode = body.ownerDocument.importNode(dirty, true);
1245
+
1246
+ if (importedNode.nodeType === 1 && importedNode.nodeName === 'BODY') {
1247
+ /* Node is already a body, use as is */
1248
+ body = importedNode;
1249
+ } else if (importedNode.nodeName === 'HTML') {
1250
+ body = importedNode;
1251
+ } else {
1252
+ // eslint-disable-next-line unicorn/prefer-node-append
1253
+ body.appendChild(importedNode);
1254
+ }
1255
+ } else {
1256
+ /* Exit directly if we have nothing to do */
1257
+ if (!RETURN_DOM && !SAFE_FOR_TEMPLATES && !WHOLE_DOCUMENT && dirty.indexOf('<') === -1) {
1258
+ return trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;
1259
+ }
1260
+ /* Initialize the document to work on */
1298
1261
 
1299
1262
 
1300
- if (_sanitizeElements(currentNode)) {
1301
- continue;
1302
- }
1303
- /* Shadow DOM detected, sanitize it */
1263
+ body = _initDocument(dirty);
1264
+ /* Check we have a DOM node from the data */
1304
1265
 
1266
+ if (!body) {
1267
+ return RETURN_DOM ? null : emptyHTML;
1268
+ }
1269
+ }
1270
+ /* Remove first element node (ours) if FORCE_BODY is set */
1305
1271
 
1306
- if (currentNode.content instanceof DocumentFragment) {
1307
- _sanitizeShadowDOM(currentNode.content);
1308
- }
1309
- /* Check attributes, sanitize if necessary */
1310
1272
 
1273
+ if (body && FORCE_BODY) {
1274
+ _forceRemove(body.firstChild);
1275
+ }
1276
+ /* Get node iterator */
1311
1277
 
1312
- _sanitizeAttributes(currentNode);
1313
1278
 
1314
- oldNode = currentNode;
1315
- }
1279
+ var nodeIterator = _createIterator(IN_PLACE ? dirty : body);
1280
+ /* Now start iterating over the created document */
1316
1281
 
1317
- oldNode = null;
1318
- /* If we sanitized `dirty` in-place, return it. */
1319
1282
 
1320
- if (IN_PLACE) {
1321
- return dirty;
1283
+ while (currentNode = nodeIterator.nextNode()) {
1284
+ /* Fix IE's strange behavior with manipulated textNodes #89 */
1285
+ if (currentNode.nodeType === 3 && currentNode === oldNode) {
1286
+ continue;
1322
1287
  }
1323
- /* Return sanitized string or DOM */
1324
-
1288
+ /* Sanitize tags and elements */
1325
1289
 
1326
- if (RETURN_DOM) {
1327
- if (RETURN_DOM_FRAGMENT) {
1328
- returnNode = createDocumentFragment.call(body.ownerDocument);
1329
1290
 
1330
- while (body.firstChild) {
1331
- // eslint-disable-next-line unicorn/prefer-node-append
1332
- returnNode.appendChild(body.firstChild);
1333
- }
1334
- } else {
1335
- returnNode = body;
1336
- }
1337
-
1338
- if (RETURN_DOM_IMPORT) {
1339
- /* AdoptNode() is not used because internal state is not reset
1340
- (e.g. the past names map of a HTMLFormElement), this is safe
1341
- in theory but we would rather not risk another attack vector.
1342
- The state that is cloned by importNode() is explicitly defined
1343
- by the specs. */
1344
- returnNode = importNode.call(originalDocument, returnNode, true);
1345
- }
1346
-
1347
- return returnNode;
1291
+ if (_sanitizeElements(currentNode)) {
1292
+ continue;
1348
1293
  }
1294
+ /* Shadow DOM detected, sanitize it */
1349
1295
 
1350
- var serializedHTML = WHOLE_DOCUMENT ? body.outerHTML : body.innerHTML;
1351
- /* Sanitize final string template-safe */
1352
1296
 
1353
- if (SAFE_FOR_TEMPLATES) {
1354
- serializedHTML = serializedHTML.replace(MUSTACHE_EXPR$$1, ' ');
1355
- serializedHTML = serializedHTML.replace(ERB_EXPR$$1, ' ');
1297
+ if (currentNode.content instanceof DocumentFragment) {
1298
+ _sanitizeShadowDOM(currentNode.content);
1356
1299
  }
1300
+ /* Check attributes, sanitize if necessary */
1357
1301
 
1358
- return trustedTypesPolicy ? trustedTypesPolicy.createHTML(serializedHTML) : serializedHTML;
1359
- };
1360
- /**
1361
- * Public method to set the configuration once
1362
- * setConfig
1363
- *
1364
- * @param {Object} cfg configuration object
1365
- */
1366
1302
 
1303
+ _sanitizeAttributes(currentNode);
1367
1304
 
1368
- DOMPurify.setConfig = function (cfg) {
1369
- _parseConfig(cfg);
1305
+ oldNode = currentNode;
1306
+ }
1370
1307
 
1371
- SET_CONFIG = true;
1372
- };
1373
- /**
1374
- * Public method to remove the configuration
1375
- * clearConfig
1376
- *
1377
- */
1308
+ oldNode = null;
1309
+ /* If we sanitized `dirty` in-place, return it. */
1378
1310
 
1311
+ if (IN_PLACE) {
1312
+ return dirty;
1313
+ }
1314
+ /* Return sanitized string or DOM */
1379
1315
 
1380
- DOMPurify.clearConfig = function () {
1381
- CONFIG = null;
1382
- SET_CONFIG = false;
1383
- };
1384
- /**
1385
- * Public method to check if an attribute value is valid.
1386
- * Uses last set config, if any. Otherwise, uses config defaults.
1387
- * isValidAttribute
1388
- *
1389
- * @param {string} tag Tag name of containing element.
1390
- * @param {string} attr Attribute name.
1391
- * @param {string} value Attribute value.
1392
- * @return {Boolean} Returns true if `value` is valid. Otherwise, returns false.
1393
- */
1394
1316
 
1317
+ if (RETURN_DOM) {
1318
+ if (RETURN_DOM_FRAGMENT) {
1319
+ returnNode = createDocumentFragment.call(body.ownerDocument);
1395
1320
 
1396
- DOMPurify.isValidAttribute = function (tag, attr, value) {
1397
- /* Initialize shared config vars if necessary. */
1398
- if (!CONFIG) {
1399
- _parseConfig({});
1321
+ while (body.firstChild) {
1322
+ // eslint-disable-next-line unicorn/prefer-node-append
1323
+ returnNode.appendChild(body.firstChild);
1324
+ }
1325
+ } else {
1326
+ returnNode = body;
1400
1327
  }
1401
1328
 
1402
- var lcTag = tag.toLowerCase();
1403
- var lcName = attr.toLowerCase();
1404
- return _isValidAttribute(lcTag, lcName, value);
1405
- };
1406
- /**
1407
- * AddHook
1408
- * Public method to add DOMPurify hooks
1409
- *
1410
- * @param {String} entryPoint entry point for the hook to add
1411
- * @param {Function} hookFunction function to execute
1412
- */
1329
+ if (RETURN_DOM_IMPORT) {
1330
+ /* AdoptNode() is not used because internal state is not reset
1331
+ (e.g. the past names map of a HTMLFormElement), this is safe
1332
+ in theory but we would rather not risk another attack vector.
1333
+ The state that is cloned by importNode() is explicitly defined
1334
+ by the specs. */
1335
+ returnNode = importNode.call(originalDocument, returnNode, true);
1336
+ }
1413
1337
 
1338
+ return returnNode;
1339
+ }
1414
1340
 
1415
- DOMPurify.addHook = function (entryPoint, hookFunction) {
1416
- if (typeof hookFunction !== 'function') {
1417
- return;
1418
- }
1341
+ var serializedHTML = WHOLE_DOCUMENT ? body.outerHTML : body.innerHTML;
1342
+ /* Sanitize final string template-safe */
1419
1343
 
1420
- hooks[entryPoint] = hooks[entryPoint] || [];
1421
- hooks[entryPoint].push(hookFunction);
1422
- };
1423
- /**
1424
- * RemoveHook
1425
- * Public method to remove a DOMPurify hook at a given entryPoint
1426
- * (pops it from the stack of hooks if more are present)
1427
- *
1428
- * @param {String} entryPoint entry point for the hook to remove
1429
- */
1344
+ if (SAFE_FOR_TEMPLATES) {
1345
+ serializedHTML = serializedHTML.replace(MUSTACHE_EXPR$$1, ' ');
1346
+ serializedHTML = serializedHTML.replace(ERB_EXPR$$1, ' ');
1347
+ }
1430
1348
 
1349
+ return trustedTypesPolicy ? trustedTypesPolicy.createHTML(serializedHTML) : serializedHTML;
1350
+ };
1351
+ /**
1352
+ * Public method to set the configuration once
1353
+ * setConfig
1354
+ *
1355
+ * @param {Object} cfg configuration object
1356
+ */
1431
1357
 
1432
- DOMPurify.removeHook = function (entryPoint) {
1433
- if (hooks[entryPoint]) {
1434
- hooks[entryPoint].pop();
1435
- }
1436
- };
1437
- /**
1438
- * RemoveHooks
1439
- * Public method to remove all DOMPurify hooks at a given entryPoint
1440
- *
1441
- * @param {String} entryPoint entry point for the hooks to remove
1442
- */
1443
1358
 
1359
+ DOMPurify.setConfig = function (cfg) {
1360
+ _parseConfig(cfg);
1444
1361
 
1445
- DOMPurify.removeHooks = function (entryPoint) {
1446
- if (hooks[entryPoint]) {
1447
- hooks[entryPoint] = [];
1448
- }
1449
- };
1450
- /**
1451
- * RemoveAllHooks
1452
- * Public method to remove all DOMPurify hooks
1453
- *
1454
- */
1362
+ SET_CONFIG = true;
1363
+ };
1364
+ /**
1365
+ * Public method to remove the configuration
1366
+ * clearConfig
1367
+ *
1368
+ */
1455
1369
 
1456
1370
 
1457
- DOMPurify.removeAllHooks = function () {
1458
- hooks = {};
1459
- };
1371
+ DOMPurify.clearConfig = function () {
1372
+ CONFIG = null;
1373
+ SET_CONFIG = false;
1374
+ };
1375
+ /**
1376
+ * Public method to check if an attribute value is valid.
1377
+ * Uses last set config, if any. Otherwise, uses config defaults.
1378
+ * isValidAttribute
1379
+ *
1380
+ * @param {string} tag Tag name of containing element.
1381
+ * @param {string} attr Attribute name.
1382
+ * @param {string} value Attribute value.
1383
+ * @return {Boolean} Returns true if `value` is valid. Otherwise, returns false.
1384
+ */
1460
1385
 
1461
- return DOMPurify;
1462
- }
1463
1386
 
1464
- var purify = createDOMPurify();
1387
+ DOMPurify.isValidAttribute = function (tag, attr, value) {
1388
+ /* Initialize shared config vars if necessary. */
1389
+ if (!CONFIG) {
1390
+ _parseConfig({});
1391
+ }
1465
1392
 
1393
+ var lcTag = tag.toLowerCase();
1394
+ var lcName = attr.toLowerCase();
1395
+ return _isValidAttribute(lcTag, lcName, value);
1396
+ };
1466
1397
  /**
1467
- * This program is free software; you can redistribute it and/or
1468
- * modify it under the terms of the GNU General Public License
1469
- * as published by the Free Software Foundation; under version 2
1470
- * of the License (non-upgradable).
1398
+ * AddHook
1399
+ * Public method to add DOMPurify hooks
1471
1400
  *
1472
- * This program is distributed in the hope that it will be useful,
1473
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
1474
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1475
- * GNU General Public License for more details.
1401
+ * @param {String} entryPoint entry point for the hook to add
1402
+ * @param {Function} hookFunction function to execute
1403
+ */
1404
+
1405
+
1406
+ DOMPurify.addHook = function (entryPoint, hookFunction) {
1407
+ if (typeof hookFunction !== 'function') {
1408
+ return;
1409
+ }
1410
+
1411
+ hooks[entryPoint] = hooks[entryPoint] || [];
1412
+ hooks[entryPoint].push(hookFunction);
1413
+ };
1414
+ /**
1415
+ * RemoveHook
1416
+ * Public method to remove a DOMPurify hook at a given entryPoint
1417
+ * (pops it from the stack of hooks if more are present)
1476
1418
  *
1477
- * You should have received a copy of the GNU General Public License
1478
- * along with this program; if not, write to the Free Software
1479
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
1419
+ * @param {String} entryPoint entry point for the hook to remove
1420
+ */
1421
+
1422
+
1423
+ DOMPurify.removeHook = function (entryPoint) {
1424
+ if (hooks[entryPoint]) {
1425
+ hooks[entryPoint].pop();
1426
+ }
1427
+ };
1428
+ /**
1429
+ * RemoveHooks
1430
+ * Public method to remove all DOMPurify hooks at a given entryPoint
1480
1431
  *
1481
- * Copyright (c) 2017-2019 (original work) Open Assessment Technologies SA ;
1432
+ * @param {String} entryPoint entry point for the hooks to remove
1482
1433
  */
1483
- var defaultConfig = {
1484
- multiple: true
1434
+
1435
+
1436
+ DOMPurify.removeHooks = function (entryPoint) {
1437
+ if (hooks[entryPoint]) {
1438
+ hooks[entryPoint] = [];
1439
+ }
1485
1440
  };
1486
1441
  /**
1487
- * Builds the resource list component
1442
+ * RemoveAllHooks
1443
+ * Public method to remove all DOMPurify hooks
1488
1444
  *
1489
- * @param {jQueryElement} $container - where to append the component
1490
- * @param {Object} config - the component config
1491
- * @param {String} config.classUri - the root Class URI
1492
- * @param {Object[]} [config.nodes] - the nodes to preload
1493
- * @param {String} [config.icon] - the icon class to show close to the resources
1494
- * @param {Boolean} [config.multiple = true] - multiple vs unique selection
1495
- * @returns {resourceList} the component
1496
1445
  */
1497
1446
 
1498
- function resourceListFactory($container, config) {
1499
- var $list;
1500
- var $loadMore;
1447
+
1448
+ DOMPurify.removeAllHooks = function () {
1449
+ hooks = {};
1450
+ };
1451
+
1452
+ return DOMPurify;
1453
+ }
1454
+
1455
+ var purify = createDOMPurify();
1456
+
1457
+ /**
1458
+ * This program is free software; you can redistribute it and/or
1459
+ * modify it under the terms of the GNU General Public License
1460
+ * as published by the Free Software Foundation; under version 2
1461
+ * of the License (non-upgradable).
1462
+ *
1463
+ * This program is distributed in the hope that it will be useful,
1464
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1465
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1466
+ * GNU General Public License for more details.
1467
+ *
1468
+ * You should have received a copy of the GNU General Public License
1469
+ * along with this program; if not, write to the Free Software
1470
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
1471
+ *
1472
+ * Copyright (c) 2017-2019 (original work) Open Assessment Technologies SA ;
1473
+ */
1474
+ var defaultConfig = {
1475
+ multiple: true
1476
+ };
1477
+ /**
1478
+ * Builds the resource list component
1479
+ *
1480
+ * @param {jQueryElement} $container - where to append the component
1481
+ * @param {Object} config - the component config
1482
+ * @param {String} config.classUri - the root Class URI
1483
+ * @param {Object[]} [config.nodes] - the nodes to preload
1484
+ * @param {String} [config.icon] - the icon class to show close to the resources
1485
+ * @param {Boolean} [config.multiple = true] - multiple vs unique selection
1486
+ * @returns {resourceList} the component
1487
+ */
1488
+
1489
+ function resourceListFactory($container, config) {
1490
+ var $list;
1491
+ var $loadMore;
1492
+ /**
1493
+ * A selectable component
1494
+ * @typedef {ui/component} resourceList
1495
+ */
1496
+
1497
+ var resourceList = selectable(component({
1501
1498
  /**
1502
- * A selectable component
1503
- * @typedef {ui/component} resourceList
1499
+ * Ask for a query (forward the event)
1500
+ * @param {Object} [params] - the query parameters
1501
+ * @param {String} [params.classUri] - the class URI
1502
+ * @param {Number} [params.offset = 0] - for paging
1503
+ * @param {Number} [params.limit] - for paging
1504
+ * @returns {resourceList} chains
1505
+ * @fires resourceList#query
1504
1506
  */
1505
-
1506
- var resourceList = selectable(component({
1507
- /**
1508
- * Ask for a query (forward the event)
1509
- * @param {Object} [params] - the query parameters
1510
- * @param {String} [params.classUri] - the class URI
1511
- * @param {Number} [params.offset = 0] - for paging
1512
- * @param {Number} [params.limit] - for paging
1513
- * @returns {resourceList} chains
1514
- * @fires resourceList#query
1515
- */
1516
- query: function query(params) {
1517
- if (!this.is('loading')) {
1518
- /**
1519
- * Formulate the query
1520
- * @event resourceList#query
1521
- * @param {Object} params
1522
- */
1523
- this.trigger('query', _.defaults(params || {}, {
1524
- classUri: this.classUri
1525
- }));
1526
- }
1527
- },
1528
-
1529
- /**
1530
- * Update the component with the given nodes
1531
- * @param resources
1532
- * @returns {resourceList} chains
1533
- * @fires resourceList#update
1534
- */
1535
- update: function update(resources) {
1536
- var self = this;
1537
-
1538
- if (this.is('rendered')) {
1539
- $list.html(_.reduce(resources.nodes, function (acc, node) {
1540
- node.icon = self.config.icon;
1541
- node.label = purify.sanitize(node.label);
1542
- acc += listNodeTpl(node);
1543
- return acc;
1544
- }, ''));
1545
-
1546
- _.forEach(resources.nodes, function (node) {
1547
- self.addNode(node.uri, node);
1548
- });
1549
-
1550
- if (resources.total > _.size(self.getNodes())) {
1551
- hider.show($loadMore);
1552
- } else {
1553
- hider.hide($loadMore);
1554
- }
1555
- /**
1556
- * The list has been updated
1557
- * @event resourceList#update
1558
- */
1559
-
1560
-
1561
- this.trigger('update');
1562
- }
1507
+ query: function query(params) {
1508
+ if (!this.is('loading')) {
1509
+ /**
1510
+ * Formulate the query
1511
+ * @event resourceList#query
1512
+ * @param {Object} params
1513
+ */
1514
+ this.trigger('query', _.defaults(params || {}, {
1515
+ classUri: this.classUri
1516
+ }));
1563
1517
  }
1564
- }, defaultConfig));
1565
- resourceList.setTemplate(listTpl).on('init', function () {
1566
- this.classUri = this.config.classUri;
1567
- this.setState('multiple', !!this.config.multiple);
1568
- this.render($container);
1569
- }).on('render', function () {
1518
+ },
1519
+
1520
+ /**
1521
+ * Update the component with the given nodes
1522
+ * @param resources
1523
+ * @returns {resourceList} chains
1524
+ * @fires resourceList#update
1525
+ */
1526
+ update: function update(resources) {
1570
1527
  var self = this;
1571
- var $component = this.getElement();
1572
- $list = $component.children('ul');
1573
- $loadMore = $$1('.more', $component); //selection
1574
1528
 
1575
- $component.on('click', 'li', function (e) {
1576
- var $instance = $$1(e.currentTarget);
1577
- e.preventDefault();
1578
- e.stopPropagation();
1529
+ if (this.is('rendered')) {
1530
+ $list.html(_.reduce(resources.nodes, function (acc, node) {
1531
+ node.icon = self.config.icon;
1532
+ node.label = purify.sanitize(node.label);
1533
+ acc += listNodeTpl(node);
1534
+ return acc;
1535
+ }, ''));
1536
+
1537
+ _.forEach(resources.nodes, function (node) {
1538
+ self.addNode(node.uri, node);
1539
+ });
1579
1540
 
1580
- if ($instance.hasClass('selected')) {
1581
- self.unselect($instance.data('uri'));
1541
+ if (resources.total > _.size(self.getNodes())) {
1542
+ hider.show($loadMore);
1582
1543
  } else {
1583
- self.select($instance.data('uri'), !self.is('multiple'));
1544
+ hider.hide($loadMore);
1584
1545
  }
1585
- }); //load next page
1546
+ /**
1547
+ * The list has been updated
1548
+ * @event resourceList#update
1549
+ */
1586
1550
 
1587
- $loadMore.on('click', function (e) {
1588
- e.preventDefault();
1589
- self.query({
1590
- offset: _.size(self.getNodes())
1591
- });
1592
- }); //initial data loading
1593
1551
 
1594
- if (this.config.nodes) {
1595
- this.update(this.config.nodes);
1596
- } else {
1597
- this.query();
1552
+ this.trigger('update');
1598
1553
  }
1599
- }).on('query', function () {
1600
- this.setState('loading', true);
1601
- }).on('update', function () {
1602
- this.setState('loading', false);
1603
- }).on('remove', function (uri) {
1604
- if (this.is('rendered')) {
1605
- $$1('[data-uri="' + uri + '"]', this.getElement()).remove();
1554
+ }
1555
+ }, defaultConfig));
1556
+ resourceList.setTemplate(listTpl).on('init', function () {
1557
+ this.classUri = this.config.classUri;
1558
+ this.setState('multiple', !!this.config.multiple);
1559
+ this.render($container);
1560
+ }).on('render', function () {
1561
+ var self = this;
1562
+ var $component = this.getElement();
1563
+ $list = $component.children('ul');
1564
+ $loadMore = $$1('.more', $component); //selection
1565
+
1566
+ $component.on('click', 'li', function (e) {
1567
+ var $instance = $$1(e.currentTarget);
1568
+ e.preventDefault();
1569
+ e.stopPropagation();
1570
+
1571
+ if ($instance.hasClass('selected')) {
1572
+ self.unselect($instance.data('uri'));
1573
+ } else {
1574
+ self.select($instance.data('uri'), !self.is('multiple'));
1606
1575
  }
1607
- }); //always defer the initialization to let consumers listen for init and render events.
1576
+ }); //load next page
1608
1577
 
1609
- _.defer(function () {
1610
- resourceList.init(config);
1611
- });
1578
+ $loadMore.on('click', function (e) {
1579
+ e.preventDefault();
1580
+ self.query({
1581
+ offset: _.size(self.getNodes())
1582
+ });
1583
+ }); //initial data loading
1612
1584
 
1613
- return resourceList;
1614
- }
1585
+ if (this.config.nodes) {
1586
+ this.update(this.config.nodes);
1587
+ } else {
1588
+ this.query();
1589
+ }
1590
+ }).on('query', function () {
1591
+ this.setState('loading', true);
1592
+ }).on('update', function () {
1593
+ this.setState('loading', false);
1594
+ }).on('remove', function (uri) {
1595
+ if (this.is('rendered')) {
1596
+ $$1('[data-uri="' + uri + '"]', this.getElement()).remove();
1597
+ }
1598
+ }); //always defer the initialization to let consumers listen for init and render events.
1599
+
1600
+ _.defer(function () {
1601
+ resourceList.init(config);
1602
+ });
1603
+
1604
+ return resourceList;
1605
+ }
1615
1606
 
1616
- return resourceListFactory;
1607
+ return resourceListFactory;
1617
1608
 
1618
1609
  });