2077 lines
80 KiB
JavaScript
2077 lines
80 KiB
JavaScript
/*
|
|
THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
|
|
if you want to view the source, please visit the github repository of this plugin
|
|
*/
|
|
|
|
var __defProp = Object.defineProperty;
|
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
var __export = (target, all) => {
|
|
for (var name in all)
|
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
};
|
|
var __copyProps = (to, from, except, desc) => {
|
|
if (from && typeof from === "object" || typeof from === "function") {
|
|
for (let key of __getOwnPropNames(from))
|
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
}
|
|
return to;
|
|
};
|
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
|
|
// src/main.ts
|
|
var main_exports = {};
|
|
__export(main_exports, {
|
|
default: () => AttachmentManagementPlugin
|
|
});
|
|
module.exports = __toCommonJS(main_exports);
|
|
var import_obsidian11 = require("obsidian");
|
|
|
|
// src/settings/settings.ts
|
|
var import_obsidian3 = require("obsidian");
|
|
|
|
// src/lib/constant.ts
|
|
var SETTINGS_VARIABLES_DATES = "${date}";
|
|
var SETTINGS_VARIABLES_NOTEPATH = "${notepath}";
|
|
var SETTINGS_VARIABLES_NOTENAME = "${notename}";
|
|
var SETTINGS_VARIABLES_NOTEPARENT = "${parent}";
|
|
var SETTINGS_VARIABLES_ORIGINALNAME = "${originalname}";
|
|
var SETTINGS_VARIABLES_MD5 = "${md5}";
|
|
var SETTINGS_ROOT_OBSFOLDER = "obsFolder";
|
|
var SETTINGS_ROOT_INFOLDER = "inFolderBelow";
|
|
var SETTINGS_ROOT_NEXTTONOTE = "nextToNote";
|
|
|
|
// src/model/extensionOverride.ts
|
|
var import_obsidian2 = require("obsidian");
|
|
|
|
// src/utils.ts
|
|
var import_obsidian = require("obsidian");
|
|
|
|
// node_modules/ts-md5/dist/esm/md5.js
|
|
var Md5 = class {
|
|
constructor() {
|
|
this._dataLength = 0;
|
|
this._bufferLength = 0;
|
|
this._state = new Int32Array(4);
|
|
this._buffer = new ArrayBuffer(68);
|
|
this._buffer8 = new Uint8Array(this._buffer, 0, 68);
|
|
this._buffer32 = new Uint32Array(this._buffer, 0, 17);
|
|
this.start();
|
|
}
|
|
static hashStr(str, raw = false) {
|
|
return this.onePassHasher.start().appendStr(str).end(raw);
|
|
}
|
|
static hashAsciiStr(str, raw = false) {
|
|
return this.onePassHasher.start().appendAsciiStr(str).end(raw);
|
|
}
|
|
static _hex(x) {
|
|
const hc = Md5.hexChars;
|
|
const ho = Md5.hexOut;
|
|
let n;
|
|
let offset;
|
|
let j;
|
|
let i;
|
|
for (i = 0; i < 4; i += 1) {
|
|
offset = i * 8;
|
|
n = x[i];
|
|
for (j = 0; j < 8; j += 2) {
|
|
ho[offset + 1 + j] = hc.charAt(n & 15);
|
|
n >>>= 4;
|
|
ho[offset + 0 + j] = hc.charAt(n & 15);
|
|
n >>>= 4;
|
|
}
|
|
}
|
|
return ho.join("");
|
|
}
|
|
static _md5cycle(x, k) {
|
|
let a = x[0];
|
|
let b = x[1];
|
|
let c = x[2];
|
|
let d = x[3];
|
|
a += (b & c | ~b & d) + k[0] - 680876936 | 0;
|
|
a = (a << 7 | a >>> 25) + b | 0;
|
|
d += (a & b | ~a & c) + k[1] - 389564586 | 0;
|
|
d = (d << 12 | d >>> 20) + a | 0;
|
|
c += (d & a | ~d & b) + k[2] + 606105819 | 0;
|
|
c = (c << 17 | c >>> 15) + d | 0;
|
|
b += (c & d | ~c & a) + k[3] - 1044525330 | 0;
|
|
b = (b << 22 | b >>> 10) + c | 0;
|
|
a += (b & c | ~b & d) + k[4] - 176418897 | 0;
|
|
a = (a << 7 | a >>> 25) + b | 0;
|
|
d += (a & b | ~a & c) + k[5] + 1200080426 | 0;
|
|
d = (d << 12 | d >>> 20) + a | 0;
|
|
c += (d & a | ~d & b) + k[6] - 1473231341 | 0;
|
|
c = (c << 17 | c >>> 15) + d | 0;
|
|
b += (c & d | ~c & a) + k[7] - 45705983 | 0;
|
|
b = (b << 22 | b >>> 10) + c | 0;
|
|
a += (b & c | ~b & d) + k[8] + 1770035416 | 0;
|
|
a = (a << 7 | a >>> 25) + b | 0;
|
|
d += (a & b | ~a & c) + k[9] - 1958414417 | 0;
|
|
d = (d << 12 | d >>> 20) + a | 0;
|
|
c += (d & a | ~d & b) + k[10] - 42063 | 0;
|
|
c = (c << 17 | c >>> 15) + d | 0;
|
|
b += (c & d | ~c & a) + k[11] - 1990404162 | 0;
|
|
b = (b << 22 | b >>> 10) + c | 0;
|
|
a += (b & c | ~b & d) + k[12] + 1804603682 | 0;
|
|
a = (a << 7 | a >>> 25) + b | 0;
|
|
d += (a & b | ~a & c) + k[13] - 40341101 | 0;
|
|
d = (d << 12 | d >>> 20) + a | 0;
|
|
c += (d & a | ~d & b) + k[14] - 1502002290 | 0;
|
|
c = (c << 17 | c >>> 15) + d | 0;
|
|
b += (c & d | ~c & a) + k[15] + 1236535329 | 0;
|
|
b = (b << 22 | b >>> 10) + c | 0;
|
|
a += (b & d | c & ~d) + k[1] - 165796510 | 0;
|
|
a = (a << 5 | a >>> 27) + b | 0;
|
|
d += (a & c | b & ~c) + k[6] - 1069501632 | 0;
|
|
d = (d << 9 | d >>> 23) + a | 0;
|
|
c += (d & b | a & ~b) + k[11] + 643717713 | 0;
|
|
c = (c << 14 | c >>> 18) + d | 0;
|
|
b += (c & a | d & ~a) + k[0] - 373897302 | 0;
|
|
b = (b << 20 | b >>> 12) + c | 0;
|
|
a += (b & d | c & ~d) + k[5] - 701558691 | 0;
|
|
a = (a << 5 | a >>> 27) + b | 0;
|
|
d += (a & c | b & ~c) + k[10] + 38016083 | 0;
|
|
d = (d << 9 | d >>> 23) + a | 0;
|
|
c += (d & b | a & ~b) + k[15] - 660478335 | 0;
|
|
c = (c << 14 | c >>> 18) + d | 0;
|
|
b += (c & a | d & ~a) + k[4] - 405537848 | 0;
|
|
b = (b << 20 | b >>> 12) + c | 0;
|
|
a += (b & d | c & ~d) + k[9] + 568446438 | 0;
|
|
a = (a << 5 | a >>> 27) + b | 0;
|
|
d += (a & c | b & ~c) + k[14] - 1019803690 | 0;
|
|
d = (d << 9 | d >>> 23) + a | 0;
|
|
c += (d & b | a & ~b) + k[3] - 187363961 | 0;
|
|
c = (c << 14 | c >>> 18) + d | 0;
|
|
b += (c & a | d & ~a) + k[8] + 1163531501 | 0;
|
|
b = (b << 20 | b >>> 12) + c | 0;
|
|
a += (b & d | c & ~d) + k[13] - 1444681467 | 0;
|
|
a = (a << 5 | a >>> 27) + b | 0;
|
|
d += (a & c | b & ~c) + k[2] - 51403784 | 0;
|
|
d = (d << 9 | d >>> 23) + a | 0;
|
|
c += (d & b | a & ~b) + k[7] + 1735328473 | 0;
|
|
c = (c << 14 | c >>> 18) + d | 0;
|
|
b += (c & a | d & ~a) + k[12] - 1926607734 | 0;
|
|
b = (b << 20 | b >>> 12) + c | 0;
|
|
a += (b ^ c ^ d) + k[5] - 378558 | 0;
|
|
a = (a << 4 | a >>> 28) + b | 0;
|
|
d += (a ^ b ^ c) + k[8] - 2022574463 | 0;
|
|
d = (d << 11 | d >>> 21) + a | 0;
|
|
c += (d ^ a ^ b) + k[11] + 1839030562 | 0;
|
|
c = (c << 16 | c >>> 16) + d | 0;
|
|
b += (c ^ d ^ a) + k[14] - 35309556 | 0;
|
|
b = (b << 23 | b >>> 9) + c | 0;
|
|
a += (b ^ c ^ d) + k[1] - 1530992060 | 0;
|
|
a = (a << 4 | a >>> 28) + b | 0;
|
|
d += (a ^ b ^ c) + k[4] + 1272893353 | 0;
|
|
d = (d << 11 | d >>> 21) + a | 0;
|
|
c += (d ^ a ^ b) + k[7] - 155497632 | 0;
|
|
c = (c << 16 | c >>> 16) + d | 0;
|
|
b += (c ^ d ^ a) + k[10] - 1094730640 | 0;
|
|
b = (b << 23 | b >>> 9) + c | 0;
|
|
a += (b ^ c ^ d) + k[13] + 681279174 | 0;
|
|
a = (a << 4 | a >>> 28) + b | 0;
|
|
d += (a ^ b ^ c) + k[0] - 358537222 | 0;
|
|
d = (d << 11 | d >>> 21) + a | 0;
|
|
c += (d ^ a ^ b) + k[3] - 722521979 | 0;
|
|
c = (c << 16 | c >>> 16) + d | 0;
|
|
b += (c ^ d ^ a) + k[6] + 76029189 | 0;
|
|
b = (b << 23 | b >>> 9) + c | 0;
|
|
a += (b ^ c ^ d) + k[9] - 640364487 | 0;
|
|
a = (a << 4 | a >>> 28) + b | 0;
|
|
d += (a ^ b ^ c) + k[12] - 421815835 | 0;
|
|
d = (d << 11 | d >>> 21) + a | 0;
|
|
c += (d ^ a ^ b) + k[15] + 530742520 | 0;
|
|
c = (c << 16 | c >>> 16) + d | 0;
|
|
b += (c ^ d ^ a) + k[2] - 995338651 | 0;
|
|
b = (b << 23 | b >>> 9) + c | 0;
|
|
a += (c ^ (b | ~d)) + k[0] - 198630844 | 0;
|
|
a = (a << 6 | a >>> 26) + b | 0;
|
|
d += (b ^ (a | ~c)) + k[7] + 1126891415 | 0;
|
|
d = (d << 10 | d >>> 22) + a | 0;
|
|
c += (a ^ (d | ~b)) + k[14] - 1416354905 | 0;
|
|
c = (c << 15 | c >>> 17) + d | 0;
|
|
b += (d ^ (c | ~a)) + k[5] - 57434055 | 0;
|
|
b = (b << 21 | b >>> 11) + c | 0;
|
|
a += (c ^ (b | ~d)) + k[12] + 1700485571 | 0;
|
|
a = (a << 6 | a >>> 26) + b | 0;
|
|
d += (b ^ (a | ~c)) + k[3] - 1894986606 | 0;
|
|
d = (d << 10 | d >>> 22) + a | 0;
|
|
c += (a ^ (d | ~b)) + k[10] - 1051523 | 0;
|
|
c = (c << 15 | c >>> 17) + d | 0;
|
|
b += (d ^ (c | ~a)) + k[1] - 2054922799 | 0;
|
|
b = (b << 21 | b >>> 11) + c | 0;
|
|
a += (c ^ (b | ~d)) + k[8] + 1873313359 | 0;
|
|
a = (a << 6 | a >>> 26) + b | 0;
|
|
d += (b ^ (a | ~c)) + k[15] - 30611744 | 0;
|
|
d = (d << 10 | d >>> 22) + a | 0;
|
|
c += (a ^ (d | ~b)) + k[6] - 1560198380 | 0;
|
|
c = (c << 15 | c >>> 17) + d | 0;
|
|
b += (d ^ (c | ~a)) + k[13] + 1309151649 | 0;
|
|
b = (b << 21 | b >>> 11) + c | 0;
|
|
a += (c ^ (b | ~d)) + k[4] - 145523070 | 0;
|
|
a = (a << 6 | a >>> 26) + b | 0;
|
|
d += (b ^ (a | ~c)) + k[11] - 1120210379 | 0;
|
|
d = (d << 10 | d >>> 22) + a | 0;
|
|
c += (a ^ (d | ~b)) + k[2] + 718787259 | 0;
|
|
c = (c << 15 | c >>> 17) + d | 0;
|
|
b += (d ^ (c | ~a)) + k[9] - 343485551 | 0;
|
|
b = (b << 21 | b >>> 11) + c | 0;
|
|
x[0] = a + x[0] | 0;
|
|
x[1] = b + x[1] | 0;
|
|
x[2] = c + x[2] | 0;
|
|
x[3] = d + x[3] | 0;
|
|
}
|
|
/**
|
|
* Initialise buffer to be hashed
|
|
*/
|
|
start() {
|
|
this._dataLength = 0;
|
|
this._bufferLength = 0;
|
|
this._state.set(Md5.stateIdentity);
|
|
return this;
|
|
}
|
|
// Char to code point to to array conversion:
|
|
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/charCodeAt
|
|
// #Example.3A_Fixing_charCodeAt_to_handle_non-Basic-Multilingual-Plane_characters_if_their_presence_earlier_in_the_string_is_unknown
|
|
/**
|
|
* Append a UTF-8 string to the hash buffer
|
|
* @param str String to append
|
|
*/
|
|
appendStr(str) {
|
|
const buf8 = this._buffer8;
|
|
const buf32 = this._buffer32;
|
|
let bufLen = this._bufferLength;
|
|
let code;
|
|
let i;
|
|
for (i = 0; i < str.length; i += 1) {
|
|
code = str.charCodeAt(i);
|
|
if (code < 128) {
|
|
buf8[bufLen++] = code;
|
|
} else if (code < 2048) {
|
|
buf8[bufLen++] = (code >>> 6) + 192;
|
|
buf8[bufLen++] = code & 63 | 128;
|
|
} else if (code < 55296 || code > 56319) {
|
|
buf8[bufLen++] = (code >>> 12) + 224;
|
|
buf8[bufLen++] = code >>> 6 & 63 | 128;
|
|
buf8[bufLen++] = code & 63 | 128;
|
|
} else {
|
|
code = (code - 55296) * 1024 + (str.charCodeAt(++i) - 56320) + 65536;
|
|
if (code > 1114111) {
|
|
throw new Error("Unicode standard supports code points up to U+10FFFF");
|
|
}
|
|
buf8[bufLen++] = (code >>> 18) + 240;
|
|
buf8[bufLen++] = code >>> 12 & 63 | 128;
|
|
buf8[bufLen++] = code >>> 6 & 63 | 128;
|
|
buf8[bufLen++] = code & 63 | 128;
|
|
}
|
|
if (bufLen >= 64) {
|
|
this._dataLength += 64;
|
|
Md5._md5cycle(this._state, buf32);
|
|
bufLen -= 64;
|
|
buf32[0] = buf32[16];
|
|
}
|
|
}
|
|
this._bufferLength = bufLen;
|
|
return this;
|
|
}
|
|
/**
|
|
* Append an ASCII string to the hash buffer
|
|
* @param str String to append
|
|
*/
|
|
appendAsciiStr(str) {
|
|
const buf8 = this._buffer8;
|
|
const buf32 = this._buffer32;
|
|
let bufLen = this._bufferLength;
|
|
let i;
|
|
let j = 0;
|
|
for (; ; ) {
|
|
i = Math.min(str.length - j, 64 - bufLen);
|
|
while (i--) {
|
|
buf8[bufLen++] = str.charCodeAt(j++);
|
|
}
|
|
if (bufLen < 64) {
|
|
break;
|
|
}
|
|
this._dataLength += 64;
|
|
Md5._md5cycle(this._state, buf32);
|
|
bufLen = 0;
|
|
}
|
|
this._bufferLength = bufLen;
|
|
return this;
|
|
}
|
|
/**
|
|
* Append a byte array to the hash buffer
|
|
* @param input array to append
|
|
*/
|
|
appendByteArray(input) {
|
|
const buf8 = this._buffer8;
|
|
const buf32 = this._buffer32;
|
|
let bufLen = this._bufferLength;
|
|
let i;
|
|
let j = 0;
|
|
for (; ; ) {
|
|
i = Math.min(input.length - j, 64 - bufLen);
|
|
while (i--) {
|
|
buf8[bufLen++] = input[j++];
|
|
}
|
|
if (bufLen < 64) {
|
|
break;
|
|
}
|
|
this._dataLength += 64;
|
|
Md5._md5cycle(this._state, buf32);
|
|
bufLen = 0;
|
|
}
|
|
this._bufferLength = bufLen;
|
|
return this;
|
|
}
|
|
/**
|
|
* Get the state of the hash buffer
|
|
*/
|
|
getState() {
|
|
const s = this._state;
|
|
return {
|
|
buffer: String.fromCharCode.apply(null, Array.from(this._buffer8)),
|
|
buflen: this._bufferLength,
|
|
length: this._dataLength,
|
|
state: [s[0], s[1], s[2], s[3]]
|
|
};
|
|
}
|
|
/**
|
|
* Override the current state of the hash buffer
|
|
* @param state New hash buffer state
|
|
*/
|
|
setState(state) {
|
|
const buf = state.buffer;
|
|
const x = state.state;
|
|
const s = this._state;
|
|
let i;
|
|
this._dataLength = state.length;
|
|
this._bufferLength = state.buflen;
|
|
s[0] = x[0];
|
|
s[1] = x[1];
|
|
s[2] = x[2];
|
|
s[3] = x[3];
|
|
for (i = 0; i < buf.length; i += 1) {
|
|
this._buffer8[i] = buf.charCodeAt(i);
|
|
}
|
|
}
|
|
/**
|
|
* Hash the current state of the hash buffer and return the result
|
|
* @param raw Whether to return the value as an `Int32Array`
|
|
*/
|
|
end(raw = false) {
|
|
const bufLen = this._bufferLength;
|
|
const buf8 = this._buffer8;
|
|
const buf32 = this._buffer32;
|
|
const i = (bufLen >> 2) + 1;
|
|
this._dataLength += bufLen;
|
|
const dataBitsLen = this._dataLength * 8;
|
|
buf8[bufLen] = 128;
|
|
buf8[bufLen + 1] = buf8[bufLen + 2] = buf8[bufLen + 3] = 0;
|
|
buf32.set(Md5.buffer32Identity.subarray(i), i);
|
|
if (bufLen > 55) {
|
|
Md5._md5cycle(this._state, buf32);
|
|
buf32.set(Md5.buffer32Identity);
|
|
}
|
|
if (dataBitsLen <= 4294967295) {
|
|
buf32[14] = dataBitsLen;
|
|
} else {
|
|
const matches = dataBitsLen.toString(16).match(/(.*?)(.{0,8})$/);
|
|
if (matches === null) {
|
|
return;
|
|
}
|
|
const lo = parseInt(matches[2], 16);
|
|
const hi = parseInt(matches[1], 16) || 0;
|
|
buf32[14] = lo;
|
|
buf32[15] = hi;
|
|
}
|
|
Md5._md5cycle(this._state, buf32);
|
|
return raw ? this._state : Md5._hex(this._state);
|
|
}
|
|
};
|
|
Md5.stateIdentity = new Int32Array([1732584193, -271733879, -1732584194, 271733878]);
|
|
Md5.buffer32Identity = new Int32Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
|
|
Md5.hexChars = "0123456789abcdef";
|
|
Md5.hexOut = [];
|
|
Md5.onePassHasher = new Md5();
|
|
if (Md5.hashStr("hello") !== "5d41402abc4b2a76b9719d911017c592") {
|
|
throw new Error("Md5 self test failed.");
|
|
}
|
|
|
|
// src/utils.ts
|
|
var PASTED_IMAGE_PREFIX = "Pasted image ";
|
|
var ImageExtensionRegex = /^(jpe?g|png|gif|svg|bmp|eps|webp)$/i;
|
|
function isMarkdownFile(extension) {
|
|
return extension === "md";
|
|
}
|
|
function isCanvasFile(extension) {
|
|
return extension === "canvas";
|
|
}
|
|
function isPastedImage(file) {
|
|
if (file instanceof import_obsidian.TFile) {
|
|
if (file.name.startsWith(PASTED_IMAGE_PREFIX)) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
function isImage(extension) {
|
|
const match = extension.match(ImageExtensionRegex);
|
|
if (match !== null) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
function stripPaths(src, dst) {
|
|
if (src === dst) {
|
|
return { stripedSrc: src, stripedDst: dst };
|
|
}
|
|
const srcParts = src.split("/");
|
|
const dstParts = dst.split("/");
|
|
if (srcParts.length !== dstParts.length) {
|
|
return { stripedSrc: src, stripedDst: dst };
|
|
}
|
|
for (let i = 0; i < srcParts.length; i++) {
|
|
const srcPart = srcParts[i];
|
|
const dstPart = dstParts[i];
|
|
if (srcPart !== dstPart) {
|
|
return {
|
|
stripedSrc: srcParts.slice(0, i + 1).join("/"),
|
|
stripedDst: dstParts.slice(0, i + 1).join("/")
|
|
};
|
|
}
|
|
}
|
|
return { stripedSrc: "", stripedDst: "" };
|
|
}
|
|
function matchExtension(extension, pattern) {
|
|
if (!pattern || pattern === "")
|
|
return false;
|
|
return new RegExp(pattern).test(extension);
|
|
}
|
|
function isAttachment(settings, filePath) {
|
|
let file = null;
|
|
if (filePath instanceof import_obsidian.TAbstractFile) {
|
|
file = filePath;
|
|
} else {
|
|
file = this.app.vault.getAbstractFileByPath(filePath);
|
|
}
|
|
if (file === null || !(file instanceof import_obsidian.TFile)) {
|
|
return false;
|
|
}
|
|
if (isMarkdownFile(file.extension) || isCanvasFile(file.extension)) {
|
|
return false;
|
|
}
|
|
return !matchExtension(file.extension, settings.excludeExtensionPattern);
|
|
}
|
|
async function md5sum(adapter, file) {
|
|
const md5 = new Md5();
|
|
if (!adapter.exists(file.path, true)) {
|
|
return "";
|
|
}
|
|
const content = await adapter.readBinary(file.path);
|
|
md5.appendByteArray(new Uint8Array(content));
|
|
const ret = md5.end();
|
|
return ret.toUpperCase();
|
|
}
|
|
function validateExtensionEntry(setting, plugin) {
|
|
const wrongIndex = [];
|
|
if (setting.extensionOverride !== void 0) {
|
|
const extOverride = setting.extensionOverride;
|
|
if (extOverride.some((ext) => ext.extension === "")) {
|
|
wrongIndex.push({ type: "empty", index: extOverride.findIndex((ext) => ext.extension === "") });
|
|
}
|
|
const duplicate = extOverride.map((ext) => ext.extension).filter((value, index, self) => self.indexOf(value) !== index);
|
|
if (duplicate.length > 0) {
|
|
duplicate.forEach((dupli) => {
|
|
wrongIndex.push({ type: "duplicate", index: extOverride.findIndex((ext) => dupli === ext.extension) });
|
|
});
|
|
}
|
|
const markdown = extOverride.filter((ext) => ext.extension === "md");
|
|
if (markdown.length > 0) {
|
|
wrongIndex.push({ type: "md", index: extOverride.findIndex((ext) => ext.extension === "md") });
|
|
}
|
|
const canvas = extOverride.filter((ext) => ext.extension === "canvas");
|
|
if (canvas.length > 0) {
|
|
wrongIndex.push({ type: "canvas", index: extOverride.findIndex((ext) => ext.extension === "canvas") });
|
|
}
|
|
const excludedFromSettings = plugin.excludeExtensionPattern.split("|");
|
|
const excluded = extOverride.filter((ext) => excludedFromSettings.includes(ext.extension));
|
|
if (excluded.length > 0) {
|
|
wrongIndex.push({
|
|
type: "excluded",
|
|
index: extOverride.findIndex((ext) => excludedFromSettings.includes(ext.extension))
|
|
});
|
|
}
|
|
}
|
|
return wrongIndex;
|
|
}
|
|
function generateErrorExtensionMessage(type) {
|
|
if (type === "canvas") {
|
|
new import_obsidian.Notice("Canvas is not supported as an extension override.");
|
|
} else if (type === "md") {
|
|
new import_obsidian.Notice("Markdown is not supported as an extension override.");
|
|
} else if (type === "empty") {
|
|
new import_obsidian.Notice("Extension override cannot be empty.");
|
|
} else if (type === "duplicate") {
|
|
new import_obsidian.Notice("Duplicate extension override.");
|
|
} else if (type === "excluded") {
|
|
new import_obsidian.Notice("Extension override cannot be an excluded extension.");
|
|
}
|
|
}
|
|
|
|
// src/lib/log.ts
|
|
var DEBUG = false;
|
|
if (DEBUG)
|
|
console.log("DEBUG is enabled");
|
|
function debugLog(...args) {
|
|
if (DEBUG) {
|
|
console.log(new Date().toISOString().slice(11, 23), ...args);
|
|
}
|
|
}
|
|
|
|
// src/model/extensionOverride.ts
|
|
function getExtensionOverrideSetting(extension, settings) {
|
|
if (settings.extensionOverride === void 0 || settings.extensionOverride.length === 0) {
|
|
return { extSetting: void 0 };
|
|
}
|
|
for (let i = 0; i < settings.extensionOverride.length; i++) {
|
|
if (matchExtension(extension, settings.extensionOverride[i].extension)) {
|
|
debugLog(
|
|
"getExtensionOverrideSetting - ",
|
|
settings.extensionOverride[i].extension,
|
|
settings.extensionOverride[i]
|
|
);
|
|
return { extSetting: settings.extensionOverride[i] };
|
|
}
|
|
}
|
|
return { extSetting: void 0 };
|
|
}
|
|
var OverrideExtensionModal = class extends import_obsidian2.Modal {
|
|
constructor(plugin, settings, onSubmit) {
|
|
super(plugin.app);
|
|
this.plugin = plugin;
|
|
this.settings = settings;
|
|
this.onSubmit = onSubmit;
|
|
}
|
|
displaySw(cont) {
|
|
cont.findAll(".setting-item").forEach((el) => {
|
|
var _a;
|
|
if ((_a = el.getAttr("class")) == null ? void 0 : _a.includes("override_root_folder_set")) {
|
|
if (this.settings.saveAttE === "obsFolder") {
|
|
el.hide();
|
|
} else {
|
|
el.show();
|
|
}
|
|
}
|
|
});
|
|
}
|
|
onOpen() {
|
|
const { contentEl } = this;
|
|
contentEl.empty();
|
|
contentEl.createEl("h3", {
|
|
text: `Extension settings for ${this.settings.extension}`
|
|
});
|
|
new import_obsidian2.Setting(contentEl).setName("Root path to save attachment").setDesc("Select root path of attachment").addDropdown(
|
|
(text) => text.addOption(`${SETTINGS_ROOT_OBSFOLDER}`, "Copy Obsidian settings").addOption(`${SETTINGS_ROOT_INFOLDER}`, "In the folder specified below").addOption(`${SETTINGS_ROOT_NEXTTONOTE}`, "Next to note in folder specified below").setValue(this.settings.saveAttE).onChange(async (value) => {
|
|
this.settings.saveAttE = value;
|
|
this.displaySw(contentEl);
|
|
this.onOpen();
|
|
})
|
|
);
|
|
if (this.settings.saveAttE !== "obsFolder") {
|
|
new import_obsidian2.Setting(contentEl).setName("Root folder").setClass("override_root_folder_set").addText(
|
|
(text) => text.setPlaceholder(DEFAULT_SETTINGS.attachPath.attachmentRoot).setValue(this.settings.attachmentRoot).onChange(async (value) => {
|
|
this.settings.attachmentRoot = value;
|
|
})
|
|
);
|
|
}
|
|
new import_obsidian2.Setting(contentEl).setName("Attachment path").setDesc(
|
|
`Path of attachment in root folder, available variables ${SETTINGS_VARIABLES_NOTEPATH}, ${SETTINGS_VARIABLES_NOTENAME} and ${SETTINGS_VARIABLES_NOTEPARENT}`
|
|
).addText(
|
|
(text) => text.setPlaceholder(DEFAULT_SETTINGS.attachPath.attachmentPath).setValue(this.settings.attachmentPath).onChange(async (value) => {
|
|
this.settings.attachmentPath = value;
|
|
})
|
|
);
|
|
new import_obsidian2.Setting(contentEl).setName("Attachment format").setDesc(
|
|
`Define how to name the attachment file, available variables ${SETTINGS_VARIABLES_DATES}, ${SETTINGS_VARIABLES_NOTENAME}, ${SETTINGS_VARIABLES_MD5} and ${SETTINGS_VARIABLES_ORIGINALNAME}.`
|
|
).addText(
|
|
(text) => text.setPlaceholder(DEFAULT_SETTINGS.attachPath.attachFormat).setValue(this.settings.attachFormat).onChange(async (value) => {
|
|
this.settings.attachFormat = value;
|
|
})
|
|
);
|
|
new import_obsidian2.Setting(contentEl).addButton(
|
|
(button) => button.setButtonText("Save").onClick(async () => {
|
|
this.onSubmit(this.settings);
|
|
this.close();
|
|
})
|
|
);
|
|
}
|
|
onClose() {
|
|
const { contentEl } = this;
|
|
contentEl.empty();
|
|
}
|
|
};
|
|
|
|
// src/settings/settings.ts
|
|
var DEFAULT_SETTINGS = {
|
|
attachPath: {
|
|
attachmentRoot: "",
|
|
saveAttE: `${SETTINGS_ROOT_OBSFOLDER}`,
|
|
attachmentPath: `${SETTINGS_VARIABLES_NOTEPATH}/${SETTINGS_VARIABLES_NOTENAME}`,
|
|
attachFormat: `IMG-${SETTINGS_VARIABLES_DATES}`,
|
|
type: "GLOBAL" /* GLOBAL */
|
|
},
|
|
dateFormat: "YYYYMMDDHHmmssSSS",
|
|
excludeExtensionPattern: "",
|
|
autoRenameAttachment: true,
|
|
excludedPaths: "",
|
|
excludePathsArray: [],
|
|
excludeSubpaths: false,
|
|
originalNameStorage: [],
|
|
overridePath: {},
|
|
disableNotification: false
|
|
};
|
|
var SettingTab = class extends import_obsidian3.PluginSettingTab {
|
|
constructor(app2, plugin) {
|
|
super(app2, plugin);
|
|
this.plugin = plugin;
|
|
}
|
|
displaySw(cont) {
|
|
cont.findAll(".setting-item").forEach((el) => {
|
|
var _a;
|
|
if ((_a = el.getAttr("class")) == null ? void 0 : _a.includes("root_folder_set")) {
|
|
if (this.plugin.settings.attachPath.saveAttE === "obsFolder") {
|
|
el.hide();
|
|
} else {
|
|
el.show();
|
|
}
|
|
}
|
|
});
|
|
}
|
|
splitPath(path2) {
|
|
const splitted = path2.split(";");
|
|
const rets = [];
|
|
for (const s of splitted) {
|
|
rets.push(s.trim());
|
|
}
|
|
return { splittedPaths: rets };
|
|
}
|
|
display() {
|
|
const { containerEl } = this;
|
|
containerEl.empty();
|
|
new import_obsidian3.Setting(containerEl).setName("Root path to save attachment").setDesc("Select root path of attachment").addDropdown(
|
|
(text) => text.addOption(`${SETTINGS_ROOT_OBSFOLDER}`, "Copy Obsidian settings").addOption(`${SETTINGS_ROOT_INFOLDER}`, "In the folder specified below").addOption(`${SETTINGS_ROOT_NEXTTONOTE}`, "Next to note in folder specified below").setValue(this.plugin.settings.attachPath.saveAttE).onChange(async (value) => {
|
|
this.plugin.settings.attachPath.saveAttE = value;
|
|
this.displaySw(containerEl);
|
|
await this.plugin.saveSettings();
|
|
})
|
|
);
|
|
new import_obsidian3.Setting(containerEl).setName("Root folder").setDesc("Root folder of new attachment").setClass("root_folder_set").addText(
|
|
(text) => text.setPlaceholder(DEFAULT_SETTINGS.attachPath.attachmentRoot).setValue(this.plugin.settings.attachPath.attachmentRoot).onChange(async (value) => {
|
|
debugLog("setting - attachment root:" + value);
|
|
this.plugin.settings.attachPath.attachmentRoot = value;
|
|
await this.plugin.saveSettings();
|
|
})
|
|
);
|
|
new import_obsidian3.Setting(containerEl).setName("Attachment path").setDesc(
|
|
`Path of attachment in root folder, available variables ${SETTINGS_VARIABLES_NOTEPATH}, ${SETTINGS_VARIABLES_NOTENAME}, ${SETTINGS_VARIABLES_NOTEPARENT}`
|
|
).addText(
|
|
(text) => text.setPlaceholder(DEFAULT_SETTINGS.attachPath.attachmentPath).setValue(this.plugin.settings.attachPath.attachmentPath).onChange(async (value) => {
|
|
debugLog("setting - attachment path:" + value);
|
|
this.plugin.settings.attachPath.attachmentPath = value;
|
|
await this.plugin.saveSettings();
|
|
})
|
|
);
|
|
new import_obsidian3.Setting(containerEl).setName("Attachment format").setDesc(
|
|
`Define how to name the attachment file, available variables ${SETTINGS_VARIABLES_DATES}, ${SETTINGS_VARIABLES_NOTENAME}, ${SETTINGS_VARIABLES_MD5} and ${SETTINGS_VARIABLES_ORIGINALNAME}.`
|
|
).addText(
|
|
(text) => text.setPlaceholder(DEFAULT_SETTINGS.attachPath.attachFormat).setValue(this.plugin.settings.attachPath.attachFormat).onChange(async (value) => {
|
|
debugLog("setting - attachment format:" + value);
|
|
this.plugin.settings.attachPath.attachFormat = value;
|
|
await this.plugin.saveSettings();
|
|
})
|
|
);
|
|
new import_obsidian3.Setting(containerEl).setName("Date format").setDesc(
|
|
createFragment((frag) => {
|
|
frag.appendText("Moment date format to use ");
|
|
frag.createEl("a", {
|
|
href: "https://momentjscom.readthedocs.io/en/latest/moment/04-displaying/01-format",
|
|
text: "Moment format options"
|
|
});
|
|
})
|
|
).addMomentFormat((component) => {
|
|
component.setPlaceholder(DEFAULT_SETTINGS.dateFormat).setValue(this.plugin.settings.dateFormat).onChange(async (value) => {
|
|
debugLog("setting - date format:" + value);
|
|
this.plugin.settings.dateFormat = value;
|
|
await this.plugin.saveSettings();
|
|
});
|
|
});
|
|
new import_obsidian3.Setting(containerEl).setName("Automatically rename attachment").setDesc(
|
|
"Automatically rename the attachment folder/filename when you rename the folder/filename where the corresponding md/canvas file be placed."
|
|
).addToggle(
|
|
(toggle) => toggle.setValue(this.plugin.settings.autoRenameAttachment).onChange(async (value) => {
|
|
debugLog("setting - automatically rename attachment folder:" + value);
|
|
this.plugin.settings.autoRenameAttachment = value;
|
|
await this.plugin.saveSettings();
|
|
})
|
|
);
|
|
new import_obsidian3.Setting(containerEl).setName("Extension override").setDesc("Using the extension override if you want to autorename the attachment with a specific extension (e.g. pdf or zip).").addButton((btn) => {
|
|
btn.setButtonText("Add extension overrides").onClick(async () => {
|
|
if (this.plugin.settings.attachPath.extensionOverride === void 0) {
|
|
this.plugin.settings.attachPath.extensionOverride = [];
|
|
}
|
|
this.plugin.settings.attachPath.extensionOverride.push({
|
|
extension: "",
|
|
attachmentRoot: this.plugin.settings.attachPath.attachmentRoot,
|
|
saveAttE: this.plugin.settings.attachPath.saveAttE,
|
|
attachmentPath: this.plugin.settings.attachPath.attachmentPath,
|
|
attachFormat: this.plugin.settings.attachPath.attachFormat
|
|
});
|
|
await this.plugin.saveSettings();
|
|
this.display();
|
|
});
|
|
});
|
|
if (this.plugin.settings.attachPath.extensionOverride !== void 0) {
|
|
this.plugin.settings.attachPath.extensionOverride.forEach((ext) => {
|
|
new import_obsidian3.Setting(containerEl).setName("Extension").setDesc("Extension to override").setClass("override_extension_set").addText(
|
|
(text) => text.setPlaceholder("pdf|docx?").setValue(ext.extension).onChange(async (value) => {
|
|
ext.extension = value;
|
|
})
|
|
).addButton((btn) => {
|
|
btn.setIcon("trash").setTooltip("Remove extension override").onClick(async () => {
|
|
var _a, _b, _c;
|
|
const index = (_b = (_a = this.plugin.settings.attachPath.extensionOverride) == null ? void 0 : _a.indexOf(ext)) != null ? _b : -1;
|
|
(_c = this.plugin.settings.attachPath.extensionOverride) == null ? void 0 : _c.splice(index, 1);
|
|
await this.plugin.saveSettings();
|
|
this.display();
|
|
});
|
|
}).addButton((btn) => {
|
|
btn.setIcon("pencil").setTooltip("Edit extension override").onClick(async () => {
|
|
new OverrideExtensionModal(this.plugin, ext, (result) => {
|
|
ext = result;
|
|
}).open();
|
|
});
|
|
}).addButton((btn) => {
|
|
btn.setIcon("check").setTooltip("Save extension override").onClick(async () => {
|
|
const wrongIndex = validateExtensionEntry(this.plugin.settings.attachPath, this.plugin.settings);
|
|
if (wrongIndex.length > 0) {
|
|
for (const i of wrongIndex) {
|
|
const resIndex = i.index < 0 ? 0 : i.index;
|
|
const wrongSetting = containerEl.getElementsByClassName("override_extension_set")[resIndex];
|
|
wrongSetting.getElementsByTagName("input")[0].style.border = "1px solid var(--color-red)";
|
|
generateErrorExtensionMessage(i.type);
|
|
}
|
|
return;
|
|
}
|
|
await this.plugin.saveSettings();
|
|
this.display();
|
|
new import_obsidian3.Notice("Saved extension override");
|
|
});
|
|
});
|
|
});
|
|
}
|
|
new import_obsidian3.Setting(containerEl).setName("Exclude extension pattern").setDesc(`Regex pattern to exclude certain extensions from being handled.`).addText(
|
|
(text) => text.setPlaceholder("pdf|docx?|xlsx?|pptx?|zip|rar").setValue(this.plugin.settings.excludeExtensionPattern).onChange(async (value) => {
|
|
this.plugin.settings.excludeExtensionPattern = value;
|
|
await this.plugin.saveSettings();
|
|
})
|
|
);
|
|
new import_obsidian3.Setting(containerEl).setName("Excluded paths").setDesc(
|
|
`Provide the full path of the folder names (case sensitive and without leading slash '/') divided by semicolon (;) to be excluded from renaming.`
|
|
).addTextArea((component) => {
|
|
component.setValue(this.plugin.settings.excludedPaths).onChange(async (value) => {
|
|
this.plugin.settings.excludedPaths = value;
|
|
const { splittedPaths } = this.splitPath(value);
|
|
this.plugin.settings.excludePathsArray = splittedPaths;
|
|
debugLog("setting - excluded paths:" + value, splittedPaths);
|
|
await this.plugin.saveSettings();
|
|
});
|
|
});
|
|
new import_obsidian3.Setting(containerEl).setName("Exclude subpaths").setDesc("Turn on this option if you want to also exclude all subfolders of the folder paths provided above.").addToggle(
|
|
(toggle) => toggle.setValue(this.plugin.settings.excludeSubpaths).onChange(async (value) => {
|
|
debugLog("setting - excluded subpaths:" + value);
|
|
this.plugin.settings.excludeSubpaths = value;
|
|
await this.plugin.saveSettings();
|
|
})
|
|
);
|
|
this.displaySw(containerEl);
|
|
}
|
|
};
|
|
|
|
// src/model/override.ts
|
|
var import_obsidian4 = require("obsidian");
|
|
var OverrideModal = class extends import_obsidian4.Modal {
|
|
constructor(plugin, file, setting) {
|
|
super(plugin.app);
|
|
this.plugin = plugin;
|
|
this.file = file;
|
|
this.setting = setting;
|
|
}
|
|
displaySw(cont) {
|
|
cont.findAll(".setting-item").forEach((el) => {
|
|
var _a;
|
|
if ((_a = el.getAttr("class")) == null ? void 0 : _a.includes("override_root_folder_set")) {
|
|
if (this.setting.saveAttE === "obsFolder") {
|
|
el.hide();
|
|
} else {
|
|
el.show();
|
|
}
|
|
}
|
|
});
|
|
}
|
|
onOpen() {
|
|
const { contentEl } = this;
|
|
contentEl.empty();
|
|
contentEl.createEl("h3", {
|
|
text: "Overriding Settings"
|
|
});
|
|
new import_obsidian4.Setting(contentEl).setName("Root path to save attachment").setDesc("Select root path of attachment").addDropdown(
|
|
(text) => text.addOption(`${SETTINGS_ROOT_OBSFOLDER}`, "Copy Obsidian settings").addOption(`${SETTINGS_ROOT_INFOLDER}`, "In the folder specified below").addOption(`${SETTINGS_ROOT_NEXTTONOTE}`, "Next to note in folder specified below").setValue(this.setting.saveAttE).onChange(async (value) => {
|
|
this.setting.saveAttE = value;
|
|
this.displaySw(contentEl);
|
|
})
|
|
);
|
|
new import_obsidian4.Setting(contentEl).setName("Root folder").setClass("override_root_folder_set").addText(
|
|
(text) => text.setPlaceholder(DEFAULT_SETTINGS.attachPath.attachmentRoot).setValue(this.setting.attachmentRoot).onChange(async (value) => {
|
|
debugLog("override - attachment root:" + value);
|
|
this.setting.attachmentRoot = value;
|
|
})
|
|
);
|
|
new import_obsidian4.Setting(contentEl).setName("Attachment path").setDesc(
|
|
`Path of attachment in root folder, available variables ${SETTINGS_VARIABLES_NOTEPATH}, ${SETTINGS_VARIABLES_NOTENAME} and ${SETTINGS_VARIABLES_NOTEPARENT}`
|
|
).addText(
|
|
(text) => text.setPlaceholder(DEFAULT_SETTINGS.attachPath.attachmentPath).setValue(this.setting.attachmentPath).onChange(async (value) => {
|
|
debugLog("override - attachment path:" + value);
|
|
this.setting.attachmentPath = value;
|
|
})
|
|
);
|
|
new import_obsidian4.Setting(contentEl).setName("Attachment format").setDesc(
|
|
`Define how to name the attachment file, available variables ${SETTINGS_VARIABLES_DATES}, ${SETTINGS_VARIABLES_NOTENAME}, ${SETTINGS_VARIABLES_MD5} and ${SETTINGS_VARIABLES_ORIGINALNAME}.`
|
|
).addText(
|
|
(text) => text.setPlaceholder(DEFAULT_SETTINGS.attachPath.attachFormat).setValue(this.setting.attachFormat).onChange(async (value) => {
|
|
debugLog("override - attachment format:" + value);
|
|
this.setting.attachFormat = value;
|
|
})
|
|
);
|
|
new import_obsidian4.Setting(contentEl).addButton((btn) => {
|
|
btn.setButtonText("Add extension overrides").onClick(async () => {
|
|
if (this.setting.extensionOverride === void 0) {
|
|
this.setting.extensionOverride = [];
|
|
}
|
|
this.setting.extensionOverride.push({
|
|
extension: "",
|
|
saveAttE: this.setting.saveAttE,
|
|
attachmentRoot: this.setting.attachmentRoot,
|
|
attachmentPath: this.setting.attachmentPath,
|
|
attachFormat: this.setting.attachFormat
|
|
});
|
|
this.onOpen();
|
|
});
|
|
});
|
|
if (this.setting.extensionOverride !== void 0) {
|
|
this.setting.extensionOverride.forEach((ext) => {
|
|
new import_obsidian4.Setting(contentEl).setName("Extension").setDesc("Extension to override").setClass("override_extension_set").addText(
|
|
(text) => text.setPlaceholder("pdf").setValue(ext.extension).onChange(async (value) => {
|
|
ext.extension = value;
|
|
})
|
|
).addButton((btn) => {
|
|
btn.setIcon("trash").onClick(async () => {
|
|
var _a, _b, _c;
|
|
const index = (_b = (_a = this.setting.extensionOverride) == null ? void 0 : _a.indexOf(ext)) != null ? _b : -1;
|
|
(_c = this.setting.extensionOverride) == null ? void 0 : _c.splice(index, 1);
|
|
this.onOpen();
|
|
});
|
|
}).addButton((btn) => {
|
|
btn.setIcon("pencil").onClick(async () => {
|
|
new OverrideExtensionModal(this.plugin, ext, (result) => {
|
|
ext = result;
|
|
}).open();
|
|
});
|
|
});
|
|
});
|
|
}
|
|
new import_obsidian4.Setting(contentEl).addButton((btn) => {
|
|
btn.setButtonText("Reset").onClick(async () => {
|
|
this.setting = this.plugin.settings.attachPath;
|
|
delete this.plugin.settings.overridePath[this.file.path];
|
|
await this.plugin.saveSettings();
|
|
await this.plugin.loadSettings();
|
|
new import_obsidian4.Notice(`Reset attachment setting of ${this.file.path}`);
|
|
this.close();
|
|
});
|
|
}).addButton(
|
|
(btn) => btn.setButtonText("Submit").setCta().onClick(async () => {
|
|
if (this.file instanceof import_obsidian4.TFile) {
|
|
this.setting.type = "FILE" /* FILE */;
|
|
} else if (this.file instanceof import_obsidian4.TFolder) {
|
|
this.setting.type = "FOLDER" /* FOLDER */;
|
|
}
|
|
this.plugin.settings.overridePath[this.file.path] = this.setting;
|
|
await this.plugin.saveSettings();
|
|
debugLog("override - overriding settings:", this.file.path, this.setting);
|
|
new import_obsidian4.Notice(`Overridden attachment setting of ${this.file.path}`);
|
|
this.close();
|
|
})
|
|
);
|
|
this.displaySw(contentEl);
|
|
}
|
|
onClose() {
|
|
const { contentEl } = this;
|
|
contentEl.empty();
|
|
}
|
|
};
|
|
|
|
// src/model/confirm.ts
|
|
var import_obsidian9 = require("obsidian");
|
|
|
|
// src/arrange.ts
|
|
var import_obsidian8 = require("obsidian");
|
|
|
|
// src/lib/path.ts
|
|
var path = {
|
|
// Credit: [@creationix/path.js](https://gist.github.com/creationix/7435851)
|
|
join(...partSegments) {
|
|
let parts = [];
|
|
for (let i = 0, l = partSegments.length; i < l; i++) {
|
|
parts = parts.concat(partSegments[i].split("/"));
|
|
}
|
|
const newParts = [];
|
|
for (let i = 0, l = parts.length; i < l; i++) {
|
|
const part = parts[i];
|
|
if (!part || part === ".")
|
|
continue;
|
|
if (part === "..")
|
|
newParts.pop();
|
|
else
|
|
newParts.push(part);
|
|
}
|
|
if (parts[0] === "")
|
|
newParts.unshift("");
|
|
return newParts.join("/");
|
|
},
|
|
// A simple function to get the dirname of a path
|
|
// Trailing slashes are ignored. Leading slash is preserved.
|
|
dirname(filepath) {
|
|
return this.join(filepath, "..");
|
|
},
|
|
// returns the last part of a path, e.g. 'foo.jpg'
|
|
basename(filepath, extension = "") {
|
|
const sp = filepath.split("/");
|
|
const filename = sp[sp.length - 1];
|
|
if (extension !== "") {
|
|
return filename.slice(0, filename.length - extension.length - 1);
|
|
}
|
|
return sp[sp.length - 1];
|
|
},
|
|
// return extension without dot, e.g. 'jpg'
|
|
extname(filepath) {
|
|
const positions = [...filepath.matchAll(new RegExp("\\.", "gi"))].map((a) => a.index);
|
|
const idx = positions[positions.length - 1];
|
|
if (idx === void 0) {
|
|
return "";
|
|
}
|
|
return filepath.slice(idx + 1);
|
|
}
|
|
};
|
|
|
|
// src/override.ts
|
|
var import_obsidian5 = require("obsidian");
|
|
function getOverrideSetting(settings, file, oldPath = "") {
|
|
if (Object.keys(settings.overridePath).length === 0) {
|
|
return { settingPath: "", setting: settings.attachPath };
|
|
}
|
|
const candidates = {};
|
|
let fileType;
|
|
let filePath;
|
|
fileType = file instanceof import_obsidian5.TFile;
|
|
fileType = !(file instanceof import_obsidian5.TFolder);
|
|
if (oldPath === "") {
|
|
filePath = file.path;
|
|
} else {
|
|
filePath = oldPath;
|
|
}
|
|
for (const overridePath of Object.keys(settings.overridePath)) {
|
|
const overrideSetting = settings.overridePath[overridePath];
|
|
if (fileType) {
|
|
if (overridePath === filePath && overrideSetting.type === "FILE" /* FILE */) {
|
|
return { settingPath: overridePath, setting: overrideSetting };
|
|
} else if (filePath.startsWith(overridePath) && filePath.charAt(overridePath.length) === "/" && overrideSetting.type === "FOLDER" /* FOLDER */) {
|
|
candidates[overridePath] = overrideSetting;
|
|
}
|
|
} else {
|
|
if (overridePath === filePath && overrideSetting.type === "FOLDER" /* FOLDER */) {
|
|
return { settingPath: overridePath, setting: overrideSetting };
|
|
} else if (filePath.startsWith(overridePath) && filePath.charAt(overridePath.length) === "/" && overrideSetting.type === "FOLDER" /* FOLDER */) {
|
|
candidates[overridePath] = overrideSetting;
|
|
}
|
|
}
|
|
}
|
|
if (Object.keys(candidates).length === 0) {
|
|
return { settingPath: "", setting: settings.attachPath };
|
|
}
|
|
const sortedK = Object.keys(candidates).sort(
|
|
(a, b) => a.split("/").length > b.split("/").length ? -1 : a.split("/").length < b.split("/").length ? 1 : 0
|
|
);
|
|
debugLog("getOverrideSetting - sortedK:", sortedK);
|
|
for (const k of sortedK) {
|
|
if (filePath.startsWith(k)) {
|
|
return { settingPath: k, setting: candidates[k] };
|
|
}
|
|
}
|
|
return { settingPath: "", setting: settings.attachPath };
|
|
}
|
|
function getRenameOverrideSetting(settings, file, oldPath) {
|
|
if (Object.keys(settings.overridePath).length === 0) {
|
|
return { settingPath: "", setting: settings.attachPath };
|
|
}
|
|
const { settingPath: np, setting: ns } = getOverrideSetting(settings, file);
|
|
const { settingPath: op, setting: os } = getOverrideSetting(settings, file, oldPath);
|
|
if (ns.type === "GLOBAL" /* GLOBAL */) {
|
|
return { settingPath: op, setting: os };
|
|
}
|
|
if (os.type === "GLOBAL" /* GLOBAL */) {
|
|
return { settingPath: np, setting: ns };
|
|
}
|
|
if (ns.type === "FILE" /* FILE */ && os.type === "FILE" /* FILE */) {
|
|
debugLog("getRenameOverrideSetting - both file type setting", np, op);
|
|
return { settingPath: "", setting: settings.attachPath };
|
|
}
|
|
if (ns.type === "FILE" /* FILE */ && os.type === "FOLDER" /* FOLDER */) {
|
|
return { settingPath: np, setting: ns };
|
|
} else if (ns.type === "FOLDER" /* FOLDER */ && os.type === "FILE" /* FILE */) {
|
|
return { settingPath: op, setting: os };
|
|
}
|
|
if (ns.type === "FOLDER" /* FOLDER */ && os.type === "FOLDER" /* FOLDER */) {
|
|
const l = np.split("/").length;
|
|
const r = op.split("/").length;
|
|
if (l > r) {
|
|
return { settingPath: np, setting: ns };
|
|
} else if (l < r) {
|
|
return { settingPath: op, setting: os };
|
|
} else if (l === r) {
|
|
return { settingPath: "", setting: os };
|
|
}
|
|
}
|
|
return { settingPath: "", setting: settings.attachPath };
|
|
}
|
|
function updateOverrideSetting(settings, file, oldPath) {
|
|
const keys = Object.keys(settings.overridePath);
|
|
if (keys.length === 0 || file.path === oldPath) {
|
|
return;
|
|
}
|
|
const { settingPath, setting } = getOverrideSetting(settings, file, oldPath);
|
|
const copySetting = Object.assign({}, setting);
|
|
if (file.path === settingPath) {
|
|
return;
|
|
}
|
|
if (oldPath === settingPath) {
|
|
settings.overridePath[file.path] = copySetting;
|
|
delete settings.overridePath[settingPath];
|
|
return;
|
|
} else {
|
|
const { stripedSrc, stripedDst } = stripPaths(oldPath, file.path);
|
|
if (stripedSrc === settingPath) {
|
|
settings.overridePath[stripedDst] = copySetting;
|
|
delete settings.overridePath[settingPath];
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
function deleteOverrideSetting(settings, file) {
|
|
const keys = Object.keys(settings.overridePath);
|
|
for (const key of keys) {
|
|
if (file.path === key) {
|
|
delete settings.overridePath[key];
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// src/lib/linkDetector.ts
|
|
var getAllLinkMatchesInFile = async (mdFile, app2, fileText) => {
|
|
const linkMatches = [];
|
|
if (fileText === void 0) {
|
|
fileText = await app2.vault.read(mdFile);
|
|
}
|
|
const wikiRegex = /\[\[.*?\]\]/g;
|
|
const wikiMatches = fileText.match(wikiRegex);
|
|
if (wikiMatches) {
|
|
const fileRegex = /(?<=\[\[).*?(?=(\]|\|))/;
|
|
for (const wikiMatch of wikiMatches) {
|
|
if (matchIsWikiTransclusion(wikiMatch)) {
|
|
const fileName = getTransclusionFileName(wikiMatch);
|
|
const file = app2.metadataCache.getFirstLinkpathDest(fileName, mdFile.path);
|
|
if (fileName !== "") {
|
|
const linkMatch = {
|
|
type: "wikiTransclusion",
|
|
match: wikiMatch,
|
|
linkText: file ? file.path : fileName,
|
|
sourceFilePath: mdFile.path
|
|
};
|
|
linkMatches.push(linkMatch);
|
|
continue;
|
|
}
|
|
}
|
|
const fileMatch = wikiMatch.match(fileRegex);
|
|
if (fileMatch) {
|
|
if (fileMatch[0].startsWith("http"))
|
|
continue;
|
|
const file = app2.metadataCache.getFirstLinkpathDest(fileMatch[0], mdFile.path);
|
|
const linkMatch = {
|
|
type: "wiki",
|
|
match: wikiMatch,
|
|
linkText: file ? file.path : fileMatch[0],
|
|
sourceFilePath: mdFile.path
|
|
};
|
|
linkMatches.push(linkMatch);
|
|
}
|
|
}
|
|
}
|
|
const markdownRegex = /\[(^$|.*?)\]\((.*?)\)/g;
|
|
const markdownMatches = fileText.match(markdownRegex);
|
|
if (markdownMatches) {
|
|
const fileRegex = /(?<=\().*(?=\))/;
|
|
for (const markdownMatch of markdownMatches) {
|
|
if (matchIsMdTransclusion(markdownMatch)) {
|
|
const fileName = getTransclusionFileName(markdownMatch);
|
|
const file = app2.metadataCache.getFirstLinkpathDest(fileName, mdFile.path);
|
|
if (fileName !== "") {
|
|
const linkMatch = {
|
|
type: "mdTransclusion",
|
|
match: markdownMatch,
|
|
linkText: file ? file.path : fileName,
|
|
sourceFilePath: mdFile.path
|
|
};
|
|
linkMatches.push(linkMatch);
|
|
continue;
|
|
}
|
|
}
|
|
const fileMatch = markdownMatch.match(fileRegex);
|
|
if (fileMatch) {
|
|
if (fileMatch[0].startsWith("http"))
|
|
continue;
|
|
const file = app2.metadataCache.getFirstLinkpathDest(fileMatch[0], mdFile.path);
|
|
const linkMatch = {
|
|
type: "markdown",
|
|
match: markdownMatch,
|
|
linkText: file ? file.path : fileMatch[0],
|
|
sourceFilePath: mdFile.path
|
|
};
|
|
linkMatches.push(linkMatch);
|
|
}
|
|
}
|
|
}
|
|
return linkMatches;
|
|
};
|
|
var wikiTransclusionRegex = /\[\[(.*?)#.*?\]\]/;
|
|
var wikiTransclusionFileNameRegex = /(?<=\[\[)(.*)(?=#)/;
|
|
var mdTransclusionRegex = /\[.*?]\((.*?)#.*?\)/;
|
|
var mdTransclusionFileNameRegex = /(?<=\]\()(.*)(?=#)/;
|
|
var matchIsWikiTransclusion = (match) => {
|
|
return wikiTransclusionRegex.test(match);
|
|
};
|
|
var matchIsMdTransclusion = (match) => {
|
|
return mdTransclusionRegex.test(match);
|
|
};
|
|
var getTransclusionFileName = (match) => {
|
|
const isWiki = wikiTransclusionRegex.test(match);
|
|
const isMd = mdTransclusionRegex.test(match);
|
|
if (isWiki || isMd) {
|
|
const fileNameMatch = match.match(isWiki ? wikiTransclusionFileNameRegex : mdTransclusionFileNameRegex);
|
|
if (fileNameMatch)
|
|
return fileNameMatch[0];
|
|
}
|
|
return "";
|
|
};
|
|
|
|
// src/lib/deduplicate.ts
|
|
function escapeRegExp(s) {
|
|
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
}
|
|
async function deduplicateNewName(newName, file) {
|
|
const dir = file.path;
|
|
const listed = await this.app.vault.adapter.list(dir);
|
|
debugLog("deduplicateNewName - sibling files", listed);
|
|
const newNameExt = path.extname(newName), newNameStem = newName.slice(0, newName.length - newNameExt.length - 1), newNameStemEscaped = escapeRegExp(newNameStem), delimiter = "-", delimiterEscaped = escapeRegExp(delimiter);
|
|
const dupNameRegex = new RegExp(
|
|
`^(?<name>${newNameStemEscaped})${delimiterEscaped}(?<number>\\d{1,3})\\.${newNameExt}$`
|
|
);
|
|
debugLog("dupNameRegex", dupNameRegex);
|
|
const dupNameNumbers = [];
|
|
let isNewNameExist = false;
|
|
for (let sibling of listed.files) {
|
|
sibling = path.basename(sibling);
|
|
if (sibling == newName) {
|
|
isNewNameExist = true;
|
|
continue;
|
|
}
|
|
const m = dupNameRegex.exec(sibling);
|
|
if (!m || m.groups === void 0)
|
|
continue;
|
|
dupNameNumbers.push(parseInt(m.groups.number));
|
|
}
|
|
if (isNewNameExist) {
|
|
const newNumber = dupNameNumbers.length > 0 ? Math.max(...dupNameNumbers) + 1 : 1;
|
|
newName = `${newNameStem}${delimiter}${newNumber}.${newNameExt}`;
|
|
}
|
|
return {
|
|
name: newName,
|
|
basename: newName.slice(0, newName.length - newNameExt.length - 1),
|
|
extension: newNameExt
|
|
};
|
|
}
|
|
|
|
// src/settings/metadata.ts
|
|
var import_obsidian7 = require("obsidian");
|
|
|
|
// src/commons.ts
|
|
var import_obsidian6 = require("obsidian");
|
|
function getActiveFile(app2) {
|
|
const view = getActiveView(app2);
|
|
if (view == null) {
|
|
return void 0;
|
|
} else if (view.file == null) {
|
|
return void 0;
|
|
} else {
|
|
return view.file;
|
|
}
|
|
}
|
|
function getActiveView(app2) {
|
|
return app2.workspace.getActiveViewOfType(import_obsidian6.TextFileView);
|
|
}
|
|
function getRootPath(notePath, setting) {
|
|
let root;
|
|
const obsmediadir = app.vault.getConfig("attachmentFolderPath");
|
|
switch (setting.saveAttE) {
|
|
case `${SETTINGS_ROOT_INFOLDER}`:
|
|
root = path.join(setting.attachmentRoot);
|
|
break;
|
|
case `${SETTINGS_ROOT_NEXTTONOTE}`:
|
|
root = path.join(notePath, setting.attachmentRoot.replace("./", ""));
|
|
break;
|
|
default:
|
|
if (obsmediadir === "/") {
|
|
root = obsmediadir;
|
|
} else if (obsmediadir === "./") {
|
|
root = path.join(notePath);
|
|
} else if (obsmediadir.match(/\.\/.+/g) !== null) {
|
|
root = path.join(notePath, obsmediadir.replace("./", ""));
|
|
} else {
|
|
root = obsmediadir;
|
|
}
|
|
}
|
|
return root === "/" ? root : (0, import_obsidian6.normalizePath)(root);
|
|
}
|
|
async function checkEmptyFolder(adapter, path2) {
|
|
const exist = await adapter.exists(path2, true);
|
|
if (!exist) {
|
|
return true;
|
|
}
|
|
const data = await adapter.list(path2);
|
|
if (data.files.length > 0) {
|
|
return false;
|
|
}
|
|
if (data.folders.length > 0) {
|
|
for (let i = 0; i < data.folders.length; i++) {
|
|
return checkEmptyFolder(adapter, data.folders[i]);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// src/settings/metadata.ts
|
|
var Metadata = class {
|
|
constructor(path2, name, basename, extension, parentPath, parentName, attachmentFile) {
|
|
/** parent path of file */
|
|
this.parentPath = "";
|
|
/** parent path basename of file */
|
|
this.parentName = "";
|
|
this.path = path2;
|
|
this.name = name;
|
|
this.basename = basename;
|
|
this.extension = extension;
|
|
this.parentPath = parentPath;
|
|
this.parentName = parentName;
|
|
this.attachmentFile = attachmentFile;
|
|
}
|
|
/**
|
|
* Returns a formatted attachment file name according to the provided settings.
|
|
*
|
|
* @param {AttachmentPathSettings} setting - attachment path settings object
|
|
* @param {string} dateFormat - format string for date and time
|
|
* @param {string} originalName - name of the original attachment
|
|
* @param {string} [linkName] - optional name for the attachment link
|
|
* @return {string} the formatted attachment file name
|
|
*/
|
|
async getAttachFileName(setting, dateFormat, originalName, adapter, linkName) {
|
|
const dateTime = window.moment().format(dateFormat);
|
|
let md5 = "";
|
|
let attachFormat = "";
|
|
if (this.attachmentFile !== void 0) {
|
|
md5 = await md5sum(adapter, this.attachmentFile);
|
|
const { extSetting } = getExtensionOverrideSetting(this.attachmentFile.extension, setting);
|
|
if (extSetting !== void 0) {
|
|
attachFormat = extSetting.attachFormat;
|
|
} else {
|
|
attachFormat = setting.attachFormat;
|
|
}
|
|
}
|
|
if (attachFormat.includes(SETTINGS_VARIABLES_ORIGINALNAME)) {
|
|
if (originalName === "" && linkName != void 0) {
|
|
return linkName;
|
|
} else {
|
|
return attachFormat.replace(`${SETTINGS_VARIABLES_DATES}`, dateTime).replace(`${SETTINGS_VARIABLES_NOTENAME}`, this.basename).replace(`${SETTINGS_VARIABLES_ORIGINALNAME}`, originalName).replace(`${SETTINGS_VARIABLES_MD5}`, md5);
|
|
}
|
|
}
|
|
return attachFormat.replace(`${SETTINGS_VARIABLES_DATES}`, dateTime).replace(`${SETTINGS_VARIABLES_NOTENAME}`, this.basename).replace(`${SETTINGS_VARIABLES_MD5}`, md5);
|
|
}
|
|
/**
|
|
* Returns the attachment path based on the given AttachmentPathSettings object.
|
|
*
|
|
* @param {AttachmentPathSettings} setting - An object containing the attachment path settings.
|
|
* @return {string} The normalized attachment path.
|
|
*/
|
|
getAttachmentPath(setting, dateFormat) {
|
|
const dateTime = window.moment().format(dateFormat);
|
|
let root = "";
|
|
let attachPath = "";
|
|
if (this.attachmentFile !== void 0) {
|
|
const { extSetting } = getExtensionOverrideSetting(this.attachmentFile.extension, setting);
|
|
if (extSetting !== void 0) {
|
|
root = getRootPath(this.parentPath, extSetting);
|
|
attachPath = path.join(
|
|
root,
|
|
extSetting.attachmentPath.replace(`${SETTINGS_VARIABLES_NOTEPATH}`, this.parentPath).replace(`${SETTINGS_VARIABLES_NOTENAME}`, this.basename).replace(`${SETTINGS_VARIABLES_NOTEPARENT}`, this.parentName).replace(`${SETTINGS_VARIABLES_DATES}`, dateTime)
|
|
);
|
|
return (0, import_obsidian7.normalizePath)(attachPath);
|
|
}
|
|
}
|
|
root = getRootPath(this.parentPath, setting);
|
|
debugLog("getAttachmentPath - root", root);
|
|
attachPath = path.join(
|
|
root,
|
|
setting.attachmentPath.replace(`${SETTINGS_VARIABLES_NOTEPATH}`, this.parentPath).replace(`${SETTINGS_VARIABLES_NOTENAME}`, this.basename).replace(`${SETTINGS_VARIABLES_NOTEPARENT}`, this.parentName).replace(`${SETTINGS_VARIABLES_DATES}`, dateTime)
|
|
);
|
|
return (0, import_obsidian7.normalizePath)(attachPath);
|
|
}
|
|
};
|
|
function getMetadata(file, attach) {
|
|
const parentPath = path.dirname(file);
|
|
const parentName = path.basename(parentPath);
|
|
const name = path.basename(file);
|
|
const extension = path.extname(file);
|
|
const basename = path.basename(file, extension);
|
|
return new Metadata(file, name, basename, extension, parentPath, parentName, attach);
|
|
}
|
|
|
|
// src/exclude.ts
|
|
function isExcluded(path2, settings) {
|
|
debugLog("excludePathsArray: ", settings.excludePathsArray);
|
|
for (const excludedPath of settings.excludePathsArray) {
|
|
if (excludedPath.length === 0) {
|
|
continue;
|
|
}
|
|
if (settings.excludeSubpaths && path2.startsWith(excludedPath)) {
|
|
debugLog("isExcluded: ", path2);
|
|
return true;
|
|
} else {
|
|
if (path2 === excludedPath) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// src/lib/originalStorage.ts
|
|
function containOriginalNameVariable(setting, ext) {
|
|
const { extSetting } = getExtensionOverrideSetting(ext, setting);
|
|
if (extSetting !== void 0 && extSetting.attachFormat.contains(SETTINGS_VARIABLES_ORIGINALNAME) || setting.attachFormat.contains(SETTINGS_VARIABLES_ORIGINALNAME)) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
function saveOriginalName(settings, setting, ext, data) {
|
|
if (settings.originalNameStorage === void 0) {
|
|
settings.originalNameStorage = [];
|
|
}
|
|
if (containOriginalNameVariable(setting, ext)) {
|
|
settings.originalNameStorage.filter((n) => n.md5 == data.md5).forEach((n) => settings.originalNameStorage.remove(n));
|
|
settings.originalNameStorage.push(data);
|
|
}
|
|
}
|
|
function loadOriginalName(settings, setting, ext, md5) {
|
|
if (containOriginalNameVariable(setting, ext)) {
|
|
const first = settings.originalNameStorage.find((data) => data.md5 === md5);
|
|
const last = settings.originalNameStorage.reverse().find((data) => data.md5 === md5);
|
|
if (first === void 0 || last == void 0) {
|
|
return void 0;
|
|
}
|
|
if (first.md5 === last.md5 && first.n === last.n) {
|
|
return last;
|
|
} else if (first.md5 === last.md5 && first.n !== last.n) {
|
|
settings.originalNameStorage.remove(first);
|
|
return last;
|
|
}
|
|
}
|
|
return void 0;
|
|
}
|
|
|
|
// src/arrange.ts
|
|
var bannerRegex = /!\[\[(.*?)\]\]/i;
|
|
var ArrangeHandler = class {
|
|
constructor(settings, app2, plugin) {
|
|
this.settings = settings;
|
|
this.app = app2;
|
|
this.plugin = plugin;
|
|
}
|
|
/**
|
|
* Rearranges attachments that are linked by markdown or canvas.
|
|
* Only rearranges attachments if autoRenameAttachment is enabled in settings.
|
|
*
|
|
* @param {RearrangeType} type - The type of attachments to rearrange.
|
|
* @param {TFile} file - The file to which the attachments are linked (optional), if the type was "file", thi should be provided.
|
|
* @param {string} oldPath - The old path of the file (optional), used for rename event.
|
|
*/
|
|
async rearrangeAttachment(type, file, oldPath) {
|
|
var _a;
|
|
if (!this.settings.autoRenameAttachment) {
|
|
debugLog("rearrangeAttachment - autoRenameAttachment not enable");
|
|
return;
|
|
}
|
|
const attachments = await this.getAttachmentsInVault(this.settings, type, file, oldPath);
|
|
debugLog("rearrangeAttachment - attachments:", Object.keys(attachments).length, Object.entries(attachments));
|
|
for (const obNote of Object.keys(attachments)) {
|
|
const innerFile = this.app.vault.getAbstractFileByPath(obNote);
|
|
if (!(innerFile instanceof import_obsidian8.TFile) || isAttachment(this.settings, innerFile)) {
|
|
debugLog(`rearrangeAttachment - ${obNote} not exists or is attachment, skipped`);
|
|
continue;
|
|
}
|
|
const { setting } = getOverrideSetting(this.settings, innerFile);
|
|
if (attachments[obNote].size == 0) {
|
|
continue;
|
|
}
|
|
const md = getMetadata(obNote);
|
|
const attachPath = md.getAttachmentPath(setting, this.settings.dateFormat);
|
|
if (!await this.app.vault.adapter.exists(attachPath, true)) {
|
|
if (oldPath != void 0 && await this.app.vault.adapter.exists(attachPath, false)) {
|
|
const mdOld = getMetadata(oldPath);
|
|
const attachPathOld = mdOld.getAttachmentPath(setting, this.settings.dateFormat);
|
|
this.app.vault.adapter.rename(attachPathOld, attachPath);
|
|
} else {
|
|
await this.app.vault.adapter.mkdir(attachPath);
|
|
}
|
|
}
|
|
for (let link of attachments[obNote]) {
|
|
try {
|
|
link = decodeURI(link);
|
|
} catch (err) {
|
|
console.log(`Invalid link: ${link}, err: ${err}`);
|
|
continue;
|
|
}
|
|
debugLog(`rearrangeAttachment - article: ${obNote} links: ${link}`);
|
|
const linkFile = this.app.vault.getAbstractFileByPath(link);
|
|
if (linkFile === null || !(linkFile instanceof import_obsidian8.TFile)) {
|
|
debugLog(`${link} not exists, skipped`);
|
|
continue;
|
|
}
|
|
const metadata = getMetadata(obNote, linkFile);
|
|
const md5 = await md5sum(this.app.vault.adapter, linkFile);
|
|
const originalName = loadOriginalName(this.settings, setting, linkFile.extension, md5);
|
|
debugLog("rearrangeAttachment - original name:", originalName);
|
|
let attachName = "";
|
|
if (containOriginalNameVariable(setting, linkFile.extension)) {
|
|
attachName = await metadata.getAttachFileName(
|
|
setting,
|
|
this.settings.dateFormat,
|
|
(_a = originalName == null ? void 0 : originalName.n) != null ? _a : "",
|
|
this.app.vault.adapter,
|
|
path.basename(link, path.extname(link))
|
|
);
|
|
} else {
|
|
attachName = await metadata.getAttachFileName(
|
|
setting,
|
|
this.settings.dateFormat,
|
|
path.basename(link, path.extname(link)),
|
|
this.app.vault.adapter
|
|
);
|
|
}
|
|
if (attachPath == path.dirname(link) && attachName === path.basename(link, path.extname(link))) {
|
|
continue;
|
|
}
|
|
const attachPathFile = this.app.vault.getAbstractFileByPath(attachPath);
|
|
if (attachPathFile === null || !(attachPathFile instanceof import_obsidian8.TFolder)) {
|
|
debugLog(`${attachPath} not exists, skipped`);
|
|
continue;
|
|
}
|
|
const { name } = await deduplicateNewName(attachName + "." + path.extname(link), attachPathFile);
|
|
debugLog("rearrangeAttachment - deduplicated name:", name);
|
|
await this.app.fileManager.renameFile(linkFile, path.join(attachPath, name));
|
|
}
|
|
}
|
|
}
|
|
/**
|
|
* Retrieves the attachments in the vault based on the specified settings and type.
|
|
* If a file is provided, only attachments related to that file will be returned.
|
|
*
|
|
* @param {AttachmentManagementPluginSettings} settings - The settings for the attachment management plugin.
|
|
* @param {RearrangeType} type - The type of attachments to retrieve.
|
|
* @param {TFile} [file] - The file to filter attachments by. Optional.
|
|
* @return {Promise<Record<string, Set<string>>>} - A promise that resolves to a record of attachments, where each key is a file name and each value is a set of associated attachment names.
|
|
*/
|
|
async getAttachmentsInVault(settings, type, file, oldPath) {
|
|
let attachmentsRecord = {};
|
|
attachmentsRecord = await this.getAttachmentsInVaultByLinks(settings, type, file, oldPath);
|
|
return attachmentsRecord;
|
|
}
|
|
/**
|
|
* Modified from https://github.com/ozntel/oz-clear-unused-images-obsidian/blob/master/src/util.ts#LL48C21-L48C21
|
|
* Retrieves a record of attachments in the vault based on the given settings and type.
|
|
*
|
|
* @param {AttachmentManagementPluginSettings} settings - The settings for the attachment management plugin.
|
|
* @param {RearrangeType} type - The type of attachments to retrieve.
|
|
* @param {TFile} file - The file to retrieve attachments for (optional).
|
|
* @return {Promise<Record<string, Set<string>>>} - A promise that resolves to a record of attachments.
|
|
*/
|
|
async getAttachmentsInVaultByLinks(settings, type, file, oldPath) {
|
|
const attachmentsRecord = {};
|
|
let resolvedLinks = {};
|
|
let allFiles = [];
|
|
if (type == 1 /* LINKS */) {
|
|
resolvedLinks = this.app.metadataCache.resolvedLinks;
|
|
allFiles = this.app.vault.getFiles();
|
|
} else if (type == 0 /* ACTIVE */) {
|
|
const file2 = getActiveFile(this.app);
|
|
if (file2) {
|
|
if (file2.parent && isExcluded(file2.parent.path, this.settings) || isAttachment(this.settings, file2)) {
|
|
allFiles = [];
|
|
new import_obsidian8.Notice(`${file2.path} was excluded, skipped`);
|
|
} else {
|
|
debugLog("getAttachmentsInVaultByLinks - active:", file2.path);
|
|
allFiles = [file2];
|
|
if (this.app.metadataCache.resolvedLinks[file2.path]) {
|
|
resolvedLinks[file2.path] = this.app.metadataCache.resolvedLinks[file2.path];
|
|
}
|
|
debugLog("getAttachmentsInVaultByLinks - resolvedLinks:", resolvedLinks);
|
|
}
|
|
}
|
|
} else if (type == 2 /* FILE */ && file != void 0) {
|
|
if (file.parent && isExcluded(file.parent.path, this.settings) || isAttachment(this.settings, file)) {
|
|
allFiles = [];
|
|
new import_obsidian8.Notice(`${file.path} was excluded, skipped`);
|
|
} else {
|
|
debugLog("getAttachmentsInVaultByLinks - file:", file.path);
|
|
allFiles = [file];
|
|
const rlinks = this.app.metadataCache.resolvedLinks[file.path];
|
|
if (rlinks) {
|
|
debugLog("getAttachmentsInVaultByLinks - rlinks:", rlinks);
|
|
resolvedLinks[file.path] = rlinks;
|
|
} else if (oldPath) {
|
|
debugLog("getAttachmentsInVaultByLinks - oldPath:", oldPath);
|
|
resolvedLinks[file.path] = this.app.metadataCache.resolvedLinks[oldPath];
|
|
}
|
|
debugLog("getAttachmentsInVaultByLinks - resolvedLinks:", resolvedLinks);
|
|
}
|
|
}
|
|
debugLog("getAttachmentsInVaultByLinks - allFiles:", allFiles.length, allFiles);
|
|
if (resolvedLinks) {
|
|
for (const [mdFile, links] of Object.entries(resolvedLinks)) {
|
|
const attachmentsSet = /* @__PURE__ */ new Set();
|
|
if (links) {
|
|
for (const [filePath] of Object.entries(links)) {
|
|
if (isAttachment(settings, filePath)) {
|
|
this.addToSet(attachmentsSet, filePath);
|
|
}
|
|
}
|
|
this.addToRecord(attachmentsRecord, mdFile, attachmentsSet);
|
|
}
|
|
}
|
|
}
|
|
for (let i = 0; i < allFiles.length; i++) {
|
|
const obsFile = allFiles[i];
|
|
const attachmentsSet = /* @__PURE__ */ new Set();
|
|
if (obsFile.parent && isExcluded(obsFile.parent.path, this.settings)) {
|
|
continue;
|
|
}
|
|
if (isMarkdownFile(obsFile.extension)) {
|
|
const fileCache = this.app.metadataCache.getFileCache(obsFile);
|
|
if (fileCache === null) {
|
|
continue;
|
|
}
|
|
if (fileCache.frontmatter) {
|
|
const frontmatter = fileCache.frontmatter;
|
|
for (const k of Object.keys(frontmatter)) {
|
|
if (typeof frontmatter[k] === "string") {
|
|
const formatMatch = frontmatter[k].match(bannerRegex);
|
|
if (formatMatch && formatMatch[1]) {
|
|
const fileName = formatMatch[1];
|
|
const file2 = this.app.metadataCache.getFirstLinkpathDest(fileName, obsFile.path);
|
|
if (file2 && isAttachment(settings, file2.path)) {
|
|
this.addToSet(attachmentsSet, file2.path);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
const linkMatches = await getAllLinkMatchesInFile(obsFile, app);
|
|
for (const linkMatch of linkMatches) {
|
|
if (isAttachment(settings, linkMatch.linkText)) {
|
|
this.addToSet(attachmentsSet, linkMatch.linkText);
|
|
}
|
|
}
|
|
} else if (isCanvasFile(obsFile.extension)) {
|
|
const fileRead = await this.app.vault.cachedRead(obsFile);
|
|
if (!fileRead || fileRead.length === 0) {
|
|
continue;
|
|
}
|
|
let canvasData;
|
|
try {
|
|
canvasData = JSON.parse(fileRead);
|
|
} catch (e) {
|
|
debugLog("getAttachmentsInVaultByLinks - parse canvas data error", e);
|
|
continue;
|
|
}
|
|
if (canvasData.nodes && canvasData.nodes.length > 0) {
|
|
for (const node of canvasData.nodes) {
|
|
if (node.type === "file") {
|
|
if (isAttachment(settings, node.file)) {
|
|
this.addToSet(attachmentsSet, node.file);
|
|
}
|
|
} else if (node.type == "text") {
|
|
const linkMatches = await getAllLinkMatchesInFile(obsFile, app, node.text);
|
|
for (const linkMatch of linkMatches) {
|
|
if (isAttachment(settings, linkMatch.linkText)) {
|
|
this.addToSet(attachmentsSet, linkMatch.linkText);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
this.addToRecord(attachmentsRecord, obsFile.path, attachmentsSet);
|
|
}
|
|
return attachmentsRecord;
|
|
}
|
|
addToRecord(record, key, value) {
|
|
if (record[key] === void 0) {
|
|
record[key] = value;
|
|
return;
|
|
}
|
|
const valueSet = record[key];
|
|
for (const val of value) {
|
|
this.addToSet(valueSet, val);
|
|
}
|
|
record[key] = valueSet;
|
|
}
|
|
addToSet(setObj, value) {
|
|
if (!setObj.has(value)) {
|
|
setObj.add(value);
|
|
}
|
|
}
|
|
needToRename(settings, attachPath, attachName, noteName, link) {
|
|
const linkPath = path.dirname(link);
|
|
const linkName = path.basename(link, path.extname(link));
|
|
if (linkName.length !== attachName.length) {
|
|
return true;
|
|
}
|
|
if (attachPath !== linkPath) {
|
|
return true;
|
|
} else {
|
|
if (settings.attachFormat.includes(SETTINGS_VARIABLES_NOTENAME) && !linkName.includes(noteName)) {
|
|
return true;
|
|
}
|
|
const noNoteNameAttachFormat = settings.attachFormat.split(SETTINGS_VARIABLES_NOTENAME);
|
|
if (settings.attachFormat.includes(SETTINGS_VARIABLES_DATES)) {
|
|
for (const formatPart in noNoteNameAttachFormat) {
|
|
const splited = formatPart.split(SETTINGS_VARIABLES_DATES);
|
|
for (const part in splited) {
|
|
if (!linkName.includes(part)) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
};
|
|
|
|
// src/model/confirm.ts
|
|
var ConfirmModal = class extends import_obsidian9.Modal {
|
|
constructor(plugin) {
|
|
super(plugin.app);
|
|
this.plugin = plugin;
|
|
}
|
|
onOpen() {
|
|
const { contentEl } = this;
|
|
contentEl.empty();
|
|
contentEl.createEl("h3", {
|
|
text: "Tips"
|
|
});
|
|
contentEl.createSpan("", (el) => {
|
|
el.innerText = "This operation is irreversible and experimental. Please backup your vault first!";
|
|
});
|
|
new import_obsidian9.Setting(contentEl).addButton((btn) => {
|
|
btn.setButtonText("Cancel").setCta().onClick(() => {
|
|
this.close();
|
|
});
|
|
}).addButton(
|
|
(btn) => btn.setButtonText("Continue").onClick(async () => {
|
|
new ArrangeHandler(this.plugin.settings, this.plugin.app, this.plugin).rearrangeAttachment(1 /* LINKS */).finally(() => {
|
|
new import_obsidian9.Notice("Arrange completed");
|
|
this.close();
|
|
});
|
|
})
|
|
);
|
|
}
|
|
onClose() {
|
|
const { contentEl } = this;
|
|
contentEl.empty();
|
|
}
|
|
};
|
|
|
|
// src/create.ts
|
|
var import_obsidian10 = require("obsidian");
|
|
var CreateHandler = class {
|
|
constructor(plugin, settings) {
|
|
this.plugin = plugin;
|
|
this.app = this.plugin.app;
|
|
this.settings = settings;
|
|
}
|
|
/**
|
|
* Post-processing of created attachment file (for paste and drop event).
|
|
* @param attach - the attachment file to process
|
|
* @param source - the notes file that linked to attach
|
|
* @returns - none
|
|
*/
|
|
processAttach(attach, source) {
|
|
if (source.parent && isExcluded(source.parent.path, this.settings)) {
|
|
debugLog("processAttach - not a file or exclude path:", source.path);
|
|
new import_obsidian10.Notice(`${source.path} was excluded, skipped`);
|
|
return;
|
|
}
|
|
const { setting } = getOverrideSetting(this.settings, source);
|
|
const { extSetting } = getExtensionOverrideSetting(attach.extension, setting);
|
|
debugLog("processAttach - file.extension:", attach.extension);
|
|
if (extSetting === void 0 && !isImage(attach.extension) && !isPastedImage(attach)) {
|
|
debugLog("renameFiles - no handle extension:", attach.extension);
|
|
return;
|
|
}
|
|
const metadata = getMetadata(source.path, attach);
|
|
debugLog("processAttach - metadata:", metadata);
|
|
const attachPath = metadata.getAttachmentPath(setting, this.settings.dateFormat);
|
|
metadata.getAttachFileName(setting, this.settings.dateFormat, attach.basename, this.app.vault.adapter).then((attachName) => {
|
|
attachName = attachName + "." + attach.extension;
|
|
this.app.vault.adapter.exists(attachPath, true).then(async (exists) => {
|
|
if (!exists) {
|
|
await this.app.vault.adapter.mkdir(attachPath);
|
|
debugLog("processAttach - create path:", attachPath);
|
|
}
|
|
}).finally(() => {
|
|
const attachPathFolder = this.app.vault.getAbstractFileByPath(attachPath);
|
|
deduplicateNewName(attachName, attachPathFolder).then(({ name }) => {
|
|
debugLog("processAttach - new path of file:", path.join(attachPath, name));
|
|
this.renameCreateFile(attach, attachPath, name, source);
|
|
});
|
|
});
|
|
});
|
|
}
|
|
/**
|
|
* Rename the file specified by `@param file`, and update the link of the file if specified updateLink
|
|
* @param attach - file to rename
|
|
* @param attachPath - where to the renamed file will be move to
|
|
* @param attachName - name of the renamed file
|
|
* @param source - associated active file
|
|
* @returns - none
|
|
*/
|
|
renameCreateFile(attach, attachPath, attachName, source) {
|
|
const dst = (0, import_obsidian10.normalizePath)(path.join(attachPath, attachName));
|
|
debugLog("renameFile - ", attach.path, " to ", dst);
|
|
const original = attach.basename;
|
|
const name = attach.name;
|
|
this.app.fileManager.renameFile(attach, dst).then(() => {
|
|
new import_obsidian10.Notice(`Renamed ${name} to ${attachName}.`);
|
|
}).finally(() => {
|
|
const { setting } = getOverrideSetting(this.settings, source);
|
|
md5sum(this.app.vault.adapter, attach).then((md5) => {
|
|
saveOriginalName(this.settings, setting, attach.extension, {
|
|
n: original,
|
|
md5
|
|
});
|
|
this.plugin.saveData(this.settings);
|
|
});
|
|
});
|
|
}
|
|
};
|
|
|
|
// src/main.ts
|
|
var AttachmentManagementPlugin = class extends import_obsidian11.Plugin {
|
|
constructor() {
|
|
super(...arguments);
|
|
this.createdQueue = [];
|
|
}
|
|
async onload() {
|
|
await this.loadSettings();
|
|
console.log(`Plugin loading: ${this.manifest.name} v.${this.manifest.version}`);
|
|
this.app.workspace.onLayoutReady(() => {
|
|
this.initCommands();
|
|
this.registerEvent(
|
|
this.app.workspace.on("file-menu", async (menu, file) => {
|
|
if (file.parent && isExcluded(file.parent.path, this.settings) || isAttachment(this.settings, file)) {
|
|
return;
|
|
}
|
|
menu.addItem((item) => {
|
|
item.setTitle("Overriding attachment setting").setIcon("image-plus").onClick(async () => {
|
|
const { setting } = getOverrideSetting(this.settings, file);
|
|
const fileSetting = Object.assign({}, setting);
|
|
this.overrideConfiguration(file, fileSetting);
|
|
});
|
|
});
|
|
})
|
|
);
|
|
this.registerEvent(
|
|
this.app.vault.on("create", async (file) => {
|
|
debugLog("on create event - file:", file.path);
|
|
if (!(file instanceof import_obsidian11.TFile)) {
|
|
return;
|
|
}
|
|
const curentTime = new Date().getTime();
|
|
const timeGapMs = curentTime - file.stat.mtime;
|
|
const timeGapCs = curentTime - file.stat.ctime;
|
|
if (timeGapMs > 1e3 || timeGapCs > 1e3 || isMarkdownFile(file.extension) || isCanvasFile(file.extension)) {
|
|
return;
|
|
}
|
|
if (matchExtension(file.extension, this.settings.excludeExtensionPattern)) {
|
|
debugLog("create - excluded file by extension", file);
|
|
return;
|
|
}
|
|
this.createdQueue.push(file);
|
|
})
|
|
);
|
|
this.registerEvent(
|
|
this.app.vault.on("modify", (file) => {
|
|
debugLog("on modify event - create queue:", this.createdQueue);
|
|
if (this.createdQueue.length < 1 || !(file instanceof import_obsidian11.TFile)) {
|
|
return;
|
|
}
|
|
debugLog("on modify event - file:", file.path);
|
|
this.app.vault.adapter.process(file.path, (pdata) => {
|
|
const f = this.createdQueue.first();
|
|
if (f != void 0) {
|
|
this.app.vault.adapter.exists(f.path, true).then((exist) => {
|
|
if (exist) {
|
|
const processor = new CreateHandler(this, this.settings);
|
|
const link = this.app.fileManager.generateMarkdownLink(f, file.path);
|
|
if (file.extension == "md" && pdata.indexOf(link) != -1 || file.extension == "canvas" && pdata.indexOf(f.path) != -1) {
|
|
this.createdQueue.remove(f);
|
|
processor.processAttach(f, file);
|
|
}
|
|
} else {
|
|
debugLog("on modify event - file does not exist:", f.path);
|
|
this.createdQueue.remove(f);
|
|
}
|
|
});
|
|
}
|
|
return pdata;
|
|
});
|
|
})
|
|
);
|
|
this.registerEvent(
|
|
// when trigger a rename event on folder, for each file/folder in this renamed folder (include itself) will trigger this event
|
|
this.app.vault.on("rename", async (file, oldPath) => {
|
|
debugLog("on rename event - new path and old path:", file.path, oldPath);
|
|
const { setting } = getRenameOverrideSetting(this.settings, file, oldPath);
|
|
debugLog("rename - using settings:", setting);
|
|
if (setting.type === "FOLDER" /* FOLDER */ || setting.type === "FILE" /* FILE */) {
|
|
updateOverrideSetting(this.settings, file, oldPath);
|
|
this.saveSettings();
|
|
}
|
|
debugLog("rename - updated settings:", setting);
|
|
if (!this.settings.autoRenameAttachment) {
|
|
debugLog("rename - auto rename not enabled:", this.settings.autoRenameAttachment);
|
|
return;
|
|
}
|
|
if (file instanceof import_obsidian11.TFile) {
|
|
if (file.parent && isExcluded(file.parent.path, this.settings)) {
|
|
debugLog("rename - exclude path:", file.parent.path);
|
|
new import_obsidian11.Notice(`${file.path} was excluded`);
|
|
return;
|
|
}
|
|
if (isAttachment(this.settings, file)) {
|
|
debugLog("rename - not processing rename on attachment:", file.path);
|
|
return;
|
|
}
|
|
await new ArrangeHandler(this.settings, this.app, this).rearrangeAttachment(
|
|
2 /* FILE */,
|
|
file,
|
|
oldPath
|
|
);
|
|
const oldMetadata = getMetadata(oldPath);
|
|
const oldAttachPath = oldMetadata.getAttachmentPath(setting, this.settings.dateFormat);
|
|
this.app.vault.adapter.exists(oldAttachPath, true).then((exists) => {
|
|
if (exists) {
|
|
checkEmptyFolder(this.app.vault.adapter, oldAttachPath).then((empty) => {
|
|
if (empty) {
|
|
this.app.vault.adapter.rmdir(oldAttachPath, true);
|
|
}
|
|
});
|
|
}
|
|
});
|
|
} else if (file instanceof import_obsidian11.TFolder) {
|
|
return;
|
|
}
|
|
})
|
|
);
|
|
this.registerEvent(
|
|
this.app.vault.on("delete", async (file) => {
|
|
debugLog("on delete event - file path:", file.path);
|
|
if (file.parent && isExcluded(file.parent.path, this.settings) || isAttachment(this.settings, file)) {
|
|
debugLog("delete - exclude path or the file is an attachment:", file.path);
|
|
return;
|
|
}
|
|
if (deleteOverrideSetting(this.settings, file)) {
|
|
await this.saveSettings();
|
|
new import_obsidian11.Notice("Removed override setting of " + file.path);
|
|
}
|
|
if (file instanceof import_obsidian11.TFile) {
|
|
const oldMetadata = getMetadata(file.path);
|
|
const { setting } = getOverrideSetting(this.settings, file);
|
|
const oldAttachPath = oldMetadata.getAttachmentPath(setting, this.settings.dateFormat);
|
|
this.app.vault.adapter.exists(oldAttachPath, true).then((exists) => {
|
|
if (exists) {
|
|
checkEmptyFolder(this.app.vault.adapter, oldAttachPath).then((empty) => {
|
|
if (empty) {
|
|
this.app.vault.adapter.rmdir(oldAttachPath, true);
|
|
}
|
|
});
|
|
}
|
|
});
|
|
}
|
|
})
|
|
);
|
|
this.addSettingTab(new SettingTab(this.app, this));
|
|
});
|
|
}
|
|
async overrideConfiguration(file, setting) {
|
|
new OverrideModal(this, file, setting).open();
|
|
}
|
|
/**
|
|
* Initializes and registers the plugin's commands
|
|
* This method is responsible for setting up the user interface by adding various commands.
|
|
* These commands include settings overrides, resetting settings, clearing unused original name storage,
|
|
* and rearranging attachments.
|
|
*
|
|
* Note: The actual implementation of each command is not included in this method and needs to be
|
|
* defined separately asynchronously.
|
|
*
|
|
* Warning: Make sure you have checked for errors while implementing the functionality of each command.
|
|
*/
|
|
initCommands() {
|
|
this.addCommand({
|
|
id: "attachment-management-rearrange-all-links",
|
|
name: "Rearrange all linked attachments",
|
|
callback: async () => {
|
|
new ConfirmModal(this).open();
|
|
}
|
|
});
|
|
this.addCommand({
|
|
id: "attachment-management-rearrange-active-links",
|
|
name: "Rearrange linked attachments",
|
|
callback: async () => {
|
|
new ArrangeHandler(this.settings, this.app, this).rearrangeAttachment(0 /* ACTIVE */).finally(() => {
|
|
new import_obsidian11.Notice("Arrange completed");
|
|
});
|
|
}
|
|
});
|
|
this.addCommand({
|
|
id: "attachment-management-override-setting",
|
|
name: "Overriding setting",
|
|
checkCallback: (checking) => {
|
|
const file = getActiveFile(this.app);
|
|
if (file) {
|
|
if (isAttachment(this.settings, file)) {
|
|
return true;
|
|
}
|
|
if (!checking) {
|
|
if (file.parent && isExcluded(file.parent.path, this.settings)) {
|
|
new import_obsidian11.Notice(`${file.path} was excluded`);
|
|
return true;
|
|
}
|
|
const { setting } = getOverrideSetting(this.settings, file);
|
|
const fileSetting = Object.assign({}, setting);
|
|
this.overrideConfiguration(file, fileSetting);
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
});
|
|
this.addCommand({
|
|
id: "attachment-management-reset-override-setting",
|
|
name: "Reset override setting",
|
|
checkCallback: (checking) => {
|
|
const file = getActiveFile(this.app);
|
|
if (file) {
|
|
if (isAttachment(this.settings, file)) {
|
|
return true;
|
|
}
|
|
if (!checking) {
|
|
if (file.parent && isExcluded(file.parent.path, this.settings)) {
|
|
new import_obsidian11.Notice(`${file.path} was excluded`);
|
|
return true;
|
|
}
|
|
delete this.settings.overridePath[file.path];
|
|
this.saveSettings().finally(() => {
|
|
new import_obsidian11.Notice(`Reset attachment setting of ${file.path}`);
|
|
});
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
});
|
|
this.addCommand({
|
|
id: "attachment-management-clear-unused-originalname-storage",
|
|
name: "Clear unused original name storage",
|
|
callback: async () => {
|
|
const attachments = await new ArrangeHandler(this.settings, this.app, this).getAttachmentsInVault(
|
|
this.settings,
|
|
1 /* LINKS */
|
|
);
|
|
const storages = [];
|
|
for (const attachs of Object.values(attachments)) {
|
|
for (const attach of attachs) {
|
|
const link = decodeURI(attach);
|
|
const linkFile = this.app.vault.getAbstractFileByPath(link);
|
|
if (linkFile !== null && linkFile instanceof import_obsidian11.TFile) {
|
|
md5sum(this.app.vault.adapter, linkFile).then((md5) => {
|
|
const ret = this.settings.originalNameStorage.find((data) => data.md5 === md5);
|
|
if (ret) {
|
|
storages.filter((n) => n.md5 == md5).forEach((n) => storages.remove(n));
|
|
storages.push(ret);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}
|
|
debugLog("clearUnusedOriginalNameStorage - storage:", storages);
|
|
this.settings.originalNameStorage = storages;
|
|
this.saveSettings();
|
|
}
|
|
});
|
|
}
|
|
async loadSettings() {
|
|
this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData());
|
|
}
|
|
async saveSettings() {
|
|
await this.saveData(this.settings);
|
|
}
|
|
async onunload() {
|
|
console.log("unloading attachment management.");
|
|
this.createdQueue = [];
|
|
}
|
|
};
|