From 6a09d71200bac0e908f780ac621fb9ab896cc4b6 Mon Sep 17 00:00:00 2001 From: Lam Kee Wei Date: Wed, 28 Apr 2021 16:28:13 +0800 Subject: [PATCH 1/4] feat: add link field to insert image popover --- .../RichTextEditor.module.scss | 10 ++- .../controls/ImageControl.tsx | 61 +++++++++++++++++-- 2 files changed, 63 insertions(+), 8 deletions(-) diff --git a/frontend/src/components/common/rich-text-editor/RichTextEditor.module.scss b/frontend/src/components/common/rich-text-editor/RichTextEditor.module.scss index 48f19c76a..83b870a0e 100644 --- a/frontend/src/components/common/rich-text-editor/RichTextEditor.module.scss +++ b/frontend/src/components/common/rich-text-editor/RichTextEditor.module.scss @@ -111,18 +111,18 @@ top: 35px; left: 5px; background: $white; - padding: $spacing-1; + padding: $spacing-2; border-radius: 5px; box-shadow: 0px 0px 20px rgba(193, 199, 205, 0.7); .item { @include flex-horizontal; margin-bottom: $spacing-1; - width: 200px; + width: 300px; label { @extend %caption; - width: 40px; + width: 50px; } .control { @@ -136,6 +136,10 @@ padding: 0.25rem $spacing-1; border: solid 1px $neutral; border-radius: 0.25rem; + + &::placeholder { + color: $neutral; + } } } diff --git a/frontend/src/components/common/rich-text-editor/controls/ImageControl.tsx b/frontend/src/components/common/rich-text-editor/controls/ImageControl.tsx index 6f1bf4dee..d09a539d0 100644 --- a/frontend/src/components/common/rich-text-editor/controls/ImageControl.tsx +++ b/frontend/src/components/common/rich-text-editor/controls/ImageControl.tsx @@ -1,9 +1,12 @@ import cx from 'classnames' import React, { useContext, useState } from 'react' +import { AtomicBlockUtils } from 'draft-js' import { EditorContext } from '../RichTextEditor' import styles from '../RichTextEditor.module.scss' +const VARIABLE_REGEX = new RegExp(/^{{\s*?\w+\s*?}}$/) + interface ImageControlProps { currentState: any expanded: boolean @@ -19,6 +22,7 @@ const ImageForm = ({ onChange: (key: string, ...vals: string[]) => void }) => { const [imgSrc, setImgSrc] = useState('') + const [link, setLink] = useState('') function stopPropagation(e: React.MouseEvent) { e.stopPropagation() @@ -26,7 +30,7 @@ const ImageForm = ({ function handleSubmit(e: React.FormEvent) { e.preventDefault() - onChange(imgSrc, 'auto', '100%', '') + onChange(imgSrc, 'auto', '100%', link) } return ( @@ -36,16 +40,29 @@ const ImageForm = ({ className={styles.form} >
+
setImgSrc(e.target.value)} />
+
+ +
+ setLink(e.target.value)} + /> +
+
+
- + - + - + + {link && ( + <> + + + Link + + + )}
)} diff --git a/frontend/src/components/common/rich-text-editor/utils/Converter.ts b/frontend/src/components/common/rich-text-editor/utils/Converter.ts index 0ef0ce604..84865d594 100644 --- a/frontend/src/components/common/rich-text-editor/utils/Converter.ts +++ b/frontend/src/components/common/rich-text-editor/utils/Converter.ts @@ -225,6 +225,9 @@ const getAttrStr = (attrs: Record): string => { case 'targetOption': key = 'target' break + case 'link': + key = 'data-link' + break } return `${attrStr} ${key}="${value}"` @@ -237,7 +240,9 @@ const renderTag = (htmlTag: HTMLTag): string => { switch (tag) { case 'img': - return `<${tag}${attrStr} />` + return attr.link + ? `<${tag}${attrStr} />` + : `<${tag}${attrStr} />` default: return type === 'open' ? `<${tag}${attrStr}>` : `` } @@ -687,11 +692,13 @@ class ContentBlocksBuilder { private addImage(node: ChildNode, style: DraftInlineStyle) { const image = node as HTMLImageElement const { src, height, width } = image + const link = image.getAttribute('data-link') this.contentState = this.contentState.createEntity('IMAGE', 'MUTABLE', { src, height: height > 0 ? height : 'auto', width: `${width}%`, + link, }) this.currentEntity = this.contentState.getLastCreatedEntityKey() diff --git a/modules/postman-templating/src/xss-options.ts b/modules/postman-templating/src/xss-options.ts index 5a2515d9e..1e4d4a27b 100644 --- a/modules/postman-templating/src/xss-options.ts +++ b/modules/postman-templating/src/xss-options.ts @@ -41,7 +41,15 @@ export const XSS_EMAIL_OPTION = { h5: DEFAULT_EMAIL_ATTRS, h6: DEFAULT_EMAIL_ATTRS, a: ['href', 'title', 'target', ...DEFAULT_EMAIL_ATTRS], - img: ['src', 'alt', 'title', 'width', 'height', ...DEFAULT_EMAIL_ATTRS], + img: [ + 'src', + 'alt', + 'title', + 'width', + 'height', + 'data-link', + ...DEFAULT_EMAIL_ATTRS, + ], div: [], tbody: [], table: DEFAULT_EMAIL_ATTRS, From 6230a96df607f76976c5415d910810742cc8c3bf Mon Sep 17 00:00:00 2001 From: Lam Kee Wei Date: Wed, 28 Apr 2021 16:38:36 +0800 Subject: [PATCH 3/4] fix: skip appending protocol if link is empty --- .../components/common/rich-text-editor/controls/ImageControl.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/src/components/common/rich-text-editor/controls/ImageControl.tsx b/frontend/src/components/common/rich-text-editor/controls/ImageControl.tsx index d09a539d0..7fd350e5a 100644 --- a/frontend/src/components/common/rich-text-editor/controls/ImageControl.tsx +++ b/frontend/src/components/common/rich-text-editor/controls/ImageControl.tsx @@ -96,6 +96,7 @@ export const ImageControl = (props: ImageControlProps) => { function formatLink(link: string): string { if (VARIABLE_REGEX.test(link)) return link if ( + link && !link.startsWith('http://') && !link.startsWith('https://') && !link.startsWith('mailto:') From c3eeb570ed4a4692c46be03be88130261f901068 Mon Sep 17 00:00:00 2001 From: Lam Kee Wei Date: Thu, 6 May 2021 12:41:25 +0800 Subject: [PATCH 4/4] feat: show linked image in preview --- .../common/rich-text-editor/blocks/ImageBlock.tsx | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/frontend/src/components/common/rich-text-editor/blocks/ImageBlock.tsx b/frontend/src/components/common/rich-text-editor/blocks/ImageBlock.tsx index 3f6788828..0a5c55ff3 100644 --- a/frontend/src/components/common/rich-text-editor/blocks/ImageBlock.tsx +++ b/frontend/src/components/common/rich-text-editor/blocks/ImageBlock.tsx @@ -99,8 +99,18 @@ export const ImageBlock = ({ } } + function renderPreviewImage() { + return link ? ( + + + + ) : ( + + ) + } + return readOnly ? ( - + renderPreviewImage() ) : (