mirror of
https://github.com/php-flasher/php-flasher.git
synced 2026-03-31 15:07:47 +01:00
chore: add escapeHtml option for secure HTML escaping in notifications
This commit is contained in:
@@ -19,6 +19,7 @@ export default class FlasherPlugin extends AbstractPlugin {
|
||||
direction: 'top',
|
||||
rtl: false,
|
||||
style: {} as Properties,
|
||||
escapeHtml: false,
|
||||
}
|
||||
|
||||
constructor(theme: Theme) {
|
||||
@@ -31,11 +32,12 @@ export default class FlasherPlugin extends AbstractPlugin {
|
||||
const render = () =>
|
||||
envelopes.forEach((envelope) => {
|
||||
// @ts-expect-error
|
||||
const typeTimeout = this.options.timeout ?? this.options.timeouts[envelope.type] ?? 5000;
|
||||
const typeTimeout = this.options.timeout ?? this.options.timeouts[envelope.type] ?? 5000
|
||||
const options = {
|
||||
...this.options,
|
||||
...envelope.options,
|
||||
timeout: envelope.options.timeout ?? typeTimeout,
|
||||
escapeHtml: (envelope.options.escapeHtml ?? this.options.escapeHtml) as boolean,
|
||||
}
|
||||
|
||||
this.addToContainer(this.createContainer(options), envelope, options)
|
||||
@@ -64,7 +66,12 @@ export default class FlasherPlugin extends AbstractPlugin {
|
||||
return container
|
||||
}
|
||||
|
||||
private addToContainer(container: HTMLDivElement, envelope: Envelope, options: { direction: string, timeout: number, fps: number, rtl: boolean }): void {
|
||||
private addToContainer(container: HTMLDivElement, envelope: Envelope, options: { direction: string, timeout: number, fps: number, rtl: boolean, escapeHtml: boolean }): void {
|
||||
if (options.escapeHtml) {
|
||||
envelope.title = this.escapeHtml(envelope.title)
|
||||
envelope.message = this.escapeHtml(envelope.message)
|
||||
}
|
||||
|
||||
const notification = this.stringToHTML(this.theme.render(envelope))
|
||||
|
||||
notification.classList.add(...`fl-container${options.rtl ? ' fl-rtl' : ''}`.split(' '))
|
||||
@@ -126,4 +133,23 @@ export default class FlasherPlugin extends AbstractPlugin {
|
||||
template.innerHTML = str.trim()
|
||||
return template.content.firstElementChild as HTMLElement
|
||||
}
|
||||
|
||||
private escapeHtml(str: string | null | undefined): string {
|
||||
if (str == null) {
|
||||
return ''
|
||||
}
|
||||
|
||||
return str.replace(/[&<>"'`=\/]/g, (char) => {
|
||||
return {
|
||||
'&': '&',
|
||||
'<': '<',
|
||||
'>': '>',
|
||||
'"': '"',
|
||||
'\'': ''',
|
||||
'`': '`',
|
||||
'=': '=',
|
||||
'/': '/',
|
||||
}[char] as string
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,4 +15,5 @@ export default class FlasherPlugin extends AbstractPlugin {
|
||||
}): void;
|
||||
private removeNotification;
|
||||
private stringToHTML;
|
||||
private escapeHtml;
|
||||
}
|
||||
|
||||
+24
-2
@@ -92,14 +92,15 @@ class FlasherPlugin extends AbstractPlugin {
|
||||
direction: 'top',
|
||||
rtl: false,
|
||||
style: {},
|
||||
escapeHtml: false,
|
||||
};
|
||||
this.theme = theme;
|
||||
}
|
||||
renderEnvelopes(envelopes) {
|
||||
const render = () => envelopes.forEach((envelope) => {
|
||||
var _a, _b, _c;
|
||||
var _a, _b, _c, _d;
|
||||
const typeTimeout = (_b = (_a = this.options.timeout) !== null && _a !== void 0 ? _a : this.options.timeouts[envelope.type]) !== null && _b !== void 0 ? _b : 5000;
|
||||
const options = Object.assign(Object.assign(Object.assign({}, this.options), envelope.options), { timeout: (_c = envelope.options.timeout) !== null && _c !== void 0 ? _c : typeTimeout });
|
||||
const options = Object.assign(Object.assign(Object.assign({}, this.options), envelope.options), { timeout: (_c = envelope.options.timeout) !== null && _c !== void 0 ? _c : typeTimeout, escapeHtml: ((_d = envelope.options.escapeHtml) !== null && _d !== void 0 ? _d : this.options.escapeHtml) });
|
||||
this.addToContainer(this.createContainer(options), envelope, options);
|
||||
});
|
||||
document.readyState === 'loading' ? document.addEventListener('DOMContentLoaded', render) : render();
|
||||
@@ -121,6 +122,10 @@ class FlasherPlugin extends AbstractPlugin {
|
||||
}
|
||||
addToContainer(container, envelope, options) {
|
||||
var _a;
|
||||
if (options.escapeHtml) {
|
||||
envelope.title = this.escapeHtml(envelope.title);
|
||||
envelope.message = this.escapeHtml(envelope.message);
|
||||
}
|
||||
const notification = this.stringToHTML(this.theme.render(envelope));
|
||||
notification.classList.add(...`fl-container${options.rtl ? ' fl-rtl' : ''}`.split(' '));
|
||||
options.direction === 'bottom' ? container.append(notification) : container.prepend(notification);
|
||||
@@ -170,6 +175,23 @@ class FlasherPlugin extends AbstractPlugin {
|
||||
template.innerHTML = str.trim();
|
||||
return template.content.firstElementChild;
|
||||
}
|
||||
escapeHtml(str) {
|
||||
if (str == null) {
|
||||
return '';
|
||||
}
|
||||
return str.replace(/[&<>"'`=\/]/g, (char) => {
|
||||
return {
|
||||
'&': '&',
|
||||
'<': '<',
|
||||
'>': '>',
|
||||
'"': '"',
|
||||
'\'': ''',
|
||||
'`': '`',
|
||||
'=': '=',
|
||||
'/': '/',
|
||||
}[char];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class Flasher extends AbstractPlugin {
|
||||
|
||||
Vendored
+24
-2
@@ -98,14 +98,15 @@
|
||||
direction: 'top',
|
||||
rtl: false,
|
||||
style: {},
|
||||
escapeHtml: false,
|
||||
};
|
||||
this.theme = theme;
|
||||
}
|
||||
renderEnvelopes(envelopes) {
|
||||
const render = () => envelopes.forEach((envelope) => {
|
||||
var _a, _b, _c;
|
||||
var _a, _b, _c, _d;
|
||||
const typeTimeout = (_b = (_a = this.options.timeout) !== null && _a !== void 0 ? _a : this.options.timeouts[envelope.type]) !== null && _b !== void 0 ? _b : 5000;
|
||||
const options = Object.assign(Object.assign(Object.assign({}, this.options), envelope.options), { timeout: (_c = envelope.options.timeout) !== null && _c !== void 0 ? _c : typeTimeout });
|
||||
const options = Object.assign(Object.assign(Object.assign({}, this.options), envelope.options), { timeout: (_c = envelope.options.timeout) !== null && _c !== void 0 ? _c : typeTimeout, escapeHtml: ((_d = envelope.options.escapeHtml) !== null && _d !== void 0 ? _d : this.options.escapeHtml) });
|
||||
this.addToContainer(this.createContainer(options), envelope, options);
|
||||
});
|
||||
document.readyState === 'loading' ? document.addEventListener('DOMContentLoaded', render) : render();
|
||||
@@ -127,6 +128,10 @@
|
||||
}
|
||||
addToContainer(container, envelope, options) {
|
||||
var _a;
|
||||
if (options.escapeHtml) {
|
||||
envelope.title = this.escapeHtml(envelope.title);
|
||||
envelope.message = this.escapeHtml(envelope.message);
|
||||
}
|
||||
const notification = this.stringToHTML(this.theme.render(envelope));
|
||||
notification.classList.add(...`fl-container${options.rtl ? ' fl-rtl' : ''}`.split(' '));
|
||||
options.direction === 'bottom' ? container.append(notification) : container.prepend(notification);
|
||||
@@ -176,6 +181,23 @@
|
||||
template.innerHTML = str.trim();
|
||||
return template.content.firstElementChild;
|
||||
}
|
||||
escapeHtml(str) {
|
||||
if (str == null) {
|
||||
return '';
|
||||
}
|
||||
return str.replace(/[&<>"'`=\/]/g, (char) => {
|
||||
return {
|
||||
'&': '&',
|
||||
'<': '<',
|
||||
'>': '>',
|
||||
'"': '"',
|
||||
'\'': ''',
|
||||
'`': '`',
|
||||
'=': '=',
|
||||
'/': '/',
|
||||
}[char];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class Flasher extends AbstractPlugin {
|
||||
|
||||
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user