fix(many): innerHTML is disabled by default (#27029)

BREAKING CHANGE:

The `innerHTMLTemplatesEnabled` Ionic Config now defaults to `false`. Developers can set this option to `true` if they would like to continue to use custom HTML features in `ion-alert`, `ion-infinite-scroll-content`, `ion-loading`, `ion-refresher-content`, and `ion-toast`.
This commit is contained in:
Liam DeBeasi
2023-03-27 12:07:00 -04:00
committed by GitHub
parent b148384a13
commit b7e46038e0
10 changed files with 35 additions and 12 deletions

View File

@ -35,6 +35,7 @@ This is a comprehensive list of the breaking changes introduced in the major ver
- [Textarea](#version-7x-textarea) - [Textarea](#version-7x-textarea)
- [Toggle](#version-7x-toggle) - [Toggle](#version-7x-toggle)
- [Virtual Scroll](#version-7x-virtual-scroll) - [Virtual Scroll](#version-7x-virtual-scroll)
- [Config](#version-7x-config)
- [Types](#version-7x-types) - [Types](#version-7x-types)
- [Overlay Attribute Interfaces](#version-7x-overlay-attribute-interfaces) - [Overlay Attribute Interfaces](#version-7x-overlay-attribute-interfaces)
- [JavaScript Frameworks](#version-7x-javascript-frameworks) - [JavaScript Frameworks](#version-7x-javascript-frameworks)
@ -297,6 +298,10 @@ Developers using the component will need to migrate to a virtual scroll solution
Any references to the virtual scroll types from `@ionic/core` have been removed. Please remove or replace these types: `Cell`, `VirtualNode`, `CellType`, `NodeChange`, `HeaderFn`, `ItemHeightFn`, `FooterHeightFn`, `ItemRenderFn` and `DomRenderFn`. Any references to the virtual scroll types from `@ionic/core` have been removed. Please remove or replace these types: `Cell`, `VirtualNode`, `CellType`, `NodeChange`, `HeaderFn`, `ItemHeightFn`, `FooterHeightFn`, `ItemRenderFn` and `DomRenderFn`.
<h2 id="version-7x-config">Config</h2>
- `innerHTMLTemplatesEnabled` defaults to `false`. Developers who wish to use the `innerHTML` functionality inside of `ion-alert`, `ion-infinite-scroll-content`, `ion-loading`, `ion-refresher-content`, and `ion-toast` must set this config to `true` and properly sanitize their content.
<h2 id="version-7x-types">Types</h2> <h2 id="version-7x-types">Types</h2>
<h4 id="version-7x-overlay-attribute-interfaces">Overlay Attribute Interfaces</h4> <h4 id="version-7x-overlay-attribute-interfaces">Overlay Attribute Interfaces</h4>

View File

@ -3,7 +3,7 @@ import { Alert } from '../alert';
import { config } from '../../../global/config'; import { config } from '../../../global/config';
describe('alert: custom html', () => { describe('alert: custom html', () => {
it('should allow for custom html by default', async () => { it('should not allow for custom html by default', async () => {
const page = await newSpecPage({ const page = await newSpecPage({
components: [Alert], components: [Alert],
html: `<ion-alert message="<button class='custom-html'>Custom Text</button>"></ion-alert>`, html: `<ion-alert message="<button class='custom-html'>Custom Text</button>"></ion-alert>`,
@ -11,7 +11,7 @@ describe('alert: custom html', () => {
const content = page.body.querySelector('.alert-message'); const content = page.body.querySelector('.alert-message');
expect(content.textContent).toContain('Custom Text'); expect(content.textContent).toContain('Custom Text');
expect(content.querySelector('button.custom-html')).not.toBe(null); expect(content.querySelector('button.custom-html')).toBe(null);
}); });
it('should allow for custom html', async () => { it('should allow for custom html', async () => {

View File

@ -58,6 +58,12 @@
</ion-app> </ion-app>
<script> <script>
window.Ionic = {
config: {
innerHTMLTemplatesEnabled: true,
},
};
async function openAlert(opts) { async function openAlert(opts) {
const alert = await alertController.create(opts); const alert = await alertController.create(opts);
await alert.present(); await alert.present();

View File

@ -3,7 +3,7 @@ import { InfiniteScrollContent } from '../infinite-scroll-content';
import { config } from '../../../global/config'; import { config } from '../../../global/config';
describe('infinite-scroll-content: custom html', () => { describe('infinite-scroll-content: custom html', () => {
it('should allow for custom html by default', async () => { it('should not allow for custom html by default', async () => {
const page = await newSpecPage({ const page = await newSpecPage({
components: [InfiniteScrollContent], components: [InfiniteScrollContent],
html: `<ion-infinite-scroll-content loading-text="<button class='custom-html'>Custom Text</button>"></ion-infinite-scroll-content>`, html: `<ion-infinite-scroll-content loading-text="<button class='custom-html'>Custom Text</button>"></ion-infinite-scroll-content>`,
@ -11,7 +11,7 @@ describe('infinite-scroll-content: custom html', () => {
const content = page.body.querySelector('.infinite-loading-text'); const content = page.body.querySelector('.infinite-loading-text');
expect(content.textContent).toContain('Custom Text'); expect(content.textContent).toContain('Custom Text');
expect(content.querySelector('button.custom-html')).not.toBe(null); expect(content.querySelector('button.custom-html')).toBe(null);
}); });
it('should allow for custom html', async () => { it('should allow for custom html', async () => {

View File

@ -100,6 +100,12 @@
</ion-content> </ion-content>
</ion-app> </ion-app>
<script> <script>
window.Ionic = {
config: {
innerHTMLTemplatesEnabled: true,
},
};
async function openLoading(opts) { async function openLoading(opts) {
const loading = await loadingController.create(opts); const loading = await loadingController.create(opts);
await loading.present(); await loading.present();

View File

@ -3,7 +3,7 @@ import { Loading } from '../loading';
import { config } from '../../../global/config'; import { config } from '../../../global/config';
describe('alert: custom html', () => { describe('alert: custom html', () => {
it('should allow for custom html by default', async () => { it('should not allow for custom html by default', async () => {
const page = await newSpecPage({ const page = await newSpecPage({
components: [Loading], components: [Loading],
html: `<ion-loading message="<button class='custom-html'>Custom Text</button>"></ion-loading>`, html: `<ion-loading message="<button class='custom-html'>Custom Text</button>"></ion-loading>`,
@ -11,7 +11,7 @@ describe('alert: custom html', () => {
const content = page.body.querySelector('.loading-content'); const content = page.body.querySelector('.loading-content');
expect(content.textContent).toContain('Custom Text'); expect(content.textContent).toContain('Custom Text');
expect(content.querySelector('button.custom-html')).not.toBe(null); expect(content.querySelector('button.custom-html')).toBe(null);
}); });
it('should allow for custom html', async () => { it('should allow for custom html', async () => {

View File

@ -3,7 +3,7 @@ import { RefresherContent } from '../refresher-content';
import { config } from '../../../global/config'; import { config } from '../../../global/config';
describe('refresher-content: custom html', () => { describe('refresher-content: custom html', () => {
it('should allow for custom html by default', async () => { it('should not allow for custom html by default', async () => {
const page = await newSpecPage({ const page = await newSpecPage({
components: [RefresherContent], 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>`, 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>`,
@ -11,11 +11,11 @@ describe('refresher-content: custom html', () => {
const pullingContent = page.body.querySelector('.refresher-pulling-text'); const pullingContent = page.body.querySelector('.refresher-pulling-text');
expect(pullingContent.textContent).toContain('Custom Pulling Text'); expect(pullingContent.textContent).toContain('Custom Pulling Text');
expect(pullingContent.querySelector('button.custom-pulling-html')).not.toBe(null); expect(pullingContent.querySelector('button.custom-pulling-html')).toBe(null);
const refreshingContent = page.body.querySelector('.refresher-refreshing-text'); const refreshingContent = page.body.querySelector('.refresher-refreshing-text');
expect(refreshingContent.textContent).toContain('Custom Refreshing Text'); expect(refreshingContent.textContent).toContain('Custom Refreshing Text');
expect(refreshingContent.querySelector('button.custom-refreshing-html')).not.toBe(null); expect(refreshingContent.querySelector('button.custom-refreshing-html')).toBe(null);
}); });
it('should allow for custom html', async () => { it('should allow for custom html', async () => {

View File

@ -195,6 +195,12 @@
</ion-content> </ion-content>
</ion-app> </ion-app>
<script> <script>
window.Ionic = {
config: {
innerHTMLTemplatesEnabled: true,
},
};
window.addEventListener('ionToastDidDismiss', function (e) { window.addEventListener('ionToastDidDismiss', function (e) {
console.log('didDismiss', e); console.log('didDismiss', e);
}); });

View File

@ -3,7 +3,7 @@ import { Toast } from '../toast';
import { config } from '../../../global/config'; import { config } from '../../../global/config';
describe('alert: custom html', () => { describe('alert: custom html', () => {
it('should allow for custom html by default', async () => { it('should not allow for custom html by default', async () => {
const page = await newSpecPage({ const page = await newSpecPage({
components: [Toast], components: [Toast],
html: `<ion-toast message="<button class='custom-html'>Custom Text</button>"></ion-toast>`, html: `<ion-toast message="<button class='custom-html'>Custom Text</button>"></ion-toast>`,
@ -12,7 +12,7 @@ describe('alert: custom html', () => {
const toast = page.body.querySelector('ion-toast'); const toast = page.body.querySelector('ion-toast');
const content = toast.shadowRoot.querySelector('.toast-message'); const content = toast.shadowRoot.querySelector('.toast-message');
expect(content.textContent).toContain('Custom Text'); expect(content.textContent).toContain('Custom Text');
expect(content.querySelector('button.custom-html')).not.toBe(null); expect(content.querySelector('button.custom-html')).toBe(null);
}); });
it('should allow for custom html', async () => { it('should allow for custom html', async () => {

View File

@ -249,4 +249,4 @@ export const getMode = (): Mode => {
return 'md'; return 'md';
}; };
export const ENABLE_HTML_CONTENT_DEFAULT = true; export const ENABLE_HTML_CONTENT_DEFAULT = false;