Files
outline/shared/editor/rules/attachments.ts
Tom Moor 631d600920 feat: File attachments (#3031)
* stash

* refactor, working in non-collab + collab editor

* attachment styling

* Avoid crypto require in browser

* AttachmentIcon, handling unknown types

* Do not allow attachment creation for file sizes over limit

* Allow image as file attachment

* Upload placeholder styling

* lint

* Refactor: Do not use placeholder for file attachmentuploads

* Add loading spinner

* fix: Extra paragraphs around attachments on insert

* Bump editor

* fix build error

* Remove attachment placeholder when upload fails

* Remove unused styles

* fix: Attachments on shared pages

* Merge fixes
2022-03-06 13:58:58 -08:00

83 lines
2.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import MarkdownIt from "markdown-it";
import Token from "markdown-it/lib/token";
import env from "../../env";
function isParagraph(token: Token) {
return token.type === "paragraph_open";
}
function isInline(token: Token) {
return token.type === "inline";
}
function isLinkOpen(token: Token) {
return token.type === "link_open";
}
function isLinkClose(token: Token) {
return token.type === "link_close";
}
function isAttachment(token: Token) {
const href = token.attrGet("href");
return (
href?.includes("attachments.redirect") ||
href?.startsWith(env.AWS_S3_UPLOAD_BUCKET_URL)
);
}
export default function linksToAttachments(md: MarkdownIt) {
md.core.ruler.after("breaks", "attachments", (state) => {
const tokens = state.tokens;
let insideLink;
for (let i = 0; i < tokens.length - 1; i++) {
// once we find an inline token look through it's children for links
if (isInline(tokens[i]) && isParagraph(tokens[i - 1])) {
const tokenChildren = tokens[i].children || [];
for (let j = 0; j < tokenChildren.length - 1; j++) {
const current = tokenChildren[j];
if (!current) {
continue;
}
if (isLinkOpen(current)) {
insideLink = current;
continue;
}
if (isLinkClose(current)) {
insideLink = null;
continue;
}
// of hey, we found a link lets check to see if it should be
// converted to a file attachment
if (insideLink && isAttachment(insideLink)) {
const { content } = current;
// convert to attachment token
const token = new Token("attachment", "a", 0);
token.attrSet("href", insideLink.attrGet("href") || "");
const parts = content.split(" ");
const size = parts.pop();
const title = parts.join(" ");
token.attrSet("size", size || "0");
token.attrSet("title", title);
// delete the inline link this makes the assumption that the
// attachment is the only thing in the para.
tokens.splice(i - 1, 3, token);
insideLink = null;
break;
}
}
}
}
return false;
});
}