From 5d6aa9129d7ea878ee72d2588fadc013530f953b Mon Sep 17 00:00:00 2001 From: Jordan Handy <6423379+jordanhandy@users.noreply.github.com> Date: Fri, 7 Apr 2023 10:13:38 -0400 Subject: [PATCH 01/19] add setting option for f_auto --- src/main.ts | 12 +++++++++++- src/settings-tab.ts | 16 ++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/main.ts b/src/main.ts index 0f2a011..7fd24d0 100755 --- a/src/main.ts +++ b/src/main.ts @@ -17,6 +17,7 @@ interface CloudinarySettings { cloudName: string; uploadPreset: string; folder: string; + f_auto: boolean; //maxWidth: number; TODO // enableResize: boolean; TODO } @@ -26,6 +27,7 @@ const DEFAULT_SETTINGS: CloudinarySettings = { cloudName: null, uploadPreset: null, folder: null, + f_auto: false, //maxWidth: 4096, TODO //enableResize: false, TODO later }; @@ -64,7 +66,15 @@ export default class CloudinaryUploader extends Plugin { // Get response public URL of uploaded image console.log(res); const url = objectPath.get(res.data, 'secure_url') - const imgMarkdownText = `![](${url})` + let imgMarkdownText =""; + if(this.settings.f_auto){ + const splitURL = url.split("/upload/",2); + let modifiedURL=''; + modifiedURL = splitURL[0]+="f_auto/"+splitURL[1]; + imgMarkdownText = `![](${modifiedURL})`; + }else{ + imgMarkdownText = `![](${url})`; + } // Show MD syntax using uploaded image URL, in Obsidian Editor this.replaceText(editor, pastePlaceText, imgMarkdownText) }, err => { diff --git a/src/settings-tab.ts b/src/settings-tab.ts index 317a746..bd6ae8c 100755 --- a/src/settings-tab.ts +++ b/src/settings-tab.ts @@ -69,5 +69,21 @@ export default class CloudinaryUploaderSettingTab extends PluginSettingTab { } }) }); + new Setting(containerEl) + .setName("f_auto Option") + .setDesc("Enable f_auto option for image uploads") + .addToggle((toggle) => { + toggle + .setValue(this.plugin.settings.folder) + .onChange(async (value) => { + try { + this.plugin.settings.folder = value; + await this.plugin.saveSettings(); + } + catch (e) { + console.log(e) + } + }) + }); } } \ No newline at end of file From 825c4f274d05b1d598370cf12ecefcd873af51fd Mon Sep 17 00:00:00 2001 From: Jordan Handy <6423379+jordanhandy@users.noreply.github.com> Date: Fri, 7 Apr 2023 10:22:09 -0400 Subject: [PATCH 02/19] fix URL --- src/main.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.ts b/src/main.ts index 7fd24d0..93d35f1 100755 --- a/src/main.ts +++ b/src/main.ts @@ -70,7 +70,7 @@ export default class CloudinaryUploader extends Plugin { if(this.settings.f_auto){ const splitURL = url.split("/upload/",2); let modifiedURL=''; - modifiedURL = splitURL[0]+="f_auto/"+splitURL[1]; + modifiedURL = splitURL[0]+="/upload/f_auto/"+splitURL[1]; imgMarkdownText = `![](${modifiedURL})`; }else{ imgMarkdownText = `![](${url})`; From 267a414b3868efb44ff7df70a311728d1e324b1b Mon Sep 17 00:00:00 2001 From: Jordan Handy <6423379+jordanhandy@users.noreply.github.com> Date: Fri, 7 Apr 2023 10:34:37 -0400 Subject: [PATCH 03/19] fix settings tab --- src/settings-tab.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/settings-tab.ts b/src/settings-tab.ts index bd6ae8c..6ecd641 100755 --- a/src/settings-tab.ts +++ b/src/settings-tab.ts @@ -74,10 +74,10 @@ export default class CloudinaryUploaderSettingTab extends PluginSettingTab { .setDesc("Enable f_auto option for image uploads") .addToggle((toggle) => { toggle - .setValue(this.plugin.settings.folder) + .setValue(this.plugin.settings.f_auto) .onChange(async (value) => { try { - this.plugin.settings.folder = value; + this.plugin.settings.f_auto = value; await this.plugin.saveSettings(); } catch (e) { From 09c29254c1dbe47915fc6dc0fa448a64341fb7b1 Mon Sep 17 00:00:00 2001 From: Jordan Handy <6423379+jordanhandy@users.noreply.github.com> Date: Fri, 7 Apr 2023 10:40:12 -0400 Subject: [PATCH 04/19] fix settings tab --- main.js | 115 ++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 82 insertions(+), 33 deletions(-) diff --git a/main.js b/main.js index 515ad24..b90a42f 100755 --- a/main.js +++ b/main.js @@ -1091,6 +1091,7 @@ var require_follow_redirects = __commonJS((exports2, module2) => { this._redirectable.emit(event, arg1, arg2, arg3); }; }); + var InvalidUrlError = createErrorType("ERR_INVALID_URL", "Invalid URL", TypeError); var RedirectionError = createErrorType("ERR_FR_REDIRECTION_FAILURE", "Redirected request failed"); var TooManyRedirectsError = createErrorType("ERR_FR_TOO_MANY_REDIRECTS", "Maximum number of redirects exceeded"); var MaxBodyLengthExceededError = createErrorType("ERR_FR_MAX_BODY_LENGTH_EXCEEDED", "Request body larger than maxBodyLength limit"); @@ -1123,10 +1124,10 @@ var require_follow_redirects = __commonJS((exports2, module2) => { if (this._ending) { throw new WriteAfterEndError(); } - if (!(typeof data === "string" || typeof data === "object" && "length" in data)) { + if (!isString(data) && !isBuffer(data)) { throw new TypeError("data should be a string, Buffer or Uint8Array"); } - if (typeof encoding === "function") { + if (isFunction(encoding)) { callback = encoding; encoding = null; } @@ -1146,10 +1147,10 @@ var require_follow_redirects = __commonJS((exports2, module2) => { } }; RedirectableRequest.prototype.end = function(data, encoding, callback) { - if (typeof data === "function") { + if (isFunction(data)) { callback = data; data = encoding = null; - } else if (typeof encoding === "function") { + } else if (isFunction(encoding)) { callback = encoding; encoding = null; } @@ -1265,15 +1266,15 @@ var require_follow_redirects = __commonJS((exports2, module2) => { return; } if (this._options.agents) { - var scheme = protocol.substr(0, protocol.length - 1); + var scheme = protocol.slice(0, -1); this._options.agent = this._options.agents[scheme]; } var request = this._currentRequest = nativeProtocol.request(this._options, this._onNativeResponse); - this._currentUrl = url.format(this._options); request._redirectable = this; - for (var e = 0; e < events.length; e++) { - request.on(events[e], eventHandlers[events[e]]); + for (var event of events) { + request.on(event, eventHandlers[event]); } + this._currentUrl = /^\//.test(this._options.path) ? url.format(this._options) : this._options.path; if (this._isRedirect) { var i = 0; var self = this; @@ -1317,6 +1318,14 @@ var require_follow_redirects = __commonJS((exports2, module2) => { this.emit("error", new TooManyRedirectsError()); return; } + var requestHeaders; + var beforeRedirect = this._options.beforeRedirect; + if (beforeRedirect) { + requestHeaders = Object.assign({ + Host: response.req.getHeader("host") + }, this._options.headers); + } + var method = this._options.method; if ((statusCode === 301 || statusCode === 302) && this._options.method === "POST" || statusCode === 303 && !/^(?:GET|HEAD)$/.test(this._options.method)) { this._options.method = "GET"; this._requestBodyBuffers = []; @@ -1330,7 +1339,7 @@ var require_follow_redirects = __commonJS((exports2, module2) => { try { redirectUrl = url.resolve(currentUrl, location); } catch (cause) { - this.emit("error", new RedirectionError(cause)); + this.emit("error", new RedirectionError({cause})); return; } debug("redirecting to", redirectUrl); @@ -1340,10 +1349,18 @@ var require_follow_redirects = __commonJS((exports2, module2) => { if (redirectUrlParts.protocol !== currentUrlParts.protocol && redirectUrlParts.protocol !== "https:" || redirectUrlParts.host !== currentHost && !isSubdomain(redirectUrlParts.host, currentHost)) { removeMatchingHeaders(/^(?:authorization|cookie)$/i, this._options.headers); } - if (typeof this._options.beforeRedirect === "function") { - var responseDetails = {headers: response.headers}; + if (isFunction(beforeRedirect)) { + var responseDetails = { + headers: response.headers, + statusCode + }; + var requestDetails = { + url: currentUrl, + method, + headers: requestHeaders + }; try { - this._options.beforeRedirect.call(null, this._options, responseDetails); + beforeRedirect(this._options, responseDetails, requestDetails); } catch (err) { this.emit("error", err); return; @@ -1353,7 +1370,7 @@ var require_follow_redirects = __commonJS((exports2, module2) => { try { this._performRequest(); } catch (cause) { - this.emit("error", new RedirectionError(cause)); + this.emit("error", new RedirectionError({cause})); } }; function wrap(protocols) { @@ -1367,13 +1384,17 @@ var require_follow_redirects = __commonJS((exports2, module2) => { var nativeProtocol = nativeProtocols[protocol] = protocols[scheme]; var wrappedProtocol = exports3[scheme] = Object.create(nativeProtocol); function request(input, options, callback) { - if (typeof input === "string") { - var urlStr = input; + if (isString(input)) { + var parsed; try { - input = urlToOptions(new URL(urlStr)); + parsed = urlToOptions(new URL(input)); } catch (err) { - input = url.parse(urlStr); + parsed = url.parse(input); } + if (!isString(parsed.protocol)) { + throw new InvalidUrlError({input}); + } + input = parsed; } else if (URL && input instanceof URL) { input = urlToOptions(input); } else { @@ -1381,7 +1402,7 @@ var require_follow_redirects = __commonJS((exports2, module2) => { options = input; input = {protocol}; } - if (typeof options === "function") { + if (isFunction(options)) { callback = options; options = null; } @@ -1390,6 +1411,9 @@ var require_follow_redirects = __commonJS((exports2, module2) => { maxBodyLength: exports3.maxBodyLength }, input, options); options.nativeProtocols = nativeProtocols; + if (!isString(options.host) && !isString(options.hostname)) { + options.hostname = "::1"; + } assert.equal(options.protocol, protocol, "protocol mismatch"); debug("options", options); return new RedirectableRequest(options, callback); @@ -1433,33 +1457,39 @@ var require_follow_redirects = __commonJS((exports2, module2) => { } return lastValue === null || typeof lastValue === "undefined" ? void 0 : String(lastValue).trim(); } - function createErrorType(code, defaultMessage) { - function CustomError(cause) { + function createErrorType(code, message, baseClass) { + function CustomError(properties) { Error.captureStackTrace(this, this.constructor); - if (!cause) { - this.message = defaultMessage; - } else { - this.message = defaultMessage + ": " + cause.message; - this.cause = cause; - } + Object.assign(this, properties || {}); + this.code = code; + this.message = this.cause ? message + ": " + this.cause.message : message; } - CustomError.prototype = new Error(); + CustomError.prototype = new (baseClass || Error)(); CustomError.prototype.constructor = CustomError; CustomError.prototype.name = "Error [" + code + "]"; - CustomError.prototype.code = code; return CustomError; } function abortRequest(request) { - for (var e = 0; e < events.length; e++) { - request.removeListener(events[e], eventHandlers[events[e]]); + for (var event of events) { + request.removeListener(event, eventHandlers[event]); } request.on("error", noop); request.abort(); } function isSubdomain(subdomain, domain) { - const dot = subdomain.length - domain.length - 1; + assert(isString(subdomain) && isString(domain)); + var dot = subdomain.length - domain.length - 1; return dot > 0 && subdomain[dot] === "." && subdomain.endsWith(domain); } + function isString(value) { + return typeof value === "string" || value instanceof String; + } + function isFunction(value) { + return typeof value === "function"; + } + function isBuffer(value) { + return typeof value === "object" && "length" in value; + } module2.exports = wrap({http, https}); module2.exports.wrap = wrap; }); @@ -2639,6 +2669,16 @@ var CloudinaryUploaderSettingTab = class extends import_obsidian.PluginSettingTa } }); }); + new import_obsidian.Setting(containerEl).setName("f_auto Option").setDesc("Enable f_auto option for image uploads").addToggle((toggle) => { + toggle.setValue(this.plugin.settings.f_auto).onChange(async (value) => { + try { + this.plugin.settings.f_auto = value; + await this.plugin.saveSettings(); + } catch (e) { + console.log(e); + } + }); + }); } }; var settings_tab_default = CloudinaryUploaderSettingTab; @@ -2647,7 +2687,8 @@ var settings_tab_default = CloudinaryUploaderSettingTab; var DEFAULT_SETTINGS = { cloudName: null, uploadPreset: null, - folder: null + folder: null, + f_auto: false }; var CloudinaryUploader = class extends import_obsidian2.Plugin { setupPasteHandler() { @@ -2672,7 +2713,15 @@ var CloudinaryUploader = class extends import_obsidian2.Plugin { }).then((res) => { console.log(res); const url = import_object_path.default.get(res.data, "secure_url"); - const imgMarkdownText = `![](${url})`; + let imgMarkdownText = ""; + if (this.settings.f_auto) { + const splitURL = url.split("/upload/", 2); + let modifiedURL = ""; + modifiedURL = splitURL[0] += "/upload/f_auto/" + splitURL[1]; + imgMarkdownText = `![](${modifiedURL})`; + } else { + imgMarkdownText = `![](${url})`; + } this.replaceText(editor, pastePlaceText, imgMarkdownText); }, (err) => { new import_obsidian2.Notice(err, 5e3); From 4f44411257aa6ef2b94abf505b20a2939fe60ef4 Mon Sep 17 00:00:00 2001 From: Jordan Handy <6423379+jordanhandy@users.noreply.github.com> Date: Fri, 7 Apr 2023 11:22:30 -0400 Subject: [PATCH 05/19] update manifest on main --- manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manifest.json b/manifest.json index 237b458..1c4807e 100755 --- a/manifest.json +++ b/manifest.json @@ -5,5 +5,5 @@ "author": "Jordan Handy", "isDesktopOnly": true, "minAppVersion": "0.11.0", - "version": "0.1.5" + "version": "0.1.6" } From 6606e8d05788ff957bf58de37022c58e39a35638 Mon Sep 17 00:00:00 2001 From: Jordan Handy <6423379+jordanhandy@users.noreply.github.com> Date: Sat, 8 Apr 2023 19:57:48 -0400 Subject: [PATCH 06/19] add placeholder for transformation parameters setting --- src/settings-tab.ts | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/settings-tab.ts b/src/settings-tab.ts index 6ecd641..c22ec7a 100755 --- a/src/settings-tab.ts +++ b/src/settings-tab.ts @@ -85,5 +85,27 @@ export default class CloudinaryUploaderSettingTab extends PluginSettingTab { } }) }); + const textFragment = document.createDocumentFragment(); + const link = document.createElement("a"); + link.href="https://cloudinary.com/documentation/transformation_reference"; + link.text="View Cloudinary's transformation reference for guidance."; + textFragment.append("Add a comma-delimited default set of transformations to your uploads. "); + textFragment.append(link); + new Setting(containerEl) + .setName("Default Transformation Parameters") + .setDesc(textFragment); + .addText((text) => { + text + .setValue(this.plugin.settings.transformParams) + .onChange(async (value) => { + try { + this.plugin.settings.transformParams = value; + await this.plugin.saveSettings(); + } + catch (e) { + console.log(e) + } + }) + }); } } \ No newline at end of file From 12963f1881ff50b2d118598d25de8983c04fd19a Mon Sep 17 00:00:00 2001 From: Jordan Handy <6423379+jordanhandy@users.noreply.github.com> Date: Sat, 8 Apr 2023 20:11:38 -0400 Subject: [PATCH 07/19] transformation option add --- main.js | 28 ++++++++++++++++++++++++++-- src/main.ts | 11 ++++++++++- src/settings-tab.ts | 2 +- 3 files changed, 37 insertions(+), 4 deletions(-) diff --git a/main.js b/main.js index b90a42f..4c8b97b 100755 --- a/main.js +++ b/main.js @@ -2679,6 +2679,22 @@ var CloudinaryUploaderSettingTab = class extends import_obsidian.PluginSettingTa } }); }); + const textFragment = document.createDocumentFragment(); + const link = document.createElement("a"); + link.href = "https://cloudinary.com/documentation/transformation_reference"; + link.text = "View Cloudinary's transformation reference for guidance."; + textFragment.append("Add a comma-delimited default set of transformations to your uploads. "); + textFragment.append(link); + new import_obsidian.Setting(containerEl).setName("Default Transformation Parameters").setDesc(textFragment).addText((text) => { + text.setValue(this.plugin.settings.transformParams).onChange(async (value) => { + try { + this.plugin.settings.transformParams = value; + await this.plugin.saveSettings(); + } catch (e) { + console.log(e); + } + }); + }); } }; var settings_tab_default = CloudinaryUploaderSettingTab; @@ -2688,7 +2704,8 @@ var DEFAULT_SETTINGS = { cloudName: null, uploadPreset: null, folder: null, - f_auto: false + f_auto: false, + transformParams: null }; var CloudinaryUploader = class extends import_obsidian2.Plugin { setupPasteHandler() { @@ -2712,8 +2729,15 @@ var CloudinaryUploader = class extends import_obsidian2.Plugin { data: formData }).then((res) => { console.log(res); - const url = import_object_path.default.get(res.data, "secure_url"); + let url = import_object_path.default.get(res.data, "secure_url"); let imgMarkdownText = ""; + if (this.settings.transformParams) { + const splitURL = url.split("/upload/", 2); + let modifiedURL = ""; + modifiedURL = splitURL[0] += "/upload/" + this.settings.transformParams + "/" + splitURL[1]; + imgMarkdownText = `![](${modifiedURL})`; + url = modifiedURL; + } if (this.settings.f_auto) { const splitURL = url.split("/upload/", 2); let modifiedURL = ""; diff --git a/src/main.ts b/src/main.ts index 93d35f1..886b9d4 100755 --- a/src/main.ts +++ b/src/main.ts @@ -18,6 +18,7 @@ interface CloudinarySettings { uploadPreset: string; folder: string; f_auto: boolean; + transformParams: string; //maxWidth: number; TODO // enableResize: boolean; TODO } @@ -28,6 +29,7 @@ const DEFAULT_SETTINGS: CloudinarySettings = { uploadPreset: null, folder: null, f_auto: false, + transformParams: null, //maxWidth: 4096, TODO //enableResize: false, TODO later }; @@ -65,8 +67,15 @@ export default class CloudinaryUploader extends Plugin { }).then(res => { // Get response public URL of uploaded image console.log(res); - const url = objectPath.get(res.data, 'secure_url') + let url = objectPath.get(res.data, 'secure_url') let imgMarkdownText =""; + if(this.settings.transformParams){ + const splitURL = url.split("/upload/",2); + let modifiedURL=''; + modifiedURL = splitURL[0]+="/upload/"+this.settings.transformParams+"/"+splitURL[1]; + imgMarkdownText = `![](${modifiedURL})`; + url = modifiedURL + } if(this.settings.f_auto){ const splitURL = url.split("/upload/",2); let modifiedURL=''; diff --git a/src/settings-tab.ts b/src/settings-tab.ts index c22ec7a..7b8f493 100755 --- a/src/settings-tab.ts +++ b/src/settings-tab.ts @@ -93,7 +93,7 @@ export default class CloudinaryUploaderSettingTab extends PluginSettingTab { textFragment.append(link); new Setting(containerEl) .setName("Default Transformation Parameters") - .setDesc(textFragment); + .setDesc(textFragment) .addText((text) => { text .setValue(this.plugin.settings.transformParams) From b65d47f6b28cafe005f633763c4d43f8aa836f4f Mon Sep 17 00:00:00 2001 From: Jordan Handy <6423379+jordanhandy@users.noreply.github.com> Date: Sat, 8 Apr 2023 20:27:30 -0400 Subject: [PATCH 08/19] add better description of options --- main.js | 24 ++++++++++++++++++++---- src/settings-tab.ts | 26 +++++++++++++++++++++++--- 2 files changed, 43 insertions(+), 7 deletions(-) diff --git a/main.js b/main.js index 4c8b97b..bf759f1 100755 --- a/main.js +++ b/main.js @@ -2669,7 +2669,23 @@ var CloudinaryUploaderSettingTab = class extends import_obsidian.PluginSettingTa } }); }); - new import_obsidian.Setting(containerEl).setName("f_auto Option").setDesc("Enable f_auto option for image uploads").addToggle((toggle) => { + containerEl.createEl("h4", {text: "URL Manipulations / Transformation"}); + let textFragment = document.createDocumentFragment(); + let link = document.createElement("a"); + link.href = "https://cloudinary.com/documentation/transformation_reference"; + link.text = " Cloudinary documentation"; + textFragment.append("The settings below are meant for default image transformations. As they only touch the resulting URL, this should not cause any upload errors, however, if syntax is incorrect, your images will not be referenced correctly (won't render). Be mindful of your Cloudinary transformation limits and use the"); + textFragment.append(link); + textFragment.append(" for guidance."); + containerEl.createEl("p", {text: textFragment}); + textFragment = document.createDocumentFragment(); + link = document.createElement("a"); + link.href = "https://cloudinary.com/documentation/image_optimization#automatic_format_selection_f_auto"; + link.text = "f_auto option"; + textFragment.append("Enable the "); + textFragment.append(link); + textFragment.append(" for uploads"); + new import_obsidian.Setting(containerEl).setName("f_auto Option").setDesc(textFragment).addToggle((toggle) => { toggle.setValue(this.plugin.settings.f_auto).onChange(async (value) => { try { this.plugin.settings.f_auto = value; @@ -2679,14 +2695,14 @@ var CloudinaryUploaderSettingTab = class extends import_obsidian.PluginSettingTa } }); }); - const textFragment = document.createDocumentFragment(); - const link = document.createElement("a"); + textFragment = document.createDocumentFragment(); + link = document.createElement("a"); link.href = "https://cloudinary.com/documentation/transformation_reference"; link.text = "View Cloudinary's transformation reference for guidance."; textFragment.append("Add a comma-delimited default set of transformations to your uploads. "); textFragment.append(link); new import_obsidian.Setting(containerEl).setName("Default Transformation Parameters").setDesc(textFragment).addText((text) => { - text.setValue(this.plugin.settings.transformParams).onChange(async (value) => { + text.setPlaceholder("w_150,h_150").setValue(this.plugin.settings.transformParams).onChange(async (value) => { try { this.plugin.settings.transformParams = value; await this.plugin.saveSettings(); diff --git a/src/settings-tab.ts b/src/settings-tab.ts index 7b8f493..674dea7 100755 --- a/src/settings-tab.ts +++ b/src/settings-tab.ts @@ -69,9 +69,28 @@ export default class CloudinaryUploaderSettingTab extends PluginSettingTab { } }) }); + containerEl.createEl("h4", { text: "URL Manipulations / Transformation" }); + let textFragment = document.createDocumentFragment(); + let link = document.createElement("a"); + link.href = "https://cloudinary.com/documentation/transformation_reference"; + link.text = " Cloudinary documentation" + textFragment.append("The settings below are meant for default image transformations. As they only touch the resulting URL, this should not cause any upload errors, however, if syntax is incorrect, your images will not be referenced correctly (won't render). Be mindful of your Cloudinary transformation limits and use the") + textFragment.append(link); + textFragment.append(" for guidance."); + containerEl.createEl("p", { text: textFragment }); + + + textFragment = document.createDocumentFragment(); + link = document.createElement("a"); + link.href="https://cloudinary.com/documentation/image_optimization#automatic_format_selection_f_auto"; + link.text="f_auto option"; + textFragment.append("Enable the "); + textFragment.append(link); + textFragment.append(" for uploads"); + new Setting(containerEl) .setName("f_auto Option") - .setDesc("Enable f_auto option for image uploads") + .setDesc(textFragment) .addToggle((toggle) => { toggle .setValue(this.plugin.settings.f_auto) @@ -85,8 +104,8 @@ export default class CloudinaryUploaderSettingTab extends PluginSettingTab { } }) }); - const textFragment = document.createDocumentFragment(); - const link = document.createElement("a"); + textFragment = document.createDocumentFragment(); + link = document.createElement("a"); link.href="https://cloudinary.com/documentation/transformation_reference"; link.text="View Cloudinary's transformation reference for guidance."; textFragment.append("Add a comma-delimited default set of transformations to your uploads. "); @@ -96,6 +115,7 @@ export default class CloudinaryUploaderSettingTab extends PluginSettingTab { .setDesc(textFragment) .addText((text) => { text + .setPlaceholder("w_150,h_150") .setValue(this.plugin.settings.transformParams) .onChange(async (value) => { try { From 17a595d7297f5636b81330a18ba95c1e5a211db9 Mon Sep 17 00:00:00 2001 From: Jordan Handy <6423379+jordanhandy@users.noreply.github.com> Date: Sat, 8 Apr 2023 20:36:39 -0400 Subject: [PATCH 09/19] improve settings descriptions --- main.js | 9 +++++++-- src/settings-tab.ts | 9 +++++++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/main.js b/main.js index bf759f1..d8a550f 100755 --- a/main.js +++ b/main.js @@ -2672,9 +2672,14 @@ var CloudinaryUploaderSettingTab = class extends import_obsidian.PluginSettingTa containerEl.createEl("h4", {text: "URL Manipulations / Transformation"}); let textFragment = document.createDocumentFragment(); let link = document.createElement("a"); + const linkTransformation = document.createElement("a"); + linkTransformation.text = "transformation limits "; + linkTransformation.href = "https://cloudinary.com/documentation/transformation_counts"; + textFragment.append("The settings below are meant for default image transformations. As they only touch the resulting URL, this should not cause any upload errors, however, if syntax is incorrect, your images will not be referenced correctly (won't render). Be mindful of your Cloudinary "); + textFragment.append(linkTransformation); + textFragment.append(" and use the "); link.href = "https://cloudinary.com/documentation/transformation_reference"; link.text = " Cloudinary documentation"; - textFragment.append("The settings below are meant for default image transformations. As they only touch the resulting URL, this should not cause any upload errors, however, if syntax is incorrect, your images will not be referenced correctly (won't render). Be mindful of your Cloudinary transformation limits and use the"); textFragment.append(link); textFragment.append(" for guidance."); containerEl.createEl("p", {text: textFragment}); @@ -2699,7 +2704,7 @@ var CloudinaryUploaderSettingTab = class extends import_obsidian.PluginSettingTa link = document.createElement("a"); link.href = "https://cloudinary.com/documentation/transformation_reference"; link.text = "View Cloudinary's transformation reference for guidance."; - textFragment.append("Add a comma-delimited default set of transformations to your uploads. "); + textFragment.append("Add a comma-delimited default set of transformations to your uploads. You do NOT need to include f_auto here if already enabled above."); textFragment.append(link); new import_obsidian.Setting(containerEl).setName("Default Transformation Parameters").setDesc(textFragment).addText((text) => { text.setPlaceholder("w_150,h_150").setValue(this.plugin.settings.transformParams).onChange(async (value) => { diff --git a/src/settings-tab.ts b/src/settings-tab.ts index 674dea7..c75aef5 100755 --- a/src/settings-tab.ts +++ b/src/settings-tab.ts @@ -72,9 +72,14 @@ export default class CloudinaryUploaderSettingTab extends PluginSettingTab { containerEl.createEl("h4", { text: "URL Manipulations / Transformation" }); let textFragment = document.createDocumentFragment(); let link = document.createElement("a"); + const linkTransformation = document.createElement("a"); + linkTransformation.text="transformation limits "; + linkTransformation.href="https://cloudinary.com/documentation/transformation_counts"; + textFragment.append("The settings below are meant for default image transformations. As they only touch the resulting URL, this should not cause any upload errors, however, if syntax is incorrect, your images will not be referenced correctly (won't render). Be mindful of your Cloudinary "); + textFragment.append(linkTransformation); + textFragment.append(" and use the "); link.href = "https://cloudinary.com/documentation/transformation_reference"; link.text = " Cloudinary documentation" - textFragment.append("The settings below are meant for default image transformations. As they only touch the resulting URL, this should not cause any upload errors, however, if syntax is incorrect, your images will not be referenced correctly (won't render). Be mindful of your Cloudinary transformation limits and use the") textFragment.append(link); textFragment.append(" for guidance."); containerEl.createEl("p", { text: textFragment }); @@ -108,7 +113,7 @@ export default class CloudinaryUploaderSettingTab extends PluginSettingTab { link = document.createElement("a"); link.href="https://cloudinary.com/documentation/transformation_reference"; link.text="View Cloudinary's transformation reference for guidance."; - textFragment.append("Add a comma-delimited default set of transformations to your uploads. "); + textFragment.append("Add a comma-delimited default set of transformations to your uploads. You do NOT need to include f_auto here if already enabled above."); textFragment.append(link); new Setting(containerEl) .setName("Default Transformation Parameters") From 16c8ec48c02ba42e051d78c7ebbe960c2df7be12 Mon Sep 17 00:00:00 2001 From: Jordan Handy <6423379+jordanhandy@users.noreply.github.com> Date: Sat, 8 Apr 2023 21:12:40 -0400 Subject: [PATCH 10/19] add comments --- main.js | 2 +- src/main.ts | 4 ++++ src/settings-tab.ts | 7 ++++++- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/main.js b/main.js index d8a550f..21ec05a 100755 --- a/main.js +++ b/main.js @@ -2704,7 +2704,7 @@ var CloudinaryUploaderSettingTab = class extends import_obsidian.PluginSettingTa link = document.createElement("a"); link.href = "https://cloudinary.com/documentation/transformation_reference"; link.text = "View Cloudinary's transformation reference for guidance."; - textFragment.append("Add a comma-delimited default set of transformations to your uploads. You do NOT need to include f_auto here if already enabled above."); + textFragment.append("Add a comma-delimited default set of transformations to your uploads. You do NOT need to include f_auto here if already enabled above. "); textFragment.append(link); new import_obsidian.Setting(containerEl).setName("Default Transformation Parameters").setDesc(textFragment).addText((text) => { text.setPlaceholder("w_150,h_150").setValue(this.plugin.settings.transformParams).onChange(async (value) => { diff --git a/src/main.ts b/src/main.ts index 886b9d4..e36d4b2 100755 --- a/src/main.ts +++ b/src/main.ts @@ -69,6 +69,8 @@ export default class CloudinaryUploader extends Plugin { console.log(res); let url = objectPath.get(res.data, 'secure_url') let imgMarkdownText =""; + + // Split URL to allow for appending transformations if(this.settings.transformParams){ const splitURL = url.split("/upload/",2); let modifiedURL=''; @@ -81,6 +83,8 @@ export default class CloudinaryUploader extends Plugin { let modifiedURL=''; modifiedURL = splitURL[0]+="/upload/f_auto/"+splitURL[1]; imgMarkdownText = `![](${modifiedURL})`; + + // leave stamdard of no transformations added }else{ imgMarkdownText = `![](${url})`; } diff --git a/src/settings-tab.ts b/src/settings-tab.ts index c75aef5..ab06c80 100755 --- a/src/settings-tab.ts +++ b/src/settings-tab.ts @@ -70,14 +70,19 @@ export default class CloudinaryUploaderSettingTab extends PluginSettingTab { }) }); containerEl.createEl("h4", { text: "URL Manipulations / Transformation" }); + + // Allow for inline hyperlinks with anchor tags let textFragment = document.createDocumentFragment(); let link = document.createElement("a"); + const linkTransformation = document.createElement("a"); linkTransformation.text="transformation limits "; linkTransformation.href="https://cloudinary.com/documentation/transformation_counts"; + textFragment.append("The settings below are meant for default image transformations. As they only touch the resulting URL, this should not cause any upload errors, however, if syntax is incorrect, your images will not be referenced correctly (won't render). Be mindful of your Cloudinary "); textFragment.append(linkTransformation); textFragment.append(" and use the "); + link.href = "https://cloudinary.com/documentation/transformation_reference"; link.text = " Cloudinary documentation" textFragment.append(link); @@ -113,7 +118,7 @@ export default class CloudinaryUploaderSettingTab extends PluginSettingTab { link = document.createElement("a"); link.href="https://cloudinary.com/documentation/transformation_reference"; link.text="View Cloudinary's transformation reference for guidance."; - textFragment.append("Add a comma-delimited default set of transformations to your uploads. You do NOT need to include f_auto here if already enabled above."); + textFragment.append("Add a comma-delimited default set of transformations to your uploads. You do NOT need to include f_auto here if already enabled above. "); textFragment.append(link); new Setting(containerEl) .setName("Default Transformation Parameters") From 6695d8a0f9c68f6987467daa8c9d79ad8192a040 Mon Sep 17 00:00:00 2001 From: Jordan Handy <6423379+jordanhandy@users.noreply.github.com> Date: Sat, 8 Apr 2023 21:13:10 -0400 Subject: [PATCH 11/19] update manifest --- manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manifest.json b/manifest.json index 1c4807e..dd454af 100755 --- a/manifest.json +++ b/manifest.json @@ -5,5 +5,5 @@ "author": "Jordan Handy", "isDesktopOnly": true, "minAppVersion": "0.11.0", - "version": "0.1.6" + "version": "0.2.0" } From 332800c074b5a0a1c36fe4679226b8d90dd1dade Mon Sep 17 00:00:00 2001 From: Jordan Handy <6423379+jordanhandy@users.noreply.github.com> Date: Sat, 8 Apr 2023 21:13:57 -0400 Subject: [PATCH 12/19] update README --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 2c11bc5..d510c14 100755 --- a/README.md +++ b/README.md @@ -23,6 +23,8 @@ This plugin allows you to automatically upload images pasted to Obsidian directl - Cloud Name - Upload Preset Name ([Set that here](https://cloudinary.com/documentation/upload_presets)) - Set a Folder Name +5. Optional configuration + - Cloudinary default transformation parameters ## Unsigned vs. Signed Uploads to Cloudinary The uploads to Cloudinary are unsigned. [You can read more about that here](https://cloudinary.com/documentation/upload_images#unsigned_upload). A signed upload would require the use of an API key and secret, and I opted against asking for that in the plugin configuration, as a choice for security reasons. From 34036af04b56ca1337d9b738e83a11c0159dccec Mon Sep 17 00:00:00 2001 From: Jordan Handy <6423379+jordanhandy@users.noreply.github.com> Date: Sat, 8 Apr 2023 22:25:02 -0400 Subject: [PATCH 13/19] update docs --- docs/assets/obsidian-settings-page.png | Bin 0 -> 109504 bytes docs/assets/obsidian-settings.png | Bin 119609 -> 0 bytes docs/configuring-the-plugin.md | 3 ++- docs/index.md | 2 +- 4 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 docs/assets/obsidian-settings-page.png delete mode 100644 docs/assets/obsidian-settings.png diff --git a/docs/assets/obsidian-settings-page.png b/docs/assets/obsidian-settings-page.png new file mode 100644 index 0000000000000000000000000000000000000000..ee0577f8747f862d1aecfdd1d1f4c2bebc45a04c GIT binary patch literal 109504 zcmc$`byQp5*FFdoinKtXEfjaR;x5I5yGx6^dm5xbaS!h9?oM%c_u@`*hhO@Y_tWyu z%wIEW)=Cza^WiFzznoA7Mi^fRVH`6gA`+0SemB6bknDDUdfdNn#EM2KV#=;DM92+aUY zdEs}jbOw~=%fEg5CQ%8zm~W~&G zuZXP0#PwiHOz?laRiFf`0aT3xkiJ@(u%C{0JotwuB5)ETqWZ8r{w3Y4J z&vbb6ktjUI$yZRQ0PFaZ6qfud?BB9L!4|#k?e8b^@bI7yFGTtzrEctt`@hCO?;RQ- zvbJVeXZ^oasErMpot=)wjs8+F&P%%^kS~i%^Z*76@8CMYiA5RDc^XF?b zL}01mC!62F`g(`_%{R-Ka*DTl{rD1;FaA1>P>vp<%6uZp%^@H=Wr<4zw-h0t+iG9v z;m#qqtqm&3@Squy(U5@({Nit`QJ%q~;PZ)ca&ju=I!W(MHAnTiuo7(^Zi;M=P{>Qz zB>>#z83=O%C0=iS`rC8;v|bwb>+ll3Hsdi`i_ zd9R*HxrGq-s=&Ruk!FUkTs#^a9tjYVimuP@@qFfRT(UGwrKygB2y}&Q$!_B85M(_G z5-*a!Bh6D04dSjZsx3V0NhLasTV>{{<&1n@apMzhoX^jEGkPiR>gqP0E!p>-SE<@e zE#y=+33BuIe%O1@!WXO#lMp_BDL$0a2!2e_N01+xL&?q~19P;jcNz7c1*{l?uqcbt z6xz@TTHteUuG+!MB+JOze~+_+xX|ZWfZ!5^M?|C-2uX1YqB%bMPAdkg6FflAOOEn) ze5@is`%{VSq(2vO0P=9y&1Ls=J{t#@2#RqNfp-$_@2Ixng>n5(B_vh9Jg(pU=hFl^ zMtR%YAqK=V@_+d(YmhA1Fazfqw-{%oAk-@1Vb_q_j}N9#x-rij&YlEVIboU}UF)7H75W2yI; zgnM4ku3>{#%h3WpFarPfqSxA+&u8yCm2BJ6QJyI`@D_6S8?oOj%U|~i6l$yFh?ax@ z>qE#nTG0ZT-!FFNtEK90>i1rFx;_*8U6_EV+sm7~8$qe}s03!u1*G=6?yLmIBMyKI zOZc~tpLrk3Yp{q`EeChiui%-H=*8QXmO`lSt|2yDo!9Sw_BF~Ie~U>^^G39c8%`)R z{ zrwvtYb?+dbTJk12%0@X{7#mctG#y(r%;xpMnQqDTquAWqlDE^znUv>pnRst^yeG32X_brAA{G}H)d&s8<|?;M z)?+MLEay?l1$3|_V zzDaRAEw^LH$;e0;eH+Fr%v#_lpDhtR$un^?FqSLZGto%!bL017#oW@RiLc+&{bn8G}6ow z!^FfS)ep`NT3pm(P0Er4NZ9xjHbvTI(;}Dm>SNjU5V~FKqEgxxD#y6qoaQulhmh=; z>(th+-1$!zFQgeRfX+`(b9CKrMWe&G9TRjuJOq}P6gPpZSjcjOn^Jh4m(}1Y{)(B; z4A8k~iUc0lDFNZ=1l^fEvT|zTtVqbn@;qkKMZ*k71QQ?<{OZ^dX&UFlc~-Zze9Sz_ zZM6h`j}vJezf3&%m$0KGs39NONFrn}4;I9T9TM1sR8*)@QBmDo&nsD6#K*e8iJB>9 zLR@+B%?;%QoaND1=MxO$X`dcU&bBNaZtN-myniQ8p1iP0f>I%_Cs;_RrKU;8I8n

;!u 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∓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 Date: Sat, 8 Apr 2023 22:31:18 -0400 Subject: [PATCH 14/19] update GH action --- .github/workflows/retype.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/retype.yml b/.github/workflows/retype.yml index e8cdf77..75d968e 100644 --- a/.github/workflows/retype.yml +++ b/.github/workflows/retype.yml @@ -11,12 +11,15 @@ jobs: runs-on: ubuntu-latest + permissions: + contents: write + steps: - uses: actions/checkout@v2 - - uses: retypeapp/action-build@v1 + - uses: retypeapp/action-build@latest - - uses: retypeapp/action-github-pages@v1 + - uses: retypeapp/action-github-pages@latest with: branch: retype update-branch: true \ No newline at end of file From 565b06c2f759295db5c70103df9440b3f233e8de Mon Sep 17 00:00:00 2001 From: Jordan Handy <6423379+jordanhandy@users.noreply.github.com> Date: Sun, 9 Apr 2023 10:59:51 -0400 Subject: [PATCH 15/19] update README --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index d510c14..3b49773 100755 --- a/README.md +++ b/README.md @@ -28,6 +28,14 @@ This plugin allows you to automatically upload images pasted to Obsidian directl ## Unsigned vs. Signed Uploads to Cloudinary The uploads to Cloudinary are unsigned. [You can read more about that here](https://cloudinary.com/documentation/upload_images#unsigned_upload). A signed upload would require the use of an API key and secret, and I opted against asking for that in the plugin configuration, as a choice for security reasons. + +## Transformations +Cloudinary allows for on-the-fly image transformations using their API. To the end-user, this is accomplished by making a simple URL modification to the resulting URL that Cloudinary gives back when an upload completes. You can [read more about Cloudinary's transformation parameters here](https://cloudinary.com/documentation/transformation_reference). +As of version 0.2.0, you can now set a default transformation to be applied to all of your uploads with a comma-delimited list. **Be mindful of syntax**, as using the incorrect transformation parameters will cause your images to not render in Obsidian. + +If this were to happen, this can be fixed by simply modifying the URL following the upload. + +**Be Mindful of your [transformation token allotment](https://cloudinary.com/blog/understanding_cloudinary_s_transformation_quotas)**. Depending on your plan, Cloudinary allows for an 'x' number of transformations to take place per month. Keep this count in mind as you apply transformations to your uploads ## Thanks Special thanks to: 1. @Creling and [their repo here](https://github.com/Creling/obsidian-image-uploader). As this was my first time creating an Obsidian plugin, their base really helped. From 1a7f1181a3047e548adb174fda3486427fae6e42 Mon Sep 17 00:00:00 2001 From: Jordan Handy <6423379+jordanhandy@users.noreply.github.com> Date: Sun, 9 Apr 2023 11:20:02 -0400 Subject: [PATCH 16/19] update README --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 3b49773..bc7d938 100755 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # Obsidian Cloudinary Uploader ![Downloads](https://img.shields.io/github/downloads/jordanhandy/obsidian-cloudinary-uploader/main.js.svg) +![Version](https://img.shields.io/github/manifest-json/v/jordanhandy/obsidian-cloudinary-uploader?color=blue) ## Documentation [Documentation](https://jordanhandy.github.io/obsidian-cloudinary-uploader/) From 393b3355aac615f366c065c257bf7b2fe3e508e0 Mon Sep 17 00:00:00 2001 From: Linnnkkk <106414095+Linnnkkk@users.noreply.github.com> Date: Sun, 19 Nov 2023 21:04:31 +0800 Subject: [PATCH 17/19] Add files via upload --- src/base/constants.ts | 4 + src/base/emo-fragment.ts | 18 +++ src/base/emo-parms.ts | 3 + src/base/emo-uploader.ts | 17 ++ src/config.ts | 47 ++++++ src/fragment/fragment-alist.ts | 61 ++++++++ src/fragment/fragment-catbox.ts | 27 ++++ src/fragment/fragment-chevereto.ts | 38 +++++ src/fragment/fragment-cloudinary.ts | 51 ++++++ src/fragment/fragment-github.ts | 112 +++++++++++++ src/fragment/fragment-imgbb.ts | 27 ++++ src/fragment/fragment-imgur.ts | 159 +++++++++++++++++++ src/fragment/fragment-imgurl.ts | 38 +++++ src/fragment/fragment-smms.ts | 27 ++++ src/lang/helpers.ts | 56 +++++++ src/lang/locale/ar.ts | 3 + src/lang/locale/cz.ts | 3 + src/lang/locale/da.ts | 3 + src/lang/locale/de.ts | 3 + src/lang/locale/en-gb.ts | 3 + src/lang/locale/en.ts | 58 +++++++ src/lang/locale/es.ts | 3 + src/lang/locale/fr.ts | 3 + src/lang/locale/hi.ts | 3 + src/lang/locale/id.ts | 3 + src/lang/locale/it.ts | 3 + src/lang/locale/ja.ts | 3 + src/lang/locale/ko.ts | 3 + src/lang/locale/nl.ts | 3 + src/lang/locale/no.ts | 3 + src/lang/locale/pl.ts | 3 + src/lang/locale/pt-br.ts | 4 + src/lang/locale/pt.ts | 3 + src/lang/locale/ro.ts | 3 + src/lang/locale/ru.ts | 3 + src/lang/locale/tr.ts | 3 + src/lang/locale/zh-cn.ts | 58 +++++++ src/lang/locale/zh-tw.ts | 58 +++++++ src/main.ts | 234 +++++++++++++--------------- src/parms/parms-alist.ts | 22 +++ src/parms/parms-catbox.ts | 15 ++ src/parms/parms-chevereto.ts | 17 ++ src/parms/parms-cloudinary.ts | 19 +++ src/parms/parms-github.ts | 32 ++++ src/parms/parms-imgbb.ts | 13 ++ src/parms/parms-imgur.ts | 17 ++ src/parms/parms-imgurl.ts | 15 ++ src/parms/parms-smms.ts | 13 ++ src/settings-tab.ts | 223 +++++++++++--------------- src/styles.css | 4 + src/uploader/uploader-alist.ts | 205 ++++++++++++++++++++++++ src/uploader/uploader-catbox.ts | 37 +++++ src/uploader/uploader-chevereto.ts | 51 ++++++ src/uploader/uploader-cloudinary.ts | 37 +++++ src/uploader/uploader-github.ts | 65 ++++++++ src/uploader/uploader-imgbb.ts | 38 +++++ src/uploader/uploader-imgur.ts | 60 +++++++ src/uploader/uploader-imgurl.ts | 38 +++++ src/uploader/uploader-smms.ts | 44 ++++++ src/utils/emo-formdata.ts | 53 +++++++ src/utils/file-helper.ts | 42 +++++ 61 files changed, 1958 insertions(+), 256 deletions(-) create mode 100644 src/base/constants.ts create mode 100644 src/base/emo-fragment.ts create mode 100644 src/base/emo-parms.ts create mode 100644 src/base/emo-uploader.ts create mode 100644 src/config.ts create mode 100644 src/fragment/fragment-alist.ts create mode 100644 src/fragment/fragment-catbox.ts create mode 100644 src/fragment/fragment-chevereto.ts create mode 100644 src/fragment/fragment-cloudinary.ts create mode 100644 src/fragment/fragment-github.ts create mode 100644 src/fragment/fragment-imgbb.ts create mode 100644 src/fragment/fragment-imgur.ts create mode 100644 src/fragment/fragment-imgurl.ts create mode 100644 src/fragment/fragment-smms.ts create mode 100644 src/lang/helpers.ts create mode 100644 src/lang/locale/ar.ts create mode 100644 src/lang/locale/cz.ts create mode 100644 src/lang/locale/da.ts create mode 100644 src/lang/locale/de.ts create mode 100644 src/lang/locale/en-gb.ts create mode 100644 src/lang/locale/en.ts create mode 100644 src/lang/locale/es.ts create mode 100644 src/lang/locale/fr.ts create mode 100644 src/lang/locale/hi.ts create mode 100644 src/lang/locale/id.ts create mode 100644 src/lang/locale/it.ts create mode 100644 src/lang/locale/ja.ts create mode 100644 src/lang/locale/ko.ts create mode 100644 src/lang/locale/nl.ts create mode 100644 src/lang/locale/no.ts create mode 100644 src/lang/locale/pl.ts create mode 100644 src/lang/locale/pt-br.ts create mode 100644 src/lang/locale/pt.ts create mode 100644 src/lang/locale/ro.ts create mode 100644 src/lang/locale/ru.ts create mode 100644 src/lang/locale/tr.ts create mode 100644 src/lang/locale/zh-cn.ts create mode 100644 src/lang/locale/zh-tw.ts create mode 100644 src/parms/parms-alist.ts create mode 100644 src/parms/parms-catbox.ts create mode 100644 src/parms/parms-chevereto.ts create mode 100644 src/parms/parms-cloudinary.ts create mode 100644 src/parms/parms-github.ts create mode 100644 src/parms/parms-imgbb.ts create mode 100644 src/parms/parms-imgur.ts create mode 100644 src/parms/parms-imgurl.ts create mode 100644 src/parms/parms-smms.ts create mode 100644 src/styles.css create mode 100644 src/uploader/uploader-alist.ts create mode 100644 src/uploader/uploader-catbox.ts create mode 100644 src/uploader/uploader-chevereto.ts create mode 100644 src/uploader/uploader-cloudinary.ts create mode 100644 src/uploader/uploader-github.ts create mode 100644 src/uploader/uploader-imgbb.ts create mode 100644 src/uploader/uploader-imgur.ts create mode 100644 src/uploader/uploader-imgurl.ts create mode 100644 src/uploader/uploader-smms.ts create mode 100644 src/utils/emo-formdata.ts create mode 100644 src/utils/file-helper.ts diff --git a/src/base/constants.ts b/src/base/constants.ts new file mode 100644 index 0000000..c9f6b05 --- /dev/null +++ b/src/base/constants.ts @@ -0,0 +1,4 @@ +export const IMGUR_ACCESS_TOKEN_LOCALSTORAGE_KEY = 'imgur-access_token' +export const IMGUR_DEFAULT_ID = '4547d4aee97ce8f' +export const RANDOM_BOUNDARY = 'loveaimeainixucheng' // magic, random, i just use it +export const CONTENT_TYPE_FORMDATA = 'multipart/form-data;boundary=' + RANDOM_BOUNDARY diff --git a/src/base/emo-fragment.ts b/src/base/emo-fragment.ts new file mode 100644 index 0000000..258afdd --- /dev/null +++ b/src/base/emo-fragment.ts @@ -0,0 +1,18 @@ +import { HostingProvider } from '../config' +import Emo from '../main' + +export abstract class EmoFragment { + kind: HostingProvider + element: HTMLDivElement + protected constructor (kind: HostingProvider, el: HTMLElement, plugin: Emo) { + this.kind = kind + this.element = el.createDiv(kind) + this.display(this.element, plugin) + this.element.hide() + } + abstract display (el: HTMLElement, plugin: Emo): void + + update (choice: HostingProvider): void { + this.kind === choice ? this.element.show() : this.element.hide() + } +} diff --git a/src/base/emo-parms.ts b/src/base/emo-parms.ts new file mode 100644 index 0000000..931cad3 --- /dev/null +++ b/src/base/emo-parms.ts @@ -0,0 +1,3 @@ +export interface EmoParms { + required: any // all string +} diff --git a/src/base/emo-uploader.ts b/src/base/emo-uploader.ts new file mode 100644 index 0000000..33b5190 --- /dev/null +++ b/src/base/emo-uploader.ts @@ -0,0 +1,17 @@ +import { EmoParms } from './emo-parms' + +export abstract class EmoUploader { + parms!: EmoParms + abstract upload (file: File): Promise + isValid (): boolean { // check the necessary parameters, type: string + let result = true + for (const i in this.parms.required) { + result &&= notEmpty(this.parms.required[i]) + if (!result) return false + } + return true + } +} +function notEmpty (value: string): boolean { + return value.length > 0 +} diff --git a/src/config.ts b/src/config.ts new file mode 100644 index 0000000..f100736 --- /dev/null +++ b/src/config.ts @@ -0,0 +1,47 @@ +import { CatboxParms, CATBOX_DEFAULT_PARMS } from './parms/parms-catbox' +import { CHEVERETO_DEFAULT_PARMS, CheveretoParms } from './parms/parms-chevereto' +import { CloudinaryParms, CLOUDINARY_DEFAULT_PARMS } from './parms/parms-cloudinary' +import { GithubParms, GITHUB_DEFAULT_PARMS } from './parms/parms-github' +import { ImgbbParms, IMGBB_DEFAULT_PARMS } from './parms/parms-imgbb' +import { ImgurParms, IMGUR_DEFAULT_PARMS } from './parms/parms-imgur' +import { ImgurlParms, IMGURL_DEFAULT_PARMS } from './parms/parms-imgurl' +import { SmmsParms, SMMS_DEFAULT_PARMS } from './parms/parms-smms' +import { ALIST_DEFAULT_PARMS, AlistParms } from './parms/parms-alist' + +export interface Config { // data from data.json + choice: HostingProvider + github_parms: GithubParms + smms_parms: SmmsParms + imgurl_parms: ImgurlParms + cloudinary_parms: CloudinaryParms + imgbb_parms: ImgbbParms + imgur_parms: ImgurParms + catbox_parms: CatboxParms + chevereto_parms: CheveretoParms + alist_parms: AlistParms +} + +export enum HostingProvider { // target hosting + Github = 'Github', + Cloudinary = 'Cloudinary', + Catbox = 'Catbox', + Imgur = 'Imgur', + Smms = 'SM.MS', + ImgURL = 'ImgURL', + Imgbb = 'imgbb', + Chevereto = 'chevereto', + Alist = 'alist' +} + +export const DEFAULT_SETTINGS: Config = { + choice: HostingProvider.Github, + github_parms: GITHUB_DEFAULT_PARMS, + imgur_parms: IMGUR_DEFAULT_PARMS, + cloudinary_parms: CLOUDINARY_DEFAULT_PARMS, + smms_parms: SMMS_DEFAULT_PARMS, + imgurl_parms: IMGURL_DEFAULT_PARMS, + imgbb_parms: IMGBB_DEFAULT_PARMS, + catbox_parms: CATBOX_DEFAULT_PARMS, + chevereto_parms: CHEVERETO_DEFAULT_PARMS, + alist_parms: ALIST_DEFAULT_PARMS +} diff --git a/src/fragment/fragment-alist.ts b/src/fragment/fragment-alist.ts new file mode 100644 index 0000000..9e4bcfc --- /dev/null +++ b/src/fragment/fragment-alist.ts @@ -0,0 +1,61 @@ +import { Setting } from 'obsidian' +import Emo from '../main' +import { EmoFragment } from '../base/emo-fragment' +import { HostingProvider } from '../config' +import { t } from '../lang/helpers' + +export class AlistFragment extends EmoFragment { + constructor (el: HTMLElement, plugin: Emo) { + super(HostingProvider.Alist, el, plugin) + } + + display (el: HTMLElement, plugin: Emo): void { + const parms = plugin.config.alist_parms + el.createEl('h3', { text: 'Alist Settings'}) + + new Setting(el) + .setName(t('domain')) + .addText((text) => { + text + .setValue(parms.required.domain) + .onChange(async (value) => { + parms.required.domain = value + await plugin.saveSettings() + }) + }) + + new Setting(el) + .setName('username') + .addText((text) => { + text + .setValue(parms.required.username) + .onChange(async (value) => { + parms.required.username = value + await plugin.saveSettings() + }) + }) + + new Setting(el) + .setName('password') + .addText((text) => { + text + .setValue(parms.required.password) + .onChange(async (value) => { + parms.required.password = value + await plugin.saveSettings() + }) + }) + + new Setting(el) + .setName('uploadPath') + .addText((text) => { + text + .setValue(parms.required.uploadPath) + .onChange(async (value) => { + parms.required.uploadPath = value + await plugin.saveSettings() + }) + }) + + } +} diff --git a/src/fragment/fragment-catbox.ts b/src/fragment/fragment-catbox.ts new file mode 100644 index 0000000..c6d53a7 --- /dev/null +++ b/src/fragment/fragment-catbox.ts @@ -0,0 +1,27 @@ +import { Setting } from 'obsidian' +import Emo from '../main' +import { EmoFragment } from '../base/emo-fragment' +import { HostingProvider } from '../config' +import { t } from '../lang/helpers' + +export class CatboxFragment extends EmoFragment { + constructor (el: HTMLElement, plugin: Emo) { + super(HostingProvider.Catbox, el, plugin) + } + + display (el: HTMLElement, plugin: Emo): void { + const parms = plugin.config.catbox_parms + el.createEl('h3', { text: t('Catbox Settings') }) + + new Setting(el) + .setName('userhash') + .addText((text) => { + text + .setValue(parms.required.userhash) + .onChange(async (value) => { + parms.required.userhash = value + await plugin.saveSettings() + }) + }) + } +} diff --git a/src/fragment/fragment-chevereto.ts b/src/fragment/fragment-chevereto.ts new file mode 100644 index 0000000..ca776ad --- /dev/null +++ b/src/fragment/fragment-chevereto.ts @@ -0,0 +1,38 @@ +import { Setting } from 'obsidian' +import Emo from '../main' +import { EmoFragment } from '../base/emo-fragment' +import { HostingProvider } from '../config' +import { t } from '../lang/helpers' + +export class CheveretoFragment extends EmoFragment { + constructor (el: HTMLElement, plugin: Emo) { + super(HostingProvider.Chevereto, el, plugin) + } + + display (el: HTMLElement, plugin: Emo): void { + const parms = plugin.config.chevereto_parms + el.createEl('h3', { text: t('Chevereto Settings') }) + + new Setting(el) + .setName(t('domain')) + .addText((text) => { + text + .setValue(parms.required.domain) + .onChange(async (value) => { + parms.required.domain = value + await plugin.saveSettings() + }) + }) + + new Setting(el) + .setName('token') + .addText((text) => { + text + .setValue(parms.required.token) + .onChange(async (value) => { + parms.required.token = value + await plugin.saveSettings() + }) + }) + } +} diff --git a/src/fragment/fragment-cloudinary.ts b/src/fragment/fragment-cloudinary.ts new file mode 100644 index 0000000..eab98ca --- /dev/null +++ b/src/fragment/fragment-cloudinary.ts @@ -0,0 +1,51 @@ +import { Setting } from 'obsidian' +import Emo from '../main' +import { EmoFragment } from '../base/emo-fragment' +import { HostingProvider } from '../config' +import { t } from '../lang/helpers' + +export class CloudinaryFragment extends EmoFragment { + constructor (el: HTMLElement, plugin: Emo) { + super(HostingProvider.Cloudinary, el, plugin) + } + + display (el: HTMLElement, plugin: Emo): void { + const parms = plugin.config.cloudinary_parms + el.createEl('h3', { text: t('Cloudinary Settings') }) + + new Setting(el) + .setName('Cloud Name') + .addText((text) => { + text + .setValue(parms.required.name) + .onChange(async (value) => { + parms.required.name = value + await plugin.saveSettings() + }) + }) + + new Setting(el) + .setName('Upload Presets') + .addText((text) => { + text + .setValue(parms.required.present) + .onChange(async (value) => { + parms.required.present = value + await plugin.saveSettings() + }) + }) + + new Setting(el) + .setName('Upload Folder') + .setDesc(t('Upload Folder desc')) + .addText((text) => { + text + .setPlaceholder('obsidian -> obsidian/pic.png') + .setValue(parms.folder) + .onChange(async (value) => { + parms.folder = value + await plugin.saveSettings() + }) + }) + } +} diff --git a/src/fragment/fragment-github.ts b/src/fragment/fragment-github.ts new file mode 100644 index 0000000..5e85792 --- /dev/null +++ b/src/fragment/fragment-github.ts @@ -0,0 +1,112 @@ +import { Setting } from 'obsidian' +import Emo from '../main' +import { EmoFragment } from '../base/emo-fragment' +import { HostingProvider } from '../config' +import { t } from '../lang/helpers' +import { CDNprovider } from '../parms/parms-github' + +export class GithubFragment extends EmoFragment { + constructor (el: HTMLElement, plugin: Emo) { + super(HostingProvider.Github, el, plugin) + } + + display (el: HTMLElement, plugin: Emo): void { + const parms = plugin.config.github_parms + el.createEl('h3', { text: t('Github Settings') }) + + new Setting(el) + .setName(t('owner')) + .addText((text) => { + text + .setValue(parms.required.owner) + .onChange(async (value) => { + parms.required.owner = value + await plugin.saveSettings() + }) + }) + + new Setting(el) + .setName(t('repo')) + .addText((text) => { + text + .setValue(parms.required.repo) + .onChange(async (value) => { + parms.required.repo = value + await plugin.saveSettings() + }) + }) + + new Setting(el) + .setName(t('branch')) + .addText((text) => { + text + .setValue(parms.required.branch) + .onChange(async (value) => { + parms.required.branch = value + await plugin.saveSettings() + }) + }) + + new Setting(el) + .setName(t('token')) + .addText((text) => { + text + .setValue(parms.required.token) + .onChange(async (value) => { + parms.required.token = value + await plugin.saveSettings() + }) + }) + + new Setting(el) + .setName(t('message')) + .addText((text) => { + text + .setValue(parms.required.message) + .onChange(async (value) => { + parms.required.message = value + await plugin.saveSettings() + }) + }) + + new Setting(el) + .setName(t('path')) + .setDesc(t('not required')) + .addText((text) => { + text + .setPlaceholder('obsidian/ -> obsidian/pic.png') + .setValue(parms.path) + .onChange(async (value) => { + parms.path = value + await plugin.saveSettings() + }) + }) + + new Setting(el) + .setName(t('random filename')) + .setDesc(t('random filename desc')) + .addToggle((toggle) => { + toggle.setValue(parms.random) + toggle.onChange(async (value) => { + parms.random = value + await plugin.saveSettings() + }) + }) + + const supportList: string[] = [] + for (const key in CDNprovider) { + supportList.push(CDNprovider[key as keyof typeof CDNprovider]) + } + + new Setting(el) + .setName(t('cdn')) + .addDropdown((dropdown) => { + supportList.forEach((record) => { dropdown.addOption(record, record) }) + dropdown.setValue(parms.cdn) + .onChange(async (value) => { + parms.cdn = value as CDNprovider + await plugin.saveSettings() + }) + }) + } +} diff --git a/src/fragment/fragment-imgbb.ts b/src/fragment/fragment-imgbb.ts new file mode 100644 index 0000000..bf837d1 --- /dev/null +++ b/src/fragment/fragment-imgbb.ts @@ -0,0 +1,27 @@ +import { Setting } from 'obsidian' +import Emo from '../main' +import { EmoFragment } from '../base/emo-fragment' +import { HostingProvider } from '../config' +import { t } from '../lang/helpers' + +export class ImgbbFragment extends EmoFragment { + constructor (el: HTMLElement, plugin: Emo) { + super(HostingProvider.Imgbb, el, plugin) + } + + display (el: HTMLElement, plugin: Emo): void { + const parms = plugin.config.imgbb_parms + el.createEl('h3', { text: t('imgbb Settings') }) + + new Setting(el) + .setName('key') + .addText((text) => { + text + .setValue(parms.required.key) + .onChange(async (value) => { + parms.required.key = value + await plugin.saveSettings() + }) + }) + } +} diff --git a/src/fragment/fragment-imgur.ts b/src/fragment/fragment-imgur.ts new file mode 100644 index 0000000..65910e5 --- /dev/null +++ b/src/fragment/fragment-imgur.ts @@ -0,0 +1,159 @@ +import { ButtonComponent, Notice, request, RequestUrlParam, Setting } from 'obsidian' +import Emo from '../main' +import { EmoFragment } from '../base/emo-fragment' +import { HostingProvider } from '../config' +import { IMGUR_ACCESS_TOKEN_LOCALSTORAGE_KEY, IMGUR_DEFAULT_ID } from '../base/constants' +import { t } from '../lang/helpers' + +export class ImgurFragment extends EmoFragment { + loginState!: Setting + loginBtn!: ButtonComponent + imgurStateText = t('authenticate') + imgurBtnText = t('sign in') + authenticated = false + constructor (el: HTMLElement, plugin: Emo) { + super(HostingProvider.Imgur, el, plugin) + } + + async display (el: HTMLElement, plugin: Emo): Promise { + const parms = plugin.config.imgur_parms + el.createEl('h3', { text: t('tips') }) + el.createDiv().setText(t('tips text')) + // anonymous or authenticated + el.createEl('h3', { text: t('Imgur Settings') }) + + new Setting(el) + .setName(t('Anonymous Upload')) + .setDesc(t('Anonymous Upload desc')) + .addToggle((toggle) => { + toggle.setValue(parms.anonymous) + toggle.onChange(async (value) => { + parms.anonymous = value + await plugin.saveSettings() + }) + }) + + new Setting(el) + .setName(t('imgurid')) + .setDesc(t('built-in id desc')) + .addText((text) => { + text + .setValue(parms.clientid) + .onChange(async (value) => { + parms.clientid = value + await plugin.saveSettings() + }) + }) + + let hash = '' + new Setting(el) + .setName(t('delete')) + .setDesc(t('delete desc')) + .addText((text) => { + text + .setPlaceholder('deletehash') + .onChange(async (value) => { + hash = value + }) + }) + .addButton((bt) => { + bt.setCta() + .setButtonText(t('delete btn')).onClick(() => { + let auth = 'Client-ID ' + if (parms.clientid !== '') { auth += parms.clientid } else auth += IMGUR_DEFAULT_ID + const req: RequestUrlParam = { + url: 'https://api.imgur.com/3/image/' + hash, + method: 'DELETE', + headers: { + Authorization: auth + } + } + request(req).then(() => { + console.log(new Notice(t('delete done'), 2000)) + }).catch(() => { + console.log(new Notice(t('delete fail'), 2000)) + }) + }) + }) + + // auth part + await this.checkState() + this.loginState = new Setting(el) + this.loginState.setName(this.imgurStateText) + .setDesc(t('auth desc')) + .addButton((bt) => { + this.loginBtn = bt + this.loginBtn.setCta() + .setButtonText(this.imgurBtnText).onClick(async () => { + if (this.authenticated) { // log out + localStorage.removeItem(IMGUR_ACCESS_TOKEN_LOCALSTORAGE_KEY) + this.authenticated = this.drawLogin() + } else { // log in + let id = '' + if (parms.clientid !== '') { id += parms.clientid } else id += IMGUR_DEFAULT_ID + window.open(`https://api.imgur.com/oauth2/authorize?client_id=${id}&response_type=token`) + } + }) + }) + } + + // influence imgurStateText imgurBtnText authenticated + async checkState (): Promise { + try { + const currentUserName = await this.getAccountName() + if (currentUserName !== t('no sign in')) { + this.imgurStateText = t('imgur account') + `${currentUserName} ✅` + this.imgurBtnText = t('Sign Out') + this.authenticated = true + } + } catch (err) { + console.log(err) + } + } + + async getAccountName (): Promise { + const accessToken = localStorage.getItem(IMGUR_ACCESS_TOKEN_LOCALSTORAGE_KEY) + if (accessToken === null) { return t('no sign in') } + const r = await fetch('https://api.imgur.com/3/account/me', { + headers: new Headers({ Authorization: `Bearer ${accessToken}` }) + }) + if (!r.ok) { + throw new Error('Imgur account error') + } + return ((await r.json()) as AccountInfo).data.url + } + + drawLogin (): boolean { + this.imgurStateText = t('authenticate') + this.imgurBtnText = t('sign in') + this.loginState.setName(this.imgurStateText) + this.loginBtn.setButtonText(this.imgurBtnText) + return false + } +} + +interface AccountInfo { + success: boolean + status: number + data: { + id: number + created: number + + url: string + bio: string + avatar: string + avatar_name: string + cover: string + cover_name: string + reputation: number + reputation_name: string + + pro_expiration: boolean + + user_flow: { + status: boolean + } + + is_blocked: boolean + } +} diff --git a/src/fragment/fragment-imgurl.ts b/src/fragment/fragment-imgurl.ts new file mode 100644 index 0000000..e2a6f91 --- /dev/null +++ b/src/fragment/fragment-imgurl.ts @@ -0,0 +1,38 @@ +import { Setting } from 'obsidian' +import Emo from '../main' +import { EmoFragment } from '../base/emo-fragment' +import { HostingProvider } from '../config' +import { t } from '../lang/helpers' + +export class ImgurlFragment extends EmoFragment { + constructor (el: HTMLElement, plugin: Emo) { + super(HostingProvider.ImgURL, el, plugin) + } + + display (el: HTMLElement, plugin: Emo): void { + const parms = plugin.config.imgurl_parms + el.createEl('h3', { text: t('ImgURL Settings') }) + + new Setting(el) + .setName('uid') + .addText((text) => { + text + .setValue(parms.required.uid) + .onChange(async (value) => { + parms.required.uid = value + await plugin.saveSettings() + }) + }) + + new Setting(el) + .setName('token') + .addText((text) => { + text + .setValue(parms.required.token) + .onChange(async (value) => { + parms.required.token = value + await plugin.saveSettings() + }) + }) + } +} diff --git a/src/fragment/fragment-smms.ts b/src/fragment/fragment-smms.ts new file mode 100644 index 0000000..8884745 --- /dev/null +++ b/src/fragment/fragment-smms.ts @@ -0,0 +1,27 @@ +import { Setting } from 'obsidian' +import Emo from '../main' +import { EmoFragment } from '../base/emo-fragment' +import { HostingProvider } from '../config' +import { t } from '../lang/helpers' + +export class SmmsFragment extends EmoFragment { + constructor (el: HTMLElement, plugin: Emo) { + super(HostingProvider.Smms, el, plugin) + } + + display (el: HTMLElement, plugin: Emo): void { + const parms = plugin.config.smms_parms + el.createEl('h3', { text: t('SM.MS Settings') }) + + new Setting(el) + .setName('token') + .addText((text) => { + text + .setValue(parms.required.token) + .onChange(async (value) => { + parms.required.token = value + await plugin.saveSettings() + }) + }) + } +} diff --git a/src/lang/helpers.ts b/src/lang/helpers.ts new file mode 100644 index 0000000..4a31e00 --- /dev/null +++ b/src/lang/helpers.ts @@ -0,0 +1,56 @@ +import { moment } from 'obsidian' +import ar from './locale/ar' +import cz from './locale/cz' +import da from './locale/da' +import de from './locale/de' +import en from './locale/en' +import enGB from './locale/en-gb' +import es from './locale/es' +import fr from './locale/fr' +import hi from './locale/hi' +import id from './locale/id' +import it from './locale/it' +import ja from './locale/ja' +import ko from './locale/ko' +import nl from './locale/nl' +import no from './locale/no' +import pl from './locale/pl' +import pt from './locale/pt' +import ptBR from './locale/pt-br' +import ro from './locale/ro' +import ru from './locale/ru' +import tr from './locale/tr' +import zhCN from './locale/zh-cn' +import zhTW from './locale/zh-tw' + +const localeMap: Record> = { + ar, + cs: cz, + da, + de, + en, + 'en-gb': enGB, + es, + fr, + hi, + id, + it, + ja, + ko, + nl, + nn: no, + pl, + pt, + 'pt-br': ptBR, + ro, + ru, + tr, + 'zh-cn': zhCN, + 'zh-tw': zhTW +} + +const locale = localeMap[moment.locale()] + +export function t (str: keyof typeof en): string { + return (locale?.[str]) ?? en[str] +} diff --git a/src/lang/locale/ar.ts b/src/lang/locale/ar.ts new file mode 100644 index 0000000..9edf62e --- /dev/null +++ b/src/lang/locale/ar.ts @@ -0,0 +1,3 @@ +// العربية + +export default {} diff --git a/src/lang/locale/cz.ts b/src/lang/locale/cz.ts new file mode 100644 index 0000000..ed826d2 --- /dev/null +++ b/src/lang/locale/cz.ts @@ -0,0 +1,3 @@ +// čeština + +export default {} diff --git a/src/lang/locale/da.ts b/src/lang/locale/da.ts new file mode 100644 index 0000000..4d0db27 --- /dev/null +++ b/src/lang/locale/da.ts @@ -0,0 +1,3 @@ +// Dansk + +export default {} diff --git a/src/lang/locale/de.ts b/src/lang/locale/de.ts new file mode 100644 index 0000000..9c1d87f --- /dev/null +++ b/src/lang/locale/de.ts @@ -0,0 +1,3 @@ +// Deutsch + +export default {} diff --git a/src/lang/locale/en-gb.ts b/src/lang/locale/en-gb.ts new file mode 100644 index 0000000..dafe957 --- /dev/null +++ b/src/lang/locale/en-gb.ts @@ -0,0 +1,3 @@ +// British English + +export default {} diff --git a/src/lang/locale/en.ts b/src/lang/locale/en.ts new file mode 100644 index 0000000..74807d4 --- /dev/null +++ b/src/lang/locale/en.ts @@ -0,0 +1,58 @@ +// English + +export default { + domain: 'dmain', + 'no sign in': 'Imgur no sign in!', + // not required + 'not required': 'not required', + // main.ts + broken: 'Emo broken. Check your target', + 'upload error': ' upload error', + 'parms error': 'Emo need more prams', + // settings-tab.ts + 'target hosting': 'target hosting', + 'target hosting desc': 'Choose your target. Before uploading, make sure you have completely filled in the necessary parameters of the selected platform.', + // fragment-cloudinary.ts + 'Cloudinary Settings': 'Cloudinary Settings', + 'Upload Folder desc': 'Folder name to use in Cloudinary. Note, this will be ignored if you have a folder set in your Cloudinary Upload Preset. Not required.', + // fragment-github.ts + 'Github Settings': 'Github Settings', + owner: 'owner', + repo: 'repo', + branch: 'branch', + token: 'token', + message: 'message', + path: 'path', + cdn: 'CDN', + 'random filename': 'random filename', + 'random filename desc': 'Random file names will greatly avoid duplicate file names. If you are sure that you need to use the original file name during this upload, make sure that no duplicate naming will occur under the path you choose.', + // fragment-imgbb.ts + 'imgbb Settings': 'imgbb Settings', + // fragment-imgur.ts + tips: 'Tips', + 'tips text': 'Imgur anonymous upload will produce the link in this format: ![deletehash](url). [deletehash] is used to delete the image you just uploaded. If your note will be used for publicity, please remember to delete it in time. Authentication upload can be deleted on Imgur.', + 'Imgur Settings': 'Imgur Settings', + 'Anonymous Upload': 'Anonymous Upload', + 'Anonymous Upload desc': 'Files uploaded anonymously will not show in your Imgur account.', + imgurid: 'ID', + 'built-in id desc': 'The built-in ID has a daily usage limit, if it is temporarily invalid, you can use your own client ID here to upload and delete. Not required.', + delete: 'delete', + 'delete desc': 'If you want to delete the image on Imgur, delete it here with the deletehash.', + 'delete btn': 'Delete', + 'delete done': 'delete done', + 'delete fail': 'delete fail', + authenticate: 'authenticate', + 'auth desc': 'Re-auth is required for the change ID to take effect.', + 'imgur account': 'Authenticated as: ', + 'auth error': 'Authentication failed with error: ', + 'sign in': 'sign in', + 'Sign Out': 'Sign Out', + // fragment-imgurl.ts + 'ImgURL Settings': 'ImgURL Settings', + // fragment-smms.ts + 'SM.MS Settings': 'SM.MS Settings', + // fragment-catbox.ts + 'Catbox Settings': 'Catbox Settings', + // fragment-chevereto.ts + 'Chevereto Settings': 'Chevereto Settings' +} diff --git a/src/lang/locale/es.ts b/src/lang/locale/es.ts new file mode 100644 index 0000000..83db432 --- /dev/null +++ b/src/lang/locale/es.ts @@ -0,0 +1,3 @@ +// Español + +export default {} diff --git a/src/lang/locale/fr.ts b/src/lang/locale/fr.ts new file mode 100644 index 0000000..575622c --- /dev/null +++ b/src/lang/locale/fr.ts @@ -0,0 +1,3 @@ +// français + +export default {} diff --git a/src/lang/locale/hi.ts b/src/lang/locale/hi.ts new file mode 100644 index 0000000..9330a89 --- /dev/null +++ b/src/lang/locale/hi.ts @@ -0,0 +1,3 @@ +// हिन्दी + +export default {} diff --git a/src/lang/locale/id.ts b/src/lang/locale/id.ts new file mode 100644 index 0000000..6c42533 --- /dev/null +++ b/src/lang/locale/id.ts @@ -0,0 +1,3 @@ +// Bahasa Indonesia + +export default {} diff --git a/src/lang/locale/it.ts b/src/lang/locale/it.ts new file mode 100644 index 0000000..4ab7b5e --- /dev/null +++ b/src/lang/locale/it.ts @@ -0,0 +1,3 @@ +// Italiano + +export default {} diff --git a/src/lang/locale/ja.ts b/src/lang/locale/ja.ts new file mode 100644 index 0000000..a838cd6 --- /dev/null +++ b/src/lang/locale/ja.ts @@ -0,0 +1,3 @@ +// 日本語 + +export default {} diff --git a/src/lang/locale/ko.ts b/src/lang/locale/ko.ts new file mode 100644 index 0000000..b6ea971 --- /dev/null +++ b/src/lang/locale/ko.ts @@ -0,0 +1,3 @@ +// 한국어 + +export default {} diff --git a/src/lang/locale/nl.ts b/src/lang/locale/nl.ts new file mode 100644 index 0000000..7c43188 --- /dev/null +++ b/src/lang/locale/nl.ts @@ -0,0 +1,3 @@ +// Nederlands + +export default {} diff --git a/src/lang/locale/no.ts b/src/lang/locale/no.ts new file mode 100644 index 0000000..1aeda70 --- /dev/null +++ b/src/lang/locale/no.ts @@ -0,0 +1,3 @@ +// Norsk + +export default {} diff --git a/src/lang/locale/pl.ts b/src/lang/locale/pl.ts new file mode 100644 index 0000000..8ca60e6 --- /dev/null +++ b/src/lang/locale/pl.ts @@ -0,0 +1,3 @@ +// język polski + +export default {} diff --git a/src/lang/locale/pt-br.ts b/src/lang/locale/pt-br.ts new file mode 100644 index 0000000..5b474d2 --- /dev/null +++ b/src/lang/locale/pt-br.ts @@ -0,0 +1,4 @@ +// Português do Brasil +// Brazilian Portuguese + +export default {} diff --git a/src/lang/locale/pt.ts b/src/lang/locale/pt.ts new file mode 100644 index 0000000..eb70f37 --- /dev/null +++ b/src/lang/locale/pt.ts @@ -0,0 +1,3 @@ +// Português + +export default {} diff --git a/src/lang/locale/ro.ts b/src/lang/locale/ro.ts new file mode 100644 index 0000000..1479eee --- /dev/null +++ b/src/lang/locale/ro.ts @@ -0,0 +1,3 @@ +// Română + +export default {} diff --git a/src/lang/locale/ru.ts b/src/lang/locale/ru.ts new file mode 100644 index 0000000..d98fbcc --- /dev/null +++ b/src/lang/locale/ru.ts @@ -0,0 +1,3 @@ +// русский + +export default {} diff --git a/src/lang/locale/tr.ts b/src/lang/locale/tr.ts new file mode 100644 index 0000000..48b7abc --- /dev/null +++ b/src/lang/locale/tr.ts @@ -0,0 +1,3 @@ +// Türkçe + +export default {} diff --git a/src/lang/locale/zh-cn.ts b/src/lang/locale/zh-cn.ts new file mode 100644 index 0000000..7397cfc --- /dev/null +++ b/src/lang/locale/zh-cn.ts @@ -0,0 +1,58 @@ +// 简体中文 + +export default { + domain: '域名', + 'no sign in': 'Imgur未登录!', + // not required + 'not required': '可不填', + // main.ts + broken: 'Emo工作异常,检视你的目标平台选择', + 'upload error': '上传失败', + 'parms error': '当前平台所需必要参数未填写完全', + // settings-tab.ts + 'target hosting': '托管平台', + 'target hosting desc': '选择目标。上传之前,请确保所选平台的必要参数已填写完成。', + // fragment-cloudinary.ts + 'Cloudinary Settings': 'Cloudinary配置', + 'Upload Folder desc': '要在Cloudinary中使用的文件夹名称。注意,如果在Cloudinary预设了文件夹,则会忽略此项。可不填。', + // fragment-github.ts + 'Github Settings': 'Github配置', + owner: '用户名', + repo: '仓库', + branch: '分支', + token: '令牌', + message: '提交信息', + path: '路径', + cdn: 'CDN', + 'random filename': '随机文件名', + 'random filename desc': '采用随机文件名将极大避免重名。如果确定在上传过程中需要使用原文件名,请确保所选路径下不会出现重名问题。', + // fragment-imgbb.ts + 'imgbb Settings': 'imgbb配置', + // fragment-imgur.ts + tips: '贴士', + 'tips text': 'Imgur匿名上传将生成以下格式的链接:![deletehash](url)。[deletehash]用于删除刚刚上传的图像。如果您的笔记会被公开,请及时在笔记中删除deletehash。认证上传可在Imgur上删除。', + 'Imgur Settings': 'Imgur配置', + 'Anonymous Upload': '匿名上传', + 'Anonymous Upload desc': '匿名上传的文件不会显示在Imgur帐户中。', + imgurid: '客户端ID', + 'built-in id desc': '内置ID有每日使用限制,如果暂时失效,可以使用自己的客户端ID以进行上传和删除。可不填。', + delete: '删除', + 'delete desc': '如果需要删除Imgur上的图像,请在此处使用deletehash将其删除。', + 'delete btn': '删除', + 'delete done': '删除成功', + 'delete fail': '删除失败', + authenticate: '认证', + 'auth desc': '更改ID需要重新认证才能生效。', + 'imgur account': '当前用户: ', + 'auth error': '认证错误: ', + 'sign in': '登录', + 'Sign Out': '注销', + // fragment-imgurl.ts + 'ImgURL Settings': 'ImgURL配置', + // fragment-smms.ts + 'SM.MS Settings': 'SM.MS配置', + // fragment-catbox.ts + 'Catbox Settings': 'Catbox配置', + // fragment-chevereto.ts + 'Chevereto Settings': 'Chevereto配置' +} diff --git a/src/lang/locale/zh-tw.ts b/src/lang/locale/zh-tw.ts new file mode 100644 index 0000000..6c57abf --- /dev/null +++ b/src/lang/locale/zh-tw.ts @@ -0,0 +1,58 @@ +// 繁體中文 + +export default { + domain: '域名', + 'no sign in': 'Imgur未登錄!', + // not required + 'not required': '可不填', + // main.ts + broken: 'Emo工作異常,檢視你的目標平台選擇', + 'upload error': '上傳失敗', + 'parms error': '目前平台所需必要參數未填寫完全', + // settings-tab.ts + 'target hosting': '託管平台', + 'target hosting desc': '選擇目標。上傳之前,請確保所選平台的必要參數已填寫完成。', + // fragment-cloudinary.ts + 'Cloudinary Settings': 'Cloudinary配置', + 'Upload Folder desc': '要在Cloudinary中使用的資料夾名稱。注意,如果在Cloudinary預設了資料夾,則會忽略此項。可不填。', + // fragment-github.ts + 'Github Settings': 'Github配置', + owner: '使用者名稱', + repo: '儲存庫', + branch: '分支', + token: '令牌', + message: '提交資訊', + path: '路徑', + cdn: 'CDN', + 'random filename': '隨機檔名', + 'random filename desc': '採用隨機檔名將極大避免重名。如果確定在上傳過程中需要使用原檔名,請確保所選路徑下不會出現重名問題。', + // fragment-imgbb.ts + 'imgbb Settings': 'imgbb配置', + // fragment-imgur.ts + tips: '小技巧', + 'tips text': 'Imgur匿名上傳將產生以下格式的鏈接:![deletehash](url)。[deletehash]用於刪除剛剛上傳的影像。如果您的筆記會被公開,請及時在筆記中刪除deletehash。認證上傳可在Imgur上刪除。', + 'Imgur Settings': 'Imgur配置', + 'Anonymous Upload': '匿名上傳', + 'Anonymous Upload desc': '匿名上傳的檔案不會顯示在Imgur帳戶中。', + imgurid: '客戶端ID', + 'built-in id desc': '內建ID有每日使用限制,如果暫時失效,可以使用自己的客戶端ID以進行上傳和刪除。可不填。', + delete: '刪除', + 'delete desc': '如果需要刪除Imgur上的影像,請在此處使用deletehash將其刪除。', + 'delete btn': '刪除', + 'delete done': '刪除成功', + 'delete fail': '刪除失敗', + authenticate: '認證', + 'auth desc': '更改ID需要重新認證才能生效。', + 'imgur account': '目前使用者: ', + 'auth error': '認證錯誤: ', + 'sign in': '登錄', + 'Sign Out': '註銷', + // fragment-imgurl.ts + 'ImgURL Settings': 'ImgURL配置', + // fragment-smms.ts + 'SM.MS Settings': 'SM.MS配置', + // fragment-catbox.ts + 'Catbox Settings': 'Catbox配置', + // fragment-chevereto.ts + 'Chevereto Settings': 'Chevereto配置' +} diff --git a/src/main.ts b/src/main.ts index e36d4b2..2bf0ea7 100755 --- a/src/main.ts +++ b/src/main.ts @@ -1,149 +1,133 @@ -// Imports for plugin import { - Notice, Plugin, Editor, -} from "obsidian"; + Notice +} from 'obsidian' +import { t } from './lang/helpers' +import { EmoUploaderSettingTab } from './settings-tab' +import { Config, DEFAULT_SETTINGS, HostingProvider } from './config' +import { EmoUploader } from './base/emo-uploader' +import { GithubUploader } from './uploader/uploader-github' +import { ImgurlUploader } from './uploader/uploader-imgurl' +import { CloudinaryUploader } from './uploader/uploader-cloudinary' +import { SmmsUploader } from './uploader/uploader-smms' +import { ImgbbUploader } from './uploader/uploader-imgbb' +import { ImgurUploader } from './uploader/uploader-imgur' +import { CatboxUploader } from './uploader/uploader-catbox' +import { CheveretoUploader } from './uploader/uploader-chevereto' +import { AlistUploader } from './uploader/uploader-alist' -// For API requests -import axios from "axios" -import objectPath from 'object-path' +export default class Emo extends Plugin { + config!: Config -// Settings tab import -import CloudinaryUploaderSettingTab from './settings-tab' - -//Define Cloudinary Settings -interface CloudinarySettings { - cloudName: string; - uploadPreset: string; - folder: string; - f_auto: boolean; - transformParams: string; - //maxWidth: number; TODO - // enableResize: boolean; TODO -} - -// Set settings defaults -const DEFAULT_SETTINGS: CloudinarySettings = { - cloudName: null, - uploadPreset: null, - folder: null, - f_auto: false, - transformParams: null, - //maxWidth: 4096, TODO - //enableResize: false, TODO later -}; -export default class CloudinaryUploader extends Plugin { - settings: CloudinarySettings; + // Plugin load steps + async onload (): Promise { + console.log('loading Emo uploader') + await this.loadSettings() + this.setupPasteHandler() + this.addSettingTab(new EmoUploaderSettingTab(this.app, this)) + } + // Plugin shutdown steps + onunload (): void { + console.log('unloading Emo uploader') + } - setupPasteHandler(): void { - // On paste event, get "files" from clipbaord data - // If files contain image, move to API call - // if Files empty or does not contain image, throw error - this.registerEvent(this.app.workspace.on('editor-paste',async (evt: ClipboardEvent, editor: Editor)=>{ - const { files } = evt.clipboardData; - if(files.length > 0){ - if (this.settings.cloudName && this.settings.uploadPreset && files[0].type.startsWith("image")) { - evt.preventDefault(); // Prevent default paste behaviour - for (let file of files) { - const randomString = (Math.random() * 10086).toString(36).substr(0, 8) - const pastePlaceText = `![uploading...](${randomString})\n` - editor.replaceSelection(pastePlaceText) // Generate random string to show on editor screen while API call completes + // Load settings infromation + async loadSettings (): Promise { + this.config = Object.assign({}, DEFAULT_SETTINGS, await this.loadData()) + } - // Cloudinary request format - // Send form data with a file and upload preset - // Optionally define a folder - const formData = new FormData(); - formData.append('file',file); - formData.append('upload_preset',this.settings.uploadPreset); - formData.append('folder',this.settings.folder); + // When saving settings + async saveSettings (): Promise { + await this.saveData(this.config) + } - // Make API call - axios({ - url: `https://api.cloudinary.com/v1_1/${this.settings.cloudName}/auto/upload`, - method: 'POST', - data: formData - }).then(res => { - // Get response public URL of uploaded image - console.log(res); - let url = objectPath.get(res.data, 'secure_url') - let imgMarkdownText =""; + setupPasteHandler (): void { + // get files from drag or drop + this.registerEvent(this.app.workspace.on('editor-drop', async (evt: DragEvent, editor: Editor) => { + const { files } = evt.dataTransfer as DataTransfer + this.startUpload(files, evt, editor) + })) + // get files from clipboard + this.registerEvent(this.app.workspace.on('editor-paste', async (evt: ClipboardEvent, editor: Editor) => { + const { files } = evt.clipboardData as DataTransfer + this.startUpload(files, evt, editor) + })) + } - // Split URL to allow for appending transformations - if(this.settings.transformParams){ - const splitURL = url.split("/upload/",2); - let modifiedURL=''; - modifiedURL = splitURL[0]+="/upload/"+this.settings.transformParams+"/"+splitURL[1]; - imgMarkdownText = `![](${modifiedURL})`; - url = modifiedURL - } - if(this.settings.f_auto){ - const splitURL = url.split("/upload/",2); - let modifiedURL=''; - modifiedURL = splitURL[0]+="/upload/f_auto/"+splitURL[1]; - imgMarkdownText = `![](${modifiedURL})`; - - // leave stamdard of no transformations added - }else{ - imgMarkdownText = `![](${url})`; - } - // Show MD syntax using uploaded image URL, in Obsidian Editor - this.replaceText(editor, pastePlaceText, imgMarkdownText) - }, err => { - // Fail otherwise - new Notice(err, 5000) + startUpload (files: FileList, evt: Event, editor: Editor): void { + let uploader: EmoUploader + if (files.length > 0) { + switch (this.config.choice) { + case HostingProvider.Github: + uploader = new GithubUploader(this.config.github_parms) + break + case HostingProvider.ImgURL: + uploader = new ImgurlUploader(this.config.imgurl_parms) + break + case HostingProvider.Cloudinary: + uploader = new CloudinaryUploader(this.config.cloudinary_parms) + break + case HostingProvider.Smms: + uploader = new SmmsUploader(this.config.smms_parms) + break + case HostingProvider.Imgbb: + uploader = new ImgbbUploader(this.config.imgbb_parms) + break + case HostingProvider.Imgur: + uploader = new ImgurUploader(this.config.imgur_parms) + break + case HostingProvider.Catbox: + uploader = new CatboxUploader(this.config.catbox_parms) + break + case HostingProvider.Chevereto: + uploader = new CheveretoUploader(this.config.chevereto_parms) + break + case HostingProvider.Alist: + uploader = new AlistUploader(this.config.alist_parms) + break + default: + console.log(new Notice(t('broken'), 2000)) + return + } + if (uploader.isValid()) { // check the necessary parameters + evt.preventDefault() + for (const file of files) { + const randomString = (Math.random() * 10086).toString(36).slice(-6) + const pastePlaceText = `![uploading...](${randomString})\n` + editor.replaceSelection(pastePlaceText) // mark the uploading + uploader.upload(file).then((markdownText) => { + const showTag = file.type.startsWith('image') ? 0 : 1// whether use `!` at the beginning + this.replaceText(editor, pastePlaceText, markdownText.slice(showTag)) // use image/file link + }).catch(err => { + this.replaceText(editor, pastePlaceText, `[${this.config.choice} upload error]()`) + console.log(new Notice(this.config.choice + t('upload error'), 2000)) console.log(err) }) } + } else { + console.log(new Notice(t('parms error'), 2000)) + console.log(uploader) } - // else { - // // If not image data, or empty files array - // new Notice("Cloudinary Image Uploader: Please check the image hosting settings."); - // editor.replaceSelection("Please check settings for upload\n This will also appear if file is not of image type"); - // } - - }})) + } } + // Function to replace text - private replaceText(editor: Editor, target: string, replacement: string): void { - target = target.trim(); - let lines = []; - for (let i = 0; i < editor.lineCount(); i++){ - lines.push(editor.getLine(i)); + private replaceText (editor: Editor, target: string, replacement: string): void { + target = target.trim() + const lines = [] + for (let i = 0; i < editor.lineCount(); i++) { + lines.push(editor.getLine(i)) } - //const tlines = editor.getValue().split("\n"); for (let i = 0; i < lines.length; i++) { const ch = lines[i].indexOf(target) if (ch !== -1) { - const from = { line: i, ch }; - const to = { line: i, ch: ch + target.length }; - editor.replaceRange(replacement, from, to); - break; + const from = { line: i, ch } + const to = { line: i, ch: ch + target.length } + editor.replaceRange(replacement, from, to) + break } } } - - // Plugin load steps - async onload(): Promise { - console.log("loading Cloudinary Uploader"); - await this.loadSettings(); - this.setupPasteHandler(); - this.addSettingTab(new CloudinaryUploaderSettingTab(this.app, this)); - } - - // Plugin shutdown steps - onunload(): void { - console.log("unloading Cloudinary Uploader"); - - } - // Load settings infromation - async loadSettings(): Promise { - this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData()); - } - - // When saving settings - async saveSettings(): Promise { - await this.saveData(this.settings); - } } diff --git a/src/parms/parms-alist.ts b/src/parms/parms-alist.ts new file mode 100644 index 0000000..388e18e --- /dev/null +++ b/src/parms/parms-alist.ts @@ -0,0 +1,22 @@ +import { EmoParms } from '../base/emo-parms' + +export interface AlistParms extends EmoParms { + required: Required +} + +interface Required { + domain: string + username: string + password: string + uploadPath: string +} + +export const ALIST_DEFAULT_PARMS: AlistParms = { + required: { + domain: 'https://alist.example.com', + username: '', + password: '', + uploadPath: '上传的相对路径', + } +} + diff --git a/src/parms/parms-catbox.ts b/src/parms/parms-catbox.ts new file mode 100644 index 0000000..883cbca --- /dev/null +++ b/src/parms/parms-catbox.ts @@ -0,0 +1,15 @@ +import { EmoParms } from '../base/emo-parms' + +export interface CatboxParms extends EmoParms { + required: Required +} + +interface Required { + userhash: string +} + +export const CATBOX_DEFAULT_PARMS: CatboxParms = { + required: { + userhash: '' + } +} diff --git a/src/parms/parms-chevereto.ts b/src/parms/parms-chevereto.ts new file mode 100644 index 0000000..5e75fb4 --- /dev/null +++ b/src/parms/parms-chevereto.ts @@ -0,0 +1,17 @@ +import { EmoParms } from '../base/emo-parms' + +export interface CheveretoParms extends EmoParms { + required: Required +} + +interface Required { + domain: string + token: string +} + +export const CHEVERETO_DEFAULT_PARMS: CheveretoParms = { + required: { + domain: '', + token: '' + } +} diff --git a/src/parms/parms-cloudinary.ts b/src/parms/parms-cloudinary.ts new file mode 100644 index 0000000..e600bd0 --- /dev/null +++ b/src/parms/parms-cloudinary.ts @@ -0,0 +1,19 @@ +import { EmoParms } from '../base/emo-parms' + +export interface CloudinaryParms extends EmoParms { + required: Required + folder: string +} + +interface Required { + name: string + present: string +} + +export const CLOUDINARY_DEFAULT_PARMS: CloudinaryParms = { + required: { + name: '', + present: '' + }, + folder: '' +} diff --git a/src/parms/parms-github.ts b/src/parms/parms-github.ts new file mode 100644 index 0000000..1ee2791 --- /dev/null +++ b/src/parms/parms-github.ts @@ -0,0 +1,32 @@ +import { EmoParms } from '../base/emo-parms' +export enum CDNprovider { // Github CDN + jsdelivr = 'jsdelivr', + statically = 'statically', + raw = 'raw' +} +export interface GithubParms extends EmoParms { + required: Required + path: string + random: boolean + cdn: CDNprovider +} + +interface Required { + owner: string + repo: string + branch: string + token: string + message: string +} +export const GITHUB_DEFAULT_PARMS: GithubParms = { + required: { + owner: '', + repo: '', + branch: 'main', + token: '', + message: 'from emo-uploader·Github' + }, + path: '', + random: true, + cdn: CDNprovider.raw +} diff --git a/src/parms/parms-imgbb.ts b/src/parms/parms-imgbb.ts new file mode 100644 index 0000000..646e5f9 --- /dev/null +++ b/src/parms/parms-imgbb.ts @@ -0,0 +1,13 @@ +import { EmoParms } from '../base/emo-parms' + +export interface ImgbbParms extends EmoParms { + required: Required +} +interface Required { + key: string +} +export const IMGBB_DEFAULT_PARMS: ImgbbParms = { + required: { + key: '' + } +} diff --git a/src/parms/parms-imgur.ts b/src/parms/parms-imgur.ts new file mode 100644 index 0000000..0afa8f6 --- /dev/null +++ b/src/parms/parms-imgur.ts @@ -0,0 +1,17 @@ +import { EmoParms } from '../base/emo-parms' + +export interface ImgurParms extends EmoParms { + required: Required + clientid: string + anonymous: boolean +} +interface Required { + emoid: string +} +export const IMGUR_DEFAULT_PARMS: ImgurParms = { + required: { + emoid: '4547d4aee97ce8f' + }, + clientid: '', + anonymous: true +} diff --git a/src/parms/parms-imgurl.ts b/src/parms/parms-imgurl.ts new file mode 100644 index 0000000..ffb015b --- /dev/null +++ b/src/parms/parms-imgurl.ts @@ -0,0 +1,15 @@ +import { EmoParms } from '../base/emo-parms' + +export interface ImgurlParms extends EmoParms { + required: Required +} +interface Required { + uid: string + token: string +} +export const IMGURL_DEFAULT_PARMS: ImgurlParms = { + required: { + uid: '', + token: '' + } +} diff --git a/src/parms/parms-smms.ts b/src/parms/parms-smms.ts new file mode 100644 index 0000000..5f43517 --- /dev/null +++ b/src/parms/parms-smms.ts @@ -0,0 +1,13 @@ +import { EmoParms } from '../base/emo-parms' + +export interface SmmsParms extends EmoParms { + required: Required +} +interface Required { + token: string +} +export const SMMS_DEFAULT_PARMS: SmmsParms = { + required: { + token: '' + } +} diff --git a/src/settings-tab.ts b/src/settings-tab.ts index ab06c80..ad24137 100755 --- a/src/settings-tab.ts +++ b/src/settings-tab.ts @@ -1,141 +1,102 @@ -/* - * @Author: Jordan Handy - */ import { - App, - PluginSettingTab, - Setting, -} from 'obsidian'; + App, + Notice, + PluginSettingTab, + Setting +} from 'obsidian' +import { HostingProvider } from './config' +import Emo from './main' +import { t } from './lang/helpers' +import { EmoFragment } from './base/emo-fragment' +import { CloudinaryFragment } from './fragment/fragment-cloudinary' +import { GithubFragment } from './fragment/fragment-github' +import { ImgbbFragment } from './fragment/fragment-imgbb' +import { ImgurlFragment } from './fragment/fragment-imgurl' +import { SmmsFragment } from './fragment/fragment-smms' +import { ImgurFragment } from './fragment/fragment-imgur' +import { CatboxFragment } from './fragment/fragment-catbox' +import { IMGUR_ACCESS_TOKEN_LOCALSTORAGE_KEY } from './base/constants' +import { CheveretoFragment } from './fragment/fragment-chevereto' +import { AlistFragment } from './fragment/fragment-alist' -import CloudinaryUploader from './main' +export class EmoUploaderSettingTab extends PluginSettingTab { + private readonly plugin: Emo + constructor (app: App, plugin: Emo) { + super(app, plugin) + this.plugin = plugin + this.setUpHandler() + } -export default class CloudinaryUploaderSettingTab extends PluginSettingTab { - plugin: CloudinaryUploader; - constructor(app: App, plugin: CloudinaryUploader) { - super(app, plugin); - this.plugin = plugin; - } - display(): void { - const { containerEl } = this; + display (): void { + const { containerEl } = this + containerEl.empty() - containerEl.empty(); - containerEl.createEl("h3", { text: "Cloudinary Settings" }); + // donate button + const colaDiv = containerEl.createDiv('cola') + colaDiv.addClass('emo-cola-div') + const colaLink = colaDiv.createEl('a', { + href: 'https://lestua.eu.org/donate' + }) + const colaImg = colaLink.createEl('img') + colaImg.outerHTML = '' - new Setting(containerEl) - .setName("Cloud Name") - .setDesc("The name of your Cloudinary Cloud Account") - .addText((text) => { - text - .setPlaceholder("") - .setValue(this.plugin.settings.cloudName) - .onChange(async (value) => { - this.plugin.settings.cloudName = value; - await this.plugin.saveSettings(); - }) - } - ); + // provide choices + containerEl.createEl('h2', { text: 'Emo' }) + const pick = new Setting(containerEl) + .setName(t('target hosting')) + .setDesc(t('target hosting desc')) - new Setting(containerEl) - .setName("Cloudinary Upload Template") - .setDesc("Cloudinary Upload Preference string") - .addText((text) => { - text - .setPlaceholder("") - .setValue(this.plugin.settings.uploadPreset) - .onChange(async (value) => { - try { - this.plugin.settings.uploadPreset = value; - await this.plugin.saveSettings(); - } - catch (e) { - console.log(e) - } - }) - }); - new Setting(containerEl) - .setName("Cloudinary Upload Folder") - .setDesc("Folder name to use in Cloudinary. Note, this will be ignored if you have a folder set in your Cloudinary Upload Preset") - .addText((text) => { - text - .setPlaceholder("obsidian") - .setValue(this.plugin.settings.folder) - .onChange(async (value) => { - try { - this.plugin.settings.folder = value; - await this.plugin.saveSettings(); - } - catch (e) { - console.log(e) - } - }) - }); - containerEl.createEl("h4", { text: "URL Manipulations / Transformation" }); - - // Allow for inline hyperlinks with anchor tags - let textFragment = document.createDocumentFragment(); - let link = document.createElement("a"); + const fragmentList: EmoFragment[] = [] + fragmentList.push(new GithubFragment(containerEl, this.plugin)) + fragmentList.push(new ImgurFragment(containerEl, this.plugin)) + fragmentList.push(new CloudinaryFragment(containerEl, this.plugin)) + fragmentList.push(new SmmsFragment(containerEl, this.plugin)) + fragmentList.push(new ImgurlFragment(containerEl, this.plugin)) + fragmentList.push(new ImgbbFragment(containerEl, this.plugin)) + fragmentList.push(new CatboxFragment(containerEl, this.plugin)) + fragmentList.push(new CheveretoFragment(containerEl, this.plugin)) + fragmentList.push(new AlistFragment(containerEl, this.plugin)) - const linkTransformation = document.createElement("a"); - linkTransformation.text="transformation limits "; - linkTransformation.href="https://cloudinary.com/documentation/transformation_counts"; - - textFragment.append("The settings below are meant for default image transformations. As they only touch the resulting URL, this should not cause any upload errors, however, if syntax is incorrect, your images will not be referenced correctly (won't render). Be mindful of your Cloudinary "); - textFragment.append(linkTransformation); - textFragment.append(" and use the "); - - link.href = "https://cloudinary.com/documentation/transformation_reference"; - link.text = " Cloudinary documentation" - textFragment.append(link); - textFragment.append(" for guidance."); - containerEl.createEl("p", { text: textFragment }); + // which one will show at the first time + fragmentList.forEach(element => { + element.update(this.plugin.config.choice) + }) + const supportList: string[] = [] + for (const key in HostingProvider) { + supportList.push(HostingProvider[key as keyof typeof HostingProvider]) + } - textFragment = document.createDocumentFragment(); - link = document.createElement("a"); - link.href="https://cloudinary.com/documentation/image_optimization#automatic_format_selection_f_auto"; - link.text="f_auto option"; - textFragment.append("Enable the "); - textFragment.append(link); - textFragment.append(" for uploads"); + pick.addDropdown((dropdown) => { + supportList.forEach((record) => { dropdown.addOption(record, record) }) + dropdown.setValue(this.plugin.config.choice) + .onChange(async (value) => { + this.plugin.config.choice = value as HostingProvider + await this.plugin.saveSettings() + fragmentList.forEach(element => { + element.update(this.plugin.config.choice) // update the tab when make a choice + }) + }) + }) + } - new Setting(containerEl) - .setName("f_auto Option") - .setDesc(textFragment) - .addToggle((toggle) => { - toggle - .setValue(this.plugin.settings.f_auto) - .onChange(async (value) => { - try { - this.plugin.settings.f_auto = value; - await this.plugin.saveSettings(); - } - catch (e) { - console.log(e) - } - }) - }); - textFragment = document.createDocumentFragment(); - link = document.createElement("a"); - link.href="https://cloudinary.com/documentation/transformation_reference"; - link.text="View Cloudinary's transformation reference for guidance."; - textFragment.append("Add a comma-delimited default set of transformations to your uploads. You do NOT need to include f_auto here if already enabled above. "); - textFragment.append(link); - new Setting(containerEl) - .setName("Default Transformation Parameters") - .setDesc(textFragment) - .addText((text) => { - text - .setPlaceholder("w_150,h_150") - .setValue(this.plugin.settings.transformParams) - .onChange(async (value) => { - try { - this.plugin.settings.transformParams = value; - await this.plugin.saveSettings(); - } - catch (e) { - console.log(e) - } - }) - }); - } -} \ No newline at end of file + setUpHandler (): void { + // handle Imgur auth + this.plugin.registerObsidianProtocolHandler('emo-imgur-oauth', async (params) => { + if (params.error !== undefined) { + console.log(new Notice(t('auth error') + `${params.error}`)) + return + } + const mappedData = params.hash.split('&').map((p) => { + const sp = p.split('=') + return [sp[0], sp[1]] as [string, string] + }) + const map = new Map(mappedData) + localStorage.setItem( + IMGUR_ACCESS_TOKEN_LOCALSTORAGE_KEY, + map.get('access_token') as string + ) + this.display() + }) + } +} diff --git a/src/styles.css b/src/styles.css new file mode 100644 index 0000000..5e0d40d --- /dev/null +++ b/src/styles.css @@ -0,0 +1,4 @@ +.emo-cola-div { + text-align: center; + margin-bottom: 10px; +} diff --git a/src/uploader/uploader-alist.ts b/src/uploader/uploader-alist.ts new file mode 100644 index 0000000..4ef459c --- /dev/null +++ b/src/uploader/uploader-alist.ts @@ -0,0 +1,205 @@ +// 第一部分 +import { request, RequestUrlParam } from 'obsidian' +import { EmoFormData } from '../utils/emo-formdata' +import { EmoUploader } from '../base/emo-uploader' +import { CONTENT_TYPE_FORMDATA } from '../base/constants' +import { AlistParms } from '../parms/parms-alist' +import { sha256 } from 'js-sha256' + +export class AlistUploader extends EmoUploader { + parms!: AlistParms + constructor (alistParms: AlistParms) { + super() + this.parms = alistParms + } + + + async upload (file: File): Promise { + // 获取token + const token = await this.getToken() + // 新建文件夹 + const determine = await this.determine(file) + if (determine != 'success') { + await this.mkdirFile(file) + } + // 上传文件 + await this.putFile(file) + // 刷新列表 + await this.refreshDir(file) + // 重命名文件 + let newName = file.name + if (file.name == 'image.png'){ + newName = await this.renameFile(file) + } + + const extension = await this.getFileExtension(file) + const req: RequestUrlParam = { + url: `${this.parms.required.domain}/api/fs/get`, + method: 'POST', + headers: { + 'Authorization': token , + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + path: `/${this.parms.required.uploadPath}/${extension}/${newName}` + }) + } + // 发送请求并返回结果 + return await new Promise((resolve, reject) => { + request(req).then(async res => { + const json = JSON.parse(res) + // 赋给markdownText + const markdownText = `![${newName}](${json.data.raw_url})` + resolve(markdownText) + }).catch(err => { + reject(err) + }) + }) + } + + //第二部分 + //获取token + async getToken (): Promise { + const req: RequestUrlParam = { + url: `${this.parms.required.domain}/api/auth/login/hash`, + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + username: this.parms.required.username, + password: sha256(this.parms.required.password + '-123123123123') + }) + } + // 发送请求并返回token + return await new Promise((resolve, reject) => { + request(req).then(res => { + const json = JSON.parse(res) + resolve(json.data.token as string) + }).catch(err => { + reject(err) + }) + }) + } + + + //文件类型 + async getFileExtension(file: File): Promise { + const filename = file.name + const match = filename.match(/\.([^.]+)$/) + return match ? match[1] : "" + } + + //判断文件夹是否存在 + async determine (file: File): Promise { + const extension = await this.getFileExtension(file) + const req: RequestUrlParam = { + url: `${this.parms.required.domain}/api/fs/get`, + method: 'POST', + headers: { + 'Authorization': await this.getToken(), + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + path: `/${this.parms.required.uploadPath}/${extension}` + }) + } + return await new Promise((resolve, reject) => { + request(req).then(res => { + const json = JSON.parse(res) + resolve(json.message as string) + }).catch(err => { + reject(err) + }) + }) + } + + async mkdirFile (file: File): Promise { + const extension = await this.getFileExtension(file) + const req: RequestUrlParam = { + url: `${this.parms.required.domain}/api/fs/mkdir`, + method: 'POST', + headers: { + 'Authorization': await this.getToken(), + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + path: `/${this.parms.required.uploadPath}/${extension}`, + }) + } + await request(req) // 发送请求并返回链接 + } + + + + // 上传文件 + async putFile (file: File): Promise { + const extension = await this.getFileExtension(file) + const formData = new EmoFormData() + await formData.add('file', file) + const req: RequestUrlParam = { + url: `${this.parms.required.domain}/api/fs/form`, + method: 'PUT', + headers: { + 'Authorization': await this.getToken(), + 'Content-Type': CONTENT_TYPE_FORMDATA, + 'File-Path': encodeURIComponent(`/${this.parms.required.uploadPath}/${extension}/${file.name}`), + 'As-Task': 'true' + }, + body: formData.getBody() + } + await request(req) // 发送请求并返回链接 + } + + //第三部分 + // 刷新目录 + async refreshDir (file: File): Promise { + const extension = await this.getFileExtension(file) + const req: RequestUrlParam = { + url: `${this.parms.required.domain}/api/fs/list`, + method: 'POST', + headers: { + 'Authorization': await this.getToken(), + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + path: `/${this.parms.required.uploadPath}/${extension}`, + page: 1, + password: "", + per_page: 0, + refresh: true, + }) + } + await request(req) + + } + + // 重命名文件 + async renameFile (file: File): Promise { + const extension = await this.getFileExtension(file) + // 获取当前时间 + const now = new Date() + // 格式化时间 + const formatTime = (n: number) => n.toString().padStart(2, '0') + // 生成新文件名 + const newName = `${now.getFullYear()}${formatTime(now.getMonth() + 1)}${formatTime(now.getDate())}-${formatTime(now.getHours())}:${formatTime(now.getMinutes())}:${formatTime(now.getSeconds())}.${extension}` + // 构造请求参数 + const req: RequestUrlParam = { + url: `${this.parms.required.domain}/api/fs/rename`, + method: 'POST', + headers: { + 'Authorization': await this.getToken(), + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + name: newName, + path: `/${this.parms.required.uploadPath}/${extension}/${file.name}` + }) + } + // 发送请求 + await request(req) + return newName + } + +} + diff --git a/src/uploader/uploader-catbox.ts b/src/uploader/uploader-catbox.ts new file mode 100644 index 0000000..cf7f36d --- /dev/null +++ b/src/uploader/uploader-catbox.ts @@ -0,0 +1,37 @@ +import { request, RequestUrlParam } from 'obsidian' +import { EmoFormData } from '../utils/emo-formdata' +import { EmoUploader } from '../base/emo-uploader' +import { CONTENT_TYPE_FORMDATA } from '../base/constants' +import { CatboxParms } from '../parms/parms-catbox' + +export class CatboxUploader extends EmoUploader { + parms!: CatboxParms + constructor (catboxParms: CatboxParms) { + super() + this.parms = catboxParms + } + + async upload (file: File): Promise { + const formData = new EmoFormData() + await formData.add('reqtype', 'fileupload') + await formData.add('userhash', this.parms.required.userhash) + await formData.add('fileToUpload', file) + const req: RequestUrlParam = { + url: 'https://catbox.moe/user/api.php', + method: 'POST', + headers: { + 'Content-Type': CONTENT_TYPE_FORMDATA + }, + body: formData.getBody() + } + + return await new Promise((resolve, reject) => { + request(req).then((res) => { + const markdownText = `![Catbox](${res})` + resolve(markdownText) + }).catch(err => { + reject(err) + }) + }) + } +} diff --git a/src/uploader/uploader-chevereto.ts b/src/uploader/uploader-chevereto.ts new file mode 100644 index 0000000..cf5dced --- /dev/null +++ b/src/uploader/uploader-chevereto.ts @@ -0,0 +1,51 @@ +import { request, RequestUrlParam } from 'obsidian' +import { EmoUploader } from '../base/emo-uploader' +import { CheveretoParms } from '../parms/parms-chevereto' +import { EmoFormData } from '../utils/emo-formdata' +import { CONTENT_TYPE_FORMDATA } from '../base/constants' + +export class CheveretoUploader extends EmoUploader { + parms!: CheveretoParms + constructor (cheveretoParms: CheveretoParms) { + super() + this.parms = cheveretoParms + } + + // here chevereto API should be look like this: https://mysite.com/api/1/upload + formatUrl (str: string): string { + if (!str.startsWith('https://') && !str.startsWith('http://')) { + str = 'https://' + str + } + if (str.endsWith('/')) { // remove '/' + str = str.slice(0, -1) + } + return str + } + + async upload (file: File): Promise { + const domain = this.formatUrl(this.parms.required.domain) + const formData = new EmoFormData() + await formData.add('source', file) + await formData.add('key', this.parms.required.token) + const req: RequestUrlParam = { + url: domain, + method: 'POST', + headers: { + 'X-API-Key': this.parms.required.token, + 'Content-Type': CONTENT_TYPE_FORMDATA + }, + body: formData.getBody() + } + return await new Promise((resolve, reject) => { + request(req).then((res) => { + const json = JSON.parse(res) + let url = '' + url = json.image.url + const markdownText = `![Chevereto](${url})` + resolve(markdownText) + }).catch(err => { + reject(err) + }) + }) + } +} diff --git a/src/uploader/uploader-cloudinary.ts b/src/uploader/uploader-cloudinary.ts new file mode 100644 index 0000000..8e8c87a --- /dev/null +++ b/src/uploader/uploader-cloudinary.ts @@ -0,0 +1,37 @@ +import { request, RequestUrlParam } from 'obsidian' +import { CloudinaryParms } from '../parms/parms-cloudinary' +import { EmoFormData } from '../utils/emo-formdata' +import { EmoUploader } from '../base/emo-uploader' +import { CONTENT_TYPE_FORMDATA } from '../base/constants' + +export class CloudinaryUploader extends EmoUploader { + parms!: CloudinaryParms + constructor (cloudinaryParms: CloudinaryParms) { + super() + this.parms = cloudinaryParms + } + + async upload (file: File): Promise { + const formData = new EmoFormData() + await formData.add('upload_preset', this.parms.required.present) + await formData.add('folder', this.parms.folder) + await formData.add('file', file) + const req: RequestUrlParam = { + url: `https://api.cloudinary.com/v1_1/${this.parms.required.name}/auto/upload`, + method: 'POST', + headers: { + 'Content-Type': CONTENT_TYPE_FORMDATA + }, + body: formData.getBody() + } + return await new Promise((resolve, reject) => { + request(req).then(res => { + const json = JSON.parse(res) + const markdownText = `![Cloudinary](${json.secure_url as string})` + resolve(markdownText) + }).catch(err => { + reject(err) + }) + }) + } +} diff --git a/src/uploader/uploader-github.ts b/src/uploader/uploader-github.ts new file mode 100644 index 0000000..0335fb2 --- /dev/null +++ b/src/uploader/uploader-github.ts @@ -0,0 +1,65 @@ +import { request, RequestUrlParam } from 'obsidian' +import { CDNprovider, GithubParms } from '../parms/parms-github' +import { getBase64, getRandomFileName } from '../utils/file-helper' +import { EmoUploader } from '../base/emo-uploader' + +export class GithubUploader extends EmoUploader { + parms!: GithubParms + constructor (githubParms: GithubParms) { + super() + this.parms = githubParms + } + + async upload (file: File): Promise { + let filePath = '' + if (this.parms.random) { // use random filename + const startSuffix = file.name.lastIndexOf('.') + filePath = this.parms.path + getRandomFileName() + filePath += startSuffix > 0 ? file.name.substring(startSuffix) : '' // for no suffix files + } else { + filePath = this.parms.path + file.name // original filename + } + const jsonBody = { + owner: this.parms.required.owner, + repo: this.parms.required.repo, + branch: this.parms.required.branch, + path: filePath, + message: this.parms.required.message, + content: await getBase64(file) + } + const form = JSON.stringify(jsonBody) + const req: RequestUrlParam = { + url: `https://api.github.com/repos/${this.parms.required.owner}/${this.parms.required.repo}/contents/${filePath}`, + method: 'PUT', + headers: { + Authorization: `token ${this.parms.required.token}` + }, + body: form + } + + return await new Promise((resolve, reject) => { + request(req).then(() => { + let markdownText: string + console.log(this.parms.cdn) + switch (this.parms.cdn) { + case CDNprovider.jsdelivr: + markdownText = `![gh](https://cdn.jsdelivr.net/gh/${this.parms.required.owner}/${this.parms.required.repo}@${this.parms.required.branch}/${filePath})` + break + case CDNprovider.statically: + markdownText = `![gh](https://cdn.statically.io/gh/${this.parms.required.owner}/${this.parms.required.repo}/${this.parms.required.branch}/${filePath})` + break + case CDNprovider.raw: + markdownText = `![gh](https://raw.githubusercontent.com/${this.parms.required.owner}/${this.parms.required.repo}/${this.parms.required.branch}/${filePath})` + break + default: + // use raw + markdownText = `![gh](https://raw.githubusercontent.com/${this.parms.required.owner}/${this.parms.required.repo}/${this.parms.required.branch}/${filePath})` + break + } + resolve(markdownText) + }).catch(err => { + reject(err) + }) + }) + } +} diff --git a/src/uploader/uploader-imgbb.ts b/src/uploader/uploader-imgbb.ts new file mode 100644 index 0000000..3dd2495 --- /dev/null +++ b/src/uploader/uploader-imgbb.ts @@ -0,0 +1,38 @@ +import { request, RequestUrlParam } from 'obsidian' +import { ImgbbParms } from '../parms/parms-imgbb' +import { EmoFormData } from '../utils/emo-formdata' +import { EmoUploader } from '../base/emo-uploader' +import { CONTENT_TYPE_FORMDATA } from '../base/constants' + +export class ImgbbUploader extends EmoUploader { + parms!: ImgbbParms + constructor (imgbbParms: ImgbbParms) { + super() + this.parms = imgbbParms + } + + async upload (file: File): Promise { + const formData = new EmoFormData() + await formData.add('key', this.parms.required.key) + await formData.add('image', file) + const req: RequestUrlParam = { + url: 'https://api.imgbb.com/1/upload', + method: 'POST', + headers: { + 'Content-Type': CONTENT_TYPE_FORMDATA + }, + body: formData.getBody() + } + + return await new Promise((resolve, reject) => { + request(req).then((res) => { + const json = JSON.parse(res) + const url = json.data.url + const markdownText = `![imgbb](${url as string})` + resolve(markdownText) + }).catch(err => { + reject(err) + }) + }) + } +} diff --git a/src/uploader/uploader-imgur.ts b/src/uploader/uploader-imgur.ts new file mode 100644 index 0000000..3dbabe6 --- /dev/null +++ b/src/uploader/uploader-imgur.ts @@ -0,0 +1,60 @@ +import { request, RequestUrlParam } from 'obsidian' +import { ImgurParms } from '../parms/parms-imgur' +import { EmoFormData } from '../utils/emo-formdata' +import { EmoUploader } from '../base/emo-uploader' +import { CONTENT_TYPE_FORMDATA, IMGUR_ACCESS_TOKEN_LOCALSTORAGE_KEY, IMGUR_DEFAULT_ID } from '../base/constants' +import { t } from '../lang/helpers' + +export class ImgurUploader extends EmoUploader { + parms!: ImgurParms + constructor (imgurlParms: ImgurParms) { + super() + this.parms = imgurlParms + } + + async upload (file: File): Promise { + const formData = new EmoFormData() + await formData.add('image', file) + let req: RequestUrlParam + if (this.parms.anonymous) { // anonymous upload + let auth = 'Client-ID ' + if (this.parms.clientid !== '') { auth += this.parms.clientid } else auth += IMGUR_DEFAULT_ID + req = { + url: 'https://api.imgur.com/3/upload', + method: 'POST', + headers: { + 'Content-Type': CONTENT_TYPE_FORMDATA, + Authorization: auth + }, + body: formData.getBody() + } + } else { // auth upload + const accessToken = localStorage.getItem(IMGUR_ACCESS_TOKEN_LOCALSTORAGE_KEY) + if (accessToken !== null) { + req = { + url: 'https://api.imgur.com/3/image', + method: 'POST', + headers: { + 'Content-Type': CONTENT_TYPE_FORMDATA, + Authorization: `Bearer ${accessToken}` + }, + body: formData.getBody() + } + } else { + return t('no sign in') + } + } + return await new Promise((resolve, reject) => { + request(req).then((res) => { + const json = JSON.parse(res) + const hash = json.data.deletehash + const url = json.data.link + let markdownText: string + if (this.parms.anonymous) { markdownText = `![${hash as string}](${url as string})` } else markdownText = `![Imgur](${url as string})` + resolve(markdownText) + }).catch(err => { + reject(err) + }) + }) + } +} diff --git a/src/uploader/uploader-imgurl.ts b/src/uploader/uploader-imgurl.ts new file mode 100644 index 0000000..ba78219 --- /dev/null +++ b/src/uploader/uploader-imgurl.ts @@ -0,0 +1,38 @@ +import { request, RequestUrlParam } from 'obsidian' +import { ImgurlParms } from '../parms/parms-imgurl' +import { EmoFormData } from '../utils/emo-formdata' +import { EmoUploader } from '../base/emo-uploader' +import { CONTENT_TYPE_FORMDATA } from '../base/constants' + +export class ImgurlUploader extends EmoUploader { + parms!: ImgurlParms + constructor (imgurlParms: ImgurlParms) { + super() + this.parms = imgurlParms + } + + async upload (file: File): Promise { + const formData = new EmoFormData() + await formData.add('uid', this.parms.required.uid) + await formData.add('token', this.parms.required.token) + await formData.add('file', file) + const req: RequestUrlParam = { + url: 'https://www.imgurl.org/api/v2/upload', + method: 'POST', + headers: { + 'Content-Type': CONTENT_TYPE_FORMDATA + }, + body: formData.getBody() + } + + return await new Promise((resolve, reject) => { + request(req).then((res) => { + const json = JSON.parse(res) + const markdownText = `![ImgURL](${json.data.url as string})` + resolve(markdownText) + }).catch(err => { + reject(err) + }) + }) + } +} diff --git a/src/uploader/uploader-smms.ts b/src/uploader/uploader-smms.ts new file mode 100644 index 0000000..5b0be4a --- /dev/null +++ b/src/uploader/uploader-smms.ts @@ -0,0 +1,44 @@ +import { request, RequestUrlParam } from 'obsidian' +import { SmmsParms } from '../parms/parms-smms' +import { EmoFormData } from '../utils/emo-formdata' +import { EmoUploader } from '../base/emo-uploader' +import { CONTENT_TYPE_FORMDATA } from '../base/constants' + +export class SmmsUploader extends EmoUploader { + parms!: SmmsParms + constructor (smmsParms: SmmsParms) { + super() + this.parms = smmsParms + } + + async upload (file: File): Promise { + const formData = new EmoFormData() + await formData.add('format', 'json') + await formData.add('smfile', file) + const req: RequestUrlParam = { + url: 'https://sm.ms/api/v2/upload', + method: 'POST', + headers: { + 'Content-Type': CONTENT_TYPE_FORMDATA, + Authorization: this.parms.required.token + }, + body: formData.getBody() + } + + return await new Promise((resolve, reject) => { + request(req).then((res) => { + const json = JSON.parse(res) + let url = '' + try { + url = json.data.url + } catch (error) { + url = json.images // Image upload repeated limit, this image exists at here + } + const markdownText = `![SMMS](${url})` + resolve(markdownText) + }).catch(err => { + reject(err) + }) + }) + } +} diff --git a/src/utils/emo-formdata.ts b/src/utils/emo-formdata.ts new file mode 100644 index 0000000..5014d21 --- /dev/null +++ b/src/utils/emo-formdata.ts @@ -0,0 +1,53 @@ +import { RANDOM_BOUNDARY } from '../base/constants' +import { getArrayBuffer } from './file-helper' + +export class EmoFormData { + private body: any[] + // Now I'm using a fixed string, it works well. So let it go. + private readonly randomBoundary = RANDOM_BOUNDARY + private readonly boundary: string + private readonly endBoundary: string + constructor () { + this.body = [] + this.boundary = '--' + this.randomBoundary + this.endBoundary = this.boundary + '--' + } + + async add (name: string, value: string | File): Promise { + let data = this.boundary + '\r\n' + if (typeof value === 'string') { // add parameters + data += 'Content-Disposition: form-data; name="' + name + '"\r\n\r\n' + data += value + '\r\n' + for (let i = 0; i < data.length; i++) { + this.body.push(data.charCodeAt(i)) + } + } else if (value instanceof File) { // add files + data += 'Content-Disposition: form-data; name="' + name + '"; filename="' + value.name + '"\r\n' + data += 'Content-Type: ' + value.type + '\r\n\r\n' + for (let i = 0; i < data.length; i++) { + this.body.push(data.charCodeAt(i)) + } + await getArrayBuffer(value).then((fileBuffer) => { + const fileArray = new Uint8Array(fileBuffer) + this.body = this.body.concat(Array.prototype.slice.call(fileArray)) + }) + const endTag = '\r\n' + for (let i = 0; i < endTag.length; i++) { + this.body.push(endTag.charCodeAt(i)) + } + } + } + + getContentType (): string { // this is required when using real random character Boundary. + return 'multipart/form-data; boundary=' + this.randomBoundary + } + + getBody (): ArrayBuffer { + const endBoundaryArray = [] + for (let i = 0; i < this.endBoundary.length; i++) { // write terminator + endBoundaryArray.push(this.endBoundary.charCodeAt(i)) + } + this.body = this.body.concat(endBoundaryArray) + return new Uint8Array(this.body).buffer + } +} diff --git a/src/utils/file-helper.ts b/src/utils/file-helper.ts new file mode 100644 index 0000000..e19c869 --- /dev/null +++ b/src/utils/file-helper.ts @@ -0,0 +1,42 @@ +// file2ArrayBuffer +export async function getArrayBuffer (file: File): Promise { + return await new Promise((resolve, reject) => { + const reader = new FileReader() + let fileResult: any + reader.readAsArrayBuffer(file) + reader.onload = () => { + fileResult = reader.result + } + reader.onerror = (error) => { + reject(error) + } + reader.onloadend = () => { + resolve(fileResult) + } + }) +} + +// file2base64 +export async function getBase64 (file: File): Promise { + return await new Promise((resolve, reject) => { + const reader = new FileReader() + let fileResult: string + reader.readAsDataURL(file) + reader.onload = () => { + fileResult = reader.result as string + fileResult = fileResult.slice(fileResult.indexOf(',') + 1) + } + reader.onerror = (error) => { + reject(error) + } + reader.onloadend = () => { + resolve(fileResult) + } + }) +} + +// get a random filename +export function getRandomFileName (): string { + const time = Date.parse(new Date().toString()) + return time.toString() + (Math.random() * 10086).toString(36).slice(-6) +} From ee4a15c86cd83ed4626696d8fc2243b8a32ca327 Mon Sep 17 00:00:00 2001 From: Linnnkkk <106414095+Linnnkkk@users.noreply.github.com> Date: Sun, 19 Nov 2023 22:31:39 +0800 Subject: [PATCH 18/19] Update uploader-alist.ts --- src/uploader/uploader-alist.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/uploader/uploader-alist.ts b/src/uploader/uploader-alist.ts index 4ef459c..105f5f6 100644 --- a/src/uploader/uploader-alist.ts +++ b/src/uploader/uploader-alist.ts @@ -68,7 +68,7 @@ export class AlistUploader extends EmoUploader { }, body: JSON.stringify({ username: this.parms.required.username, - password: sha256(this.parms.required.password + '-123123123123') + password: sha256(this.parms.required.password + '-https://github.com/alist-org/alist') }) } // 发送请求并返回token From 8c9bb22844247909bf07d267d19bbea69bad8eb1 Mon Sep 17 00:00:00 2001 From: Linnnkkk <106414095+Linnnkkk@users.noreply.github.com> Date: Sun, 19 Nov 2023 22:34:00 +0800 Subject: [PATCH 19/19] Update README.md --- README.md | 45 ++------------------------------------------- 1 file changed, 2 insertions(+), 43 deletions(-) diff --git a/README.md b/README.md index bc7d938..38f120d 100755 --- a/README.md +++ b/README.md @@ -1,43 +1,2 @@ -# Obsidian Cloudinary Uploader - -![Downloads](https://img.shields.io/github/downloads/jordanhandy/obsidian-cloudinary-uploader/main.js.svg) -![Version](https://img.shields.io/github/manifest-json/v/jordanhandy/obsidian-cloudinary-uploader?color=blue) - -## Documentation -[Documentation](https://jordanhandy.github.io/obsidian-cloudinary-uploader/) -## What is it? -[Cloudinary](https://cloudinary.com/) is a cloud storage platform that allows you to upload various media files to a storage account. The media files within this storage account can then be manipulated using Cloudinary's APIs to manipulate the data properties and metadata. - -This plugin allows you to automatically upload images pasted to Obsidian directly into your Cloudinary account (instead of stored locally). Note: There is no functionality for media manipulation in this plugin. -## How it Works -![Action GIF](https://res.cloudinary.com/dakfccuv5/image/upload/v1636859613/Nov-13-2021_22-11-40_bpei0d.gif) -## Configuration -1. Disable Obsidian Safe Mode -2. Install the Plugin - - Install from the Obsidian Community Plugins tab - - Manual install - - Clone this repo - - Install dependencies with `yarn` or `npm` - - `npm run dev` will start compilation -3. Enable the Plugin -4. Configure the settings and set your: - - Cloud Name - - Upload Preset Name ([Set that here](https://cloudinary.com/documentation/upload_presets)) - - Set a Folder Name -5. Optional configuration - - Cloudinary default transformation parameters - -## Unsigned vs. Signed Uploads to Cloudinary -The uploads to Cloudinary are unsigned. [You can read more about that here](https://cloudinary.com/documentation/upload_images#unsigned_upload). A signed upload would require the use of an API key and secret, and I opted against asking for that in the plugin configuration, as a choice for security reasons. - -## Transformations -Cloudinary allows for on-the-fly image transformations using their API. To the end-user, this is accomplished by making a simple URL modification to the resulting URL that Cloudinary gives back when an upload completes. You can [read more about Cloudinary's transformation parameters here](https://cloudinary.com/documentation/transformation_reference). -As of version 0.2.0, you can now set a default transformation to be applied to all of your uploads with a comma-delimited list. **Be mindful of syntax**, as using the incorrect transformation parameters will cause your images to not render in Obsidian. - -If this were to happen, this can be fixed by simply modifying the URL following the upload. - -**Be Mindful of your [transformation token allotment](https://cloudinary.com/blog/understanding_cloudinary_s_transformation_quotas)**. Depending on your plan, Cloudinary allows for an 'x' number of transformations to take place per month. Keep this count in mind as you apply transformations to your uploads -## Thanks -Special thanks to: -1. @Creling and [their repo here](https://github.com/Creling/obsidian-image-uploader). As this was my first time creating an Obsidian plugin, their base really helped. -2. [Obsidian Unofficial Plugin Developer Docs](https://marcus.se.net/obsidian-plugin-docs/) \ No newline at end of file +原项目https://github.com/yaleiyale/obsidian-emo-uploader +新增对alist的支持