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