Permalink
Cannot retrieve contributors at this time
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
206 lines (170 sloc)
7.15 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import {App, MarkdownView, Plugin, PluginSettingTab, Setting} from 'obsidian'; | |
| import {Editor} from "codemirror"; | |
| interface ImgurPluginSettings { | |
| clientId: string; | |
| } | |
| const DEFAULT_SETTINGS: ImgurPluginSettings = { | |
| clientId: null | |
| } | |
| export default class ImgurPlugin extends Plugin { | |
| settings: ImgurPluginSettings; | |
| readonly cmAndHandlersMap = new Map; | |
| async loadSettings() { | |
| this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData()); | |
| } | |
| async saveSettings() { | |
| await this.saveData(this.settings); | |
| } | |
| onunload() { | |
| this.restoreOriginalHandlers(); | |
| } | |
| restoreOriginalHandlers() { | |
| this.cmAndHandlersMap.forEach((originalHandlers, cm) => { | |
| cm._handlers.drop[0] = originalHandlers.drop; | |
| cm._handlers.paste[0] = originalHandlers.paste; | |
| }) | |
| } | |
| async onload() { | |
| await this.loadSettings(); | |
| this.addSettingTab(new ImgurSettingTab(this.app, this)); | |
| this.setupImgurHandlers(); | |
| } | |
| setupImgurHandlers() { | |
| this.registerCodeMirror((cm: any) => { | |
| let originalHandlers = this.backupOriginalHandlers(cm); | |
| cm._handlers.drop[0] = (_: any, e: DragEvent) => { | |
| if (!this.settings.clientId) { | |
| console.warn("Please either set imgur client id or disable the plugin"); | |
| return originalHandlers.drop(_, e); | |
| } | |
| if (e.dataTransfer.types.length !== 1 || e.dataTransfer.types[0] !== "Files") { | |
| return originalHandlers.drop(_, e); | |
| } | |
| let files = e.dataTransfer.files; | |
| for (let i = 0; i < files.length; i++) { | |
| if (!files[i].type.startsWith("image")) { | |
| // using original handlers if at least one of drag-and drop files is not an image | |
| // It is not possible to call DragEvent.dataTransfer#clearData(images) here | |
| // to split images and non-images processing | |
| return originalHandlers.drop(_, e); | |
| } | |
| } | |
| let images = e.dataTransfer.files | |
| for (let i = 0; i < images.length; i++) { | |
| this.uploadFileAndEmbedImgurImage(images[i]).catch(console.error); | |
| } | |
| }; | |
| cm._handlers.paste[0] = (_: any, e: ClipboardEvent) => { | |
| if (!this.settings.clientId) { | |
| console.warn("Please either set imgur client id or disable the plugin"); | |
| return originalHandlers.paste(_, e); | |
| } | |
| let files = e.clipboardData.files; | |
| if (files.length === 0 || !files[0].type.startsWith("image")) { | |
| return originalHandlers.paste(_, e); | |
| } | |
| for (let i = 0; i < files.length; i++) { | |
| this.uploadFileAndEmbedImgurImage(files[i]).catch(console.error); | |
| } | |
| }; | |
| }); | |
| } | |
| backupOriginalHandlers(cm: any) { | |
| if (!this.cmAndHandlersMap.has(cm)) { | |
| let originalDropHandler = cm._handlers.drop[0]; | |
| let originalPasteHandler = cm._handlers.paste[0]; | |
| this.cmAndHandlersMap.set(cm, {drop: originalDropHandler, paste: originalPasteHandler}); | |
| } | |
| return this.cmAndHandlersMap.get(cm); | |
| } | |
| async uploadFileAndEmbedImgurImage(file: File) { | |
| let pasteId = (Math.random() + 1).toString(36).substr(2, 5); | |
| this.insertTemporaryText(pasteId); | |
| try { | |
| let resp = await this.uploadFile(file); | |
| if (!resp.ok) { | |
| let err = {response: resp, body: await resp.text()}; | |
| this.handleFailedUpload(pasteId, err) | |
| return | |
| } | |
| let json = await resp.json(); | |
| this.embedMarkDownImage(pasteId, json) | |
| } catch (e) { | |
| this.handleFailedUpload(pasteId, e) | |
| } | |
| } | |
| insertTemporaryText(pasteId: string) { | |
| let progressText = ImgurPlugin.progressTextFor(pasteId); | |
| this.getEditor().replaceSelection(progressText + "\n"); | |
| } | |
| private static progressTextFor(id: string) { | |
| return `![Uploading file...${id}]()` | |
| } | |
| uploadFile(file: File) { | |
| const data = new FormData(); | |
| data.append('image', file); | |
| return fetch('https://api.imgur.com/3/image.json', { | |
| method: 'POST', | |
| headers: new Headers({'Authorization': 'Client-ID ' + this.settings.clientId}), | |
| body: data | |
| }); | |
| } | |
| embedMarkDownImage(pasteId: string, jsonResponse: any) { | |
| let imageUrl = jsonResponse.data.link; | |
| let progressText = ImgurPlugin.progressTextFor(pasteId); | |
| let markDownImage = ``; | |
| ImgurPlugin.replaceFirstOccurrence(this.getEditor(), progressText, markDownImage); | |
| }; | |
| handleFailedUpload(pasteId: string, reason: any) { | |
| console.error("Failed imgur request: ", reason); | |
| let progressText = ImgurPlugin.progressTextFor(pasteId); | |
| ImgurPlugin.replaceFirstOccurrence(this.getEditor(), progressText, "⚠️Imgur upload failed, check dev console"); | |
| }; | |
| static replaceFirstOccurrence(editor: Editor, target: string, replacement: string) { | |
| let lines = editor.getValue().split('\n'); | |
| for (let i = 0; i < lines.length; i++) { | |
| let ch = lines[i].indexOf(target); | |
| if (ch != -1) { | |
| let from = {line: i, ch: ch}; | |
| let to = {line: i, ch: ch + target.length}; | |
| editor.replaceRange(replacement, from, to); | |
| break; | |
| } | |
| } | |
| } | |
| getEditor(): Editor { | |
| let view = this.app.workspace.activeLeaf.view as MarkdownView; | |
| return view.sourceMode.cmEditor; | |
| } | |
| } | |
| class ImgurSettingTab extends PluginSettingTab { | |
| plugin: ImgurPlugin; | |
| constructor(app: App, plugin: ImgurPlugin) { | |
| super(app, plugin); | |
| this.plugin = plugin; | |
| } | |
| display(): void { | |
| let {containerEl} = this; | |
| containerEl.empty(); | |
| containerEl.createEl('h2', {text: 'imgur.com plugin settings'}); | |
| new Setting(containerEl) | |
| .setName('Client ID') | |
| .setDesc(this.clientIdSettingDescription()) | |
| .addText(text => text.setPlaceholder('Enter your client_id') | |
| .setValue(this.plugin.settings.clientId) | |
| .onChange(async (value) => { | |
| this.plugin.settings.clientId = value; | |
| await this.plugin.saveSettings(); | |
| })); | |
| } | |
| clientIdSettingDescription() { | |
| const registerClientUrl = "https://api.imgur.com/oauth2/addclient"; | |
| let fragment = document.createDocumentFragment(); | |
| let a = document.createElement('a'); | |
| a.textContent = registerClientUrl | |
| a.setAttribute("href", registerClientUrl); | |
| fragment.append("Obtained from "); | |
| fragment.append(a); | |
| return fragment; | |
| } | |
| } |