mirror of
https://github.com/outline/outline.git
synced 2026-06-13 11:25:03 +03:00
ac06a06a66
* wip * wip * tsc * lint * Detect imported Draw.io * Add empty diagram placeholder * fix: Do not close editor on save fix: Account for nodes moving / multiplayer * fix: Reduce image menu for diagrams * Add custom server settings page * refactor * sp * Move edit button
86 lines
2.2 KiB
TypeScript
86 lines
2.2 KiB
TypeScript
import { Node } from "prosemirror-model";
|
|
import { isCode } from "./isCode";
|
|
import { EditorView } from "prosemirror-view";
|
|
import { sanitizeUrl } from "@shared/utils/urls";
|
|
|
|
export abstract class LightboxImage {
|
|
public pos: number;
|
|
public src: string;
|
|
public alt: string;
|
|
public source: string;
|
|
|
|
protected element: Element;
|
|
|
|
constructor() {}
|
|
|
|
public abstract getElement(): Element | null | undefined;
|
|
}
|
|
|
|
class LightboxRegularImage extends LightboxImage {
|
|
constructor(view: EditorView, pos: number) {
|
|
super();
|
|
this.pos = pos;
|
|
const node = view.state.doc.nodeAt(pos);
|
|
this.src = sanitizeUrl(node?.attrs.src) ?? "";
|
|
this.alt = node?.attrs.alt ?? "";
|
|
this.source = node?.attrs.source;
|
|
this.element = view.nodeDOM(pos) as HTMLSpanElement;
|
|
}
|
|
|
|
getElement() {
|
|
return this.element.querySelector("img");
|
|
}
|
|
}
|
|
|
|
class LightboxMermaidImage extends LightboxImage {
|
|
constructor(view: EditorView, pos: number) {
|
|
super();
|
|
this.element = view.nodeDOM(pos) as HTMLDivElement;
|
|
this.pos = pos;
|
|
this.src = this.svgToSrc(this.extractSvg());
|
|
this.alt = "";
|
|
}
|
|
|
|
private svgToSrc(svg: string): string {
|
|
return `data:image/svg+xml,${encodeURIComponent(svg)}`;
|
|
}
|
|
|
|
private extractSvg(): string {
|
|
const mermaidWrapper = this.element.nextElementSibling;
|
|
if (!mermaidWrapper) {
|
|
return "";
|
|
}
|
|
const svg = mermaidWrapper.firstElementChild;
|
|
if (!svg || !(svg instanceof SVGElement)) {
|
|
return "";
|
|
}
|
|
|
|
return svg.outerHTML;
|
|
}
|
|
|
|
getElement() {
|
|
return this.element.nextElementSibling?.firstElementChild;
|
|
}
|
|
}
|
|
|
|
export class LightboxImageFactory {
|
|
static createLightboxImage(view: EditorView, pos: number): LightboxImage {
|
|
const node = view.state.doc.nodeAt(pos)!;
|
|
if (isImage(node)) {
|
|
return new LightboxRegularImage(view, pos);
|
|
}
|
|
|
|
if (isMermaid(node)) {
|
|
return new LightboxMermaidImage(view, pos);
|
|
}
|
|
|
|
throw new Error("Unsupported node type for LightboxImage");
|
|
}
|
|
}
|
|
|
|
const isImage = (node: Node) => node.type.name === "image";
|
|
const isMermaid = (node: Node) =>
|
|
isCode(node) && node.attrs.language === "mermaidjs";
|
|
|
|
export const isLightboxNode = (node: Node) => isImage(node) || isMermaid(node);
|