feat(config): add option to disable custom html functionality (#26956)

This commit is contained in:
Liam DeBeasi
2023-03-22 13:59:59 -04:00
committed by GitHub
parent 6c639ff3a5
commit 3b0af7c55d
12 changed files with 351 additions and 28 deletions

View File

@ -5,6 +5,7 @@ import { arrowDown, caretBackSharp } from 'ionicons/icons';
import { config } from '../../global/config';
import { getIonMode } from '../../global/ionic-global';
import type { SpinnerTypes } from '../../interface';
import { ENABLE_HTML_CONTENT_DEFAULT } from '../../utils/config';
import { isPlatform } from '../../utils/platform';
import type { IonicSafeString } from '../../utils/sanitization';
import { sanitizeDOMString } from '../../utils/sanitization';
@ -14,6 +15,8 @@ import { SPINNERS } from '../spinner/spinner-configs';
tag: 'ion-refresher-content',
})
export class RefresherContent implements ComponentInterface {
private customHTMLEnabled = config.get('innerHTMLTemplatesEnabled', ENABLE_HTML_CONTENT_DEFAULT);
@Element() el!: HTMLIonRefresherContentElement;
/**
@ -31,6 +34,11 @@ export class RefresherContent implements ComponentInterface {
* `<Ionic>`
*
* For more information: [Security Documentation](https://ionicframework.com/docs/faq/security)
*
* This property accepts custom HTML as a string.
* Developers who only want to pass plain text
* can disable the custom HTML functionality
* by setting `innerHTMLTemplatesEnabled: false` in the Ionic config.
*/
@Prop() pullingText?: string | IonicSafeString;
@ -47,6 +55,11 @@ export class RefresherContent implements ComponentInterface {
* `<Ionic>`
*
* For more information: [Security Documentation](https://ionicframework.com/docs/faq/security)
*
* This property accepts custom HTML as a string.
* Developers who only want to pass plain text
* can disable the custom HTML functionality
* by setting `innerHTMLTemplatesEnabled: false` in the Ionic config.
*/
@Prop() refreshingText?: string | IonicSafeString;
@ -68,6 +81,24 @@ export class RefresherContent implements ComponentInterface {
}
}
private renderPullingText() {
const { customHTMLEnabled, pullingText } = this;
if (customHTMLEnabled) {
return <div class="refresher-pulling-text" innerHTML={sanitizeDOMString(pullingText)}></div>;
}
return <div class="refresher-pulling-text">{pullingText}</div>;
}
private renderRefreshingText() {
const { customHTMLEnabled, refreshingText } = this;
if (customHTMLEnabled) {
return <div class="refresher-refreshing-text" innerHTML={sanitizeDOMString(refreshingText)}></div>;
}
return <div class="refresher-refreshing-text">{refreshingText}</div>;
}
render() {
const pullingIcon = this.pullingIcon;
const hasSpinner = pullingIcon != null && (SPINNERS[pullingIcon] as any) !== undefined;
@ -93,9 +124,7 @@ export class RefresherContent implements ComponentInterface {
<ion-icon icon={this.pullingIcon} lazy={false}></ion-icon>
</div>
)}
{this.pullingText !== undefined && (
<div class="refresher-pulling-text" innerHTML={sanitizeDOMString(this.pullingText)}></div>
)}
{this.pullingText !== undefined && this.renderPullingText()}
</div>
<div class="refresher-refreshing">
{this.refreshingSpinner && (
@ -103,9 +132,7 @@ export class RefresherContent implements ComponentInterface {
<ion-spinner name={this.refreshingSpinner}></ion-spinner>
</div>
)}
{this.refreshingText !== undefined && (
<div class="refresher-refreshing-text" innerHTML={sanitizeDOMString(this.refreshingText)}></div>
)}
{this.refreshingText !== undefined && this.renderRefreshingText()}
</div>
</Host>
);

View File

@ -0,0 +1,52 @@
import { newSpecPage } from '@stencil/core/testing';
import { RefresherContent } from '../refresher-content';
import { config } from '../../../global/config';
describe('refresher-content: custom html', () => {
it('should allow for custom html by default', async () => {
const page = await newSpecPage({
components: [RefresherContent],
html: `<ion-refresher-content pulling-text="<button class='custom-pulling-html'>Custom Pulling Text</button>" refreshing-text="<button class='custom-refreshing-html'>Custom Refreshing Text</button>"></ion-refresher-content>`,
});
const pullingContent = page.body.querySelector('.refresher-pulling-text');
expect(pullingContent.textContent).toContain('Custom Pulling Text');
expect(pullingContent.querySelector('button.custom-pulling-html')).not.toBe(null);
const refreshingContent = page.body.querySelector('.refresher-refreshing-text');
expect(refreshingContent.textContent).toContain('Custom Refreshing Text');
expect(refreshingContent.querySelector('button.custom-refreshing-html')).not.toBe(null);
});
it('should allow for custom html', async () => {
config.reset({ innerHTMLTemplatesEnabled: true });
const page = await newSpecPage({
components: [RefresherContent],
html: `<ion-refresher-content pulling-text="<button class='custom-pulling-html'>Custom Pulling Text</button>" refreshing-text="<button class='custom-refreshing-html'>Custom Refreshing Text</button>"></ion-refresher-content>`,
});
const pullingContent = page.body.querySelector('.refresher-pulling-text');
expect(pullingContent.textContent).toContain('Custom Pulling Text');
expect(pullingContent.querySelector('button.custom-pulling-html')).not.toBe(null);
const refreshingContent = page.body.querySelector('.refresher-refreshing-text');
expect(refreshingContent.textContent).toContain('Custom Refreshing Text');
expect(refreshingContent.querySelector('button.custom-refreshing-html')).not.toBe(null);
});
it('should not allow for custom html', async () => {
config.reset({ innerHTMLTemplatesEnabled: false });
const page = await newSpecPage({
components: [RefresherContent],
html: `<ion-refresher-content pulling-text="<button class='custom-pulling-html'>Custom Pulling Text</button>" refreshing-text="<button class='custom-html'>Custom Refreshing Text</button>"></ion-refresher-content>`,
});
const pullingContent = page.body.querySelector('.refresher-pulling-text');
expect(pullingContent.textContent).toContain('Custom Pulling Text');
expect(pullingContent.querySelector('button.custom-pulling-html')).toBe(null);
const refreshingContent = page.body.querySelector('.refresher-refreshing-text');
expect(refreshingContent.textContent).toContain('Custom Refreshing Text');
expect(refreshingContent.querySelector('button.custom-refreshing-html')).toBe(null);
});
});