Fix email parsing issue in text widget

This commit is contained in:
vicky-primathon.in 2021-05-05 10:59:49 +05:30
parent 59ad172d81
commit 53b99c1a34
2 changed files with 88 additions and 5 deletions

View File

@ -0,0 +1,81 @@
import React from "react";
import { ChildrenNode, Matcher, MatchResponse, Node } from "interweave";
import { EmailProps, Email } from "interweave-autolink";
type EmailMatch = Pick<EmailProps, "email" | "emailParts">;
interface CombinePatternsOptions {
capture?: boolean;
flags?: string;
join?: string;
match?: string;
nonCapture?: boolean;
}
function combinePatterns(
patterns: RegExp[],
options: CombinePatternsOptions = {},
) {
let regex = patterns
.map((pattern) => pattern.source)
.join(options.join || "");
if (options.capture) {
regex = `(${regex})`;
} else if (options.nonCapture) {
regex = `(?:${regex})`;
}
if (options.match) {
regex += options.match;
}
return new RegExp(regex, options.flags || "");
}
const URL_HOST = combinePatterns(
[
/(?:(?:[a-z0-9](?:[-a-z0-9_]*[a-z0-9])?)\.)*/, // Subdomain
/(?:(?:[a-z0-9](?:[-a-z0-9]*[a-z0-9])?)\.)/, // Domain
/(?:[a-z](?:[-a-z0-9]*[a-z0-9])?)/, // TLD
],
{
capture: true,
},
);
const EMAIL_USERNAME_PART = /[.a-z0-9!#$%&?*+=_{|}~-]+/;
const VALID_ALNUM_CHARS = /[a-z0-9]/;
const EMAIL_USERNAME = combinePatterns(
[VALID_ALNUM_CHARS, EMAIL_USERNAME_PART, VALID_ALNUM_CHARS],
{
capture: true,
},
);
export const EMAIL_PATTERN = combinePatterns([EMAIL_USERNAME, URL_HOST], {
flags: "i",
join: "@",
});
export default class EmailMatcher extends Matcher<EmailProps> {
replaceWith(children: ChildrenNode, props: EmailProps): Node {
return React.createElement(Email, props, children);
}
asTag(): string {
return "a";
}
match(string: string): MatchResponse<EmailMatch> | null {
return this.doMatch(string, EMAIL_PATTERN, (matches) => ({
email: matches[0],
emailParts: {
host: matches[2],
username: matches[1],
},
}));
}
}

View File

@ -4,7 +4,8 @@ import styled from "styled-components";
import { ComponentProps } from "components/designSystems/appsmith/BaseComponent";
import { TextAlign } from "widgets/TextWidget";
import Interweave from "interweave";
import { UrlMatcher, EmailMatcher } from "interweave-autolink";
import { UrlMatcher } from "interweave-autolink";
import EmailMatcher, { EMAIL_PATTERN } from "./EmailMatcher";
import {
FontStyleTypes,
TextSize,
@ -83,6 +84,10 @@ class TextComponent extends React.Component<TextComponentProps> {
textColor,
backgroundColor,
} = this.props;
let matchers = [new UrlMatcher("url"), new EmailMatcher("email")];
if (text && EMAIL_PATTERN.test(text)) {
matchers = [new EmailMatcher("email")];
}
return (
<TextContainer>
<StyledText
@ -95,10 +100,7 @@ class TextComponent extends React.Component<TextComponentProps> {
backgroundColor={backgroundColor}
className={this.props.isLoading ? "bp3-skeleton" : "bp3-ui-text"}
>
<Interweave
content={text}
matchers={[new UrlMatcher("url"), new EmailMatcher("email")]}
/>
<Interweave content={text} matchers={matchers} />
</StyledText>
</TextContainer>
);