Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix deleting unused images #427

Merged
merged 5 commits into from
Sep 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,7 @@ src/dg-testVault/*
package-lock.json
package.json

*.md
*.mjs
README.md
*.md
4 changes: 3 additions & 1 deletion src/dg-testVault/.obsidian/app.json
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
{}
{
"alwaysUpdateLinks": true
}
Binary file added src/dg-testVault/A Assets/travolta.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/dg-testVault/A Assets/unused_image.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions src/dg-testVault/E Embeds/E02 PNG published.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
dg-publish: true
---


![[travolta.png]]
7 changes: 7 additions & 0 deletions src/dg-testVault/E Embeds/E03 PNG_not_published.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
dg-publish: false
---



![[unused_image.png|100]]
6 changes: 6 additions & 0 deletions src/dg-testVault/E Embeds/E04 PNG reuse.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
dg-publish: true
---
This file uses the same image as in [[E03 PNG_not_published]]. When removing the other one, the image should not be removed.

![[unused_image.png|100]]
15 changes: 7 additions & 8 deletions src/publisher/DigitalGardenSiteManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
import { Octokit } from "@octokit/core";
import { Base64 } from "js-base64";
import type DigitalGardenPluginInfo from "../models/pluginInfo";
import { IMAGE_PATH_BASE, NOTE_PATH_BASE } from "./Publisher";

export interface PathRewriteRule {
from: string;
Expand Down Expand Up @@ -146,7 +147,7 @@ export default class DigitalGardenSiteManager {
{
owner: this.settings.githubUserName,
repo: this.settings.githubRepo,
path: "src/site/notes/" + path,
path: NOTE_PATH_BASE + path,
},
);

Expand Down Expand Up @@ -175,14 +176,14 @@ export default class DigitalGardenSiteManager {

const notes: Array<{ path: string; sha: string }> = files.filter(
(x: { path: string; type: string }) =>
x.path.startsWith("src/site/notes/") &&
x.path.startsWith(NOTE_PATH_BASE) &&
x.type === "blob" &&
x.path !== "src/site/notes/notes.json",
x.path !== `${NOTE_PATH_BASE}notes.json`,
);
const hashes: Record<string, string> = {};

for (const note of notes) {
const vaultPath = note.path.replace("src/site/notes/", "");
const vaultPath = note.path.replace(NOTE_PATH_BASE, "");
hashes[vaultPath] = note.sha;
}

Expand All @@ -208,14 +209,12 @@ export default class DigitalGardenSiteManager {

const images: Array<{ path: string; sha: string }> = files.filter(
(x: { path: string; type: string }) =>
x.path.startsWith("src/site/img/user/") && x.type === "blob",
x.path.startsWith(IMAGE_PATH_BASE) && x.type === "blob",
);
const hashes: Record<string, string> = {};

for (const img of images) {
const vaultPath = decodeURI(
img.path.replace("src/site/img/user/", ""),
);
const vaultPath = decodeURI(img.path.replace(IMAGE_PATH_BASE, ""));
hashes[vaultPath] = img.sha;
}

Expand Down
17 changes: 10 additions & 7 deletions src/publisher/PublishStatusManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,16 @@ export default class PublishStatusManager implements IPublishStatusManager {
remoteNoteHashes: { [key: string]: string },
marked: string[],
): Array<string> {
const deletedContentPaths: Array<string> = [];
const isJsFile = (key: string) => key.endsWith(".js");

Object.keys(remoteNoteHashes).forEach((key) => {
if (!key.endsWith(".js") && !marked.find((f) => f === key)) {
deletedContentPaths.push(key);
}
});
const isMarkedForPublish = (key: string) =>
marked.find((f) => f === key);

const deletedImagePaths = Object.keys(remoteNoteHashes).filter(
(key) => !isJsFile(key) && !isMarkedForPublish(key),
);

return deletedContentPaths;
return deletedImagePaths;
}
async getPublishStatus(): Promise<PublishStatus> {
const unpublishedNotes: Array<TFile> = [];
Expand All @@ -55,6 +56,7 @@ export default class PublishStatusManager implements IPublishStatusManager {

const remoteNoteHashes = await this.siteManager.getNoteHashes();
const remoteImageHashes = await this.siteManager.getImageHashes();

const marked = await this.publisher.getFilesMarkedForPublishing();

for (const file of marked.notes) {
Expand Down Expand Up @@ -82,6 +84,7 @@ export default class PublishStatusManager implements IPublishStatusManager {
remoteImageHashes,
marked.images,
);

unpublishedNotes.sort((a, b) => (a.path > b.path ? 1 : -1));
publishedNotes.sort((a, b) => (a.path > b.path ? 1 : -1));
changedNotes.sort((a, b) => (a.path > b.path ? 1 : -1));
Expand Down
10 changes: 7 additions & 3 deletions src/publisher/Publisher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ export interface MarkedForPublishing {
notes: TFile[];
images: string[];
}

export const IMAGE_PATH_BASE = "src/site/img/user/";
export const NOTE_PATH_BASE = "src/site/notes/";

/**
* Prepares files to be published and publishes them to Github
*/
Expand Down Expand Up @@ -70,13 +74,13 @@ export default class Publisher {
}

async deleteNote(vaultFilePath: string) {
const path = `src/site/notes/${vaultFilePath}`;
const path = `${NOTE_PATH_BASE}${vaultFilePath}`;

return await this.delete(path);
}

async deleteImage(vaultFilePath: string) {
const path = `src/site/img/user/${encodeURI(vaultFilePath)}`;
const path = `${IMAGE_PATH_BASE}${vaultFilePath}`;

return await this.delete(path);
}
Expand Down Expand Up @@ -230,7 +234,7 @@ export default class Publisher {

async uploadText(filePath: string, content: string) {
content = Base64.encode(content);
const path = `src/site/notes/${filePath}`;
const path = `${NOTE_PATH_BASE}${filePath}`;
await this.uploadToGithub(path, content);
}

Expand Down
14 changes: 14 additions & 0 deletions src/test/snapshot/snapshot.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,20 @@ I'm a list of all files in this folder:

{ .block-language-dataview}

---
{"dg-publish":true,"permalink":"/e-embeds/e04-png-reuse/"}
---

This file uses the same image as in [[E Embeds/E03 PNG_not_published\|E03 PNG_not_published]]. When removing the other one, the image should not be removed.

![unused_image.png|100](/img/user/A%20Assets/unused_image.png)
---
{"dg-publish":true,"permalink":"/e-embeds/e02-png-published/"}
---



![travolta.png](/img/user/A%20Assets/travolta.png)
---
{"dg-publish":true,"permalink":"/009-comments/"}
---
Expand Down
85 changes: 56 additions & 29 deletions src/ui/PublicationCenter.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
export let showDiff: (path: string) => void;
export let close: () => void;

let publishStatus: PublishStatus | undefined;
let publishStatus: PublishStatus;
let showPublishingView: boolean = false;

async function getPublishStatus() {
Expand Down Expand Up @@ -90,37 +90,44 @@
return cog;
};

$: publishedNotesTree = publishStatus
? filePathsToTree(
publishStatus.publishedNotes.map((note) => note.path),
"Published Notes",
)
: null;

$: changedNotesTree = publishStatus
? filePathsToTree(
publishStatus.changedNotes.map((note) => note.path),
"Changed Notes",
)
: null;

$: deletedNoteTree = publishStatus
? filePathsToTree(publishStatus.deletedNotePaths, "Deleted Notes")
: null;

$: unpublishedNoteTree = publishStatus
? filePathsToTree(
publishStatus.unpublishedNotes.map((note) => note.path),
"Unpublished Notes",
)
: null;
$: publishedNotesTree =
publishStatus &&
filePathsToTree(
publishStatus.publishedNotes.map((note) => note.path),
"Published Notes",
);

$: changedNotesTree =
publishStatus &&
filePathsToTree(
publishStatus.changedNotes.map((note) => note.path),
"Changed Notes",
);

$: deletedNoteTree =
publishStatus &&
filePathsToTree(
[
...publishStatus.deletedNotePaths,
...publishStatus.deletedImagePaths,
],
"Deleted Notes",
);

$: unpublishedNoteTree =
publishStatus &&
filePathsToTree(
publishStatus.unpublishedNotes.map((note) => note.path),
"Unpublished Notes",
);

$: publishProgress =
((publishedPaths.length + failedPublish.length) /
(unpublishedToPublish.length +
changedToPublish.length +
pathsToDelete.length)) *
100;

const traverseTree = (tree: TreeNode): Array<string> => {
const paths: Array<string> = [];

Expand Down Expand Up @@ -148,13 +155,25 @@
const publishMarkedNotes = async () => {
if (!unpublishedNoteTree || !changedNotesTree) return;

if (!publishStatus) {
throw new Error("Publish status is undefined");
}

const unpublishedPaths = traverseTree(unpublishedNoteTree!);
const changedPaths = traverseTree(changedNotesTree!);

pathsToDelete = traverseTree(deletedNoteTree!);

const notesToDelete = pathsToDelete.filter((path) =>
publishStatus.deletedNotePaths.includes(path),
);

const imagesToDelete = pathsToDelete.filter((path) =>
publishStatus.deletedImagePaths.includes(path),
);

unpublishedToPublish =
publishStatus?.unpublishedNotes.filter((note) =>
publishStatus.unpublishedNotes.filter((note) =>
unpublishedPaths.includes(note.path),
) ?? [];

Expand All @@ -180,9 +199,17 @@
}
}

for (const path of pathsToDelete) {
for (const path of [...notesToDelete, ...imagesToDelete]) {
processingPaths.push(path);
let isDeleted = await publisher.deleteNote(path);
const isNote = path.endsWith(".md");
let isDeleted: boolean;

if (isNote) {
isDeleted = await publisher.deleteNote(path);
} else {
isDeleted = await publisher.deleteImage(path);
}

processingPaths = processingPaths.filter((p) => p !== path);

if (isDeleted) {
Expand Down Expand Up @@ -252,7 +279,7 @@
<div
class="loading-bar"
style="width: {publishProgress}%"
></div>
/>
</div>
</div>

Expand Down
1 change: 0 additions & 1 deletion src/ui/PublishModal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ export class PublishModal {
const remoteContent =
await this.siteManager.getNoteContent(notePath);
const localFile = this.vault.getAbstractFileByPath(notePath);
console.log(localFile);

if (localFile instanceof TFile) {
const [localContent, _] =
Expand Down