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