@syncfusion/ej2-base 24.2.8 → 25.1.35-579988

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (163) hide show
  1. package/.eslintrc.json +2 -1
  2. package/CHANGELOG.md +641 -677
  3. package/{README.md → ReadMe.md} +100 -100
  4. package/dist/ej2-base.umd.min.js +1 -10
  5. package/dist/ej2-base.umd.min.js.map +1 -1
  6. package/dist/es6/ej2-base.es2015.js +178 -1025
  7. package/dist/es6/ej2-base.es2015.js.map +1 -1
  8. package/dist/es6/ej2-base.es5.js +226 -934
  9. package/dist/es6/ej2-base.es5.js.map +1 -1
  10. package/dist/global/ej2-base.min.js +1 -10
  11. package/dist/global/ej2-base.min.js.map +1 -1
  12. package/dist/global/index.d.ts +0 -9
  13. package/dist/ts/ajax.ts +236 -0
  14. package/dist/ts/animation.ts +544 -0
  15. package/dist/ts/base.ts +357 -0
  16. package/dist/ts/browser.ts +387 -0
  17. package/dist/ts/child-property.ts +192 -0
  18. package/dist/ts/component.ts +519 -0
  19. package/dist/ts/dom.ts +488 -0
  20. package/dist/ts/draggable.ts +1155 -0
  21. package/dist/ts/droppable.ts +172 -0
  22. package/dist/ts/event-handler.ts +169 -0
  23. package/dist/ts/internationalization.ts +369 -0
  24. package/dist/ts/intl/date-formatter.ts +317 -0
  25. package/dist/ts/intl/date-parser.ts +426 -0
  26. package/dist/ts/intl/intl-base.ts +1104 -0
  27. package/dist/ts/intl/number-formatter.ts +411 -0
  28. package/dist/ts/intl/number-parser.ts +158 -0
  29. package/dist/ts/intl/parser-base.ts +394 -0
  30. package/dist/ts/keyboard.ts +238 -0
  31. package/dist/ts/l10n.ts +94 -0
  32. package/dist/ts/module-loader.ts +149 -0
  33. package/dist/ts/notify-property-change.ts +726 -0
  34. package/dist/ts/observer.ts +236 -0
  35. package/dist/ts/sanitize-helper.ts +224 -0
  36. package/dist/ts/template-engine.ts +191 -0
  37. package/dist/ts/template.ts +329 -0
  38. package/dist/ts/touch.ts +544 -0
  39. package/dist/ts/util.ts +523 -0
  40. package/dist/ts/validate-lic.ts +0 -0
  41. package/e2e/crypto.js +16 -16
  42. package/e2e/m.protractor.config.js +286 -286
  43. package/e2e/modified-protractor/protractor.config.js +316 -316
  44. package/e2e/protractor.config.js +389 -332
  45. package/helpers/e2e/index.js +3 -3
  46. package/license +10 -10
  47. package/package.json +225 -174
  48. package/src/ajax.d.ts +1 -1
  49. package/src/ajax.js +3 -8
  50. package/src/animation-model.d.ts +41 -41
  51. package/src/animation.d.ts +6 -6
  52. package/src/animation.js +25 -25
  53. package/src/base.d.ts +2 -1
  54. package/src/base.js +9 -7
  55. package/src/component-model.d.ts +16 -16
  56. package/src/component.d.ts +9 -3
  57. package/src/component.js +50 -38
  58. package/src/draggable-model.d.ts +113 -113
  59. package/src/draggable.d.ts +2 -0
  60. package/src/draggable.js +45 -29
  61. package/src/droppable-model.d.ts +23 -23
  62. package/src/droppable.js +19 -19
  63. package/src/event-handler.js +2 -1
  64. package/src/index.d.ts +0 -3
  65. package/src/index.js +0 -3
  66. package/src/intl/date-formatter.js +2 -6
  67. package/src/intl/date-parser.js +1 -20
  68. package/src/intl/intl-base.js +1 -164
  69. package/src/intl/number-formatter.d.ts +3 -0
  70. package/src/intl/number-formatter.js +7 -7
  71. package/src/intl/number-parser.js +1 -0
  72. package/src/keyboard-model.d.ts +16 -16
  73. package/src/keyboard.js +19 -19
  74. package/src/module-loader.d.ts +12 -0
  75. package/src/module-loader.js +11 -0
  76. package/src/notify-property-change.js +3 -2
  77. package/src/observer.js +2 -0
  78. package/src/sanitize-helper.js +5 -0
  79. package/src/template-engine.js +1 -0
  80. package/src/template.js +3 -2
  81. package/src/touch-model.d.ts +39 -39
  82. package/src/touch.js +19 -19
  83. package/src/validate-lic.d.ts +0 -11
  84. package/src/validate-lic.js +1 -259
  85. package/styles/_all.scss +2 -2
  86. package/styles/_bds-dark-definition.scss +15 -0
  87. package/styles/_bds-definition.scss +15 -0
  88. package/styles/_bootstrap-dark-definition.scss +42 -42
  89. package/styles/_bootstrap-definition.scss +42 -42
  90. package/styles/_bootstrap4-definition.scss +11 -11
  91. package/styles/_bootstrap5-dark-definition.scss +9 -9
  92. package/styles/_bootstrap5-definition.scss +8 -8
  93. package/styles/_fabric-dark-definition.scss +42 -42
  94. package/styles/_fabric-definition.scss +42 -42
  95. package/styles/_fluent-dark-definition.scss +9 -9
  96. package/styles/_fluent-definition.scss +9 -9
  97. package/styles/_fluent2-definition.scss +9 -0
  98. package/styles/_fusionnew-dark-definition.scss +8 -8
  99. package/styles/_fusionnew-definition.scss +8 -8
  100. package/styles/_highcontrast-definition.scss +42 -42
  101. package/styles/_highcontrast-light-definition.scss +42 -42
  102. package/styles/_material-dark-definition.scss +48 -48
  103. package/styles/_material-definition.scss +49 -49
  104. package/styles/_material3-dark-definition.scss +14 -14
  105. package/styles/_material3-definition.scss +15 -15
  106. package/styles/_tailwind-dark-definition.scss +15 -15
  107. package/styles/_tailwind-definition.scss +15 -15
  108. package/styles/animation/_all.scss +560 -560
  109. package/styles/bootstrap-dark.css +10 -1
  110. package/styles/bootstrap.css +10 -1
  111. package/styles/bootstrap4.css +10 -1
  112. package/styles/bootstrap5-dark.css +10 -1
  113. package/styles/bootstrap5.css +10 -1
  114. package/styles/common/_all.scss +2 -2
  115. package/styles/common/_core.scss +117 -117
  116. package/styles/common/_mixin.scss +9 -9
  117. package/styles/definition/_bds-dark.scss +1179 -0
  118. package/styles/definition/_bds.scss +1474 -0
  119. package/styles/definition/_bootstrap-dark.scss +219 -219
  120. package/styles/definition/_bootstrap.scss +215 -215
  121. package/styles/definition/_bootstrap4.scss +167 -167
  122. package/styles/definition/_bootstrap5-dark.scss +493 -493
  123. package/styles/definition/_bootstrap5.scss +494 -494
  124. package/styles/definition/_fabric-dark.scss +200 -200
  125. package/styles/definition/_fabric.scss +198 -198
  126. package/styles/definition/_fluent-dark.scss +557 -557
  127. package/styles/definition/_fluent.scss +558 -558
  128. package/styles/definition/_fluent2.scss +2198 -0
  129. package/styles/definition/_fusionnew-dark.scss +362 -362
  130. package/styles/definition/_fusionnew.scss +363 -363
  131. package/styles/definition/_highcontrast-light.scss +193 -193
  132. package/styles/definition/_highcontrast.scss +195 -195
  133. package/styles/definition/_material-dark.scss +198 -198
  134. package/styles/definition/_material.scss +192 -192
  135. package/styles/definition/_material3-dark.scss +710 -710
  136. package/styles/definition/_material3.scss +792 -792
  137. package/styles/definition/_tailwind-dark.scss +488 -488
  138. package/styles/definition/_tailwind.scss +485 -485
  139. package/styles/fabric-dark.css +10 -1
  140. package/styles/fabric.css +10 -1
  141. package/styles/fluent-dark.css +10 -1
  142. package/styles/fluent.css +10 -1
  143. package/styles/highcontrast-light.css +10 -1
  144. package/styles/highcontrast.css +10 -1
  145. package/styles/material-dark.css +10 -1
  146. package/styles/material.css +10 -1
  147. package/styles/material3-dark.css +10 -1
  148. package/styles/material3.css +10 -1
  149. package/styles/offline-theme/material-dark.css +10 -1
  150. package/styles/offline-theme/material.css +10 -1
  151. package/styles/offline-theme/tailwind-dark.css +10 -1
  152. package/styles/offline-theme/tailwind.css +10 -1
  153. package/styles/tailwind-dark.css +10 -1
  154. package/styles/tailwind.css +10 -1
  155. package/.github/PULL_REQUEST_TEMPLATE/Bug.md +0 -60
  156. package/.github/PULL_REQUEST_TEMPLATE/feature.md +0 -42
  157. package/bin/syncfusion-license.js +0 -2
  158. package/dist/ej2-base.min.js +0 -10
  159. package/e2e/index.d.ts +0 -27
  160. package/src/fetch.d.ts +0 -114
  161. package/src/fetch.js +0 -116
  162. package/src/hijri-parser.d.ts +0 -19
  163. package/src/hijri-parser.js +0 -204
@@ -0,0 +1,236 @@
1
+ import { isNullOrUndefined, getValue, extend, isBlazor } from './util';
2
+ /**
3
+ * Observer is used to perform event handling based the object.
4
+ * ```
5
+ * //Creating observer instance.
6
+ * let observer:Observer = Observer(this);
7
+ * let handler: Function = (a:number, b: number): number => {return a + b; }
8
+ * //add handler to event.
9
+ * observe.on('eventname', handler);
10
+ * //remove handler from event.
11
+ * observe.off('eventname', handler);
12
+ * //notify the handlers in event.
13
+ * observe.notify('eventname');
14
+ * ```
15
+ *
16
+ */
17
+ export interface BoundOptions {
18
+ handler?: Function;
19
+ context?: Object;
20
+ event?: string;
21
+ id?: string;
22
+ }
23
+ export class Observer {
24
+ private context: Object;
25
+ private ranArray: string[] = [];
26
+ private boundedEvents: { [key: string]: [BoundOptions] } = {};
27
+ constructor(context?: Object) {
28
+ if (isNullOrUndefined(context)) {
29
+ return;
30
+ }
31
+ this.context = context;
32
+ }
33
+ /**
34
+ * To attach handler for given property in current context.
35
+ *
36
+ * @param {string} property - specifies the name of the event.
37
+ * @param {Function} handler - Specifies the handler function to be called while event notified.
38
+ * @param {Object} context - Specifies the context binded to the handler.
39
+ * @param {string} id - specifies the random generated id.
40
+ * @returns {void}
41
+ */
42
+ public on(property: string, handler: Function, context?: Object, id?: string): void {
43
+ if (isNullOrUndefined(handler)) {
44
+ return;
45
+ }
46
+ const cntxt: Object = context || this.context;
47
+ if (this.notExist(property)) {
48
+ this.boundedEvents[`${property}`] = [{ handler: handler, context: cntxt, id: id }];
49
+ return;
50
+ }
51
+ if (!isNullOrUndefined(id)) {
52
+ if (this.ranArray.indexOf(id) === -1) {
53
+ this.ranArray.push(id);
54
+ this.boundedEvents[`${property}`].push({ handler: handler, context: cntxt, id: id });
55
+ }
56
+ } else if (!this.isHandlerPresent(this.boundedEvents[`${property}`], handler)) {
57
+ this.boundedEvents[`${property}`].push({ handler: handler, context: cntxt });
58
+ }
59
+ }
60
+
61
+ /**
62
+ * To remove handlers from a event attached using on() function.
63
+ *
64
+ * @param {string} property - specifies the name of the event.
65
+ * @param {Function} handler - Optional argument specifies the handler function to be called while event notified.
66
+ * @param {string} id - specifies the random generated id.
67
+ * @returns {void} ?
68
+ */
69
+ public off(property: string, handler?: Function, id?: string): void {
70
+ if (this.notExist(property)) {
71
+ return;
72
+ }
73
+ const curObject: BoundOptions[] = getValue(property, this.boundedEvents);
74
+ if (handler) {
75
+ for (let i: number = 0; i < curObject.length; i++) {
76
+ if (id) {
77
+ if (curObject[parseInt(i.toString(), 10)].id === id) {
78
+ curObject.splice(i, 1);
79
+ const indexLocation: number = this.ranArray.indexOf(id);
80
+ if (indexLocation !== -1) {
81
+ this.ranArray.splice(indexLocation, 1);
82
+ }
83
+ break;
84
+ }
85
+ } else if (handler === curObject[parseInt(i.toString(), 10)].handler) {
86
+ curObject.splice(i, 1);
87
+ break;
88
+ }
89
+ }
90
+ } else {
91
+ delete this.boundedEvents[`${property}`];
92
+ }
93
+ }
94
+
95
+ /**
96
+ * To notify the handlers in the specified event.
97
+ *
98
+ * @param {string} property - Specifies the event to be notify.
99
+ * @param {Object} argument - Additional parameters to pass while calling the handler.
100
+ * @param {Function} successHandler - this function will invoke after event successfully triggered
101
+ * @param {Function} errorHandler - this function will invoke after event if it was failure to call.
102
+ * @returns {void} ?
103
+ */
104
+ public notify(property: string, argument?: Object, successHandler?: Function, errorHandler?: Function): void | Object {
105
+ if (this.notExist(property)) {
106
+ if (successHandler) {
107
+ successHandler.call(this, argument);
108
+ }
109
+ return;
110
+ }
111
+ if (argument) {
112
+ (<{ name: string }>argument).name = property;
113
+ }
114
+ const blazor: string = 'Blazor';
115
+ const curObject: BoundOptions[] = getValue(property, this.boundedEvents).slice(0);
116
+ if (window[`${blazor}`]) {
117
+ return this.blazorCallback(curObject, argument, successHandler, errorHandler, 0);
118
+ } else {
119
+ for (const cur of curObject) {
120
+ cur.handler.call(cur.context, argument);
121
+ }
122
+ if (successHandler) {
123
+ successHandler.call(this, argument);
124
+ }
125
+ }
126
+ }
127
+
128
+ private blazorCallback(
129
+ objs: BoundOptions[],
130
+ argument: object,
131
+ successHandler: Function,
132
+ errorHandler: Function,
133
+ index: number): void | object {
134
+ const isTrigger: boolean = index === objs.length - 1;
135
+ if (index < objs.length) {
136
+ const obj: BoundOptions = objs[parseInt(index.toString(), 10)];
137
+ const promise: Promise<object> = obj.handler.call(obj.context, argument);
138
+ if (promise && typeof promise.then === 'function') {
139
+ if (!successHandler) {
140
+ return promise;
141
+ }
142
+ promise.then((data: object) => {
143
+ data = typeof data === 'string' && this.isJson(data) ? JSON.parse(data as string, this.dateReviver) : data;
144
+ extend(argument, argument, data, true);
145
+ if (successHandler && isTrigger) {
146
+ successHandler.call(obj.context, argument);
147
+ } else {
148
+ return this.blazorCallback(objs, argument, successHandler, errorHandler, index + 1);
149
+ }
150
+ }).catch((data: object) => {
151
+ if (errorHandler) {
152
+ errorHandler.call(obj.context, typeof data === 'string' &&
153
+ this.isJson(data) ? JSON.parse(data, this.dateReviver) : data);
154
+ }
155
+ });
156
+ } else if (successHandler && isTrigger) {
157
+ successHandler.call(obj.context, argument);
158
+ } else {
159
+ return this.blazorCallback(objs, argument, successHandler, errorHandler, index + 1);
160
+ }
161
+ }
162
+ }
163
+
164
+ // eslint-disable-next-line
165
+ public dateReviver(key: any, value: any): void | object {
166
+ const dPattern: RegExp = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/;
167
+ if (isBlazor && typeof value === 'string' && value.match(dPattern) !== null) {
168
+ return (new Date(value));
169
+ }
170
+ return (value);
171
+ }
172
+
173
+ public isJson(value: string): boolean {
174
+ try {
175
+ JSON.parse(value);
176
+ } catch (e) {
177
+ return false;
178
+ }
179
+ return true;
180
+ }
181
+ /**
182
+ * To destroy handlers in the event
183
+ *
184
+ * @returns {void} ?
185
+ */
186
+ public destroy(): void {
187
+ this.boundedEvents = this.context = undefined;
188
+ }
189
+ /**
190
+ * To remove internationalization events
191
+ *
192
+ * @returns {void} ?
193
+ */
194
+ public offIntlEvents(): void {
195
+ // eslint-disable-next-line
196
+ const eventsArr: any = this.boundedEvents['notifyExternalChange'];
197
+ if (eventsArr) {
198
+ for (let i: number = 0; i < eventsArr.length; i++) {
199
+ // eslint-disable-next-line
200
+ const curContext: any = eventsArr[`${i}`].context;
201
+ if (curContext && curContext.detectFunction && curContext.randomId && !curContext.isRendered) {
202
+ this.off('notifyExternalChange', curContext.detectFunction, curContext.randomId);
203
+ i--;
204
+ }
205
+ }
206
+ if (!this.boundedEvents['notifyExternalChange'].length) {
207
+ delete this.boundedEvents['notifyExternalChange'];
208
+ }
209
+ }
210
+ }
211
+ /**
212
+ * Returns if the property exists.
213
+ *
214
+ * @param {string} prop ?
215
+ * @returns {boolean} ?
216
+ */
217
+ private notExist(prop: string): boolean {
218
+ // eslint-disable-next-line
219
+ return this.boundedEvents.hasOwnProperty(prop) === false || this.boundedEvents[prop].length <= 0;
220
+ }
221
+ /**
222
+ * Returns if the handler is present.
223
+ *
224
+ * @param {BoundOptions[]} boundedEvents ?
225
+ * @param {Function} handler ?
226
+ * @returns {boolean} ?
227
+ */
228
+ private isHandlerPresent(boundedEvents: BoundOptions[], handler: Function): boolean {
229
+ for (const cur of boundedEvents) {
230
+ if (cur.handler === handler) {
231
+ return true;
232
+ }
233
+ }
234
+ return false;
235
+ }
236
+ }
@@ -0,0 +1,224 @@
1
+ /**
2
+ * SanitizeHtmlHelper for sanitize the value.
3
+ */
4
+ import { detach } from './dom';
5
+ import { isNullOrUndefined } from './util';
6
+
7
+ interface BeforeSanitizeHtml {
8
+ /** Illustrates whether the current action needs to be prevented or not. */
9
+ cancel?: boolean;
10
+ /** It is a callback function and executed it before our inbuilt action. It should return HTML as a string.
11
+ *
12
+ * @function
13
+ * @param {string} value - Returns the value.
14
+ * @returns {string}
15
+ */
16
+ /** Returns the selectors object which carrying both tags and attributes selectors to block list of cross-site scripting attack.
17
+ * Also possible to modify the block list in this event.
18
+ */
19
+ selectors?: SanitizeSelectors;
20
+ }
21
+
22
+ interface SanitizeSelectors {
23
+ /** Returns the tags. */
24
+ tags?: string[];
25
+ /** Returns the attributes. */
26
+ attributes?: SanitizeRemoveAttrs[];
27
+ }
28
+
29
+ interface SanitizeRemoveAttrs {
30
+ /** Defines the attribute name to sanitize */
31
+ attribute?: string;
32
+ /** Defines the selector that sanitize the specified attributes within the selector */
33
+ selector?: string;
34
+ }
35
+
36
+ const removeTags: string[] = [
37
+ 'script',
38
+ 'style',
39
+ 'iframe[src]',
40
+ 'link[href*="javascript:"]',
41
+ 'object[type="text/x-scriptlet"]',
42
+ 'object[data^="data:text/html;base64"]',
43
+ 'img[src^="data:text/html;base64"]',
44
+ '[src^="javascript:"]',
45
+ '[dynsrc^="javascript:"]',
46
+ '[lowsrc^="javascript:"]',
47
+ '[type^="application/x-shockwave-flash"]'
48
+ ];
49
+
50
+ const removeAttrs: SanitizeRemoveAttrs[] = [
51
+ { attribute: 'href', selector: '[href*="javascript:"]' },
52
+ { attribute: 'background', selector: '[background^="javascript:"]' },
53
+ { attribute: 'style', selector: '[style*="javascript:"]' },
54
+ { attribute: 'style', selector: '[style*="expression("]' },
55
+ { attribute: 'href', selector: 'a[href^="data:text/html;base64"]' }];
56
+
57
+ const jsEvents: string[] = ['onchange',
58
+ 'onclick',
59
+ 'onmouseover',
60
+ 'onmouseout',
61
+ 'onkeydown',
62
+ 'onload',
63
+ 'onerror',
64
+ 'onblur',
65
+ 'onfocus',
66
+ 'onbeforeload',
67
+ 'onbeforeunload',
68
+ 'onkeyup',
69
+ 'onsubmit',
70
+ 'onafterprint',
71
+ 'onbeforeonload',
72
+ 'onbeforeprint',
73
+ 'oncanplay',
74
+ 'oncanplaythrough',
75
+ 'oncontextmenu',
76
+ 'ondblclick',
77
+ 'ondrag',
78
+ 'ondragend',
79
+ 'ondragenter',
80
+ 'ondragleave',
81
+ 'ondragover',
82
+ 'ondragstart',
83
+ 'ondrop',
84
+ 'ondurationchange',
85
+ 'onemptied',
86
+ 'onended',
87
+ 'onformchange',
88
+ 'onforminput',
89
+ 'onhaschange',
90
+ 'oninput',
91
+ 'oninvalid',
92
+ 'onkeypress',
93
+ 'onloadeddata',
94
+ 'onloadedmetadata',
95
+ 'onloadstart',
96
+ 'onmessage',
97
+ 'onmousedown',
98
+ 'onmousemove',
99
+ 'onmouseup',
100
+ 'onmousewheel',
101
+ 'onoffline',
102
+ 'onoine',
103
+ 'ononline',
104
+ 'onpagehide',
105
+ 'onpageshow',
106
+ 'onpause',
107
+ 'onplay',
108
+ 'onplaying',
109
+ 'onpopstate',
110
+ 'onprogress',
111
+ 'onratechange',
112
+ 'onreadystatechange',
113
+ 'onredo',
114
+ 'onresize',
115
+ 'onscroll',
116
+ 'onseeked',
117
+ 'onseeking',
118
+ 'onselect',
119
+ 'onstalled',
120
+ 'onstorage',
121
+ 'onsuspend',
122
+ 'ontimeupdate',
123
+ 'onundo',
124
+ 'onunload',
125
+ 'onvolumechange',
126
+ 'onwaiting',
127
+ 'onmouseenter',
128
+ 'onmouseleave',
129
+ 'onstart',
130
+ 'onpropertychange',
131
+ 'oncopy',
132
+ 'ontoggle',
133
+ 'onpointerout',
134
+ 'onpointermove',
135
+ 'onpointerleave',
136
+ 'onpointerenter',
137
+ 'onpointerrawupdate',
138
+ 'onpointerover',
139
+ 'onbeforecopy',
140
+ 'onbeforecut',
141
+ 'onbeforeinput'
142
+ ];
143
+ export class SanitizeHtmlHelper {
144
+ public static removeAttrs: SanitizeRemoveAttrs[];
145
+ public static removeTags: string[];
146
+ public static wrapElement: HTMLElement;
147
+ public static beforeSanitize(): BeforeSanitizeHtml {
148
+ return {
149
+ selectors: {
150
+ tags: removeTags,
151
+ attributes: removeAttrs
152
+ }
153
+ };
154
+ }
155
+ public static sanitize(value: string): string {
156
+ if (isNullOrUndefined(value)) { return value; }
157
+ const item: BeforeSanitizeHtml = this.beforeSanitize();
158
+ const output: string = this.serializeValue(item, value);
159
+ return output;
160
+ }
161
+
162
+ public static serializeValue(item: BeforeSanitizeHtml, value: string): string {
163
+ this.removeAttrs = item.selectors.attributes;
164
+ this.removeTags = item.selectors.tags;
165
+ this.wrapElement = document.createElement('div');
166
+ this.wrapElement.innerHTML = value;
167
+ this.removeXssTags();
168
+ this.removeJsEvents();
169
+ this.removeXssAttrs();
170
+ const tempEleValue: string = this.wrapElement.innerHTML;
171
+ this.removeElement();
172
+ this.wrapElement = null;
173
+ return tempEleValue.replace(/&amp;/g, '&');
174
+ }
175
+
176
+ private static removeElement(): void {
177
+ // Removes an element's attibute to avoid html tag validation
178
+ const nodes: HTMLCollection = this.wrapElement.children;
179
+ for (let j: number = 0; j < nodes.length; j++) {
180
+ const attribute: NamedNodeMap = nodes[parseInt(j.toString(), 10)].attributes;
181
+ for (let i: number = 0; i < attribute.length; i++) {
182
+ this.wrapElement.children[parseInt(j.toString(), 10)].removeAttribute(attribute[parseInt(i.toString(), 10)].localName);
183
+ }
184
+ }
185
+ }
186
+
187
+ private static removeXssTags(): void {
188
+ const elements: NodeListOf<HTMLElement> = this.wrapElement.querySelectorAll(this.removeTags.join(','));
189
+ if (elements.length > 0) {
190
+ elements.forEach((element: Element) => {
191
+ detach(element);
192
+ });
193
+ } else {
194
+ return;
195
+ }
196
+ }
197
+
198
+ private static removeJsEvents(): void {
199
+ const elements: NodeListOf<HTMLElement> = this.wrapElement.querySelectorAll('[' + jsEvents.join('],[') + ']');
200
+ if (elements.length > 0) {
201
+ elements.forEach((element: Element) => {
202
+ jsEvents.forEach((attr: string) => {
203
+ if (element.hasAttribute(attr)) {
204
+ element.removeAttribute(attr);
205
+ }
206
+ });
207
+ });
208
+ } else {
209
+ return;
210
+ }
211
+ }
212
+
213
+ private static removeXssAttrs(): void {
214
+ // eslint-disable-next-line
215
+ this.removeAttrs.forEach((item: { [key: string]: string }, index: number) => {
216
+ const elements: NodeListOf<HTMLElement> = this.wrapElement.querySelectorAll(item.selector);
217
+ if (elements.length > 0) {
218
+ elements.forEach((element: Element) => {
219
+ element.removeAttribute(item.attribute);
220
+ });
221
+ }
222
+ });
223
+ }
224
+ }
@@ -0,0 +1,191 @@
1
+ /**
2
+ * Template Engine Bridge
3
+ */
4
+ import { compile as render } from './template';
5
+ import { createElement } from './dom';
6
+ import { isNullOrUndefined, isBlazor } from './util';
7
+
8
+ const HAS_ROW: RegExp = /^[\n\r.]+<tr|^<tr/;
9
+ const HAS_SVG: RegExp = /^[\n\r.]+<svg|^<path|^<g/;
10
+ export const blazorTemplates: object = {};
11
+
12
+ /**
13
+ *
14
+ * @returns {string} ?
15
+ */
16
+ export function getRandomId(): string {
17
+
18
+ return '-' + Math.random().toString(36).substr(2, 5);
19
+ }
20
+
21
+ /**
22
+ * Interface for Template Engine.
23
+ */
24
+ export interface ITemplateEngine {
25
+ compile: (templateString: string | Function, helper?: Object, ignorePrefix?: boolean) => (data: Object | JSON) => string;
26
+ }
27
+
28
+ /**
29
+ * Compile the template string into template function.
30
+ *
31
+ * @param {string | Function} templateString - The template string which is going to convert.
32
+ * @param {Object} helper - Helper functions as an object.
33
+ * @param {boolean} ignorePrefix ?
34
+ * @returns {NodeList} ?
35
+ * @private
36
+ */
37
+ // eslint-disable-next-line
38
+ export function compile(templateString: string | Function, helper?: Object, ignorePrefix?:boolean): (data: Object | JSON, component?: any, propName?: any) => NodeList {
39
+ const compiler: Function = engineObj.compile(templateString, helper, ignorePrefix);
40
+ // eslint-disable-next-line
41
+ return (data: Object, component?: any, propName?: any, templateId?: any, isStringTemplate?: boolean, index?: number, element?: any, root?: any): NodeList => {
42
+ const result: object = compiler(data, component, propName, element, root);
43
+ const blazorTemplateId: string = 'BlazorTemplateId';
44
+ if (isBlazor() && !isStringTemplate) {
45
+ const randomId: string = getRandomId();
46
+ let blazorId: string = templateId + randomId;
47
+ if (!blazorTemplates[`${templateId}`]) {
48
+ blazorTemplates[`${templateId}`] = [];
49
+ }
50
+ if (!isNullOrUndefined(index)) {
51
+ const keys: string[] = Object.keys(blazorTemplates[`${templateId}`][parseInt(index.toString(), 10)]);
52
+ for (const key of keys) {
53
+ if (key !== blazorTemplateId && data[`${key}`]) {
54
+ blazorTemplates[`${templateId}`][parseInt(index.toString(), 10)][`${key}`] = data[`${key}`];
55
+ }
56
+ if (key === blazorTemplateId) {
57
+ blazorId = blazorTemplates[`${templateId}`][parseInt(index.toString(), 10)][`${key}`];
58
+ }
59
+ }
60
+ } else {
61
+ data[`${blazorTemplateId}`] = blazorId;
62
+ blazorTemplates[`${templateId}`].push(data);
63
+ }
64
+ // eslint-disable-next-line
65
+ return propName === 'rowTemplate' ? [createElement('tr', { id: blazorId, className: 'e-blazor-template' })] as any :
66
+ // eslint-disable-next-line
67
+ [createElement('div', { id: blazorId, className: 'e-blazor-template' })] as any;
68
+
69
+ }
70
+ if (typeof result === 'string') {
71
+ if (HAS_SVG.test(result)) {
72
+ const ele: HTMLElement = createElement('svg', { innerHTML: result });
73
+ return <NodeList>ele.childNodes;
74
+ } else {
75
+ const ele: HTMLElement = createElement((HAS_ROW.test(result) ? 'table' : 'div'), { innerHTML: result });
76
+ return <NodeList>ele.childNodes;
77
+ }
78
+ } else {
79
+ return <NodeList>result;
80
+ }
81
+ };
82
+ }
83
+
84
+ /**
85
+ *
86
+ * @param {string} templateId ?
87
+ * @param {string} templateName ?
88
+ * @param {string} comp ?
89
+ * @param {boolean} isEmpty ?
90
+ * @param {Function} callBack ?
91
+ * @returns {void} ?
92
+ */
93
+ export function updateBlazorTemplate(
94
+ templateId?: string, templateName?: string, comp?: object,
95
+ isEmpty?: boolean, callBack?: Function): void {
96
+ if (isBlazor()) {
97
+ const ejsIntrop: string = 'sfBlazor';
98
+ window[`${ejsIntrop}`].updateTemplate(templateName, blazorTemplates[`${templateId}`], templateId, comp, callBack);
99
+ if (isEmpty !== false) {
100
+ blazorTemplates[`${templateId}`] = [];
101
+ }
102
+ }
103
+ }
104
+
105
+ /**
106
+ *
107
+ * @param {string} templateId ?
108
+ * @param {string} templateName ?
109
+ * @param {number} index ?
110
+ * @returns {void} ?
111
+ */
112
+ export function resetBlazorTemplate(templateId?: string, templateName?: string, index?: number): void {
113
+ const templateDiv: HTMLElement = document.getElementById(templateId);
114
+ if (templateDiv) {
115
+ // eslint-disable-next-line
116
+ const innerTemplates: HTMLElement[] = templateDiv.getElementsByClassName('blazor-inner-template') as any;
117
+ for (let i: number = 0; i < innerTemplates.length; i++) {
118
+ let tempId: string = ' ';
119
+ if (!isNullOrUndefined(index)) {
120
+ tempId = innerTemplates[parseInt(index.toString(), 10)].getAttribute('data-templateId');
121
+ } else {
122
+ tempId = innerTemplates[parseInt(i.toString(), 10)].getAttribute('data-templateId');
123
+ }
124
+ const tempElement: HTMLElement = document.getElementById(tempId);
125
+ if (tempElement) {
126
+ const length: number = tempElement.childNodes.length;
127
+ for (let j: number = 0; j < length; j++) {
128
+ if (!isNullOrUndefined(index)) {
129
+ innerTemplates[parseInt(index.toString(), 10)].appendChild(tempElement.childNodes[0]);
130
+ i = innerTemplates.length;
131
+ } else {
132
+ innerTemplates[parseInt(i.toString(), 10)].appendChild(tempElement.childNodes[0]);
133
+ }
134
+ }
135
+
136
+ }
137
+ }
138
+ }
139
+ }
140
+
141
+ /**
142
+ * Set your custom template engine for template rendering.
143
+ *
144
+ * @param {ITemplateEngine} classObj - Class object for custom template.
145
+ * @returns {void} ?
146
+ * @private
147
+ */
148
+ export function setTemplateEngine(classObj: ITemplateEngine): void {
149
+ engineObj.compile = classObj.compile;
150
+ }
151
+
152
+ /**
153
+ * Get current template engine for template rendering
154
+ *
155
+ * @returns {string} ?
156
+ * @private
157
+ */
158
+ export function getTemplateEngine(): (template: string, helper?: Object) => (data: Object | JSON) => string {
159
+ return engineObj.compile;
160
+ }
161
+
162
+ /**
163
+ * Set the current template function to support Content Security Policy.
164
+ *
165
+ * @param {Function} template - The template function that is going to render.
166
+ * @param {any} helper - The data utilized by the template from the helper.
167
+ * @returns {Function} ?
168
+ * @private
169
+ */
170
+ // eslint-disable-next-line
171
+ export function initializeCSPTemplate (template : Function, helper?: any): Function {
172
+ let boundFunc : Function;
173
+ template.prototype.CSPTemplate = true;
174
+ if (!isNullOrUndefined(helper)) {
175
+ boundFunc = template.bind(helper);
176
+ boundFunc.prototype = Object.create(template.prototype);
177
+ } else {
178
+ boundFunc = template;
179
+ }
180
+ return boundFunc;
181
+ }
182
+
183
+ //Default Engine Class
184
+ class Engine implements ITemplateEngine {
185
+ // eslint-disable-next-line
186
+ public compile(templateString: string, helper: Object = {}, ignorePrefix?:boolean): (data: Object | JSON) => string {
187
+ return render(templateString, helper);
188
+ }
189
+ }
190
+
191
+ const engineObj: ITemplateEngine = { compile: new Engine().compile };