feat: Show icon on external links (#3100)

* feat: External links get treatment

* cache decorations
This commit is contained in:
Tom Moor
2022-02-16 18:05:02 -08:00
committed by GitHub
parent 3760a03c44
commit d7ee801fe4
11 changed files with 162 additions and 73 deletions

View File

@@ -1,6 +1,7 @@
import * as React from "react";
import { Optional } from "utility-types";
import embeds from "@shared/editor/embeds";
import { isInternalUrl } from "@shared/utils/urls";
import ErrorBoundary from "~/components/ErrorBoundary";
import { Props as EditorProps } from "~/editor";
import useDictionary from "~/hooks/useDictionary";
@@ -8,7 +9,7 @@ import useToasts from "~/hooks/useToasts";
import history from "~/utils/history";
import { isModKey } from "~/utils/keyboard";
import { uploadFile } from "~/utils/uploadFile";
import { isInternalUrl, isHash } from "~/utils/urls";
import { isHash } from "~/utils/urls";
const SharedEditor = React.lazy(
() =>

View File

@@ -3,10 +3,10 @@ import * as React from "react";
import { Portal } from "react-portal";
import styled from "styled-components";
import parseDocumentSlug from "@shared/utils/parseDocumentSlug";
import { isInternalUrl } from "@shared/utils/urls";
import HoverPreviewDocument from "~/components/HoverPreviewDocument";
import useStores from "~/hooks/useStores";
import { fadeAndSlideDown } from "~/styles/animations";
import { isInternalUrl } from "~/utils/urls";
const DELAY_OPEN = 300;
const DELAY_CLOSE = 300;

View File

@@ -1,4 +1,5 @@
import {
ArrowIcon,
DocumentIcon,
CloseIcon,
PlusIcon,
@@ -11,6 +12,7 @@ import { EditorView } from "prosemirror-view";
import * as React from "react";
import styled from "styled-components";
import isUrl from "@shared/editor/lib/isUrl";
import { isInternalUrl } from "@shared/utils/urls";
import Flex from "~/components/Flex";
import { Dictionary } from "~/hooks/useDictionary";
import Input from "./Input";
@@ -299,6 +301,7 @@ class LinkEditor extends React.Component<Props, State> {
const looksLikeUrl = value.match(/^https?:\/\//i);
const suggestedLinkTitle = this.suggestedLinkTitle;
const isInternal = isInternalUrl(value);
const showCreateLink =
!!this.props.onCreateLink &&
@@ -324,9 +327,15 @@ class LinkEditor extends React.Component<Props, State> {
autoFocus={this.href === ""}
/>
<Tooltip tooltip={dictionary.openLink}>
<Tooltip
tooltip={isInternal ? dictionary.goToLink : dictionary.openLink}
>
<ToolbarButton onClick={this.handleOpenLink} disabled={!value}>
<OpenIcon color="currentColor" />
{isInternal ? (
<ArrowIcon color="currentColor" />
) : (
<OpenIcon color="currentColor" />
)}
</ToolbarButton>
</Tooltip>
<Tooltip tooltip={dictionary.removeLink}>

View File

@@ -529,13 +529,16 @@ const EditorStyles = styled.div<{
a {
color: ${(props) => props.theme.text};
border-bottom: 1px solid ${(props) => lighten(0.5, props.theme.text)};
text-decoration: none !important;
text-decoration: underline;
text-decoration-color: ${(props) => lighten(0.5, props.theme.text)};
text-decoration-thickness: 1px;
text-underline-offset: .15em;
font-weight: 500;
&:hover {
border-bottom: 1px solid ${(props) => props.theme.text};
text-decoration: none;
text-decoration: underline;
text-decoration-color: ${(props) => props.theme.text};
text-decoration-thickness: 1px;
}
}
}
@@ -718,6 +721,11 @@ const EditorStyles = styled.div<{
}
}
.external-link {
position: relative;
top: 2px;
}
.code-actions,
.notice-actions {
display: flex;

View File

@@ -50,6 +50,7 @@ export default function useDictionary() {
newLineWithSlash: `${t("Keep typing to filter")}`,
noResults: t("No results"),
openLink: t("Open link"),
goToLink: t("Go to link"),
orderedList: t("Ordered list"),
pageBreak: t("Page break"),
pasteLink: `${t("Paste a link")}`,

View File

@@ -6,6 +6,7 @@ import { observer } from "mobx-react";
import * as React from "react";
import { RouteComponentProps, StaticContext } from "react-router";
import parseDocumentSlug from "@shared/utils/parseDocumentSlug";
import { isInternalUrl } from "@shared/utils/urls";
import RootStore from "~/stores/RootStore";
import Document from "~/models/Document";
import Revision from "~/models/Revision";
@@ -17,7 +18,6 @@ import { NavigationNode } from "~/types";
import { NotFoundError, OfflineError } from "~/utils/errors";
import history from "~/utils/history";
import { matchDocumentEdit } from "~/utils/routeHelpers";
import { isInternalUrl } from "~/utils/urls";
import HideSidebar from "./HideSidebar";
import Loading from "./Loading";

View File

@@ -1,25 +1,3 @@
import { parseDomain } from "@shared/utils/domains";
export function isInternalUrl(href: string) {
if (href[0] === "/") {
return true;
}
const outline = parseDomain(window.location.href);
const parsed = parseDomain(href);
if (
parsed &&
outline &&
parsed.subdomain === outline.subdomain &&
parsed.domain === outline.domain &&
parsed.tld === outline.tld
) {
return true;
}
return false;
}
export function isHash(href: string) {
if (href[0] === "#") {
return true;