commit 8cffa38ebae2a46b7c8e855c7b21a124e35adc89
Author: fyears <1142836+fyears@users.noreply.github.com>
Date: Thu Mar 10 23:52:56 2022 +0800
bypass more cors for onedrive
commit 1b59ac1e58032099068aab55d22ef96c6396f203
Author: fyears <1142836+fyears@users.noreply.github.com>
Date: Wed Mar 9 23:58:28 2022 +0800
change wordings for webdav cors
commit 73142eb18b59fff20839680e866f51cfcb0a6226
Author: fyears <1142836+fyears@users.noreply.github.com>
Date: Wed Mar 9 23:38:58 2022 +0800
remove cors hint for webdav
commit 7dbb0b49d50e529b2b72e55ea2c8503ba7fa9268
Author: fyears <1142836+fyears@users.noreply.github.com>
Date: Wed Mar 9 23:31:54 2022 +0800
fix webdav
commit c28c4e19720a56230d483acf306463d42e619fa4
Author: fyears <1142836+fyears@users.noreply.github.com>
Date: Wed Mar 9 23:31:35 2022 +0800
remove more headers
commit 4eeae7043fa68d669a5c23c5549c14c1260ce638
Author: fyears <1142836+fyears@users.noreply.github.com>
Date: Wed Mar 9 23:18:32 2022 +0800
polish cors hints for s3
commit d9e55a91a1c413e9419cd6b30a3a6e3b403d483b
Author: fyears <1142836+fyears@users.noreply.github.com>
Date: Wed Mar 9 22:40:37 2022 +0800
fix format
commit b780a3eb4e37b05b8e8b92d6a2f9283b3459d738
Author: fyears <1142836+fyears@users.noreply.github.com>
Date: Wed Mar 9 22:37:02 2022 +0800
finally correctly inject requestUrl into s3
commit 6a55a1a43d7653d65579ab88aa816e5d54cd276a
Author: fyears <1142836+fyears@users.noreply.github.com>
Date: Wed Mar 9 22:33:18 2022 +0800
to arraybuffer from view
commit 2f2607b4f0a3d9db5943528ced57cb2fdb419607
Author: fyears <1142836+fyears@users.noreply.github.com>
Date: Wed Mar 9 13:31:22 2022 +0800
add split ranges
commit ea24da24dea83fdb770e7e391cf8a2e4fea78d0d
Author: fyears <1142836+fyears@users.noreply.github.com>
Date: Sun Mar 6 22:57:50 2022 +0800
add settings of bypassing for s3
commit 2f099dc8ca1e66ea137b28dd329be50968734ba6
Author: fyears <1142836+fyears@users.noreply.github.com>
Date: Sun Mar 6 22:38:07 2022 +0800
use api ver var
commit 74c7ce2449a88cbe7c7f50cbb687b36ff3732c04
Author: fyears <1142836+fyears@users.noreply.github.com>
Date: Sun Mar 6 22:37:25 2022 +0800
correct way to inject s3
commit f29945d73132d21b2c44472ec2cafc06b9d71e8f
Author: fyears <1142836+fyears@users.noreply.github.com>
Date: Tue Mar 1 00:09:57 2022 +0800
add new http handler
commit d55104cb08e168cbcc243cf901cbd7f46f2e324b
Author: fyears <1142836+fyears@users.noreply.github.com>
Date: Mon Feb 28 22:59:55 2022 +0800
add types for patch
commit 50b79ade7188ee7dfab9c1d03119585db358ba6f
Author: fyears <1142836+fyears@users.noreply.github.com>
Date: Mon Feb 28 08:25:19 2022 +0800
remove verbose
commit 83f0e71aa15aa7586f6d4e105cd77c25c2e113ce
Author: fyears <1142836+fyears@users.noreply.github.com>
Date: Mon Feb 28 08:25:04 2022 +0800
patch webdav!
263 lines
6.3 KiB
TypeScript
263 lines
6.3 KiB
TypeScript
import { Vault } from "obsidian";
|
|
import * as path from "path";
|
|
|
|
import { base32, base64url } from "rfc4648";
|
|
import XRegExp from "xregexp";
|
|
|
|
import * as origLog from "loglevel";
|
|
const log = origLog.getLogger("rs-default");
|
|
|
|
/**
|
|
* If any part of the file starts with '.' or '_' then it's a hidden file.
|
|
* @param item
|
|
* @param loose
|
|
* @returns
|
|
*/
|
|
export const isHiddenPath = (item: string, loose: boolean = true) => {
|
|
const k = path.posix.normalize(item); // TODO: only unix path now
|
|
const k2 = k.split("/"); // TODO: only unix path now
|
|
// log.info(k2)
|
|
for (const singlePart of k2) {
|
|
if (singlePart === "." || singlePart === ".." || singlePart === "") {
|
|
continue;
|
|
}
|
|
if (singlePart[0] === ".") {
|
|
return true;
|
|
}
|
|
if (loose && singlePart[0] === "_") {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
};
|
|
|
|
/**
|
|
* Util func for mkdir -p based on the "path" of original file or folder
|
|
* "a/b/c/" => ["a", "a/b", "a/b/c"]
|
|
* "a/b/c/d/e.txt" => ["a", "a/b", "a/b/c", "a/b/c/d"]
|
|
* @param x string
|
|
* @returns string[] might be empty
|
|
*/
|
|
export const getFolderLevels = (x: string, addEndingSlash: boolean = false) => {
|
|
const res: string[] = [];
|
|
|
|
if (x === "" || x === "/") {
|
|
return res;
|
|
}
|
|
|
|
const y1 = x.split("/");
|
|
let i = 0;
|
|
for (let index = 0; index + 1 < y1.length; index++) {
|
|
let k = y1.slice(0, index + 1).join("/");
|
|
if (k === "" || k === "/") {
|
|
continue;
|
|
}
|
|
if (addEndingSlash) {
|
|
k = `${k}/`;
|
|
}
|
|
res.push(k);
|
|
}
|
|
return res;
|
|
};
|
|
|
|
export const mkdirpInVault = async (thePath: string, vault: Vault) => {
|
|
// log.info(thePath);
|
|
const foldersToBuild = getFolderLevels(thePath);
|
|
// log.info(foldersToBuild);
|
|
for (const folder of foldersToBuild) {
|
|
const r = await vault.adapter.exists(folder);
|
|
// log.info(r);
|
|
if (!r) {
|
|
log.info(`mkdir ${folder}`);
|
|
await vault.adapter.mkdir(folder);
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* https://stackoverflow.com/questions/8609289
|
|
* @param b Buffer
|
|
* @returns ArrayBuffer
|
|
*/
|
|
export const bufferToArrayBuffer = (
|
|
b: Buffer | Uint8Array | ArrayBufferView
|
|
) => {
|
|
return b.buffer.slice(b.byteOffset, b.byteOffset + b.byteLength);
|
|
};
|
|
|
|
/**
|
|
* Simple func.
|
|
* @param b
|
|
* @returns
|
|
*/
|
|
export const arrayBufferToBuffer = (b: ArrayBuffer) => {
|
|
return Buffer.from(b);
|
|
};
|
|
|
|
export const arrayBufferToBase64 = (b: ArrayBuffer) => {
|
|
return arrayBufferToBuffer(b).toString("base64");
|
|
};
|
|
|
|
export const arrayBufferToHex = (b: ArrayBuffer) => {
|
|
return arrayBufferToBuffer(b).toString("hex");
|
|
};
|
|
|
|
export const base64ToArrayBuffer = (b64text: string) => {
|
|
return bufferToArrayBuffer(Buffer.from(b64text, "base64"));
|
|
};
|
|
|
|
/**
|
|
* https://stackoverflow.com/questions/43131242
|
|
* @param hex
|
|
* @returns
|
|
*/
|
|
export const hexStringToTypedArray = (hex: string) => {
|
|
return new Uint8Array(
|
|
hex.match(/[\da-f]{2}/gi).map(function (h) {
|
|
return parseInt(h, 16);
|
|
})
|
|
);
|
|
};
|
|
|
|
export const base64ToBase32 = (a: string) => {
|
|
return base32.stringify(Buffer.from(a, "base64"));
|
|
};
|
|
|
|
export const base64ToBase64url = (a: string, pad: boolean = false) => {
|
|
let b = a.replace(/\+/g, "-").replace(/\//g, "_");
|
|
if (!pad) {
|
|
b = b.replace(/=/g, "");
|
|
}
|
|
return b;
|
|
};
|
|
|
|
/**
|
|
* iOS Safari could decrypt string with invalid password!
|
|
* So we need an extra way to test the decrypted result.
|
|
* One simple way is testing the result are "valid", printable chars or not.
|
|
*
|
|
* https://stackoverflow.com/questions/6198986
|
|
* https://www.regular-expressions.info/unicode.html
|
|
* Manual test shows that emojis like '🍎' match '\\p{Cs}',
|
|
* so we need to write the regrex in a form that \p{C} minus \p{Cs}
|
|
* @param a
|
|
*/
|
|
export const isVaildText = (a: string) => {
|
|
// If the regex matches, the string is invalid.
|
|
return !XRegExp("\\p{Cc}|\\p{Cf}|\\p{Co}|\\p{Cn}|\\p{Zl}|\\p{Zp}", "A").test(
|
|
a
|
|
);
|
|
};
|
|
|
|
/**
|
|
* If input is already a folder, returns it as is;
|
|
* And if input is a file, returns its direname.
|
|
* @param a
|
|
* @returns
|
|
*/
|
|
export const getPathFolder = (a: string) => {
|
|
if (a.endsWith("/")) {
|
|
return a;
|
|
}
|
|
const b = path.posix.dirname(a);
|
|
return b.endsWith("/") ? b : `${b}/`;
|
|
};
|
|
|
|
/**
|
|
* If input is already a folder, returns its folder;
|
|
* And if input is a file, returns its direname.
|
|
* @param a
|
|
* @returns
|
|
*/
|
|
export const getParentFolder = (a: string) => {
|
|
const b = path.posix.dirname(a);
|
|
if (b === "." || b === "/") {
|
|
// the root
|
|
return "/";
|
|
}
|
|
if (b.endsWith("/")) {
|
|
return b;
|
|
}
|
|
return `${b}/`;
|
|
};
|
|
|
|
/**
|
|
* https://stackoverflow.com/questions/54511144
|
|
* @param a
|
|
* @param delimiter
|
|
* @returns
|
|
*/
|
|
export const setToString = (a: Set<string>, delimiter: string = ",") => {
|
|
return [...a].join(delimiter);
|
|
};
|
|
|
|
export const extractSvgSub = (x: string, subEl: string = "rect") => {
|
|
const parser = new window.DOMParser();
|
|
const dom = parser.parseFromString(x, "image/svg+xml");
|
|
const svg = dom.querySelector("svg");
|
|
svg.setAttribute("viewbox", "0 0 10 10");
|
|
return svg.innerHTML;
|
|
};
|
|
|
|
/**
|
|
* https://stackoverflow.com/questions/18230217
|
|
* @param min
|
|
* @param max
|
|
* @returns
|
|
*/
|
|
export const getRandomIntInclusive = (min: number, max: number) => {
|
|
const randomBuffer = new Uint32Array(1);
|
|
window.crypto.getRandomValues(randomBuffer);
|
|
let randomNumber = randomBuffer[0] / (0xffffffff + 1);
|
|
min = Math.ceil(min);
|
|
max = Math.floor(max);
|
|
return Math.floor(randomNumber * (max - min + 1)) + min;
|
|
};
|
|
|
|
/**
|
|
* Random buffer
|
|
* @param byteLength
|
|
* @returns
|
|
*/
|
|
export const getRandomArrayBuffer = (byteLength: number) => {
|
|
const k = window.crypto.getRandomValues(new Uint8Array(byteLength));
|
|
return bufferToArrayBuffer(k);
|
|
};
|
|
|
|
/**
|
|
* https://stackoverflow.com/questions/958908
|
|
* @param x
|
|
* @returns
|
|
*/
|
|
export const reverseString = (x: string) => {
|
|
return [...x].reverse().join("");
|
|
};
|
|
|
|
export interface SplitRange {
|
|
partNum: number; // startting from 1
|
|
start: number;
|
|
end: number; // exclusive
|
|
}
|
|
export const getSplitRanges = (bytesTotal: number, bytesEachPart: number) => {
|
|
const res: SplitRange[] = [];
|
|
if (bytesEachPart >= bytesTotal) {
|
|
res.push({
|
|
partNum: 1,
|
|
start: 0,
|
|
end: bytesTotal,
|
|
});
|
|
return res;
|
|
}
|
|
const remainder = bytesTotal % bytesEachPart;
|
|
const howMany =
|
|
Math.floor(bytesTotal / bytesEachPart) + (remainder === 0 ? 0 : 1);
|
|
for (let i = 0; i < howMany; ++i) {
|
|
res.push({
|
|
partNum: i + 1,
|
|
start: bytesEachPart * i,
|
|
end: Math.min(bytesEachPart * (i + 1), bytesTotal),
|
|
});
|
|
}
|
|
return res;
|
|
};
|