Path: blob/master/src/packages/frontend/editors/slate/elements/link/index.tsx
1698 views
/*1* This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.2* License: MS-RSL – see LICENSE.md for details3*/45import { Text } from "slate";67import { CSS } from "@cocalc/frontend/app-framework";8import { useFileContext } from "@cocalc/frontend/lib/file-context";9import { dict } from "@cocalc/util/misc";10import { register, SlateElement } from "../register";1112export const LINK_STYLE: CSS = {13backgroundColor: "white",14padding: "1px",15margin: "-1px", // so the position isn't changed; important when background is white so doesn't look weird.16borderRadius: "2px",17} as const;1819export interface Link extends SlateElement {20type: "link";21isInline: true;22url?: string;23title?: string;24}2526register({27slateType: "link",2829StaticElement: ({ attributes, children, element }) => {30const node = element as Link;31let { url, title } = node;32const { AnchorTagComponent, urlTransform, anchorStyle } = useFileContext();33const style: CSS = { ...LINK_STYLE, ...anchorStyle };34if (AnchorTagComponent != null) {35return (36<AnchorTagComponent37{...attributes}38href={url}39title={title}40style={style}41>42{children}43</AnchorTagComponent>44);45}46let props;47if (url != null) {48const isExternal = url.includes("://");49props = {50href: urlTransform?.(url, "a") ?? url,51target: isExternal ? "_blank" : undefined,52rel: isExternal ? "noopener" : undefined,53};54}55return (56<a {...attributes} {...props} title={title} style={style}>57{children}58{isBlank(element) && <span contentEditable={false}>(blank link)</span>}59</a>60);61},6263toSlate: ({ type, children, state }) => {64const attrs = dict(state.attrs as any);65return {66type,67children,68isInline: true,69url: attrs.href,70title: attrs.title,71};72},73});7475function isBlank(element): boolean {76return (77element.children.length == 1 &&78Text.isText(element.children[0]) &&79!element.children[0].text.trim()80);81}828384