Add 'Copy as Markdown' action
Remove smart quotes from Markdown export, closes #5303
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import copy from "copy-to-clipboard";
|
||||
import invariant from "invariant";
|
||||
import {
|
||||
DownloadIcon,
|
||||
@@ -24,10 +25,12 @@ import {
|
||||
PublishIcon,
|
||||
CommentIcon,
|
||||
GlobeIcon,
|
||||
CopyIcon,
|
||||
} from "outline-icons";
|
||||
import * as React from "react";
|
||||
import { toast } from "sonner";
|
||||
import { ExportContentType, TeamPreference } from "@shared/types";
|
||||
import MarkdownHelper from "@shared/utils/MarkdownHelper";
|
||||
import { getEventFiles } from "@shared/utils/files";
|
||||
import SharePopover from "~/scenes/Document/components/SharePopover";
|
||||
import DocumentDelete from "~/scenes/DocumentDelete";
|
||||
@@ -111,6 +114,23 @@ export const createDocumentFromTemplate = createAction({
|
||||
),
|
||||
});
|
||||
|
||||
export const copyDocumentAsMarkdown = createAction({
|
||||
name: ({ t }) => t("Copy as Markdown"),
|
||||
section: DocumentSection,
|
||||
icon: <CopyIcon />,
|
||||
keywords: "clipboard",
|
||||
visible: ({ activeDocumentId }) => !!activeDocumentId,
|
||||
perform: ({ stores, activeDocumentId, t }) => {
|
||||
const document = activeDocumentId
|
||||
? stores.documents.get(activeDocumentId)
|
||||
: undefined;
|
||||
if (document) {
|
||||
copy(MarkdownHelper.toMarkdown(document));
|
||||
toast.success(t("Markdown copied to clipboard"));
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
export const createNestedDocument = createAction({
|
||||
name: ({ t }) => t("New nested document"),
|
||||
analyticsName: "New document",
|
||||
@@ -889,6 +909,7 @@ export const rootDocumentActions = [
|
||||
deleteDocument,
|
||||
importDocument,
|
||||
downloadDocument,
|
||||
copyDocumentAsMarkdown,
|
||||
starDocument,
|
||||
unstarDocument,
|
||||
publishDocument,
|
||||
|
||||
@@ -10,6 +10,7 @@ import { Transaction } from "sequelize";
|
||||
import * as Y from "yjs";
|
||||
import textBetween from "@shared/editor/lib/textBetween";
|
||||
import { AttachmentPreset } from "@shared/types";
|
||||
import MarkdownHelper from "@shared/utils/MarkdownHelper";
|
||||
import {
|
||||
getCurrentDateAsString,
|
||||
getCurrentDateTimeAsString,
|
||||
@@ -88,13 +89,7 @@ export default class DocumentHelper {
|
||||
* @returns The document title and content as a Markdown string
|
||||
*/
|
||||
static toMarkdown(document: Document | Revision) {
|
||||
const text = document.text.replace(/\n\\\n/g, "\n\n");
|
||||
|
||||
if (document.version) {
|
||||
return `# ${document.title}\n\n${text}`;
|
||||
}
|
||||
|
||||
return text;
|
||||
return MarkdownHelper.toMarkdown(document);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -536,13 +536,8 @@ router.post(
|
||||
contentType = "text/markdown";
|
||||
content = DocumentHelper.toMarkdown(document);
|
||||
} else {
|
||||
contentType = "application/json";
|
||||
content = DocumentHelper.toMarkdown(document);
|
||||
}
|
||||
|
||||
if (contentType === "application/json") {
|
||||
ctx.body = {
|
||||
data: content,
|
||||
data: DocumentHelper.toMarkdown(document),
|
||||
};
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
"Open document": "Open document",
|
||||
"New document": "New document",
|
||||
"New from template": "New from template",
|
||||
"Copy as Markdown": "Copy as Markdown",
|
||||
"Markdown copied to clipboard": "Markdown copied to clipboard",
|
||||
"New nested document": "New nested document",
|
||||
"Publish": "Publish",
|
||||
"Published {{ documentName }}": "Published {{ documentName }}",
|
||||
|
||||
29
shared/utils/MarkdownHelper.ts
Normal file
29
shared/utils/MarkdownHelper.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
interface DocumentInterface {
|
||||
emoji?: string | null;
|
||||
title: string;
|
||||
text: string;
|
||||
}
|
||||
|
||||
export default class MarkdownHelper {
|
||||
/**
|
||||
* Returns the document as cleaned Markdown for export.
|
||||
*
|
||||
* @param document The document or revision to convert
|
||||
* @returns The document title and content as a Markdown string
|
||||
*/
|
||||
static toMarkdown(document: DocumentInterface) {
|
||||
const text = document.text
|
||||
.replace(/\n\\\n/g, "\n\n")
|
||||
.replace(/“/g, '"')
|
||||
.replace(/”/g, '"')
|
||||
.replace(/‘/g, "'")
|
||||
.replace(/’/g, "'")
|
||||
.trim();
|
||||
|
||||
const title = `${document.emoji ? document.emoji + " " : ""}${
|
||||
document.title
|
||||
}`;
|
||||
|
||||
return `# ${title}\n\n${text}`;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user