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