More fixes related to #363
parent
a5c7405a35
commit
30436d97ea
|
@ -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"),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
|
@ -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("/");
|
||||||
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
},
|
},
|
||||||
|
|
|
@ -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),
|
||||||
|
|
|
@ -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({
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue