rhino-editor
Version:
A custom element wrapped rich text editor
205 lines (200 loc) • 5.57 kB
JavaScript
import {
AttachmentUploadCompleteEvent,
AttachmentUploadSucceedEvent
} from "./chunk-SIPZ6BV2.js";
import {
LOADING_STATES,
toMemorySize
} from "./chunk-KCKEIVYI.js";
// src/internal/uuidv4.ts
function uuidv4() {
const crypto = window.crypto || window.msCrypto;
return ("10000000-1000-4000-8000" + -1e11).replace(
/[018]/g,
(c) => (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
);
}
// src/internal/to-default-caption.ts
function toDefaultCaption({
fileName,
fileSize
}) {
if (!fileName || !fileSize) {
return "";
}
return `${fileName} \xB7 ${toMemorySize(Number(fileSize))}`;
}
// src/exports/attachment-manager.ts
var AttachmentManager = class _AttachmentManager {
static get previewableRegex() {
return /^image(\/(gif|png|jpe?g)|$)/;
}
static isPreviewable(str) {
return (this || _AttachmentManager).previewableRegex.test(str);
}
constructor(obj, editorView) {
this.editorView = editorView;
this.attributes = {
attachmentId: uuidv4(),
content: null,
imageId: uuidv4(),
sgid: null,
url: null,
...obj
};
this.attributes.previewable = this.isPreviewable;
}
setUploadProgress(progress) {
if (this.content == null) {
this.setNodeMarkup({
progress,
loadingState: progress >= 100 ? LOADING_STATES.success : LOADING_STATES.loading
});
}
}
setAttributes(obj) {
this.attributes = Object.assign(this.attributes, obj);
if (obj.content) {
this.setNodeMarkup({
sgid: this.attributes.sgid,
content: this.attributes.content,
previewable: this.isPreviewable
});
this.handleSuccess();
return;
}
if (!obj.url) {
return;
}
if (this.isPreviewable) {
const image = new Image();
image.setAttribute("src", obj.url);
image.onload = () => {
this.attributes.width = image.naturalWidth;
this.attributes.height = image.naturalHeight;
this.setNodeMarkup({
sgid: this.attributes.sgid,
url: this.attributes.url,
src: this.attributes.url,
href: this.attributes.url + "?content-disposition=attachment",
width: this.attributes.width,
height: this.attributes.height,
contentType: this.contentType,
previewable: this.isPreviewable
});
image.remove();
this.handleSuccess();
};
return;
}
this.setNodeMarkup({
sgid: this.attributes.sgid,
url: this.attributes.url,
contentType: this.contentType,
previewable: this.isPreviewable
});
this.handleSuccess();
}
handleSuccess() {
this.setUploadProgress(100);
const upload = this.directUpload;
if (upload) {
upload.element.dispatchEvent(new AttachmentUploadSucceedEvent(upload));
upload.element.dispatchEvent(new AttachmentUploadCompleteEvent(upload));
}
}
/**
* Helper function to set the markup for an attachment. We map a uuid to the "attachmentId"
* of the TipTap node to guarantee we're targeting the right one.
*/
setNodeMarkup(obj) {
const view = this.editorView;
if (view == null) return;
view.state.doc.descendants((descendantNode, position) => {
if (descendantNode.attrs.attachmentId === this.attachmentId) {
view.dispatch(
view.state.tr.setNodeMarkup(position, void 0, {
...descendantNode.attrs,
...obj
})
);
}
});
}
/**
* This is an internal ID used for finding newly attached attachments in the TipTap editor.
* This is used primarily for direct upload purposes.
* This generally won't exist when a node is recreated from you database.
*/
get attachmentId() {
return this.attributes.attachmentId;
}
/**
* This is an internal ID used for finding newly attached images in the TipTap editor.
* This is used primarily for direct upload purposes.
* This generally won't exist when a node is recreated from you database.
*/
get imageId() {
return this.attributes.imageId;
}
/**
* `src` (when present) always maps to a URL.createObjectURL.
*/
get src() {
return this.attributes.src;
}
set src(val) {
this.attributes.src = val;
}
get sgid() {
return this.attributes.sgid;
}
get file() {
return this.attributes.file;
}
get contentType() {
return this.attributes.contentType || this.file?.type;
}
get fileName() {
return this.attributes.fileName || this.file?.name;
}
get fileSize() {
return this.attributes.fileSize || this.file?.size;
}
/**
* This field is populated by the old Trix custom attachment API and denotes if we're using a custom
* attachment.
*/
get content() {
return this.attributes.content;
}
set content(val) {
this.attributes.content = val;
}
get height() {
return this.attributes.height;
}
get width() {
return this.attributes.width;
}
get isPreviewable() {
const isPreviewable = this.constructor.isPreviewable;
const contentType = this.contentType;
return isPreviewable(contentType || "");
}
get caption() {
const defaultCaption = toDefaultCaption({
fileName: this.attributes.fileName,
fileSize: this.attributes.fileSize
});
if (this.isPreviewable) {
return defaultCaption;
}
return this.attributes.caption || defaultCaption || "";
}
};
export {
toDefaultCaption,
AttachmentManager
};
//# sourceMappingURL=chunk-KSVK26OY.js.map