From 104b6356dff1ce4abab33a9b5c4285df745691d8 Mon Sep 17 00:00:00 2001 From: Zef Hemel Date: Sat, 6 Jul 2024 15:45:04 +0200 Subject: [PATCH] Fixes #902 --- web/cm_plugins/inline_image.ts | 69 ++++++++++++++++++++++++---------- 1 file changed, 49 insertions(+), 20 deletions(-) diff --git a/web/cm_plugins/inline_image.ts b/web/cm_plugins/inline_image.ts index b25e5733..79d84021 100644 --- a/web/cm_plugins/inline_image.ts +++ b/web/cm_plugins/inline_image.ts @@ -4,22 +4,25 @@ import { Decoration, WidgetType } from "@codemirror/view"; import { decoratorStateField } from "./util.ts"; import type { Client } from "../client.ts"; import { isLocalPath, resolvePath } from "$sb/lib/resolve.ts"; -import { mdLinkRegex, wikiLinkRegex } from "$common/markdown_parser/parser.ts"; + +type ImageDimensions = { + width?: number; + height?: number; +}; class InlineImageWidget extends WidgetType { constructor( readonly url: string, readonly title: string, - readonly dim: string | null, + readonly dim: ImageDimensions | undefined, readonly client: Client, ) { super(); - // console.log("Creating widget", url); } eq(other: InlineImageWidget) { return other.url === this.url && other.title === this.title && - other.dim === this.dim; + JSON.stringify(other.dim) === JSON.stringify(this.dim); } get estimatedHeight(): number { @@ -28,12 +31,6 @@ class InlineImageWidget extends WidgetType { return cachedHeight; } - private getDimensions(dimensionsToParse: string) { - const [, width, widthUnit = "px", height, heightUnit = "px"] = - dimensionsToParse.match(/(\d*)(\S*?x?)??[xX](\d*)(.*)?/) ?? []; - return { width, widthUnit, height, heightUnit }; - } - toDOM() { const img = document.createElement("img"); // console.log("Creating DOM", this.url); @@ -52,11 +49,8 @@ class InlineImageWidget extends WidgetType { img.style.display = "block"; img.className = "sb-inline-img"; if (this.dim) { - const { width, widthUnit, height, heightUnit } = this.getDimensions( - this.dim, - ); - img.style.height = height ? `${height}${heightUnit}` : ""; - img.style.width = width ? `${width}${widthUnit}` : ""; + img.style.height = this.dim.height ? `${this.dim.height}px` : ""; + img.style.width = this.dim.width ? `${this.dim.width}px` : ""; } else if (cachedImageHeight > 0) { img.height = cachedImageHeight; } @@ -65,6 +59,40 @@ class InlineImageWidget extends WidgetType { } } +// Parse an alias, possibly containing image dimensions into an object +// Formats supported: "alias", "alias|100", "alias|100x200", "100", "100x200" +function parseAlias( + text: string, +): { alias?: string; dim?: ImageDimensions } { + let alias: string | undefined; + let dim: ImageDimensions | undefined; + if (text.includes("|")) { + const [aliasPart, dimPart] = text.split("|"); + alias = aliasPart; + const [width, height] = dimPart.split("x"); + dim = {}; + if (width) { + dim.width = parseInt(width); + } + if (height) { + dim.height = parseInt(height); + } + } else if (/^[x\d]/.test(text)) { + const [width, height] = text.split("x"); + dim = {}; + if (width) { + dim.width = parseInt(width); + } + if (height) { + dim.height = parseInt(height); + } + } else { + alias = text; + } + + return { alias, dim }; +} + export function inlineImagesPlugin(client: Client) { return decoratorStateField((state: EditorState) => { const widgets: Range[] = []; @@ -76,7 +104,8 @@ export function inlineImagesPlugin(client: Client) { } const text = state.sliceDoc(node.from, node.to); - let [url, alias, dim]: (string | null)[] = [null, null, null]; + let [url, alias]: (string | null)[] = [null, null]; + let dim: ImageDimensions | undefined; let match: RegExpExecArray | null; if ((match = /!?\[([^\]]*)\]\((.+)\)/g.exec(text))) { [/* fullMatch */, alias, url] = match; @@ -90,11 +119,11 @@ export function inlineImagesPlugin(client: Client) { } if (alias) { - const dimReg = /\d*[^\|\s]*?[xX]\d*[^\|\s]*/.exec(alias); - if (dimReg) { - dim = dimReg[0]; - alias = alias.replace(dim, "").replace("|", ""); + const { alias: parsedAlias, dim: parsedDim } = parseAlias(alias); + if (parsedAlias) { + alias = parsedAlias; } + dim = parsedDim; } else { alias = ""; }