@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.
- package/dist/actionbar.js +386 -395
- package/dist/adder.js +21 -19
- package/dist/animable/absorbable/absorbable.js +204 -213
- package/dist/animable/absorbable/css/absorb.css +1 -0
- package/dist/animable/absorbable/css/absorb.css.map +1 -1
- package/dist/animable/pulsable/pulsable.js +168 -177
- package/dist/autocomplete/css/autocomplete.css +1 -0
- package/dist/autocomplete/css/autocomplete.css.map +1 -1
- package/dist/autocomplete.js +68 -66
- package/dist/badge/badge.js +188 -197
- package/dist/badge/css/badge.css +1 -0
- package/dist/badge/css/badge.css.map +1 -1
- package/dist/breadcrumbs.js +275 -284
- package/dist/btngrouper.js +5 -5
- package/dist/bulkActionPopup.js +490 -495
- package/dist/button.js +283 -291
- package/dist/cascadingComboBox.js +249 -258
- package/dist/ckeditor/ckConfigurator.js +26 -19
- package/dist/ckeditor/dtdHandler.js +11 -9
- package/dist/class/selector.js +441 -450
- package/dist/component/resizable.js +1 -1
- package/dist/component/windowed.js +285 -294
- package/dist/component.js +419 -428
- package/dist/contextualPopup.js +417 -426
- package/dist/dashboard.js +300 -309
- package/dist/datalist.js +753 -762
- package/dist/datatable/filterStrategy/multiple.js +1 -1
- package/dist/datatable/filterStrategy/single.js +1 -1
- package/dist/datatable.js +1527 -1550
- package/dist/dateRange/dateRange.js +393 -402
- package/dist/datetime/picker.js +665 -672
- package/dist/deleter.js +368 -377
- package/dist/destination/selector.js +286 -295
- package/dist/dialog/alert.js +3 -3
- package/dist/dialog/confirm.js +1 -1
- package/dist/dialog/confirmDelete.js +216 -225
- package/dist/dialog.js +650 -654
- package/dist/disabler.js +8 -8
- package/dist/documentViewer/providers/pdfViewer/fallback/viewer.js +166 -175
- package/dist/documentViewer/providers/pdfViewer/pdfjs/findBar.js +518 -527
- package/dist/documentViewer/providers/pdfViewer/pdfjs/pageView.js +380 -389
- package/dist/documentViewer/providers/pdfViewer/pdfjs/searchEngine.js +539 -548
- package/dist/documentViewer/providers/pdfViewer/pdfjs/viewer.js +369 -378
- package/dist/documentViewer/providers/pdfViewer.js +184 -193
- package/dist/documentViewer.js +292 -301
- package/dist/dropdown.js +383 -392
- package/dist/durationer.js +5 -5
- package/dist/dynamicComponent.js +597 -598
- package/dist/feedback.js +356 -362
- package/dist/figure/FigureStateActive.js +117 -108
- package/dist/filesender.js +2 -2
- package/dist/filter.js +230 -239
- package/dist/form/dropdownForm.js +355 -357
- package/dist/form/form.js +919 -690
- package/dist/form/simpleForm.js +1 -1
- package/dist/form/validator/renderer.js +233 -235
- package/dist/form/validator/validator.js +257 -189
- package/dist/form/widget/definitions.js +1 -1
- package/dist/form/widget/providers/checkBox.js +254 -259
- package/dist/form/widget/providers/comboBox.js +187 -192
- package/dist/form/widget/providers/default.js +8 -9
- package/dist/form/widget/providers/hidden.js +170 -179
- package/dist/form/widget/providers/hiddenBox.js +262 -267
- package/dist/form/widget/providers/radioBox.js +216 -225
- package/dist/form/widget/providers/textArea.js +187 -196
- package/dist/form/widget/providers/textBox.js +2 -3
- package/dist/form/widget/widget.js +473 -475
- package/dist/formValidator/formValidator.js +1 -1
- package/dist/formValidator/highlighters/message.js +1 -1
- package/dist/generis/form/form.js +314 -323
- package/dist/generis/validator/validator.js +209 -218
- package/dist/generis/widget/checkBox/checkBox.js +218 -227
- package/dist/generis/widget/comboBox/comboBox.js +179 -188
- package/dist/generis/widget/hiddenBox/hiddenBox.js +220 -229
- package/dist/generis/widget/textBox/textBox.js +169 -178
- package/dist/generis/widget/widget.js +246 -255
- package/dist/groupedComboBox.js +222 -231
- package/dist/groupvalidator.js +2 -2
- package/dist/highlighter.js +967 -958
- package/dist/image/ImgStateActive/helper.js +7 -5
- package/dist/image/ImgStateActive/initHelper.js +49 -43
- package/dist/image/ImgStateActive/initMediaEditor.js +24 -20
- package/dist/image/ImgStateActive/mediaSizer.js +14 -12
- package/dist/image/ImgStateActive.js +72 -70
- package/dist/incrementer.js +6 -6
- package/dist/inplacer.js +6 -6
- package/dist/itemButtonList/css/item-button-list.css +1 -0
- package/dist/itemButtonList/css/item-button-list.css.map +1 -1
- package/dist/itemButtonList.js +439 -435
- package/dist/keyNavigation/navigableDomElement.js +51 -38
- package/dist/keyNavigation/navigator.js +85 -70
- package/dist/listbox.js +460 -469
- package/dist/liststyler.js +8 -8
- package/dist/loadingButton/loadingButton.js +209 -218
- package/dist/lock.js +476 -485
- package/dist/login/login.js +475 -484
- package/dist/maths/calculator/basicCalculator.js +235 -244
- package/dist/maths/calculator/calculatorComponent.js +3 -3
- package/dist/maths/calculator/core/board.js +772 -781
- package/dist/maths/calculator/core/expression.js +476 -485
- package/dist/maths/calculator/core/labels.js +228 -237
- package/dist/maths/calculator/core/tokenizer.js +1 -1
- package/dist/maths/calculator/core/tokens.js +163 -170
- package/dist/maths/calculator/plugins/keyboard/templateKeyboard/templateKeyboard.js +244 -253
- package/dist/maths/calculator/plugins/screen/simpleScreen/simpleScreen.js +279 -288
- package/dist/maths/calculator/scientificCalculator.js +327 -336
- package/dist/mediaEditor/mediaEditorComponent.js +238 -245
- package/dist/mediaEditor/plugins/mediaAlignment/helper.js +7 -7
- package/dist/mediaEditor/plugins/mediaAlignment/mediaAlignmentComponent.js +229 -235
- package/dist/mediaEditor/plugins/mediaDimension/mediaDimensionComponent.js +580 -589
- package/dist/mediaplayer/players/html5.js +666 -675
- package/dist/mediaplayer/players/youtube.js +419 -424
- package/dist/mediaplayer/support.js +11 -10
- package/dist/mediaplayer/utils/reminder.js +14 -13
- package/dist/mediaplayer/utils/timeObserver.js +10 -11
- package/dist/mediaplayer/youtubeManager.js +164 -145
- package/dist/mediaplayer.js +1565 -1520
- package/dist/mediasizer.js +669 -678
- package/dist/modal.js +10 -17
- package/dist/pageSizeSelector.js +219 -228
- package/dist/pagination/providers/pages.js +280 -289
- package/dist/pagination/providers/simple.js +192 -201
- package/dist/previewer.js +30 -30
- package/dist/progressbar.js +4 -4
- package/dist/report.js +347 -356
- package/dist/resource/filters.js +271 -280
- package/dist/resource/list.js +1264 -1273
- package/dist/resource/selector.js +865 -874
- package/dist/resource/tree.js +1483 -1492
- package/dist/resourcemgr/fileBrowser.js +564 -569
- package/dist/resourcemgr/filePreview.js +16 -16
- package/dist/resourcemgr/fileSelector.js +515 -524
- package/dist/resourcemgr/util/updatePermissions.js +2 -2
- package/dist/resourcemgr.js +306 -315
- package/dist/searchModal/advancedSearch.js +796 -767
- package/dist/searchModal.js +114 -91
- package/dist/switch/switch.js +298 -307
- package/dist/tabs.js +598 -575
- package/dist/taskQueue/status.js +312 -321
- package/dist/taskQueue/table.js +375 -384
- package/dist/taskQueue/taskQueueModel.js +488 -472
- package/dist/taskQueueButton/taskable.js +264 -273
- package/dist/taskQueueButton/treeButton.js +189 -198
- package/dist/themeLoader.js +24 -23
- package/dist/themes.js +1 -1
- package/dist/toggler.js +3 -3
- package/dist/tooltip.js +295 -304
- package/dist/transformer.js +2 -2
- package/dist/tristateCheckboxGroup.js +311 -320
- package/dist/uploader.js +687 -696
- package/dist/validator/Report.js +1 -1
- package/dist/validator/Validator.js +3 -3
- package/dist/validator/validators.js +9 -9
- package/dist/validator.js +240 -230
- package/dist/waitForMedia.js +1 -1
- package/package.json +3 -3
- package/src/animable/absorbable/css/absorb.css +1 -0
- package/src/animable/absorbable/css/absorb.css.map +1 -1
- package/src/autocomplete/css/autocomplete.css +1 -0
- package/src/autocomplete/css/autocomplete.css.map +1 -1
- package/src/badge/css/badge.css +1 -0
- package/src/badge/css/badge.css.map +1 -1
- package/src/ckeditor/ckConfigurator.js +4 -0
- package/src/itemButtonList/css/item-button-list.css +1 -0
- package/src/itemButtonList/css/item-button-list.css.map +1 -1
- package/src/.DS_Store +0 -0
- package/src/css/basic.css +0 -7826
- package/src/css/basic.css.map +0 -1
- package/src/css/ckeditor/skins/tao/css/dialog.css +0 -950
- package/src/css/ckeditor/skins/tao/css/dialog.css.map +0 -1
- package/src/css/ckeditor/skins/tao/css/editor.css +0 -1850
- package/src/css/ckeditor/skins/tao/css/editor.css.map +0 -1
- package/src/scss/.DS_Store +0 -0
- package/src/scss/basic.scss +0 -16
- package/src/scss/ckeditor/skins/tao/scss/dialog.scss +0 -763
- package/src/scss/ckeditor/skins/tao/scss/editor.scss +0 -111
- package/src/scss/ckeditor/skins/tao/scss/inc/_ck-icons.scss +0 -59
- package/src/scss/ckeditor/skins/tao/scss/inc/_colorpanel.scss +0 -118
- package/src/scss/ckeditor/skins/tao/scss/inc/_elementspath.scss +0 -69
- package/src/scss/ckeditor/skins/tao/scss/inc/_mainui.scss +0 -194
- package/src/scss/ckeditor/skins/tao/scss/inc/_menu.scss +0 -181
- package/src/scss/ckeditor/skins/tao/scss/inc/_panel.scss +0 -200
- package/src/scss/ckeditor/skins/tao/scss/inc/_presets.scss +0 -32
- package/src/scss/ckeditor/skins/tao/scss/inc/_reset.scss +0 -101
- package/src/scss/ckeditor/skins/tao/scss/inc/_richcombo.scss +0 -213
- package/src/scss/ckeditor/skins/tao/scss/inc/_tao.scss +0 -59
- package/src/scss/ckeditor/skins/tao/scss/inc/_toolbar.scss +0 -301
- package/src/scss/font/source-sans-pro/source-sans-pro-italic.eot +0 -0
- package/src/scss/font/source-sans-pro/source-sans-pro-italic.eot.b64 +0 -1
- package/src/scss/font/source-sans-pro/source-sans-pro-italic.woff +0 -0
- package/src/scss/font/source-sans-pro/source-sans-pro-italic.woff.b64 +0 -1
- package/src/scss/font/source-sans-pro/source-sans-pro-regular.eot +0 -0
- package/src/scss/font/source-sans-pro/source-sans-pro-regular.eot.b64 +0 -1
- package/src/scss/font/source-sans-pro/source-sans-pro-regular.woff +0 -0
- package/src/scss/font/source-sans-pro/source-sans-pro-regular.woff.b64 +0 -1
- package/src/scss/font/source-sans-pro/source-sans-pro-semibold-italic.eot +0 -0
- package/src/scss/font/source-sans-pro/source-sans-pro-semibold-italic.eot.b64 +0 -1
- package/src/scss/font/source-sans-pro/source-sans-pro-semibold-italic.woff +0 -0
- package/src/scss/font/source-sans-pro/source-sans-pro-semibold-italic.woff.b64 +0 -1
- package/src/scss/font/source-sans-pro/source-sans-pro-semibold.eot +0 -0
- package/src/scss/font/source-sans-pro/source-sans-pro-semibold.eot.b64 +0 -1
- package/src/scss/font/source-sans-pro/source-sans-pro-semibold.woff +0 -0
- package/src/scss/font/source-sans-pro/source-sans-pro-semibold.woff.b64 +0 -1
- package/src/scss/font/tao/tao.eot +0 -0
- package/src/scss/font/tao/tao.svg +0 -235
- package/src/scss/font/tao/tao.ttf +0 -0
- package/src/scss/font/tao/tao.woff +0 -0
- package/src/scss/inc/_base.scss +0 -496
- package/src/scss/inc/_bootstrap.scss +0 -6
- package/src/scss/inc/_buttons.scss +0 -114
- package/src/scss/inc/_colors.scss +0 -88
- package/src/scss/inc/_feedback.scss +0 -150
- package/src/scss/inc/_flex-grid.scss +0 -15
- package/src/scss/inc/_fonts.scss +0 -4
- package/src/scss/inc/_forms.scss +0 -827
- package/src/scss/inc/_functions.scss +0 -283
- package/src/scss/inc/_grid.scss +0 -66
- package/src/scss/inc/_jquery.nouislider.scss +0 -254
- package/src/scss/inc/_normalize.scss +0 -528
- package/src/scss/inc/_report.scss +0 -68
- package/src/scss/inc/_secondary-properties.scss +0 -89
- package/src/scss/inc/_select2.scss +0 -634
- package/src/scss/inc/_toolbars.scss +0 -155
- package/src/scss/inc/_tooltip.scss +0 -312
- package/src/scss/inc/_variables.scss +0 -21
- package/src/scss/inc/base/_highlight.scss +0 -5
- package/src/scss/inc/base/_list-style.scss +0 -59
- package/src/scss/inc/base/_svg.scss +0 -3
- package/src/scss/inc/base/_table.scss +0 -63
- package/src/scss/inc/fonts/_source-sans-pro.scss +0 -29
- package/src/scss/inc/fonts/_tao-icon-classes.scss +0 -226
- package/src/scss/inc/fonts/_tao-icon-def.scss +0 -12
- package/src/scss/inc/fonts/_tao-icon-vars.scss +0 -240
package/dist/resource/list.js
CHANGED
|
@@ -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
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
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
|
-
*
|
|
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
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
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
|
-
|
|
57
|
-
var
|
|
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
|
-
|
|
76
|
-
|
|
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
|
-
|
|
63
|
+
value = '';
|
|
106
64
|
}
|
|
107
|
-
}); // register a "get property" helper
|
|
108
|
-
// it gets the named property from the provided context
|
|
109
65
|
|
|
110
|
-
|
|
111
|
-
|
|
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
|
-
|
|
123
|
-
|
|
124
|
-
|
|
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
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
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
|
-
|
|
151
|
-
|
|
152
|
-
|
|
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
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
else {
|
|
171
|
-
|
|
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
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
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
|
-
|
|
211
|
-
|
|
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
|
-
|
|
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
|
-
|
|
217
|
-
|
|
218
|
-
var
|
|
219
|
-
|
|
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
|
-
|
|
222
|
-
|
|
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
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
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
|
-
|
|
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
|
-
|
|
258
|
-
|
|
245
|
+
while (l--) {
|
|
246
|
+
var element = array[l];
|
|
259
247
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
if (!Object.isFrozen(array)) {
|
|
263
|
-
array[l] = lcElement;
|
|
264
|
-
}
|
|
248
|
+
if (typeof element === 'string') {
|
|
249
|
+
var lcElement = element.toLowerCase();
|
|
265
250
|
|
|
266
|
-
|
|
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
|
-
|
|
257
|
+
element = lcElement;
|
|
258
|
+
}
|
|
271
259
|
}
|
|
272
260
|
|
|
273
|
-
|
|
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
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
}
|
|
286
|
-
}
|
|
269
|
+
function clone(object) {
|
|
270
|
+
var newObject = {};
|
|
271
|
+
var property = void 0;
|
|
287
272
|
|
|
288
|
-
|
|
273
|
+
for (property in object) {
|
|
274
|
+
if (apply$1(hasOwnProperty, object, [property])) {
|
|
275
|
+
newObject[property] = object[property];
|
|
276
|
+
}
|
|
289
277
|
}
|
|
290
278
|
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
};
|
|
279
|
+
return newObject;
|
|
280
|
+
}
|
|
294
281
|
|
|
295
|
-
|
|
282
|
+
var seal = Object.seal || function (x) {
|
|
283
|
+
return x;
|
|
284
|
+
};
|
|
296
285
|
|
|
297
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
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
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
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
|
-
|
|
321
|
-
|
|
322
|
-
|
|
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
|
-
|
|
317
|
+
var _ref = typeof Reflect !== 'undefined' && Reflect;
|
|
327
318
|
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
319
|
+
var apply = _ref.apply;
|
|
320
|
+
var arraySlice = Array.prototype.slice;
|
|
321
|
+
var freeze = Object.freeze;
|
|
331
322
|
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
323
|
+
var getGlobal = function getGlobal() {
|
|
324
|
+
return typeof window === 'undefined' ? null : window;
|
|
325
|
+
};
|
|
335
326
|
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
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
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
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
|
-
|
|
360
|
-
|
|
374
|
+
function createDOMPurify() {
|
|
375
|
+
var window = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getGlobal();
|
|
361
376
|
|
|
362
|
-
|
|
363
|
-
|
|
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
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
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
|
-
|
|
384
|
-
var window = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getGlobal();
|
|
392
|
+
DOMPurify.removed = [];
|
|
385
393
|
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
441
|
-
|
|
442
|
-
|
|
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
|
-
|
|
453
|
-
|
|
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
|
-
|
|
469
|
+
var FORBID_ATTR = null;
|
|
470
|
+
/* Decide if ARIA attributes are okay */
|
|
466
471
|
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
/* Allowed attribute names */
|
|
472
|
+
var ALLOW_ARIA_ATTR = true;
|
|
473
|
+
/* Decide if custom data attributes are okay */
|
|
470
474
|
|
|
471
|
-
|
|
472
|
-
|
|
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
|
-
|
|
476
|
-
|
|
478
|
+
var ALLOW_UNKNOWN_PROTOCOLS = false;
|
|
479
|
+
/* Output should be safe for jQuery's $() factory? */
|
|
477
480
|
|
|
478
|
-
|
|
479
|
-
|
|
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
|
-
|
|
482
|
-
|
|
486
|
+
var SAFE_FOR_TEMPLATES = false;
|
|
487
|
+
/* Decide if document with <html>... should be returned */
|
|
483
488
|
|
|
484
|
-
|
|
485
|
-
|
|
489
|
+
var WHOLE_DOCUMENT = false;
|
|
490
|
+
/* Track whether config is already set on this instance of DOMPurify. */
|
|
486
491
|
|
|
487
|
-
|
|
488
|
-
|
|
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
|
-
|
|
491
|
-
|
|
492
|
-
|
|
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
|
-
|
|
496
|
-
|
|
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
|
-
|
|
499
|
-
|
|
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
|
-
|
|
502
|
-
|
|
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
|
-
|
|
506
|
-
|
|
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
|
-
|
|
512
|
-
|
|
513
|
-
|
|
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
|
-
|
|
516
|
-
|
|
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
|
-
|
|
522
|
-
|
|
525
|
+
var USE_PROFILES = {};
|
|
526
|
+
/* Tags to ignore content of when KEEP_CONTENT is true */
|
|
523
527
|
|
|
524
|
-
|
|
525
|
-
|
|
528
|
+
var FORBID_CONTENTS = addToSet({}, ['audio', 'head', 'math', 'script', 'style', 'template', 'svg', 'video']);
|
|
529
|
+
/* Tags that are safe for data: URIs */
|
|
526
530
|
|
|
527
|
-
|
|
528
|
-
|
|
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
|
-
|
|
532
|
-
|
|
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
|
-
|
|
535
|
-
|
|
538
|
+
var CONFIG = null;
|
|
539
|
+
/* Ideally, do not touch anything below this line */
|
|
536
540
|
|
|
537
|
-
|
|
538
|
-
/* Tags that are safe for data: URIs */
|
|
541
|
+
/* ______________________________________________ */
|
|
539
542
|
|
|
540
|
-
|
|
541
|
-
|
|
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
|
-
|
|
544
|
-
|
|
545
|
-
|
|
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
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
580
|
+
WHOLE_DOCUMENT = cfg.WHOLE_DOCUMENT || false; // Default false
|
|
582
581
|
|
|
583
|
-
|
|
582
|
+
RETURN_DOM = cfg.RETURN_DOM || false; // Default false
|
|
584
583
|
|
|
585
|
-
|
|
584
|
+
RETURN_DOM_FRAGMENT = cfg.RETURN_DOM_FRAGMENT || false; // Default false
|
|
586
585
|
|
|
587
|
-
|
|
586
|
+
RETURN_DOM_IMPORT = cfg.RETURN_DOM_IMPORT || false; // Default false
|
|
588
587
|
|
|
589
|
-
|
|
588
|
+
FORCE_BODY = cfg.FORCE_BODY || false; // Default false
|
|
590
589
|
|
|
591
|
-
|
|
590
|
+
SANITIZE_DOM = cfg.SANITIZE_DOM !== false; // Default true
|
|
592
591
|
|
|
593
|
-
|
|
592
|
+
KEEP_CONTENT = cfg.KEEP_CONTENT !== false; // Default true
|
|
594
593
|
|
|
595
|
-
|
|
594
|
+
IN_PLACE = cfg.IN_PLACE || false; // Default false
|
|
596
595
|
|
|
597
|
-
|
|
596
|
+
IS_ALLOWED_URI$$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI$$1;
|
|
598
597
|
|
|
599
|
-
|
|
598
|
+
if (SAFE_FOR_TEMPLATES) {
|
|
599
|
+
ALLOW_DATA_ATTR = false;
|
|
600
|
+
}
|
|
600
601
|
|
|
601
|
-
|
|
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
|
-
|
|
608
|
+
if (USE_PROFILES) {
|
|
609
|
+
ALLOWED_TAGS = addToSet({}, [].concat(_toConsumableArray(text)));
|
|
610
|
+
ALLOWED_ATTR = [];
|
|
606
611
|
|
|
607
|
-
if (
|
|
608
|
-
|
|
612
|
+
if (USE_PROFILES.html === true) {
|
|
613
|
+
addToSet(ALLOWED_TAGS, html);
|
|
614
|
+
addToSet(ALLOWED_ATTR, html$1);
|
|
609
615
|
}
|
|
610
616
|
|
|
611
|
-
if (
|
|
612
|
-
|
|
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
|
-
|
|
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
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
}
|
|
638
|
+
if (cfg.ADD_TAGS) {
|
|
639
|
+
if (ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) {
|
|
640
|
+
ALLOWED_TAGS = clone(ALLOWED_TAGS);
|
|
641
|
+
}
|
|
631
642
|
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
addToSet(ALLOWED_ATTR, svg$1);
|
|
635
|
-
addToSet(ALLOWED_ATTR, xml);
|
|
636
|
-
}
|
|
643
|
+
addToSet(ALLOWED_TAGS, cfg.ADD_TAGS);
|
|
644
|
+
}
|
|
637
645
|
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
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
|
-
|
|
648
|
-
|
|
649
|
-
ALLOWED_TAGS = clone(ALLOWED_TAGS);
|
|
650
|
-
}
|
|
651
|
+
addToSet(ALLOWED_ATTR, cfg.ADD_ATTR);
|
|
652
|
+
}
|
|
651
653
|
|
|
652
|
-
|
|
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
|
-
|
|
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
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
682
|
+
CONFIG = cfg;
|
|
683
|
+
};
|
|
684
|
+
/**
|
|
685
|
+
* _forceRemove
|
|
686
|
+
*
|
|
687
|
+
* @param {Node} node a DOM node
|
|
688
|
+
*/
|
|
685
689
|
|
|
686
690
|
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
691
|
+
var _forceRemove = function _forceRemove(node) {
|
|
692
|
+
DOMPurify.removed.push({
|
|
693
|
+
element: node
|
|
694
|
+
});
|
|
690
695
|
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
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
|
-
|
|
710
|
+
var _removeAttribute = function _removeAttribute(name, node) {
|
|
711
|
+
try {
|
|
701
712
|
DOMPurify.removed.push({
|
|
702
|
-
|
|
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
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
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
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
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
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
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
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
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
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
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
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
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
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
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></title><img>');
|
|
789
807
|
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
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
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
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
|
-
|
|
814
|
-
|
|
815
|
-
|
|
835
|
+
var _isClobbered = function _isClobbered(elm) {
|
|
836
|
+
if (elm instanceof Text || elm instanceof Comment) {
|
|
837
|
+
return false;
|
|
838
|
+
}
|
|
816
839
|
|
|
817
|
-
|
|
818
|
-
|
|
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
|
-
|
|
850
|
-
|
|
851
|
-
|
|
867
|
+
var _executeHook = function _executeHook(entryPoint, currentNode, data) {
|
|
868
|
+
if (!hooks[entryPoint]) {
|
|
869
|
+
return;
|
|
870
|
+
}
|
|
852
871
|
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
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
|
-
|
|
864
|
-
|
|
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
|
-
|
|
882
|
-
|
|
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
|
-
|
|
903
|
-
|
|
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
|
-
|
|
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
|
-
|
|
915
|
-
|
|
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
|
-
|
|
925
|
-
|
|
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
|
-
|
|
937
|
+
if (tagName === 'noembed' && currentNode.innerHTML.match(/<\/noembed/i)) {
|
|
938
|
+
_forceRemove(currentNode);
|
|
934
939
|
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
940
|
+
return true;
|
|
941
|
+
}
|
|
942
|
+
/* Convert markup to cover jQuery behavior */
|
|
938
943
|
|
|
939
944
|
|
|
940
|
-
|
|
941
|
-
|
|
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
|
-
|
|
950
|
+
if (currentNode.innerHTML) {
|
|
951
|
+
currentNode.innerHTML = currentNode.innerHTML.replace(/</g, '<');
|
|
952
|
+
} else {
|
|
953
|
+
currentNode.innerHTML = currentNode.textContent.replace(/</g, '<');
|
|
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 (
|
|
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, '<');
|
|
961
|
-
} else {
|
|
962
|
-
currentNode.innerHTML = currentNode.textContent.replace(/</g, '<');
|
|
963
|
-
}
|
|
969
|
+
currentNode.textContent = content;
|
|
964
970
|
}
|
|
965
|
-
|
|
971
|
+
}
|
|
972
|
+
/* Execute a hook if present */
|
|
966
973
|
|
|
967
974
|
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
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
|
-
|
|
1032
|
-
|
|
1033
|
-
var
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
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
|
-
|
|
1057
|
+
hookEvent.attrName = lcName;
|
|
1058
|
+
hookEvent.attrValue = value;
|
|
1059
|
+
hookEvent.keepAttr = true;
|
|
1040
1060
|
|
|
1041
|
-
|
|
1042
|
-
/* Check if we have attributes; if not we might have a text node */
|
|
1061
|
+
_executeHook('uponSanitizeAttribute', currentNode, hookEvent);
|
|
1043
1062
|
|
|
1044
|
-
|
|
1045
|
-
|
|
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
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
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
|
-
|
|
1107
|
-
continue;
|
|
1108
|
-
}
|
|
1109
|
-
/* Sanitize attribute content to be template-safe */
|
|
1110
|
-
|
|
1075
|
+
_removeAttribute(name, currentNode);
|
|
1111
1076
|
|
|
1112
|
-
if (
|
|
1113
|
-
|
|
1114
|
-
|
|
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
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1097
|
+
if (!hookEvent.keepAttr) {
|
|
1098
|
+
continue;
|
|
1099
|
+
}
|
|
1100
|
+
/* Sanitize attribute content to be template-safe */
|
|
1125
1101
|
|
|
1126
1102
|
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
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
|
-
/*
|
|
1107
|
+
/* Is `value` valid for this attribute? */
|
|
1139
1108
|
|
|
1140
1109
|
|
|
1141
|
-
|
|
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
|
-
|
|
1154
|
-
|
|
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
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1132
|
+
_executeHook('afterSanitizeAttributes', currentNode, null);
|
|
1133
|
+
};
|
|
1134
|
+
/**
|
|
1135
|
+
* _sanitizeShadowDOM
|
|
1136
|
+
*
|
|
1137
|
+
* @param {DocumentFragment} fragment to iterate over recursively
|
|
1138
|
+
*/
|
|
1163
1139
|
|
|
1164
1140
|
|
|
1165
|
-
|
|
1166
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
/*
|
|
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
|
-
|
|
1218
|
-
|
|
1219
|
-
}
|
|
1220
|
-
}
|
|
1162
|
+
if (shadowNode.content instanceof DocumentFragment) {
|
|
1163
|
+
_sanitizeShadowDOM(shadowNode.content);
|
|
1221
1164
|
}
|
|
1222
|
-
/* Check
|
|
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
|
-
|
|
1232
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
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
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1206
|
+
dirty = dirty.toString();
|
|
1207
|
+
|
|
1208
|
+
if (typeof dirty !== 'string') {
|
|
1209
|
+
throw new TypeError('dirty is not a string, aborting');
|
|
1268
1210
|
}
|
|
1269
|
-
|
|
1211
|
+
}
|
|
1212
|
+
}
|
|
1213
|
+
/* Check we can run. Otherwise fall back or ignore */
|
|
1270
1214
|
|
|
1271
1215
|
|
|
1272
|
-
|
|
1273
|
-
|
|
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 (
|
|
1276
|
-
return
|
|
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
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
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
|
-
|
|
1301
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1321
|
-
|
|
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
|
-
/*
|
|
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
|
-
|
|
1331
|
-
|
|
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 (
|
|
1354
|
-
|
|
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
|
-
|
|
1369
|
-
|
|
1305
|
+
oldNode = currentNode;
|
|
1306
|
+
}
|
|
1370
1307
|
|
|
1371
|
-
|
|
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
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
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
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
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
|
-
|
|
1416
|
-
|
|
1417
|
-
return;
|
|
1418
|
-
}
|
|
1341
|
+
var serializedHTML = WHOLE_DOCUMENT ? body.outerHTML : body.innerHTML;
|
|
1342
|
+
/* Sanitize final string template-safe */
|
|
1419
1343
|
|
|
1420
|
-
|
|
1421
|
-
|
|
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
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
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
|
-
|
|
1458
|
-
|
|
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
|
-
|
|
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
|
-
*
|
|
1468
|
-
*
|
|
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
|
-
*
|
|
1473
|
-
*
|
|
1474
|
-
|
|
1475
|
-
|
|
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
|
-
*
|
|
1478
|
-
|
|
1479
|
-
|
|
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
|
-
*
|
|
1432
|
+
* @param {String} entryPoint entry point for the hooks to remove
|
|
1482
1433
|
*/
|
|
1483
|
-
|
|
1484
|
-
|
|
1434
|
+
|
|
1435
|
+
|
|
1436
|
+
DOMPurify.removeHooks = function (entryPoint) {
|
|
1437
|
+
if (hooks[entryPoint]) {
|
|
1438
|
+
hooks[entryPoint] = [];
|
|
1439
|
+
}
|
|
1485
1440
|
};
|
|
1486
1441
|
/**
|
|
1487
|
-
*
|
|
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
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
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
|
-
*
|
|
1503
|
-
* @
|
|
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
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
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
|
-
},
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
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
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
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 (
|
|
1581
|
-
|
|
1541
|
+
if (resources.total > _.size(self.getNodes())) {
|
|
1542
|
+
hider.show($loadMore);
|
|
1582
1543
|
} else {
|
|
1583
|
-
|
|
1544
|
+
hider.hide($loadMore);
|
|
1584
1545
|
}
|
|
1585
|
-
|
|
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
|
-
|
|
1595
|
-
this.update(this.config.nodes);
|
|
1596
|
-
} else {
|
|
1597
|
-
this.query();
|
|
1552
|
+
this.trigger('update');
|
|
1598
1553
|
}
|
|
1599
|
-
}
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
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
|
-
}); //
|
|
1576
|
+
}); //load next page
|
|
1608
1577
|
|
|
1609
|
-
|
|
1610
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1607
|
+
return resourceListFactory;
|
|
1617
1608
|
|
|
1618
1609
|
});
|