chore: More type improvements
This commit is contained in:
@@ -1,13 +1,14 @@
|
||||
import { lighten } from "polished";
|
||||
import * as React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Extension } from "rich-markdown-editor";
|
||||
import styled, { DefaultTheme, withTheme } from "styled-components";
|
||||
import { Props as EditorProps } from "rich-markdown-editor";
|
||||
import { EmbedDescriptor } from "rich-markdown-editor/dist/types";
|
||||
import styled, { useTheme } from "styled-components";
|
||||
import { Optional } from "utility-types";
|
||||
import embeds from "@shared/embeds";
|
||||
import { light } from "@shared/theme";
|
||||
import UiStore from "~/stores/UiStore";
|
||||
import ErrorBoundary from "~/components/ErrorBoundary";
|
||||
import Tooltip from "~/components/Tooltip";
|
||||
import useDictionary from "~/hooks/useDictionary";
|
||||
import useMediaQuery from "~/hooks/useMediaQuery";
|
||||
import useToasts from "~/hooks/useToasts";
|
||||
import history from "~/utils/history";
|
||||
@@ -23,56 +24,25 @@ const RichMarkdownEditor = React.lazy(
|
||||
)
|
||||
);
|
||||
|
||||
// @ts-expect-error ts-migrate(7034) FIXME: Variable 'EMPTY_ARRAY' implicitly has type 'any[]'... Remove this comment to see the full error message
|
||||
const EMPTY_ARRAY = [];
|
||||
const EMPTY_ARRAY: EmbedDescriptor[] = [];
|
||||
|
||||
export type Props = {
|
||||
id?: string;
|
||||
value?: string;
|
||||
defaultValue?: string;
|
||||
readOnly?: boolean;
|
||||
grow?: boolean;
|
||||
export type Props = Optional<
|
||||
EditorProps,
|
||||
"placeholder" | "defaultValue" | "tooltip" | "onClickLink" | "embeds"
|
||||
> & {
|
||||
shareId?: string | undefined;
|
||||
disableEmbeds?: boolean;
|
||||
ui?: UiStore;
|
||||
style?: React.CSSProperties;
|
||||
extensions?: Extension[];
|
||||
shareId?: string | null | undefined;
|
||||
autoFocus?: boolean;
|
||||
template?: boolean;
|
||||
placeholder?: string;
|
||||
maxLength?: number;
|
||||
scrollTo?: string;
|
||||
theme?: DefaultTheme;
|
||||
className?: string;
|
||||
readOnlyWriteCheckboxes?: boolean;
|
||||
onBlur?: () => void;
|
||||
onFocus?: () => void;
|
||||
onPublish?: (event: React.MouseEvent) => any;
|
||||
onSave?: (arg0: {
|
||||
done?: boolean;
|
||||
autosave?: boolean;
|
||||
publish?: boolean;
|
||||
}) => any;
|
||||
grow?: boolean;
|
||||
onSynced?: () => Promise<void>;
|
||||
onCancel?: () => any;
|
||||
onDoubleClick?: () => any;
|
||||
onChange?: (getValue: () => string) => any;
|
||||
onSearchLink?: (title: string) => any;
|
||||
onHoverLink?: (event: MouseEvent) => any;
|
||||
onCreateLink?: (title: string) => Promise<string>;
|
||||
onImageUploadStart?: () => any;
|
||||
onImageUploadStop?: () => any;
|
||||
onPublish?: (event: React.MouseEvent) => any;
|
||||
};
|
||||
|
||||
type PropsWithRef = Props & {
|
||||
forwardedRef: React.Ref<any>;
|
||||
};
|
||||
|
||||
function Editor(props: PropsWithRef) {
|
||||
function Editor(props: Props, ref: React.Ref<any>) {
|
||||
const { id, shareId } = props;
|
||||
const { t } = useTranslation();
|
||||
const theme = useTheme();
|
||||
const { showToast } = useToasts();
|
||||
const isPrinting = useMediaQuery("print");
|
||||
const dictionary = useDictionary();
|
||||
|
||||
const onUploadImage = React.useCallback(
|
||||
async (file: File) => {
|
||||
@@ -115,7 +85,7 @@ function Editor(props: PropsWithRef) {
|
||||
window.open(href, "_blank");
|
||||
}
|
||||
},
|
||||
[history, shareId]
|
||||
[shareId]
|
||||
);
|
||||
|
||||
const onShowToast = React.useCallback(
|
||||
@@ -125,88 +95,20 @@ function Editor(props: PropsWithRef) {
|
||||
[showToast]
|
||||
);
|
||||
|
||||
const dictionary = React.useMemo(() => {
|
||||
return {
|
||||
addColumnAfter: t("Insert column after"),
|
||||
addColumnBefore: t("Insert column before"),
|
||||
addRowAfter: t("Insert row after"),
|
||||
addRowBefore: t("Insert row before"),
|
||||
alignCenter: t("Align center"),
|
||||
alignLeft: t("Align left"),
|
||||
alignRight: t("Align right"),
|
||||
bulletList: t("Bulleted list"),
|
||||
checkboxList: t("Todo list"),
|
||||
codeBlock: t("Code block"),
|
||||
codeCopied: t("Copied to clipboard"),
|
||||
codeInline: t("Code"),
|
||||
createLink: t("Create link"),
|
||||
createLinkError: t("Sorry, an error occurred creating the link"),
|
||||
createNewDoc: t("Create a new doc"),
|
||||
deleteColumn: t("Delete column"),
|
||||
deleteRow: t("Delete row"),
|
||||
deleteTable: t("Delete table"),
|
||||
deleteImage: t("Delete image"),
|
||||
downloadImage: t("Download image"),
|
||||
alignImageLeft: t("Float left"),
|
||||
alignImageRight: t("Float right"),
|
||||
alignImageDefault: t("Center large"),
|
||||
em: t("Italic"),
|
||||
embedInvalidLink: t("Sorry, that link won’t work for this embed type"),
|
||||
findOrCreateDoc: `${t("Find or create a doc")}…`,
|
||||
h1: t("Big heading"),
|
||||
h2: t("Medium heading"),
|
||||
h3: t("Small heading"),
|
||||
heading: t("Heading"),
|
||||
hr: t("Divider"),
|
||||
image: t("Image"),
|
||||
imageUploadError: t("Sorry, an error occurred uploading the image"),
|
||||
imageCaptionPlaceholder: t("Write a caption"),
|
||||
info: t("Info"),
|
||||
infoNotice: t("Info notice"),
|
||||
link: t("Link"),
|
||||
linkCopied: t("Link copied to clipboard"),
|
||||
mark: t("Highlight"),
|
||||
newLineEmpty: `${t("Type '/' to insert")}…`,
|
||||
newLineWithSlash: `${t("Keep typing to filter")}…`,
|
||||
noResults: t("No results"),
|
||||
openLink: t("Open link"),
|
||||
orderedList: t("Ordered list"),
|
||||
pageBreak: t("Page break"),
|
||||
pasteLink: `${t("Paste a link")}…`,
|
||||
pasteLinkWithTitle: (service: string) =>
|
||||
t("Paste a {{service}} link…", {
|
||||
service,
|
||||
}),
|
||||
placeholder: t("Placeholder"),
|
||||
quote: t("Quote"),
|
||||
removeLink: t("Remove link"),
|
||||
searchOrPasteLink: `${t("Search or paste a link")}…`,
|
||||
strikethrough: t("Strikethrough"),
|
||||
strong: t("Bold"),
|
||||
subheading: t("Subheading"),
|
||||
table: t("Table"),
|
||||
tip: t("Tip"),
|
||||
tipNotice: t("Tip notice"),
|
||||
warning: t("Warning"),
|
||||
warningNotice: t("Warning notice"),
|
||||
};
|
||||
}, [t]);
|
||||
|
||||
return (
|
||||
<ErrorBoundary reloadOnChunkMissing>
|
||||
<StyledEditor
|
||||
ref={props.forwardedRef}
|
||||
ref={ref}
|
||||
uploadImage={onUploadImage}
|
||||
onClickLink={onClickLink}
|
||||
onShowToast={onShowToast}
|
||||
// @ts-expect-error ts-migrate(7005) FIXME: Variable 'EMPTY_ARRAY' implicitly has an 'any[]' t... Remove this comment to see the full error message
|
||||
embeds={props.disableEmbeds ? EMPTY_ARRAY : embeds}
|
||||
tooltip={EditorTooltip}
|
||||
dictionary={dictionary}
|
||||
{...props}
|
||||
tooltip={EditorTooltip}
|
||||
onClickLink={onClickLink}
|
||||
placeholder={props.placeholder || ""}
|
||||
defaultValue={props.defaultValue || ""}
|
||||
theme={isPrinting ? light : props.theme}
|
||||
theme={isPrinting ? light : theme}
|
||||
/>
|
||||
</ErrorBoundary>
|
||||
);
|
||||
@@ -320,20 +222,19 @@ const StyledEditor = styled(RichMarkdownEditor)<{ grow?: boolean }>`
|
||||
}
|
||||
`;
|
||||
|
||||
// @ts-expect-error ts-migrate(7031) FIXME: Binding element 'children' implicitly has an 'any'... Remove this comment to see the full error message
|
||||
const EditorTooltip = ({ children, ...props }) => (
|
||||
// @ts-expect-error ts-migrate(2769) FIXME: No overload matches this call.
|
||||
<Tooltip offset="0, 16" delay={150} {...props}>
|
||||
<Span>{children}</Span>
|
||||
type TooltipProps = {
|
||||
children: React.ReactNode;
|
||||
tooltip: string;
|
||||
};
|
||||
|
||||
const EditorTooltip = ({ children, tooltip, ...props }: TooltipProps) => (
|
||||
<Tooltip offset="0, 16" delay={150} tooltip={tooltip} {...props}>
|
||||
<TooltipContent>{children}</TooltipContent>
|
||||
</Tooltip>
|
||||
);
|
||||
|
||||
const Span = styled.span`
|
||||
const TooltipContent = styled.span`
|
||||
outline: none;
|
||||
`;
|
||||
|
||||
const EditorWithTheme = withTheme(Editor);
|
||||
|
||||
export default React.forwardRef<typeof Editor, Props>((props, ref) => (
|
||||
<EditorWithTheme {...props} forwardedRef={ref} />
|
||||
));
|
||||
export default React.forwardRef<typeof Editor, Props>(Editor);
|
||||
|
||||
@@ -5,7 +5,6 @@ import styled from "styled-components";
|
||||
import Editor from "~/components/Editor";
|
||||
import HelpText from "~/components/HelpText";
|
||||
import { LabelText, Outline } from "~/components/Input";
|
||||
import useStores from "~/hooks/useStores";
|
||||
|
||||
type Props = {
|
||||
label: string;
|
||||
@@ -16,7 +15,6 @@ type Props = {
|
||||
|
||||
function InputRich({ label, minHeight, maxHeight, ...rest }: Props) {
|
||||
const [focused, setFocused] = React.useState<boolean>(false);
|
||||
const { ui } = useStores();
|
||||
const handleBlur = React.useCallback(() => {
|
||||
setFocused(false);
|
||||
}, []);
|
||||
@@ -39,13 +37,7 @@ function InputRich({ label, minHeight, maxHeight, ...rest }: Props) {
|
||||
</HelpText>
|
||||
}
|
||||
>
|
||||
<Editor
|
||||
onBlur={handleBlur}
|
||||
onFocus={handleFocus}
|
||||
ui={ui}
|
||||
grow
|
||||
{...rest}
|
||||
/>
|
||||
<Editor onBlur={handleBlur} onFocus={handleFocus} grow {...rest} />
|
||||
</React.Suspense>
|
||||
</StyledOutline>
|
||||
</>
|
||||
|
||||
@@ -1,15 +1,11 @@
|
||||
import Tippy from "@tippy.js/react";
|
||||
import Tippy, { TippyProps } from "@tippy.js/react";
|
||||
import { TFunctionResult } from "i18next";
|
||||
import * as React from "react";
|
||||
import styled from "styled-components";
|
||||
|
||||
type Props = {
|
||||
type Props = Omit<TippyProps, "content" | "theme"> & {
|
||||
tooltip: React.ReactChild | React.ReactChild[] | TFunctionResult;
|
||||
shortcut?: React.ReactNode;
|
||||
placement?: "top" | "bottom" | "left" | "right";
|
||||
children: React.ReactElement<any>;
|
||||
delay?: number;
|
||||
className?: string;
|
||||
};
|
||||
|
||||
function Tooltip({ shortcut, tooltip, delay = 50, ...rest }: Props) {
|
||||
|
||||
74
app/hooks/useDictionary.ts
Normal file
74
app/hooks/useDictionary.ts
Normal file
@@ -0,0 +1,74 @@
|
||||
import * as React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
export default function useDictionary() {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return React.useMemo(() => {
|
||||
return {
|
||||
addColumnAfter: t("Insert column after"),
|
||||
addColumnBefore: t("Insert column before"),
|
||||
addRowAfter: t("Insert row after"),
|
||||
addRowBefore: t("Insert row before"),
|
||||
alignCenter: t("Align center"),
|
||||
alignLeft: t("Align left"),
|
||||
alignRight: t("Align right"),
|
||||
bulletList: t("Bulleted list"),
|
||||
checkboxList: t("Todo list"),
|
||||
codeBlock: t("Code block"),
|
||||
codeCopied: t("Copied to clipboard"),
|
||||
codeInline: t("Code"),
|
||||
createLink: t("Create link"),
|
||||
createLinkError: t("Sorry, an error occurred creating the link"),
|
||||
createNewDoc: t("Create a new doc"),
|
||||
deleteColumn: t("Delete column"),
|
||||
deleteRow: t("Delete row"),
|
||||
deleteTable: t("Delete table"),
|
||||
deleteImage: t("Delete image"),
|
||||
downloadImage: t("Download image"),
|
||||
replaceImage: t("Replace image"),
|
||||
alignImageLeft: t("Float left"),
|
||||
alignImageRight: t("Float right"),
|
||||
alignImageDefault: t("Center large"),
|
||||
em: t("Italic"),
|
||||
embedInvalidLink: t("Sorry, that link won’t work for this embed type"),
|
||||
findOrCreateDoc: `${t("Find or create a doc")}…`,
|
||||
h1: t("Big heading"),
|
||||
h2: t("Medium heading"),
|
||||
h3: t("Small heading"),
|
||||
heading: t("Heading"),
|
||||
hr: t("Divider"),
|
||||
image: t("Image"),
|
||||
imageUploadError: t("Sorry, an error occurred uploading the image"),
|
||||
imageCaptionPlaceholder: t("Write a caption"),
|
||||
info: t("Info"),
|
||||
infoNotice: t("Info notice"),
|
||||
link: t("Link"),
|
||||
linkCopied: t("Link copied to clipboard"),
|
||||
mark: t("Highlight"),
|
||||
newLineEmpty: `${t("Type '/' to insert")}…`,
|
||||
newLineWithSlash: `${t("Keep typing to filter")}…`,
|
||||
noResults: t("No results"),
|
||||
openLink: t("Open link"),
|
||||
orderedList: t("Ordered list"),
|
||||
pageBreak: t("Page break"),
|
||||
pasteLink: `${t("Paste a link")}…`,
|
||||
pasteLinkWithTitle: (service: string) =>
|
||||
t("Paste a {{service}} link…", {
|
||||
service,
|
||||
}),
|
||||
placeholder: t("Placeholder"),
|
||||
quote: t("Quote"),
|
||||
removeLink: t("Remove link"),
|
||||
searchOrPasteLink: `${t("Search or paste a link")}…`,
|
||||
strikethrough: t("Strikethrough"),
|
||||
strong: t("Bold"),
|
||||
subheading: t("Subheading"),
|
||||
table: t("Table"),
|
||||
tip: t("Tip"),
|
||||
tipNotice: t("Tip notice"),
|
||||
warning: t("Warning"),
|
||||
warningNotice: t("Warning notice"),
|
||||
};
|
||||
}, [t]);
|
||||
}
|
||||
@@ -568,7 +568,6 @@ class DocumentScene extends React.Component<Props> {
|
||||
onCancel={this.goBack}
|
||||
readOnly={readOnly}
|
||||
readOnlyWriteCheckboxes={readOnly && abilities.update}
|
||||
ui={this.props.ui}
|
||||
>
|
||||
{shareId && (
|
||||
<ReferencesWrapper isOnlyTitle={document.isOnlyTitle}>
|
||||
|
||||
@@ -18,7 +18,6 @@ type Props = EditorProps &
|
||||
title: string;
|
||||
document: Document;
|
||||
isDraft: boolean;
|
||||
shareId: string | null | undefined;
|
||||
multiplayer?: boolean;
|
||||
onSave: (arg0: {
|
||||
done?: boolean;
|
||||
@@ -60,6 +59,7 @@ class DocumentEditor extends React.Component<Props> {
|
||||
|
||||
handleLinkActive = (event: MouseEvent) => {
|
||||
this.activeLinkEvent = event;
|
||||
return false;
|
||||
};
|
||||
|
||||
handleLinkInactive = () => {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import * as React from "react";
|
||||
import { EmbedDescriptor } from "rich-markdown-editor/dist/types";
|
||||
import styled from "styled-components";
|
||||
import Abstract from "./Abstract";
|
||||
import Airtable from "./Airtable";
|
||||
@@ -43,7 +44,7 @@ export type EmbedProps = {
|
||||
};
|
||||
|
||||
function matcher(Component: React.ComponentType<EmbedProps>) {
|
||||
return (url: string) => {
|
||||
return (url: string): boolean | [] | RegExpMatchArray => {
|
||||
// @ts-expect-error not aware of static
|
||||
const regexes = Component.ENABLED;
|
||||
|
||||
@@ -55,7 +56,7 @@ function matcher(Component: React.ComponentType<EmbedProps>) {
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -65,7 +66,7 @@ const Img = styled(Image)`
|
||||
height: 18px;
|
||||
`;
|
||||
|
||||
export default [
|
||||
const embeds: EmbedDescriptor[] = [
|
||||
{
|
||||
title: "Abstract",
|
||||
keywords: "design",
|
||||
@@ -162,6 +163,7 @@ export default [
|
||||
},
|
||||
{
|
||||
title: "Google Docs",
|
||||
keywords: "documents word",
|
||||
icon: () => <Img src="/images/google-docs.png" alt="Google Docs" />,
|
||||
component: GoogleDocs,
|
||||
matcher: matcher(GoogleDocs),
|
||||
@@ -298,3 +300,5 @@ export default [
|
||||
matcher: matcher(YouTube),
|
||||
},
|
||||
];
|
||||
|
||||
export default embeds;
|
||||
|
||||
@@ -88,65 +88,6 @@
|
||||
"Currently editing": "Currently editing",
|
||||
"Currently viewing": "Currently viewing",
|
||||
"Viewed {{ timeAgo }} ago": "Viewed {{ timeAgo }} ago",
|
||||
"Insert column after": "Insert column after",
|
||||
"Insert column before": "Insert column before",
|
||||
"Insert row after": "Insert row after",
|
||||
"Insert row before": "Insert row before",
|
||||
"Align center": "Align center",
|
||||
"Align left": "Align left",
|
||||
"Align right": "Align right",
|
||||
"Bulleted list": "Bulleted list",
|
||||
"Todo list": "Task list",
|
||||
"Code block": "Code block",
|
||||
"Copied to clipboard": "Copied to clipboard",
|
||||
"Code": "Code",
|
||||
"Create link": "Create link",
|
||||
"Sorry, an error occurred creating the link": "Sorry, an error occurred creating the link",
|
||||
"Create a new doc": "Create a new doc",
|
||||
"Delete column": "Delete column",
|
||||
"Delete row": "Delete row",
|
||||
"Delete table": "Delete table",
|
||||
"Delete image": "Delete image",
|
||||
"Download image": "Download image",
|
||||
"Float left": "Float left",
|
||||
"Float right": "Float right",
|
||||
"Center large": "Center large",
|
||||
"Italic": "Italic",
|
||||
"Sorry, that link won’t work for this embed type": "Sorry, that link won’t work for this embed type",
|
||||
"Find or create a doc": "Find or create a doc",
|
||||
"Big heading": "Big heading",
|
||||
"Medium heading": "Medium heading",
|
||||
"Small heading": "Small heading",
|
||||
"Heading": "Heading",
|
||||
"Divider": "Divider",
|
||||
"Image": "Image",
|
||||
"Sorry, an error occurred uploading the image": "Sorry, an error occurred uploading the image",
|
||||
"Write a caption": "Write a caption",
|
||||
"Info": "Info",
|
||||
"Info notice": "Info notice",
|
||||
"Link": "Link",
|
||||
"Link copied to clipboard": "Link copied to clipboard",
|
||||
"Highlight": "Highlight",
|
||||
"Type '/' to insert": "Type '/' to insert",
|
||||
"Keep typing to filter": "Keep typing to filter",
|
||||
"No results": "No results",
|
||||
"Open link": "Open link",
|
||||
"Ordered list": "Ordered list",
|
||||
"Page break": "Page break",
|
||||
"Paste a link": "Paste a link",
|
||||
"Paste a {{service}} link…": "Paste a {{service}} link…",
|
||||
"Placeholder": "Placeholder",
|
||||
"Quote": "Quote",
|
||||
"Remove link": "Remove link",
|
||||
"Search or paste a link": "Search or paste a link",
|
||||
"Strikethrough": "Strikethrough",
|
||||
"Bold": "Bold",
|
||||
"Subheading": "Subheading",
|
||||
"Table": "Table",
|
||||
"Tip": "Tip",
|
||||
"Tip notice": "Tip notice",
|
||||
"Warning": "Warning",
|
||||
"Warning notice": "Warning notice",
|
||||
"Module failed to load": "Module failed to load",
|
||||
"Loading Failed": "Loading Failed",
|
||||
"Sorry, part of the application failed to load. This may be because it was updated since you opened the tab or because of a failed network request. Please try reloading.": "Sorry, part of the application failed to load. This may be because it was updated since you opened the tab or because of a failed network request. Please try reloading.",
|
||||
@@ -209,8 +150,68 @@
|
||||
"Export": "Export",
|
||||
"Integrations": "Integrations",
|
||||
"Installation": "Installation",
|
||||
"No results": "No results",
|
||||
"Previous page": "Previous page",
|
||||
"Next page": "Next page",
|
||||
"Insert column after": "Insert column after",
|
||||
"Insert column before": "Insert column before",
|
||||
"Insert row after": "Insert row after",
|
||||
"Insert row before": "Insert row before",
|
||||
"Align center": "Align center",
|
||||
"Align left": "Align left",
|
||||
"Align right": "Align right",
|
||||
"Bulleted list": "Bulleted list",
|
||||
"Todo list": "Task list",
|
||||
"Code block": "Code block",
|
||||
"Copied to clipboard": "Copied to clipboard",
|
||||
"Code": "Code",
|
||||
"Create link": "Create link",
|
||||
"Sorry, an error occurred creating the link": "Sorry, an error occurred creating the link",
|
||||
"Create a new doc": "Create a new doc",
|
||||
"Delete column": "Delete column",
|
||||
"Delete row": "Delete row",
|
||||
"Delete table": "Delete table",
|
||||
"Delete image": "Delete image",
|
||||
"Download image": "Download image",
|
||||
"Replace image": "Replace image",
|
||||
"Float left": "Float left",
|
||||
"Float right": "Float right",
|
||||
"Center large": "Center large",
|
||||
"Italic": "Italic",
|
||||
"Sorry, that link won’t work for this embed type": "Sorry, that link won’t work for this embed type",
|
||||
"Find or create a doc": "Find or create a doc",
|
||||
"Big heading": "Big heading",
|
||||
"Medium heading": "Medium heading",
|
||||
"Small heading": "Small heading",
|
||||
"Heading": "Heading",
|
||||
"Divider": "Divider",
|
||||
"Image": "Image",
|
||||
"Sorry, an error occurred uploading the image": "Sorry, an error occurred uploading the image",
|
||||
"Write a caption": "Write a caption",
|
||||
"Info": "Info",
|
||||
"Info notice": "Info notice",
|
||||
"Link": "Link",
|
||||
"Link copied to clipboard": "Link copied to clipboard",
|
||||
"Highlight": "Highlight",
|
||||
"Type '/' to insert": "Type '/' to insert",
|
||||
"Keep typing to filter": "Keep typing to filter",
|
||||
"Open link": "Open link",
|
||||
"Ordered list": "Ordered list",
|
||||
"Page break": "Page break",
|
||||
"Paste a link": "Paste a link",
|
||||
"Paste a {{service}} link…": "Paste a {{service}} link…",
|
||||
"Placeholder": "Placeholder",
|
||||
"Quote": "Quote",
|
||||
"Remove link": "Remove link",
|
||||
"Search or paste a link": "Search or paste a link",
|
||||
"Strikethrough": "Strikethrough",
|
||||
"Bold": "Bold",
|
||||
"Subheading": "Subheading",
|
||||
"Table": "Table",
|
||||
"Tip": "Tip",
|
||||
"Tip notice": "Tip notice",
|
||||
"Warning": "Warning",
|
||||
"Warning notice": "Warning notice",
|
||||
"Could not import file": "Could not import file",
|
||||
"Switch team": "Switch team",
|
||||
"Show path to document": "Show path to document",
|
||||
|
||||
Reference in New Issue
Block a user