More fixes related to #363

pull/612/head
Zef Hemel 2023-12-19 17:55:11 +01:00
parent a5c7405a35
commit 30436d97ea
9 changed files with 70 additions and 31 deletions

View File

@ -1,6 +1,7 @@
import { import {
cleanPageRef, cleanPageRef,
federatedPathToUrl, federatedPathToUrl,
resolveAttachmentPath,
resolvePath, resolvePath,
rewritePageRefs, rewritePageRefs,
} from "$sb/lib/resolve.ts"; } from "$sb/lib/resolve.ts";
@ -90,4 +91,22 @@ This is a [[!silverbullet.md/local link]] and [[!silverbullet.md/local link|with
rewrittenText, rewrittenText,
`This is a [[local link]] and [[local link|with alias]].`, `This is a [[local link]] and [[local link|with alias]].`,
); );
assertEquals("test.jpg", resolveAttachmentPath("test", "test.jpg"));
assertEquals(
"folder/test.jpg",
resolveAttachmentPath("folder/test", "test.jpg"),
);
assertEquals(
"test.jpg",
resolveAttachmentPath("folder/test", "/test.jpg"),
);
assertEquals(
"https://silverbullet.md/something/test.jpg",
resolveAttachmentPath("!silverbullet.md/something/bla", "test.jpg"),
);
assertEquals(
"https://silverbullet.md/test.jpg",
resolveAttachmentPath("!silverbullet.md/something/bla", "/test.jpg"),
);
}); });

View File

@ -16,7 +16,24 @@ export function resolvePath(
} }
} }
export function resolveAttachmentPath(
currentPage: string,
pathToResolve: string,
): string {
const folder = folderName(currentPage);
if (folder && !pathToResolve.startsWith("/")) {
pathToResolve = folder + "/" + pathToResolve;
}
if (pathToResolve.startsWith("/")) {
pathToResolve = pathToResolve.slice(1);
}
return federatedPathToUrl(resolvePath(currentPage, pathToResolve));
}
export function federatedPathToUrl(path: string): string { export function federatedPathToUrl(path: string): string {
if (!path.startsWith("!")) {
return path;
}
path = path.substring(1); path = path.substring(1);
if (path.startsWith("localhost")) { if (path.startsWith("localhost")) {
path = "http://" + path; path = "http://" + path;
@ -101,3 +118,7 @@ export function cleanPageRef(pageRef: string) {
return pageRef; return pageRef;
} }
} }
export function folderName(path: string) {
return path.split("/").slice(0, -1).join("/");
}

View File

@ -7,7 +7,7 @@ import {
nodeAtPos, nodeAtPos,
ParseTree, ParseTree,
} from "$sb/lib/tree.ts"; } from "$sb/lib/tree.ts";
import { resolvePath } from "$sb/lib/resolve.ts"; import { resolveAttachmentPath, resolvePath } from "$sb/lib/resolve.ts";
async function actionClickOrActionEnter( async function actionClickOrActionEnter(
mdTree: ParseTree | null, mdTree: ParseTree | null,
@ -79,7 +79,9 @@ async function actionClickOrActionEnter(
return editor.flashNotification("Empty link, ignoring", "error"); return editor.flashNotification("Empty link, ignoring", "error");
} }
if (url.indexOf("://") === -1 && !url.startsWith("mailto:")) { if (url.indexOf("://") === -1 && !url.startsWith("mailto:")) {
return editor.openUrl(resolvePath(currentPage, decodeURI(url))); return editor.openUrl(
resolveAttachmentPath(currentPage, decodeURI(url)),
);
} else { } else {
await editor.openUrl(url); await editor.openUrl(url);
} }
@ -93,8 +95,11 @@ async function actionClickOrActionEnter(
try { try {
const args = argsText ? JSON.parse(`[${argsText}]`) : []; const args = argsText ? JSON.parse(`[${argsText}]`) : [];
await system.invokeCommand(commandName, args); await system.invokeCommand(commandName, args);
} catch(e: any) { } catch (e: any) {
await editor.flashNotification(`Error parsing command link arguments: ${e.message}`, "error"); await editor.flashNotification(
`Error parsing command link arguments: ${e.message}`,
"error",
);
} }
break; break;
} }

View File

@ -1,8 +1,7 @@
import { asset, clientStore, editor, markdown, system } from "$sb/syscalls.ts"; import { asset, clientStore, editor, markdown, system } from "$sb/syscalls.ts";
import { renderMarkdownToHtml } from "./markdown_render.ts"; import { renderMarkdownToHtml } from "./markdown_render.ts";
import { resolvePath } from "$sb/lib/resolve.ts"; import { resolveAttachmentPath } from "$sb/lib/resolve.ts";
import { expandCodeWidgets } from "./api.ts"; import { expandCodeWidgets } from "./api.ts";
import { folderName, resolve } from "../../common/path.ts";
export async function updateMarkdownPreview() { export async function updateMarkdownPreview() {
if (!(await clientStore.get("enableMarkdownPreview"))) { if (!(await clientStore.get("enableMarkdownPreview"))) {
@ -19,14 +18,9 @@ export async function updateMarkdownPreview() {
const html = renderMarkdownToHtml(mdTree, { const html = renderMarkdownToHtml(mdTree, {
smartHardBreak: true, smartHardBreak: true,
annotationPositions: true, annotationPositions: true,
translateUrls: (url, type) => { translateUrls: (url) => {
if (!url.includes("://")) { if (!url.includes("://")) {
if (type === "image" && !url.startsWith("/")) { url = resolveAttachmentPath(currentPage, decodeURI(url));
// Make relative to current folder
url = resolve(folderName(currentPage), decodeURI(url));
} else if (type === "link") { // link
url = resolvePath(currentPage, decodeURI(url), true);
}
} }
return url; return url;
}, },

View File

@ -16,7 +16,7 @@ import { fencedCodePlugin } from "./fenced_code.ts";
export function cleanModePlugins(editor: Client) { export function cleanModePlugins(editor: Client) {
return [ return [
linkPlugin(), linkPlugin(editor),
directivePlugin(), directivePlugin(),
blockquotePlugin(), blockquotePlugin(),
admonitionPlugin(editor), admonitionPlugin(editor),

View File

@ -8,8 +8,7 @@ import {
import { decoratorStateField } from "./util.ts"; import { decoratorStateField } from "./util.ts";
import type { Client } from "../client.ts"; import type { Client } from "../client.ts";
import { resolvePath } from "$sb/lib/resolve.ts"; import { resolveAttachmentPath, resolvePath } from "$sb/lib/resolve.ts";
import { folderName, resolve } from "../../common/path.ts";
class InlineImageWidget extends WidgetType { class InlineImageWidget extends WidgetType {
constructor( constructor(
@ -77,11 +76,8 @@ export function inlineImagesPlugin(client: Client) {
let url = imageRexexResult.groups.url; let url = imageRexexResult.groups.url;
const title = imageRexexResult.groups.title; const title = imageRexexResult.groups.title;
const currentPage = client.currentPage!;
const currentFolder = folderName(currentPage);
if (url.indexOf("://") === -1 && !url.startsWith("/")) { if (url.indexOf("://") === -1 && !url.startsWith("/")) {
url = resolve(currentFolder, decodeURI(url)); url = resolveAttachmentPath(client.currentPage!, decodeURI(url));
} }
widgets.push( widgets.push(
Decoration.widget({ Decoration.widget({

View File

@ -1,3 +1,5 @@
import { resolveAttachmentPath } from "$sb/lib/resolve.ts";
import { Client } from "../client.ts";
import { Decoration, syntaxTree } from "../deps.ts"; import { Decoration, syntaxTree } from "../deps.ts";
import { import {
decoratorStateField, decoratorStateField,
@ -5,7 +7,7 @@ import {
isCursorInRange, isCursorInRange,
} from "./util.ts"; } from "./util.ts";
export function linkPlugin() { export function linkPlugin(client: Client) {
return decoratorStateField((state) => { return decoratorStateField((state) => {
const widgets: any[] = []; const widgets: any[] = [];
@ -31,7 +33,14 @@ export function linkPlugin() {
return; return;
} }
const cleanAnchor = anchorPart.substring(1); // cut off the initial [ const cleanAnchor = anchorPart.substring(1); // cut off the initial [
const cleanLink = linkPart.substring(0, linkPart.length - 1); // cut off the final ) let cleanLink = linkPart.substring(0, linkPart.length - 1); // cut off the final )
if (!cleanLink.includes("://")) {
cleanLink = resolveAttachmentPath(
client.currentPage!,
decodeURI(cleanLink),
);
}
// Hide the start [ // Hide the start [
widgets.push( widgets.push(

View File

@ -9,8 +9,7 @@ import { renderMarkdownToHtml } from "../../plugs/markdown/markdown_render.ts";
import { ParseTree } from "$sb/lib/tree.ts"; import { ParseTree } from "$sb/lib/tree.ts";
import { lezerToParseTree } from "../../common/markdown_parser/parse_tree.ts"; import { lezerToParseTree } from "../../common/markdown_parser/parse_tree.ts";
import type { Client } from "../client.ts"; import type { Client } from "../client.ts";
import { resolvePath } from "$sb/lib/resolve.ts"; import { resolveAttachmentPath } from "$sb/lib/resolve.ts";
import { folderName, resolve } from "../../common/path.ts";
class TableViewWidget extends WidgetType { class TableViewWidget extends WidgetType {
constructor( constructor(
@ -39,14 +38,9 @@ class TableViewWidget extends WidgetType {
// Annotate every element with its position so we can use it to put // Annotate every element with its position so we can use it to put
// the cursor there when the user clicks on the table. // the cursor there when the user clicks on the table.
annotationPositions: true, annotationPositions: true,
translateUrls: (url, type) => { translateUrls: (url) => {
if (!url.includes("://")) { if (!url.includes("://")) {
if (type === "image" && !url.startsWith("/")) { url = resolveAttachmentPath(this.editor.currentPage!, decodeURI(url));
// Make relative to current folder
url = resolve(folderName(this.editor.currentPage!), decodeURI(url));
} else if (type === "link") { // link
url = resolvePath(this.editor.currentPage!, decodeURI(url), true);
}
} }
return url; return url;

View File

@ -11,6 +11,7 @@ release.
* A new `silverbullet sync` command to [[Sync]] spaces (early days, use with caution) * A new `silverbullet sync` command to [[Sync]] spaces (early days, use with caution)
* Technical refactoring in preparation for multi-tenant deployment support (allowing you to run a single SB instance and serve multiple spaces and users at the same time) * Technical refactoring in preparation for multi-tenant deployment support (allowing you to run a single SB instance and serve multiple spaces and users at the same time)
* Lazy everything: plugs are now lazily loaded (after a first load, manifests are cached). On the server side, a whole lot of infrastructure is now only booted once the first HTTP request comes in * Lazy everything: plugs are now lazily loaded (after a first load, manifests are cached). On the server side, a whole lot of infrastructure is now only booted once the first HTTP request comes in
* Non-external URLs used in links (`[page](url)` syntax and `![alt](url)` image syntax) are now relative to the page's folder, unless their URL starts with a `/` then they're relative to the space root.
--- ---