1/* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this file, 3 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5import { Localized } from "fluent-react"; 6import React from "react"; 7import { RICH_TEXT_KEYS } from "../../rich-text-strings"; 8import { safeURI } from "../../template-utils"; 9 10// Elements allowed in snippet content 11const ALLOWED_TAGS = { 12 b: <b />, 13 i: <i />, 14 u: <u />, 15 strong: <strong />, 16 em: <em />, 17 br: <br />, 18}; 19 20/** 21 * Transform an object (tag name: {url}) into (tag name: anchor) where the url 22 * is used as href, in order to render links inside a Fluent.Localized component. 23 */ 24export function convertLinks( 25 links, 26 sendClick, 27 doNotAutoBlock, 28 openNewWindow = false 29) { 30 if (links) { 31 return Object.keys(links).reduce((acc, linkTag) => { 32 const { action } = links[linkTag]; 33 // Setting the value to false will not include the attribute in the anchor 34 const url = action ? false : safeURI(links[linkTag].url); 35 36 acc[linkTag] = ( 37 // eslint was getting a false positive caused by the dynamic injection 38 // of content. 39 // eslint-disable-next-line jsx-a11y/anchor-has-content 40 <a 41 href={url} 42 target={openNewWindow ? "_blank" : ""} 43 data-metric={links[linkTag].metric} 44 data-action={action} 45 data-args={links[linkTag].args} 46 data-do_not_autoblock={doNotAutoBlock} 47 data-entrypoint_name={links[linkTag].entrypoint_name} 48 data-entrypoint_value={links[linkTag].entrypoint_value} 49 onClick={sendClick} 50 /> 51 ); 52 return acc; 53 }, {}); 54 } 55 56 return null; 57} 58 59/** 60 * Message wrapper used to sanitize markup and render HTML. 61 */ 62export function RichText(props) { 63 if (!RICH_TEXT_KEYS.includes(props.localization_id)) { 64 throw new Error( 65 `ASRouter: ${props.localization_id} is not a valid rich text property. If you want it to be processed, you need to add it to asrouter/rich-text-strings.js` 66 ); 67 } 68 return ( 69 <Localized 70 id={props.localization_id} 71 {...ALLOWED_TAGS} 72 {...props.customElements} 73 {...convertLinks( 74 props.links, 75 props.sendClick, 76 props.doNotAutoBlock, 77 props.openNewWindow 78 )} 79 > 80 <span>{props.text}</span> 81 </Localized> 82 ); 83} 84