@happeouikit/content-renderer 3.0.1 → 3.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # Changelog
2
2
 
3
+ ## 3.0.4
4
+
5
+ - [Fixed] ContentRenderer should now render content without applying links to domain-like text.
6
+ - [Updated] Updated ContentRenderer unit test with Testing Linkify hyper-link Features.
7
+
8
+ ## 3.0.3
9
+
10
+ - [Added] Added prop `forceDefaultLinkTarget` that will force external links with `target="_blank"` and removes `target` from internal links.
11
+
12
+ ## 3.0.2
13
+
14
+ - [Fixed] ContentRenderer now applies styling options from Pages
15
+
3
16
  ## 3.0.1
4
17
 
5
18
  - [Fixed] ContentRenderer should now deal with all kinds of xss
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@happeouikit/content-renderer",
3
- "version": "3.0.1",
3
+ "version": "3.0.4",
4
4
  "description": "Rendering html and markdown content",
5
5
  "main": "dist/index.js",
6
6
  "module": "src/index.js",
@@ -34,5 +34,6 @@
34
34
  },
35
35
  "publishConfig": {
36
36
  "access": "public"
37
- }
37
+ },
38
+ "gitHead": "592299ab27c858a3540e4614ce4c09dec84a6fcc"
38
39
  }
@@ -1,273 +0,0 @@
1
- import _taggedTemplateLiteral from "@babel/runtime/helpers/taggedTemplateLiteral";
2
- import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
3
- import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
4
-
5
- function _templateObject5() {
6
- var data = _taggedTemplateLiteral(["\n margin-top: 8px;\n "]);
7
-
8
- _templateObject5 = function _templateObject5() {
9
- return data;
10
- };
11
-
12
- return data;
13
- }
14
-
15
- function _templateObject4() {
16
- var data = _taggedTemplateLiteral(["\n margin: 30px -150px;\n width: calc(100% + 300px) !important;\n max-width: none;\n "]);
17
-
18
- _templateObject4 = function _templateObject4() {
19
- return data;
20
- };
21
-
22
- return data;
23
- }
24
-
25
- function _templateObject3() {
26
- var data = _taggedTemplateLiteral(["\n margin: 30px -150px 10px 30px;\n float: right;\n max-width: 75%;\n "]);
27
-
28
- _templateObject3 = function _templateObject3() {
29
- return data;
30
- };
31
-
32
- return data;
33
- }
34
-
35
- function _templateObject2() {
36
- var data = _taggedTemplateLiteral(["\n margin: 30px 30px 10px -150px;\n float: left;\n max-width: 75%;\n "]);
37
-
38
- _templateObject2 = function _templateObject2() {
39
- return data;
40
- };
41
-
42
- return data;
43
- }
44
-
45
- function _templateObject() {
46
- var data = _taggedTemplateLiteral([" \n max-width: 100%;\n "]);
47
-
48
- _templateObject = function _templateObject() {
49
- return data;
50
- };
51
-
52
- return data;
53
- }
54
-
55
- /* eslint-disable no-param-reassign */
56
-
57
- /**
58
- *
59
- * ContentRenderer
60
- *
61
- */
62
- import React, { useRef, useEffect, useState, useCallback, useMemo } from "react";
63
- import ReactDOM from "react-dom";
64
- import PropTypes from "prop-types";
65
- import styled, { css } from "styled-components";
66
- import loadjs from "loadjs";
67
- import { CopyToClipboardButton } from "@happeouikit/copy-to-clipboard-button";
68
- import { BodyUI, sansFamily } from "@happeouikit/typography";
69
- import { margin200, media, padding200 } from "@happeouikit/layout";
70
- import { active, gray04, gray07, gray09, lighten, warn } from "@happeouikit/colors";
71
- import { toHtml, loadCodeFont, decodeHtmlEntities, removeSpecialCharacters, toSafeText } from "./utils";
72
- import { ELEMENT_TYPE_PRE, ELEMENT_TYPE_CODE, HIGHLIGHJS_CSS, HIGHLIGHJS_JS, CODE_BLOCK_AVAILABLE_LANGUAGES } from "./constants";
73
- import { jsx as _jsx } from "react/jsx-runtime";
74
- import { Fragment as _Fragment } from "react/jsx-runtime";
75
- import { jsxs as _jsxs } from "react/jsx-runtime";
76
-
77
- var ContentRenderer = function ContentRenderer(_ref) {
78
- var content = _ref.content,
79
- type = _ref.type,
80
- _ref$widgetType = _ref.widgetType,
81
- widgetType = _ref$widgetType === void 0 ? "post" : _ref$widgetType,
82
- _ref$headerFont = _ref.headerFont,
83
- headerFont = _ref$headerFont === void 0 ? sansFamily : _ref$headerFont,
84
- _ref$bodyFont = _ref.bodyFont,
85
- bodyFont = _ref$bodyFont === void 0 ? sansFamily : _ref$bodyFont,
86
- createAnchors = _ref.createAnchors,
87
- useHashAutoscroll = _ref.useHashAutoscroll,
88
- _ref$hashAutoscrollTo = _ref.hashAutoscrollTopMargin,
89
- hashAutoscrollTopMargin = _ref$hashAutoscrollTo === void 0 ? 0 : _ref$hashAutoscrollTo,
90
- decodeHtmlEntitiesOnRender = _ref.decodeHtmlEntitiesOnRender;
91
- var element = useRef({});
92
-
93
- var _useState = useState([]),
94
- _useState2 = _slicedToArray(_useState, 2),
95
- copyBtns = _useState2[0],
96
- setCopyBtns = _useState2[1]; // Autoscroll to hashes
97
-
98
-
99
- var scrollAndHighlightHash = useCallback(function () {
100
- try {
101
- var hash = window.location.hash;
102
-
103
- if (hash) {
104
- var hashEl = element.current.querySelector(hash);
105
-
106
- if (hashEl) {
107
- setTimeout(function () {
108
- window.scrollTo({
109
- top: hashEl.getBoundingClientRect().top - hashAutoscrollTopMargin,
110
- behavior: "smooth"
111
- });
112
- hashEl.classList.add("highlight");
113
- setTimeout(function () {
114
- hashEl.classList.remove("highlight");
115
- }, 5000);
116
- }, 500);
117
- }
118
- }
119
- } catch (error) {
120
- /* In some cases the hash may be cause this function to fail. In this case, handle and do nothing */
121
- }
122
- }, [hashAutoscrollTopMargin]);
123
- useEffect(function () {
124
- if (!element.current) return;
125
- var headerElems = createAnchors ? element.current.querySelectorAll("h1, h2, h3, h4, h5, h6") : [];
126
-
127
- if (headerElems.length > 0) {
128
- headerElems.forEach(function (header) {
129
- var _header$textContent = header.textContent,
130
- textContent = _header$textContent === void 0 ? "" : _header$textContent;
131
-
132
- if (textContent.length > 0) {
133
- header.id = header.id || removeSpecialCharacters(textContent.toLowerCase().replace(/\s/g, "-"));
134
- }
135
- });
136
- }
137
-
138
- var blockElems = element.current.querySelectorAll(ELEMENT_TYPE_PRE);
139
-
140
- if (blockElems.length > 0) {
141
- if (!loadjs.isDefined("highlightjs")) {
142
- loadCodeFont();
143
- loadjs([].concat(_toConsumableArray(HIGHLIGHJS_JS), _toConsumableArray(HIGHLIGHJS_CSS)), "highlightjs");
144
- }
145
-
146
- loadjs.ready("highlightjs", function () {
147
- // highlight.js register only languages we want to support?
148
- window.hljs.configure({
149
- languages: CODE_BLOCK_AVAILABLE_LANGUAGES,
150
- useBr: true
151
- });
152
- blockElems.forEach(function (elem) {
153
- var plainCode = elem.innerText; // Take the inner content and put inside single code block
154
- // This will ensure nice readability.
155
- // Needs to be done since editor will generate multiple lines for code for ease of editing
156
-
157
- var codeBlock = document.createElement(ELEMENT_TYPE_CODE);
158
- var decodedText = decodeHtmlEntities(plainCode);
159
- codeBlock.textContent = decodedText; // Done like this to prevent xss
160
-
161
- elem.innerHTML = ""; // Clear content so we can set just the single code block there
162
-
163
- elem.appendChild(codeBlock);
164
- window.hljs.highlightBlock(elem);
165
- });
166
- setCopyBtns(function (prevState) {
167
- return [].concat(_toConsumableArray(prevState), _toConsumableArray(blockElems));
168
- });
169
- });
170
- }
171
-
172
- setCopyBtns(_toConsumableArray(headerElems));
173
-
174
- if (useHashAutoscroll) {
175
- scrollAndHighlightHash();
176
- }
177
- }, [element, createAnchors, useHashAutoscroll, scrollAndHighlightHash]);
178
- var safeText = useMemo(function () {
179
- var lowercaseType = type && typeof type === "string" ? type.toLowerCase() : "html";
180
- var transformedContent = lowercaseType === "text" ? toSafeText("<p>".concat(content, "</p>")) : toHtml(content, lowercaseType);
181
-
182
- if (decodeHtmlEntitiesOnRender) {
183
- transformedContent = decodeHtmlEntities(transformedContent);
184
- }
185
-
186
- return transformedContent;
187
- }, [content, type, decodeHtmlEntitiesOnRender]); // Use dangerouslySetInnerHTML as there might be nested <p>'s header etc
188
- // This requires that all content is run through the toSafeText filter
189
- // before displaying. This will run it through xss filter.
190
-
191
- return /*#__PURE__*/_jsxs(_Fragment, {
192
- children: [/*#__PURE__*/_jsx(Wrapper, {
193
- className: "content-renderer",
194
- ref: element,
195
- widgetType: widgetType,
196
- headerFont: headerFont,
197
- bodyFont: bodyFont,
198
- createAnchors: createAnchors,
199
- dangerouslySetInnerHTML: {
200
- __html: safeText
201
- }
202
- }), copyBtns.map(function (el) {
203
- var clipboardContent = el.textContent || "";
204
-
205
- if (el.tagName !== ELEMENT_TYPE_PRE) {
206
- clipboardContent = "".concat(window.location.href.split("#")[0], "#").concat(el.id);
207
- } // eslint-disable-next-line no-control-regex
208
-
209
-
210
- clipboardContent = removeSpecialCharacters(clipboardContent);
211
- return /*#__PURE__*/ReactDOM.createPortal( /*#__PURE__*/_jsx(BtnContainer, {
212
- className: "content-copy-btn",
213
- children: /*#__PURE__*/_jsx(CopyToClipboardButton, {
214
- clipboardContent: clipboardContent
215
- })
216
- }), el);
217
- })]
218
- });
219
- };
220
-
221
- var BtnContainer = styled.div.withConfig({
222
- displayName: "ContentRenderer__BtnContainer",
223
- componentId: "sc-1mleu9k-0"
224
- })(["display:inline-flex;margin-left:", ";button{opacity:0;transition-property:opacity;transition-duration:150ms;transition-timing-function:ease-in;}button:hover,button:active,button:focus{opacity:1 !important;}div p{font-size:12px;line-height:16px;}"], margin200);
225
- var Wrapper = styled(BodyUI).attrs({
226
- as: "div"
227
- }).withConfig({
228
- displayName: "ContentRenderer__Wrapper",
229
- componentId: "sc-1mleu9k-1"
230
- })(["", " h1.highlight,h2.highlight,h3.highlight,h4.highlight,h5.highlight,h6.highlight{border-radius:6px;position:relative;:after{content:\" \";position:absolute;top:-8px;bottom:-8px;left:-8px;right:-8px;border-radius:6px;border:5px solid ", ";}}pre{border-radius:4px;background:", ";padding:8px;margin-bottom:10px;overflow:auto;white-space:pre;position:relative;overflow:visible;*:not(p){font-weight:inherit;font-family:\"IBM Plex Mono\",monospace !important;}.content-copy-btn{position:absolute;top:0;right:0;padding:", " 0;}:hover button{opacity:1;}}.mention{border-radius:0.2em;background-color:#fff5cc;border:1px solid #fff5cc;color:#0f1621;font-weight:400;&:hover{text-decoration:none;border:1px solid #fabd24;}}.extraMention{cursor:inherit;}", " ", ""], function (_ref2) {
231
- var createAnchors = _ref2.createAnchors;
232
- return createAnchors ? "\n h1, h2, h3, h4, h5, h6 {\n display: flex;\n align-items: center;\n :hover button {\n opacity: 0.4;\n }\n }\n " : "";
233
- }, lighten(warn, 0.8), gray09, padding200, function (_ref3) {
234
- var widgetType = _ref3.widgetType;
235
- return widgetType === "page" ? "" : "\n * {\n font-family: ".concat(sansFamily, " !important;\n }\n\n \n\n h1 {\n font-weight: 500;\n font-size: 24px;\n letter-spacing: -0.5px;\n line-height: 32px;\n + h1,\n + h2,\n + h3,\n + h4,\n + p {\n margin-top: 16px;\n }\n }\n h2 {\n font-weight: 500;\n font-size: 20px;\n line-height: 28px;\n + h1,\n + h2,\n + h3,\n + h4,\n + p {\n margin-top: 14px;\n }\n }\n h3 {\n font-weight: 500;\n font-size: 16px;\n line-height: 24px;\n + h1,\n + h2,\n + h3,\n + h4,\n + p {\n margin-top: 12px;\n }\n }\n h4 {\n font-size: 16px;\n line-height: 24px;\n + h1,\n + h2,\n + h3,\n + h4,\n + p {\n margin-top: 12px;\n }\n }\n p {\n font-size: 16px;\n line-height: 24px;\n letter-spacing: 0px;\n + h1,\n + h2,\n + h3,\n + h4,\n + p {\n margin-top: 12px;\n }\n }\n a {\n color: ").concat(active, ";\n text-decoration: none;\n :hover {\n text-decoration: underline;\n }\n }\n ul {\n list-style-type: disc;\n }\n ol {\n list-style-type: decimal;\n counter-reset: item;\n li {\n padding-left: 12px;\n text-indent: -33px;\n list-style-type: none;\n counter-increment: item;\n &:before {\n display: inline-block;\n width: 13px;\n padding-right: 15px;\n padding-left: 5px;\n font-weight: bold;\n text-align: right;\n content: counter(item) \".\";\n }\n }\n }\n ol,\n ul {\n font-size: 16px;\n line-height: 24px;\n margin: 18px 16px;\n display: block;\n -webkit-margin-before: 0.5em;\n -webkit-margin-after: 0.5em;\n -webkit-padding-start: 0.5em;\n li,\n li {\n margin-bottom: 5px;\n padding-left: 10px;\n > ul,\n > ol {\n -webkit-margin-before: 8px !important;\n -webkit-margin-after: 8px !important;\n }\n }\n\n &:first-child,\n &:first-child {\n -webkit-margin-before: 0;\n }\n &:last-child,\n &:last-child {\n -webkit-margin-after: 0;\n }\n }\n hr {\n -webkit-margin-before: 16px;\n -webkit-margin-after: 13px;\n border-color: @border-color;\n border-style: solid;\n height: 0px;\n border-width: 1px 0 0 0;\n }\n table {\n width: 100%;\n margin: 15px 0;\n text-align: left;\n thead th {\n background: @white;\n }\n th,\n td {\n border-width: 1px;\n border-style: solid;\n border-color: @border-color;\n padding: 0.5em;\n }\n tr:nth-child(even) {\n background: @almost-white;\n }\n tr:nth-child(odd) {\n background: @white;\n }\n }\n table.no-borders {\n th,\n td {\n border: none;\n }\n }\n table.padded-2 {\n th,\n td {\n padding: 2em;\n }\n }\n table.padded-1 {\n th,\n td {\n padding: 1em;\n }\n }\n img {\n max-width: 100%;\n margin: 15px 0;\n & + img {\n margin-top: 0;\n }\n }\n .xl-emoji * {\n font-size: 40px;\n line-height: 1.2;\n }\n \n blockquote {\n border-top: 2px solid ").concat(gray07, ";\n border-bottom: 2px solid ").concat(gray07, ";\n font-size: 18px;\n padding: 24px 48px;\n position: relative;\n text-align: center;\n margin: 48px 0;\n }\n ");
236
- }, function (_ref4) {
237
- var widgetType = _ref4.widgetType,
238
- bodyFont = _ref4.bodyFont,
239
- headerFont = _ref4.headerFont;
240
- return widgetType === "article" && css(["h1,h2,h3{font-family:", " !important;& *{font-family:", " !important;}}h4,h5,h6,p,ul,ol,li,table{font-family:", " !important;& *{font-family:", " !important;}}h1{font-size:32px;line-height:1.13;margin:0 0 20px;letter-spacing:-0.75px;}h2{font-size:24px;line-height:1.17;margin:0 0 16px;letter-spacing:-0.5px;}h3{font-size:20px;line-height:1.2;margin:0 0 14px;}h4,h5,h6,p,ul,ol,li{font-size:18px;line-height:1.56;margin-bottom:13px;margin-top:0;}hr{border-color:", ";}table{width:100% !important;margin:15px 0;font-size:18px !important;text-align:left;border-collapse:collapse;border-spacing:0;thead th{background:@white;}th,td{border-width:1px;border-style:solid;border-color:", ";padding:0.5em;word-wrap:break-word;}tr:nth-child(odd){background:", ";}tr:nth-child(even){background:@white;}}table.no-borders{th,td{border:none;}tr:nth-child(odd){background:", ";}tr:nth-child(even){background:@white;}}pre{position:relative;background-color:", ";padding:1em;margin:1em 0;border-radius:4px;white-space:pre;}img,span.fr-img-caption,span.fr-video{display:block;margin:30px 0;", ";&.article-align-left{margin:30px auto;display:block;max-width:100%;", "}&.article-align-center{margin:30px auto;display:block;}&.article-align-right{margin:30px auto;display:block;max-width:100%;", "}&.article-align-overflow{margin:30px auto;display:block;max-width:100%;", " img{width:100%;}}}img{&.image-border-radius{border-radius:6px;}&.image-box-shadow{box-shadow:0 4px 16px 0 #bacad5;}}span.fr-img-caption{&.image-border-radius img{border-radius:6px;}&.image-box-shadow img{box-shadow:0 4px 16px 0 #bacad5;}}p{img:first-child,span.fr-img-caption:first-child{&.article-align-left,&.article-align-right{", "}}}span.fr-img-caption{text-align:center;img{margin:0;}.fr-inner{font-weight:400;font-size:16px;margin:8px auto 0 auto;padding:0 8px;color:", ";display:block;max-width:671px;}}span.fr-video{position:relative;padding-bottom:56.25%;padding-top:30px;height:0;overflow:hidden;border-radius:6px;&.article-align-overflow{padding-top:170px;}iframe{position:absolute;top:0;left:0;width:100% !important;height:100% !important;}}blockquote{border-left:0 !important;padding-left:0 !important;margin:0 !important;color:inherit !important;p{line-height:30px;font-size:26px;text-align:center;margin:0 auto;}}.content-attachments{width:100%;}"], headerFont, headerFont, bodyFont, bodyFont, gray07, gray07, gray09, gray09, gray09, media.only.xs(_templateObject()), media.min.md(_templateObject2()), media.min.md(_templateObject3()), media.min.md(_templateObject4()), media.min.md(_templateObject5()), gray04);
241
- });
242
- ContentRenderer.propTypes = {
243
- content: PropTypes.string,
244
- type: function type(props, propName) {
245
- if (propName === "type" && props[propName] !== props[propName].toUpperCase()) {
246
- // eslint-disable-next-line no-console
247
- console.warn("Please use uppercase type 'HTML', 'MARKDOWN' or 'TEXT'");
248
- }
249
-
250
- if (propName === "type" && !["HTML", "MARKDOWN", "TEXT"].includes(props[propName].toUpperCase())) {
251
- throw new Error("Invalid type, use 'HTML', 'MARKDOWN' or 'TEXT'");
252
- }
253
- },
254
- widgetType: PropTypes.oneOf(["post", "article", "page"]),
255
- bodyFont: PropTypes.string,
256
- headerFont: PropTypes.string,
257
- decodeHtmlEntitiesOnRender: PropTypes.bool,
258
- createAnchors: PropTypes.bool,
259
- useHashAutoscroll: PropTypes.bool,
260
- hashAutoscrollTopMargin: PropTypes.number
261
- };
262
- ContentRenderer.defaultProps = {
263
- content: "",
264
- type: "html",
265
- widgetType: "post",
266
- bodyFont: "IBM Plex Sans, sans-serif",
267
- headerFont: "IBM Plex Sans, sans-serif",
268
- decodeHtmlEntitiesOnRender: false,
269
- createAnchors: false,
270
- useHashAutoscroll: true,
271
- hashAutoscrollTopMargin: 0
272
- };
273
- export default ContentRenderer;
package/dist/constants.js DELETED
@@ -1,73 +0,0 @@
1
- export var safeTagsAndAttributes = {
2
- a: ["class", "target", "href", "title", "data-collection-id", "data-page-id", "rel", "data-user-id", "data-user-id-old"],
3
- abbr: ["title"],
4
- address: [],
5
- area: ["shape", "coords", "href", "alt"],
6
- article: [],
7
- aside: [],
8
- audio: ["autoplay", "controls", "loop", "preload", "src"],
9
- b: [],
10
- bdi: ["dir"],
11
- bdo: ["dir"],
12
- big: [],
13
- blockquote: ["cite"],
14
- br: [],
15
- caption: [],
16
- center: [],
17
- cite: [],
18
- code: [],
19
- col: ["align", "valign", "span", "width"],
20
- colgroup: ["align", "valign", "span", "width"],
21
- dd: [],
22
- del: ["datetime"],
23
- details: ["open"],
24
- div: ["style"],
25
- dl: [],
26
- dt: [],
27
- em: [],
28
- font: ["color", "size", "face", "style"],
29
- footer: [],
30
- h1: ["style"],
31
- h2: ["style"],
32
- h3: ["style"],
33
- h4: ["style"],
34
- h5: ["style"],
35
- h6: ["style"],
36
- header: ["style"],
37
- hr: ["style", "class"],
38
- i: [],
39
- img: ["src", "alt", "title", "width", "height", "style", "class"],
40
- ins: ["datetime"],
41
- li: ["style"],
42
- mark: [],
43
- nav: [],
44
- ol: ["style"],
45
- p: ["style"],
46
- pre: ["style"],
47
- s: [],
48
- section: [],
49
- small: [],
50
- span: ["style", "class"],
51
- sub: [],
52
- sup: [],
53
- strong: [],
54
- table: ["width", "border", "align", "valign", "style", "class"],
55
- tbody: ["align", "valign", "style", "class"],
56
- td: ["width", "rowspan", "colspan", "align", "valign", "style", "class"],
57
- tfoot: ["align", "valign", "style", "class"],
58
- th: ["width", "rowspan", "colspan", "align", "valign", "style", "class"],
59
- thead: ["align", "valign", "style", "class"],
60
- tr: ["rowspan", "align", "valign", "style", "class"],
61
- tt: [],
62
- u: [],
63
- ul: ["style", "class"],
64
- video: ["style", "autoplay", "controls", "loop", "preload", "src", "height", "width"],
65
- iframe: ["src", "frameborder", "allow", "sandbox", "referrerpolicy", "allowfullscreen", "style", "class"]
66
- };
67
- var HIGHLIGHT_JS_THEME = "a11y-light";
68
- export var MONOSPACE_FONT_URL = "https://fonts.googleapis.com/css2?family=IBM+Plex+Mono&display=swap";
69
- export var HIGHLIGHJS_JS = ["https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.6.0/highlight.min.js"];
70
- export var HIGHLIGHJS_CSS = ["https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.6.0/styles/default.min.css", "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.6.0/styles/".concat(HIGHLIGHT_JS_THEME, ".min.css")];
71
- export var ELEMENT_TYPE_PRE = "PRE";
72
- export var ELEMENT_TYPE_CODE = "CODE";
73
- export var CODE_BLOCK_AVAILABLE_LANGUAGES = ["javascript", "html", "css", "xml", "json", "java", "php", "typescript"];
@@ -1,61 +0,0 @@
1
- import showdown from "showdown";
2
- import { extraMentioning, mentioningRegex } from "@universe/frontend-utils";
3
- var mentioningRegexCaseInsensitive = new RegExp(mentioningRegex, "i");
4
- var mentioningRegexGroupCaseInsensitive = new RegExp(mentioningRegex, "gi");
5
- var converter;
6
- var customRules = {
7
- color: {
8
- type: "lang",
9
- regex: /\((.*?)\)\[(rgb\((?:([0-9]{1,2}|1[0-9]{1,2}|2[0-4][0-9]|25[0-5]), ?)(?:([0-9]{1,2}|1[0-9]{1,2}|2[0-4][0-9]|25[0-5]), ?)(?:([0-9]{1,2}|1[0-9]{1,2}|2[0-4][0-9]|25[0-5]))\))\]/gi,
10
- replace: function replace(s, val) {
11
- var color = s.match(/\[(rgb\((?:([0-9]{1,2}|1[0-9]{1,2}|2[0-4][0-9]|25[0-5]), ?)(?:([0-9]{1,2}|1[0-9]{1,2}|2[0-4][0-9]|25[0-5]), ?)(?:([0-9]{1,2}|1[0-9]{1,2}|2[0-4][0-9]|25[0-5]))\))\]/gi)[0].replace("[", "").replace("]", "");
12
- return "<span style=\"color:".concat(color, "\">").concat(val, "</span>");
13
- }
14
- },
15
- mention: {
16
- type: "lang",
17
- regex: mentioningRegexGroupCaseInsensitive,
18
- replace: function replace(s) {
19
- var r = s.match(mentioningRegexCaseInsensitive);
20
- var id = r && r.length > 1 && r[1];
21
- var name = r && r.length > 2 && r[2];
22
-
23
- if (extraMentioning.find(function (mentioning) {
24
- return mentioning.toLowerCase() === String(id).toLowerCase();
25
- })) {
26
- return "<a class=\"mention extraMention\" data-user-id=\"".concat(id, "\">@").concat(name, "</a>");
27
- }
28
-
29
- return "<a class=\"mention\" data-user-id=\"".concat(id, "\">@").concat(name, "</a>");
30
- }
31
- },
32
- userMentioTag: {
33
- type: "lang",
34
- regex: /<user-mentio[^>]*>(.+?)<\/user-mentio>/gi,
35
- replace: function replace(s) {
36
- var r = s.match(/<user-mentio[^>]*>(.+?)<\/user-mentio>/);
37
- var attr = s.match(/data-user-id=["']([^"]+)["']/);
38
- var name = r && r.length > 1 && r[1];
39
- var id = attr && attr.length > 1 && attr[1];
40
- return "<a class=\"mention\" data-user-id=\"".concat(id, "\">").concat(name, "</a>");
41
- }
42
- }
43
- };
44
-
45
- function getConverter() {
46
- if (converter) return converter;
47
- showdown.extension("color", customRules.color);
48
- showdown.extension("mention", customRules.mention);
49
- showdown.extension("usermentiotag", customRules.userMentioTag);
50
- converter = new showdown.Converter({
51
- extensions: ["color", "mention", "usermentiotag"]
52
- });
53
- converter.setOption("strikethrough", true); // <del>
54
-
55
- converter.setOption("tables", true); // <table>
56
-
57
- converter.setOption("openLinksInNewWindow", true);
58
- return converter;
59
- }
60
-
61
- export default getConverter();
package/dist/index.js DELETED
@@ -1 +0,0 @@
1
- export { default as ContentRenderer } from "./ContentRenderer";
package/dist/utils.js DELETED
@@ -1,111 +0,0 @@
1
- import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
-
3
- function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
4
-
5
- function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
6
-
7
- import linkifyHtml from "linkifyjs/html";
8
- import xss from "xss";
9
- import { decode as decodeHtmlEntities } from "html-entities";
10
- import { extraMentioning, mentioningRegex } from "@universe/frontend-utils";
11
- import { fixEmojioneBug, shortToUnicode } from "@happeouikit/emojis";
12
- import { MONOSPACE_FONT_URL, safeTagsAndAttributes } from "./constants";
13
- import htmlConverter from "./htmlConverter";
14
- var mentioningRegexGroupCaseInsensitive = new RegExp(mentioningRegex, "gi");
15
- var mentioningHtmlRegexGroupCaseInsensitive = new RegExp(/<user-mentio[^>]*data-user-id=["']([^"]+)["'][^>]*>(?:@|(?:&#64;))(.+?)<\/user-mentio>/, "gi");
16
-
17
- var processMatch = function processMatch(match, id, name) {
18
- if (extraMentioning.find(function (mentioning) {
19
- return mentioning.toLowerCase() === String(id).toLowerCase();
20
- })) {
21
- return "<a class=\"mention extraMention\" data-user-id=\"".concat(id, "\">@").concat(name, "</a>");
22
- }
23
-
24
- return "<a class=\"mention\" data-user-id=\"".concat(id, "\">@").concat(name, "</a>");
25
- };
26
-
27
- var processMentions = function processMentions() {
28
- var str = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : "";
29
- return str.replace(mentioningRegexGroupCaseInsensitive, processMatch).replace(mentioningHtmlRegexGroupCaseInsensitive, processMatch);
30
- };
31
- /**
32
- * @name toSafeText
33
- * @description Returns filtered text with filterXSS library
34
- * @author Antero Hanhirova
35
- * @param {String} - Text to whitelist
36
- * @returns {String}
37
- */
38
-
39
-
40
- var toSafeText = function toSafeText(text) {
41
- return xss(text, {
42
- whiteList: safeTagsAndAttributes,
43
- css: {
44
- whiteList: _objectSpread({}, xss.getDefaultCSSWhiteList(), {
45
- "vertical-align": true
46
- })
47
- },
48
- stripIgnoreTag: true
49
- }).replace(/&nbsp;/g, " ").replace(/\u2060/g, ""); // Replaces a hidden character that resulted in a "?"-character in backend
50
- };
51
- /**
52
- * @name toHtml
53
- * @description Converts markdown to html, adds space to end of String
54
- * The non-breaking space helps users to add text if last word is mention item
55
- * @author Antero Hanhirova
56
- * @param {String} - Markdown
57
- * @returns {String} - Html
58
- */
59
-
60
-
61
- var toHtml = function toHtml() {
62
- var str = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : "";
63
- var type = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : "html";
64
- var newString = shortToUnicode(str);
65
- newString = fixEmojioneBug(newString);
66
-
67
- if (type === "markdown") {
68
- newString = htmlConverter.makeHtml(newString);
69
- } else {
70
- newString = processMentions(newString);
71
- }
72
-
73
- newString = toSafeText(newString);
74
- return linkifyHtml(newString, {
75
- target: "_blank",
76
- ignoreTags: ["pre", "code", "script", "style"]
77
- });
78
- };
79
-
80
- var loadCodeFont = function loadCodeFont() {
81
- var id = "ibmMonoOnDemand";
82
-
83
- if (!document.getElementById(id)) {
84
- var style = document.createElement("style");
85
- style.id = id;
86
- style.appendChild(document.createTextNode("@import url(".concat(MONOSPACE_FONT_URL, ");")));
87
- document.head.appendChild(style);
88
- }
89
- };
90
-
91
- var getNearestRelativeParent = function getNearestRelativeParent(el) {
92
- if (!el) return null;
93
- var elStyle = el.currentStyle || window.getComputedStyle(el, "");
94
- var positionStyle = elStyle.position;
95
-
96
- if (["relative", "absolute"].includes(positionStyle)) {
97
- return el;
98
- }
99
-
100
- return getNearestRelativeParent(el.parentNode);
101
- }; // Remove special and hidden characters from string
102
-
103
-
104
- var removeSpecialCharacters = function removeSpecialCharacters() {
105
- var str = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : "";
106
- return (// eslint-disable-next-line no-control-regex
107
- str.replace(/[^\u0000-\u007E]/g, "")
108
- );
109
- };
110
-
111
- export { toHtml, toSafeText, loadCodeFont, decodeHtmlEntities, getNearestRelativeParent, removeSpecialCharacters };