mirror of
https://github.com/Nystik-gh/ignis.git
synced 2026-06-17 04:35:53 +00:00
fix image urls, fix context menu
This commit is contained in:
@@ -24,20 +24,39 @@ export function createFsPromises(metadataCache, contentCache, transport) {
|
||||
if (meta && meta.type === "file") {
|
||||
return [];
|
||||
}
|
||||
// If path not in cache at all (and not root), it doesn't exist
|
||||
if (!meta && path && path !== "/" && path !== ".") {
|
||||
const e = new Error(
|
||||
`ENOENT: no such file or directory, scandir '${path}'`,
|
||||
);
|
||||
e.code = "ENOENT";
|
||||
throw e;
|
||||
}
|
||||
// Serve from metadata cache
|
||||
const entries = metadataCache.readdir(path);
|
||||
if (entries.length > 0) {
|
||||
return entries.map((e) => e.name);
|
||||
}
|
||||
// Fallback to server
|
||||
const serverEntries = await transport.readdir(path);
|
||||
return serverEntries.map((e) => e.name);
|
||||
return entries.map((e) => e.name);
|
||||
},
|
||||
|
||||
async readFile(path, encoding) {
|
||||
if (typeof encoding === "object") encoding = encoding?.encoding;
|
||||
const wantText = encoding === "utf8" || encoding === "utf-8";
|
||||
|
||||
// Short-circuit: reading a directory is an error
|
||||
const meta = metadataCache.get(path);
|
||||
if (meta && meta.type === "directory") {
|
||||
const e = new Error("EISDIR: illegal operation on a directory, read");
|
||||
e.code = "EISDIR";
|
||||
throw e;
|
||||
}
|
||||
// Short-circuit: file not in metadata cache → doesn't exist
|
||||
if (!meta && path) {
|
||||
const e = new Error(
|
||||
`ENOENT: no such file or directory, open '${path}'`,
|
||||
);
|
||||
e.code = "ENOENT";
|
||||
throw e;
|
||||
}
|
||||
|
||||
// Check content cache
|
||||
const cached = contentCache.get(path);
|
||||
if (cached !== null) {
|
||||
@@ -142,7 +161,11 @@ export function createFsPromises(metadataCache, contentCache, transport) {
|
||||
|
||||
async access(path) {
|
||||
if (metadataCache.has(path)) return;
|
||||
await transport.access(path);
|
||||
const e = new Error(
|
||||
`ENOENT: no such file or directory, access '${path}'`,
|
||||
);
|
||||
e.code = "ENOENT";
|
||||
throw e;
|
||||
},
|
||||
|
||||
async realpath(path) {
|
||||
|
||||
@@ -10,8 +10,10 @@ export function createFsSync(metadataCache, contentCache, transport) {
|
||||
statSync(path) {
|
||||
const stat = metadataCache.toStat(path);
|
||||
if (!stat) {
|
||||
const err = new Error(`ENOENT: no such file or directory, stat '${path}'`);
|
||||
err.code = 'ENOENT';
|
||||
const err = new Error(
|
||||
`ENOENT: no such file or directory, stat '${path}'`,
|
||||
);
|
||||
err.code = "ENOENT";
|
||||
throw err;
|
||||
}
|
||||
return stat;
|
||||
@@ -19,39 +21,52 @@ export function createFsSync(metadataCache, contentCache, transport) {
|
||||
|
||||
accessSync(path, mode) {
|
||||
if (!metadataCache.has(path)) {
|
||||
const err = new Error(`ENOENT: no such file or directory, access '${path}'`);
|
||||
err.code = 'ENOENT';
|
||||
const err = new Error(
|
||||
`ENOENT: no such file or directory, access '${path}'`,
|
||||
);
|
||||
err.code = "ENOENT";
|
||||
throw err;
|
||||
}
|
||||
},
|
||||
|
||||
readFileSync(path, encoding) {
|
||||
if (typeof encoding === 'object') encoding = encoding?.encoding;
|
||||
if (typeof encoding === "object") encoding = encoding?.encoding;
|
||||
|
||||
// Short-circuit: reading a directory is an error
|
||||
const meta = metadataCache.get(path);
|
||||
if (meta && meta.type === "directory") {
|
||||
const e = new Error("EISDIR: illegal operation on a directory, read");
|
||||
e.code = "EISDIR";
|
||||
throw e;
|
||||
}
|
||||
|
||||
// Try content cache first
|
||||
const cached = contentCache.get(path);
|
||||
if (cached !== null) {
|
||||
if (encoding === 'utf8' || encoding === 'utf-8') {
|
||||
return typeof cached === 'string' ? cached : new TextDecoder().decode(cached);
|
||||
if (encoding === "utf8" || encoding === "utf-8") {
|
||||
return typeof cached === "string"
|
||||
? cached
|
||||
: new TextDecoder().decode(cached);
|
||||
}
|
||||
return cached;
|
||||
}
|
||||
|
||||
// Fallback: synchronous XHR
|
||||
console.warn('[shim:fs] readFileSync cache miss, using sync XHR:', path);
|
||||
console.warn("[shim:fs] readFileSync cache miss, using sync XHR:", path);
|
||||
const data = transport.readFileSync(path, encoding);
|
||||
contentCache.set(path, data);
|
||||
return data;
|
||||
},
|
||||
|
||||
writeFileSync(path, data, encoding) {
|
||||
if (typeof encoding === 'object') encoding = encoding?.encoding;
|
||||
if (typeof encoding === "object") encoding = encoding?.encoding;
|
||||
|
||||
// Write to cache immediately (sync return)
|
||||
contentCache.set(path, data);
|
||||
const size = typeof data === 'string' ? data.length : (data.byteLength || 0);
|
||||
const size =
|
||||
typeof data === "string" ? data.length : data.byteLength || 0;
|
||||
metadataCache.set(path, {
|
||||
type: 'file',
|
||||
type: "file",
|
||||
size,
|
||||
mtime: Date.now(),
|
||||
ctime: metadataCache.get(path)?.ctime || Date.now(),
|
||||
@@ -59,7 +74,11 @@ export function createFsSync(metadataCache, contentCache, transport) {
|
||||
|
||||
// Fire-and-forget async send to server
|
||||
transport.writeFile(path, data, encoding).catch((e) => {
|
||||
console.error('[shim:fs] writeFileSync background save failed:', path, e);
|
||||
console.error(
|
||||
"[shim:fs] writeFileSync background save failed:",
|
||||
path,
|
||||
e,
|
||||
);
|
||||
});
|
||||
},
|
||||
|
||||
@@ -67,15 +86,21 @@ export function createFsSync(metadataCache, contentCache, transport) {
|
||||
contentCache.delete(path);
|
||||
metadataCache.delete(path);
|
||||
|
||||
// Fire-and-forget
|
||||
// Fire-and-forget - suppress ENOENT (file already gone, e.g. .OBSIDIANTEST race)
|
||||
transport.unlink(path).catch((e) => {
|
||||
console.error('[shim:fs] unlinkSync background delete failed:', path, e);
|
||||
if (e.code !== "ENOENT") {
|
||||
console.error(
|
||||
"[shim:fs] unlinkSync background delete failed:",
|
||||
path,
|
||||
e,
|
||||
);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
readdirSync(path) {
|
||||
const entries = metadataCache.readdir(path);
|
||||
return entries.map(e => e.name);
|
||||
return entries.map((e) => e.name);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -10,6 +10,16 @@ function normPath(p) {
|
||||
return (p || "").replace(/^\/+/, "");
|
||||
}
|
||||
|
||||
// Convert a Uint8Array to base64 without blowing the stack
|
||||
function uint8ToBase64(bytes) {
|
||||
let binary = "";
|
||||
const chunk = 8192;
|
||||
for (let i = 0; i < bytes.length; i += chunk) {
|
||||
binary += String.fromCharCode.apply(null, bytes.subarray(i, i + chunk));
|
||||
}
|
||||
return btoa(binary);
|
||||
}
|
||||
|
||||
async function request(method, endpoint, params = {}) {
|
||||
const url = new URL(API_BASE + endpoint, window.location.origin);
|
||||
|
||||
@@ -109,7 +119,7 @@ export const transport = {
|
||||
const isText = typeof content === "string";
|
||||
return requestJson("POST", "/writeFile", {
|
||||
path: normPath(path),
|
||||
content: isText ? content : btoa(String.fromCharCode(...content)),
|
||||
content: isText ? content : uint8ToBase64(content),
|
||||
encoding: encoding || (isText ? "utf-8" : "binary"),
|
||||
base64: !isText,
|
||||
});
|
||||
@@ -197,7 +207,7 @@ export const transport = {
|
||||
const isText = typeof content === "string";
|
||||
requestSync("POST", "/writeFile", {
|
||||
path: normPath(path),
|
||||
content: isText ? content : btoa(String.fromCharCode(...content)),
|
||||
content: isText ? content : uint8ToBase64(content),
|
||||
encoding: encoding || (isText ? "utf-8" : "binary"),
|
||||
base64: !isText,
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user