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          rel="noreferrer"
50          onClick={sendClick}
51        />
52      );
53      return acc;
54    }, {});
55  }
56
57  return null;
58}
59
60/**
61 * Message wrapper used to sanitize markup and render HTML.
62 */
63export function RichText(props) {
64  if (!RICH_TEXT_KEYS.includes(props.localization_id)) {
65    throw new Error(
66      `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`
67    );
68  }
69  return (
70    <Localized
71      id={props.localization_id}
72      {...ALLOWED_TAGS}
73      {...props.customElements}
74      {...convertLinks(
75        props.links,
76        props.sendClick,
77        props.doNotAutoBlock,
78        props.openNewWindow
79      )}
80    >
81      <span>{props.text}</span>
82    </Localized>
83  );
84}
85