diff --git a/angular/src/index.ts b/angular/src/index.ts index 7ba346de35..46de9c0012 100644 --- a/angular/src/index.ts +++ b/angular/src/index.ts @@ -39,5 +39,8 @@ export { IonicRouteStrategy } from './util/ionic-router-reuse-strategy'; // PACKAGE MODULE export { IonicModule } from './ionic-module'; +// UTILS +export { IonicSafeString } from '@ionic/core'; + // CORE TYPES export { Animation, AnimationBuilder, AnimationCallbackOptions, AnimationDirection, AnimationFill, AnimationKeyFrames, AnimationLifecycle, Gesture, GestureConfig, GestureDetail, mdTransitionAnimation, iosTransitionAnimation } from '@ionic/core'; diff --git a/core/api.txt b/core/api.txt index 5be77e4e01..2b129bd100 100644 --- a/core/api.txt +++ b/core/api.txt @@ -53,7 +53,7 @@ ion-alert,prop,header,string | undefined,undefined,false,false ion-alert,prop,inputs,AlertInput[],[],false,false ion-alert,prop,keyboardClose,boolean,true,false,false ion-alert,prop,leaveAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false -ion-alert,prop,message,string | undefined,undefined,false,false +ion-alert,prop,message,IonicSafeString | string | undefined,undefined,false,false ion-alert,prop,mode,"ios" | "md",undefined,false,false ion-alert,prop,subHeader,string | undefined,undefined,false,false ion-alert,prop,translucent,boolean,false,false,false @@ -433,7 +433,7 @@ ion-infinite-scroll,event,ionInfinite,void,true ion-infinite-scroll-content,none ion-infinite-scroll-content,prop,loadingSpinner,"bubbles" | "circles" | "circular" | "crescent" | "dots" | "lines" | "lines-small" | null | undefined,undefined,false,false -ion-infinite-scroll-content,prop,loadingText,string | undefined,undefined,false,false +ion-infinite-scroll-content,prop,loadingText,IonicSafeString | string | undefined,undefined,false,false ion-input,scoped ion-input,prop,accept,string | undefined,undefined,false,false @@ -606,7 +606,7 @@ ion-loading,prop,duration,number,0,false,false ion-loading,prop,enterAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false ion-loading,prop,keyboardClose,boolean,true,false,false ion-loading,prop,leaveAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false -ion-loading,prop,message,string | undefined,undefined,false,false +ion-loading,prop,message,IonicSafeString | string | undefined,undefined,false,false ion-loading,prop,mode,"ios" | "md",undefined,false,false ion-loading,prop,showBackdrop,boolean,true,false,false ion-loading,prop,spinner,"bubbles" | "circles" | "circular" | "crescent" | "dots" | "lines" | "lines-small" | null | undefined,undefined,false,false @@ -896,9 +896,9 @@ ion-refresher,event,ionStart,void,true ion-refresher-content,none ion-refresher-content,prop,pullingIcon,null | string | undefined,undefined,false,false -ion-refresher-content,prop,pullingText,string | undefined,undefined,false,false +ion-refresher-content,prop,pullingText,IonicSafeString | string | undefined,undefined,false,false ion-refresher-content,prop,refreshingSpinner,"bubbles" | "circles" | "circular" | "crescent" | "dots" | "lines" | "lines-small" | null | undefined,undefined,false,false -ion-refresher-content,prop,refreshingText,string | undefined,undefined,false,false +ion-refresher-content,prop,refreshingText,IonicSafeString | string | undefined,undefined,false,false ion-reorder,shadow ion-reorder,part,icon @@ -1237,7 +1237,7 @@ ion-toast,prop,enterAnimation,((baseEl: any, opts?: any) => Animation) | undefin ion-toast,prop,header,string | undefined,undefined,false,false ion-toast,prop,keyboardClose,boolean,false,false,false ion-toast,prop,leaveAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false -ion-toast,prop,message,string | undefined,undefined,false,false +ion-toast,prop,message,IonicSafeString | string | undefined,undefined,false,false ion-toast,prop,mode,"ios" | "md",undefined,false,false ion-toast,prop,position,"bottom" | "middle" | "top",'bottom',false,false ion-toast,prop,translucent,boolean,false,false,false diff --git a/core/src/components.d.ts b/core/src/components.d.ts index b87b66bea6..ecf81d8edd 100644 --- a/core/src/components.d.ts +++ b/core/src/components.d.ts @@ -6,6 +6,7 @@ */ import { HTMLStencilElement, JSXBase } from "@stencil/core/internal"; import { ActionSheetButton, AlertButton, AlertInput, AnimationBuilder, CheckboxChangeEventDetail, Color, ComponentProps, ComponentRef, DatetimeChangeEventDetail, DatetimeOptions, DomRenderFn, FooterHeightFn, FrameworkDelegate, HeaderFn, HeaderHeightFn, InputChangeEventDetail, ItemHeightFn, ItemRenderFn, ItemReorderEventDetail, MenuChangeEventDetail, NavComponent, NavOptions, OverlayEventDetail, PickerButton, PickerColumn, RadioGroupChangeEventDetail, RangeChangeEventDetail, RangeValue, RefresherEventDetail, RouteID, RouterDirection, RouterEventDetail, RouterOutletOptions, RouteWrite, ScrollBaseDetail, ScrollDetail, SearchbarChangeEventDetail, SegmentButtonLayout, SegmentChangeEventDetail, SelectChangeEventDetail, SelectInterface, SelectPopoverOption, Side, SpinnerTypes, StyleEventDetail, SwipeGestureHandler, TabBarChangedEventDetail, TabButtonClickEventDetail, TabButtonLayout, TextareaChangeEventDetail, TextFieldTypes, ToastButton, ToggleChangeEventDetail, TransitionDoneFn, TransitionInstruction, ViewController, } from "./interface"; +import { IonicSafeString, } from "."; import { SelectCompareFn, } from "./components/select/select-interface"; export namespace Components { interface IonActionSheet { @@ -119,7 +120,7 @@ export namespace Components { /** * The main message to be displayed in the alert. `message` can accept either plaintext or HTML as a string. To display characters normally reserved for HTML, they must be escaped. For example `` would become `<Ionic>` For more information: [Security Documentation](https://ionicframework.com/docs/faq/security) */ - "message"?: string; + "message"?: string | IonicSafeString; /** * The mode determines which platform styles to use. */ @@ -800,7 +801,7 @@ export namespace Components { /** * Optional text to display while loading. `loadingText` can accept either plaintext or HTML as a string. To display characters normally reserved for HTML, they must be escaped. For example `` would become `<Ionic>` For more information: [Security Documentation](https://ionicframework.com/docs/faq/security) */ - "loadingText"?: string; + "loadingText"?: string | IonicSafeString; } interface IonInput { /** @@ -1150,7 +1151,7 @@ export namespace Components { /** * Optional text content to display in the loading indicator. */ - "message"?: string; + "message"?: string | IonicSafeString; /** * The mode determines which platform styles to use. */ @@ -1780,7 +1781,7 @@ export namespace Components { /** * The text you want to display when you begin to pull down. `pullingText` can accept either plaintext or HTML as a string. To display characters normally reserved for HTML, they must be escaped. For example `` would become `<Ionic>` For more information: [Security Documentation](https://ionicframework.com/docs/faq/security) */ - "pullingText"?: string; + "pullingText"?: string | IonicSafeString; /** * An animated SVG spinner that shows when refreshing begins */ @@ -1788,7 +1789,7 @@ export namespace Components { /** * The text you want to display when performing a refresh. `refreshingText` can accept either plaintext or HTML as a string. To display characters normally reserved for HTML, they must be escaped. For example `` would become `<Ionic>` For more information: [Security Documentation](https://ionicframework.com/docs/faq/security) */ - "refreshingText"?: string; + "refreshingText"?: string | IonicSafeString; } interface IonReorder { } @@ -2501,7 +2502,7 @@ export namespace Components { /** * Message to be shown in the toast. */ - "message"?: string; + "message"?: string | IonicSafeString; /** * The mode determines which platform styles to use. */ @@ -3348,7 +3349,7 @@ declare namespace LocalJSX { /** * The main message to be displayed in the alert. `message` can accept either plaintext or HTML as a string. To display characters normally reserved for HTML, they must be escaped. For example `` would become `<Ionic>` For more information: [Security Documentation](https://ionicframework.com/docs/faq/security) */ - "message"?: string; + "message"?: string | IonicSafeString; /** * The mode determines which platform styles to use. */ @@ -4068,7 +4069,7 @@ declare namespace LocalJSX { /** * Optional text to display while loading. `loadingText` can accept either plaintext or HTML as a string. To display characters normally reserved for HTML, they must be escaped. For example `` would become `<Ionic>` For more information: [Security Documentation](https://ionicframework.com/docs/faq/security) */ - "loadingText"?: string; + "loadingText"?: string | IonicSafeString; } interface IonInput { /** @@ -4402,7 +4403,7 @@ declare namespace LocalJSX { /** * Optional text content to display in the loading indicator. */ - "message"?: string; + "message"?: string | IonicSafeString; /** * The mode determines which platform styles to use. */ @@ -4954,7 +4955,7 @@ declare namespace LocalJSX { /** * The text you want to display when you begin to pull down. `pullingText` can accept either plaintext or HTML as a string. To display characters normally reserved for HTML, they must be escaped. For example `` would become `<Ionic>` For more information: [Security Documentation](https://ionicframework.com/docs/faq/security) */ - "pullingText"?: string; + "pullingText"?: string | IonicSafeString; /** * An animated SVG spinner that shows when refreshing begins */ @@ -4962,7 +4963,7 @@ declare namespace LocalJSX { /** * The text you want to display when performing a refresh. `refreshingText` can accept either plaintext or HTML as a string. To display characters normally reserved for HTML, they must be escaped. For example `` would become `<Ionic>` For more information: [Security Documentation](https://ionicframework.com/docs/faq/security) */ - "refreshingText"?: string; + "refreshingText"?: string | IonicSafeString; } interface IonReorder { } @@ -5684,7 +5685,7 @@ declare namespace LocalJSX { /** * Message to be shown in the toast. */ - "message"?: string; + "message"?: string | IonicSafeString; /** * The mode determines which platform styles to use. */ diff --git a/core/src/components/alert/alert-interface.ts b/core/src/components/alert/alert-interface.ts index cee6826020..21f33c0dcb 100644 --- a/core/src/components/alert/alert-interface.ts +++ b/core/src/components/alert/alert-interface.ts @@ -1,9 +1,10 @@ +import { IonicSafeString } from '../../'; import { AnimationBuilder, Mode, TextFieldTypes } from '../../interface'; export interface AlertOptions { header?: string; subHeader?: string; - message?: string; + message?: string | IonicSafeString; cssClass?: string | string[]; inputs?: AlertInput[]; buttons?: (AlertButton | string)[]; diff --git a/core/src/components/alert/alert.tsx b/core/src/components/alert/alert.tsx index 193b4b7749..8476b02c75 100644 --- a/core/src/components/alert/alert.tsx +++ b/core/src/components/alert/alert.tsx @@ -1,5 +1,6 @@ import { Component, ComponentInterface, Element, Event, EventEmitter, Host, Method, Prop, Watch, forceUpdate, h } from '@stencil/core'; +import { IonicSafeString } from '../../'; import { getIonMode } from '../../global/ionic-global'; import { AlertButton, AlertInput, AnimationBuilder, CssClassMap, OverlayEventDetail, OverlayInterface } from '../../interface'; import { BACKDROP, dismiss, eventMethod, isCancel, prepareOverlay, present, safeCall } from '../../utils/overlays'; @@ -76,7 +77,7 @@ export class Alert implements ComponentInterface, OverlayInterface { * * For more information: [Security Documentation](https://ionicframework.com/docs/faq/security) */ - @Prop() message?: string; + @Prop() message?: string | IonicSafeString; /** * Array of buttons to be added to the alert. diff --git a/core/src/components/alert/readme.md b/core/src/components/alert/readme.md index aab76aff70..b86b6fe5ab 100644 --- a/core/src/components/alert/readme.md +++ b/core/src/components/alert/readme.md @@ -1044,7 +1044,7 @@ export default { | `inputs` | -- | Array of input to show in the alert. | `AlertInput[]` | `[]` | | `keyboardClose` | `keyboard-close` | If `true`, the keyboard will be automatically dismissed when the overlay is presented. | `boolean` | `true` | | `leaveAnimation` | -- | Animation to use when the alert is dismissed. | `((baseEl: any, opts?: any) => Animation) \| undefined` | `undefined` | -| `message` | `message` | The main message to be displayed in the alert. `message` can accept either plaintext or HTML as a string. To display characters normally reserved for HTML, they must be escaped. For example `` would become `<Ionic>` For more information: [Security Documentation](https://ionicframework.com/docs/faq/security) | `string \| undefined` | `undefined` | +| `message` | `message` | The main message to be displayed in the alert. `message` can accept either plaintext or HTML as a string. To display characters normally reserved for HTML, they must be escaped. For example `` would become `<Ionic>` For more information: [Security Documentation](https://ionicframework.com/docs/faq/security) | `IonicSafeString \| string \| undefined` | `undefined` | | `mode` | `mode` | The mode determines which platform styles to use. | `"ios" \| "md"` | `undefined` | | `subHeader` | `sub-header` | The subtitle in the heading of the alert. Displayed under the title. | `string \| undefined` | `undefined` | | `translucent` | `translucent` | If `true`, the alert will be translucent. Only applies when the mode is `"ios"` and the device supports [`backdrop-filter`](https://developer.mozilla.org/en-US/docs/Web/CSS/backdrop-filter#Browser_compatibility). | `boolean` | `false` | diff --git a/core/src/components/infinite-scroll-content/infinite-scroll-content.tsx b/core/src/components/infinite-scroll-content/infinite-scroll-content.tsx index 14c526d595..098836b4c7 100644 --- a/core/src/components/infinite-scroll-content/infinite-scroll-content.tsx +++ b/core/src/components/infinite-scroll-content/infinite-scroll-content.tsx @@ -1,5 +1,6 @@ import { Component, ComponentInterface, Host, Prop, h } from '@stencil/core'; +import { IonicSafeString } from '../../'; import { config } from '../../global/config'; import { getIonMode } from '../../global/ionic-global'; import { SpinnerTypes } from '../../interface'; @@ -28,7 +29,7 @@ export class InfiniteScrollContent implements ComponentInterface { * * For more information: [Security Documentation](https://ionicframework.com/docs/faq/security) */ - @Prop() loadingText?: string; + @Prop() loadingText?: string | IonicSafeString; componentDidLoad() { if (this.loadingSpinner === undefined) { diff --git a/core/src/components/infinite-scroll-content/readme.md b/core/src/components/infinite-scroll-content/readme.md index ee3ca1caf6..96dcbf08a0 100644 --- a/core/src/components/infinite-scroll-content/readme.md +++ b/core/src/components/infinite-scroll-content/readme.md @@ -61,7 +61,7 @@ The `ion-infinite-scroll-content` component is not supported in React. | Property | Attribute | Description | Type | Default | | ---------------- | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- | ----------- | | `loadingSpinner` | `loading-spinner` | An animated SVG spinner that shows while loading. | `"bubbles" \| "circles" \| "circular" \| "crescent" \| "dots" \| "lines" \| "lines-small" \| null \| undefined` | `undefined` | -| `loadingText` | `loading-text` | Optional text to display while loading. `loadingText` can accept either plaintext or HTML as a string. To display characters normally reserved for HTML, they must be escaped. For example `` would become `<Ionic>` For more information: [Security Documentation](https://ionicframework.com/docs/faq/security) | `string \| undefined` | `undefined` | +| `loadingText` | `loading-text` | Optional text to display while loading. `loadingText` can accept either plaintext or HTML as a string. To display characters normally reserved for HTML, they must be escaped. For example `` would become `<Ionic>` For more information: [Security Documentation](https://ionicframework.com/docs/faq/security) | `IonicSafeString \| string \| undefined` | `undefined` | ## Dependencies diff --git a/core/src/components/loading/loading-interface.ts b/core/src/components/loading/loading-interface.ts index 80a6d59582..9719895b5b 100644 --- a/core/src/components/loading/loading-interface.ts +++ b/core/src/components/loading/loading-interface.ts @@ -1,8 +1,9 @@ +import { IonicSafeString } from '../../'; import { AnimationBuilder, Mode, SpinnerTypes } from '../../interface'; export interface LoadingOptions { spinner?: SpinnerTypes | null; - message?: string; + message?: string | IonicSafeString; cssClass?: string | string[]; showBackdrop?: boolean; duration?: number; diff --git a/core/src/components/loading/loading.tsx b/core/src/components/loading/loading.tsx index ef312e6816..9e1f799210 100644 --- a/core/src/components/loading/loading.tsx +++ b/core/src/components/loading/loading.tsx @@ -1,5 +1,6 @@ import { Component, ComponentInterface, Element, Event, EventEmitter, Host, Method, Prop, h } from '@stencil/core'; +import { IonicSafeString } from '../../'; import { config } from '../../global/config'; import { getIonMode } from '../../global/ionic-global'; import { AnimationBuilder, OverlayEventDetail, OverlayInterface, SpinnerTypes } from '../../interface'; @@ -51,7 +52,7 @@ export class Loading implements ComponentInterface, OverlayInterface { /** * Optional text content to display in the loading indicator. */ - @Prop() message?: string; + @Prop() message?: string | IonicSafeString; /** * Additional classes to apply for custom CSS. If multiple classes are diff --git a/core/src/components/loading/readme.md b/core/src/components/loading/readme.md index 2b0e6ea173..98f4fe7b4b 100644 --- a/core/src/components/loading/readme.md +++ b/core/src/components/loading/readme.md @@ -182,7 +182,7 @@ export default { | `enterAnimation` | -- | Animation to use when the loading indicator is presented. | `((baseEl: any, opts?: any) => Animation) \| undefined` | `undefined` | | `keyboardClose` | `keyboard-close` | If `true`, the keyboard will be automatically dismissed when the overlay is presented. | `boolean` | `true` | | `leaveAnimation` | -- | Animation to use when the loading indicator is dismissed. | `((baseEl: any, opts?: any) => Animation) \| undefined` | `undefined` | -| `message` | `message` | Optional text content to display in the loading indicator. | `string \| undefined` | `undefined` | +| `message` | `message` | Optional text content to display in the loading indicator. | `IonicSafeString \| string \| undefined` | `undefined` | | `mode` | `mode` | The mode determines which platform styles to use. | `"ios" \| "md"` | `undefined` | | `showBackdrop` | `show-backdrop` | If `true`, a backdrop will be displayed behind the loading indicator. | `boolean` | `true` | | `spinner` | `spinner` | The name of the spinner to display. | `"bubbles" \| "circles" \| "circular" \| "crescent" \| "dots" \| "lines" \| "lines-small" \| null \| undefined` | `undefined` | diff --git a/core/src/components/refresher-content/readme.md b/core/src/components/refresher-content/readme.md index f4536f9fa6..1bc410ffb6 100644 --- a/core/src/components/refresher-content/readme.md +++ b/core/src/components/refresher-content/readme.md @@ -12,9 +12,9 @@ The refresher content contains the text, icon and spinner to display during a pu | Property | Attribute | Description | Type | Default | | ------------------- | -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- | ----------- | | `pullingIcon` | `pulling-icon` | A static icon or a spinner to display when you begin to pull down. A spinner name can be provided to gradually show tick marks when pulling down on iOS devices. | `null \| string \| undefined` | `undefined` | -| `pullingText` | `pulling-text` | The text you want to display when you begin to pull down. `pullingText` can accept either plaintext or HTML as a string. To display characters normally reserved for HTML, they must be escaped. For example `` would become `<Ionic>` For more information: [Security Documentation](https://ionicframework.com/docs/faq/security) | `string \| undefined` | `undefined` | +| `pullingText` | `pulling-text` | The text you want to display when you begin to pull down. `pullingText` can accept either plaintext or HTML as a string. To display characters normally reserved for HTML, they must be escaped. For example `` would become `<Ionic>` For more information: [Security Documentation](https://ionicframework.com/docs/faq/security) | `IonicSafeString \| string \| undefined` | `undefined` | | `refreshingSpinner` | `refreshing-spinner` | An animated SVG spinner that shows when refreshing begins | `"bubbles" \| "circles" \| "circular" \| "crescent" \| "dots" \| "lines" \| "lines-small" \| null \| undefined` | `undefined` | -| `refreshingText` | `refreshing-text` | The text you want to display when performing a refresh. `refreshingText` can accept either plaintext or HTML as a string. To display characters normally reserved for HTML, they must be escaped. For example `` would become `<Ionic>` For more information: [Security Documentation](https://ionicframework.com/docs/faq/security) | `string \| undefined` | `undefined` | +| `refreshingText` | `refreshing-text` | The text you want to display when performing a refresh. `refreshingText` can accept either plaintext or HTML as a string. To display characters normally reserved for HTML, they must be escaped. For example `` would become `<Ionic>` For more information: [Security Documentation](https://ionicframework.com/docs/faq/security) | `IonicSafeString \| string \| undefined` | `undefined` | ## Dependencies diff --git a/core/src/components/refresher-content/refresher-content.tsx b/core/src/components/refresher-content/refresher-content.tsx index a42466c696..002a59d3a1 100644 --- a/core/src/components/refresher-content/refresher-content.tsx +++ b/core/src/components/refresher-content/refresher-content.tsx @@ -1,5 +1,6 @@ import { Component, ComponentInterface, Element, Host, Prop, h } from '@stencil/core'; +import { IonicSafeString } from '../../'; import { config } from '../../global/config'; import { getIonMode } from '../../global/ionic-global'; import { SpinnerTypes } from '../../interface'; @@ -30,7 +31,7 @@ export class RefresherContent implements ComponentInterface { * * For more information: [Security Documentation](https://ionicframework.com/docs/faq/security) */ - @Prop() pullingText?: string; + @Prop() pullingText?: string | IonicSafeString; /** * An animated SVG spinner that shows when refreshing begins @@ -46,7 +47,7 @@ export class RefresherContent implements ComponentInterface { * * For more information: [Security Documentation](https://ionicframework.com/docs/faq/security) */ - @Prop() refreshingText?: string; + @Prop() refreshingText?: string | IonicSafeString; componentWillLoad() { if (this.pullingIcon === undefined) { diff --git a/core/src/components/toast/readme.md b/core/src/components/toast/readme.md index 4a697a1d78..8dff3cb405 100644 --- a/core/src/components/toast/readme.md +++ b/core/src/components/toast/readme.md @@ -172,7 +172,7 @@ export const ToastExample: React.FC = () => { | `header` | `header` | Header to be shown in the toast. | `string \| undefined` | `undefined` | | `keyboardClose` | `keyboard-close` | If `true`, the keyboard will be automatically dismissed when the overlay is presented. | `boolean` | `false` | | `leaveAnimation` | -- | Animation to use when the toast is dismissed. | `((baseEl: any, opts?: any) => Animation) \| undefined` | `undefined` | -| `message` | `message` | Message to be shown in the toast. | `string \| undefined` | `undefined` | +| `message` | `message` | Message to be shown in the toast. | `IonicSafeString \| string \| undefined` | `undefined` | | `mode` | `mode` | The mode determines which platform styles to use. | `"ios" \| "md"` | `undefined` | | `position` | `position` | The position of the toast on the screen. | `"bottom" \| "middle" \| "top"` | `'bottom'` | | `translucent` | `translucent` | If `true`, the toast will be translucent. Only applies when the mode is `"ios"` and the device supports [`backdrop-filter`](https://developer.mozilla.org/en-US/docs/Web/CSS/backdrop-filter#Browser_compatibility). | `boolean` | `false` | diff --git a/core/src/components/toast/toast-interface.ts b/core/src/components/toast/toast-interface.ts index ba2ad7c33e..0d8f1a828a 100644 --- a/core/src/components/toast/toast-interface.ts +++ b/core/src/components/toast/toast-interface.ts @@ -1,8 +1,9 @@ +import { IonicSafeString } from '../../'; import { AnimationBuilder, Color, Mode } from '../../interface'; export interface ToastOptions { header?: string; - message?: string; + message?: string | IonicSafeString; cssClass?: string | string[]; duration?: number; buttons?: (ToastButton | string)[]; diff --git a/core/src/components/toast/toast.tsx b/core/src/components/toast/toast.tsx index 0d716d5295..a395c34465 100644 --- a/core/src/components/toast/toast.tsx +++ b/core/src/components/toast/toast.tsx @@ -1,5 +1,6 @@ import { Component, ComponentInterface, Element, Event, EventEmitter, Host, Method, Prop, h } from '@stencil/core'; +import { IonicSafeString } from '../../'; import { getIonMode } from '../../global/ionic-global'; import { AnimationBuilder, Color, CssClassMap, OverlayEventDetail, OverlayInterface, ToastButton } from '../../interface'; import { dismiss, eventMethod, isCancel, prepareOverlay, present, safeCall } from '../../utils/overlays'; @@ -72,7 +73,7 @@ export class Toast implements ComponentInterface, OverlayInterface { /** * Message to be shown in the toast. */ - @Prop() message?: string; + @Prop() message?: string | IonicSafeString; /** * If `true`, the keyboard will be automatically dismissed when the overlay is presented. diff --git a/core/src/index.ts b/core/src/index.ts index 235b76ff23..fecad054b2 100644 --- a/core/src/index.ts +++ b/core/src/index.ts @@ -6,6 +6,7 @@ export { mdTransitionAnimation } from './utils/transition/md.transition'; export { getTimeGivenProgression } from './utils/animation/cubic-bezier'; export { createGesture } from './utils/gesture'; export { isPlatform, Platforms, getPlatforms } from './utils/platform'; +export { IonicSafeString } from './utils/sanitization'; export * from './utils/config'; export * from './components/nav/constants'; diff --git a/core/src/utils/config.ts b/core/src/utils/config.ts index f89d5a6661..c6c476889f 100644 --- a/core/src/utils/config.ts +++ b/core/src/utils/config.ts @@ -175,6 +175,11 @@ export interface IonicConfig { */ experimentalTransitionShadow?: boolean; + /** + * If `true`, Ionic will enable a basic DOM sanitizer on component properties that accept custom HTML. + */ + sanitizerEnabled?: boolean; + // PRIVATE configs keyboardHeight?: number; inputShims?: boolean; diff --git a/core/src/utils/sanitization/index.ts b/core/src/utils/sanitization/index.ts index 73a5d415af..ce0dc5013e 100644 --- a/core/src/utils/sanitization/index.ts +++ b/core/src/utils/sanitization/index.ts @@ -3,9 +3,10 @@ * in an untrusted string */ -export const sanitizeDOMString = (untrustedString: string | undefined): string | undefined => { +export const sanitizeDOMString = (untrustedString: IonicSafeString | string | undefined): string | undefined => { try { - if (typeof untrustedString !== 'string' || untrustedString === '') { return untrustedString; } + if (untrustedString instanceof IonicSafeString) { return untrustedString.value; } + if (!isSanitizerEnabled() || typeof untrustedString !== 'string' || untrustedString === '') { return untrustedString; } /** * Create a document fragment @@ -122,5 +123,22 @@ const getElementChildren = (el: any) => { return (el.children != null) ? el.children : el.childNodes; }; +const isSanitizerEnabled = (): boolean => { + const win = window as any; + const config = win && win.Ionic && win.Ionic.config; + if (config) { + if (config.get) { + return config.get('sanitizerEnabled', true); + } else { + return config.sanitizerEnabled === true || config.sanitizerEnabled === undefined; + } + } + return true; +}; + const allowedAttributes = ['class', 'id', 'href', 'src', 'name', 'slot']; const blockedTags = ['script', 'style', 'iframe', 'meta', 'link', 'object', 'embed']; + +export class IonicSafeString { + constructor(public value: string) {} +} diff --git a/core/src/utils/sanitization/test/sanitization.spec.ts b/core/src/utils/sanitization/test/sanitization.spec.ts index 83ee9a0586..30ba04523d 100644 --- a/core/src/utils/sanitization/test/sanitization.spec.ts +++ b/core/src/utils/sanitization/test/sanitization.spec.ts @@ -1,6 +1,16 @@ -import { sanitizeDOMString } from ".."; +import { IonicSafeString, sanitizeDOMString } from ".."; describe('sanitizeDOMString', () => { + it('disable sanitizer', () => { + enableSanitizer(false); + expect(sanitizeDOMString('')) + .toEqual(''); + }) + + it('bypass sanitizer', () => { + expect(sanitizeDOMString(new IonicSafeString(''))) + .toEqual(''); + }); it('filter onerror', () => { expect(sanitizeDOMString('')) @@ -41,4 +51,10 @@ describe('sanitizeDOMString', () => { expect(sanitizeDOMString('Hello!Click me')) .toEqual('Hello!Click me'); }); -}); \ No newline at end of file +}); + +const enableSanitizer = (enable: boolean = true) => { + window.Ionic = {}; + window.Ionic.config = {}; + window.Ionic.config.sanitizerEnabled = enable; +} diff --git a/packages/react/src/components/index.ts b/packages/react/src/components/index.ts index 4e172a6b89..7e8dd3069a 100644 --- a/packages/react/src/components/index.ts +++ b/packages/react/src/components/index.ts @@ -2,7 +2,7 @@ import { defineCustomElements } from '@ionic/core/loader'; import { addIcons } from 'ionicons'; import { arrowBackSharp, caretBackSharp, chevronBack, chevronForward, close, closeCircle, closeSharp, menuOutline, menuSharp, reorderThreeOutline, reorderTwoSharp, searchOutline, searchSharp } from 'ionicons/icons'; -export { createAnimation, createGesture, AlertButton, AlertInput, Gesture, GestureConfig, GestureDetail, mdTransitionAnimation, iosTransitionAnimation, setupConfig } from '@ionic/core'; +export { createAnimation, createGesture, AlertButton, AlertInput, Gesture, GestureConfig, GestureDetail, iosTransitionAnimation, IonicSafeString, mdTransitionAnimation, setupConfig } from '@ionic/core'; export * from './proxies'; // createControllerComponent