commit a57afa86b47c58aeca557e7cbcb0d38b81159d78 Author: Gahow Wang Date: Thu May 7 15:04:41 2026 +0800 Initial commit: obsidian to gitea diff --git a/.obsidian/app.json b/.obsidian/app.json new file mode 100644 index 0000000..f99de1c --- /dev/null +++ b/.obsidian/app.json @@ -0,0 +1,16 @@ +{ + "vimMode": true, + "attachmentFolderPath": "/", + "newFileLocation": "current", + "alwaysUpdateLinks": true, + "promptDelete": false, + "showInlineTitle": false, + "pdfExportSettings": { + "includeName": false, + "pageSize": "A4", + "landscape": false, + "margin": "0", + "downscalePercent": 100 + }, + "showIndentGuide": false +} \ No newline at end of file diff --git a/.obsidian/appearance.json b/.obsidian/appearance.json new file mode 100644 index 0000000..85a4d14 --- /dev/null +++ b/.obsidian/appearance.json @@ -0,0 +1,7 @@ +{ + "cssTheme": "Minimal", + "enabledCssSnippets": [ + "table-wrap-fix", + "mermaid" + ] +} \ No newline at end of file diff --git a/.obsidian/community-plugins.json b/.obsidian/community-plugins.json new file mode 100644 index 0000000..fa8a94d --- /dev/null +++ b/.obsidian/community-plugins.json @@ -0,0 +1,10 @@ +[ + "attachment-management", + "periodic-notes", + "oz-clear-unused-images", + "obsidian-focus-mode", + "remember-cursor-position", + "remotely-save", + "copy-as-html", + "obsidian-image-toolkit" +] \ No newline at end of file diff --git a/.obsidian/core-plugins-migration.json b/.obsidian/core-plugins-migration.json new file mode 100644 index 0000000..436f43c --- /dev/null +++ b/.obsidian/core-plugins-migration.json @@ -0,0 +1,30 @@ +{ + "file-explorer": true, + "global-search": true, + "switcher": true, + "graph": true, + "backlink": true, + "canvas": true, + "outgoing-link": true, + "tag-pane": true, + "properties": false, + "page-preview": true, + "daily-notes": true, + "templates": true, + "note-composer": true, + "command-palette": true, + "slash-command": false, + "editor-status": true, + "bookmarks": true, + "markdown-importer": false, + "zk-prefixer": false, + "random-note": false, + "outline": true, + "word-count": true, + "slides": false, + "audio-recorder": false, + "workspaces": false, + "file-recovery": true, + "publish": false, + "sync": false +} \ No newline at end of file diff --git a/.obsidian/core-plugins.json b/.obsidian/core-plugins.json new file mode 100644 index 0000000..8e719d8 --- /dev/null +++ b/.obsidian/core-plugins.json @@ -0,0 +1,33 @@ +{ + "file-explorer": true, + "global-search": true, + "switcher": true, + "graph": true, + "backlink": true, + "canvas": true, + "outgoing-link": true, + "tag-pane": true, + "properties": false, + "page-preview": true, + "daily-notes": true, + "templates": true, + "note-composer": true, + "command-palette": true, + "slash-command": false, + "editor-status": true, + "bookmarks": true, + "markdown-importer": false, + "zk-prefixer": false, + "random-note": false, + "outline": true, + "word-count": true, + "slides": false, + "audio-recorder": false, + "workspaces": false, + "file-recovery": true, + "publish": false, + "sync": false, + "webviewer": false, + "footnotes": false, + "bases": true +} \ No newline at end of file diff --git a/.obsidian/daily-notes.json b/.obsidian/daily-notes.json new file mode 100644 index 0000000..89cf326 --- /dev/null +++ b/.obsidian/daily-notes.json @@ -0,0 +1,5 @@ +{ + "folder": "daily", + "format": "YYMMDD", + "template": "daily/250216" +} \ No newline at end of file diff --git a/.obsidian/graph.json b/.obsidian/graph.json new file mode 100644 index 0000000..42a46ec --- /dev/null +++ b/.obsidian/graph.json @@ -0,0 +1,22 @@ +{ + "collapse-filter": true, + "search": "", + "showTags": false, + "showAttachments": false, + "hideUnresolved": false, + "showOrphans": true, + "collapse-color-groups": true, + "colorGroups": [], + "collapse-display": true, + "showArrow": false, + "textFadeMultiplier": 0, + "nodeSizeMultiplier": 1, + "lineSizeMultiplier": 1, + "collapse-forces": true, + "centerStrength": 0.518713248970312, + "repelStrength": 10, + "linkStrength": 1, + "linkDistance": 250, + "scale": 1, + "close": true +} \ No newline at end of file diff --git a/.obsidian/hotkeys.json b/.obsidian/hotkeys.json new file mode 100644 index 0000000..3c1d108 --- /dev/null +++ b/.obsidian/hotkeys.json @@ -0,0 +1,11 @@ +{ + "app:toggle-left-sidebar": [ + { + "modifiers": [ + "Mod" + ], + "key": "B" + } + ], + "editor:toggle-bold": [] +} \ No newline at end of file diff --git a/.obsidian/plugins/attachment-management/data.json b/.obsidian/plugins/attachment-management/data.json new file mode 100644 index 0000000..53f4680 --- /dev/null +++ b/.obsidian/plugins/attachment-management/data.json @@ -0,0 +1,19 @@ +{ + "attachPath": { + "attachmentRoot": "", + "saveAttE": "obsFolder", + "attachmentPath": "${notepath}/${notename}.figs", + "attachFormat": "${date}", + "type": "GLOBAL", + "extensionOverride": [] + }, + "dateFormat": "YYMMDD-HHmmss", + "excludeExtensionPattern": "", + "autoRenameAttachment": true, + "excludedPaths": "", + "excludePathsArray": [], + "excludeSubpaths": false, + "originalNameStorage": [], + "overridePath": {}, + "disableNotification": false +} \ No newline at end of file diff --git a/.obsidian/plugins/attachment-management/main.js b/.obsidian/plugins/attachment-management/main.js new file mode 100644 index 0000000..caffb0c --- /dev/null +++ b/.obsidian/plugins/attachment-management/main.js @@ -0,0 +1,2078 @@ +/* +THIS IS A GENERATED/BUNDLED FILE BY ESBUILD +if you want to view the source, please visit the github repository of this plugin +*/ + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/main.ts +var main_exports = {}; +__export(main_exports, { + default: () => AttachmentManagementPlugin +}); +module.exports = __toCommonJS(main_exports); +var import_obsidian11 = require("obsidian"); + +// src/settings/settings.ts +var import_obsidian3 = require("obsidian"); + +// src/lib/constant.ts +var SETTINGS_VARIABLES_DATES = "${date}"; +var SETTINGS_VARIABLES_NOTEPATH = "${notepath}"; +var SETTINGS_VARIABLES_NOTENAME = "${notename}"; +var SETTINGS_VARIABLES_NOTEPARENT = "${parent}"; +var SETTINGS_VARIABLES_ORIGINALNAME = "${originalname}"; +var SETTINGS_VARIABLES_MD5 = "${md5}"; +var SETTINGS_ROOT_OBSFOLDER = "obsFolder"; +var SETTINGS_ROOT_INFOLDER = "inFolderBelow"; +var SETTINGS_ROOT_NEXTTONOTE = "nextToNote"; + +// src/model/extensionOverride.ts +var import_obsidian2 = require("obsidian"); + +// src/utils.ts +var import_obsidian = require("obsidian"); + +// node_modules/ts-md5/dist/esm/md5.js +var Md5 = class { + constructor() { + this._dataLength = 0; + this._bufferLength = 0; + this._state = new Int32Array(4); + this._buffer = new ArrayBuffer(68); + this._buffer8 = new Uint8Array(this._buffer, 0, 68); + this._buffer32 = new Uint32Array(this._buffer, 0, 17); + this.start(); + } + static hashStr(str, raw = false) { + return this.onePassHasher.start().appendStr(str).end(raw); + } + static hashAsciiStr(str, raw = false) { + return this.onePassHasher.start().appendAsciiStr(str).end(raw); + } + static _hex(x) { + const hc = Md5.hexChars; + const ho = Md5.hexOut; + let n; + let offset; + let j; + let i; + for (i = 0; i < 4; i += 1) { + offset = i * 8; + n = x[i]; + for (j = 0; j < 8; j += 2) { + ho[offset + 1 + j] = hc.charAt(n & 15); + n >>>= 4; + ho[offset + 0 + j] = hc.charAt(n & 15); + n >>>= 4; + } + } + return ho.join(""); + } + static _md5cycle(x, k) { + let a = x[0]; + let b = x[1]; + let c = x[2]; + let d = x[3]; + a += (b & c | ~b & d) + k[0] - 680876936 | 0; + a = (a << 7 | a >>> 25) + b | 0; + d += (a & b | ~a & c) + k[1] - 389564586 | 0; + d = (d << 12 | d >>> 20) + a | 0; + c += (d & a | ~d & b) + k[2] + 606105819 | 0; + c = (c << 17 | c >>> 15) + d | 0; + b += (c & d | ~c & a) + k[3] - 1044525330 | 0; + b = (b << 22 | b >>> 10) + c | 0; + a += (b & c | ~b & d) + k[4] - 176418897 | 0; + a = (a << 7 | a >>> 25) + b | 0; + d += (a & b | ~a & c) + k[5] + 1200080426 | 0; + d = (d << 12 | d >>> 20) + a | 0; + c += (d & a | ~d & b) + k[6] - 1473231341 | 0; + c = (c << 17 | c >>> 15) + d | 0; + b += (c & d | ~c & a) + k[7] - 45705983 | 0; + b = (b << 22 | b >>> 10) + c | 0; + a += (b & c | ~b & d) + k[8] + 1770035416 | 0; + a = (a << 7 | a >>> 25) + b | 0; + d += (a & b | ~a & c) + k[9] - 1958414417 | 0; + d = (d << 12 | d >>> 20) + a | 0; + c += (d & a | ~d & b) + k[10] - 42063 | 0; + c = (c << 17 | c >>> 15) + d | 0; + b += (c & d | ~c & a) + k[11] - 1990404162 | 0; + b = (b << 22 | b >>> 10) + c | 0; + a += (b & c | ~b & d) + k[12] + 1804603682 | 0; + a = (a << 7 | a >>> 25) + b | 0; + d += (a & b | ~a & c) + k[13] - 40341101 | 0; + d = (d << 12 | d >>> 20) + a | 0; + c += (d & a | ~d & b) + k[14] - 1502002290 | 0; + c = (c << 17 | c >>> 15) + d | 0; + b += (c & d | ~c & a) + k[15] + 1236535329 | 0; + b = (b << 22 | b >>> 10) + c | 0; + a += (b & d | c & ~d) + k[1] - 165796510 | 0; + a = (a << 5 | a >>> 27) + b | 0; + d += (a & c | b & ~c) + k[6] - 1069501632 | 0; + d = (d << 9 | d >>> 23) + a | 0; + c += (d & b | a & ~b) + k[11] + 643717713 | 0; + c = (c << 14 | c >>> 18) + d | 0; + b += (c & a | d & ~a) + k[0] - 373897302 | 0; + b = (b << 20 | b >>> 12) + c | 0; + a += (b & d | c & ~d) + k[5] - 701558691 | 0; + a = (a << 5 | a >>> 27) + b | 0; + d += (a & c | b & ~c) + k[10] + 38016083 | 0; + d = (d << 9 | d >>> 23) + a | 0; + c += (d & b | a & ~b) + k[15] - 660478335 | 0; + c = (c << 14 | c >>> 18) + d | 0; + b += (c & a | d & ~a) + k[4] - 405537848 | 0; + b = (b << 20 | b >>> 12) + c | 0; + a += (b & d | c & ~d) + k[9] + 568446438 | 0; + a = (a << 5 | a >>> 27) + b | 0; + d += (a & c | b & ~c) + k[14] - 1019803690 | 0; + d = (d << 9 | d >>> 23) + a | 0; + c += (d & b | a & ~b) + k[3] - 187363961 | 0; + c = (c << 14 | c >>> 18) + d | 0; + b += (c & a | d & ~a) + k[8] + 1163531501 | 0; + b = (b << 20 | b >>> 12) + c | 0; + a += (b & d | c & ~d) + k[13] - 1444681467 | 0; + a = (a << 5 | a >>> 27) + b | 0; + d += (a & c | b & ~c) + k[2] - 51403784 | 0; + d = (d << 9 | d >>> 23) + a | 0; + c += (d & b | a & ~b) + k[7] + 1735328473 | 0; + c = (c << 14 | c >>> 18) + d | 0; + b += (c & a | d & ~a) + k[12] - 1926607734 | 0; + b = (b << 20 | b >>> 12) + c | 0; + a += (b ^ c ^ d) + k[5] - 378558 | 0; + a = (a << 4 | a >>> 28) + b | 0; + d += (a ^ b ^ c) + k[8] - 2022574463 | 0; + d = (d << 11 | d >>> 21) + a | 0; + c += (d ^ a ^ b) + k[11] + 1839030562 | 0; + c = (c << 16 | c >>> 16) + d | 0; + b += (c ^ d ^ a) + k[14] - 35309556 | 0; + b = (b << 23 | b >>> 9) + c | 0; + a += (b ^ c ^ d) + k[1] - 1530992060 | 0; + a = (a << 4 | a >>> 28) + b | 0; + d += (a ^ b ^ c) + k[4] + 1272893353 | 0; + d = (d << 11 | d >>> 21) + a | 0; + c += (d ^ a ^ b) + k[7] - 155497632 | 0; + c = (c << 16 | c >>> 16) + d | 0; + b += (c ^ d ^ a) + k[10] - 1094730640 | 0; + b = (b << 23 | b >>> 9) + c | 0; + a += (b ^ c ^ d) + k[13] + 681279174 | 0; + a = (a << 4 | a >>> 28) + b | 0; + d += (a ^ b ^ c) + k[0] - 358537222 | 0; + d = (d << 11 | d >>> 21) + a | 0; + c += (d ^ a ^ b) + k[3] - 722521979 | 0; + c = (c << 16 | c >>> 16) + d | 0; + b += (c ^ d ^ a) + k[6] + 76029189 | 0; + b = (b << 23 | b >>> 9) + c | 0; + a += (b ^ c ^ d) + k[9] - 640364487 | 0; + a = (a << 4 | a >>> 28) + b | 0; + d += (a ^ b ^ c) + k[12] - 421815835 | 0; + d = (d << 11 | d >>> 21) + a | 0; + c += (d ^ a ^ b) + k[15] + 530742520 | 0; + c = (c << 16 | c >>> 16) + d | 0; + b += (c ^ d ^ a) + k[2] - 995338651 | 0; + b = (b << 23 | b >>> 9) + c | 0; + a += (c ^ (b | ~d)) + k[0] - 198630844 | 0; + a = (a << 6 | a >>> 26) + b | 0; + d += (b ^ (a | ~c)) + k[7] + 1126891415 | 0; + d = (d << 10 | d >>> 22) + a | 0; + c += (a ^ (d | ~b)) + k[14] - 1416354905 | 0; + c = (c << 15 | c >>> 17) + d | 0; + b += (d ^ (c | ~a)) + k[5] - 57434055 | 0; + b = (b << 21 | b >>> 11) + c | 0; + a += (c ^ (b | ~d)) + k[12] + 1700485571 | 0; + a = (a << 6 | a >>> 26) + b | 0; + d += (b ^ (a | ~c)) + k[3] - 1894986606 | 0; + d = (d << 10 | d >>> 22) + a | 0; + c += (a ^ (d | ~b)) + k[10] - 1051523 | 0; + c = (c << 15 | c >>> 17) + d | 0; + b += (d ^ (c | ~a)) + k[1] - 2054922799 | 0; + b = (b << 21 | b >>> 11) + c | 0; + a += (c ^ (b | ~d)) + k[8] + 1873313359 | 0; + a = (a << 6 | a >>> 26) + b | 0; + d += (b ^ (a | ~c)) + k[15] - 30611744 | 0; + d = (d << 10 | d >>> 22) + a | 0; + c += (a ^ (d | ~b)) + k[6] - 1560198380 | 0; + c = (c << 15 | c >>> 17) + d | 0; + b += (d ^ (c | ~a)) + k[13] + 1309151649 | 0; + b = (b << 21 | b >>> 11) + c | 0; + a += (c ^ (b | ~d)) + k[4] - 145523070 | 0; + a = (a << 6 | a >>> 26) + b | 0; + d += (b ^ (a | ~c)) + k[11] - 1120210379 | 0; + d = (d << 10 | d >>> 22) + a | 0; + c += (a ^ (d | ~b)) + k[2] + 718787259 | 0; + c = (c << 15 | c >>> 17) + d | 0; + b += (d ^ (c | ~a)) + k[9] - 343485551 | 0; + b = (b << 21 | b >>> 11) + c | 0; + x[0] = a + x[0] | 0; + x[1] = b + x[1] | 0; + x[2] = c + x[2] | 0; + x[3] = d + x[3] | 0; + } + /** + * Initialise buffer to be hashed + */ + start() { + this._dataLength = 0; + this._bufferLength = 0; + this._state.set(Md5.stateIdentity); + return this; + } + // Char to code point to to array conversion: + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/charCodeAt + // #Example.3A_Fixing_charCodeAt_to_handle_non-Basic-Multilingual-Plane_characters_if_their_presence_earlier_in_the_string_is_unknown + /** + * Append a UTF-8 string to the hash buffer + * @param str String to append + */ + appendStr(str) { + const buf8 = this._buffer8; + const buf32 = this._buffer32; + let bufLen = this._bufferLength; + let code; + let i; + for (i = 0; i < str.length; i += 1) { + code = str.charCodeAt(i); + if (code < 128) { + buf8[bufLen++] = code; + } else if (code < 2048) { + buf8[bufLen++] = (code >>> 6) + 192; + buf8[bufLen++] = code & 63 | 128; + } else if (code < 55296 || code > 56319) { + buf8[bufLen++] = (code >>> 12) + 224; + buf8[bufLen++] = code >>> 6 & 63 | 128; + buf8[bufLen++] = code & 63 | 128; + } else { + code = (code - 55296) * 1024 + (str.charCodeAt(++i) - 56320) + 65536; + if (code > 1114111) { + throw new Error("Unicode standard supports code points up to U+10FFFF"); + } + buf8[bufLen++] = (code >>> 18) + 240; + buf8[bufLen++] = code >>> 12 & 63 | 128; + buf8[bufLen++] = code >>> 6 & 63 | 128; + buf8[bufLen++] = code & 63 | 128; + } + if (bufLen >= 64) { + this._dataLength += 64; + Md5._md5cycle(this._state, buf32); + bufLen -= 64; + buf32[0] = buf32[16]; + } + } + this._bufferLength = bufLen; + return this; + } + /** + * Append an ASCII string to the hash buffer + * @param str String to append + */ + appendAsciiStr(str) { + const buf8 = this._buffer8; + const buf32 = this._buffer32; + let bufLen = this._bufferLength; + let i; + let j = 0; + for (; ; ) { + i = Math.min(str.length - j, 64 - bufLen); + while (i--) { + buf8[bufLen++] = str.charCodeAt(j++); + } + if (bufLen < 64) { + break; + } + this._dataLength += 64; + Md5._md5cycle(this._state, buf32); + bufLen = 0; + } + this._bufferLength = bufLen; + return this; + } + /** + * Append a byte array to the hash buffer + * @param input array to append + */ + appendByteArray(input) { + const buf8 = this._buffer8; + const buf32 = this._buffer32; + let bufLen = this._bufferLength; + let i; + let j = 0; + for (; ; ) { + i = Math.min(input.length - j, 64 - bufLen); + while (i--) { + buf8[bufLen++] = input[j++]; + } + if (bufLen < 64) { + break; + } + this._dataLength += 64; + Md5._md5cycle(this._state, buf32); + bufLen = 0; + } + this._bufferLength = bufLen; + return this; + } + /** + * Get the state of the hash buffer + */ + getState() { + const s = this._state; + return { + buffer: String.fromCharCode.apply(null, Array.from(this._buffer8)), + buflen: this._bufferLength, + length: this._dataLength, + state: [s[0], s[1], s[2], s[3]] + }; + } + /** + * Override the current state of the hash buffer + * @param state New hash buffer state + */ + setState(state) { + const buf = state.buffer; + const x = state.state; + const s = this._state; + let i; + this._dataLength = state.length; + this._bufferLength = state.buflen; + s[0] = x[0]; + s[1] = x[1]; + s[2] = x[2]; + s[3] = x[3]; + for (i = 0; i < buf.length; i += 1) { + this._buffer8[i] = buf.charCodeAt(i); + } + } + /** + * Hash the current state of the hash buffer and return the result + * @param raw Whether to return the value as an `Int32Array` + */ + end(raw = false) { + const bufLen = this._bufferLength; + const buf8 = this._buffer8; + const buf32 = this._buffer32; + const i = (bufLen >> 2) + 1; + this._dataLength += bufLen; + const dataBitsLen = this._dataLength * 8; + buf8[bufLen] = 128; + buf8[bufLen + 1] = buf8[bufLen + 2] = buf8[bufLen + 3] = 0; + buf32.set(Md5.buffer32Identity.subarray(i), i); + if (bufLen > 55) { + Md5._md5cycle(this._state, buf32); + buf32.set(Md5.buffer32Identity); + } + if (dataBitsLen <= 4294967295) { + buf32[14] = dataBitsLen; + } else { + const matches = dataBitsLen.toString(16).match(/(.*?)(.{0,8})$/); + if (matches === null) { + return; + } + const lo = parseInt(matches[2], 16); + const hi = parseInt(matches[1], 16) || 0; + buf32[14] = lo; + buf32[15] = hi; + } + Md5._md5cycle(this._state, buf32); + return raw ? this._state : Md5._hex(this._state); + } +}; +Md5.stateIdentity = new Int32Array([1732584193, -271733879, -1732584194, 271733878]); +Md5.buffer32Identity = new Int32Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); +Md5.hexChars = "0123456789abcdef"; +Md5.hexOut = []; +Md5.onePassHasher = new Md5(); +if (Md5.hashStr("hello") !== "5d41402abc4b2a76b9719d911017c592") { + throw new Error("Md5 self test failed."); +} + +// src/utils.ts +var PASTED_IMAGE_PREFIX = "Pasted image "; +var ImageExtensionRegex = /^(jpe?g|png|gif|svg|bmp|eps|webp)$/i; +function isMarkdownFile(extension) { + return extension === "md"; +} +function isCanvasFile(extension) { + return extension === "canvas"; +} +function isPastedImage(file) { + if (file instanceof import_obsidian.TFile) { + if (file.name.startsWith(PASTED_IMAGE_PREFIX)) { + return true; + } + } + return false; +} +function isImage(extension) { + const match = extension.match(ImageExtensionRegex); + if (match !== null) { + return true; + } + return false; +} +function stripPaths(src, dst) { + if (src === dst) { + return { stripedSrc: src, stripedDst: dst }; + } + const srcParts = src.split("/"); + const dstParts = dst.split("/"); + if (srcParts.length !== dstParts.length) { + return { stripedSrc: src, stripedDst: dst }; + } + for (let i = 0; i < srcParts.length; i++) { + const srcPart = srcParts[i]; + const dstPart = dstParts[i]; + if (srcPart !== dstPart) { + return { + stripedSrc: srcParts.slice(0, i + 1).join("/"), + stripedDst: dstParts.slice(0, i + 1).join("/") + }; + } + } + return { stripedSrc: "", stripedDst: "" }; +} +function matchExtension(extension, pattern) { + if (!pattern || pattern === "") + return false; + return new RegExp(pattern).test(extension); +} +function isAttachment(settings, filePath) { + let file = null; + if (filePath instanceof import_obsidian.TAbstractFile) { + file = filePath; + } else { + file = this.app.vault.getAbstractFileByPath(filePath); + } + if (file === null || !(file instanceof import_obsidian.TFile)) { + return false; + } + if (isMarkdownFile(file.extension) || isCanvasFile(file.extension)) { + return false; + } + return !matchExtension(file.extension, settings.excludeExtensionPattern); +} +async function md5sum(adapter, file) { + const md5 = new Md5(); + if (!adapter.exists(file.path, true)) { + return ""; + } + const content = await adapter.readBinary(file.path); + md5.appendByteArray(new Uint8Array(content)); + const ret = md5.end(); + return ret.toUpperCase(); +} +function validateExtensionEntry(setting, plugin) { + const wrongIndex = []; + if (setting.extensionOverride !== void 0) { + const extOverride = setting.extensionOverride; + if (extOverride.some((ext) => ext.extension === "")) { + wrongIndex.push({ type: "empty", index: extOverride.findIndex((ext) => ext.extension === "") }); + } + const duplicate = extOverride.map((ext) => ext.extension).filter((value, index, self) => self.indexOf(value) !== index); + if (duplicate.length > 0) { + duplicate.forEach((dupli) => { + wrongIndex.push({ type: "duplicate", index: extOverride.findIndex((ext) => dupli === ext.extension) }); + }); + } + const markdown = extOverride.filter((ext) => ext.extension === "md"); + if (markdown.length > 0) { + wrongIndex.push({ type: "md", index: extOverride.findIndex((ext) => ext.extension === "md") }); + } + const canvas = extOverride.filter((ext) => ext.extension === "canvas"); + if (canvas.length > 0) { + wrongIndex.push({ type: "canvas", index: extOverride.findIndex((ext) => ext.extension === "canvas") }); + } + const excludedFromSettings = plugin.excludeExtensionPattern.split("|"); + const excluded = extOverride.filter((ext) => excludedFromSettings.includes(ext.extension)); + if (excluded.length > 0) { + wrongIndex.push({ + type: "excluded", + index: extOverride.findIndex((ext) => excludedFromSettings.includes(ext.extension)) + }); + } + } + return wrongIndex; +} +function generateErrorExtensionMessage(type) { + if (type === "canvas") { + new import_obsidian.Notice("Canvas is not supported as an extension override."); + } else if (type === "md") { + new import_obsidian.Notice("Markdown is not supported as an extension override."); + } else if (type === "empty") { + new import_obsidian.Notice("Extension override cannot be empty."); + } else if (type === "duplicate") { + new import_obsidian.Notice("Duplicate extension override."); + } else if (type === "excluded") { + new import_obsidian.Notice("Extension override cannot be an excluded extension."); + } +} + +// src/lib/log.ts +var DEBUG = false; +if (DEBUG) + console.log("DEBUG is enabled"); +function debugLog(...args) { + if (DEBUG) { + console.log(new Date().toISOString().slice(11, 23), ...args); + } +} + +// src/model/extensionOverride.ts +function getExtensionOverrideSetting(extension, settings) { + if (settings.extensionOverride === void 0 || settings.extensionOverride.length === 0) { + return { extSetting: void 0 }; + } + for (let i = 0; i < settings.extensionOverride.length; i++) { + if (matchExtension(extension, settings.extensionOverride[i].extension)) { + debugLog( + "getExtensionOverrideSetting - ", + settings.extensionOverride[i].extension, + settings.extensionOverride[i] + ); + return { extSetting: settings.extensionOverride[i] }; + } + } + return { extSetting: void 0 }; +} +var OverrideExtensionModal = class extends import_obsidian2.Modal { + constructor(plugin, settings, onSubmit) { + super(plugin.app); + this.plugin = plugin; + this.settings = settings; + this.onSubmit = onSubmit; + } + displaySw(cont) { + cont.findAll(".setting-item").forEach((el) => { + var _a; + if ((_a = el.getAttr("class")) == null ? void 0 : _a.includes("override_root_folder_set")) { + if (this.settings.saveAttE === "obsFolder") { + el.hide(); + } else { + el.show(); + } + } + }); + } + onOpen() { + const { contentEl } = this; + contentEl.empty(); + contentEl.createEl("h3", { + text: `Extension settings for ${this.settings.extension}` + }); + new import_obsidian2.Setting(contentEl).setName("Root path to save attachment").setDesc("Select root path of attachment").addDropdown( + (text) => text.addOption(`${SETTINGS_ROOT_OBSFOLDER}`, "Copy Obsidian settings").addOption(`${SETTINGS_ROOT_INFOLDER}`, "In the folder specified below").addOption(`${SETTINGS_ROOT_NEXTTONOTE}`, "Next to note in folder specified below").setValue(this.settings.saveAttE).onChange(async (value) => { + this.settings.saveAttE = value; + this.displaySw(contentEl); + this.onOpen(); + }) + ); + if (this.settings.saveAttE !== "obsFolder") { + new import_obsidian2.Setting(contentEl).setName("Root folder").setClass("override_root_folder_set").addText( + (text) => text.setPlaceholder(DEFAULT_SETTINGS.attachPath.attachmentRoot).setValue(this.settings.attachmentRoot).onChange(async (value) => { + this.settings.attachmentRoot = value; + }) + ); + } + new import_obsidian2.Setting(contentEl).setName("Attachment path").setDesc( + `Path of attachment in root folder, available variables ${SETTINGS_VARIABLES_NOTEPATH}, ${SETTINGS_VARIABLES_NOTENAME} and ${SETTINGS_VARIABLES_NOTEPARENT}` + ).addText( + (text) => text.setPlaceholder(DEFAULT_SETTINGS.attachPath.attachmentPath).setValue(this.settings.attachmentPath).onChange(async (value) => { + this.settings.attachmentPath = value; + }) + ); + new import_obsidian2.Setting(contentEl).setName("Attachment format").setDesc( + `Define how to name the attachment file, available variables ${SETTINGS_VARIABLES_DATES}, ${SETTINGS_VARIABLES_NOTENAME}, ${SETTINGS_VARIABLES_MD5} and ${SETTINGS_VARIABLES_ORIGINALNAME}.` + ).addText( + (text) => text.setPlaceholder(DEFAULT_SETTINGS.attachPath.attachFormat).setValue(this.settings.attachFormat).onChange(async (value) => { + this.settings.attachFormat = value; + }) + ); + new import_obsidian2.Setting(contentEl).addButton( + (button) => button.setButtonText("Save").onClick(async () => { + this.onSubmit(this.settings); + this.close(); + }) + ); + } + onClose() { + const { contentEl } = this; + contentEl.empty(); + } +}; + +// src/settings/settings.ts +var DEFAULT_SETTINGS = { + attachPath: { + attachmentRoot: "", + saveAttE: `${SETTINGS_ROOT_OBSFOLDER}`, + attachmentPath: `${SETTINGS_VARIABLES_NOTEPATH}/${SETTINGS_VARIABLES_NOTENAME}`, + attachFormat: `IMG-${SETTINGS_VARIABLES_DATES}`, + type: "GLOBAL" /* GLOBAL */ + }, + dateFormat: "YYYYMMDDHHmmssSSS", + excludeExtensionPattern: "", + autoRenameAttachment: true, + excludedPaths: "", + excludePathsArray: [], + excludeSubpaths: false, + originalNameStorage: [], + overridePath: {}, + disableNotification: false +}; +var SettingTab = class extends import_obsidian3.PluginSettingTab { + constructor(app2, plugin) { + super(app2, plugin); + this.plugin = plugin; + } + displaySw(cont) { + cont.findAll(".setting-item").forEach((el) => { + var _a; + if ((_a = el.getAttr("class")) == null ? void 0 : _a.includes("root_folder_set")) { + if (this.plugin.settings.attachPath.saveAttE === "obsFolder") { + el.hide(); + } else { + el.show(); + } + } + }); + } + splitPath(path2) { + const splitted = path2.split(";"); + const rets = []; + for (const s of splitted) { + rets.push(s.trim()); + } + return { splittedPaths: rets }; + } + display() { + const { containerEl } = this; + containerEl.empty(); + new import_obsidian3.Setting(containerEl).setName("Root path to save attachment").setDesc("Select root path of attachment").addDropdown( + (text) => text.addOption(`${SETTINGS_ROOT_OBSFOLDER}`, "Copy Obsidian settings").addOption(`${SETTINGS_ROOT_INFOLDER}`, "In the folder specified below").addOption(`${SETTINGS_ROOT_NEXTTONOTE}`, "Next to note in folder specified below").setValue(this.plugin.settings.attachPath.saveAttE).onChange(async (value) => { + this.plugin.settings.attachPath.saveAttE = value; + this.displaySw(containerEl); + await this.plugin.saveSettings(); + }) + ); + new import_obsidian3.Setting(containerEl).setName("Root folder").setDesc("Root folder of new attachment").setClass("root_folder_set").addText( + (text) => text.setPlaceholder(DEFAULT_SETTINGS.attachPath.attachmentRoot).setValue(this.plugin.settings.attachPath.attachmentRoot).onChange(async (value) => { + debugLog("setting - attachment root:" + value); + this.plugin.settings.attachPath.attachmentRoot = value; + await this.plugin.saveSettings(); + }) + ); + new import_obsidian3.Setting(containerEl).setName("Attachment path").setDesc( + `Path of attachment in root folder, available variables ${SETTINGS_VARIABLES_NOTEPATH}, ${SETTINGS_VARIABLES_NOTENAME}, ${SETTINGS_VARIABLES_NOTEPARENT}` + ).addText( + (text) => text.setPlaceholder(DEFAULT_SETTINGS.attachPath.attachmentPath).setValue(this.plugin.settings.attachPath.attachmentPath).onChange(async (value) => { + debugLog("setting - attachment path:" + value); + this.plugin.settings.attachPath.attachmentPath = value; + await this.plugin.saveSettings(); + }) + ); + new import_obsidian3.Setting(containerEl).setName("Attachment format").setDesc( + `Define how to name the attachment file, available variables ${SETTINGS_VARIABLES_DATES}, ${SETTINGS_VARIABLES_NOTENAME}, ${SETTINGS_VARIABLES_MD5} and ${SETTINGS_VARIABLES_ORIGINALNAME}.` + ).addText( + (text) => text.setPlaceholder(DEFAULT_SETTINGS.attachPath.attachFormat).setValue(this.plugin.settings.attachPath.attachFormat).onChange(async (value) => { + debugLog("setting - attachment format:" + value); + this.plugin.settings.attachPath.attachFormat = value; + await this.plugin.saveSettings(); + }) + ); + new import_obsidian3.Setting(containerEl).setName("Date format").setDesc( + createFragment((frag) => { + frag.appendText("Moment date format to use "); + frag.createEl("a", { + href: "https://momentjscom.readthedocs.io/en/latest/moment/04-displaying/01-format", + text: "Moment format options" + }); + }) + ).addMomentFormat((component) => { + component.setPlaceholder(DEFAULT_SETTINGS.dateFormat).setValue(this.plugin.settings.dateFormat).onChange(async (value) => { + debugLog("setting - date format:" + value); + this.plugin.settings.dateFormat = value; + await this.plugin.saveSettings(); + }); + }); + new import_obsidian3.Setting(containerEl).setName("Automatically rename attachment").setDesc( + "Automatically rename the attachment folder/filename when you rename the folder/filename where the corresponding md/canvas file be placed." + ).addToggle( + (toggle) => toggle.setValue(this.plugin.settings.autoRenameAttachment).onChange(async (value) => { + debugLog("setting - automatically rename attachment folder:" + value); + this.plugin.settings.autoRenameAttachment = value; + await this.plugin.saveSettings(); + }) + ); + new import_obsidian3.Setting(containerEl).setName("Extension override").setDesc("Using the extension override if you want to autorename the attachment with a specific extension (e.g. pdf or zip).").addButton((btn) => { + btn.setButtonText("Add extension overrides").onClick(async () => { + if (this.plugin.settings.attachPath.extensionOverride === void 0) { + this.plugin.settings.attachPath.extensionOverride = []; + } + this.plugin.settings.attachPath.extensionOverride.push({ + extension: "", + attachmentRoot: this.plugin.settings.attachPath.attachmentRoot, + saveAttE: this.plugin.settings.attachPath.saveAttE, + attachmentPath: this.plugin.settings.attachPath.attachmentPath, + attachFormat: this.plugin.settings.attachPath.attachFormat + }); + await this.plugin.saveSettings(); + this.display(); + }); + }); + if (this.plugin.settings.attachPath.extensionOverride !== void 0) { + this.plugin.settings.attachPath.extensionOverride.forEach((ext) => { + new import_obsidian3.Setting(containerEl).setName("Extension").setDesc("Extension to override").setClass("override_extension_set").addText( + (text) => text.setPlaceholder("pdf|docx?").setValue(ext.extension).onChange(async (value) => { + ext.extension = value; + }) + ).addButton((btn) => { + btn.setIcon("trash").setTooltip("Remove extension override").onClick(async () => { + var _a, _b, _c; + const index = (_b = (_a = this.plugin.settings.attachPath.extensionOverride) == null ? void 0 : _a.indexOf(ext)) != null ? _b : -1; + (_c = this.plugin.settings.attachPath.extensionOverride) == null ? void 0 : _c.splice(index, 1); + await this.plugin.saveSettings(); + this.display(); + }); + }).addButton((btn) => { + btn.setIcon("pencil").setTooltip("Edit extension override").onClick(async () => { + new OverrideExtensionModal(this.plugin, ext, (result) => { + ext = result; + }).open(); + }); + }).addButton((btn) => { + btn.setIcon("check").setTooltip("Save extension override").onClick(async () => { + const wrongIndex = validateExtensionEntry(this.plugin.settings.attachPath, this.plugin.settings); + if (wrongIndex.length > 0) { + for (const i of wrongIndex) { + const resIndex = i.index < 0 ? 0 : i.index; + const wrongSetting = containerEl.getElementsByClassName("override_extension_set")[resIndex]; + wrongSetting.getElementsByTagName("input")[0].style.border = "1px solid var(--color-red)"; + generateErrorExtensionMessage(i.type); + } + return; + } + await this.plugin.saveSettings(); + this.display(); + new import_obsidian3.Notice("Saved extension override"); + }); + }); + }); + } + new import_obsidian3.Setting(containerEl).setName("Exclude extension pattern").setDesc(`Regex pattern to exclude certain extensions from being handled.`).addText( + (text) => text.setPlaceholder("pdf|docx?|xlsx?|pptx?|zip|rar").setValue(this.plugin.settings.excludeExtensionPattern).onChange(async (value) => { + this.plugin.settings.excludeExtensionPattern = value; + await this.plugin.saveSettings(); + }) + ); + new import_obsidian3.Setting(containerEl).setName("Excluded paths").setDesc( + `Provide the full path of the folder names (case sensitive and without leading slash '/') divided by semicolon (;) to be excluded from renaming.` + ).addTextArea((component) => { + component.setValue(this.plugin.settings.excludedPaths).onChange(async (value) => { + this.plugin.settings.excludedPaths = value; + const { splittedPaths } = this.splitPath(value); + this.plugin.settings.excludePathsArray = splittedPaths; + debugLog("setting - excluded paths:" + value, splittedPaths); + await this.plugin.saveSettings(); + }); + }); + new import_obsidian3.Setting(containerEl).setName("Exclude subpaths").setDesc("Turn on this option if you want to also exclude all subfolders of the folder paths provided above.").addToggle( + (toggle) => toggle.setValue(this.plugin.settings.excludeSubpaths).onChange(async (value) => { + debugLog("setting - excluded subpaths:" + value); + this.plugin.settings.excludeSubpaths = value; + await this.plugin.saveSettings(); + }) + ); + this.displaySw(containerEl); + } +}; + +// src/model/override.ts +var import_obsidian4 = require("obsidian"); +var OverrideModal = class extends import_obsidian4.Modal { + constructor(plugin, file, setting) { + super(plugin.app); + this.plugin = plugin; + this.file = file; + this.setting = setting; + } + displaySw(cont) { + cont.findAll(".setting-item").forEach((el) => { + var _a; + if ((_a = el.getAttr("class")) == null ? void 0 : _a.includes("override_root_folder_set")) { + if (this.setting.saveAttE === "obsFolder") { + el.hide(); + } else { + el.show(); + } + } + }); + } + onOpen() { + const { contentEl } = this; + contentEl.empty(); + contentEl.createEl("h3", { + text: "Overriding Settings" + }); + new import_obsidian4.Setting(contentEl).setName("Root path to save attachment").setDesc("Select root path of attachment").addDropdown( + (text) => text.addOption(`${SETTINGS_ROOT_OBSFOLDER}`, "Copy Obsidian settings").addOption(`${SETTINGS_ROOT_INFOLDER}`, "In the folder specified below").addOption(`${SETTINGS_ROOT_NEXTTONOTE}`, "Next to note in folder specified below").setValue(this.setting.saveAttE).onChange(async (value) => { + this.setting.saveAttE = value; + this.displaySw(contentEl); + }) + ); + new import_obsidian4.Setting(contentEl).setName("Root folder").setClass("override_root_folder_set").addText( + (text) => text.setPlaceholder(DEFAULT_SETTINGS.attachPath.attachmentRoot).setValue(this.setting.attachmentRoot).onChange(async (value) => { + debugLog("override - attachment root:" + value); + this.setting.attachmentRoot = value; + }) + ); + new import_obsidian4.Setting(contentEl).setName("Attachment path").setDesc( + `Path of attachment in root folder, available variables ${SETTINGS_VARIABLES_NOTEPATH}, ${SETTINGS_VARIABLES_NOTENAME} and ${SETTINGS_VARIABLES_NOTEPARENT}` + ).addText( + (text) => text.setPlaceholder(DEFAULT_SETTINGS.attachPath.attachmentPath).setValue(this.setting.attachmentPath).onChange(async (value) => { + debugLog("override - attachment path:" + value); + this.setting.attachmentPath = value; + }) + ); + new import_obsidian4.Setting(contentEl).setName("Attachment format").setDesc( + `Define how to name the attachment file, available variables ${SETTINGS_VARIABLES_DATES}, ${SETTINGS_VARIABLES_NOTENAME}, ${SETTINGS_VARIABLES_MD5} and ${SETTINGS_VARIABLES_ORIGINALNAME}.` + ).addText( + (text) => text.setPlaceholder(DEFAULT_SETTINGS.attachPath.attachFormat).setValue(this.setting.attachFormat).onChange(async (value) => { + debugLog("override - attachment format:" + value); + this.setting.attachFormat = value; + }) + ); + new import_obsidian4.Setting(contentEl).addButton((btn) => { + btn.setButtonText("Add extension overrides").onClick(async () => { + if (this.setting.extensionOverride === void 0) { + this.setting.extensionOverride = []; + } + this.setting.extensionOverride.push({ + extension: "", + saveAttE: this.setting.saveAttE, + attachmentRoot: this.setting.attachmentRoot, + attachmentPath: this.setting.attachmentPath, + attachFormat: this.setting.attachFormat + }); + this.onOpen(); + }); + }); + if (this.setting.extensionOverride !== void 0) { + this.setting.extensionOverride.forEach((ext) => { + new import_obsidian4.Setting(contentEl).setName("Extension").setDesc("Extension to override").setClass("override_extension_set").addText( + (text) => text.setPlaceholder("pdf").setValue(ext.extension).onChange(async (value) => { + ext.extension = value; + }) + ).addButton((btn) => { + btn.setIcon("trash").onClick(async () => { + var _a, _b, _c; + const index = (_b = (_a = this.setting.extensionOverride) == null ? void 0 : _a.indexOf(ext)) != null ? _b : -1; + (_c = this.setting.extensionOverride) == null ? void 0 : _c.splice(index, 1); + this.onOpen(); + }); + }).addButton((btn) => { + btn.setIcon("pencil").onClick(async () => { + new OverrideExtensionModal(this.plugin, ext, (result) => { + ext = result; + }).open(); + }); + }); + }); + } + new import_obsidian4.Setting(contentEl).addButton((btn) => { + btn.setButtonText("Reset").onClick(async () => { + this.setting = this.plugin.settings.attachPath; + delete this.plugin.settings.overridePath[this.file.path]; + await this.plugin.saveSettings(); + await this.plugin.loadSettings(); + new import_obsidian4.Notice(`Reset attachment setting of ${this.file.path}`); + this.close(); + }); + }).addButton( + (btn) => btn.setButtonText("Submit").setCta().onClick(async () => { + if (this.file instanceof import_obsidian4.TFile) { + this.setting.type = "FILE" /* FILE */; + } else if (this.file instanceof import_obsidian4.TFolder) { + this.setting.type = "FOLDER" /* FOLDER */; + } + this.plugin.settings.overridePath[this.file.path] = this.setting; + await this.plugin.saveSettings(); + debugLog("override - overriding settings:", this.file.path, this.setting); + new import_obsidian4.Notice(`Overridden attachment setting of ${this.file.path}`); + this.close(); + }) + ); + this.displaySw(contentEl); + } + onClose() { + const { contentEl } = this; + contentEl.empty(); + } +}; + +// src/model/confirm.ts +var import_obsidian9 = require("obsidian"); + +// src/arrange.ts +var import_obsidian8 = require("obsidian"); + +// src/lib/path.ts +var path = { + // Credit: [@creationix/path.js](https://gist.github.com/creationix/7435851) + join(...partSegments) { + let parts = []; + for (let i = 0, l = partSegments.length; i < l; i++) { + parts = parts.concat(partSegments[i].split("/")); + } + const newParts = []; + for (let i = 0, l = parts.length; i < l; i++) { + const part = parts[i]; + if (!part || part === ".") + continue; + if (part === "..") + newParts.pop(); + else + newParts.push(part); + } + if (parts[0] === "") + newParts.unshift(""); + return newParts.join("/"); + }, + // A simple function to get the dirname of a path + // Trailing slashes are ignored. Leading slash is preserved. + dirname(filepath) { + return this.join(filepath, ".."); + }, + // returns the last part of a path, e.g. 'foo.jpg' + basename(filepath, extension = "") { + const sp = filepath.split("/"); + const filename = sp[sp.length - 1]; + if (extension !== "") { + return filename.slice(0, filename.length - extension.length - 1); + } + return sp[sp.length - 1]; + }, + // return extension without dot, e.g. 'jpg' + extname(filepath) { + const positions = [...filepath.matchAll(new RegExp("\\.", "gi"))].map((a) => a.index); + const idx = positions[positions.length - 1]; + if (idx === void 0) { + return ""; + } + return filepath.slice(idx + 1); + } +}; + +// src/override.ts +var import_obsidian5 = require("obsidian"); +function getOverrideSetting(settings, file, oldPath = "") { + if (Object.keys(settings.overridePath).length === 0) { + return { settingPath: "", setting: settings.attachPath }; + } + const candidates = {}; + let fileType; + let filePath; + fileType = file instanceof import_obsidian5.TFile; + fileType = !(file instanceof import_obsidian5.TFolder); + if (oldPath === "") { + filePath = file.path; + } else { + filePath = oldPath; + } + for (const overridePath of Object.keys(settings.overridePath)) { + const overrideSetting = settings.overridePath[overridePath]; + if (fileType) { + if (overridePath === filePath && overrideSetting.type === "FILE" /* FILE */) { + return { settingPath: overridePath, setting: overrideSetting }; + } else if (filePath.startsWith(overridePath) && filePath.charAt(overridePath.length) === "/" && overrideSetting.type === "FOLDER" /* FOLDER */) { + candidates[overridePath] = overrideSetting; + } + } else { + if (overridePath === filePath && overrideSetting.type === "FOLDER" /* FOLDER */) { + return { settingPath: overridePath, setting: overrideSetting }; + } else if (filePath.startsWith(overridePath) && filePath.charAt(overridePath.length) === "/" && overrideSetting.type === "FOLDER" /* FOLDER */) { + candidates[overridePath] = overrideSetting; + } + } + } + if (Object.keys(candidates).length === 0) { + return { settingPath: "", setting: settings.attachPath }; + } + const sortedK = Object.keys(candidates).sort( + (a, b) => a.split("/").length > b.split("/").length ? -1 : a.split("/").length < b.split("/").length ? 1 : 0 + ); + debugLog("getOverrideSetting - sortedK:", sortedK); + for (const k of sortedK) { + if (filePath.startsWith(k)) { + return { settingPath: k, setting: candidates[k] }; + } + } + return { settingPath: "", setting: settings.attachPath }; +} +function getRenameOverrideSetting(settings, file, oldPath) { + if (Object.keys(settings.overridePath).length === 0) { + return { settingPath: "", setting: settings.attachPath }; + } + const { settingPath: np, setting: ns } = getOverrideSetting(settings, file); + const { settingPath: op, setting: os } = getOverrideSetting(settings, file, oldPath); + if (ns.type === "GLOBAL" /* GLOBAL */) { + return { settingPath: op, setting: os }; + } + if (os.type === "GLOBAL" /* GLOBAL */) { + return { settingPath: np, setting: ns }; + } + if (ns.type === "FILE" /* FILE */ && os.type === "FILE" /* FILE */) { + debugLog("getRenameOverrideSetting - both file type setting", np, op); + return { settingPath: "", setting: settings.attachPath }; + } + if (ns.type === "FILE" /* FILE */ && os.type === "FOLDER" /* FOLDER */) { + return { settingPath: np, setting: ns }; + } else if (ns.type === "FOLDER" /* FOLDER */ && os.type === "FILE" /* FILE */) { + return { settingPath: op, setting: os }; + } + if (ns.type === "FOLDER" /* FOLDER */ && os.type === "FOLDER" /* FOLDER */) { + const l = np.split("/").length; + const r = op.split("/").length; + if (l > r) { + return { settingPath: np, setting: ns }; + } else if (l < r) { + return { settingPath: op, setting: os }; + } else if (l === r) { + return { settingPath: "", setting: os }; + } + } + return { settingPath: "", setting: settings.attachPath }; +} +function updateOverrideSetting(settings, file, oldPath) { + const keys = Object.keys(settings.overridePath); + if (keys.length === 0 || file.path === oldPath) { + return; + } + const { settingPath, setting } = getOverrideSetting(settings, file, oldPath); + const copySetting = Object.assign({}, setting); + if (file.path === settingPath) { + return; + } + if (oldPath === settingPath) { + settings.overridePath[file.path] = copySetting; + delete settings.overridePath[settingPath]; + return; + } else { + const { stripedSrc, stripedDst } = stripPaths(oldPath, file.path); + if (stripedSrc === settingPath) { + settings.overridePath[stripedDst] = copySetting; + delete settings.overridePath[settingPath]; + return; + } + } +} +function deleteOverrideSetting(settings, file) { + const keys = Object.keys(settings.overridePath); + for (const key of keys) { + if (file.path === key) { + delete settings.overridePath[key]; + return true; + } + } + return false; +} + +// src/lib/linkDetector.ts +var getAllLinkMatchesInFile = async (mdFile, app2, fileText) => { + const linkMatches = []; + if (fileText === void 0) { + fileText = await app2.vault.read(mdFile); + } + const wikiRegex = /\[\[.*?\]\]/g; + const wikiMatches = fileText.match(wikiRegex); + if (wikiMatches) { + const fileRegex = /(?<=\[\[).*?(?=(\]|\|))/; + for (const wikiMatch of wikiMatches) { + if (matchIsWikiTransclusion(wikiMatch)) { + const fileName = getTransclusionFileName(wikiMatch); + const file = app2.metadataCache.getFirstLinkpathDest(fileName, mdFile.path); + if (fileName !== "") { + const linkMatch = { + type: "wikiTransclusion", + match: wikiMatch, + linkText: file ? file.path : fileName, + sourceFilePath: mdFile.path + }; + linkMatches.push(linkMatch); + continue; + } + } + const fileMatch = wikiMatch.match(fileRegex); + if (fileMatch) { + if (fileMatch[0].startsWith("http")) + continue; + const file = app2.metadataCache.getFirstLinkpathDest(fileMatch[0], mdFile.path); + const linkMatch = { + type: "wiki", + match: wikiMatch, + linkText: file ? file.path : fileMatch[0], + sourceFilePath: mdFile.path + }; + linkMatches.push(linkMatch); + } + } + } + const markdownRegex = /\[(^$|.*?)\]\((.*?)\)/g; + const markdownMatches = fileText.match(markdownRegex); + if (markdownMatches) { + const fileRegex = /(?<=\().*(?=\))/; + for (const markdownMatch of markdownMatches) { + if (matchIsMdTransclusion(markdownMatch)) { + const fileName = getTransclusionFileName(markdownMatch); + const file = app2.metadataCache.getFirstLinkpathDest(fileName, mdFile.path); + if (fileName !== "") { + const linkMatch = { + type: "mdTransclusion", + match: markdownMatch, + linkText: file ? file.path : fileName, + sourceFilePath: mdFile.path + }; + linkMatches.push(linkMatch); + continue; + } + } + const fileMatch = markdownMatch.match(fileRegex); + if (fileMatch) { + if (fileMatch[0].startsWith("http")) + continue; + const file = app2.metadataCache.getFirstLinkpathDest(fileMatch[0], mdFile.path); + const linkMatch = { + type: "markdown", + match: markdownMatch, + linkText: file ? file.path : fileMatch[0], + sourceFilePath: mdFile.path + }; + linkMatches.push(linkMatch); + } + } + } + return linkMatches; +}; +var wikiTransclusionRegex = /\[\[(.*?)#.*?\]\]/; +var wikiTransclusionFileNameRegex = /(?<=\[\[)(.*)(?=#)/; +var mdTransclusionRegex = /\[.*?]\((.*?)#.*?\)/; +var mdTransclusionFileNameRegex = /(?<=\]\()(.*)(?=#)/; +var matchIsWikiTransclusion = (match) => { + return wikiTransclusionRegex.test(match); +}; +var matchIsMdTransclusion = (match) => { + return mdTransclusionRegex.test(match); +}; +var getTransclusionFileName = (match) => { + const isWiki = wikiTransclusionRegex.test(match); + const isMd = mdTransclusionRegex.test(match); + if (isWiki || isMd) { + const fileNameMatch = match.match(isWiki ? wikiTransclusionFileNameRegex : mdTransclusionFileNameRegex); + if (fileNameMatch) + return fileNameMatch[0]; + } + return ""; +}; + +// src/lib/deduplicate.ts +function escapeRegExp(s) { + return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); +} +async function deduplicateNewName(newName, file) { + const dir = file.path; + const listed = await this.app.vault.adapter.list(dir); + debugLog("deduplicateNewName - sibling files", listed); + const newNameExt = path.extname(newName), newNameStem = newName.slice(0, newName.length - newNameExt.length - 1), newNameStemEscaped = escapeRegExp(newNameStem), delimiter = "-", delimiterEscaped = escapeRegExp(delimiter); + const dupNameRegex = new RegExp( + `^(?${newNameStemEscaped})${delimiterEscaped}(?\\d{1,3})\\.${newNameExt}$` + ); + debugLog("dupNameRegex", dupNameRegex); + const dupNameNumbers = []; + let isNewNameExist = false; + for (let sibling of listed.files) { + sibling = path.basename(sibling); + if (sibling == newName) { + isNewNameExist = true; + continue; + } + const m = dupNameRegex.exec(sibling); + if (!m || m.groups === void 0) + continue; + dupNameNumbers.push(parseInt(m.groups.number)); + } + if (isNewNameExist) { + const newNumber = dupNameNumbers.length > 0 ? Math.max(...dupNameNumbers) + 1 : 1; + newName = `${newNameStem}${delimiter}${newNumber}.${newNameExt}`; + } + return { + name: newName, + basename: newName.slice(0, newName.length - newNameExt.length - 1), + extension: newNameExt + }; +} + +// src/settings/metadata.ts +var import_obsidian7 = require("obsidian"); + +// src/commons.ts +var import_obsidian6 = require("obsidian"); +function getActiveFile(app2) { + const view = getActiveView(app2); + if (view == null) { + return void 0; + } else if (view.file == null) { + return void 0; + } else { + return view.file; + } +} +function getActiveView(app2) { + return app2.workspace.getActiveViewOfType(import_obsidian6.TextFileView); +} +function getRootPath(notePath, setting) { + let root; + const obsmediadir = app.vault.getConfig("attachmentFolderPath"); + switch (setting.saveAttE) { + case `${SETTINGS_ROOT_INFOLDER}`: + root = path.join(setting.attachmentRoot); + break; + case `${SETTINGS_ROOT_NEXTTONOTE}`: + root = path.join(notePath, setting.attachmentRoot.replace("./", "")); + break; + default: + if (obsmediadir === "/") { + root = obsmediadir; + } else if (obsmediadir === "./") { + root = path.join(notePath); + } else if (obsmediadir.match(/\.\/.+/g) !== null) { + root = path.join(notePath, obsmediadir.replace("./", "")); + } else { + root = obsmediadir; + } + } + return root === "/" ? root : (0, import_obsidian6.normalizePath)(root); +} +async function checkEmptyFolder(adapter, path2) { + const exist = await adapter.exists(path2, true); + if (!exist) { + return true; + } + const data = await adapter.list(path2); + if (data.files.length > 0) { + return false; + } + if (data.folders.length > 0) { + for (let i = 0; i < data.folders.length; i++) { + return checkEmptyFolder(adapter, data.folders[i]); + } + } + return true; +} + +// src/settings/metadata.ts +var Metadata = class { + constructor(path2, name, basename, extension, parentPath, parentName, attachmentFile) { + /** parent path of file */ + this.parentPath = ""; + /** parent path basename of file */ + this.parentName = ""; + this.path = path2; + this.name = name; + this.basename = basename; + this.extension = extension; + this.parentPath = parentPath; + this.parentName = parentName; + this.attachmentFile = attachmentFile; + } + /** + * Returns a formatted attachment file name according to the provided settings. + * + * @param {AttachmentPathSettings} setting - attachment path settings object + * @param {string} dateFormat - format string for date and time + * @param {string} originalName - name of the original attachment + * @param {string} [linkName] - optional name for the attachment link + * @return {string} the formatted attachment file name + */ + async getAttachFileName(setting, dateFormat, originalName, adapter, linkName) { + const dateTime = window.moment().format(dateFormat); + let md5 = ""; + let attachFormat = ""; + if (this.attachmentFile !== void 0) { + md5 = await md5sum(adapter, this.attachmentFile); + const { extSetting } = getExtensionOverrideSetting(this.attachmentFile.extension, setting); + if (extSetting !== void 0) { + attachFormat = extSetting.attachFormat; + } else { + attachFormat = setting.attachFormat; + } + } + if (attachFormat.includes(SETTINGS_VARIABLES_ORIGINALNAME)) { + if (originalName === "" && linkName != void 0) { + return linkName; + } else { + return attachFormat.replace(`${SETTINGS_VARIABLES_DATES}`, dateTime).replace(`${SETTINGS_VARIABLES_NOTENAME}`, this.basename).replace(`${SETTINGS_VARIABLES_ORIGINALNAME}`, originalName).replace(`${SETTINGS_VARIABLES_MD5}`, md5); + } + } + return attachFormat.replace(`${SETTINGS_VARIABLES_DATES}`, dateTime).replace(`${SETTINGS_VARIABLES_NOTENAME}`, this.basename).replace(`${SETTINGS_VARIABLES_MD5}`, md5); + } + /** + * Returns the attachment path based on the given AttachmentPathSettings object. + * + * @param {AttachmentPathSettings} setting - An object containing the attachment path settings. + * @return {string} The normalized attachment path. + */ + getAttachmentPath(setting, dateFormat) { + const dateTime = window.moment().format(dateFormat); + let root = ""; + let attachPath = ""; + if (this.attachmentFile !== void 0) { + const { extSetting } = getExtensionOverrideSetting(this.attachmentFile.extension, setting); + if (extSetting !== void 0) { + root = getRootPath(this.parentPath, extSetting); + attachPath = path.join( + root, + extSetting.attachmentPath.replace(`${SETTINGS_VARIABLES_NOTEPATH}`, this.parentPath).replace(`${SETTINGS_VARIABLES_NOTENAME}`, this.basename).replace(`${SETTINGS_VARIABLES_NOTEPARENT}`, this.parentName).replace(`${SETTINGS_VARIABLES_DATES}`, dateTime) + ); + return (0, import_obsidian7.normalizePath)(attachPath); + } + } + root = getRootPath(this.parentPath, setting); + debugLog("getAttachmentPath - root", root); + attachPath = path.join( + root, + setting.attachmentPath.replace(`${SETTINGS_VARIABLES_NOTEPATH}`, this.parentPath).replace(`${SETTINGS_VARIABLES_NOTENAME}`, this.basename).replace(`${SETTINGS_VARIABLES_NOTEPARENT}`, this.parentName).replace(`${SETTINGS_VARIABLES_DATES}`, dateTime) + ); + return (0, import_obsidian7.normalizePath)(attachPath); + } +}; +function getMetadata(file, attach) { + const parentPath = path.dirname(file); + const parentName = path.basename(parentPath); + const name = path.basename(file); + const extension = path.extname(file); + const basename = path.basename(file, extension); + return new Metadata(file, name, basename, extension, parentPath, parentName, attach); +} + +// src/exclude.ts +function isExcluded(path2, settings) { + debugLog("excludePathsArray: ", settings.excludePathsArray); + for (const excludedPath of settings.excludePathsArray) { + if (excludedPath.length === 0) { + continue; + } + if (settings.excludeSubpaths && path2.startsWith(excludedPath)) { + debugLog("isExcluded: ", path2); + return true; + } else { + if (path2 === excludedPath) { + return true; + } + } + } + return false; +} + +// src/lib/originalStorage.ts +function containOriginalNameVariable(setting, ext) { + const { extSetting } = getExtensionOverrideSetting(ext, setting); + if (extSetting !== void 0 && extSetting.attachFormat.contains(SETTINGS_VARIABLES_ORIGINALNAME) || setting.attachFormat.contains(SETTINGS_VARIABLES_ORIGINALNAME)) { + return true; + } + return false; +} +function saveOriginalName(settings, setting, ext, data) { + if (settings.originalNameStorage === void 0) { + settings.originalNameStorage = []; + } + if (containOriginalNameVariable(setting, ext)) { + settings.originalNameStorage.filter((n) => n.md5 == data.md5).forEach((n) => settings.originalNameStorage.remove(n)); + settings.originalNameStorage.push(data); + } +} +function loadOriginalName(settings, setting, ext, md5) { + if (containOriginalNameVariable(setting, ext)) { + const first = settings.originalNameStorage.find((data) => data.md5 === md5); + const last = settings.originalNameStorage.reverse().find((data) => data.md5 === md5); + if (first === void 0 || last == void 0) { + return void 0; + } + if (first.md5 === last.md5 && first.n === last.n) { + return last; + } else if (first.md5 === last.md5 && first.n !== last.n) { + settings.originalNameStorage.remove(first); + return last; + } + } + return void 0; +} + +// src/arrange.ts +var bannerRegex = /!\[\[(.*?)\]\]/i; +var ArrangeHandler = class { + constructor(settings, app2, plugin) { + this.settings = settings; + this.app = app2; + this.plugin = plugin; + } + /** + * Rearranges attachments that are linked by markdown or canvas. + * Only rearranges attachments if autoRenameAttachment is enabled in settings. + * + * @param {RearrangeType} type - The type of attachments to rearrange. + * @param {TFile} file - The file to which the attachments are linked (optional), if the type was "file", thi should be provided. + * @param {string} oldPath - The old path of the file (optional), used for rename event. + */ + async rearrangeAttachment(type, file, oldPath) { + var _a; + if (!this.settings.autoRenameAttachment) { + debugLog("rearrangeAttachment - autoRenameAttachment not enable"); + return; + } + const attachments = await this.getAttachmentsInVault(this.settings, type, file, oldPath); + debugLog("rearrangeAttachment - attachments:", Object.keys(attachments).length, Object.entries(attachments)); + for (const obNote of Object.keys(attachments)) { + const innerFile = this.app.vault.getAbstractFileByPath(obNote); + if (!(innerFile instanceof import_obsidian8.TFile) || isAttachment(this.settings, innerFile)) { + debugLog(`rearrangeAttachment - ${obNote} not exists or is attachment, skipped`); + continue; + } + const { setting } = getOverrideSetting(this.settings, innerFile); + if (attachments[obNote].size == 0) { + continue; + } + const md = getMetadata(obNote); + const attachPath = md.getAttachmentPath(setting, this.settings.dateFormat); + if (!await this.app.vault.adapter.exists(attachPath, true)) { + if (oldPath != void 0 && await this.app.vault.adapter.exists(attachPath, false)) { + const mdOld = getMetadata(oldPath); + const attachPathOld = mdOld.getAttachmentPath(setting, this.settings.dateFormat); + this.app.vault.adapter.rename(attachPathOld, attachPath); + } else { + await this.app.vault.adapter.mkdir(attachPath); + } + } + for (let link of attachments[obNote]) { + try { + link = decodeURI(link); + } catch (err) { + console.log(`Invalid link: ${link}, err: ${err}`); + continue; + } + debugLog(`rearrangeAttachment - article: ${obNote} links: ${link}`); + const linkFile = this.app.vault.getAbstractFileByPath(link); + if (linkFile === null || !(linkFile instanceof import_obsidian8.TFile)) { + debugLog(`${link} not exists, skipped`); + continue; + } + const metadata = getMetadata(obNote, linkFile); + const md5 = await md5sum(this.app.vault.adapter, linkFile); + const originalName = loadOriginalName(this.settings, setting, linkFile.extension, md5); + debugLog("rearrangeAttachment - original name:", originalName); + let attachName = ""; + if (containOriginalNameVariable(setting, linkFile.extension)) { + attachName = await metadata.getAttachFileName( + setting, + this.settings.dateFormat, + (_a = originalName == null ? void 0 : originalName.n) != null ? _a : "", + this.app.vault.adapter, + path.basename(link, path.extname(link)) + ); + } else { + attachName = await metadata.getAttachFileName( + setting, + this.settings.dateFormat, + path.basename(link, path.extname(link)), + this.app.vault.adapter + ); + } + if (attachPath == path.dirname(link) && attachName === path.basename(link, path.extname(link))) { + continue; + } + const attachPathFile = this.app.vault.getAbstractFileByPath(attachPath); + if (attachPathFile === null || !(attachPathFile instanceof import_obsidian8.TFolder)) { + debugLog(`${attachPath} not exists, skipped`); + continue; + } + const { name } = await deduplicateNewName(attachName + "." + path.extname(link), attachPathFile); + debugLog("rearrangeAttachment - deduplicated name:", name); + await this.app.fileManager.renameFile(linkFile, path.join(attachPath, name)); + } + } + } + /** + * Retrieves the attachments in the vault based on the specified settings and type. + * If a file is provided, only attachments related to that file will be returned. + * + * @param {AttachmentManagementPluginSettings} settings - The settings for the attachment management plugin. + * @param {RearrangeType} type - The type of attachments to retrieve. + * @param {TFile} [file] - The file to filter attachments by. Optional. + * @return {Promise>>} - A promise that resolves to a record of attachments, where each key is a file name and each value is a set of associated attachment names. + */ + async getAttachmentsInVault(settings, type, file, oldPath) { + let attachmentsRecord = {}; + attachmentsRecord = await this.getAttachmentsInVaultByLinks(settings, type, file, oldPath); + return attachmentsRecord; + } + /** + * Modified from https://github.com/ozntel/oz-clear-unused-images-obsidian/blob/master/src/util.ts#LL48C21-L48C21 + * Retrieves a record of attachments in the vault based on the given settings and type. + * + * @param {AttachmentManagementPluginSettings} settings - The settings for the attachment management plugin. + * @param {RearrangeType} type - The type of attachments to retrieve. + * @param {TFile} file - The file to retrieve attachments for (optional). + * @return {Promise>>} - A promise that resolves to a record of attachments. + */ + async getAttachmentsInVaultByLinks(settings, type, file, oldPath) { + const attachmentsRecord = {}; + let resolvedLinks = {}; + let allFiles = []; + if (type == 1 /* LINKS */) { + resolvedLinks = this.app.metadataCache.resolvedLinks; + allFiles = this.app.vault.getFiles(); + } else if (type == 0 /* ACTIVE */) { + const file2 = getActiveFile(this.app); + if (file2) { + if (file2.parent && isExcluded(file2.parent.path, this.settings) || isAttachment(this.settings, file2)) { + allFiles = []; + new import_obsidian8.Notice(`${file2.path} was excluded, skipped`); + } else { + debugLog("getAttachmentsInVaultByLinks - active:", file2.path); + allFiles = [file2]; + if (this.app.metadataCache.resolvedLinks[file2.path]) { + resolvedLinks[file2.path] = this.app.metadataCache.resolvedLinks[file2.path]; + } + debugLog("getAttachmentsInVaultByLinks - resolvedLinks:", resolvedLinks); + } + } + } else if (type == 2 /* FILE */ && file != void 0) { + if (file.parent && isExcluded(file.parent.path, this.settings) || isAttachment(this.settings, file)) { + allFiles = []; + new import_obsidian8.Notice(`${file.path} was excluded, skipped`); + } else { + debugLog("getAttachmentsInVaultByLinks - file:", file.path); + allFiles = [file]; + const rlinks = this.app.metadataCache.resolvedLinks[file.path]; + if (rlinks) { + debugLog("getAttachmentsInVaultByLinks - rlinks:", rlinks); + resolvedLinks[file.path] = rlinks; + } else if (oldPath) { + debugLog("getAttachmentsInVaultByLinks - oldPath:", oldPath); + resolvedLinks[file.path] = this.app.metadataCache.resolvedLinks[oldPath]; + } + debugLog("getAttachmentsInVaultByLinks - resolvedLinks:", resolvedLinks); + } + } + debugLog("getAttachmentsInVaultByLinks - allFiles:", allFiles.length, allFiles); + if (resolvedLinks) { + for (const [mdFile, links] of Object.entries(resolvedLinks)) { + const attachmentsSet = /* @__PURE__ */ new Set(); + if (links) { + for (const [filePath] of Object.entries(links)) { + if (isAttachment(settings, filePath)) { + this.addToSet(attachmentsSet, filePath); + } + } + this.addToRecord(attachmentsRecord, mdFile, attachmentsSet); + } + } + } + for (let i = 0; i < allFiles.length; i++) { + const obsFile = allFiles[i]; + const attachmentsSet = /* @__PURE__ */ new Set(); + if (obsFile.parent && isExcluded(obsFile.parent.path, this.settings)) { + continue; + } + if (isMarkdownFile(obsFile.extension)) { + const fileCache = this.app.metadataCache.getFileCache(obsFile); + if (fileCache === null) { + continue; + } + if (fileCache.frontmatter) { + const frontmatter = fileCache.frontmatter; + for (const k of Object.keys(frontmatter)) { + if (typeof frontmatter[k] === "string") { + const formatMatch = frontmatter[k].match(bannerRegex); + if (formatMatch && formatMatch[1]) { + const fileName = formatMatch[1]; + const file2 = this.app.metadataCache.getFirstLinkpathDest(fileName, obsFile.path); + if (file2 && isAttachment(settings, file2.path)) { + this.addToSet(attachmentsSet, file2.path); + } + } + } + } + } + const linkMatches = await getAllLinkMatchesInFile(obsFile, app); + for (const linkMatch of linkMatches) { + if (isAttachment(settings, linkMatch.linkText)) { + this.addToSet(attachmentsSet, linkMatch.linkText); + } + } + } else if (isCanvasFile(obsFile.extension)) { + const fileRead = await this.app.vault.cachedRead(obsFile); + if (!fileRead || fileRead.length === 0) { + continue; + } + let canvasData; + try { + canvasData = JSON.parse(fileRead); + } catch (e) { + debugLog("getAttachmentsInVaultByLinks - parse canvas data error", e); + continue; + } + if (canvasData.nodes && canvasData.nodes.length > 0) { + for (const node of canvasData.nodes) { + if (node.type === "file") { + if (isAttachment(settings, node.file)) { + this.addToSet(attachmentsSet, node.file); + } + } else if (node.type == "text") { + const linkMatches = await getAllLinkMatchesInFile(obsFile, app, node.text); + for (const linkMatch of linkMatches) { + if (isAttachment(settings, linkMatch.linkText)) { + this.addToSet(attachmentsSet, linkMatch.linkText); + } + } + } + } + } + } + this.addToRecord(attachmentsRecord, obsFile.path, attachmentsSet); + } + return attachmentsRecord; + } + addToRecord(record, key, value) { + if (record[key] === void 0) { + record[key] = value; + return; + } + const valueSet = record[key]; + for (const val of value) { + this.addToSet(valueSet, val); + } + record[key] = valueSet; + } + addToSet(setObj, value) { + if (!setObj.has(value)) { + setObj.add(value); + } + } + needToRename(settings, attachPath, attachName, noteName, link) { + const linkPath = path.dirname(link); + const linkName = path.basename(link, path.extname(link)); + if (linkName.length !== attachName.length) { + return true; + } + if (attachPath !== linkPath) { + return true; + } else { + if (settings.attachFormat.includes(SETTINGS_VARIABLES_NOTENAME) && !linkName.includes(noteName)) { + return true; + } + const noNoteNameAttachFormat = settings.attachFormat.split(SETTINGS_VARIABLES_NOTENAME); + if (settings.attachFormat.includes(SETTINGS_VARIABLES_DATES)) { + for (const formatPart in noNoteNameAttachFormat) { + const splited = formatPart.split(SETTINGS_VARIABLES_DATES); + for (const part in splited) { + if (!linkName.includes(part)) { + return true; + } + } + } + } + } + return false; + } +}; + +// src/model/confirm.ts +var ConfirmModal = class extends import_obsidian9.Modal { + constructor(plugin) { + super(plugin.app); + this.plugin = plugin; + } + onOpen() { + const { contentEl } = this; + contentEl.empty(); + contentEl.createEl("h3", { + text: "Tips" + }); + contentEl.createSpan("", (el) => { + el.innerText = "This operation is irreversible and experimental. Please backup your vault first!"; + }); + new import_obsidian9.Setting(contentEl).addButton((btn) => { + btn.setButtonText("Cancel").setCta().onClick(() => { + this.close(); + }); + }).addButton( + (btn) => btn.setButtonText("Continue").onClick(async () => { + new ArrangeHandler(this.plugin.settings, this.plugin.app, this.plugin).rearrangeAttachment(1 /* LINKS */).finally(() => { + new import_obsidian9.Notice("Arrange completed"); + this.close(); + }); + }) + ); + } + onClose() { + const { contentEl } = this; + contentEl.empty(); + } +}; + +// src/create.ts +var import_obsidian10 = require("obsidian"); +var CreateHandler = class { + constructor(plugin, settings) { + this.plugin = plugin; + this.app = this.plugin.app; + this.settings = settings; + } + /** + * Post-processing of created attachment file (for paste and drop event). + * @param attach - the attachment file to process + * @param source - the notes file that linked to attach + * @returns - none + */ + processAttach(attach, source) { + if (source.parent && isExcluded(source.parent.path, this.settings)) { + debugLog("processAttach - not a file or exclude path:", source.path); + new import_obsidian10.Notice(`${source.path} was excluded, skipped`); + return; + } + const { setting } = getOverrideSetting(this.settings, source); + const { extSetting } = getExtensionOverrideSetting(attach.extension, setting); + debugLog("processAttach - file.extension:", attach.extension); + if (extSetting === void 0 && !isImage(attach.extension) && !isPastedImage(attach)) { + debugLog("renameFiles - no handle extension:", attach.extension); + return; + } + const metadata = getMetadata(source.path, attach); + debugLog("processAttach - metadata:", metadata); + const attachPath = metadata.getAttachmentPath(setting, this.settings.dateFormat); + metadata.getAttachFileName(setting, this.settings.dateFormat, attach.basename, this.app.vault.adapter).then((attachName) => { + attachName = attachName + "." + attach.extension; + this.app.vault.adapter.exists(attachPath, true).then(async (exists) => { + if (!exists) { + await this.app.vault.adapter.mkdir(attachPath); + debugLog("processAttach - create path:", attachPath); + } + }).finally(() => { + const attachPathFolder = this.app.vault.getAbstractFileByPath(attachPath); + deduplicateNewName(attachName, attachPathFolder).then(({ name }) => { + debugLog("processAttach - new path of file:", path.join(attachPath, name)); + this.renameCreateFile(attach, attachPath, name, source); + }); + }); + }); + } + /** + * Rename the file specified by `@param file`, and update the link of the file if specified updateLink + * @param attach - file to rename + * @param attachPath - where to the renamed file will be move to + * @param attachName - name of the renamed file + * @param source - associated active file + * @returns - none + */ + renameCreateFile(attach, attachPath, attachName, source) { + const dst = (0, import_obsidian10.normalizePath)(path.join(attachPath, attachName)); + debugLog("renameFile - ", attach.path, " to ", dst); + const original = attach.basename; + const name = attach.name; + this.app.fileManager.renameFile(attach, dst).then(() => { + new import_obsidian10.Notice(`Renamed ${name} to ${attachName}.`); + }).finally(() => { + const { setting } = getOverrideSetting(this.settings, source); + md5sum(this.app.vault.adapter, attach).then((md5) => { + saveOriginalName(this.settings, setting, attach.extension, { + n: original, + md5 + }); + this.plugin.saveData(this.settings); + }); + }); + } +}; + +// src/main.ts +var AttachmentManagementPlugin = class extends import_obsidian11.Plugin { + constructor() { + super(...arguments); + this.createdQueue = []; + } + async onload() { + await this.loadSettings(); + console.log(`Plugin loading: ${this.manifest.name} v.${this.manifest.version}`); + this.app.workspace.onLayoutReady(() => { + this.initCommands(); + this.registerEvent( + this.app.workspace.on("file-menu", async (menu, file) => { + if (file.parent && isExcluded(file.parent.path, this.settings) || isAttachment(this.settings, file)) { + return; + } + menu.addItem((item) => { + item.setTitle("Overriding attachment setting").setIcon("image-plus").onClick(async () => { + const { setting } = getOverrideSetting(this.settings, file); + const fileSetting = Object.assign({}, setting); + this.overrideConfiguration(file, fileSetting); + }); + }); + }) + ); + this.registerEvent( + this.app.vault.on("create", async (file) => { + debugLog("on create event - file:", file.path); + if (!(file instanceof import_obsidian11.TFile)) { + return; + } + const curentTime = new Date().getTime(); + const timeGapMs = curentTime - file.stat.mtime; + const timeGapCs = curentTime - file.stat.ctime; + if (timeGapMs > 1e3 || timeGapCs > 1e3 || isMarkdownFile(file.extension) || isCanvasFile(file.extension)) { + return; + } + if (matchExtension(file.extension, this.settings.excludeExtensionPattern)) { + debugLog("create - excluded file by extension", file); + return; + } + this.createdQueue.push(file); + }) + ); + this.registerEvent( + this.app.vault.on("modify", (file) => { + debugLog("on modify event - create queue:", this.createdQueue); + if (this.createdQueue.length < 1 || !(file instanceof import_obsidian11.TFile)) { + return; + } + debugLog("on modify event - file:", file.path); + this.app.vault.adapter.process(file.path, (pdata) => { + const f = this.createdQueue.first(); + if (f != void 0) { + this.app.vault.adapter.exists(f.path, true).then((exist) => { + if (exist) { + const processor = new CreateHandler(this, this.settings); + const link = this.app.fileManager.generateMarkdownLink(f, file.path); + if (file.extension == "md" && pdata.indexOf(link) != -1 || file.extension == "canvas" && pdata.indexOf(f.path) != -1) { + this.createdQueue.remove(f); + processor.processAttach(f, file); + } + } else { + debugLog("on modify event - file does not exist:", f.path); + this.createdQueue.remove(f); + } + }); + } + return pdata; + }); + }) + ); + this.registerEvent( + // when trigger a rename event on folder, for each file/folder in this renamed folder (include itself) will trigger this event + this.app.vault.on("rename", async (file, oldPath) => { + debugLog("on rename event - new path and old path:", file.path, oldPath); + const { setting } = getRenameOverrideSetting(this.settings, file, oldPath); + debugLog("rename - using settings:", setting); + if (setting.type === "FOLDER" /* FOLDER */ || setting.type === "FILE" /* FILE */) { + updateOverrideSetting(this.settings, file, oldPath); + this.saveSettings(); + } + debugLog("rename - updated settings:", setting); + if (!this.settings.autoRenameAttachment) { + debugLog("rename - auto rename not enabled:", this.settings.autoRenameAttachment); + return; + } + if (file instanceof import_obsidian11.TFile) { + if (file.parent && isExcluded(file.parent.path, this.settings)) { + debugLog("rename - exclude path:", file.parent.path); + new import_obsidian11.Notice(`${file.path} was excluded`); + return; + } + if (isAttachment(this.settings, file)) { + debugLog("rename - not processing rename on attachment:", file.path); + return; + } + await new ArrangeHandler(this.settings, this.app, this).rearrangeAttachment( + 2 /* FILE */, + file, + oldPath + ); + const oldMetadata = getMetadata(oldPath); + const oldAttachPath = oldMetadata.getAttachmentPath(setting, this.settings.dateFormat); + this.app.vault.adapter.exists(oldAttachPath, true).then((exists) => { + if (exists) { + checkEmptyFolder(this.app.vault.adapter, oldAttachPath).then((empty) => { + if (empty) { + this.app.vault.adapter.rmdir(oldAttachPath, true); + } + }); + } + }); + } else if (file instanceof import_obsidian11.TFolder) { + return; + } + }) + ); + this.registerEvent( + this.app.vault.on("delete", async (file) => { + debugLog("on delete event - file path:", file.path); + if (file.parent && isExcluded(file.parent.path, this.settings) || isAttachment(this.settings, file)) { + debugLog("delete - exclude path or the file is an attachment:", file.path); + return; + } + if (deleteOverrideSetting(this.settings, file)) { + await this.saveSettings(); + new import_obsidian11.Notice("Removed override setting of " + file.path); + } + if (file instanceof import_obsidian11.TFile) { + const oldMetadata = getMetadata(file.path); + const { setting } = getOverrideSetting(this.settings, file); + const oldAttachPath = oldMetadata.getAttachmentPath(setting, this.settings.dateFormat); + this.app.vault.adapter.exists(oldAttachPath, true).then((exists) => { + if (exists) { + checkEmptyFolder(this.app.vault.adapter, oldAttachPath).then((empty) => { + if (empty) { + this.app.vault.adapter.rmdir(oldAttachPath, true); + } + }); + } + }); + } + }) + ); + this.addSettingTab(new SettingTab(this.app, this)); + }); + } + async overrideConfiguration(file, setting) { + new OverrideModal(this, file, setting).open(); + } + /** + * Initializes and registers the plugin's commands + * This method is responsible for setting up the user interface by adding various commands. + * These commands include settings overrides, resetting settings, clearing unused original name storage, + * and rearranging attachments. + * + * Note: The actual implementation of each command is not included in this method and needs to be + * defined separately asynchronously. + * + * Warning: Make sure you have checked for errors while implementing the functionality of each command. + */ + initCommands() { + this.addCommand({ + id: "attachment-management-rearrange-all-links", + name: "Rearrange all linked attachments", + callback: async () => { + new ConfirmModal(this).open(); + } + }); + this.addCommand({ + id: "attachment-management-rearrange-active-links", + name: "Rearrange linked attachments", + callback: async () => { + new ArrangeHandler(this.settings, this.app, this).rearrangeAttachment(0 /* ACTIVE */).finally(() => { + new import_obsidian11.Notice("Arrange completed"); + }); + } + }); + this.addCommand({ + id: "attachment-management-override-setting", + name: "Overriding setting", + checkCallback: (checking) => { + const file = getActiveFile(this.app); + if (file) { + if (isAttachment(this.settings, file)) { + return true; + } + if (!checking) { + if (file.parent && isExcluded(file.parent.path, this.settings)) { + new import_obsidian11.Notice(`${file.path} was excluded`); + return true; + } + const { setting } = getOverrideSetting(this.settings, file); + const fileSetting = Object.assign({}, setting); + this.overrideConfiguration(file, fileSetting); + } + return true; + } + return false; + } + }); + this.addCommand({ + id: "attachment-management-reset-override-setting", + name: "Reset override setting", + checkCallback: (checking) => { + const file = getActiveFile(this.app); + if (file) { + if (isAttachment(this.settings, file)) { + return true; + } + if (!checking) { + if (file.parent && isExcluded(file.parent.path, this.settings)) { + new import_obsidian11.Notice(`${file.path} was excluded`); + return true; + } + delete this.settings.overridePath[file.path]; + this.saveSettings().finally(() => { + new import_obsidian11.Notice(`Reset attachment setting of ${file.path}`); + }); + } + return true; + } + return false; + } + }); + this.addCommand({ + id: "attachment-management-clear-unused-originalname-storage", + name: "Clear unused original name storage", + callback: async () => { + const attachments = await new ArrangeHandler(this.settings, this.app, this).getAttachmentsInVault( + this.settings, + 1 /* LINKS */ + ); + const storages = []; + for (const attachs of Object.values(attachments)) { + for (const attach of attachs) { + const link = decodeURI(attach); + const linkFile = this.app.vault.getAbstractFileByPath(link); + if (linkFile !== null && linkFile instanceof import_obsidian11.TFile) { + md5sum(this.app.vault.adapter, linkFile).then((md5) => { + const ret = this.settings.originalNameStorage.find((data) => data.md5 === md5); + if (ret) { + storages.filter((n) => n.md5 == md5).forEach((n) => storages.remove(n)); + storages.push(ret); + } + }); + } + } + } + debugLog("clearUnusedOriginalNameStorage - storage:", storages); + this.settings.originalNameStorage = storages; + this.saveSettings(); + } + }); + } + async loadSettings() { + this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData()); + } + async saveSettings() { + await this.saveData(this.settings); + } + async onunload() { + console.log("unloading attachment management."); + this.createdQueue = []; + } +}; + +/* nosourcemap */ \ No newline at end of file diff --git a/.obsidian/plugins/attachment-management/manifest.json b/.obsidian/plugins/attachment-management/manifest.json new file mode 100644 index 0000000..cae6cf0 --- /dev/null +++ b/.obsidian/plugins/attachment-management/manifest.json @@ -0,0 +1,10 @@ +{ + "id": "attachment-management", + "name": "Attachment Management", + "version": "0.9.16", + "description": "Customize your attachment path of notes independently with variables and auto rename it on change.", + "author": "trganda", + "authorUrl": "https://github.com/trganda", + "fundingUrl": "https://paypal.me/trganda", + "isDesktopOnly": false +} diff --git a/.obsidian/plugins/attachment-management/styles.css b/.obsidian/plugins/attachment-management/styles.css new file mode 100644 index 0000000..e30a878 --- /dev/null +++ b/.obsidian/plugins/attachment-management/styles.css @@ -0,0 +1,15 @@ +/* + +This CSS file will be included with your plugin, and +available in the app when your plugin is enabled. + +If your plugin does not need CSS, delete this file. + +*/ +.attach_management_sub_setting { + padding-left: 2em; +} +.attach_management_sub_setting + .attach_management_sub_setting { + padding-left: 0; + margin-left: 2em; +} diff --git a/.obsidian/plugins/copy-as-html/main.js b/.obsidian/plugins/copy-as-html/main.js new file mode 100644 index 0000000..4c1c48f --- /dev/null +++ b/.obsidian/plugins/copy-as-html/main.js @@ -0,0 +1,3747 @@ +/* +THIS IS A GENERATED/BUNDLED FILE BY ESBUILD +if you want to view the source, please visit the github repository of this plugin +*/ + +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __markAsModule = (target) => __defProp(target, "__esModule", { value: true }); +var __commonJS = (cb, mod) => function __require() { + return mod || (0, cb[Object.keys(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; +}; +var __export = (target, all) => { + __markAsModule(target); + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __reExport = (target, module2, desc) => { + if (module2 && typeof module2 === "object" || typeof module2 === "function") { + for (let key of __getOwnPropNames(module2)) + if (!__hasOwnProp.call(target, key) && key !== "default") + __defProp(target, key, { get: () => module2[key], enumerable: !(desc = __getOwnPropDesc(module2, key)) || desc.enumerable }); + } + return target; +}; +var __toModule = (module2) => { + return __reExport(__markAsModule(__defProp(module2 != null ? __create(__getProtoOf(module2)) : {}, "default", module2 && module2.__esModule && "default" in module2 ? { get: () => module2.default, enumerable: true } : { value: module2, enumerable: true })), module2); +}; +var __async = (__this, __arguments, generator) => { + return new Promise((resolve, reject) => { + var fulfilled = (value) => { + try { + step(generator.next(value)); + } catch (e) { + reject(e); + } + }; + var rejected = (value) => { + try { + step(generator.throw(value)); + } catch (e) { + reject(e); + } + }; + var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected); + step((generator = generator.apply(__this, __arguments)).next()); + }); +}; + +// node_modules/showdown/dist/showdown.js +var require_showdown = __commonJS({ + "node_modules/showdown/dist/showdown.js"(exports, module2) { + (function() { + function getDefaultOpts(simple) { + "use strict"; + var defaultOptions = { + omitExtraWLInCodeBlocks: { + defaultValue: false, + describe: "Omit the default extra whiteline added to code blocks", + type: "boolean" + }, + noHeaderId: { + defaultValue: false, + describe: "Turn on/off generated header id", + type: "boolean" + }, + prefixHeaderId: { + defaultValue: false, + describe: "Add a prefix to the generated header ids. Passing a string will prefix that string to the header id. Setting to true will add a generic 'section-' prefix", + type: "string" + }, + rawPrefixHeaderId: { + defaultValue: false, + describe: 'Setting this option to true will prevent showdown from modifying the prefix. This might result in malformed IDs (if, for instance, the " char is used in the prefix)', + type: "boolean" + }, + ghCompatibleHeaderId: { + defaultValue: false, + describe: "Generate header ids compatible with github style (spaces are replaced with dashes, a bunch of non alphanumeric chars are removed)", + type: "boolean" + }, + rawHeaderId: { + defaultValue: false, + describe: `Remove only spaces, ' and " from generated header ids (including prefixes), replacing them with dashes (-). WARNING: This might result in malformed ids`, + type: "boolean" + }, + headerLevelStart: { + defaultValue: false, + describe: "The header blocks level start", + type: "integer" + }, + parseImgDimensions: { + defaultValue: false, + describe: "Turn on/off image dimension parsing", + type: "boolean" + }, + simplifiedAutoLink: { + defaultValue: false, + describe: "Turn on/off GFM autolink style", + type: "boolean" + }, + excludeTrailingPunctuationFromURLs: { + defaultValue: false, + describe: "Excludes trailing punctuation from links generated with autoLinking", + type: "boolean" + }, + literalMidWordUnderscores: { + defaultValue: false, + describe: "Parse midword underscores as literal underscores", + type: "boolean" + }, + literalMidWordAsterisks: { + defaultValue: false, + describe: "Parse midword asterisks as literal asterisks", + type: "boolean" + }, + strikethrough: { + defaultValue: false, + describe: "Turn on/off strikethrough support", + type: "boolean" + }, + tables: { + defaultValue: false, + describe: "Turn on/off tables support", + type: "boolean" + }, + tablesHeaderId: { + defaultValue: false, + describe: "Add an id to table headers", + type: "boolean" + }, + ghCodeBlocks: { + defaultValue: true, + describe: "Turn on/off GFM fenced code blocks support", + type: "boolean" + }, + tasklists: { + defaultValue: false, + describe: "Turn on/off GFM tasklist support", + type: "boolean" + }, + smoothLivePreview: { + defaultValue: false, + describe: "Prevents weird effects in live previews due to incomplete input", + type: "boolean" + }, + smartIndentationFix: { + defaultValue: false, + describe: "Tries to smartly fix indentation in es6 strings", + type: "boolean" + }, + disableForced4SpacesIndentedSublists: { + defaultValue: false, + describe: "Disables the requirement of indenting nested sublists by 4 spaces", + type: "boolean" + }, + simpleLineBreaks: { + defaultValue: false, + describe: "Parses simple line breaks as
(GFM Style)", + type: "boolean" + }, + requireSpaceBeforeHeadingText: { + defaultValue: false, + describe: "Makes adding a space between `#` and the header text mandatory (GFM Style)", + type: "boolean" + }, + ghMentions: { + defaultValue: false, + describe: "Enables github @mentions", + type: "boolean" + }, + ghMentionsLink: { + defaultValue: "https://github.com/{u}", + describe: "Changes the link generated by @mentions. Only applies if ghMentions option is enabled.", + type: "string" + }, + encodeEmails: { + defaultValue: true, + describe: "Encode e-mail addresses through the use of Character Entities, transforming ASCII e-mail addresses into its equivalent decimal entities", + type: "boolean" + }, + openLinksInNewWindow: { + defaultValue: false, + describe: "Open all links in new windows", + type: "boolean" + }, + backslashEscapesHTMLTags: { + defaultValue: false, + describe: "Support for HTML Tag escaping. ex:
foo
", + type: "boolean" + }, + emoji: { + defaultValue: false, + describe: "Enable emoji support. Ex: `this is a :smile: emoji`", + type: "boolean" + }, + underline: { + defaultValue: false, + describe: "Enable support for underline. Syntax is double or triple underscores: `__underline word__`. With this option enabled, underscores no longer parses into `` and ``", + type: "boolean" + }, + ellipsis: { + defaultValue: true, + describe: "Replaces three dots with the ellipsis unicode character", + type: "boolean" + }, + completeHTMLDocument: { + defaultValue: false, + describe: "Outputs a complete html document, including ``, `` and `` tags", + type: "boolean" + }, + metadata: { + defaultValue: false, + describe: "Enable support for document metadata (defined at the top of the document between `\xAB\xAB\xAB` and `\xBB\xBB\xBB` or between `---` and `---`).", + type: "boolean" + }, + splitAdjacentBlockquotes: { + defaultValue: false, + describe: "Split adjacent blockquote blocks", + type: "boolean" + } + }; + if (simple === false) { + return JSON.parse(JSON.stringify(defaultOptions)); + } + var ret = {}; + for (var opt in defaultOptions) { + if (defaultOptions.hasOwnProperty(opt)) { + ret[opt] = defaultOptions[opt].defaultValue; + } + } + return ret; + } + function allOptionsOn() { + "use strict"; + var options = getDefaultOpts(true), ret = {}; + for (var opt in options) { + if (options.hasOwnProperty(opt)) { + ret[opt] = true; + } + } + return ret; + } + var showdown2 = {}, parsers = {}, extensions = {}, globalOptions = getDefaultOpts(true), setFlavor = "vanilla", flavor = { + github: { + omitExtraWLInCodeBlocks: true, + simplifiedAutoLink: true, + excludeTrailingPunctuationFromURLs: true, + literalMidWordUnderscores: true, + strikethrough: true, + tables: true, + tablesHeaderId: true, + ghCodeBlocks: true, + tasklists: true, + disableForced4SpacesIndentedSublists: true, + simpleLineBreaks: true, + requireSpaceBeforeHeadingText: true, + ghCompatibleHeaderId: true, + ghMentions: true, + backslashEscapesHTMLTags: true, + emoji: true, + splitAdjacentBlockquotes: true + }, + original: { + noHeaderId: true, + ghCodeBlocks: false + }, + ghost: { + omitExtraWLInCodeBlocks: true, + parseImgDimensions: true, + simplifiedAutoLink: true, + excludeTrailingPunctuationFromURLs: true, + literalMidWordUnderscores: true, + strikethrough: true, + tables: true, + tablesHeaderId: true, + ghCodeBlocks: true, + tasklists: true, + smoothLivePreview: true, + simpleLineBreaks: true, + requireSpaceBeforeHeadingText: true, + ghMentions: false, + encodeEmails: true + }, + vanilla: getDefaultOpts(true), + allOn: allOptionsOn() + }; + showdown2.helper = {}; + showdown2.extensions = {}; + showdown2.setOption = function(key, value) { + "use strict"; + globalOptions[key] = value; + return this; + }; + showdown2.getOption = function(key) { + "use strict"; + return globalOptions[key]; + }; + showdown2.getOptions = function() { + "use strict"; + return globalOptions; + }; + showdown2.resetOptions = function() { + "use strict"; + globalOptions = getDefaultOpts(true); + }; + showdown2.setFlavor = function(name) { + "use strict"; + if (!flavor.hasOwnProperty(name)) { + throw Error(name + " flavor was not found"); + } + showdown2.resetOptions(); + var preset = flavor[name]; + setFlavor = name; + for (var option in preset) { + if (preset.hasOwnProperty(option)) { + globalOptions[option] = preset[option]; + } + } + }; + showdown2.getFlavor = function() { + "use strict"; + return setFlavor; + }; + showdown2.getFlavorOptions = function(name) { + "use strict"; + if (flavor.hasOwnProperty(name)) { + return flavor[name]; + } + }; + showdown2.getDefaultOptions = function(simple) { + "use strict"; + return getDefaultOpts(simple); + }; + showdown2.subParser = function(name, func) { + "use strict"; + if (showdown2.helper.isString(name)) { + if (typeof func !== "undefined") { + parsers[name] = func; + } else { + if (parsers.hasOwnProperty(name)) { + return parsers[name]; + } else { + throw Error("SubParser named " + name + " not registered!"); + } + } + } + }; + showdown2.extension = function(name, ext) { + "use strict"; + if (!showdown2.helper.isString(name)) { + throw Error("Extension 'name' must be a string"); + } + name = showdown2.helper.stdExtName(name); + if (showdown2.helper.isUndefined(ext)) { + if (!extensions.hasOwnProperty(name)) { + throw Error("Extension named " + name + " is not registered!"); + } + return extensions[name]; + } else { + if (typeof ext === "function") { + ext = ext(); + } + if (!showdown2.helper.isArray(ext)) { + ext = [ext]; + } + var validExtension = validate(ext, name); + if (validExtension.valid) { + extensions[name] = ext; + } else { + throw Error(validExtension.error); + } + } + }; + showdown2.getAllExtensions = function() { + "use strict"; + return extensions; + }; + showdown2.removeExtension = function(name) { + "use strict"; + delete extensions[name]; + }; + showdown2.resetExtensions = function() { + "use strict"; + extensions = {}; + }; + function validate(extension, name) { + "use strict"; + var errMsg = name ? "Error in " + name + " extension->" : "Error in unnamed extension", ret = { + valid: true, + error: "" + }; + if (!showdown2.helper.isArray(extension)) { + extension = [extension]; + } + for (var i = 0; i < extension.length; ++i) { + var baseMsg = errMsg + " sub-extension " + i + ": ", ext = extension[i]; + if (typeof ext !== "object") { + ret.valid = false; + ret.error = baseMsg + "must be an object, but " + typeof ext + " given"; + return ret; + } + if (!showdown2.helper.isString(ext.type)) { + ret.valid = false; + ret.error = baseMsg + 'property "type" must be a string, but ' + typeof ext.type + " given"; + return ret; + } + var type = ext.type = ext.type.toLowerCase(); + if (type === "language") { + type = ext.type = "lang"; + } + if (type === "html") { + type = ext.type = "output"; + } + if (type !== "lang" && type !== "output" && type !== "listener") { + ret.valid = false; + ret.error = baseMsg + "type " + type + ' is not recognized. Valid values: "lang/language", "output/html" or "listener"'; + return ret; + } + if (type === "listener") { + if (showdown2.helper.isUndefined(ext.listeners)) { + ret.valid = false; + ret.error = baseMsg + '. Extensions of type "listener" must have a property called "listeners"'; + return ret; + } + } else { + if (showdown2.helper.isUndefined(ext.filter) && showdown2.helper.isUndefined(ext.regex)) { + ret.valid = false; + ret.error = baseMsg + type + ' extensions must define either a "regex" property or a "filter" method'; + return ret; + } + } + if (ext.listeners) { + if (typeof ext.listeners !== "object") { + ret.valid = false; + ret.error = baseMsg + '"listeners" property must be an object but ' + typeof ext.listeners + " given"; + return ret; + } + for (var ln in ext.listeners) { + if (ext.listeners.hasOwnProperty(ln)) { + if (typeof ext.listeners[ln] !== "function") { + ret.valid = false; + ret.error = baseMsg + '"listeners" property must be an hash of [event name]: [callback]. listeners.' + ln + " must be a function but " + typeof ext.listeners[ln] + " given"; + return ret; + } + } + } + } + if (ext.filter) { + if (typeof ext.filter !== "function") { + ret.valid = false; + ret.error = baseMsg + '"filter" must be a function, but ' + typeof ext.filter + " given"; + return ret; + } + } else if (ext.regex) { + if (showdown2.helper.isString(ext.regex)) { + ext.regex = new RegExp(ext.regex, "g"); + } + if (!(ext.regex instanceof RegExp)) { + ret.valid = false; + ret.error = baseMsg + '"regex" property must either be a string or a RegExp object, but ' + typeof ext.regex + " given"; + return ret; + } + if (showdown2.helper.isUndefined(ext.replace)) { + ret.valid = false; + ret.error = baseMsg + '"regex" extensions must implement a replace string or function'; + return ret; + } + } + } + return ret; + } + showdown2.validateExtension = function(ext) { + "use strict"; + var validateExtension = validate(ext, null); + if (!validateExtension.valid) { + console.warn(validateExtension.error); + return false; + } + return true; + }; + if (!showdown2.hasOwnProperty("helper")) { + showdown2.helper = {}; + } + showdown2.helper.isString = function(a) { + "use strict"; + return typeof a === "string" || a instanceof String; + }; + showdown2.helper.isFunction = function(a) { + "use strict"; + var getType = {}; + return a && getType.toString.call(a) === "[object Function]"; + }; + showdown2.helper.isArray = function(a) { + "use strict"; + return Array.isArray(a); + }; + showdown2.helper.isUndefined = function(value) { + "use strict"; + return typeof value === "undefined"; + }; + showdown2.helper.forEach = function(obj, callback) { + "use strict"; + if (showdown2.helper.isUndefined(obj)) { + throw new Error("obj param is required"); + } + if (showdown2.helper.isUndefined(callback)) { + throw new Error("callback param is required"); + } + if (!showdown2.helper.isFunction(callback)) { + throw new Error("callback param must be a function/closure"); + } + if (typeof obj.forEach === "function") { + obj.forEach(callback); + } else if (showdown2.helper.isArray(obj)) { + for (var i = 0; i < obj.length; i++) { + callback(obj[i], i, obj); + } + } else if (typeof obj === "object") { + for (var prop in obj) { + if (obj.hasOwnProperty(prop)) { + callback(obj[prop], prop, obj); + } + } + } else { + throw new Error("obj does not seem to be an array or an iterable object"); + } + }; + showdown2.helper.stdExtName = function(s) { + "use strict"; + return s.replace(/[_?*+\/\\.^-]/g, "").replace(/\s/g, "").toLowerCase(); + }; + function escapeCharactersCallback(wholeMatch, m1) { + "use strict"; + var charCodeToEscape = m1.charCodeAt(0); + return "\xA8E" + charCodeToEscape + "E"; + } + showdown2.helper.escapeCharactersCallback = escapeCharactersCallback; + showdown2.helper.escapeCharacters = function(text, charsToEscape, afterBackslash) { + "use strict"; + var regexString = "([" + charsToEscape.replace(/([\[\]\\])/g, "\\$1") + "])"; + if (afterBackslash) { + regexString = "\\\\" + regexString; + } + var regex = new RegExp(regexString, "g"); + text = text.replace(regex, escapeCharactersCallback); + return text; + }; + showdown2.helper.unescapeHTMLEntities = function(txt) { + "use strict"; + return txt.replace(/"/g, '"').replace(/</g, "<").replace(/>/g, ">").replace(/&/g, "&"); + }; + var rgxFindMatchPos = function(str, left, right, flags) { + "use strict"; + var f = flags || "", g = f.indexOf("g") > -1, x = new RegExp(left + "|" + right, "g" + f.replace(/g/g, "")), l = new RegExp(left, f.replace(/g/g, "")), pos = [], t, s, m, start, end; + do { + t = 0; + while (m = x.exec(str)) { + if (l.test(m[0])) { + if (!t++) { + s = x.lastIndex; + start = s - m[0].length; + } + } else if (t) { + if (!--t) { + end = m.index + m[0].length; + var obj = { + left: { start, end: s }, + match: { start: s, end: m.index }, + right: { start: m.index, end }, + wholeMatch: { start, end } + }; + pos.push(obj); + if (!g) { + return pos; + } + } + } + } + } while (t && (x.lastIndex = s)); + return pos; + }; + showdown2.helper.matchRecursiveRegExp = function(str, left, right, flags) { + "use strict"; + var matchPos = rgxFindMatchPos(str, left, right, flags), results = []; + for (var i = 0; i < matchPos.length; ++i) { + results.push([ + str.slice(matchPos[i].wholeMatch.start, matchPos[i].wholeMatch.end), + str.slice(matchPos[i].match.start, matchPos[i].match.end), + str.slice(matchPos[i].left.start, matchPos[i].left.end), + str.slice(matchPos[i].right.start, matchPos[i].right.end) + ]); + } + return results; + }; + showdown2.helper.replaceRecursiveRegExp = function(str, replacement, left, right, flags) { + "use strict"; + if (!showdown2.helper.isFunction(replacement)) { + var repStr = replacement; + replacement = function() { + return repStr; + }; + } + var matchPos = rgxFindMatchPos(str, left, right, flags), finalStr = str, lng = matchPos.length; + if (lng > 0) { + var bits = []; + if (matchPos[0].wholeMatch.start !== 0) { + bits.push(str.slice(0, matchPos[0].wholeMatch.start)); + } + for (var i = 0; i < lng; ++i) { + bits.push(replacement(str.slice(matchPos[i].wholeMatch.start, matchPos[i].wholeMatch.end), str.slice(matchPos[i].match.start, matchPos[i].match.end), str.slice(matchPos[i].left.start, matchPos[i].left.end), str.slice(matchPos[i].right.start, matchPos[i].right.end))); + if (i < lng - 1) { + bits.push(str.slice(matchPos[i].wholeMatch.end, matchPos[i + 1].wholeMatch.start)); + } + } + if (matchPos[lng - 1].wholeMatch.end < str.length) { + bits.push(str.slice(matchPos[lng - 1].wholeMatch.end)); + } + finalStr = bits.join(""); + } + return finalStr; + }; + showdown2.helper.regexIndexOf = function(str, regex, fromIndex) { + "use strict"; + if (!showdown2.helper.isString(str)) { + throw "InvalidArgumentError: first parameter of showdown.helper.regexIndexOf function must be a string"; + } + if (regex instanceof RegExp === false) { + throw "InvalidArgumentError: second parameter of showdown.helper.regexIndexOf function must be an instance of RegExp"; + } + var indexOf = str.substring(fromIndex || 0).search(regex); + return indexOf >= 0 ? indexOf + (fromIndex || 0) : indexOf; + }; + showdown2.helper.splitAtIndex = function(str, index) { + "use strict"; + if (!showdown2.helper.isString(str)) { + throw "InvalidArgumentError: first parameter of showdown.helper.regexIndexOf function must be a string"; + } + return [str.substring(0, index), str.substring(index)]; + }; + showdown2.helper.encodeEmailAddress = function(mail) { + "use strict"; + var encode = [ + function(ch) { + return "&#" + ch.charCodeAt(0) + ";"; + }, + function(ch) { + return "&#x" + ch.charCodeAt(0).toString(16) + ";"; + }, + function(ch) { + return ch; + } + ]; + mail = mail.replace(/./g, function(ch) { + if (ch === "@") { + ch = encode[Math.floor(Math.random() * 2)](ch); + } else { + var r = Math.random(); + ch = r > 0.9 ? encode[2](ch) : r > 0.45 ? encode[1](ch) : encode[0](ch); + } + return ch; + }); + return mail; + }; + showdown2.helper.padEnd = function padEnd(str, targetLength, padString) { + "use strict"; + targetLength = targetLength >> 0; + padString = String(padString || " "); + if (str.length > targetLength) { + return String(str); + } else { + targetLength = targetLength - str.length; + if (targetLength > padString.length) { + padString += padString.repeat(targetLength / padString.length); + } + return String(str) + padString.slice(0, targetLength); + } + }; + if (typeof console === "undefined") { + console = { + warn: function(msg) { + "use strict"; + alert(msg); + }, + log: function(msg) { + "use strict"; + alert(msg); + }, + error: function(msg) { + "use strict"; + throw msg; + } + }; + } + showdown2.helper.regexes = { + asteriskDashAndColon: /([*_:~])/g + }; + showdown2.helper.emojis = { + "+1": "\u{1F44D}", + "-1": "\u{1F44E}", + "100": "\u{1F4AF}", + "1234": "\u{1F522}", + "1st_place_medal": "\u{1F947}", + "2nd_place_medal": "\u{1F948}", + "3rd_place_medal": "\u{1F949}", + "8ball": "\u{1F3B1}", + "a": "\u{1F170}\uFE0F", + "ab": "\u{1F18E}", + "abc": "\u{1F524}", + "abcd": "\u{1F521}", + "accept": "\u{1F251}", + "aerial_tramway": "\u{1F6A1}", + "airplane": "\u2708\uFE0F", + "alarm_clock": "\u23F0", + "alembic": "\u2697\uFE0F", + "alien": "\u{1F47D}", + "ambulance": "\u{1F691}", + "amphora": "\u{1F3FA}", + "anchor": "\u2693\uFE0F", + "angel": "\u{1F47C}", + "anger": "\u{1F4A2}", + "angry": "\u{1F620}", + "anguished": "\u{1F627}", + "ant": "\u{1F41C}", + "apple": "\u{1F34E}", + "aquarius": "\u2652\uFE0F", + "aries": "\u2648\uFE0F", + "arrow_backward": "\u25C0\uFE0F", + "arrow_double_down": "\u23EC", + "arrow_double_up": "\u23EB", + "arrow_down": "\u2B07\uFE0F", + "arrow_down_small": "\u{1F53D}", + "arrow_forward": "\u25B6\uFE0F", + "arrow_heading_down": "\u2935\uFE0F", + "arrow_heading_up": "\u2934\uFE0F", + "arrow_left": "\u2B05\uFE0F", + "arrow_lower_left": "\u2199\uFE0F", + "arrow_lower_right": "\u2198\uFE0F", + "arrow_right": "\u27A1\uFE0F", + "arrow_right_hook": "\u21AA\uFE0F", + "arrow_up": "\u2B06\uFE0F", + "arrow_up_down": "\u2195\uFE0F", + "arrow_up_small": "\u{1F53C}", + "arrow_upper_left": "\u2196\uFE0F", + "arrow_upper_right": "\u2197\uFE0F", + "arrows_clockwise": "\u{1F503}", + "arrows_counterclockwise": "\u{1F504}", + "art": "\u{1F3A8}", + "articulated_lorry": "\u{1F69B}", + "artificial_satellite": "\u{1F6F0}", + "astonished": "\u{1F632}", + "athletic_shoe": "\u{1F45F}", + "atm": "\u{1F3E7}", + "atom_symbol": "\u269B\uFE0F", + "avocado": "\u{1F951}", + "b": "\u{1F171}\uFE0F", + "baby": "\u{1F476}", + "baby_bottle": "\u{1F37C}", + "baby_chick": "\u{1F424}", + "baby_symbol": "\u{1F6BC}", + "back": "\u{1F519}", + "bacon": "\u{1F953}", + "badminton": "\u{1F3F8}", + "baggage_claim": "\u{1F6C4}", + "baguette_bread": "\u{1F956}", + "balance_scale": "\u2696\uFE0F", + "balloon": "\u{1F388}", + "ballot_box": "\u{1F5F3}", + "ballot_box_with_check": "\u2611\uFE0F", + "bamboo": "\u{1F38D}", + "banana": "\u{1F34C}", + "bangbang": "\u203C\uFE0F", + "bank": "\u{1F3E6}", + "bar_chart": "\u{1F4CA}", + "barber": "\u{1F488}", + "baseball": "\u26BE\uFE0F", + "basketball": "\u{1F3C0}", + "basketball_man": "\u26F9\uFE0F", + "basketball_woman": "\u26F9\uFE0F‍\u2640\uFE0F", + "bat": "\u{1F987}", + "bath": "\u{1F6C0}", + "bathtub": "\u{1F6C1}", + "battery": "\u{1F50B}", + "beach_umbrella": "\u{1F3D6}", + "bear": "\u{1F43B}", + "bed": "\u{1F6CF}", + "bee": "\u{1F41D}", + "beer": "\u{1F37A}", + "beers": "\u{1F37B}", + "beetle": "\u{1F41E}", + "beginner": "\u{1F530}", + "bell": "\u{1F514}", + "bellhop_bell": "\u{1F6CE}", + "bento": "\u{1F371}", + "biking_man": "\u{1F6B4}", + "bike": "\u{1F6B2}", + "biking_woman": "\u{1F6B4}‍\u2640\uFE0F", + "bikini": "\u{1F459}", + "biohazard": "\u2623\uFE0F", + "bird": "\u{1F426}", + "birthday": "\u{1F382}", + "black_circle": "\u26AB\uFE0F", + "black_flag": "\u{1F3F4}", + "black_heart": "\u{1F5A4}", + "black_joker": "\u{1F0CF}", + "black_large_square": "\u2B1B\uFE0F", + "black_medium_small_square": "\u25FE\uFE0F", + "black_medium_square": "\u25FC\uFE0F", + "black_nib": "\u2712\uFE0F", + "black_small_square": "\u25AA\uFE0F", + "black_square_button": "\u{1F532}", + "blonde_man": "\u{1F471}", + "blonde_woman": "\u{1F471}‍\u2640\uFE0F", + "blossom": "\u{1F33C}", + "blowfish": "\u{1F421}", + "blue_book": "\u{1F4D8}", + "blue_car": "\u{1F699}", + "blue_heart": "\u{1F499}", + "blush": "\u{1F60A}", + "boar": "\u{1F417}", + "boat": "\u26F5\uFE0F", + "bomb": "\u{1F4A3}", + "book": "\u{1F4D6}", + "bookmark": "\u{1F516}", + "bookmark_tabs": "\u{1F4D1}", + "books": "\u{1F4DA}", + "boom": "\u{1F4A5}", + "boot": "\u{1F462}", + "bouquet": "\u{1F490}", + "bowing_man": "\u{1F647}", + "bow_and_arrow": "\u{1F3F9}", + "bowing_woman": "\u{1F647}‍\u2640\uFE0F", + "bowling": "\u{1F3B3}", + "boxing_glove": "\u{1F94A}", + "boy": "\u{1F466}", + "bread": "\u{1F35E}", + "bride_with_veil": "\u{1F470}", + "bridge_at_night": "\u{1F309}", + "briefcase": "\u{1F4BC}", + "broken_heart": "\u{1F494}", + "bug": "\u{1F41B}", + "building_construction": "\u{1F3D7}", + "bulb": "\u{1F4A1}", + "bullettrain_front": "\u{1F685}", + "bullettrain_side": "\u{1F684}", + "burrito": "\u{1F32F}", + "bus": "\u{1F68C}", + "business_suit_levitating": "\u{1F574}", + "busstop": "\u{1F68F}", + "bust_in_silhouette": "\u{1F464}", + "busts_in_silhouette": "\u{1F465}", + "butterfly": "\u{1F98B}", + "cactus": "\u{1F335}", + "cake": "\u{1F370}", + "calendar": "\u{1F4C6}", + "call_me_hand": "\u{1F919}", + "calling": "\u{1F4F2}", + "camel": "\u{1F42B}", + "camera": "\u{1F4F7}", + "camera_flash": "\u{1F4F8}", + "camping": "\u{1F3D5}", + "cancer": "\u264B\uFE0F", + "candle": "\u{1F56F}", + "candy": "\u{1F36C}", + "canoe": "\u{1F6F6}", + "capital_abcd": "\u{1F520}", + "capricorn": "\u2651\uFE0F", + "car": "\u{1F697}", + "card_file_box": "\u{1F5C3}", + "card_index": "\u{1F4C7}", + "card_index_dividers": "\u{1F5C2}", + "carousel_horse": "\u{1F3A0}", + "carrot": "\u{1F955}", + "cat": "\u{1F431}", + "cat2": "\u{1F408}", + "cd": "\u{1F4BF}", + "chains": "\u26D3", + "champagne": "\u{1F37E}", + "chart": "\u{1F4B9}", + "chart_with_downwards_trend": "\u{1F4C9}", + "chart_with_upwards_trend": "\u{1F4C8}", + "checkered_flag": "\u{1F3C1}", + "cheese": "\u{1F9C0}", + "cherries": "\u{1F352}", + "cherry_blossom": "\u{1F338}", + "chestnut": "\u{1F330}", + "chicken": "\u{1F414}", + "children_crossing": "\u{1F6B8}", + "chipmunk": "\u{1F43F}", + "chocolate_bar": "\u{1F36B}", + "christmas_tree": "\u{1F384}", + "church": "\u26EA\uFE0F", + "cinema": "\u{1F3A6}", + "circus_tent": "\u{1F3AA}", + "city_sunrise": "\u{1F307}", + "city_sunset": "\u{1F306}", + "cityscape": "\u{1F3D9}", + "cl": "\u{1F191}", + "clamp": "\u{1F5DC}", + "clap": "\u{1F44F}", + "clapper": "\u{1F3AC}", + "classical_building": "\u{1F3DB}", + "clinking_glasses": "\u{1F942}", + "clipboard": "\u{1F4CB}", + "clock1": "\u{1F550}", + "clock10": "\u{1F559}", + "clock1030": "\u{1F565}", + "clock11": "\u{1F55A}", + "clock1130": "\u{1F566}", + "clock12": "\u{1F55B}", + "clock1230": "\u{1F567}", + "clock130": "\u{1F55C}", + "clock2": "\u{1F551}", + "clock230": "\u{1F55D}", + "clock3": "\u{1F552}", + "clock330": "\u{1F55E}", + "clock4": "\u{1F553}", + "clock430": "\u{1F55F}", + "clock5": "\u{1F554}", + "clock530": "\u{1F560}", + "clock6": "\u{1F555}", + "clock630": "\u{1F561}", + "clock7": "\u{1F556}", + "clock730": "\u{1F562}", + "clock8": "\u{1F557}", + "clock830": "\u{1F563}", + "clock9": "\u{1F558}", + "clock930": "\u{1F564}", + "closed_book": "\u{1F4D5}", + "closed_lock_with_key": "\u{1F510}", + "closed_umbrella": "\u{1F302}", + "cloud": "\u2601\uFE0F", + "cloud_with_lightning": "\u{1F329}", + "cloud_with_lightning_and_rain": "\u26C8", + "cloud_with_rain": "\u{1F327}", + "cloud_with_snow": "\u{1F328}", + "clown_face": "\u{1F921}", + "clubs": "\u2663\uFE0F", + "cocktail": "\u{1F378}", + "coffee": "\u2615\uFE0F", + "coffin": "\u26B0\uFE0F", + "cold_sweat": "\u{1F630}", + "comet": "\u2604\uFE0F", + "computer": "\u{1F4BB}", + "computer_mouse": "\u{1F5B1}", + "confetti_ball": "\u{1F38A}", + "confounded": "\u{1F616}", + "confused": "\u{1F615}", + "congratulations": "\u3297\uFE0F", + "construction": "\u{1F6A7}", + "construction_worker_man": "\u{1F477}", + "construction_worker_woman": "\u{1F477}‍\u2640\uFE0F", + "control_knobs": "\u{1F39B}", + "convenience_store": "\u{1F3EA}", + "cookie": "\u{1F36A}", + "cool": "\u{1F192}", + "policeman": "\u{1F46E}", + "copyright": "\xA9\uFE0F", + "corn": "\u{1F33D}", + "couch_and_lamp": "\u{1F6CB}", + "couple": "\u{1F46B}", + "couple_with_heart_woman_man": "\u{1F491}", + "couple_with_heart_man_man": "\u{1F468}‍\u2764\uFE0F‍\u{1F468}", + "couple_with_heart_woman_woman": "\u{1F469}‍\u2764\uFE0F‍\u{1F469}", + "couplekiss_man_man": "\u{1F468}‍\u2764\uFE0F‍\u{1F48B}‍\u{1F468}", + "couplekiss_man_woman": "\u{1F48F}", + "couplekiss_woman_woman": "\u{1F469}‍\u2764\uFE0F‍\u{1F48B}‍\u{1F469}", + "cow": "\u{1F42E}", + "cow2": "\u{1F404}", + "cowboy_hat_face": "\u{1F920}", + "crab": "\u{1F980}", + "crayon": "\u{1F58D}", + "credit_card": "\u{1F4B3}", + "crescent_moon": "\u{1F319}", + "cricket": "\u{1F3CF}", + "crocodile": "\u{1F40A}", + "croissant": "\u{1F950}", + "crossed_fingers": "\u{1F91E}", + "crossed_flags": "\u{1F38C}", + "crossed_swords": "\u2694\uFE0F", + "crown": "\u{1F451}", + "cry": "\u{1F622}", + "crying_cat_face": "\u{1F63F}", + "crystal_ball": "\u{1F52E}", + "cucumber": "\u{1F952}", + "cupid": "\u{1F498}", + "curly_loop": "\u27B0", + "currency_exchange": "\u{1F4B1}", + "curry": "\u{1F35B}", + "custard": "\u{1F36E}", + "customs": "\u{1F6C3}", + "cyclone": "\u{1F300}", + "dagger": "\u{1F5E1}", + "dancer": "\u{1F483}", + "dancing_women": "\u{1F46F}", + "dancing_men": "\u{1F46F}‍\u2642\uFE0F", + "dango": "\u{1F361}", + "dark_sunglasses": "\u{1F576}", + "dart": "\u{1F3AF}", + "dash": "\u{1F4A8}", + "date": "\u{1F4C5}", + "deciduous_tree": "\u{1F333}", + "deer": "\u{1F98C}", + "department_store": "\u{1F3EC}", + "derelict_house": "\u{1F3DA}", + "desert": "\u{1F3DC}", + "desert_island": "\u{1F3DD}", + "desktop_computer": "\u{1F5A5}", + "male_detective": "\u{1F575}\uFE0F", + "diamond_shape_with_a_dot_inside": "\u{1F4A0}", + "diamonds": "\u2666\uFE0F", + "disappointed": "\u{1F61E}", + "disappointed_relieved": "\u{1F625}", + "dizzy": "\u{1F4AB}", + "dizzy_face": "\u{1F635}", + "do_not_litter": "\u{1F6AF}", + "dog": "\u{1F436}", + "dog2": "\u{1F415}", + "dollar": "\u{1F4B5}", + "dolls": "\u{1F38E}", + "dolphin": "\u{1F42C}", + "door": "\u{1F6AA}", + "doughnut": "\u{1F369}", + "dove": "\u{1F54A}", + "dragon": "\u{1F409}", + "dragon_face": "\u{1F432}", + "dress": "\u{1F457}", + "dromedary_camel": "\u{1F42A}", + "drooling_face": "\u{1F924}", + "droplet": "\u{1F4A7}", + "drum": "\u{1F941}", + "duck": "\u{1F986}", + "dvd": "\u{1F4C0}", + "e-mail": "\u{1F4E7}", + "eagle": "\u{1F985}", + "ear": "\u{1F442}", + "ear_of_rice": "\u{1F33E}", + "earth_africa": "\u{1F30D}", + "earth_americas": "\u{1F30E}", + "earth_asia": "\u{1F30F}", + "egg": "\u{1F95A}", + "eggplant": "\u{1F346}", + "eight_pointed_black_star": "\u2734\uFE0F", + "eight_spoked_asterisk": "\u2733\uFE0F", + "electric_plug": "\u{1F50C}", + "elephant": "\u{1F418}", + "email": "\u2709\uFE0F", + "end": "\u{1F51A}", + "envelope_with_arrow": "\u{1F4E9}", + "euro": "\u{1F4B6}", + "european_castle": "\u{1F3F0}", + "european_post_office": "\u{1F3E4}", + "evergreen_tree": "\u{1F332}", + "exclamation": "\u2757\uFE0F", + "expressionless": "\u{1F611}", + "eye": "\u{1F441}", + "eye_speech_bubble": "\u{1F441}‍\u{1F5E8}", + "eyeglasses": "\u{1F453}", + "eyes": "\u{1F440}", + "face_with_head_bandage": "\u{1F915}", + "face_with_thermometer": "\u{1F912}", + "fist_oncoming": "\u{1F44A}", + "factory": "\u{1F3ED}", + "fallen_leaf": "\u{1F342}", + "family_man_woman_boy": "\u{1F46A}", + "family_man_boy": "\u{1F468}‍\u{1F466}", + "family_man_boy_boy": "\u{1F468}‍\u{1F466}‍\u{1F466}", + "family_man_girl": "\u{1F468}‍\u{1F467}", + "family_man_girl_boy": "\u{1F468}‍\u{1F467}‍\u{1F466}", + "family_man_girl_girl": "\u{1F468}‍\u{1F467}‍\u{1F467}", + "family_man_man_boy": "\u{1F468}‍\u{1F468}‍\u{1F466}", + "family_man_man_boy_boy": "\u{1F468}‍\u{1F468}‍\u{1F466}‍\u{1F466}", + "family_man_man_girl": "\u{1F468}‍\u{1F468}‍\u{1F467}", + "family_man_man_girl_boy": "\u{1F468}‍\u{1F468}‍\u{1F467}‍\u{1F466}", + "family_man_man_girl_girl": "\u{1F468}‍\u{1F468}‍\u{1F467}‍\u{1F467}", + "family_man_woman_boy_boy": "\u{1F468}‍\u{1F469}‍\u{1F466}‍\u{1F466}", + "family_man_woman_girl": "\u{1F468}‍\u{1F469}‍\u{1F467}", + "family_man_woman_girl_boy": "\u{1F468}‍\u{1F469}‍\u{1F467}‍\u{1F466}", + "family_man_woman_girl_girl": "\u{1F468}‍\u{1F469}‍\u{1F467}‍\u{1F467}", + "family_woman_boy": "\u{1F469}‍\u{1F466}", + "family_woman_boy_boy": "\u{1F469}‍\u{1F466}‍\u{1F466}", + "family_woman_girl": "\u{1F469}‍\u{1F467}", + "family_woman_girl_boy": "\u{1F469}‍\u{1F467}‍\u{1F466}", + "family_woman_girl_girl": "\u{1F469}‍\u{1F467}‍\u{1F467}", + "family_woman_woman_boy": "\u{1F469}‍\u{1F469}‍\u{1F466}", + "family_woman_woman_boy_boy": "\u{1F469}‍\u{1F469}‍\u{1F466}‍\u{1F466}", + "family_woman_woman_girl": "\u{1F469}‍\u{1F469}‍\u{1F467}", + "family_woman_woman_girl_boy": "\u{1F469}‍\u{1F469}‍\u{1F467}‍\u{1F466}", + "family_woman_woman_girl_girl": "\u{1F469}‍\u{1F469}‍\u{1F467}‍\u{1F467}", + "fast_forward": "\u23E9", + "fax": "\u{1F4E0}", + "fearful": "\u{1F628}", + "feet": "\u{1F43E}", + "female_detective": "\u{1F575}\uFE0F‍\u2640\uFE0F", + "ferris_wheel": "\u{1F3A1}", + "ferry": "\u26F4", + "field_hockey": "\u{1F3D1}", + "file_cabinet": "\u{1F5C4}", + "file_folder": "\u{1F4C1}", + "film_projector": "\u{1F4FD}", + "film_strip": "\u{1F39E}", + "fire": "\u{1F525}", + "fire_engine": "\u{1F692}", + "fireworks": "\u{1F386}", + "first_quarter_moon": "\u{1F313}", + "first_quarter_moon_with_face": "\u{1F31B}", + "fish": "\u{1F41F}", + "fish_cake": "\u{1F365}", + "fishing_pole_and_fish": "\u{1F3A3}", + "fist_raised": "\u270A", + "fist_left": "\u{1F91B}", + "fist_right": "\u{1F91C}", + "flags": "\u{1F38F}", + "flashlight": "\u{1F526}", + "fleur_de_lis": "\u269C\uFE0F", + "flight_arrival": "\u{1F6EC}", + "flight_departure": "\u{1F6EB}", + "floppy_disk": "\u{1F4BE}", + "flower_playing_cards": "\u{1F3B4}", + "flushed": "\u{1F633}", + "fog": "\u{1F32B}", + "foggy": "\u{1F301}", + "football": "\u{1F3C8}", + "footprints": "\u{1F463}", + "fork_and_knife": "\u{1F374}", + "fountain": "\u26F2\uFE0F", + "fountain_pen": "\u{1F58B}", + "four_leaf_clover": "\u{1F340}", + "fox_face": "\u{1F98A}", + "framed_picture": "\u{1F5BC}", + "free": "\u{1F193}", + "fried_egg": "\u{1F373}", + "fried_shrimp": "\u{1F364}", + "fries": "\u{1F35F}", + "frog": "\u{1F438}", + "frowning": "\u{1F626}", + "frowning_face": "\u2639\uFE0F", + "frowning_man": "\u{1F64D}‍\u2642\uFE0F", + "frowning_woman": "\u{1F64D}", + "middle_finger": "\u{1F595}", + "fuelpump": "\u26FD\uFE0F", + "full_moon": "\u{1F315}", + "full_moon_with_face": "\u{1F31D}", + "funeral_urn": "\u26B1\uFE0F", + "game_die": "\u{1F3B2}", + "gear": "\u2699\uFE0F", + "gem": "\u{1F48E}", + "gemini": "\u264A\uFE0F", + "ghost": "\u{1F47B}", + "gift": "\u{1F381}", + "gift_heart": "\u{1F49D}", + "girl": "\u{1F467}", + "globe_with_meridians": "\u{1F310}", + "goal_net": "\u{1F945}", + "goat": "\u{1F410}", + "golf": "\u26F3\uFE0F", + "golfing_man": "\u{1F3CC}\uFE0F", + "golfing_woman": "\u{1F3CC}\uFE0F‍\u2640\uFE0F", + "gorilla": "\u{1F98D}", + "grapes": "\u{1F347}", + "green_apple": "\u{1F34F}", + "green_book": "\u{1F4D7}", + "green_heart": "\u{1F49A}", + "green_salad": "\u{1F957}", + "grey_exclamation": "\u2755", + "grey_question": "\u2754", + "grimacing": "\u{1F62C}", + "grin": "\u{1F601}", + "grinning": "\u{1F600}", + "guardsman": "\u{1F482}", + "guardswoman": "\u{1F482}‍\u2640\uFE0F", + "guitar": "\u{1F3B8}", + "gun": "\u{1F52B}", + "haircut_woman": "\u{1F487}", + "haircut_man": "\u{1F487}‍\u2642\uFE0F", + "hamburger": "\u{1F354}", + "hammer": "\u{1F528}", + "hammer_and_pick": "\u2692", + "hammer_and_wrench": "\u{1F6E0}", + "hamster": "\u{1F439}", + "hand": "\u270B", + "handbag": "\u{1F45C}", + "handshake": "\u{1F91D}", + "hankey": "\u{1F4A9}", + "hatched_chick": "\u{1F425}", + "hatching_chick": "\u{1F423}", + "headphones": "\u{1F3A7}", + "hear_no_evil": "\u{1F649}", + "heart": "\u2764\uFE0F", + "heart_decoration": "\u{1F49F}", + "heart_eyes": "\u{1F60D}", + "heart_eyes_cat": "\u{1F63B}", + "heartbeat": "\u{1F493}", + "heartpulse": "\u{1F497}", + "hearts": "\u2665\uFE0F", + "heavy_check_mark": "\u2714\uFE0F", + "heavy_division_sign": "\u2797", + "heavy_dollar_sign": "\u{1F4B2}", + "heavy_heart_exclamation": "\u2763\uFE0F", + "heavy_minus_sign": "\u2796", + "heavy_multiplication_x": "\u2716\uFE0F", + "heavy_plus_sign": "\u2795", + "helicopter": "\u{1F681}", + "herb": "\u{1F33F}", + "hibiscus": "\u{1F33A}", + "high_brightness": "\u{1F506}", + "high_heel": "\u{1F460}", + "hocho": "\u{1F52A}", + "hole": "\u{1F573}", + "honey_pot": "\u{1F36F}", + "horse": "\u{1F434}", + "horse_racing": "\u{1F3C7}", + "hospital": "\u{1F3E5}", + "hot_pepper": "\u{1F336}", + "hotdog": "\u{1F32D}", + "hotel": "\u{1F3E8}", + "hotsprings": "\u2668\uFE0F", + "hourglass": "\u231B\uFE0F", + "hourglass_flowing_sand": "\u23F3", + "house": "\u{1F3E0}", + "house_with_garden": "\u{1F3E1}", + "houses": "\u{1F3D8}", + "hugs": "\u{1F917}", + "hushed": "\u{1F62F}", + "ice_cream": "\u{1F368}", + "ice_hockey": "\u{1F3D2}", + "ice_skate": "\u26F8", + "icecream": "\u{1F366}", + "id": "\u{1F194}", + "ideograph_advantage": "\u{1F250}", + "imp": "\u{1F47F}", + "inbox_tray": "\u{1F4E5}", + "incoming_envelope": "\u{1F4E8}", + "tipping_hand_woman": "\u{1F481}", + "information_source": "\u2139\uFE0F", + "innocent": "\u{1F607}", + "interrobang": "\u2049\uFE0F", + "iphone": "\u{1F4F1}", + "izakaya_lantern": "\u{1F3EE}", + "jack_o_lantern": "\u{1F383}", + "japan": "\u{1F5FE}", + "japanese_castle": "\u{1F3EF}", + "japanese_goblin": "\u{1F47A}", + "japanese_ogre": "\u{1F479}", + "jeans": "\u{1F456}", + "joy": "\u{1F602}", + "joy_cat": "\u{1F639}", + "joystick": "\u{1F579}", + "kaaba": "\u{1F54B}", + "key": "\u{1F511}", + "keyboard": "\u2328\uFE0F", + "keycap_ten": "\u{1F51F}", + "kick_scooter": "\u{1F6F4}", + "kimono": "\u{1F458}", + "kiss": "\u{1F48B}", + "kissing": "\u{1F617}", + "kissing_cat": "\u{1F63D}", + "kissing_closed_eyes": "\u{1F61A}", + "kissing_heart": "\u{1F618}", + "kissing_smiling_eyes": "\u{1F619}", + "kiwi_fruit": "\u{1F95D}", + "koala": "\u{1F428}", + "koko": "\u{1F201}", + "label": "\u{1F3F7}", + "large_blue_circle": "\u{1F535}", + "large_blue_diamond": "\u{1F537}", + "large_orange_diamond": "\u{1F536}", + "last_quarter_moon": "\u{1F317}", + "last_quarter_moon_with_face": "\u{1F31C}", + "latin_cross": "\u271D\uFE0F", + "laughing": "\u{1F606}", + "leaves": "\u{1F343}", + "ledger": "\u{1F4D2}", + "left_luggage": "\u{1F6C5}", + "left_right_arrow": "\u2194\uFE0F", + "leftwards_arrow_with_hook": "\u21A9\uFE0F", + "lemon": "\u{1F34B}", + "leo": "\u264C\uFE0F", + "leopard": "\u{1F406}", + "level_slider": "\u{1F39A}", + "libra": "\u264E\uFE0F", + "light_rail": "\u{1F688}", + "link": "\u{1F517}", + "lion": "\u{1F981}", + "lips": "\u{1F444}", + "lipstick": "\u{1F484}", + "lizard": "\u{1F98E}", + "lock": "\u{1F512}", + "lock_with_ink_pen": "\u{1F50F}", + "lollipop": "\u{1F36D}", + "loop": "\u27BF", + "loud_sound": "\u{1F50A}", + "loudspeaker": "\u{1F4E2}", + "love_hotel": "\u{1F3E9}", + "love_letter": "\u{1F48C}", + "low_brightness": "\u{1F505}", + "lying_face": "\u{1F925}", + "m": "\u24C2\uFE0F", + "mag": "\u{1F50D}", + "mag_right": "\u{1F50E}", + "mahjong": "\u{1F004}\uFE0F", + "mailbox": "\u{1F4EB}", + "mailbox_closed": "\u{1F4EA}", + "mailbox_with_mail": "\u{1F4EC}", + "mailbox_with_no_mail": "\u{1F4ED}", + "man": "\u{1F468}", + "man_artist": "\u{1F468}‍\u{1F3A8}", + "man_astronaut": "\u{1F468}‍\u{1F680}", + "man_cartwheeling": "\u{1F938}‍\u2642\uFE0F", + "man_cook": "\u{1F468}‍\u{1F373}", + "man_dancing": "\u{1F57A}", + "man_facepalming": "\u{1F926}‍\u2642\uFE0F", + "man_factory_worker": "\u{1F468}‍\u{1F3ED}", + "man_farmer": "\u{1F468}‍\u{1F33E}", + "man_firefighter": "\u{1F468}‍\u{1F692}", + "man_health_worker": "\u{1F468}‍\u2695\uFE0F", + "man_in_tuxedo": "\u{1F935}", + "man_judge": "\u{1F468}‍\u2696\uFE0F", + "man_juggling": "\u{1F939}‍\u2642\uFE0F", + "man_mechanic": "\u{1F468}‍\u{1F527}", + "man_office_worker": "\u{1F468}‍\u{1F4BC}", + "man_pilot": "\u{1F468}‍\u2708\uFE0F", + "man_playing_handball": "\u{1F93E}‍\u2642\uFE0F", + "man_playing_water_polo": "\u{1F93D}‍\u2642\uFE0F", + "man_scientist": "\u{1F468}‍\u{1F52C}", + "man_shrugging": "\u{1F937}‍\u2642\uFE0F", + "man_singer": "\u{1F468}‍\u{1F3A4}", + "man_student": "\u{1F468}‍\u{1F393}", + "man_teacher": "\u{1F468}‍\u{1F3EB}", + "man_technologist": "\u{1F468}‍\u{1F4BB}", + "man_with_gua_pi_mao": "\u{1F472}", + "man_with_turban": "\u{1F473}", + "tangerine": "\u{1F34A}", + "mans_shoe": "\u{1F45E}", + "mantelpiece_clock": "\u{1F570}", + "maple_leaf": "\u{1F341}", + "martial_arts_uniform": "\u{1F94B}", + "mask": "\u{1F637}", + "massage_woman": "\u{1F486}", + "massage_man": "\u{1F486}‍\u2642\uFE0F", + "meat_on_bone": "\u{1F356}", + "medal_military": "\u{1F396}", + "medal_sports": "\u{1F3C5}", + "mega": "\u{1F4E3}", + "melon": "\u{1F348}", + "memo": "\u{1F4DD}", + "men_wrestling": "\u{1F93C}‍\u2642\uFE0F", + "menorah": "\u{1F54E}", + "mens": "\u{1F6B9}", + "metal": "\u{1F918}", + "metro": "\u{1F687}", + "microphone": "\u{1F3A4}", + "microscope": "\u{1F52C}", + "milk_glass": "\u{1F95B}", + "milky_way": "\u{1F30C}", + "minibus": "\u{1F690}", + "minidisc": "\u{1F4BD}", + "mobile_phone_off": "\u{1F4F4}", + "money_mouth_face": "\u{1F911}", + "money_with_wings": "\u{1F4B8}", + "moneybag": "\u{1F4B0}", + "monkey": "\u{1F412}", + "monkey_face": "\u{1F435}", + "monorail": "\u{1F69D}", + "moon": "\u{1F314}", + "mortar_board": "\u{1F393}", + "mosque": "\u{1F54C}", + "motor_boat": "\u{1F6E5}", + "motor_scooter": "\u{1F6F5}", + "motorcycle": "\u{1F3CD}", + "motorway": "\u{1F6E3}", + "mount_fuji": "\u{1F5FB}", + "mountain": "\u26F0", + "mountain_biking_man": "\u{1F6B5}", + "mountain_biking_woman": "\u{1F6B5}‍\u2640\uFE0F", + "mountain_cableway": "\u{1F6A0}", + "mountain_railway": "\u{1F69E}", + "mountain_snow": "\u{1F3D4}", + "mouse": "\u{1F42D}", + "mouse2": "\u{1F401}", + "movie_camera": "\u{1F3A5}", + "moyai": "\u{1F5FF}", + "mrs_claus": "\u{1F936}", + "muscle": "\u{1F4AA}", + "mushroom": "\u{1F344}", + "musical_keyboard": "\u{1F3B9}", + "musical_note": "\u{1F3B5}", + "musical_score": "\u{1F3BC}", + "mute": "\u{1F507}", + "nail_care": "\u{1F485}", + "name_badge": "\u{1F4DB}", + "national_park": "\u{1F3DE}", + "nauseated_face": "\u{1F922}", + "necktie": "\u{1F454}", + "negative_squared_cross_mark": "\u274E", + "nerd_face": "\u{1F913}", + "neutral_face": "\u{1F610}", + "new": "\u{1F195}", + "new_moon": "\u{1F311}", + "new_moon_with_face": "\u{1F31A}", + "newspaper": "\u{1F4F0}", + "newspaper_roll": "\u{1F5DE}", + "next_track_button": "\u23ED", + "ng": "\u{1F196}", + "no_good_man": "\u{1F645}‍\u2642\uFE0F", + "no_good_woman": "\u{1F645}", + "night_with_stars": "\u{1F303}", + "no_bell": "\u{1F515}", + "no_bicycles": "\u{1F6B3}", + "no_entry": "\u26D4\uFE0F", + "no_entry_sign": "\u{1F6AB}", + "no_mobile_phones": "\u{1F4F5}", + "no_mouth": "\u{1F636}", + "no_pedestrians": "\u{1F6B7}", + "no_smoking": "\u{1F6AD}", + "non-potable_water": "\u{1F6B1}", + "nose": "\u{1F443}", + "notebook": "\u{1F4D3}", + "notebook_with_decorative_cover": "\u{1F4D4}", + "notes": "\u{1F3B6}", + "nut_and_bolt": "\u{1F529}", + "o": "\u2B55\uFE0F", + "o2": "\u{1F17E}\uFE0F", + "ocean": "\u{1F30A}", + "octopus": "\u{1F419}", + "oden": "\u{1F362}", + "office": "\u{1F3E2}", + "oil_drum": "\u{1F6E2}", + "ok": "\u{1F197}", + "ok_hand": "\u{1F44C}", + "ok_man": "\u{1F646}‍\u2642\uFE0F", + "ok_woman": "\u{1F646}", + "old_key": "\u{1F5DD}", + "older_man": "\u{1F474}", + "older_woman": "\u{1F475}", + "om": "\u{1F549}", + "on": "\u{1F51B}", + "oncoming_automobile": "\u{1F698}", + "oncoming_bus": "\u{1F68D}", + "oncoming_police_car": "\u{1F694}", + "oncoming_taxi": "\u{1F696}", + "open_file_folder": "\u{1F4C2}", + "open_hands": "\u{1F450}", + "open_mouth": "\u{1F62E}", + "open_umbrella": "\u2602\uFE0F", + "ophiuchus": "\u26CE", + "orange_book": "\u{1F4D9}", + "orthodox_cross": "\u2626\uFE0F", + "outbox_tray": "\u{1F4E4}", + "owl": "\u{1F989}", + "ox": "\u{1F402}", + "package": "\u{1F4E6}", + "page_facing_up": "\u{1F4C4}", + "page_with_curl": "\u{1F4C3}", + "pager": "\u{1F4DF}", + "paintbrush": "\u{1F58C}", + "palm_tree": "\u{1F334}", + "pancakes": "\u{1F95E}", + "panda_face": "\u{1F43C}", + "paperclip": "\u{1F4CE}", + "paperclips": "\u{1F587}", + "parasol_on_ground": "\u26F1", + "parking": "\u{1F17F}\uFE0F", + "part_alternation_mark": "\u303D\uFE0F", + "partly_sunny": "\u26C5\uFE0F", + "passenger_ship": "\u{1F6F3}", + "passport_control": "\u{1F6C2}", + "pause_button": "\u23F8", + "peace_symbol": "\u262E\uFE0F", + "peach": "\u{1F351}", + "peanuts": "\u{1F95C}", + "pear": "\u{1F350}", + "pen": "\u{1F58A}", + "pencil2": "\u270F\uFE0F", + "penguin": "\u{1F427}", + "pensive": "\u{1F614}", + "performing_arts": "\u{1F3AD}", + "persevere": "\u{1F623}", + "person_fencing": "\u{1F93A}", + "pouting_woman": "\u{1F64E}", + "phone": "\u260E\uFE0F", + "pick": "\u26CF", + "pig": "\u{1F437}", + "pig2": "\u{1F416}", + "pig_nose": "\u{1F43D}", + "pill": "\u{1F48A}", + "pineapple": "\u{1F34D}", + "ping_pong": "\u{1F3D3}", + "pisces": "\u2653\uFE0F", + "pizza": "\u{1F355}", + "place_of_worship": "\u{1F6D0}", + "plate_with_cutlery": "\u{1F37D}", + "play_or_pause_button": "\u23EF", + "point_down": "\u{1F447}", + "point_left": "\u{1F448}", + "point_right": "\u{1F449}", + "point_up": "\u261D\uFE0F", + "point_up_2": "\u{1F446}", + "police_car": "\u{1F693}", + "policewoman": "\u{1F46E}‍\u2640\uFE0F", + "poodle": "\u{1F429}", + "popcorn": "\u{1F37F}", + "post_office": "\u{1F3E3}", + "postal_horn": "\u{1F4EF}", + "postbox": "\u{1F4EE}", + "potable_water": "\u{1F6B0}", + "potato": "\u{1F954}", + "pouch": "\u{1F45D}", + "poultry_leg": "\u{1F357}", + "pound": "\u{1F4B7}", + "rage": "\u{1F621}", + "pouting_cat": "\u{1F63E}", + "pouting_man": "\u{1F64E}‍\u2642\uFE0F", + "pray": "\u{1F64F}", + "prayer_beads": "\u{1F4FF}", + "pregnant_woman": "\u{1F930}", + "previous_track_button": "\u23EE", + "prince": "\u{1F934}", + "princess": "\u{1F478}", + "printer": "\u{1F5A8}", + "purple_heart": "\u{1F49C}", + "purse": "\u{1F45B}", + "pushpin": "\u{1F4CC}", + "put_litter_in_its_place": "\u{1F6AE}", + "question": "\u2753", + "rabbit": "\u{1F430}", + "rabbit2": "\u{1F407}", + "racehorse": "\u{1F40E}", + "racing_car": "\u{1F3CE}", + "radio": "\u{1F4FB}", + "radio_button": "\u{1F518}", + "radioactive": "\u2622\uFE0F", + "railway_car": "\u{1F683}", + "railway_track": "\u{1F6E4}", + "rainbow": "\u{1F308}", + "rainbow_flag": "\u{1F3F3}\uFE0F‍\u{1F308}", + "raised_back_of_hand": "\u{1F91A}", + "raised_hand_with_fingers_splayed": "\u{1F590}", + "raised_hands": "\u{1F64C}", + "raising_hand_woman": "\u{1F64B}", + "raising_hand_man": "\u{1F64B}‍\u2642\uFE0F", + "ram": "\u{1F40F}", + "ramen": "\u{1F35C}", + "rat": "\u{1F400}", + "record_button": "\u23FA", + "recycle": "\u267B\uFE0F", + "red_circle": "\u{1F534}", + "registered": "\xAE\uFE0F", + "relaxed": "\u263A\uFE0F", + "relieved": "\u{1F60C}", + "reminder_ribbon": "\u{1F397}", + "repeat": "\u{1F501}", + "repeat_one": "\u{1F502}", + "rescue_worker_helmet": "\u26D1", + "restroom": "\u{1F6BB}", + "revolving_hearts": "\u{1F49E}", + "rewind": "\u23EA", + "rhinoceros": "\u{1F98F}", + "ribbon": "\u{1F380}", + "rice": "\u{1F35A}", + "rice_ball": "\u{1F359}", + "rice_cracker": "\u{1F358}", + "rice_scene": "\u{1F391}", + "right_anger_bubble": "\u{1F5EF}", + "ring": "\u{1F48D}", + "robot": "\u{1F916}", + "rocket": "\u{1F680}", + "rofl": "\u{1F923}", + "roll_eyes": "\u{1F644}", + "roller_coaster": "\u{1F3A2}", + "rooster": "\u{1F413}", + "rose": "\u{1F339}", + "rosette": "\u{1F3F5}", + "rotating_light": "\u{1F6A8}", + "round_pushpin": "\u{1F4CD}", + "rowing_man": "\u{1F6A3}", + "rowing_woman": "\u{1F6A3}‍\u2640\uFE0F", + "rugby_football": "\u{1F3C9}", + "running_man": "\u{1F3C3}", + "running_shirt_with_sash": "\u{1F3BD}", + "running_woman": "\u{1F3C3}‍\u2640\uFE0F", + "sa": "\u{1F202}\uFE0F", + "sagittarius": "\u2650\uFE0F", + "sake": "\u{1F376}", + "sandal": "\u{1F461}", + "santa": "\u{1F385}", + "satellite": "\u{1F4E1}", + "saxophone": "\u{1F3B7}", + "school": "\u{1F3EB}", + "school_satchel": "\u{1F392}", + "scissors": "\u2702\uFE0F", + "scorpion": "\u{1F982}", + "scorpius": "\u264F\uFE0F", + "scream": "\u{1F631}", + "scream_cat": "\u{1F640}", + "scroll": "\u{1F4DC}", + "seat": "\u{1F4BA}", + "secret": "\u3299\uFE0F", + "see_no_evil": "\u{1F648}", + "seedling": "\u{1F331}", + "selfie": "\u{1F933}", + "shallow_pan_of_food": "\u{1F958}", + "shamrock": "\u2618\uFE0F", + "shark": "\u{1F988}", + "shaved_ice": "\u{1F367}", + "sheep": "\u{1F411}", + "shell": "\u{1F41A}", + "shield": "\u{1F6E1}", + "shinto_shrine": "\u26E9", + "ship": "\u{1F6A2}", + "shirt": "\u{1F455}", + "shopping": "\u{1F6CD}", + "shopping_cart": "\u{1F6D2}", + "shower": "\u{1F6BF}", + "shrimp": "\u{1F990}", + "signal_strength": "\u{1F4F6}", + "six_pointed_star": "\u{1F52F}", + "ski": "\u{1F3BF}", + "skier": "\u26F7", + "skull": "\u{1F480}", + "skull_and_crossbones": "\u2620\uFE0F", + "sleeping": "\u{1F634}", + "sleeping_bed": "\u{1F6CC}", + "sleepy": "\u{1F62A}", + "slightly_frowning_face": "\u{1F641}", + "slightly_smiling_face": "\u{1F642}", + "slot_machine": "\u{1F3B0}", + "small_airplane": "\u{1F6E9}", + "small_blue_diamond": "\u{1F539}", + "small_orange_diamond": "\u{1F538}", + "small_red_triangle": "\u{1F53A}", + "small_red_triangle_down": "\u{1F53B}", + "smile": "\u{1F604}", + "smile_cat": "\u{1F638}", + "smiley": "\u{1F603}", + "smiley_cat": "\u{1F63A}", + "smiling_imp": "\u{1F608}", + "smirk": "\u{1F60F}", + "smirk_cat": "\u{1F63C}", + "smoking": "\u{1F6AC}", + "snail": "\u{1F40C}", + "snake": "\u{1F40D}", + "sneezing_face": "\u{1F927}", + "snowboarder": "\u{1F3C2}", + "snowflake": "\u2744\uFE0F", + "snowman": "\u26C4\uFE0F", + "snowman_with_snow": "\u2603\uFE0F", + "sob": "\u{1F62D}", + "soccer": "\u26BD\uFE0F", + "soon": "\u{1F51C}", + "sos": "\u{1F198}", + "sound": "\u{1F509}", + "space_invader": "\u{1F47E}", + "spades": "\u2660\uFE0F", + "spaghetti": "\u{1F35D}", + "sparkle": "\u2747\uFE0F", + "sparkler": "\u{1F387}", + "sparkles": "\u2728", + "sparkling_heart": "\u{1F496}", + "speak_no_evil": "\u{1F64A}", + "speaker": "\u{1F508}", + "speaking_head": "\u{1F5E3}", + "speech_balloon": "\u{1F4AC}", + "speedboat": "\u{1F6A4}", + "spider": "\u{1F577}", + "spider_web": "\u{1F578}", + "spiral_calendar": "\u{1F5D3}", + "spiral_notepad": "\u{1F5D2}", + "spoon": "\u{1F944}", + "squid": "\u{1F991}", + "stadium": "\u{1F3DF}", + "star": "\u2B50\uFE0F", + "star2": "\u{1F31F}", + "star_and_crescent": "\u262A\uFE0F", + "star_of_david": "\u2721\uFE0F", + "stars": "\u{1F320}", + "station": "\u{1F689}", + "statue_of_liberty": "\u{1F5FD}", + "steam_locomotive": "\u{1F682}", + "stew": "\u{1F372}", + "stop_button": "\u23F9", + "stop_sign": "\u{1F6D1}", + "stopwatch": "\u23F1", + "straight_ruler": "\u{1F4CF}", + "strawberry": "\u{1F353}", + "stuck_out_tongue": "\u{1F61B}", + "stuck_out_tongue_closed_eyes": "\u{1F61D}", + "stuck_out_tongue_winking_eye": "\u{1F61C}", + "studio_microphone": "\u{1F399}", + "stuffed_flatbread": "\u{1F959}", + "sun_behind_large_cloud": "\u{1F325}", + "sun_behind_rain_cloud": "\u{1F326}", + "sun_behind_small_cloud": "\u{1F324}", + "sun_with_face": "\u{1F31E}", + "sunflower": "\u{1F33B}", + "sunglasses": "\u{1F60E}", + "sunny": "\u2600\uFE0F", + "sunrise": "\u{1F305}", + "sunrise_over_mountains": "\u{1F304}", + "surfing_man": "\u{1F3C4}", + "surfing_woman": "\u{1F3C4}‍\u2640\uFE0F", + "sushi": "\u{1F363}", + "suspension_railway": "\u{1F69F}", + "sweat": "\u{1F613}", + "sweat_drops": "\u{1F4A6}", + "sweat_smile": "\u{1F605}", + "sweet_potato": "\u{1F360}", + "swimming_man": "\u{1F3CA}", + "swimming_woman": "\u{1F3CA}‍\u2640\uFE0F", + "symbols": "\u{1F523}", + "synagogue": "\u{1F54D}", + "syringe": "\u{1F489}", + "taco": "\u{1F32E}", + "tada": "\u{1F389}", + "tanabata_tree": "\u{1F38B}", + "taurus": "\u2649\uFE0F", + "taxi": "\u{1F695}", + "tea": "\u{1F375}", + "telephone_receiver": "\u{1F4DE}", + "telescope": "\u{1F52D}", + "tennis": "\u{1F3BE}", + "tent": "\u26FA\uFE0F", + "thermometer": "\u{1F321}", + "thinking": "\u{1F914}", + "thought_balloon": "\u{1F4AD}", + "ticket": "\u{1F3AB}", + "tickets": "\u{1F39F}", + "tiger": "\u{1F42F}", + "tiger2": "\u{1F405}", + "timer_clock": "\u23F2", + "tipping_hand_man": "\u{1F481}‍\u2642\uFE0F", + "tired_face": "\u{1F62B}", + "tm": "\u2122\uFE0F", + "toilet": "\u{1F6BD}", + "tokyo_tower": "\u{1F5FC}", + "tomato": "\u{1F345}", + "tongue": "\u{1F445}", + "top": "\u{1F51D}", + "tophat": "\u{1F3A9}", + "tornado": "\u{1F32A}", + "trackball": "\u{1F5B2}", + "tractor": "\u{1F69C}", + "traffic_light": "\u{1F6A5}", + "train": "\u{1F68B}", + "train2": "\u{1F686}", + "tram": "\u{1F68A}", + "triangular_flag_on_post": "\u{1F6A9}", + "triangular_ruler": "\u{1F4D0}", + "trident": "\u{1F531}", + "triumph": "\u{1F624}", + "trolleybus": "\u{1F68E}", + "trophy": "\u{1F3C6}", + "tropical_drink": "\u{1F379}", + "tropical_fish": "\u{1F420}", + "truck": "\u{1F69A}", + "trumpet": "\u{1F3BA}", + "tulip": "\u{1F337}", + "tumbler_glass": "\u{1F943}", + "turkey": "\u{1F983}", + "turtle": "\u{1F422}", + "tv": "\u{1F4FA}", + "twisted_rightwards_arrows": "\u{1F500}", + "two_hearts": "\u{1F495}", + "two_men_holding_hands": "\u{1F46C}", + "two_women_holding_hands": "\u{1F46D}", + "u5272": "\u{1F239}", + "u5408": "\u{1F234}", + "u55b6": "\u{1F23A}", + "u6307": "\u{1F22F}\uFE0F", + "u6708": "\u{1F237}\uFE0F", + "u6709": "\u{1F236}", + "u6e80": "\u{1F235}", + "u7121": "\u{1F21A}\uFE0F", + "u7533": "\u{1F238}", + "u7981": "\u{1F232}", + "u7a7a": "\u{1F233}", + "umbrella": "\u2614\uFE0F", + "unamused": "\u{1F612}", + "underage": "\u{1F51E}", + "unicorn": "\u{1F984}", + "unlock": "\u{1F513}", + "up": "\u{1F199}", + "upside_down_face": "\u{1F643}", + "v": "\u270C\uFE0F", + "vertical_traffic_light": "\u{1F6A6}", + "vhs": "\u{1F4FC}", + "vibration_mode": "\u{1F4F3}", + "video_camera": "\u{1F4F9}", + "video_game": "\u{1F3AE}", + "violin": "\u{1F3BB}", + "virgo": "\u264D\uFE0F", + "volcano": "\u{1F30B}", + "volleyball": "\u{1F3D0}", + "vs": "\u{1F19A}", + "vulcan_salute": "\u{1F596}", + "walking_man": "\u{1F6B6}", + "walking_woman": "\u{1F6B6}‍\u2640\uFE0F", + "waning_crescent_moon": "\u{1F318}", + "waning_gibbous_moon": "\u{1F316}", + "warning": "\u26A0\uFE0F", + "wastebasket": "\u{1F5D1}", + "watch": "\u231A\uFE0F", + "water_buffalo": "\u{1F403}", + "watermelon": "\u{1F349}", + "wave": "\u{1F44B}", + "wavy_dash": "\u3030\uFE0F", + "waxing_crescent_moon": "\u{1F312}", + "wc": "\u{1F6BE}", + "weary": "\u{1F629}", + "wedding": "\u{1F492}", + "weight_lifting_man": "\u{1F3CB}\uFE0F", + "weight_lifting_woman": "\u{1F3CB}\uFE0F‍\u2640\uFE0F", + "whale": "\u{1F433}", + "whale2": "\u{1F40B}", + "wheel_of_dharma": "\u2638\uFE0F", + "wheelchair": "\u267F\uFE0F", + "white_check_mark": "\u2705", + "white_circle": "\u26AA\uFE0F", + "white_flag": "\u{1F3F3}\uFE0F", + "white_flower": "\u{1F4AE}", + "white_large_square": "\u2B1C\uFE0F", + "white_medium_small_square": "\u25FD\uFE0F", + "white_medium_square": "\u25FB\uFE0F", + "white_small_square": "\u25AB\uFE0F", + "white_square_button": "\u{1F533}", + "wilted_flower": "\u{1F940}", + "wind_chime": "\u{1F390}", + "wind_face": "\u{1F32C}", + "wine_glass": "\u{1F377}", + "wink": "\u{1F609}", + "wolf": "\u{1F43A}", + "woman": "\u{1F469}", + "woman_artist": "\u{1F469}‍\u{1F3A8}", + "woman_astronaut": "\u{1F469}‍\u{1F680}", + "woman_cartwheeling": "\u{1F938}‍\u2640\uFE0F", + "woman_cook": "\u{1F469}‍\u{1F373}", + "woman_facepalming": "\u{1F926}‍\u2640\uFE0F", + "woman_factory_worker": "\u{1F469}‍\u{1F3ED}", + "woman_farmer": "\u{1F469}‍\u{1F33E}", + "woman_firefighter": "\u{1F469}‍\u{1F692}", + "woman_health_worker": "\u{1F469}‍\u2695\uFE0F", + "woman_judge": "\u{1F469}‍\u2696\uFE0F", + "woman_juggling": "\u{1F939}‍\u2640\uFE0F", + "woman_mechanic": "\u{1F469}‍\u{1F527}", + "woman_office_worker": "\u{1F469}‍\u{1F4BC}", + "woman_pilot": "\u{1F469}‍\u2708\uFE0F", + "woman_playing_handball": "\u{1F93E}‍\u2640\uFE0F", + "woman_playing_water_polo": "\u{1F93D}‍\u2640\uFE0F", + "woman_scientist": "\u{1F469}‍\u{1F52C}", + "woman_shrugging": "\u{1F937}‍\u2640\uFE0F", + "woman_singer": "\u{1F469}‍\u{1F3A4}", + "woman_student": "\u{1F469}‍\u{1F393}", + "woman_teacher": "\u{1F469}‍\u{1F3EB}", + "woman_technologist": "\u{1F469}‍\u{1F4BB}", + "woman_with_turban": "\u{1F473}‍\u2640\uFE0F", + "womans_clothes": "\u{1F45A}", + "womans_hat": "\u{1F452}", + "women_wrestling": "\u{1F93C}‍\u2640\uFE0F", + "womens": "\u{1F6BA}", + "world_map": "\u{1F5FA}", + "worried": "\u{1F61F}", + "wrench": "\u{1F527}", + "writing_hand": "\u270D\uFE0F", + "x": "\u274C", + "yellow_heart": "\u{1F49B}", + "yen": "\u{1F4B4}", + "yin_yang": "\u262F\uFE0F", + "yum": "\u{1F60B}", + "zap": "\u26A1\uFE0F", + "zipper_mouth_face": "\u{1F910}", + "zzz": "\u{1F4A4}", + "octocat": ':octocat:', + "showdown": `S` + }; + showdown2.Converter = function(converterOptions) { + "use strict"; + var options = {}, langExtensions = [], outputModifiers = [], listeners = {}, setConvFlavor = setFlavor, metadata = { + parsed: {}, + raw: "", + format: "" + }; + _constructor(); + function _constructor() { + converterOptions = converterOptions || {}; + for (var gOpt in globalOptions) { + if (globalOptions.hasOwnProperty(gOpt)) { + options[gOpt] = globalOptions[gOpt]; + } + } + if (typeof converterOptions === "object") { + for (var opt in converterOptions) { + if (converterOptions.hasOwnProperty(opt)) { + options[opt] = converterOptions[opt]; + } + } + } else { + throw Error("Converter expects the passed parameter to be an object, but " + typeof converterOptions + " was passed instead."); + } + if (options.extensions) { + showdown2.helper.forEach(options.extensions, _parseExtension); + } + } + function _parseExtension(ext, name) { + name = name || null; + if (showdown2.helper.isString(ext)) { + ext = showdown2.helper.stdExtName(ext); + name = ext; + if (showdown2.extensions[ext]) { + console.warn("DEPRECATION WARNING: " + ext + " is an old extension that uses a deprecated loading method.Please inform the developer that the extension should be updated!"); + legacyExtensionLoading(showdown2.extensions[ext], ext); + return; + } else if (!showdown2.helper.isUndefined(extensions[ext])) { + ext = extensions[ext]; + } else { + throw Error('Extension "' + ext + '" could not be loaded. It was either not found or is not a valid extension.'); + } + } + if (typeof ext === "function") { + ext = ext(); + } + if (!showdown2.helper.isArray(ext)) { + ext = [ext]; + } + var validExt = validate(ext, name); + if (!validExt.valid) { + throw Error(validExt.error); + } + for (var i = 0; i < ext.length; ++i) { + switch (ext[i].type) { + case "lang": + langExtensions.push(ext[i]); + break; + case "output": + outputModifiers.push(ext[i]); + break; + } + if (ext[i].hasOwnProperty("listeners")) { + for (var ln in ext[i].listeners) { + if (ext[i].listeners.hasOwnProperty(ln)) { + listen(ln, ext[i].listeners[ln]); + } + } + } + } + } + function legacyExtensionLoading(ext, name) { + if (typeof ext === "function") { + ext = ext(new showdown2.Converter()); + } + if (!showdown2.helper.isArray(ext)) { + ext = [ext]; + } + var valid = validate(ext, name); + if (!valid.valid) { + throw Error(valid.error); + } + for (var i = 0; i < ext.length; ++i) { + switch (ext[i].type) { + case "lang": + langExtensions.push(ext[i]); + break; + case "output": + outputModifiers.push(ext[i]); + break; + default: + throw Error("Extension loader error: Type unrecognized!!!"); + } + } + } + function listen(name, callback) { + if (!showdown2.helper.isString(name)) { + throw Error("Invalid argument in converter.listen() method: name must be a string, but " + typeof name + " given"); + } + if (typeof callback !== "function") { + throw Error("Invalid argument in converter.listen() method: callback must be a function, but " + typeof callback + " given"); + } + if (!listeners.hasOwnProperty(name)) { + listeners[name] = []; + } + listeners[name].push(callback); + } + function rTrimInputText(text) { + var rsp = text.match(/^\s*/)[0].length, rgx = new RegExp("^\\s{0," + rsp + "}", "gm"); + return text.replace(rgx, ""); + } + this._dispatch = function dispatch(evtName, text, options2, globals) { + if (listeners.hasOwnProperty(evtName)) { + for (var ei = 0; ei < listeners[evtName].length; ++ei) { + var nText = listeners[evtName][ei](evtName, text, this, options2, globals); + if (nText && typeof nText !== "undefined") { + text = nText; + } + } + } + return text; + }; + this.listen = function(name, callback) { + listen(name, callback); + return this; + }; + this.makeHtml = function(text) { + if (!text) { + return text; + } + var globals = { + gHtmlBlocks: [], + gHtmlMdBlocks: [], + gHtmlSpans: [], + gUrls: {}, + gTitles: {}, + gDimensions: {}, + gListLevel: 0, + hashLinkCounts: {}, + langExtensions, + outputModifiers, + converter: this, + ghCodeBlocks: [], + metadata: { + parsed: {}, + raw: "", + format: "" + } + }; + text = text.replace(/¨/g, "\xA8T"); + text = text.replace(/\$/g, "\xA8D"); + text = text.replace(/\r\n/g, "\n"); + text = text.replace(/\r/g, "\n"); + text = text.replace(/\u00A0/g, " "); + if (options.smartIndentationFix) { + text = rTrimInputText(text); + } + text = "\n\n" + text + "\n\n"; + text = showdown2.subParser("detab")(text, options, globals); + text = text.replace(/^[ \t]+$/mg, ""); + showdown2.helper.forEach(langExtensions, function(ext) { + text = showdown2.subParser("runExtension")(ext, text, options, globals); + }); + text = showdown2.subParser("metadata")(text, options, globals); + text = showdown2.subParser("hashPreCodeTags")(text, options, globals); + text = showdown2.subParser("githubCodeBlocks")(text, options, globals); + text = showdown2.subParser("hashHTMLBlocks")(text, options, globals); + text = showdown2.subParser("hashCodeTags")(text, options, globals); + text = showdown2.subParser("stripLinkDefinitions")(text, options, globals); + text = showdown2.subParser("blockGamut")(text, options, globals); + text = showdown2.subParser("unhashHTMLSpans")(text, options, globals); + text = showdown2.subParser("unescapeSpecialChars")(text, options, globals); + text = text.replace(/¨D/g, "$$"); + text = text.replace(/¨T/g, "\xA8"); + text = showdown2.subParser("completeHTMLDocument")(text, options, globals); + showdown2.helper.forEach(outputModifiers, function(ext) { + text = showdown2.subParser("runExtension")(ext, text, options, globals); + }); + metadata = globals.metadata; + return text; + }; + this.makeMarkdown = this.makeMd = function(src, HTMLParser) { + src = src.replace(/\r\n/g, "\n"); + src = src.replace(/\r/g, "\n"); + src = src.replace(/>[ \t]+\xA8NBSP;<"); + if (!HTMLParser) { + if (window && window.document) { + HTMLParser = window.document; + } else { + throw new Error("HTMLParser is undefined. If in a webworker or nodejs environment, you need to provide a WHATWG DOM and HTML such as JSDOM"); + } + } + var doc = HTMLParser.createElement("div"); + doc.innerHTML = src; + var globals = { + preList: substitutePreCodeTags(doc) + }; + clean(doc); + var nodes = doc.childNodes, mdDoc = ""; + for (var i = 0; i < nodes.length; i++) { + mdDoc += showdown2.subParser("makeMarkdown.node")(nodes[i], globals); + } + function clean(node) { + for (var n = 0; n < node.childNodes.length; ++n) { + var child = node.childNodes[n]; + if (child.nodeType === 3) { + if (!/\S/.test(child.nodeValue) && !/^[ ]+$/.test(child.nodeValue)) { + node.removeChild(child); + --n; + } else { + child.nodeValue = child.nodeValue.split("\n").join(" "); + child.nodeValue = child.nodeValue.replace(/(\s)+/g, "$1"); + } + } else if (child.nodeType === 1) { + clean(child); + } + } + } + function substitutePreCodeTags(doc2) { + var pres = doc2.querySelectorAll("pre"), presPH = []; + for (var i2 = 0; i2 < pres.length; ++i2) { + if (pres[i2].childElementCount === 1 && pres[i2].firstChild.tagName.toLowerCase() === "code") { + var content = pres[i2].firstChild.innerHTML.trim(), language = pres[i2].firstChild.getAttribute("data-language") || ""; + if (language === "") { + var classes = pres[i2].firstChild.className.split(" "); + for (var c = 0; c < classes.length; ++c) { + var matches = classes[c].match(/^language-(.+)$/); + if (matches !== null) { + language = matches[1]; + break; + } + } + } + content = showdown2.helper.unescapeHTMLEntities(content); + presPH.push(content); + pres[i2].outerHTML = ''; + } else { + presPH.push(pres[i2].innerHTML); + pres[i2].innerHTML = ""; + pres[i2].setAttribute("prenum", i2.toString()); + } + } + return presPH; + } + return mdDoc; + }; + this.setOption = function(key, value) { + options[key] = value; + }; + this.getOption = function(key) { + return options[key]; + }; + this.getOptions = function() { + return options; + }; + this.addExtension = function(extension, name) { + name = name || null; + _parseExtension(extension, name); + }; + this.useExtension = function(extensionName) { + _parseExtension(extensionName); + }; + this.setFlavor = function(name) { + if (!flavor.hasOwnProperty(name)) { + throw Error(name + " flavor was not found"); + } + var preset = flavor[name]; + setConvFlavor = name; + for (var option in preset) { + if (preset.hasOwnProperty(option)) { + options[option] = preset[option]; + } + } + }; + this.getFlavor = function() { + return setConvFlavor; + }; + this.removeExtension = function(extension) { + if (!showdown2.helper.isArray(extension)) { + extension = [extension]; + } + for (var a = 0; a < extension.length; ++a) { + var ext = extension[a]; + for (var i = 0; i < langExtensions.length; ++i) { + if (langExtensions[i] === ext) { + langExtensions.splice(i, 1); + } + } + for (var ii = 0; ii < outputModifiers.length; ++ii) { + if (outputModifiers[ii] === ext) { + outputModifiers.splice(ii, 1); + } + } + } + }; + this.getAllExtensions = function() { + return { + language: langExtensions, + output: outputModifiers + }; + }; + this.getMetadata = function(raw) { + if (raw) { + return metadata.raw; + } else { + return metadata.parsed; + } + }; + this.getMetadataFormat = function() { + return metadata.format; + }; + this._setMetadataPair = function(key, value) { + metadata.parsed[key] = value; + }; + this._setMetadataFormat = function(format) { + metadata.format = format; + }; + this._setMetadataRaw = function(raw) { + metadata.raw = raw; + }; + }; + showdown2.subParser("anchors", function(text, options, globals) { + "use strict"; + text = globals.converter._dispatch("anchors.before", text, options, globals); + var writeAnchorTag = function(wholeMatch, linkText, linkId, url, m5, m6, title) { + if (showdown2.helper.isUndefined(title)) { + title = ""; + } + linkId = linkId.toLowerCase(); + if (wholeMatch.search(/\(? ?(['"].*['"])?\)$/m) > -1) { + url = ""; + } else if (!url) { + if (!linkId) { + linkId = linkText.toLowerCase().replace(/ ?\n/g, " "); + } + url = "#" + linkId; + if (!showdown2.helper.isUndefined(globals.gUrls[linkId])) { + url = globals.gUrls[linkId]; + if (!showdown2.helper.isUndefined(globals.gTitles[linkId])) { + title = globals.gTitles[linkId]; + } + } else { + return wholeMatch; + } + } + url = url.replace(showdown2.helper.regexes.asteriskDashAndColon, showdown2.helper.escapeCharactersCallback); + var result = '"; + return result; + }; + text = text.replace(/\[((?:\[[^\]]*]|[^\[\]])*)] ?(?:\n *)?\[(.*?)]()()()()/g, writeAnchorTag); + text = text.replace(/\[((?:\[[^\]]*]|[^\[\]])*)]()[ \t]*\([ \t]?<([^>]*)>(?:[ \t]*((["'])([^"]*?)\5))?[ \t]?\)/g, writeAnchorTag); + text = text.replace(/\[((?:\[[^\]]*]|[^\[\]])*)]()[ \t]*\([ \t]??(?:[ \t]*((["'])([^"]*?)\5))?[ \t]?\)/g, writeAnchorTag); + text = text.replace(/\[([^\[\]]+)]()()()()()/g, writeAnchorTag); + if (options.ghMentions) { + text = text.replace(/(^|\s)(\\)?(@([a-z\d]+(?:[a-z\d.-]+?[a-z\d]+)*))/gmi, function(wm, st, escape, mentions, username) { + if (escape === "\\") { + return st + mentions; + } + if (!showdown2.helper.isString(options.ghMentionsLink)) { + throw new Error("ghMentionsLink option must be a string"); + } + var lnk = options.ghMentionsLink.replace(/\{u}/g, username), target = ""; + if (options.openLinksInNewWindow) { + target = ' rel="noopener noreferrer" target="\xA8E95Eblank"'; + } + return st + '" + mentions + ""; + }); + } + text = globals.converter._dispatch("anchors.after", text, options, globals); + return text; + }); + var simpleURLRegex = /([*~_]+|\b)(((https?|ftp|dict):\/\/|www\.)[^'">\s]+?\.[^'">\s]+?)()(\1)?(?=\s|$)(?!["<>])/gi, simpleURLRegex2 = /([*~_]+|\b)(((https?|ftp|dict):\/\/|www\.)[^'">\s]+\.[^'">\s]+?)([.!?,()\[\]])?(\1)?(?=\s|$)(?!["<>])/gi, delimUrlRegex = /()<(((https?|ftp|dict):\/\/|www\.)[^'">\s]+)()>()/gi, simpleMailRegex = /(^|\s)(?:mailto:)?([A-Za-z0-9!#$%&'*+-/=?^_`{|}~.]+@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)(?=$|\s)/gmi, delimMailRegex = /<()(?:mailto:)?([-.\w]+@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)>/gi, replaceLink = function(options) { + "use strict"; + return function(wm, leadingMagicChars, link, m2, m3, trailingPunctuation, trailingMagicChars) { + link = link.replace(showdown2.helper.regexes.asteriskDashAndColon, showdown2.helper.escapeCharactersCallback); + var lnkTxt = link, append = "", target = "", lmc = leadingMagicChars || "", tmc = trailingMagicChars || ""; + if (/^www\./i.test(link)) { + link = link.replace(/^www\./i, "http://www."); + } + if (options.excludeTrailingPunctuationFromURLs && trailingPunctuation) { + append = trailingPunctuation; + } + if (options.openLinksInNewWindow) { + target = ' rel="noopener noreferrer" target="\xA8E95Eblank"'; + } + return lmc + '" + lnkTxt + "" + append + tmc; + }; + }, replaceMail = function(options, globals) { + "use strict"; + return function(wholeMatch, b, mail) { + var href = "mailto:"; + b = b || ""; + mail = showdown2.subParser("unescapeSpecialChars")(mail, options, globals); + if (options.encodeEmails) { + href = showdown2.helper.encodeEmailAddress(href + mail); + mail = showdown2.helper.encodeEmailAddress(mail); + } else { + href = href + mail; + } + return b + '' + mail + ""; + }; + }; + showdown2.subParser("autoLinks", function(text, options, globals) { + "use strict"; + text = globals.converter._dispatch("autoLinks.before", text, options, globals); + text = text.replace(delimUrlRegex, replaceLink(options)); + text = text.replace(delimMailRegex, replaceMail(options, globals)); + text = globals.converter._dispatch("autoLinks.after", text, options, globals); + return text; + }); + showdown2.subParser("simplifiedAutoLinks", function(text, options, globals) { + "use strict"; + if (!options.simplifiedAutoLink) { + return text; + } + text = globals.converter._dispatch("simplifiedAutoLinks.before", text, options, globals); + if (options.excludeTrailingPunctuationFromURLs) { + text = text.replace(simpleURLRegex2, replaceLink(options)); + } else { + text = text.replace(simpleURLRegex, replaceLink(options)); + } + text = text.replace(simpleMailRegex, replaceMail(options, globals)); + text = globals.converter._dispatch("simplifiedAutoLinks.after", text, options, globals); + return text; + }); + showdown2.subParser("blockGamut", function(text, options, globals) { + "use strict"; + text = globals.converter._dispatch("blockGamut.before", text, options, globals); + text = showdown2.subParser("blockQuotes")(text, options, globals); + text = showdown2.subParser("headers")(text, options, globals); + text = showdown2.subParser("horizontalRule")(text, options, globals); + text = showdown2.subParser("lists")(text, options, globals); + text = showdown2.subParser("codeBlocks")(text, options, globals); + text = showdown2.subParser("tables")(text, options, globals); + text = showdown2.subParser("hashHTMLBlocks")(text, options, globals); + text = showdown2.subParser("paragraphs")(text, options, globals); + text = globals.converter._dispatch("blockGamut.after", text, options, globals); + return text; + }); + showdown2.subParser("blockQuotes", function(text, options, globals) { + "use strict"; + text = globals.converter._dispatch("blockQuotes.before", text, options, globals); + text = text + "\n\n"; + var rgx = /(^ {0,3}>[ \t]?.+\n(.+\n)*\n*)+/gm; + if (options.splitAdjacentBlockquotes) { + rgx = /^ {0,3}>[\s\S]*?(?:\n\n)/gm; + } + text = text.replace(rgx, function(bq) { + bq = bq.replace(/^[ \t]*>[ \t]?/gm, ""); + bq = bq.replace(/¨0/g, ""); + bq = bq.replace(/^[ \t]+$/gm, ""); + bq = showdown2.subParser("githubCodeBlocks")(bq, options, globals); + bq = showdown2.subParser("blockGamut")(bq, options, globals); + bq = bq.replace(/(^|\n)/g, "$1 "); + bq = bq.replace(/(\s*
[^\r]+?<\/pre>)/gm, function(wholeMatch, m1) {
+            var pre = m1;
+            pre = pre.replace(/^  /mg, "\xA80");
+            pre = pre.replace(/¨0/g, "");
+            return pre;
+          });
+          return showdown2.subParser("hashBlock")("
\n" + bq + "\n
", options, globals); + }); + text = globals.converter._dispatch("blockQuotes.after", text, options, globals); + return text; + }); + showdown2.subParser("codeBlocks", function(text, options, globals) { + "use strict"; + text = globals.converter._dispatch("codeBlocks.before", text, options, globals); + text += "\xA80"; + var pattern = /(?:\n\n|^)((?:(?:[ ]{4}|\t).*\n+)+)(\n*[ ]{0,3}[^ \t\n]|(?=¨0))/g; + text = text.replace(pattern, function(wholeMatch, m1, m2) { + var codeblock = m1, nextChar = m2, end = "\n"; + codeblock = showdown2.subParser("outdent")(codeblock, options, globals); + codeblock = showdown2.subParser("encodeCode")(codeblock, options, globals); + codeblock = showdown2.subParser("detab")(codeblock, options, globals); + codeblock = codeblock.replace(/^\n+/g, ""); + codeblock = codeblock.replace(/\n+$/g, ""); + if (options.omitExtraWLInCodeBlocks) { + end = ""; + } + codeblock = "
" + codeblock + end + "
"; + return showdown2.subParser("hashBlock")(codeblock, options, globals) + nextChar; + }); + text = text.replace(/¨0/, ""); + text = globals.converter._dispatch("codeBlocks.after", text, options, globals); + return text; + }); + showdown2.subParser("codeSpans", function(text, options, globals) { + "use strict"; + text = globals.converter._dispatch("codeSpans.before", text, options, globals); + if (typeof text === "undefined") { + text = ""; + } + text = text.replace(/(^|[^\\])(`+)([^\r]*?[^`])\2(?!`)/gm, function(wholeMatch, m1, m2, m3) { + var c = m3; + c = c.replace(/^([ \t]*)/g, ""); + c = c.replace(/[ \t]*$/g, ""); + c = showdown2.subParser("encodeCode")(c, options, globals); + c = m1 + "" + c + ""; + c = showdown2.subParser("hashHTMLSpans")(c, options, globals); + return c; + }); + text = globals.converter._dispatch("codeSpans.after", text, options, globals); + return text; + }); + showdown2.subParser("completeHTMLDocument", function(text, options, globals) { + "use strict"; + if (!options.completeHTMLDocument) { + return text; + } + text = globals.converter._dispatch("completeHTMLDocument.before", text, options, globals); + var doctype = "html", doctypeParsed = "\n", title = "", charset = '\n', lang = "", metadata = ""; + if (typeof globals.metadata.parsed.doctype !== "undefined") { + doctypeParsed = "\n"; + doctype = globals.metadata.parsed.doctype.toString().toLowerCase(); + if (doctype === "html" || doctype === "html5") { + charset = ''; + } + } + for (var meta in globals.metadata.parsed) { + if (globals.metadata.parsed.hasOwnProperty(meta)) { + switch (meta.toLowerCase()) { + case "doctype": + break; + case "title": + title = "" + globals.metadata.parsed.title + "\n"; + break; + case "charset": + if (doctype === "html" || doctype === "html5") { + charset = '\n'; + } else { + charset = '\n'; + } + break; + case "language": + case "lang": + lang = ' lang="' + globals.metadata.parsed[meta] + '"'; + metadata += '\n'; + break; + default: + metadata += '\n'; + } + } + } + text = doctypeParsed + "\n\n" + title + charset + metadata + "\n\n" + text.trim() + "\n\n"; + text = globals.converter._dispatch("completeHTMLDocument.after", text, options, globals); + return text; + }); + showdown2.subParser("detab", function(text, options, globals) { + "use strict"; + text = globals.converter._dispatch("detab.before", text, options, globals); + text = text.replace(/\t(?=\t)/g, " "); + text = text.replace(/\t/g, "\xA8A\xA8B"); + text = text.replace(/¨B(.+?)¨A/g, function(wholeMatch, m1) { + var leadingText = m1, numSpaces = 4 - leadingText.length % 4; + for (var i = 0; i < numSpaces; i++) { + leadingText += " "; + } + return leadingText; + }); + text = text.replace(/¨A/g, " "); + text = text.replace(/¨B/g, ""); + text = globals.converter._dispatch("detab.after", text, options, globals); + return text; + }); + showdown2.subParser("ellipsis", function(text, options, globals) { + "use strict"; + if (!options.ellipsis) { + return text; + } + text = globals.converter._dispatch("ellipsis.before", text, options, globals); + text = text.replace(/\.\.\./g, "\u2026"); + text = globals.converter._dispatch("ellipsis.after", text, options, globals); + return text; + }); + showdown2.subParser("emoji", function(text, options, globals) { + "use strict"; + if (!options.emoji) { + return text; + } + text = globals.converter._dispatch("emoji.before", text, options, globals); + var emojiRgx = /:([\S]+?):/g; + text = text.replace(emojiRgx, function(wm, emojiCode) { + if (showdown2.helper.emojis.hasOwnProperty(emojiCode)) { + return showdown2.helper.emojis[emojiCode]; + } + return wm; + }); + text = globals.converter._dispatch("emoji.after", text, options, globals); + return text; + }); + showdown2.subParser("encodeAmpsAndAngles", function(text, options, globals) { + "use strict"; + text = globals.converter._dispatch("encodeAmpsAndAngles.before", text, options, globals); + text = text.replace(/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/g, "&"); + text = text.replace(/<(?![a-z\/?$!])/gi, "<"); + text = text.replace(//g, ">"); + text = globals.converter._dispatch("encodeAmpsAndAngles.after", text, options, globals); + return text; + }); + showdown2.subParser("encodeBackslashEscapes", function(text, options, globals) { + "use strict"; + text = globals.converter._dispatch("encodeBackslashEscapes.before", text, options, globals); + text = text.replace(/\\(\\)/g, showdown2.helper.escapeCharactersCallback); + text = text.replace(/\\([`*_{}\[\]()>#+.!~=|:-])/g, showdown2.helper.escapeCharactersCallback); + text = globals.converter._dispatch("encodeBackslashEscapes.after", text, options, globals); + return text; + }); + showdown2.subParser("encodeCode", function(text, options, globals) { + "use strict"; + text = globals.converter._dispatch("encodeCode.before", text, options, globals); + text = text.replace(/&/g, "&").replace(//g, ">").replace(/([*_{}\[\]\\=~-])/g, showdown2.helper.escapeCharactersCallback); + text = globals.converter._dispatch("encodeCode.after", text, options, globals); + return text; + }); + showdown2.subParser("escapeSpecialCharsWithinTagAttributes", function(text, options, globals) { + "use strict"; + text = globals.converter._dispatch("escapeSpecialCharsWithinTagAttributes.before", text, options, globals); + var tags = /<\/?[a-z\d_:-]+(?:[\s]+[\s\S]+?)?>/gi, comments = /-]|-[^>])(?:[^-]|-[^-])*)--)>/gi; + text = text.replace(tags, function(wholeMatch) { + return wholeMatch.replace(/(.)<\/?code>(?=.)/g, "$1`").replace(/([\\`*_~=|])/g, showdown2.helper.escapeCharactersCallback); + }); + text = text.replace(comments, function(wholeMatch) { + return wholeMatch.replace(/([\\`*_~=|])/g, showdown2.helper.escapeCharactersCallback); + }); + text = globals.converter._dispatch("escapeSpecialCharsWithinTagAttributes.after", text, options, globals); + return text; + }); + showdown2.subParser("githubCodeBlocks", function(text, options, globals) { + "use strict"; + if (!options.ghCodeBlocks) { + return text; + } + text = globals.converter._dispatch("githubCodeBlocks.before", text, options, globals); + text += "\xA80"; + text = text.replace(/(?:^|\n)(?: {0,3})(```+|~~~+)(?: *)([^\s`~]*)\n([\s\S]*?)\n(?: {0,3})\1/g, function(wholeMatch, delim, language, codeblock) { + var end = options.omitExtraWLInCodeBlocks ? "" : "\n"; + codeblock = showdown2.subParser("encodeCode")(codeblock, options, globals); + codeblock = showdown2.subParser("detab")(codeblock, options, globals); + codeblock = codeblock.replace(/^\n+/g, ""); + codeblock = codeblock.replace(/\n+$/g, ""); + codeblock = "
" + codeblock + end + "
"; + codeblock = showdown2.subParser("hashBlock")(codeblock, options, globals); + return "\n\n\xA8G" + (globals.ghCodeBlocks.push({ text: wholeMatch, codeblock }) - 1) + "G\n\n"; + }); + text = text.replace(/¨0/, ""); + return globals.converter._dispatch("githubCodeBlocks.after", text, options, globals); + }); + showdown2.subParser("hashBlock", function(text, options, globals) { + "use strict"; + text = globals.converter._dispatch("hashBlock.before", text, options, globals); + text = text.replace(/(^\n+|\n+$)/g, ""); + text = "\n\n\xA8K" + (globals.gHtmlBlocks.push(text) - 1) + "K\n\n"; + text = globals.converter._dispatch("hashBlock.after", text, options, globals); + return text; + }); + showdown2.subParser("hashCodeTags", function(text, options, globals) { + "use strict"; + text = globals.converter._dispatch("hashCodeTags.before", text, options, globals); + var repFunc = function(wholeMatch, match, left, right) { + var codeblock = left + showdown2.subParser("encodeCode")(match, options, globals) + right; + return "\xA8C" + (globals.gHtmlSpans.push(codeblock) - 1) + "C"; + }; + text = showdown2.helper.replaceRecursiveRegExp(text, repFunc, "]*>", "", "gim"); + text = globals.converter._dispatch("hashCodeTags.after", text, options, globals); + return text; + }); + showdown2.subParser("hashElement", function(text, options, globals) { + "use strict"; + return function(wholeMatch, m1) { + var blockText = m1; + blockText = blockText.replace(/\n\n/g, "\n"); + blockText = blockText.replace(/^\n/, ""); + blockText = blockText.replace(/\n+$/g, ""); + blockText = "\n\n\xA8K" + (globals.gHtmlBlocks.push(blockText) - 1) + "K\n\n"; + return blockText; + }; + }); + showdown2.subParser("hashHTMLBlocks", function(text, options, globals) { + "use strict"; + text = globals.converter._dispatch("hashHTMLBlocks.before", text, options, globals); + var blockTags = [ + "pre", + "div", + "h1", + "h2", + "h3", + "h4", + "h5", + "h6", + "blockquote", + "table", + "dl", + "ol", + "ul", + "script", + "noscript", + "form", + "fieldset", + "iframe", + "math", + "style", + "section", + "header", + "footer", + "nav", + "article", + "aside", + "address", + "audio", + "canvas", + "figure", + "hgroup", + "output", + "video", + "p" + ], repFunc = function(wholeMatch, match, left, right) { + var txt = wholeMatch; + if (left.search(/\bmarkdown\b/) !== -1) { + txt = left + globals.converter.makeHtml(match) + right; + } + return "\n\n\xA8K" + (globals.gHtmlBlocks.push(txt) - 1) + "K\n\n"; + }; + if (options.backslashEscapesHTMLTags) { + text = text.replace(/\\<(\/?[^>]+?)>/g, function(wm, inside) { + return "<" + inside + ">"; + }); + } + for (var i = 0; i < blockTags.length; ++i) { + var opTagPos, rgx1 = new RegExp("^ {0,3}(<" + blockTags[i] + "\\b[^>]*>)", "im"), patLeft = "<" + blockTags[i] + "\\b[^>]*>", patRight = ""; + while ((opTagPos = showdown2.helper.regexIndexOf(text, rgx1)) !== -1) { + var subTexts = showdown2.helper.splitAtIndex(text, opTagPos), newSubText1 = showdown2.helper.replaceRecursiveRegExp(subTexts[1], repFunc, patLeft, patRight, "im"); + if (newSubText1 === subTexts[1]) { + break; + } + text = subTexts[0].concat(newSubText1); + } + } + text = text.replace(/(\n {0,3}(<(hr)\b([^<>])*?\/?>)[ \t]*(?=\n{2,}))/g, showdown2.subParser("hashElement")(text, options, globals)); + text = showdown2.helper.replaceRecursiveRegExp(text, function(txt) { + return "\n\n\xA8K" + (globals.gHtmlBlocks.push(txt) - 1) + "K\n\n"; + }, "^ {0,3}", "gm"); + text = text.replace(/(?:\n\n)( {0,3}(?:<([?%])[^\r]*?\2>)[ \t]*(?=\n{2,}))/g, showdown2.subParser("hashElement")(text, options, globals)); + text = globals.converter._dispatch("hashHTMLBlocks.after", text, options, globals); + return text; + }); + showdown2.subParser("hashHTMLSpans", function(text, options, globals) { + "use strict"; + text = globals.converter._dispatch("hashHTMLSpans.before", text, options, globals); + function hashHTMLSpan(html) { + return "\xA8C" + (globals.gHtmlSpans.push(html) - 1) + "C"; + } + text = text.replace(/<[^>]+?\/>/gi, function(wm) { + return hashHTMLSpan(wm); + }); + text = text.replace(/<([^>]+?)>[\s\S]*?<\/\1>/g, function(wm) { + return hashHTMLSpan(wm); + }); + text = text.replace(/<([^>]+?)\s[^>]+?>[\s\S]*?<\/\1>/g, function(wm) { + return hashHTMLSpan(wm); + }); + text = text.replace(/<[^>]+?>/gi, function(wm) { + return hashHTMLSpan(wm); + }); + text = globals.converter._dispatch("hashHTMLSpans.after", text, options, globals); + return text; + }); + showdown2.subParser("unhashHTMLSpans", function(text, options, globals) { + "use strict"; + text = globals.converter._dispatch("unhashHTMLSpans.before", text, options, globals); + for (var i = 0; i < globals.gHtmlSpans.length; ++i) { + var repText = globals.gHtmlSpans[i], limit = 0; + while (/¨C(\d+)C/.test(repText)) { + var num = RegExp.$1; + repText = repText.replace("\xA8C" + num + "C", globals.gHtmlSpans[num]); + if (limit === 10) { + console.error("maximum nesting of 10 spans reached!!!"); + break; + } + ++limit; + } + text = text.replace("\xA8C" + i + "C", repText); + } + text = globals.converter._dispatch("unhashHTMLSpans.after", text, options, globals); + return text; + }); + showdown2.subParser("hashPreCodeTags", function(text, options, globals) { + "use strict"; + text = globals.converter._dispatch("hashPreCodeTags.before", text, options, globals); + var repFunc = function(wholeMatch, match, left, right) { + var codeblock = left + showdown2.subParser("encodeCode")(match, options, globals) + right; + return "\n\n\xA8G" + (globals.ghCodeBlocks.push({ text: wholeMatch, codeblock }) - 1) + "G\n\n"; + }; + text = showdown2.helper.replaceRecursiveRegExp(text, repFunc, "^ {0,3}]*>\\s*]*>", "^ {0,3}\\s*
", "gim"); + text = globals.converter._dispatch("hashPreCodeTags.after", text, options, globals); + return text; + }); + showdown2.subParser("headers", function(text, options, globals) { + "use strict"; + text = globals.converter._dispatch("headers.before", text, options, globals); + var headerLevelStart = isNaN(parseInt(options.headerLevelStart)) ? 1 : parseInt(options.headerLevelStart), setextRegexH1 = options.smoothLivePreview ? /^(.+)[ \t]*\n={2,}[ \t]*\n+/gm : /^(.+)[ \t]*\n=+[ \t]*\n+/gm, setextRegexH2 = options.smoothLivePreview ? /^(.+)[ \t]*\n-{2,}[ \t]*\n+/gm : /^(.+)[ \t]*\n-+[ \t]*\n+/gm; + text = text.replace(setextRegexH1, function(wholeMatch, m1) { + var spanGamut = showdown2.subParser("spanGamut")(m1, options, globals), hID = options.noHeaderId ? "" : ' id="' + headerId(m1) + '"', hLevel = headerLevelStart, hashBlock = "" + spanGamut + ""; + return showdown2.subParser("hashBlock")(hashBlock, options, globals); + }); + text = text.replace(setextRegexH2, function(matchFound, m1) { + var spanGamut = showdown2.subParser("spanGamut")(m1, options, globals), hID = options.noHeaderId ? "" : ' id="' + headerId(m1) + '"', hLevel = headerLevelStart + 1, hashBlock = "" + spanGamut + ""; + return showdown2.subParser("hashBlock")(hashBlock, options, globals); + }); + var atxStyle = options.requireSpaceBeforeHeadingText ? /^(#{1,6})[ \t]+(.+?)[ \t]*#*\n+/gm : /^(#{1,6})[ \t]*(.+?)[ \t]*#*\n+/gm; + text = text.replace(atxStyle, function(wholeMatch, m1, m2) { + var hText = m2; + if (options.customizedHeaderId) { + hText = m2.replace(/\s?\{([^{]+?)}\s*$/, ""); + } + var span = showdown2.subParser("spanGamut")(hText, options, globals), hID = options.noHeaderId ? "" : ' id="' + headerId(m2) + '"', hLevel = headerLevelStart - 1 + m1.length, header = "" + span + ""; + return showdown2.subParser("hashBlock")(header, options, globals); + }); + function headerId(m) { + var title, prefix; + if (options.customizedHeaderId) { + var match = m.match(/\{([^{]+?)}\s*$/); + if (match && match[1]) { + m = match[1]; + } + } + title = m; + if (showdown2.helper.isString(options.prefixHeaderId)) { + prefix = options.prefixHeaderId; + } else if (options.prefixHeaderId === true) { + prefix = "section-"; + } else { + prefix = ""; + } + if (!options.rawPrefixHeaderId) { + title = prefix + title; + } + if (options.ghCompatibleHeaderId) { + title = title.replace(/ /g, "-").replace(/&/g, "").replace(/¨T/g, "").replace(/¨D/g, "").replace(/[&+$,\/:;=?@"#{}|^¨~\[\]`\\*)(%.!'<>]/g, "").toLowerCase(); + } else if (options.rawHeaderId) { + title = title.replace(/ /g, "-").replace(/&/g, "&").replace(/¨T/g, "\xA8").replace(/¨D/g, "$").replace(/["']/g, "-").toLowerCase(); + } else { + title = title.replace(/[^\w]/g, "").toLowerCase(); + } + if (options.rawPrefixHeaderId) { + title = prefix + title; + } + if (globals.hashLinkCounts[title]) { + title = title + "-" + globals.hashLinkCounts[title]++; + } else { + globals.hashLinkCounts[title] = 1; + } + return title; + } + text = globals.converter._dispatch("headers.after", text, options, globals); + return text; + }); + showdown2.subParser("horizontalRule", function(text, options, globals) { + "use strict"; + text = globals.converter._dispatch("horizontalRule.before", text, options, globals); + var key = showdown2.subParser("hashBlock")("
", options, globals); + text = text.replace(/^ {0,2}( ?-){3,}[ \t]*$/gm, key); + text = text.replace(/^ {0,2}( ?\*){3,}[ \t]*$/gm, key); + text = text.replace(/^ {0,2}( ?_){3,}[ \t]*$/gm, key); + text = globals.converter._dispatch("horizontalRule.after", text, options, globals); + return text; + }); + showdown2.subParser("images", function(text, options, globals) { + "use strict"; + text = globals.converter._dispatch("images.before", text, options, globals); + var inlineRegExp = /!\[([^\]]*?)][ \t]*()\([ \t]??(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*(?:(["'])([^"]*?)\6)?[ \t]?\)/g, crazyRegExp = /!\[([^\]]*?)][ \t]*()\([ \t]?<([^>]*)>(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*(?:(?:(["'])([^"]*?)\6))?[ \t]?\)/g, base64RegExp = /!\[([^\]]*?)][ \t]*()\([ \t]??(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*(?:(["'])([^"]*?)\6)?[ \t]?\)/g, referenceRegExp = /!\[([^\]]*?)] ?(?:\n *)?\[([\s\S]*?)]()()()()()/g, refShortcutRegExp = /!\[([^\[\]]+)]()()()()()/g; + function writeImageTagBase64(wholeMatch, altText, linkId, url, width, height, m5, title) { + url = url.replace(/\s/g, ""); + return writeImageTag(wholeMatch, altText, linkId, url, width, height, m5, title); + } + function writeImageTag(wholeMatch, altText, linkId, url, width, height, m5, title) { + var gUrls = globals.gUrls, gTitles = globals.gTitles, gDims = globals.gDimensions; + linkId = linkId.toLowerCase(); + if (!title) { + title = ""; + } + if (wholeMatch.search(/\(? ?(['"].*['"])?\)$/m) > -1) { + url = ""; + } else if (url === "" || url === null) { + if (linkId === "" || linkId === null) { + linkId = altText.toLowerCase().replace(/ ?\n/g, " "); + } + url = "#" + linkId; + if (!showdown2.helper.isUndefined(gUrls[linkId])) { + url = gUrls[linkId]; + if (!showdown2.helper.isUndefined(gTitles[linkId])) { + title = gTitles[linkId]; + } + if (!showdown2.helper.isUndefined(gDims[linkId])) { + width = gDims[linkId].width; + height = gDims[linkId].height; + } + } else { + return wholeMatch; + } + } + altText = altText.replace(/"/g, """).replace(showdown2.helper.regexes.asteriskDashAndColon, showdown2.helper.escapeCharactersCallback); + url = url.replace(showdown2.helper.regexes.asteriskDashAndColon, showdown2.helper.escapeCharactersCallback); + var result = '' + altText + '", "
"); + }); + text = text.replace(/\b__(\S[\s\S]*?)__\b/g, function(wm, txt) { + return parseInside(txt, "", ""); + }); + text = text.replace(/\b_(\S[\s\S]*?)_\b/g, function(wm, txt) { + return parseInside(txt, "", ""); + }); + } else { + text = text.replace(/___(\S[\s\S]*?)___/g, function(wm, m) { + return /\S$/.test(m) ? parseInside(m, "", "") : wm; + }); + text = text.replace(/__(\S[\s\S]*?)__/g, function(wm, m) { + return /\S$/.test(m) ? parseInside(m, "", "") : wm; + }); + text = text.replace(/_([^\s_][\s\S]*?)_/g, function(wm, m) { + return /\S$/.test(m) ? parseInside(m, "", "") : wm; + }); + } + if (options.literalMidWordAsterisks) { + text = text.replace(/([^*]|^)\B\*\*\*(\S[\s\S]*?)\*\*\*\B(?!\*)/g, function(wm, lead, txt) { + return parseInside(txt, lead + "", ""); + }); + text = text.replace(/([^*]|^)\B\*\*(\S[\s\S]*?)\*\*\B(?!\*)/g, function(wm, lead, txt) { + return parseInside(txt, lead + "", ""); + }); + text = text.replace(/([^*]|^)\B\*(\S[\s\S]*?)\*\B(?!\*)/g, function(wm, lead, txt) { + return parseInside(txt, lead + "", ""); + }); + } else { + text = text.replace(/\*\*\*(\S[\s\S]*?)\*\*\*/g, function(wm, m) { + return /\S$/.test(m) ? parseInside(m, "", "") : wm; + }); + text = text.replace(/\*\*(\S[\s\S]*?)\*\*/g, function(wm, m) { + return /\S$/.test(m) ? parseInside(m, "", "") : wm; + }); + text = text.replace(/\*([^\s*][\s\S]*?)\*/g, function(wm, m) { + return /\S$/.test(m) ? parseInside(m, "", "") : wm; + }); + } + text = globals.converter._dispatch("italicsAndBold.after", text, options, globals); + return text; + }); + showdown2.subParser("lists", function(text, options, globals) { + "use strict"; + function processListItems(listStr, trimTrailing) { + globals.gListLevel++; + listStr = listStr.replace(/\n{2,}$/, "\n"); + listStr += "\xA80"; + var rgx = /(\n)?(^ {0,3})([*+-]|\d+[.])[ \t]+((\[(x|X| )?])?[ \t]*[^\r]+?(\n{1,2}))(?=\n*(¨0| {0,3}([*+-]|\d+[.])[ \t]+))/gm, isParagraphed = /\n[ \t]*\n(?!¨0)/.test(listStr); + if (options.disableForced4SpacesIndentedSublists) { + rgx = /(\n)?(^ {0,3})([*+-]|\d+[.])[ \t]+((\[(x|X| )?])?[ \t]*[^\r]+?(\n{1,2}))(?=\n*(¨0|\2([*+-]|\d+[.])[ \t]+))/gm; + } + listStr = listStr.replace(rgx, function(wholeMatch, m1, m2, m3, m4, taskbtn, checked) { + checked = checked && checked.trim() !== ""; + var item = showdown2.subParser("outdent")(m4, options, globals), bulletStyle = ""; + if (taskbtn && options.tasklists) { + bulletStyle = ' class="task-list-item" style="list-style-type: none;"'; + item = item.replace(/^[ \t]*\[(x|X| )?]/m, function() { + var otp = ' -1) { + item = showdown2.subParser("githubCodeBlocks")(item, options, globals); + item = showdown2.subParser("blockGamut")(item, options, globals); + } else { + item = showdown2.subParser("lists")(item, options, globals); + item = item.replace(/\n$/, ""); + item = showdown2.subParser("hashHTMLBlocks")(item, options, globals); + item = item.replace(/\n\n+/g, "\n\n"); + if (isParagraphed) { + item = showdown2.subParser("paragraphs")(item, options, globals); + } else { + item = showdown2.subParser("spanGamut")(item, options, globals); + } + } + item = item.replace("\xA8A", ""); + item = "" + item + "\n"; + return item; + }); + listStr = listStr.replace(/¨0/g, ""); + globals.gListLevel--; + if (trimTrailing) { + listStr = listStr.replace(/\s+$/, ""); + } + return listStr; + } + function styleStartNumber(list, listType) { + if (listType === "ol") { + var res = list.match(/^ *(\d+)\./); + if (res && res[1] !== "1") { + return ' start="' + res[1] + '"'; + } + } + return ""; + } + function parseConsecutiveLists(list, listType, trimTrailing) { + var olRgx = options.disableForced4SpacesIndentedSublists ? /^ ?\d+\.[ \t]/gm : /^ {0,3}\d+\.[ \t]/gm, ulRgx = options.disableForced4SpacesIndentedSublists ? /^ ?[*+-][ \t]/gm : /^ {0,3}[*+-][ \t]/gm, counterRxg = listType === "ul" ? olRgx : ulRgx, result = ""; + if (list.search(counterRxg) !== -1) { + (function parseCL(txt) { + var pos = txt.search(counterRxg), style2 = styleStartNumber(list, listType); + if (pos !== -1) { + result += "\n\n<" + listType + style2 + ">\n" + processListItems(txt.slice(0, pos), !!trimTrailing) + "\n"; + listType = listType === "ul" ? "ol" : "ul"; + counterRxg = listType === "ul" ? olRgx : ulRgx; + parseCL(txt.slice(pos)); + } else { + result += "\n\n<" + listType + style2 + ">\n" + processListItems(txt, !!trimTrailing) + "\n"; + } + })(list); + } else { + var style = styleStartNumber(list, listType); + result = "\n\n<" + listType + style + ">\n" + processListItems(list, !!trimTrailing) + "\n"; + } + return result; + } + text = globals.converter._dispatch("lists.before", text, options, globals); + text += "\xA80"; + if (globals.gListLevel) { + text = text.replace(/^(( {0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(¨0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm, function(wholeMatch, list, m2) { + var listType = m2.search(/[*+-]/g) > -1 ? "ul" : "ol"; + return parseConsecutiveLists(list, listType, true); + }); + } else { + text = text.replace(/(\n\n|^\n?)(( {0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(¨0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm, function(wholeMatch, m1, list, m3) { + var listType = m3.search(/[*+-]/g) > -1 ? "ul" : "ol"; + return parseConsecutiveLists(list, listType, false); + }); + } + text = text.replace(/¨0/, ""); + text = globals.converter._dispatch("lists.after", text, options, globals); + return text; + }); + showdown2.subParser("metadata", function(text, options, globals) { + "use strict"; + if (!options.metadata) { + return text; + } + text = globals.converter._dispatch("metadata.before", text, options, globals); + function parseMetadataContents(content) { + globals.metadata.raw = content; + content = content.replace(/&/g, "&").replace(/"/g, """); + content = content.replace(/\n {4}/g, " "); + content.replace(/^([\S ]+): +([\s\S]+?)$/gm, function(wm, key, value) { + globals.metadata.parsed[key] = value; + return ""; + }); + } + text = text.replace(/^\s*«««+(\S*?)\n([\s\S]+?)\n»»»+\n/, function(wholematch, format, content) { + parseMetadataContents(content); + return "\xA8M"; + }); + text = text.replace(/^\s*---+(\S*?)\n([\s\S]+?)\n---+\n/, function(wholematch, format, content) { + if (format) { + globals.metadata.format = format; + } + parseMetadataContents(content); + return "\xA8M"; + }); + text = text.replace(/¨M/g, ""); + text = globals.converter._dispatch("metadata.after", text, options, globals); + return text; + }); + showdown2.subParser("outdent", function(text, options, globals) { + "use strict"; + text = globals.converter._dispatch("outdent.before", text, options, globals); + text = text.replace(/^(\t|[ ]{1,4})/gm, "\xA80"); + text = text.replace(/¨0/g, ""); + text = globals.converter._dispatch("outdent.after", text, options, globals); + return text; + }); + showdown2.subParser("paragraphs", function(text, options, globals) { + "use strict"; + text = globals.converter._dispatch("paragraphs.before", text, options, globals); + text = text.replace(/^\n+/g, ""); + text = text.replace(/\n+$/g, ""); + var grafs = text.split(/\n{2,}/g), grafsOut = [], end = grafs.length; + for (var i = 0; i < end; i++) { + var str = grafs[i]; + if (str.search(/¨(K|G)(\d+)\1/g) >= 0) { + grafsOut.push(str); + } else if (str.search(/\S/) >= 0) { + str = showdown2.subParser("spanGamut")(str, options, globals); + str = str.replace(/^([ \t]*)/g, "

"); + str += "

"; + grafsOut.push(str); + } + } + end = grafsOut.length; + for (i = 0; i < end; i++) { + var blockText = "", grafsOutIt = grafsOut[i], codeFlag = false; + while (/¨(K|G)(\d+)\1/.test(grafsOutIt)) { + var delim = RegExp.$1, num = RegExp.$2; + if (delim === "K") { + blockText = globals.gHtmlBlocks[num]; + } else { + if (codeFlag) { + blockText = showdown2.subParser("encodeCode")(globals.ghCodeBlocks[num].text, options, globals); + } else { + blockText = globals.ghCodeBlocks[num].codeblock; + } + } + blockText = blockText.replace(/\$/g, "$$$$"); + grafsOutIt = grafsOutIt.replace(/(\n\n)?¨(K|G)\d+\2(\n\n)?/, blockText); + if (/^]*>\s*]*>/.test(grafsOutIt)) { + codeFlag = true; + } + } + grafsOut[i] = grafsOutIt; + } + text = grafsOut.join("\n"); + text = text.replace(/^\n+/g, ""); + text = text.replace(/\n+$/g, ""); + return globals.converter._dispatch("paragraphs.after", text, options, globals); + }); + showdown2.subParser("runExtension", function(ext, text, options, globals) { + "use strict"; + if (ext.filter) { + text = ext.filter(text, globals.converter, options); + } else if (ext.regex) { + var re = ext.regex; + if (!(re instanceof RegExp)) { + re = new RegExp(re, "g"); + } + text = text.replace(re, ext.replace); + } + return text; + }); + showdown2.subParser("spanGamut", function(text, options, globals) { + "use strict"; + text = globals.converter._dispatch("spanGamut.before", text, options, globals); + text = showdown2.subParser("codeSpans")(text, options, globals); + text = showdown2.subParser("escapeSpecialCharsWithinTagAttributes")(text, options, globals); + text = showdown2.subParser("encodeBackslashEscapes")(text, options, globals); + text = showdown2.subParser("images")(text, options, globals); + text = showdown2.subParser("anchors")(text, options, globals); + text = showdown2.subParser("autoLinks")(text, options, globals); + text = showdown2.subParser("simplifiedAutoLinks")(text, options, globals); + text = showdown2.subParser("emoji")(text, options, globals); + text = showdown2.subParser("underline")(text, options, globals); + text = showdown2.subParser("italicsAndBold")(text, options, globals); + text = showdown2.subParser("strikethrough")(text, options, globals); + text = showdown2.subParser("ellipsis")(text, options, globals); + text = showdown2.subParser("hashHTMLSpans")(text, options, globals); + text = showdown2.subParser("encodeAmpsAndAngles")(text, options, globals); + if (options.simpleLineBreaks) { + if (!/\n\n¨K/.test(text)) { + text = text.replace(/\n+/g, "
\n"); + } + } else { + text = text.replace(/ +\n/g, "
\n"); + } + text = globals.converter._dispatch("spanGamut.after", text, options, globals); + return text; + }); + showdown2.subParser("strikethrough", function(text, options, globals) { + "use strict"; + function parseInside(txt) { + if (options.simplifiedAutoLink) { + txt = showdown2.subParser("simplifiedAutoLinks")(txt, options, globals); + } + return "" + txt + ""; + } + if (options.strikethrough) { + text = globals.converter._dispatch("strikethrough.before", text, options, globals); + text = text.replace(/(?:~){2}([\s\S]+?)(?:~){2}/g, function(wm, txt) { + return parseInside(txt); + }); + text = globals.converter._dispatch("strikethrough.after", text, options, globals); + } + return text; + }); + showdown2.subParser("stripLinkDefinitions", function(text, options, globals) { + "use strict"; + var regex = /^ {0,3}\[([^\]]+)]:[ \t]*\n?[ \t]*\s]+)>?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*\n?[ \t]*(?:(\n*)["|'(](.+?)["|')][ \t]*)?(?:\n+|(?=¨0))/gm, base64Regex = /^ {0,3}\[([^\]]+)]:[ \t]*\n?[ \t]*?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*\n?[ \t]*(?:(\n*)["|'(](.+?)["|')][ \t]*)?(?:\n\n|(?=¨0)|(?=\n\[))/gm; + text += "\xA80"; + var replaceFunc = function(wholeMatch, linkId, url, width, height, blankLines, title) { + linkId = linkId.toLowerCase(); + if (text.toLowerCase().split(linkId).length - 1 < 2) { + return wholeMatch; + } + if (url.match(/^data:.+?\/.+?;base64,/)) { + globals.gUrls[linkId] = url.replace(/\s/g, ""); + } else { + globals.gUrls[linkId] = showdown2.subParser("encodeAmpsAndAngles")(url, options, globals); + } + if (blankLines) { + return blankLines + title; + } else { + if (title) { + globals.gTitles[linkId] = title.replace(/"|'/g, """); + } + if (options.parseImgDimensions && width && height) { + globals.gDimensions[linkId] = { + width, + height + }; + } + } + return ""; + }; + text = text.replace(base64Regex, replaceFunc); + text = text.replace(regex, replaceFunc); + text = text.replace(/¨0/, ""); + return text; + }); + showdown2.subParser("tables", function(text, options, globals) { + "use strict"; + if (!options.tables) { + return text; + } + var tableRgx = /^ {0,3}\|?.+\|.+\n {0,3}\|?[ \t]*:?[ \t]*(?:[-=]){2,}[ \t]*:?[ \t]*\|[ \t]*:?[ \t]*(?:[-=]){2,}[\s\S]+?(?:\n\n|¨0)/gm, singeColTblRgx = /^ {0,3}\|.+\|[ \t]*\n {0,3}\|[ \t]*:?[ \t]*(?:[-=]){2,}[ \t]*:?[ \t]*\|[ \t]*\n( {0,3}\|.+\|[ \t]*\n)*(?:\n|¨0)/gm; + function parseStyles(sLine) { + if (/^:[ \t]*--*$/.test(sLine)) { + return ' style="text-align:left;"'; + } else if (/^--*[ \t]*:[ \t]*$/.test(sLine)) { + return ' style="text-align:right;"'; + } else if (/^:[ \t]*--*[ \t]*:$/.test(sLine)) { + return ' style="text-align:center;"'; + } else { + return ""; + } + } + function parseHeaders(header, style) { + var id = ""; + header = header.trim(); + if (options.tablesHeaderId || options.tableHeaderId) { + id = ' id="' + header.replace(/ /g, "_").toLowerCase() + '"'; + } + header = showdown2.subParser("spanGamut")(header, options, globals); + return "" + header + "\n"; + } + function parseCells(cell, style) { + var subText = showdown2.subParser("spanGamut")(cell, options, globals); + return "" + subText + "\n"; + } + function buildTable(headers, cells) { + var tb = "\n\n\n", tblLgn = headers.length; + for (var i = 0; i < tblLgn; ++i) { + tb += headers[i]; + } + tb += "\n\n\n"; + for (i = 0; i < cells.length; ++i) { + tb += "\n"; + for (var ii = 0; ii < tblLgn; ++ii) { + tb += cells[i][ii]; + } + tb += "\n"; + } + tb += "\n
\n"; + return tb; + } + function parseTable(rawTable) { + var i, tableLines = rawTable.split("\n"); + for (i = 0; i < tableLines.length; ++i) { + if (/^ {0,3}\|/.test(tableLines[i])) { + tableLines[i] = tableLines[i].replace(/^ {0,3}\|/, ""); + } + if (/\|[ \t]*$/.test(tableLines[i])) { + tableLines[i] = tableLines[i].replace(/\|[ \t]*$/, ""); + } + tableLines[i] = showdown2.subParser("codeSpans")(tableLines[i], options, globals); + } + var rawHeaders = tableLines[0].split("|").map(function(s) { + return s.trim(); + }), rawStyles = tableLines[1].split("|").map(function(s) { + return s.trim(); + }), rawCells = [], headers = [], styles = [], cells = []; + tableLines.shift(); + tableLines.shift(); + for (i = 0; i < tableLines.length; ++i) { + if (tableLines[i].trim() === "") { + continue; + } + rawCells.push(tableLines[i].split("|").map(function(s) { + return s.trim(); + })); + } + if (rawHeaders.length < rawStyles.length) { + return rawTable; + } + for (i = 0; i < rawStyles.length; ++i) { + styles.push(parseStyles(rawStyles[i])); + } + for (i = 0; i < rawHeaders.length; ++i) { + if (showdown2.helper.isUndefined(styles[i])) { + styles[i] = ""; + } + headers.push(parseHeaders(rawHeaders[i], styles[i])); + } + for (i = 0; i < rawCells.length; ++i) { + var row = []; + for (var ii = 0; ii < headers.length; ++ii) { + if (showdown2.helper.isUndefined(rawCells[i][ii])) { + } + row.push(parseCells(rawCells[i][ii], styles[ii])); + } + cells.push(row); + } + return buildTable(headers, cells); + } + text = globals.converter._dispatch("tables.before", text, options, globals); + text = text.replace(/\\(\|)/g, showdown2.helper.escapeCharactersCallback); + text = text.replace(tableRgx, parseTable); + text = text.replace(singeColTblRgx, parseTable); + text = globals.converter._dispatch("tables.after", text, options, globals); + return text; + }); + showdown2.subParser("underline", function(text, options, globals) { + "use strict"; + if (!options.underline) { + return text; + } + text = globals.converter._dispatch("underline.before", text, options, globals); + if (options.literalMidWordUnderscores) { + text = text.replace(/\b___(\S[\s\S]*?)___\b/g, function(wm, txt) { + return "" + txt + ""; + }); + text = text.replace(/\b__(\S[\s\S]*?)__\b/g, function(wm, txt) { + return "" + txt + ""; + }); + } else { + text = text.replace(/___(\S[\s\S]*?)___/g, function(wm, m) { + return /\S$/.test(m) ? "" + m + "" : wm; + }); + text = text.replace(/__(\S[\s\S]*?)__/g, function(wm, m) { + return /\S$/.test(m) ? "" + m + "" : wm; + }); + } + text = text.replace(/(_)/g, showdown2.helper.escapeCharactersCallback); + text = globals.converter._dispatch("underline.after", text, options, globals); + return text; + }); + showdown2.subParser("unescapeSpecialChars", function(text, options, globals) { + "use strict"; + text = globals.converter._dispatch("unescapeSpecialChars.before", text, options, globals); + text = text.replace(/¨E(\d+)E/g, function(wholeMatch, m1) { + var charCodeToReplace = parseInt(m1); + return String.fromCharCode(charCodeToReplace); + }); + text = globals.converter._dispatch("unescapeSpecialChars.after", text, options, globals); + return text; + }); + showdown2.subParser("makeMarkdown.blockquote", function(node, globals) { + "use strict"; + var txt = ""; + if (node.hasChildNodes()) { + var children = node.childNodes, childrenLength = children.length; + for (var i = 0; i < childrenLength; ++i) { + var innerTxt = showdown2.subParser("makeMarkdown.node")(children[i], globals); + if (innerTxt === "") { + continue; + } + txt += innerTxt; + } + } + txt = txt.trim(); + txt = "> " + txt.split("\n").join("\n> "); + return txt; + }); + showdown2.subParser("makeMarkdown.codeBlock", function(node, globals) { + "use strict"; + var lang = node.getAttribute("language"), num = node.getAttribute("precodenum"); + return "```" + lang + "\n" + globals.preList[num] + "\n```"; + }); + showdown2.subParser("makeMarkdown.codeSpan", function(node) { + "use strict"; + return "`" + node.innerHTML + "`"; + }); + showdown2.subParser("makeMarkdown.emphasis", function(node, globals) { + "use strict"; + var txt = ""; + if (node.hasChildNodes()) { + txt += "*"; + var children = node.childNodes, childrenLength = children.length; + for (var i = 0; i < childrenLength; ++i) { + txt += showdown2.subParser("makeMarkdown.node")(children[i], globals); + } + txt += "*"; + } + return txt; + }); + showdown2.subParser("makeMarkdown.header", function(node, globals, headerLevel) { + "use strict"; + var headerMark = new Array(headerLevel + 1).join("#"), txt = ""; + if (node.hasChildNodes()) { + txt = headerMark + " "; + var children = node.childNodes, childrenLength = children.length; + for (var i = 0; i < childrenLength; ++i) { + txt += showdown2.subParser("makeMarkdown.node")(children[i], globals); + } + } + return txt; + }); + showdown2.subParser("makeMarkdown.hr", function() { + "use strict"; + return "---"; + }); + showdown2.subParser("makeMarkdown.image", function(node) { + "use strict"; + var txt = ""; + if (node.hasAttribute("src")) { + txt += "![" + node.getAttribute("alt") + "]("; + txt += "<" + node.getAttribute("src") + ">"; + if (node.hasAttribute("width") && node.hasAttribute("height")) { + txt += " =" + node.getAttribute("width") + "x" + node.getAttribute("height"); + } + if (node.hasAttribute("title")) { + txt += ' "' + node.getAttribute("title") + '"'; + } + txt += ")"; + } + return txt; + }); + showdown2.subParser("makeMarkdown.links", function(node, globals) { + "use strict"; + var txt = ""; + if (node.hasChildNodes() && node.hasAttribute("href")) { + var children = node.childNodes, childrenLength = children.length; + txt = "["; + for (var i = 0; i < childrenLength; ++i) { + txt += showdown2.subParser("makeMarkdown.node")(children[i], globals); + } + txt += "]("; + txt += "<" + node.getAttribute("href") + ">"; + if (node.hasAttribute("title")) { + txt += ' "' + node.getAttribute("title") + '"'; + } + txt += ")"; + } + return txt; + }); + showdown2.subParser("makeMarkdown.list", function(node, globals, type) { + "use strict"; + var txt = ""; + if (!node.hasChildNodes()) { + return ""; + } + var listItems = node.childNodes, listItemsLenght = listItems.length, listNum = node.getAttribute("start") || 1; + for (var i = 0; i < listItemsLenght; ++i) { + if (typeof listItems[i].tagName === "undefined" || listItems[i].tagName.toLowerCase() !== "li") { + continue; + } + var bullet = ""; + if (type === "ol") { + bullet = listNum.toString() + ". "; + } else { + bullet = "- "; + } + txt += bullet + showdown2.subParser("makeMarkdown.listItem")(listItems[i], globals); + ++listNum; + } + txt += "\n\n"; + return txt.trim(); + }); + showdown2.subParser("makeMarkdown.listItem", function(node, globals) { + "use strict"; + var listItemTxt = ""; + var children = node.childNodes, childrenLenght = children.length; + for (var i = 0; i < childrenLenght; ++i) { + listItemTxt += showdown2.subParser("makeMarkdown.node")(children[i], globals); + } + if (!/\n$/.test(listItemTxt)) { + listItemTxt += "\n"; + } else { + listItemTxt = listItemTxt.split("\n").join("\n ").replace(/^ {4}$/gm, "").replace(/\n\n+/g, "\n\n"); + } + return listItemTxt; + }); + showdown2.subParser("makeMarkdown.node", function(node, globals, spansOnly) { + "use strict"; + spansOnly = spansOnly || false; + var txt = ""; + if (node.nodeType === 3) { + return showdown2.subParser("makeMarkdown.txt")(node, globals); + } + if (node.nodeType === 8) { + return "\n\n"; + } + if (node.nodeType !== 1) { + return ""; + } + var tagName = node.tagName.toLowerCase(); + switch (tagName) { + case "h1": + if (!spansOnly) { + txt = showdown2.subParser("makeMarkdown.header")(node, globals, 1) + "\n\n"; + } + break; + case "h2": + if (!spansOnly) { + txt = showdown2.subParser("makeMarkdown.header")(node, globals, 2) + "\n\n"; + } + break; + case "h3": + if (!spansOnly) { + txt = showdown2.subParser("makeMarkdown.header")(node, globals, 3) + "\n\n"; + } + break; + case "h4": + if (!spansOnly) { + txt = showdown2.subParser("makeMarkdown.header")(node, globals, 4) + "\n\n"; + } + break; + case "h5": + if (!spansOnly) { + txt = showdown2.subParser("makeMarkdown.header")(node, globals, 5) + "\n\n"; + } + break; + case "h6": + if (!spansOnly) { + txt = showdown2.subParser("makeMarkdown.header")(node, globals, 6) + "\n\n"; + } + break; + case "p": + if (!spansOnly) { + txt = showdown2.subParser("makeMarkdown.paragraph")(node, globals) + "\n\n"; + } + break; + case "blockquote": + if (!spansOnly) { + txt = showdown2.subParser("makeMarkdown.blockquote")(node, globals) + "\n\n"; + } + break; + case "hr": + if (!spansOnly) { + txt = showdown2.subParser("makeMarkdown.hr")(node, globals) + "\n\n"; + } + break; + case "ol": + if (!spansOnly) { + txt = showdown2.subParser("makeMarkdown.list")(node, globals, "ol") + "\n\n"; + } + break; + case "ul": + if (!spansOnly) { + txt = showdown2.subParser("makeMarkdown.list")(node, globals, "ul") + "\n\n"; + } + break; + case "precode": + if (!spansOnly) { + txt = showdown2.subParser("makeMarkdown.codeBlock")(node, globals) + "\n\n"; + } + break; + case "pre": + if (!spansOnly) { + txt = showdown2.subParser("makeMarkdown.pre")(node, globals) + "\n\n"; + } + break; + case "table": + if (!spansOnly) { + txt = showdown2.subParser("makeMarkdown.table")(node, globals) + "\n\n"; + } + break; + case "code": + txt = showdown2.subParser("makeMarkdown.codeSpan")(node, globals); + break; + case "em": + case "i": + txt = showdown2.subParser("makeMarkdown.emphasis")(node, globals); + break; + case "strong": + case "b": + txt = showdown2.subParser("makeMarkdown.strong")(node, globals); + break; + case "del": + txt = showdown2.subParser("makeMarkdown.strikethrough")(node, globals); + break; + case "a": + txt = showdown2.subParser("makeMarkdown.links")(node, globals); + break; + case "img": + txt = showdown2.subParser("makeMarkdown.image")(node, globals); + break; + default: + txt = node.outerHTML + "\n\n"; + } + return txt; + }); + showdown2.subParser("makeMarkdown.paragraph", function(node, globals) { + "use strict"; + var txt = ""; + if (node.hasChildNodes()) { + var children = node.childNodes, childrenLength = children.length; + for (var i = 0; i < childrenLength; ++i) { + txt += showdown2.subParser("makeMarkdown.node")(children[i], globals); + } + } + txt = txt.trim(); + return txt; + }); + showdown2.subParser("makeMarkdown.pre", function(node, globals) { + "use strict"; + var num = node.getAttribute("prenum"); + return "
" + globals.preList[num] + "
"; + }); + showdown2.subParser("makeMarkdown.strikethrough", function(node, globals) { + "use strict"; + var txt = ""; + if (node.hasChildNodes()) { + txt += "~~"; + var children = node.childNodes, childrenLength = children.length; + for (var i = 0; i < childrenLength; ++i) { + txt += showdown2.subParser("makeMarkdown.node")(children[i], globals); + } + txt += "~~"; + } + return txt; + }); + showdown2.subParser("makeMarkdown.strong", function(node, globals) { + "use strict"; + var txt = ""; + if (node.hasChildNodes()) { + txt += "**"; + var children = node.childNodes, childrenLength = children.length; + for (var i = 0; i < childrenLength; ++i) { + txt += showdown2.subParser("makeMarkdown.node")(children[i], globals); + } + txt += "**"; + } + return txt; + }); + showdown2.subParser("makeMarkdown.table", function(node, globals) { + "use strict"; + var txt = "", tableArray = [[], []], headings = node.querySelectorAll("thead>tr>th"), rows = node.querySelectorAll("tbody>tr"), i, ii; + for (i = 0; i < headings.length; ++i) { + var headContent = showdown2.subParser("makeMarkdown.tableCell")(headings[i], globals), allign = "---"; + if (headings[i].hasAttribute("style")) { + var style = headings[i].getAttribute("style").toLowerCase().replace(/\s/g, ""); + switch (style) { + case "text-align:left;": + allign = ":---"; + break; + case "text-align:right;": + allign = "---:"; + break; + case "text-align:center;": + allign = ":---:"; + break; + } + } + tableArray[0][i] = headContent.trim(); + tableArray[1][i] = allign; + } + for (i = 0; i < rows.length; ++i) { + var r = tableArray.push([]) - 1, cols = rows[i].getElementsByTagName("td"); + for (ii = 0; ii < headings.length; ++ii) { + var cellContent = " "; + if (typeof cols[ii] !== "undefined") { + cellContent = showdown2.subParser("makeMarkdown.tableCell")(cols[ii], globals); + } + tableArray[r].push(cellContent); + } + } + var cellSpacesCount = 3; + for (i = 0; i < tableArray.length; ++i) { + for (ii = 0; ii < tableArray[i].length; ++ii) { + var strLen = tableArray[i][ii].length; + if (strLen > cellSpacesCount) { + cellSpacesCount = strLen; + } + } + } + for (i = 0; i < tableArray.length; ++i) { + for (ii = 0; ii < tableArray[i].length; ++ii) { + if (i === 1) { + if (tableArray[i][ii].slice(-1) === ":") { + tableArray[i][ii] = showdown2.helper.padEnd(tableArray[i][ii].slice(-1), cellSpacesCount - 1, "-") + ":"; + } else { + tableArray[i][ii] = showdown2.helper.padEnd(tableArray[i][ii], cellSpacesCount, "-"); + } + } else { + tableArray[i][ii] = showdown2.helper.padEnd(tableArray[i][ii], cellSpacesCount); + } + } + txt += "| " + tableArray[i].join(" | ") + " |\n"; + } + return txt.trim(); + }); + showdown2.subParser("makeMarkdown.tableCell", function(node, globals) { + "use strict"; + var txt = ""; + if (!node.hasChildNodes()) { + return ""; + } + var children = node.childNodes, childrenLength = children.length; + for (var i = 0; i < childrenLength; ++i) { + txt += showdown2.subParser("makeMarkdown.node")(children[i], globals, true); + } + return txt.trim(); + }); + showdown2.subParser("makeMarkdown.txt", function(node) { + "use strict"; + var txt = node.nodeValue; + txt = txt.replace(/ +/g, " "); + txt = txt.replace(/¨NBSP;/g, " "); + txt = showdown2.helper.unescapeHTMLEntities(txt); + txt = txt.replace(/([*_~|`])/g, "\\$1"); + txt = txt.replace(/^(\s*)>/g, "\\$1>"); + txt = txt.replace(/^#/gm, "\\#"); + txt = txt.replace(/^(\s*)([-=]{3,})(\s*)$/, "$1\\$2$3"); + txt = txt.replace(/^( {0,3}\d+)\./gm, "$1\\."); + txt = txt.replace(/^( {0,3})([+-])/gm, "$1\\$2"); + txt = txt.replace(/]([\s]*)\(/g, "\\]$1\\("); + txt = txt.replace(/^ {0,3}\[([\S \t]*?)]:/gm, "\\[$1]:"); + return txt; + }); + var root = this; + if (typeof define === "function" && define.amd) { + define(function() { + "use strict"; + return showdown2; + }); + } else if (typeof module2 !== "undefined" && module2.exports) { + module2.exports = showdown2; + } else { + root.showdown = showdown2; + } + }).call(exports); + } +}); + +// main.ts +__export(exports, { + default: () => MarkdownToHTML +}); +var import_obsidian = __toModule(require("obsidian")); +var showdown = __toModule(require_showdown()); +var DEFAULT_SETTINGS = { + removeBrackets: true, + removeEmphasis: false, + removeTags: false, + removeComments: false +}; +var MarkdownToHTML = class extends import_obsidian.Plugin { + onload() { + return __async(this, null, function* () { + yield this.loadSettings(); + this.addCommand({ + id: "copy-as-html-command", + name: "Copy as HTML command", + editorCallback: (editor) => this.markdownToHTML(editor) + }); + this.addSettingTab(new MarkdownToHTMLSettingTab(this.app, this)); + }); + } + markdownToHTML(editor) { + const converter = new showdown.Converter(); + converter.setFlavor("github"); + converter.setOption("ellipsis", false); + let text = editor.getSelection(); + text = text.replace(/==/g, ""); + text = text.replace(/\^\w+/g, ""); + if (this.settings.removeBrackets) { + text = text.replace(/\[\[(.*?)\]\]/g, "$1"); + } + if (this.settings.removeEmphasis) { + text = text.replace(/[*~]+(\w+)[*~]+/g, "$1"); + } + if (this.settings.removeTags) { + text = text.replace(/#\w+/g, ""); + } + if (this.settings.removeComments) { + text = text.replace(/%%.+%%/g, ""); + } + const html = converter.makeHtml(text).toString(); + const withDivWrapper = ` +
${html}
`; + const blob = new Blob([withDivWrapper], { + type: ["text/plain", "text/html"] + }); + const data = [new ClipboardItem({ + ["text/plain"]: blob, + ["text/html"]: blob + })]; + navigator.clipboard.write(data); + } + loadSettings() { + return __async(this, null, function* () { + this.settings = Object.assign({}, DEFAULT_SETTINGS, yield this.loadData()); + }); + } + saveSettings() { + return __async(this, null, function* () { + yield this.saveData(this.settings); + }); + } + onunload() { + } +}; +var MarkdownToHTMLSettingTab = class extends import_obsidian.PluginSettingTab { + constructor(app, plugin) { + super(app, plugin); + this.plugin = plugin; + } + display() { + let { containerEl } = this; + containerEl.empty(); + new import_obsidian.Setting(containerEl).setName("Remove Wikilink brackets").setDesc("If enabled, removes wikilink brackets from copied text.").addToggle((toggle) => toggle.setValue(this.plugin.settings.removeBrackets).onChange((value) => __async(this, null, function* () { + this.plugin.settings.removeBrackets = value; + yield this.plugin.saveSettings(); + }))); + new import_obsidian.Setting(containerEl).setName("Remove text emphasis").setDesc("If enabled, removes text styling such as bold, italics, and highlights.").addToggle((toggle) => toggle.setValue(this.plugin.settings.removeEmphasis).onChange((value) => __async(this, null, function* () { + this.plugin.settings.removeEmphasis = value; + yield this.plugin.saveSettings(); + }))); + new import_obsidian.Setting(containerEl).setName("Remove hashtags").setDesc("If enabled, removes text immediately after a hashtag.").addToggle((toggle) => toggle.setValue(this.plugin.settings.removeTags).onChange((value) => __async(this, null, function* () { + this.plugin.settings.removeTags = value; + yield this.plugin.saveSettings(); + }))); + new import_obsidian.Setting(containerEl).setName("Remove comments").setDesc("If enabled, removes commented text.").addToggle((toggle) => toggle.setValue(this.plugin.settings.removeComments).onChange((value) => __async(this, null, function* () { + this.plugin.settings.removeComments = value; + yield this.plugin.saveSettings(); + }))); + } +}; +/*! showdown v 2.1.0 - 21-04-2022 */ + +/* nosourcemap */ \ No newline at end of file diff --git a/.obsidian/plugins/copy-as-html/manifest.json b/.obsidian/plugins/copy-as-html/manifest.json new file mode 100644 index 0000000..b1d3207 --- /dev/null +++ b/.obsidian/plugins/copy-as-html/manifest.json @@ -0,0 +1,10 @@ +{ + "id": "copy-as-html", + "name": "Copy as HTML", + "version": "1.1.3", + "minAppVersion": "0.12.0", + "description": "This is a simple plugin that converts the selected markdown to HTML and copies it to the clipboard.", + "author": "Bailey Jennings", + "authorUrl": "https://twitter.com/Bailey_Jennings", + "isDesktopOnly": false +} \ No newline at end of file diff --git a/.obsidian/plugins/obsidian-focus-mode/main.js b/.obsidian/plugins/obsidian-focus-mode/main.js new file mode 100644 index 0000000..acd4bd9 --- /dev/null +++ b/.obsidian/plugins/obsidian-focus-mode/main.js @@ -0,0 +1,182 @@ +/* +THIS IS A GENERATED/BUNDLED FILE BY ROLLUP +if you want to view the source visit the plugins github repository +*/ + +'use strict'; + +var obsidian = require('obsidian'); + +/****************************************************************************** +Copyright (c) Microsoft Corporation. + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. +***************************************************************************** */ + +function __awaiter(thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +} + +class FocusMode extends obsidian.Plugin { + constructor() { + super(...arguments); + this.focusModeActive = false; + this.maximisedClass = "maximised"; + this.focusModeClass = "focus-mode"; + this.superFocusModeClass = "super-focus-mode"; + } + storeSplitsValues() { + // @ts-ignore + this.leftSplitCollapsed = this.app.workspace.leftSplit.collapsed; + // @ts-ignore + this.rightSplitCollapsed = this.app.workspace.rightSplit.collapsed; + } + collapseSplits() { + // @ts-ignore + this.app.workspace.leftSplit.collapse(); + // @ts-ignore + this.app.workspace.rightSplit.collapse(); + } + restoreSplits() { + if (!this.leftSplitCollapsed) { + // @ts-ignore + this.app.workspace.leftSplit.expand(); + } + if (!this.rightSplitCollapsed) { + // @ts-ignore + this.app.workspace.rightSplit.expand(); + } + } + removeExtraneousClasses() { + if ( + // @ts-ignore + this.app.workspace.rootSplit.containerEl.hasClass(this.maximisedClass)) { + // @ts-ignore + this.app.workspace.rootSplit.containerEl.removeClass(this.maximisedClass); + // @ts-ignore + this.app.workspace.onLayoutChange(); + } + if (document.body.classList.contains(this.superFocusModeClass)) { + document.body.classList.remove(this.superFocusModeClass); + } + } + sharedFocusModeCommands() { + this.focusModeActive = true; + // @ts-ignore + this.app.on("active-leaf-change", () => { + try { + // @ts-ignore + this.app.workspace.activeLeaf.view.editor.blur(); + // @ts-ignore + this.app.workspace.activeLeaf.view.editor.focus(); + // @ts-ignore + this.app.workspace.activeLeaf.view.editor.refresh(); + } + catch (ignore) { } + }); + if (!document.body.classList.contains(this.focusModeClass)) { + this.storeSplitsValues(); + } + this.collapseSplits(); + } + enableSuperFocusMode() { + this.sharedFocusModeCommands(); + // @ts-ignore + this.app.workspace.rootSplit.containerEl.toggleClass(this.maximisedClass, + // @ts-ignore + !this.app.workspace.rootSplit.containerEl.hasClass(this.maximisedClass)); + document.body.classList.toggle(this.superFocusModeClass, !document.body.classList.contains(this.superFocusModeClass)); + if (!document.body.classList.contains(this.focusModeClass)) { + document.body.classList.add(this.focusModeClass); + } + if (document.body.classList.contains(this.superFocusModeClass)) { + Array.from(document.querySelectorAll(`.${this.superFocusModeClass} .workspace-split`)).forEach((node) => { + const theNode = node; + const hasActiveKids = theNode.querySelector(".mod-active"); + if (hasActiveKids) { + theNode.style.display = "flex"; + } + else { + theNode.style.display = "none"; + } + }); + } + // @ts-ignore + this.app.workspace.onLayoutChange(); + } + enableFocusMode() { + this.sharedFocusModeCommands(); + this.removeExtraneousClasses(); + document.body.classList.toggle(this.focusModeClass, !document.body.classList.contains(this.focusModeClass)); + } + disableFocusMode() { + this.removeExtraneousClasses(); + if (document.body.classList.contains(this.focusModeClass)) { + document.body.classList.remove(this.focusModeClass); + } + this.restoreSplits(); + Array.from(document.querySelectorAll(".workspace-split")).forEach((node) => { + const theNode = node; + theNode.style.display = "flex"; + }); + this.focusModeActive = false; + } + toggleFocusMode(superFocus = false) { + if (superFocus) { + this.enableSuperFocusMode(); + } + else if (this.focusModeActive) { + this.disableFocusMode(); + } + else { + this.enableFocusMode(); + } + } + onload() { + return __awaiter(this, void 0, void 0, function* () { + console.log("Loading Focus Mode plugin ..."); + this.addRibbonIcon("enter", "Toggle Focus Mode (Shift + Click to show active pane only)", (event) => { + this.toggleFocusMode(event.shiftKey); + }); + this.addCommand({ + id: "toggle-focus-mode", + name: "Toggle Focus Mode", + callback: () => { + this.toggleFocusMode(); + }, + hotkeys: [{ modifiers: ["Alt", "Mod"], key: "Z" }], + }); + this.addCommand({ + id: "toggle-super-focus-mode", + name: "Toggle Super Focus Mode (Active pane only)", + callback: () => { + this.toggleFocusMode(true); + }, + hotkeys: [{ modifiers: ["Alt", "Mod", "Shift"], key: "Z" }], + }); + }); + } + onunload() { + console.log("Unloading Focus Mode plugin ..."); + } +} + +module.exports = FocusMode; + + +/* nosourcemap */ \ No newline at end of file diff --git a/.obsidian/plugins/obsidian-focus-mode/manifest.json b/.obsidian/plugins/obsidian-focus-mode/manifest.json new file mode 100644 index 0000000..4bbe709 --- /dev/null +++ b/.obsidian/plugins/obsidian-focus-mode/manifest.json @@ -0,0 +1,10 @@ +{ + "id": "obsidian-focus-mode", + "name": "Focus Mode", + "version": "1.11.5", + "minAppVersion": "0.9.12", + "description": "Add Focus Mode to Obsidian.", + "author": "ryanpcmcquen", + "authorUrl": "https://github.com/ryanpcmcquen", + "isDesktopOnly": false +} diff --git a/.obsidian/plugins/obsidian-focus-mode/styles.css b/.obsidian/plugins/obsidian-focus-mode/styles.css new file mode 100644 index 0000000..9048424 --- /dev/null +++ b/.obsidian/plugins/obsidian-focus-mode/styles.css @@ -0,0 +1,44 @@ +.focus-mode .cm-s-obsidian .cm-line:not(.cm-active), +.focus-mode .cm-s-obsidian div:not(.CodeMirror-activeline) > .CodeMirror-line { + opacity: 0.85; + filter: saturate(0.85); +} + +.focus-mode .status-bar, +.focus-mode .view-actions, +.focus-mode .view-header-icon, +.focus-mode .inline-title, +.focus-mode .workspace-ribbon:not(.mod-left), +.focus-mode .workspace-split.maximised .workspace-leaf:not(.mod-active), +.focus-mode + .workspace-split.maximised + .workspace-leaf.mod-active + ~ .workspace-split, +.focus-mode.plugin-tabs .stayopen .view-header, +.super-focus-mode .workspace-tabs:not(.mod-active) { + display: none; +} + +.super-focus-mode .workspace-tab-header-container { + padding-left: var(--size-4-8); +} + +.focus-mode .view-content { + height: 100%; +} + +.focus-mode .workspace-split.maximised .workspace-leaf.mod-active { + /* 4px is for scrollbar width: */ + flex-basis: calc(100% - 4px); +} + +.focus-mode .workspace-ribbon, +.focus-mode .sidebar-toggle-button { + visibility: hidden; +} + +.focus-mode .workspace-ribbon::before, +.focus-mode + .side-dock-ribbon-action[aria-label="Toggle Focus Mode (Shift + Click to show active pane only)"] { + visibility: visible; +} diff --git a/.obsidian/plugins/obsidian-image-toolkit/main.js b/.obsidian/plugins/obsidian-image-toolkit/main.js new file mode 100644 index 0000000..6e15c9f --- /dev/null +++ b/.obsidian/plugins/obsidian-image-toolkit/main.js @@ -0,0 +1,3294 @@ +'use strict'; + +var obsidian = require('obsidian'); +var crypto = require('crypto'); + +/****************************************************************************** +Copyright (c) Microsoft Corporation. + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. +***************************************************************************** */ + +function __awaiter(thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +} + +typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) { + var e = new Error(message); + return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e; +}; + +// English +var en = { + // >>>Common Settings: + VIEW_MODE_NAME: 'Choose a mode to view images', + VIEW_MODE_NORMAL: '🖼 Normal', + VIEW_MODE_PIN: '📌 Pin', + RESET: 'reset to default', + // >>>View Trigger Settings: + VIEW_TRIGGER_SETTINGS: 'View trigger', + VIEW_IMAGE_GLOBAL_NAME: 'Click and view an image globally', + VIEW_IMAGE_GLOBAL_DESC: 'You can zoom, rotate, drag, and invert it on the popup layer when clicking an image.', + VIEW_IMAGE_IN_EDITOR_NAME: 'Click and view an image in the Editor Area', + VIEW_IMAGE_IN_EDITOR_DESC: 'Turn on this option if you want to click and view an image in the Editor Area.', + // CPB = COMMUNITY_PLUGINS_BROWSER + VIEW_IMAGE_IN_CPB_NAME: 'Click and view an image in the Community Plugins browser', + VIEW_IMAGE_IN_CPB_DESC: 'Turn on this option if you want to click and view an image in the Community Plugins browser.', + VIEW_IMAGE_WITH_A_LINK_NAME: 'Click and view an image with a link', + VIEW_IMAGE_WITH_A_LINK_DESC: 'Turn on this option if you want to click and view an image with a link. (NOTE: The browser will be opened for you to visit the link and the image will be popped up for being viewed at the same time when you click the image.)', + VIEW_IMAGE_OTHER_NAME: 'Click and view in the other areas except the above', + VIEW_IMAGE_OTHER_DESC: 'Except for the above mentioned, it also supports other areas, like some modal user interface components.', + // >>> PIN_MODE_SETTINGS + PIN_MODE_SETTINGS: "Pin mode", + PIN_MODE_NAME: "📌 Pin an image", + PIN_MODE_DESC: "You can pin an image onto the top of the screen. And have more options by right click. (press Esc to close the image where your mouse cursor is hovering)", + PIN_MAXIMUM_NAME: "The maximum images you can pin", + PIN_COVER_NAME: "Cover mode", + PIN_COVER_DESC: "After those pinned images reach maximum, you can cover the earliest pinned image when you click an image once again.", + PIN_MAXIMUM_NOTICE: "Exceeded maximum images you can pin (non cover mode)", + // >>>View Detail Settings: + VIEW_DETAILS_SETTINGS: 'View details', + IMAGE_MOVE_SPEED_NAME: 'Set the moving speed of the image', + IMAGE_MOVE_SPEED_DESC: 'When you move an image on the popup layer by keyboard (up, down, left, right), the moving speed of the image can be set here.', + IMAGE_TIP_TOGGLE_NAME: "Display the image's zoom number", + IMAGE_TIP_TOGGLE_DESC: "Turn on this option if you want to display the zoom number when you zoom the image.", + IMG_FULL_SCREEN_MODE_NAME: 'Full-screen preview mode', + // preview mode options: + FIT: 'Fit', + FILL: 'Fill', + STRETCH: 'Stretch', + IMG_VIEW_BACKGROUND_COLOR_NAME: "Background color of the previewed image (Only support the image with transparent background)", + // >>>Image Border Settings: + IMAGE_BORDER_SETTINGS: 'Image border', + IMAGE_BORDER_TOGGLE_NAME: "Display the image's border", + IMAGE_BORDER_TOGGLE_DESC: "The clicked image's border can be displayed after you exit previewing and close the popup layer.", + IMAGE_BORDER_WIDTH_NAME: "Image border width", + IMAGE_BORDER_STYLE_NAME: "Image border style", + IMAGE_BORDER_COLOR_NAME: "Image border color", + // IMG_BORDER_WIDTH options: + THIN: 'thin', + MEDIUM: 'medium', + THICK: 'thick', + // IMG_BORDER_STYLE options: + //HIDDEN: 'hidden', + DOTTED: 'dotted', + DASHED: 'dashed', + SOLID: 'solid', + DOUBLE: 'double', + GROOVE: 'groove', + RIDGE: 'ridge', + INSET: 'inset', + OUTSET: 'outset', + // IMAGE_BORDER_COLOR_NAME options: + BLACK: 'black', + BLUE: 'blue', + DARK_GREEN: 'dark green', + GREEN: 'green', + LIME: 'lime', + STEEL_BLUE: 'steel blue', + INDIGO: 'indigo', + PURPLE: 'purple', + GRAY: 'gray', + DARK_RED: 'dark red', + LIGHT_GREEN: 'light green', + BROWN: 'brown', + LIGHT_BLUE: 'light blue', + SILVER: 'silver', + RED: 'red', + PINK: 'pink', + ORANGE: 'orange', + GOLD: 'gold', + YELLOW: 'yellow', + // >>>Gallery Navbar Settings: + GALLERY_NAVBAR_SETTINGS: 'Gallery navbar (experimental)', + GALLERY_NAVBAR_TOGGLE_NAME: "Display gallery navbar", + GALLERY_NAVBAR_TOGGLE_DESC: "All of the images in the current pane view can be displayed at the bottom of the popup layer.", + GALLERY_NAVBAR_DEFAULT_COLOR_NAME: "Background color of the gallery navbar (default state)", + GALLERY_NAVBAR_HOVER_COLOR_NAME: "Background color of the gallery navbar (hovering state)", + GALLERY_IMG_BORDER_TOGGLE_NAME: "Display the selected image on the gallery navbar", + GALLERY_IMG_BORDER_TOGGLE_DESC: "When you select an image, the image's border will be displayed, so you can know which image is currently active.", + GALLERY_IMG_BORDER_ACTIVE_COLOR_NAME: 'Border color of the selected image', + // >>>HOTKEYS_SETTINGS: + HOTKEY_SETTINGS: "Hotkeys", + HOTKEY_SETTINGS_DESC: "📢 You cannot set the same hotkey for 'Move the image' and 'Switch the image' at the same time. (NOT SUPPORT in Pin Mode)", + MOVE_THE_IMAGE_NAME: "Hotkey for moving the image", + MOVE_THE_IMAGE_DESC: "You can move the image on the popup layer by hotkey.", + SWITCH_THE_IMAGE_NAME: "Hotkey for switching the image", + SWITCH_THE_IMAGE_DESC: "You can switch to the previous/next image on the gallery navbar by hotkey. (NOTE: You need to turn on 'Display gallery navbar' first, if you wanna use this hotkey.)", + DOUBLE_CLICK_TOOLBAR_NAME: "Double click", + VIEW_TRIGGER_HOTKEY_NAME: "Hotkey for triggering viewing an image", + VIEW_TRIGGER_HOTKEY_DESC: "When you set 'None', you can directly click and preview an image without holding any modifier keys; otherwise, you must hold the configured modifier keys to click and preview an image.", + // MODIFIER_HOTKEYS + NONE: "None", + CTRL: "Ctrl", + ALT: "Alt", + SHIFT: "Shift", + CTRL_ALT: "Ctrl+Alt", + CTRL_SHIFT: "Ctrl+Shift", + SHIFT_ALT: "Shift+Alt", + CTRL_SHIFT_ALT: "Ctrl+Shift+Alt", + // toolbar icon title + ZOOM_TO_100: "zoom to 100%", + ZOOM_IN: "zoom in", + ZOOM_OUT: "zoom out", + FULL_SCREEN: 'full screen', + REFRESH: "refresh", + ROTATE_LEFT: "rotate left", + ROTATE_RIGHT: "rotate right", + SCALE_X: 'flip along x-axis', + SCALE_Y: 'flip along y-axis', + INVERT_COLOR: 'invert color', + COPY: 'copy', + CLOSE: 'close', + // tip: + COPY_IMAGE_SUCCESS: 'Copy the image successfully!', + COPY_IMAGE_ERROR: 'Fail to copy the image!' +}; + +// 简体中文 +var zhCN = { + VIEW_MODE_NAME: '选择查看模式', + VIEW_MODE_NORMAL: '🖼 普通', + VIEW_MODE_PIN: '📌 贴图', + // >>> 预览触发配置: + VIEW_TRIGGER_SETTINGS: '预览触发配置', + VIEW_IMAGE_GLOBAL_NAME: '支持全局预览图片', + VIEW_IMAGE_GLOBAL_DESC: '开启后,在任何地方点击图片都可以弹出预览界面,可对图片进行缩放、旋转、拖动、和反色等。', + VIEW_IMAGE_IN_EDITOR_NAME: '支持在编辑区域预览图片', + VIEW_IMAGE_IN_EDITOR_DESC: '开启后,支持在编辑区域,点击图片预览。', + // CPB = COMMUNITY_PLUGINS_BROWSER + VIEW_IMAGE_IN_CPB_NAME: '支持在社区插件页面预览图片', + VIEW_IMAGE_IN_CPB_DESC: '开启后,支持在社区插件页面,点击图片预览。', + VIEW_IMAGE_WITH_A_LINK_NAME: '支持预览带链接的图片', + VIEW_IMAGE_WITH_A_LINK_DESC: '开启后,支持点击带链接的图片(注意:点击该图片,会同时打开浏览器访问指定地址和弹出预览图片)', + VIEW_IMAGE_OTHER_NAME: '支持除上述其他地方来预览图片', + VIEW_IMAGE_OTHER_DESC: '除上述支持范围外,还支持一些其他区域,如Modal用户界面组件。', + // >>> PIN_MODE_SETTINGS + PIN_MODE_SETTINGS: "贴图模式设置", + PIN_MODE_NAME: "📌 将所点击的图片贴到屏幕上", + PIN_MODE_DESC: "你可以将当前所点击的图片贴到屏幕上,并且可以通过右击图片选择更多操作(按 Esc 关闭已贴图片的展示)", + PIN_MAXIMUM_NAME: "最大贴图数量", + PIN_COVER_NAME: "覆盖模式", + PIN_COVER_DESC: "当贴图数量达到最大值后,此时再次点击图片,该图片会覆盖最早弹出的那个贴图。", + PIN_MAXIMUM_NOTICE: "超过最大Pin图设置(非覆盖模式)", + // >>>查看细节设置: + VIEW_DETAILS_SETTINGS: '查看细节设置', + IMAGE_MOVE_SPEED_NAME: '图片移动速度设置', + IMAGE_MOVE_SPEED_DESC: '当使用键盘(上、下、左、右)移动图片时,可对图片移动速度进行设置。', + IMAGE_TIP_TOGGLE_NAME: "展示缩放比例提示", + IMAGE_TIP_TOGGLE_DESC: "开启后,当你缩放图片时会展示当前缩放的比例。", + IMG_FULL_SCREEN_MODE_NAME: '全屏预览模式', + // 全屏预览模式 下拉: + FIT: '自适应', + FILL: '填充', + STRETCH: '拉伸', + IMG_VIEW_BACKGROUND_COLOR_NAME: "设置预览图片的背景色(仅对透明背景的图片生效)", + // >>>图片边框设置: + IMAGE_BORDER_SETTINGS: '图片边框设置', + IMAGE_BORDER_TOGGLE_NAME: "展示被点击图片的边框", + IMAGE_BORDER_TOGGLE_DESC: "当离开图片预览和关闭弹出层后,突出展示被点击图片的边框。", + IMAGE_BORDER_WIDTH_NAME: "设置图片边框宽度", + IMAGE_BORDER_STYLE_NAME: "设置图片边框样式", + IMAGE_BORDER_COLOR_NAME: "设置图片边框颜色", + // IMG_BORDER_WIDTH 下拉: + THIN: '较细', + MEDIUM: '正常', + THICK: '较粗', + // IMG_BORDER_STYLE 下拉: + //HIDDEN: '隐藏', + DOTTED: '点状', + DASHED: '虚线', + SOLID: '实线', + DOUBLE: '双线', + GROOVE: '凹槽', + RIDGE: ' 垄状', + INSET: '凹边', + OUTSET: '凸边', + // IMAGE_BORDER_COLOR_NAME 下拉: + BLACK: '黑色', + BLUE: '蓝色', + DARK_GREEN: '深绿色', + GREEN: '绿色', + LIME: '淡黄绿色', + STEEL_BLUE: '钢青色', + INDIGO: '靛蓝色', + PURPLE: '紫色', + GRAY: '灰色', + DARK_RED: '深红色', + LIGHT_GREEN: '浅绿色', + BROWN: '棕色', + LIGHT_BLUE: '浅蓝色', + SILVER: '银色', + RED: '红色', + PINK: '粉红色', + ORANGE: '橘黄色', + GOLD: '金色', + YELLOW: '黄色', + // >>>Gallery Navbar Settings: + GALLERY_NAVBAR_SETTINGS: '图片导航设置 (体验版)', + GALLERY_NAVBAR_TOGGLE_NAME: "展示图片导航", + GALLERY_NAVBAR_TOGGLE_DESC: "当前文档的所有图片会展示在弹出层的底部,可随意切换展示不同图片。", + GALLERY_NAVBAR_DEFAULT_COLOR_NAME: "设置图片导航底栏背景色(默认展示)", + GALLERY_NAVBAR_HOVER_COLOR_NAME: "设置图片导航底栏背景色(鼠标悬浮时)", + GALLERY_IMG_BORDER_TOGGLE_NAME: "展示图片导航上被选中的图片", + GALLERY_IMG_BORDER_TOGGLE_DESC: "当你选中正查看某一图片,对应图片导航底栏上将突出显示该缩略图片的边框。", + GALLERY_IMG_BORDER_ACTIVE_COLOR_NAME: '设置被选中图片的边框色', + // >>>HOTKEYS_SETTINGS: + HOTKEY_SETTINGS: "快捷键设置", + HOTKEY_SETTINGS_DESC: "📢 你无法为'移动图片'和'切换图片'设置相同的快捷键。(不支持贴图模式)", + MOVE_THE_IMAGE_NAME: "为移动图片设置快捷键", + MOVE_THE_IMAGE_DESC: "你可以利用快捷键来移动弹出层上的图片。", + SWITCH_THE_IMAGE_NAME: "为切换图片设置快捷键", + SWITCH_THE_IMAGE_DESC: "你可以利用快捷键来切换在图片导航栏上的图片至上一张/下一张。(注意: 仅当开启“展示图片导航”后,才能使用该快捷键来控制切换图片。)", + DOUBLE_CLICK_TOOLBAR_NAME: "双击", + VIEW_TRIGGER_HOTKEY_NAME: "为触发弹出查看图片设置快捷键", + VIEW_TRIGGER_HOTKEY_DESC: "当你设置为“无”,你可以直接点击预览图片;否则,须按住已配置的修改键(Ctrl、Alt、Shift)才能点击查看某个图片。", + // MODIFIER_HOTKEYS + NONE: "无", + // toolbar icon title + ZOOM_TO_100: "缩放至100%", + ZOOM_IN: "放大", + ZOOM_OUT: "缩小", + FULL_SCREEN: "全屏", + REFRESH: "刷新", + ROTATE_LEFT: "左旋", + ROTATE_RIGHT: "右旋", + SCALE_X: 'x轴翻转', + SCALE_Y: 'y轴翻转', + INVERT_COLOR: '反色', + COPY: '复制', + CLOSE: '关闭', + // tip: + COPY_IMAGE_SUCCESS: '拷贝图片成功!', + COPY_IMAGE_ERROR: '拷贝图片失败!' +}; + +// 繁體中文 +var zhTW = { + // toolbar icon title + ZOOM_IN: "放大", + ZOOM_OUT: "縮小", + FULL_SCREEN: '全螢幕', + REFRESH: "重整", + ROTATE_LEFT: "向左旋轉", + ROTATE_RIGHT: "向右旋轉", + SCALE_X: 'x 軸縮放', + SCALE_Y: 'y 軸縮放', + INVERT_COLOR: '色彩反轉', + COPY: '複製', + COPY_IMAGE_SUCCESS: '成功複製圖片!' +}; + +const localeMap = { + en, + "zh-cn": zhCN, + "zh-tw": zhTW, +}; +const locale = localeMap[obsidian.moment.locale()]; +function t(str) { + if (!locale) { + console.error("[oit] Image toolkit locale not found", obsidian.moment.locale()); + } + return (locale && locale[str]) || en[str]; +} + +var ViewMode; +(function (ViewMode) { + ViewMode["Normal"] = "Normal"; + ViewMode["Pin"] = "Pin"; +})(ViewMode || (ViewMode = {})); +const DEFAULT_VIEW_MODE = ViewMode.Normal; +const OIT_CLASS = { + CONTAINER_ROOT: 'oit', + CONTAINER_NORMAL: 'oit-normal', + CONTAINER_PIN: 'oit-pin', + // the place for storing images + IMG_CONTAINER: 'oit-img-container', + IMG_VIEW: 'oit-img-view', + IMG_TTP: 'oit-img-tip', + IMG_FOOTER: 'oit-img-footer', + IMG_TITLE: 'oit-img-title', + IMG_TITLE_NAME: 'oit-img-title-name', + IMG_TITLE_INDEX: 'oit-img-title-index', + IMG_TOOLBAR: 'oit-img-toolbar', + IMG_PLAYER: 'img-player', + IMG_FULLSCREEN: 'img-fullscreen', +}; +const ZOOM_FACTOR = 0.8; +const IMG_VIEW_MIN = 30; +const ICONS = [{ + id: 'zoom-to-100', + svg: ` 1:1 ` + }]; +const SEPARATOR_SYMBOL = "---"; +const TOOLBAR_CONF = [{ + title: "ZOOM_TO_100", + class: 'toolbar_zoom_to_100', + icon: 'zoom-to-100', + enableToolbarIcon: true, + enableMenu: true, + enableHotKey: true + }, { + title: "ZOOM_IN", + class: 'toolbar_zoom_in', + icon: 'zoom-in', + enableToolbarIcon: true, + enableMenu: false, + enableHotKey: true + }, { + title: "ZOOM_OUT", + class: 'toolbar_zoom_out', + icon: 'zoom-out', + enableToolbarIcon: true, + enableMenu: false, + enableHotKey: true + }, { + title: "FULL_SCREEN", + class: 'toolbar_full_screen', + icon: 'expand', + enableToolbarIcon: true, + enableMenu: true, + enableHotKey: true + }, { + title: "REFRESH", + class: 'toolbar_refresh', + icon: 'refresh-ccw', + enableToolbarIcon: true, + enableMenu: true, + enableHotKey: true + }, { + title: "ROTATE_LEFT", + class: 'toolbar_rotate_left', + icon: 'rotate-ccw', + enableToolbarIcon: true, + enableMenu: true, + enableHotKey: true + }, { + title: "ROTATE_RIGHT", + class: 'toolbar_rotate_right', + icon: 'rotate-cw', + enableToolbarIcon: true, + enableMenu: true, + enableHotKey: true + }, { + title: "SCALE_X", + class: 'toolbar_scale_x', + icon: 'move-horizontal', + enableToolbarIcon: true, + enableMenu: true, + enableHotKey: true + }, { + title: "SCALE_Y", + class: 'toolbar_scale_y', + icon: 'move-vertical', + enableToolbarIcon: true, + enableMenu: true, + enableHotKey: true + }, { + title: "INVERT_COLOR", + class: 'toolbar_invert_color', + icon: 'droplet', + enableToolbarIcon: true, + enableMenu: true, + enableHotKey: true + }, { + title: "COPY", + class: 'toolbar_copy', + icon: 'copy', + enableToolbarIcon: true, + enableMenu: true, + enableHotKey: true + }, { + title: SEPARATOR_SYMBOL, + enableToolbarIcon: false, + enableMenu: true, + enableHotKey: false + }, { + title: "CLOSE", + class: 'toolbar_close', + icon: 'trash', + enableToolbarIcon: false, + enableMenu: true, + enableHotKey: true + }]; +const IMG_FULL_SCREEN_MODE = { + FIT: 'FIT', + FILL: 'FILL', + STRETCH: 'STRETCH' +}; +const VIEW_IMG_SELECTOR = { + EDITOR_AREAS: `.workspace-leaf-content[data-type='markdown'] img,.workspace-leaf-content[data-type='image'] img`, + EDITOR_AREAS_NO_LINK: `.workspace-leaf-content[data-type='markdown'] img:not(a img),.workspace-leaf-content[data-type='image'] img:not(a img)`, + CPB: `.community-modal-details img`, + CPB_NO_LINK: `.community-modal-details img:not(a img)`, + OTHER: `.modal-content img`, + OTHER_NO_LINK: `.modal-content img:not(a img)`, +}; +const IMG_BORDER_WIDTH = { + THIN: 'thin', + MEDIUM: 'medium', + THICK: 'thick' +}; +const IMG_BORDER_STYLE = { + // HIDDEN: 'hidden', + DOTTED: 'dotted', + DASHED: 'dashed', + SOLID: 'solid', + DOUBLE: 'double', + GROOVE: 'groove', + RIDGE: 'ridge', + INSET: 'inset', + OUTSET: 'outset' +}; +// https://www.runoob.com/cssref/css-colorsfull.html +const IMG_BORDER_COLOR = { + BLACK: 'black', + BLUE: 'blue', + DARK_GREEN: 'darkgreen', + GREEN: 'green', + LIME: 'lime', + STEEL_BLUE: 'steelblue', + INDIGO: 'indigo', + PURPLE: 'purple', + GRAY: 'gray', + DARK_RED: 'darkred', + LIGHT_GREEN: 'lightgreen', + BROWN: 'brown', + LIGHT_BLUE: 'lightblue', + SILVER: 'silver', + RED: 'red', + PINK: 'pink', + ORANGE: 'orange', + GOLD: 'gold', + YELLOW: 'yellow' +}; +const GALLERY_NAVBAR_DEFAULT_COLOR = '#0000001A'; // rgba(0, 0, 0, 0.1) +const GALLERY_NAVBAR_HOVER_COLOR = '#0000004D'; // rgba(0, 0, 0, 0.3) +const GALLERY_IMG_BORDER_ACTIVE_COLOR = '#FF0000'; // red +const MODIFIER_HOTKEYS = { + NONE: "NONE", + CTRL: "CTRL", + ALT: "ALT", + SHIFT: "SHIFT", + CTRL_ALT: "CTRL_ALT", + CTRL_SHIFT: "CTRL_SHIFT", + SHIFT_ALT: "SHIFT_ALT", + CTRL_SHIFT_ALT: "CTRL_SHIFT_ALT" +}; +const MOVE_THE_IMAGE = { + CODE: "MOVE_THE_IMAGE", + DEFAULT_HOTKEY: MODIFIER_HOTKEYS.NONE, + SVG: `` +}; +const SWITCH_THE_IMAGE = { + CODE: "SWITCH_THE_IMAGE", + DEFAULT_HOTKEY: MODIFIER_HOTKEYS.CTRL, + SVG: `` +}; +const IMG_DEFAULT_BACKGROUND_COLOR = '#00000000'; + +const DEFAULT_SETTINGS = { + viewMode: ViewMode.Normal, + viewImageInEditor: true, + viewImageInCPB: true, + viewImageWithLink: true, + viewImageOther: true, + // pinMode: false, + pinMaximum: 3, + pinCoverMode: true, + imageMoveSpeed: 10, + imgTipToggle: true, + imgFullScreenMode: IMG_FULL_SCREEN_MODE.FIT, + imgViewBackgroundColor: IMG_DEFAULT_BACKGROUND_COLOR, + imageBorderToggle: false, + imageBorderWidth: IMG_BORDER_WIDTH.MEDIUM, + imageBorderStyle: IMG_BORDER_STYLE.SOLID, + imageBorderColor: IMG_BORDER_COLOR.RED, + galleryNavbarToggle: true, + galleryNavbarDefaultColor: GALLERY_NAVBAR_DEFAULT_COLOR, + galleryNavbarHoverColor: GALLERY_NAVBAR_HOVER_COLOR, + galleryImgBorderActive: true, + galleryImgBorderActiveColor: GALLERY_IMG_BORDER_ACTIVE_COLOR, + // hotkeys conf + moveTheImageHotkey: MOVE_THE_IMAGE.DEFAULT_HOTKEY, + switchTheImageHotkey: SWITCH_THE_IMAGE.DEFAULT_HOTKEY, + doubleClickToolbar: TOOLBAR_CONF[3].class, + viewTriggerHotkey: MODIFIER_HOTKEYS.NONE +}; +class ImageToolkitSettingTab extends obsidian.PluginSettingTab { + constructor(app, plugin) { + super(app, plugin); + this.plugin = plugin; + } + display() { + let { containerEl } = this; + containerEl.empty(); + // Common Settings: + this.displayCommonSettings(containerEl); + // View Trigger Settings: + this.displayViewTriggerSettings(containerEl); + // Pin Mode Settings: + this.displayPinModeSettings(containerEl); + //region >>> VIEW_DETAILS_SETTINGS + new obsidian.Setting(containerEl).setName(t("VIEW_DETAILS_SETTINGS")).setHeading(); + let imgMoveSpeedScaleText; + new obsidian.Setting(containerEl) + .setName(t("IMAGE_MOVE_SPEED_NAME")) + .setDesc(t("IMAGE_MOVE_SPEED_DESC")) + .addSlider(slider => slider + .setLimits(1, 30, 1) + .setValue(this.plugin.settings.imageMoveSpeed) + .onChange((value) => __awaiter(this, void 0, void 0, function* () { + imgMoveSpeedScaleText.innerText = " " + value.toString(); + this.plugin.settings.imageMoveSpeed = value; + this.plugin.saveSettings(); + }))) + .settingEl.createDiv('', (el) => { + imgMoveSpeedScaleText = el; + el.style.minWidth = "2.3em"; + el.style.textAlign = "right"; + el.innerText = " " + this.plugin.settings.imageMoveSpeed.toString(); + }); + new obsidian.Setting(containerEl) + .setName(t("IMAGE_TIP_TOGGLE_NAME")) + .setDesc(t("IMAGE_TIP_TOGGLE_DESC")) + .addToggle(toggle => toggle + .setValue(this.plugin.settings.imgTipToggle) + .onChange((value) => __awaiter(this, void 0, void 0, function* () { + this.plugin.settings.imgTipToggle = value; + yield this.plugin.saveSettings(); + }))); + new obsidian.Setting(containerEl) + .setName(t("IMG_FULL_SCREEN_MODE_NAME")) + .addDropdown((dropdown) => __awaiter(this, void 0, void 0, function* () { + for (const key in IMG_FULL_SCREEN_MODE) { + // @ts-ignore + dropdown.addOption(key, t(key)); + } + dropdown.setValue(this.plugin.settings.imgFullScreenMode); + dropdown.onChange((option) => __awaiter(this, void 0, void 0, function* () { + this.plugin.settings.imgFullScreenMode = option; + yield this.plugin.saveSettings(); + })); + })); + new obsidian.Setting(containerEl) + .setName(t("IMG_VIEW_BACKGROUND_COLOR_NAME")) + .addColorPicker(picker => { + picker + .setValue(this.plugin.settings.imgViewBackgroundColor || DEFAULT_SETTINGS.imgViewBackgroundColor) + .onChange((value) => __awaiter(this, void 0, void 0, function* () { + this.plugin.settings.imgViewBackgroundColor = value; + yield this.plugin.saveSettings(); + })); + }) + .addExtraButton(button => { + button.setIcon('rotate-ccw') + .setTooltip(t('RESET')) + .onClick(() => __awaiter(this, void 0, void 0, function* () { + this.plugin.settings.imgViewBackgroundColor = DEFAULT_SETTINGS.imgViewBackgroundColor; + yield this.plugin.saveSettings(); + this.display(); + })); + }); + //endregion + //region >>> IMAGE_BORDER_SETTINGS + new obsidian.Setting(containerEl).setName(t("IMAGE_BORDER_SETTINGS")).setHeading(); + new obsidian.Setting(containerEl) + .setName(t("IMAGE_BORDER_TOGGLE_NAME")) + .setDesc(t("IMAGE_BORDER_TOGGLE_DESC")) + .addToggle(toggle => toggle + .setValue(this.plugin.settings.imageBorderToggle) + .onChange((value) => __awaiter(this, void 0, void 0, function* () { + this.plugin.settings.imageBorderToggle = value; + yield this.plugin.saveSettings(); + }))); + new obsidian.Setting(containerEl) + .setName(t("IMAGE_BORDER_WIDTH_NAME")) + .addDropdown((dropdown) => __awaiter(this, void 0, void 0, function* () { + for (const key in IMG_BORDER_WIDTH) { + // @ts-ignore + dropdown.addOption(IMG_BORDER_WIDTH[key], t(key)); + } + dropdown.setValue(this.plugin.settings.imageBorderWidth); + dropdown.onChange((option) => __awaiter(this, void 0, void 0, function* () { + this.plugin.settings.imageBorderWidth = option; + yield this.plugin.saveSettings(); + })); + })); + new obsidian.Setting(containerEl) + .setName(t("IMAGE_BORDER_STYLE_NAME")) + .addDropdown((dropdown) => __awaiter(this, void 0, void 0, function* () { + for (const key in IMG_BORDER_STYLE) { + // @ts-ignore + dropdown.addOption(IMG_BORDER_STYLE[key], t(key)); + } + dropdown.setValue(this.plugin.settings.imageBorderStyle); + dropdown.onChange((option) => __awaiter(this, void 0, void 0, function* () { + this.plugin.settings.imageBorderStyle = option; + yield this.plugin.saveSettings(); + })); + })); + new obsidian.Setting(containerEl) + .setName(t("IMAGE_BORDER_COLOR_NAME")) + .addDropdown((dropdown) => __awaiter(this, void 0, void 0, function* () { + for (const key in IMG_BORDER_COLOR) { + // @ts-ignore + dropdown.addOption(IMG_BORDER_COLOR[key], t(key)); + } + dropdown.setValue(this.plugin.settings.imageBorderColor); + dropdown.onChange((option) => __awaiter(this, void 0, void 0, function* () { + this.plugin.settings.imageBorderColor = option; + yield this.plugin.saveSettings(); + })); + })); + //endregion + //region >>> GALLERY_NAVBAR_SETTINGS + //let galleryNavbarDefaultColorSetting: Setting, galleryNavbarHoverColorSetting: Setting, + // galleryImgBorderToggleSetting: Setting, galleryImgBorderActiveColorSetting: Setting; + new obsidian.Setting(containerEl).setName(t("GALLERY_NAVBAR_SETTINGS")).setHeading(); + new obsidian.Setting(containerEl) + .setName(t("GALLERY_NAVBAR_TOGGLE_NAME")) + .setDesc(t("GALLERY_NAVBAR_TOGGLE_DESC")) + .addToggle(toggle => toggle + .setValue(this.plugin.settings.galleryNavbarToggle) + .onChange((value) => __awaiter(this, void 0, void 0, function* () { + this.plugin.settings.galleryNavbarToggle = value; + this.switchSettingsDisabled(!value, galleryNavbarDefaultColorSetting, galleryNavbarHoverColorSetting, galleryImgBorderToggleSetting, galleryImgBorderActiveColorSetting); + yield this.plugin.saveSettings(); + }))); + const galleryNavbarDefaultColorSetting = new obsidian.Setting(containerEl) + .setName(t("GALLERY_NAVBAR_DEFAULT_COLOR_NAME")) + .addColorPicker(picker => { + picker + .setValue(this.plugin.settings.galleryNavbarDefaultColor || DEFAULT_SETTINGS.galleryNavbarDefaultColor) + .onChange((value) => __awaiter(this, void 0, void 0, function* () { + this.plugin.settings.galleryNavbarDefaultColor = value; + yield this.plugin.saveSettings(); + })); + }) + .addExtraButton(button => { + button.setIcon('rotate-ccw') + .setTooltip(t('RESET')) + .onClick(() => __awaiter(this, void 0, void 0, function* () { + this.plugin.settings.galleryNavbarDefaultColor = DEFAULT_SETTINGS.galleryNavbarDefaultColor; + yield this.plugin.saveSettings(); + this.display(); + })); + }); + const galleryNavbarHoverColorSetting = new obsidian.Setting(containerEl) + .setName(t("GALLERY_NAVBAR_HOVER_COLOR_NAME")) + .addColorPicker(picker => { + picker + .setValue(this.plugin.settings.galleryNavbarHoverColor || DEFAULT_SETTINGS.galleryNavbarHoverColor) + .onChange((value) => __awaiter(this, void 0, void 0, function* () { + this.plugin.settings.galleryNavbarHoverColor = value; + yield this.plugin.saveSettings(); + })); + }) + .addExtraButton(button => { + button.setIcon('rotate-ccw') + .setTooltip(t('RESET')) + .onClick(() => __awaiter(this, void 0, void 0, function* () { + this.plugin.settings.galleryNavbarHoverColor = DEFAULT_SETTINGS.galleryNavbarHoverColor; + yield this.plugin.saveSettings(); + this.display(); + })); + }); + const galleryImgBorderToggleSetting = new obsidian.Setting(containerEl) + .setName(t("GALLERY_IMG_BORDER_TOGGLE_NAME")) + .setDesc(t("GALLERY_IMG_BORDER_TOGGLE_DESC")) + .addToggle(toggle => toggle + .setValue(this.plugin.settings.galleryImgBorderActive) + .onChange((value) => __awaiter(this, void 0, void 0, function* () { + this.plugin.settings.galleryImgBorderActive = value; + yield this.plugin.saveSettings(); + }))); + const galleryImgBorderActiveColorSetting = new obsidian.Setting(containerEl) + .setName(t("GALLERY_IMG_BORDER_ACTIVE_COLOR_NAME")) + .addColorPicker(picker => { + picker.setValue(this.plugin.settings.galleryImgBorderActiveColor || DEFAULT_SETTINGS.galleryImgBorderActiveColor) + .onChange((value) => __awaiter(this, void 0, void 0, function* () { + this.plugin.settings.galleryImgBorderActiveColor = value; + yield this.plugin.saveSettings(); + })); + }) + .addExtraButton(button => { + button.setIcon('rotate-ccw') + .setTooltip(t('RESET')) + .onClick(() => __awaiter(this, void 0, void 0, function* () { + this.plugin.settings.imgViewBackgroundColor = DEFAULT_SETTINGS.galleryImgBorderActiveColor; + yield this.plugin.saveSettings(); + this.display(); + })); + }); + this.switchSettingsDisabled(!this.plugin.settings.galleryNavbarToggle, galleryNavbarDefaultColorSetting, galleryNavbarHoverColorSetting, galleryImgBorderToggleSetting, galleryImgBorderActiveColorSetting); + //endregion + //region >>> HOTKEYS_SETTINGS + new obsidian.Setting(containerEl).setName(t("HOTKEY_SETTINGS")).setDesc(t("HOTKEY_SETTINGS_DESC")).setHeading(); + if (this.plugin.settings.moveTheImageHotkey === this.plugin.settings.switchTheImageHotkey) { + this.plugin.settings.moveTheImageHotkey = MOVE_THE_IMAGE.DEFAULT_HOTKEY; + } + const moveTheImageSetting = new obsidian.Setting(containerEl) + .setName(t("MOVE_THE_IMAGE_NAME")) + .setDesc(t("MOVE_THE_IMAGE_DESC")) + .addDropdown((dropdown) => __awaiter(this, void 0, void 0, function* () { + dropdown.addOptions(this.getDropdownOptions()); + dropdown.setValue(this.plugin.settings.moveTheImageHotkey); + dropdown.onChange((option) => __awaiter(this, void 0, void 0, function* () { + this.plugin.settings.moveTheImageHotkey = option; + this.checkDropdownOptions(MOVE_THE_IMAGE.CODE, switchTheImageSetting); + yield this.plugin.saveSettings(); + })); + })).then((setting) => { + setting.addExtraButton(button => { + button.setIcon('plus').setDisabled(true); + }); + setting.controlEl.appendChild(obsidian.sanitizeHTMLToDom(MOVE_THE_IMAGE.SVG)); + }); + if (this.plugin.settings.switchTheImageHotkey === this.plugin.settings.moveTheImageHotkey) { + this.plugin.settings.switchTheImageHotkey = SWITCH_THE_IMAGE.DEFAULT_HOTKEY; + } + const switchTheImageSetting = new obsidian.Setting(containerEl) + .setName(t("SWITCH_THE_IMAGE_NAME")) + .setDesc(t("SWITCH_THE_IMAGE_DESC")) + .addDropdown((dropdown) => __awaiter(this, void 0, void 0, function* () { + dropdown.addOptions(this.getDropdownOptions()); + dropdown.setValue(this.plugin.settings.switchTheImageHotkey); + dropdown.onChange((option) => __awaiter(this, void 0, void 0, function* () { + this.plugin.settings.switchTheImageHotkey = option; + this.checkDropdownOptions(SWITCH_THE_IMAGE.CODE, moveTheImageSetting); + yield this.plugin.saveSettings(); + })); + })).then((setting) => { + setting.addExtraButton(button => { + button.setIcon('plus').setDisabled(true); + }); + setting.controlEl.appendChild(obsidian.sanitizeHTMLToDom(SWITCH_THE_IMAGE.SVG)); + }); + if (switchTheImageSetting) { + this.checkDropdownOptions(MOVE_THE_IMAGE.CODE, switchTheImageSetting); + } + if (moveTheImageSetting) { + this.checkDropdownOptions(SWITCH_THE_IMAGE.CODE, moveTheImageSetting); + } + new obsidian.Setting(containerEl) + .setName(t("DOUBLE_CLICK_TOOLBAR_NAME")) + .addDropdown((dropdown) => __awaiter(this, void 0, void 0, function* () { + for (const conf of TOOLBAR_CONF) { + if (!conf.enableHotKey) + continue; + // @ts-ignore + dropdown.addOption(conf.class, t(conf.title)); + } + dropdown.setValue(this.plugin.settings.doubleClickToolbar); + dropdown.onChange((option) => __awaiter(this, void 0, void 0, function* () { + this.plugin.settings.doubleClickToolbar = option; + yield this.plugin.saveSettings(); + })); + })); + new obsidian.Setting(containerEl) + .setName(t("VIEW_TRIGGER_HOTKEY_NAME")) + .setDesc(t("VIEW_TRIGGER_HOTKEY_DESC")) + .addDropdown((dropdown) => __awaiter(this, void 0, void 0, function* () { + dropdown.addOptions(this.getDropdownOptions()); + dropdown.setValue(this.plugin.settings.viewTriggerHotkey); + dropdown.onChange((option) => __awaiter(this, void 0, void 0, function* () { + this.plugin.settings.viewTriggerHotkey = option; + yield this.plugin.saveSettings(); + })); + })); + //endregion + } + displayCommonSettings(containerEl) { + new obsidian.Setting(containerEl) + .setName(t("VIEW_MODE_NAME")) + .addDropdown((dropdown) => __awaiter(this, void 0, void 0, function* () { + for (const key in ViewMode) { + // @ts-ignore + dropdown.addOption(key, t('VIEW_MODE_' + key.toUpperCase())); + } + dropdown.setValue(this.plugin.settings.viewMode); + dropdown.onChange((option) => __awaiter(this, void 0, void 0, function* () { + yield this.plugin.switchViewMode(option); + })); + })); + } + displayViewTriggerSettings(containerEl) { + new obsidian.Setting(containerEl).setName(t("VIEW_TRIGGER_SETTINGS")).setHeading(); + new obsidian.Setting(containerEl) + .setName(t("VIEW_IMAGE_IN_EDITOR_NAME")) + .setDesc(t("VIEW_IMAGE_IN_EDITOR_DESC")) + .addToggle(toggle => toggle + .setValue(this.plugin.settings.viewImageInEditor) + .onChange((value) => __awaiter(this, void 0, void 0, function* () { + this.plugin.settings.viewImageInEditor = value; + this.plugin.refreshViewTrigger(); + yield this.plugin.saveSettings(); + }))); + new obsidian.Setting(containerEl) + .setName(t("VIEW_IMAGE_IN_CPB_NAME")) + .setDesc(t("VIEW_IMAGE_IN_CPB_DESC")) + .addToggle(toggle => toggle + .setValue(this.plugin.settings.viewImageInCPB) + .onChange((value) => __awaiter(this, void 0, void 0, function* () { + this.plugin.settings.viewImageInCPB = value; + this.plugin.refreshViewTrigger(); + yield this.plugin.saveSettings(); + }))); + new obsidian.Setting(containerEl) + .setName(t("VIEW_IMAGE_WITH_A_LINK_NAME")) + .setDesc(t("VIEW_IMAGE_WITH_A_LINK_DESC")) + .addToggle(toggle => toggle + .setValue(this.plugin.settings.viewImageWithLink) + .onChange((value) => __awaiter(this, void 0, void 0, function* () { + this.plugin.settings.viewImageWithLink = value; + this.plugin.refreshViewTrigger(); + yield this.plugin.saveSettings(); + }))); + new obsidian.Setting(containerEl) + .setName(t("VIEW_IMAGE_OTHER_NAME")) + .setDesc(t("VIEW_IMAGE_OTHER_DESC")) + .addToggle(toggle => toggle + .setValue(this.plugin.settings.viewImageOther) + .onChange((value) => __awaiter(this, void 0, void 0, function* () { + this.plugin.settings.viewImageOther = value; + this.plugin.refreshViewTrigger(); + yield this.plugin.saveSettings(); + }))); + } + displayPinModeSettings(containerEl) { + //region >>> PIN_MODE_SETTINGS + let pinMaximumSetting; + new obsidian.Setting(containerEl).setName(t("PIN_MODE_SETTINGS")).setHeading(); + /*new Setting(containerEl) + .setName(t("PIN_MODE_NAME")) + .setDesc(t("PIN_MODE_DESC")) + .addToggle(toggle => toggle + .setValue(this.plugin.settings.pinMode) + .onChange(async (value) => { + this.plugin.settings.pinMode = value; + this.switchSettingsDisabled(!value, pinMaximumSetting, pinCoverSetting); + //this.plugin.togglePinMode(value); + await this.plugin.saveSettings(); + }));*/ + let pinMaximumScaleText; + pinMaximumSetting = new obsidian.Setting(containerEl) + .setName(t("PIN_MAXIMUM_NAME")) + .addSlider(slider => slider + .setLimits(1, 5, 1) + .setValue(this.plugin.settings.pinMaximum) + .onChange((value) => __awaiter(this, void 0, void 0, function* () { + pinMaximumScaleText.innerText = " " + value.toString(); + this.plugin.settings.pinMaximum = value; + // this.plugin.containerView?.setPinMaximum(value); + this.plugin.saveSettings(); + }))); + pinMaximumSetting.settingEl.createDiv('', (el) => { + pinMaximumScaleText = el; + el.style.minWidth = "2.3em"; + el.style.textAlign = "right"; + el.innerText = " " + this.plugin.settings.pinMaximum.toString(); + }); + new obsidian.Setting(containerEl) + .setName(t("PIN_COVER_NAME")) + .setDesc(t("PIN_COVER_DESC")) + .addToggle(toggle => toggle + .setValue(this.plugin.settings.pinCoverMode) + .onChange((value) => __awaiter(this, void 0, void 0, function* () { + this.plugin.settings.pinCoverMode = value; + yield this.plugin.saveSettings(); + }))); + //this.switchSettingsDisabled(!this.plugin.settings.pinMode, pinMaximumSetting, pinCoverSetting); + //endregion + } + switchSettingsDisabled(disabled, ...settings) { + for (const setting of settings) { + setting === null || setting === void 0 ? void 0 : setting.setDisabled(disabled); + } + } + getDropdownOptions() { + let options = {}; + for (const key in MODIFIER_HOTKEYS) { + //@ts-ignore + options[key] = t(key); + } + return options; + } + checkDropdownOptions(code, setting) { + if (!setting || !setting.controlEl) + return; + const optionElList = setting.controlEl.getElementsByClassName('dropdown')[0].getElementsByTagName('option'); + for (let i = 0, size = optionElList.length; i < size; i++) { + if (code === MOVE_THE_IMAGE.CODE) { + optionElList[i].disabled = optionElList[i].value === this.plugin.settings.moveTheImageHotkey; + } + else if (code === SWITCH_THE_IMAGE.CODE) { + optionElList[i].disabled = optionElList[i].value === this.plugin.settings.switchTheImageHotkey; + } + } + } +} + +/** + * ts class object: image operating status + */ +class ImgStatusCto { + constructor() { + // true: the popup layer of viewing image is displayed + this.popup = false; + // whether the image is being dragged + this.dragging = false; + // keybord pressing status + this.arrowUp = false; + this.arrowDown = false; + this.arrowLeft = false; + this.arrowRight = false; + this.fullScreen = false; + this.activeImgZIndex = 0; /*--layer-status-bar*/ + this.clickCount = 0; + } +} +/** + * ts class object: image information including all html elements + */ +class ImgInfoCto { + constructor() { + this.imgList = new Array(); + this.getPopupImgNum = () => { + let num = 0; + for (const imgCto of this.imgList) { + if (imgCto.popup) + num++; + } + return num; + }; + } +} +class ImgCto { + constructor(index, mtime, imgViewEl) { + this.popup = false; + this.zIndex = 0; + this.curWidth = 0; // image's current width + this.curHeight = 0; + this.realWidth = 0; // image's real width + this.realHeight = 0; + this.left = 0; // margin-left + this.top = 0; // margin-top + this.moveX = 0; // 鼠标相对于图片的位置 + this.moveY = 0; + this.rotate = 0; // rotateDeg + this.invertColor = false; + this.scaleX = false; // scaleX(-1) + this.scaleY = false; // scaleY(-1) + this.fullScreen = false; // whether the image is being previewed in full-screen mode + this.defaultImgStyle = { + transform: 'none', + filter: 'none', + mixBlendMode: 'normal', + borderWidth: '', + borderStyle: '', + borderColor: '' + }; + this.index = index; + this.mtime = mtime; + this.imgViewEl = imgViewEl; + } +} + +/** + * Image utility class + */ +class ImgUtil { + static copyText(text) { + navigator.clipboard.writeText(text) + .then(() => { + //console.log('copyText:', copyText); + }) + .catch(err => { + console.error('copy text error', err); + }); + } + static copyImage(imgEle, width, height) { + let image = new Image(); + image.crossOrigin = 'anonymous'; + image.src = imgEle.src; + image.onload = () => { + const canvas = document.createElement('canvas'); + canvas.width = image.width; + canvas.height = image.height; + const ctx = canvas.getContext('2d'); + ctx.fillStyle = '#fff'; + ctx.fillRect(0, 0, canvas.width, canvas.height); + ctx.drawImage(image, 0, 0); + try { + canvas.toBlob((blob) => __awaiter(this, void 0, void 0, function* () { + yield navigator.clipboard.write([new ClipboardItem({ "image/png": blob })]) + .then(() => { + new obsidian.Notice(t("COPY_IMAGE_SUCCESS")); + }, () => { + new obsidian.Notice(t("COPY_IMAGE_ERROR")); + }); + })); + } + catch (error) { + new obsidian.Notice(t("COPY_IMAGE_ERROR")); + console.error(error); + } + }; + image.onerror = () => { + new obsidian.Notice(t("COPY_IMAGE_ERROR")); + }; + } +} +ImgUtil.calculateImgZoomSize = (realImg, imgCto, windowWidth, windowHeight) => { + if (!windowWidth) { + windowWidth = document.documentElement.clientWidth || document.body.clientWidth; + } + if (!windowHeight) { + windowHeight = (document.documentElement.clientHeight || document.body.clientHeight) - 100; + } + const windowZoomWidth = windowWidth * ZOOM_FACTOR; + const windowZoomHeight = windowHeight * ZOOM_FACTOR; + let tempWidth = realImg.width, tempHeight = realImg.height; + if (realImg.height > windowZoomHeight) { + tempHeight = windowZoomHeight; + if ((tempWidth = tempHeight / realImg.height * realImg.width) > windowZoomWidth) { + tempWidth = windowZoomWidth; + } + } + else if (realImg.width > windowZoomWidth) { + tempWidth = windowZoomWidth; + tempHeight = tempWidth / realImg.width * realImg.height; + } + tempHeight = tempWidth * realImg.height / realImg.width; + // cache image info: curWidth, curHeight, realWidth, realHeight, left, top + imgCto.left = (windowWidth - tempWidth) / 2; + imgCto.top = (windowHeight - tempHeight) / 2; + imgCto.curWidth = tempWidth; + imgCto.curHeight = tempHeight; + imgCto.realWidth = realImg.width; + imgCto.realHeight = realImg.height; + /* console.log('calculateImgZoomSize', 'realImg: ' + realImg.width + ',' + realImg.height, + 'tempSize: ' + tempWidth + ',' + tempHeight, + 'windowZoomSize: ' + windowZoomWidth + ',' + windowZoomHeight, + 'windowSize: ' + windowWidth + ',' + windowHeight); */ + return imgCto; +}; +/** + * zoom an image + * @param ratio + * @param targetImgInfo + * @param offsetSize + * @param actualSize + * @returns + */ +ImgUtil.zoom = (ratio, targetImgInfo, offsetSize, actualSize) => { + let zoomRatio; + if (!actualSize) { + const zoomInFlag = ratio > 0; + ratio = zoomInFlag ? 1 + ratio : 1 / (1 - ratio); + zoomRatio = targetImgInfo.curWidth * ratio / targetImgInfo.realWidth; + } + // Snap to 100% zoom when we pass over it + const curRatio = targetImgInfo.curWidth / targetImgInfo.realWidth; + if (actualSize || (curRatio < 1 && zoomRatio > 1) || (curRatio > 1 && zoomRatio < 1)) { + // set zoom ratio to 100% + zoomRatio = 1; + // reduce snap offset ratio accordingly + ratio = 1 / curRatio; + } + let newWidth = targetImgInfo.realWidth * zoomRatio; + let newHeight = targetImgInfo.realHeight * zoomRatio; + if (IMG_VIEW_MIN >= newWidth || IMG_VIEW_MIN >= newHeight) { + // set minimum width or height + if (IMG_VIEW_MIN >= newWidth) { + newWidth = IMG_VIEW_MIN; + newHeight = (newWidth * targetImgInfo.realHeight) / targetImgInfo.realWidth; + } + else { + newHeight = IMG_VIEW_MIN; + newWidth = (newHeight * targetImgInfo.realWidth) / targetImgInfo.realHeight; + } + ratio = 1; + } + const left = targetImgInfo.left + offsetSize.offsetX * (1 - ratio); + const top = targetImgInfo.top + offsetSize.offsetY * (1 - ratio); + // cache image info: curWidth, curHeight, left, top + targetImgInfo.curWidth = newWidth; + targetImgInfo.curHeight = newHeight; + targetImgInfo.left = left; + targetImgInfo.top = top; + // return { newWidth, left, top }; + return targetImgInfo; +}; +ImgUtil.transform = (targetImgInfo) => { + let transform = 'rotate(' + targetImgInfo.rotate + 'deg)'; + if (targetImgInfo.scaleX) { + transform += ' scaleX(-1)'; + } + if (targetImgInfo.scaleY) { + transform += ' scaleY(-1)'; + } + targetImgInfo.imgViewEl.style.setProperty('transform', transform); +}; +ImgUtil.rotate = (degree, targetImgInfo) => { + targetImgInfo.imgViewEl.style.setProperty('transform', 'rotate(' + (targetImgInfo.rotate += degree) + 'deg)'); +}; +ImgUtil.invertImgColor = (imgEle, open) => { + if (open) { + imgEle.style.setProperty('filter', 'invert(1) hue-rotate(180deg)'); + imgEle.style.setProperty('mix-blend-mode', 'screen'); + } + else { + imgEle.style.setProperty('filter', 'none'); + imgEle.style.setProperty('mix-blend-mode', 'normal'); + } + // open ? imgEle.addClass('image-toolkit-img-invert') : imgEle.removeClass('image-toolkit-img-invert'); +}; + +class ContainerView { + constructor(plugin) { + this.lastClickedImgDefaultStyle = { + borderWidth: '', + borderStyle: '', + borderColor: '' + }; + this.imgGlobalStatus = new ImgStatusCto(); + this.imgInfo = new ImgInfoCto(); + this.getViewMode = () => { + return this.plugin.settings.viewMode; + }; + this.isPinMode = () => { + return ViewMode.Pin === this.getViewMode(); + }; + this.isNormalMode = () => { + return ViewMode.Normal === this.getViewMode(); + }; + this.setMenuView = (menuView) => { + this.menuView = menuView; + }; + this.getPlugin = () => { + return this.plugin; + }; + this.getLastClickedImgEl = () => { + return this.lastClickedImgEl; + }; + this.getActiveImg = () => { + return this.imgGlobalStatus.activeImg; + }; + this.getDoc = () => { + return this.doc; + }; + /*public setPinMaximum = (val: number) => { + this.pinMaximum = val; + }*/ + this.getOitContainerViewEl = () => { + return this.imgInfo.imgContainerEl; + }; + this.getParentContainerEl = (targetEl) => { + if (!targetEl) { + return this.parentContainerEl; + } + if (!this.parentContainerEl) { + this.parentContainerEl = targetEl.matchParent('body'); + this.doc = this.parentContainerEl.ownerDocument; + } + return this.parentContainerEl; + }; + //region ================== Container View & Init ======================== + /** + * Render when clicking an image (core step) + * @param targetEl clicked image's element + * @returns + */ + this.renderContainer = (targetEl) => { + if (!this.checkStatus()) + return; + const matchedImg = this.initContainerView(targetEl, this.getParentContainerEl(targetEl)); + if (!matchedImg) + return; + this.openOitContainerView(matchedImg); + this.renderGalleryNavbar(); + this.refreshImg(matchedImg, targetEl.src, targetEl.alt); + matchedImg.mtime = new Date().getTime(); + }; + /** + * initContainerDom -> + * @param targetEl + * @param parentContainerEl targetEl's body + */ + this.initContainerView = (targetEl, parentContainerEl) => { + const matchedImg = this.initContainerDom(parentContainerEl); + if (!matchedImg) + return null; + matchedImg.targetOriginalImgEl = targetEl; + this.restoreBorderForLastClickedImg(); + this.initDefaultData(matchedImg, window.getComputedStyle(targetEl)); + this.addBorderForLastClickedImg(targetEl); + this.addOrRemoveEvents(matchedImg, true); // add events + return matchedImg; + }; + this.removeOitContainerView = () => { + var _a; + this.restoreBorderForLastClickedImg(); + this.removeGalleryNavbar(); + (_a = this.imgInfo.oitContainerEl) === null || _a === void 0 ? void 0 : _a.remove(); + this.imgInfo.oitContainerEl = null; + this.imgInfo.imgContainerEl = null; + this.imgGlobalStatus.dragging = false; + this.imgGlobalStatus.popup = false; + this.imgGlobalStatus.activeImgZIndex = 0; + this.imgGlobalStatus.fullScreen = false; + this.imgGlobalStatus.activeImg = null; + // clear imgList + this.imgInfo.imgList.length = 0; + }; + this.checkStatus = () => { + const viewMode = this.plugin.getViewMode(); + if (!viewMode) + return false; + // none of popped-up-images + if (!this.imgGlobalStatus.popup) + return true; + // Pin mode && Cover mode + if (this.isPinMode() && this.plugin.settings.pinCoverMode) + return true; + // configured max images > current pop-up images + if (this.getConfiguredPinMaximum() > this.imgInfo.getPopupImgNum()) + return true; + new obsidian.Notice(t("PIN_MAXIMUM_NOTICE")); + return false; + }; + this.getConfiguredPinMaximum = () => { + if (this.isPinMode()) + return this.plugin.settings.pinMaximum; + return 1; + }; + this.initDefaultData = (matchedImg, targetImgStyle) => { + if (targetImgStyle) { + matchedImg.defaultImgStyle.transform = 'none'; + matchedImg.defaultImgStyle.filter = targetImgStyle.filter; + matchedImg.defaultImgStyle.mixBlendMode = targetImgStyle.mixBlendMode; + matchedImg.defaultImgStyle.borderWidth = targetImgStyle.borderWidth; + matchedImg.defaultImgStyle.borderStyle = targetImgStyle.borderStyle; + matchedImg.defaultImgStyle.borderColor = targetImgStyle.borderColor; + this.lastClickedImgDefaultStyle.borderWidth = targetImgStyle.borderWidth; + this.lastClickedImgDefaultStyle.borderStyle = targetImgStyle.borderStyle; + this.lastClickedImgDefaultStyle.borderColor = targetImgStyle.borderColor; + } + this.imgGlobalStatus.dragging = false; + this.imgGlobalStatus.arrowUp = false; + this.imgGlobalStatus.arrowDown = false; + this.imgGlobalStatus.arrowLeft = false; + this.imgGlobalStatus.arrowRight = false; + matchedImg.invertColor = false; + matchedImg.scaleX = false; + matchedImg.scaleY = false; + matchedImg.fullScreen = false; + if (!this.imgGlobalStatus.popup) { + this.resetClickTimer(); + } + }; + /** + * set 'data-oit-target' and lastClickedImgEl + * @param targetEl + */ + this.setLastClickedImg = (targetEl) => { + if (!targetEl) + return; + // 'data-oit-target' is set for locating current image + targetEl.setAttribute('data-oit-target', '1'); + this.lastClickedImgEl = targetEl; + }; + //endregion + //region ================== (Original) Image Border ======================== + this.addBorderForLastClickedImg = (targetEl) => { + this.setLastClickedImg(targetEl); + if (!targetEl || !this.plugin.settings.imageBorderToggle) + return; + const lastClickedImgStyle = targetEl === null || targetEl === void 0 ? void 0 : targetEl.style; + if (!lastClickedImgStyle) + return; + lastClickedImgStyle.setProperty('border-width', this.plugin.settings.imageBorderWidth); + lastClickedImgStyle.setProperty('border-style', this.plugin.settings.imageBorderStyle); + lastClickedImgStyle.setProperty('border-color', this.plugin.settings.imageBorderColor); + }; + /** + * remove 'data-oit-target' + * restore default border style + */ + this.restoreBorderForLastClickedImg = () => { + if (!this.lastClickedImgEl) + return; + this.lastClickedImgEl.removeAttribute('data-oit-target'); + const lastClickedImgStyle = this.lastClickedImgEl.style; + if (lastClickedImgStyle) { + lastClickedImgStyle.setProperty('border-width', this.lastClickedImgDefaultStyle.borderWidth); + lastClickedImgStyle.setProperty('border-style', this.lastClickedImgDefaultStyle.borderStyle); + lastClickedImgStyle.setProperty('border-color', this.lastClickedImgDefaultStyle.borderColor); + } + }; + //endregion + //region ================== Image ======================== + this.updateImgViewElAndList = (imgInfo) => { + if (!(imgInfo === null || imgInfo === void 0 ? void 0 : imgInfo.imgContainerEl)) + return; + const pinMaximum = this.getConfiguredPinMaximum(); + const imgNum = this.imgInfo.imgList.length; + if (pinMaximum < imgNum) { + // remove all imgViewEl and imgList + imgInfo.imgContainerEl.innerHTML = ''; + // clear imgList + imgInfo.imgList.length = 0; + } + // let isUpdate: boolean = false; + const curTime = new Date().getTime(); + for (let i = imgNum; i < pinMaximum; i++) { + //
``
+ let imgViewEl = createEl('img'); + imgViewEl.addClass(OIT_CLASS.IMG_VIEW); + imgViewEl.hidden = true; // hide 'oit-img-view' for now + imgViewEl.dataset.index = i + ''; // set data-index + this.setImgViewDefaultBackground(imgViewEl); + imgInfo.imgContainerEl.appendChild(imgViewEl); + // cache imgList + imgInfo.imgList.push(new ImgCto(i, curTime, imgViewEl)); + // isUpdate = true; + } + }; + this.getMatchedImg = () => { + let earliestImg; + for (const img of this.imgInfo.imgList) { + if (!earliestImg || earliestImg.mtime > img.mtime) + earliestImg = img; + if (img.popup) + continue; + return img; + } + if (this.plugin.settings.pinCoverMode) { + return earliestImg; + } + return null; + }; + /** + * it may from: renderContainerView(), switch GalleryNavbarView, click toolbar_refresh + * @param imgCto + * @param imgSrc + * @param imgAlt + * @param imgTitleIndex + */ + this.refreshImg = (imgCto, imgSrc, imgAlt, imgTitleIndex) => { + if (!imgSrc) + imgSrc = imgCto.imgViewEl.src; + if (!imgAlt) + imgAlt = imgCto.imgViewEl.alt; + this.renderImgTitle(imgAlt, imgTitleIndex); + if (imgSrc) { + if (imgCto.refreshImgInterval) { + clearInterval(imgCto.refreshImgInterval); + imgCto.refreshImgInterval = null; + } + let realImg = new Image(); + realImg.src = imgSrc; + imgCto.refreshImgInterval = setInterval((realImg) => { + var _a, _b; + if (realImg.width > 0 || realImg.height > 0) { + clearInterval(imgCto.refreshImgInterval); + imgCto.refreshImgInterval = null; + this.setImgViewPosition(ImgUtil.calculateImgZoomSize(realImg, imgCto, (_a = this.parentContainerEl) === null || _a === void 0 ? void 0 : _a.clientWidth, (_b = this.parentContainerEl) === null || _b === void 0 ? void 0 : _b.clientHeight), 0); + this.renderImgView(imgCto.imgViewEl, imgSrc, imgAlt); + this.renderImgTip(imgCto); + imgCto.imgViewEl.style.setProperty('transform', imgCto.defaultImgStyle.transform); + imgCto.imgViewEl.style.setProperty('filter', imgCto.defaultImgStyle.filter); + imgCto.imgViewEl.style.setProperty('mix-blend-mode', imgCto.defaultImgStyle.mixBlendMode); + } + }, 40, realImg); + } + }; + this.renderImgTitle = (name, index) => { + }; + this.setImgViewPosition = (imgZoomSize, rotate) => { + const imgViewEl = imgZoomSize.imgViewEl; + if (!imgViewEl) + return; + if (imgZoomSize) { + imgViewEl.setAttribute('width', imgZoomSize.curWidth + 'px'); + imgViewEl.style.setProperty('margin-top', imgZoomSize.top + 'px', 'important'); + imgViewEl.style.setProperty('margin-left', imgZoomSize.left + 'px', 'important'); + } + const rotateDeg = rotate ? rotate : 0; + imgViewEl.style.transform = 'rotate(' + rotateDeg + 'deg)'; + imgZoomSize.rotate = rotateDeg; + }; + this.renderImgView = (imgViewEl, src, alt) => { + if (!imgViewEl) + return; + imgViewEl.setAttribute('src', src); + imgViewEl.setAttribute('alt', alt); + imgViewEl.hidden = !src && !alt; + }; + this.renderImgTip = (activeImg) => { + if (!activeImg) + activeImg = this.imgGlobalStatus.activeImg; + if (activeImg && this.imgInfo.imgTipEl && activeImg.realWidth > 0 && activeImg.curWidth > 0) { + if (this.imgInfo.imgTipTimeout) { + clearTimeout(this.imgInfo.imgTipTimeout); + } + if (this.plugin.settings.imgTipToggle) { + this.imgInfo.imgTipEl.hidden = false; // display 'oit-img-tip' + const ratio = activeImg.curWidth * 100 / activeImg.realWidth; + const isSingleDigit = 10 > ratio; + const width = isSingleDigit ? 20 : 40; + const left = activeImg.left + activeImg.curWidth / 2 - width / 2; + const top = activeImg.top + activeImg.curHeight / 2 - 10; + this.imgInfo.imgTipEl.style.setProperty("width", width + 'px'); + this.imgInfo.imgTipEl.style.setProperty("font-size", isSingleDigit || 100 >= activeImg.curWidth ? 'xx-small' : 'x-small'); + this.imgInfo.imgTipEl.style.setProperty("left", left + 'px'); + this.imgInfo.imgTipEl.style.setProperty("top", top + 'px'); + this.imgInfo.imgTipEl.style.setProperty("z-index", activeImg.zIndex + ''); + this.imgInfo.imgTipEl.setText(parseInt(ratio + '') + '%'); + this.imgInfo.imgTipTimeout = setTimeout(() => { + this.imgInfo.imgTipEl.hidden = true; + }, 1000); + } + else { + this.imgInfo.imgTipEl.hidden = true; // hide 'oit-img-tip' + this.imgInfo.imgTipTimeout = null; + } + } + }; + this.setImgViewDefaultBackgroundForImgList = () => { + for (const imgCto of this.imgInfo.imgList) { + this.setImgViewDefaultBackground(imgCto.imgViewEl); + } + }; + this.setImgViewDefaultBackground = (imgViewEl) => { + if (!imgViewEl) + return; + if (this.plugin.settings.imgViewBackgroundColor && IMG_DEFAULT_BACKGROUND_COLOR != this.plugin.settings.imgViewBackgroundColor) { + imgViewEl.removeClass('img-default-background'); + imgViewEl.style.setProperty('background-color', this.plugin.settings.imgViewBackgroundColor); + } + else { + imgViewEl.addClass('img-default-background'); + imgViewEl.style.removeProperty('background-color'); + } + }; + this.setActiveImgZIndex = (activeImg) => { + }; + //endregion + //region ================== Gallery NavBar ======================== + this.switchImageOnGalleryNavBar = (event, next) => { + }; + this.renderGalleryNavbar = () => { + }; + this.removeGalleryNavbar = () => { + }; + //endregion + //region ================== full screen ======================== + /** + * full-screen mode + */ + this.showPlayerImg = (activeImg) => { + if (!activeImg && !(activeImg = this.imgGlobalStatus.activeImg)) + return; + this.imgGlobalStatus.fullScreen = true; + activeImg.fullScreen = true; + // activeImg.imgViewEl.style.setProperty('display', 'none', 'important'); // hide imgViewEl + // this.imgInfoCto.imgFooterEl?.style.setProperty('display', 'none'); // hide 'oit-img-footer' + // show the img-player + this.imgInfo.imgPlayerEl.style.setProperty('display', 'block'); + this.imgInfo.imgPlayerEl.style.setProperty('z-index', (this.imgGlobalStatus.activeImgZIndex + 10) + ''); + this.imgInfo.imgPlayerEl.addEventListener('click', this.closePlayerImg); + const windowWidth = this.doc.documentElement.clientWidth || this.doc.body.clientWidth; + const windowHeight = this.doc.documentElement.clientHeight || this.doc.body.clientHeight; + let newWidth, newHeight; + let top = 0; + if (IMG_FULL_SCREEN_MODE.STRETCH == this.plugin.settings.imgFullScreenMode) { + newWidth = windowWidth + 'px'; + newHeight = windowHeight + 'px'; + } + else if (IMG_FULL_SCREEN_MODE.FILL == this.plugin.settings.imgFullScreenMode) { + newWidth = '100%'; + newHeight = '100%'; + } + else { + // fit + const widthRatio = windowWidth / activeImg.realWidth; + const heightRatio = windowHeight / activeImg.realHeight; + if (widthRatio <= heightRatio) { + newWidth = windowWidth; + newHeight = widthRatio * activeImg.realHeight; + } + else { + newHeight = windowHeight; + newWidth = heightRatio * activeImg.realWidth; + } + top = (windowHeight - newHeight) / 2; + newWidth = newWidth + 'px'; + newHeight = newHeight + 'px'; + } + const imgPlayerImgViewEl = this.imgInfo.imgPlayerImgViewEl; + if (imgPlayerImgViewEl) { + imgPlayerImgViewEl.setAttribute('src', activeImg.imgViewEl.src); + imgPlayerImgViewEl.setAttribute('alt', activeImg.imgViewEl.alt); + imgPlayerImgViewEl.setAttribute('width', newWidth); + imgPlayerImgViewEl.setAttribute('height', newHeight); + imgPlayerImgViewEl.style.setProperty('margin-top', top + 'px'); + //this.imgInfo.imgPlayerImgViewEl.style.setProperty('margin-left', left + 'px'); + this.setImgViewDefaultBackground(imgPlayerImgViewEl); + } + }; + /** + * close full screen + */ + this.closePlayerImg = () => { + for (const imgCto of this.imgInfo.imgList) { + if (!imgCto.fullScreen) + continue; + // show the popped up image + // imgCto.imgViewEl?.style.setProperty('display', 'block', 'important'); + // this.imgInfoCto.imgFooterEl?.style.setProperty('display', 'block'); + } + // hide full screen + if (this.imgInfo.imgPlayerEl) { + this.imgInfo.imgPlayerEl.style.setProperty('display', 'none'); // hide 'img-player' + this.imgInfo.imgPlayerEl.removeEventListener('click', this.closePlayerImg); + } + if (this.imgInfo.imgPlayerImgViewEl) { + this.imgInfo.imgPlayerImgViewEl.setAttribute('src', ''); + this.imgInfo.imgPlayerImgViewEl.setAttribute('alt', ''); + } + this.imgGlobalStatus.fullScreen = false; + }; + //endregion + //region ================== events ======================== + this.addOrRemoveEvents = (matchedImg, isAdd) => { + if (isAdd) { + if (!this.imgGlobalStatus.popup) { + this.doc.addEventListener('keydown', this.triggerKeydown); + this.doc.addEventListener('keyup', this.triggerKeyup); + } + if (this.isNormalMode()) { + // click event: hide container view + this.imgInfo.oitContainerEl.addEventListener('click', this.closeContainerView); + } + matchedImg.imgViewEl.addEventListener('mouseenter', this.mouseenterImgView); + matchedImg.imgViewEl.addEventListener('mouseleave', this.mouseleaveImgView); + // drag the image via mouse + matchedImg.imgViewEl.addEventListener('mousedown', this.mousedownImgView); + matchedImg.imgViewEl.addEventListener('mouseup', this.mouseupImgView); + // zoom the image via mouse wheel + matchedImg.imgViewEl.addEventListener('mousewheel', this.mousewheelViewContainer, { passive: true }); + } + else { + if (!this.imgGlobalStatus.popup) { + this.doc.removeEventListener('keydown', this.triggerKeydown); + this.doc.removeEventListener('keyup', this.triggerKeyup); + if (this.imgGlobalStatus.clickTimer) { + clearTimeout(this.imgGlobalStatus.clickTimer); + this.imgGlobalStatus.clickTimer = null; + this.imgGlobalStatus.clickCount = 0; + } + } + if (!this.isPinMode()) { + this.imgInfo.oitContainerEl.removeEventListener('click', this.closeContainerView); + } + matchedImg.imgViewEl.removeEventListener('mouseenter', this.mouseenterImgView); + matchedImg.imgViewEl.removeEventListener('mouseleave', this.mouseleaveImgView); + matchedImg.imgViewEl.removeEventListener('mousedown', this.mousedownImgView); + matchedImg.imgViewEl.removeEventListener('mouseup', this.mouseupImgView); + matchedImg.imgViewEl.removeEventListener('mousewheel', this.mousewheelViewContainer); + if (matchedImg.refreshImgInterval) { + clearInterval(matchedImg.refreshImgInterval); + matchedImg.refreshImgInterval = null; + } + } + }; + this.triggerKeyup = (event) => { + // console.log('keyup', event, event.key); + const key = event.key; + if (!key) + return; + if (!('Escape' === key)) { + event.preventDefault(); + event.stopPropagation(); + } + switch (key) { + case 'Escape': + // close full screen, hide container view + this.imgGlobalStatus.fullScreen ? this.closePlayerImg() : this.closeContainerView(); + break; + case 'ArrowUp': + this.imgGlobalStatus.arrowUp = false; + break; + case 'ArrowDown': + this.imgGlobalStatus.arrowDown = false; + break; + case 'ArrowLeft': + this.imgGlobalStatus.arrowLeft = false; + // switch to the previous image on the gallery navBar + this.switchImageOnGalleryNavBar(event, false); + break; + case 'ArrowRight': + this.imgGlobalStatus.arrowRight = false; + // switch to the next image on the gallery navBar + this.switchImageOnGalleryNavBar(event, true); + break; + } + }; + /** + * move the image by keyboard + * @param event + */ + this.triggerKeydown = (event) => { + //console.log('keydown', event, event.key, this.imgStatus); + if (this.isPinMode()) + return; + event.preventDefault(); + event.stopPropagation(); + if (this.imgGlobalStatus.arrowUp && this.imgGlobalStatus.arrowLeft) { + this.moveImgViewByHotkey(event, 'UP_LEFT'); + return; + } + else if (this.imgGlobalStatus.arrowUp && this.imgGlobalStatus.arrowRight) { + this.moveImgViewByHotkey(event, 'UP_RIGHT'); + return; + } + else if (this.imgGlobalStatus.arrowDown && this.imgGlobalStatus.arrowLeft) { + this.moveImgViewByHotkey(event, 'DOWN_LEFT'); + return; + } + else if (this.imgGlobalStatus.arrowDown && this.imgGlobalStatus.arrowRight) { + this.moveImgViewByHotkey(event, 'DOWN_RIGHT'); + return; + } + switch (event.key) { + case 'ArrowUp': + this.imgGlobalStatus.arrowUp = true; + this.moveImgViewByHotkey(event, 'UP'); + break; + case 'ArrowDown': + this.imgGlobalStatus.arrowDown = true; + this.moveImgViewByHotkey(event, 'DOWN'); + break; + case 'ArrowLeft': + this.imgGlobalStatus.arrowLeft = true; + this.moveImgViewByHotkey(event, 'LEFT'); + break; + case 'ArrowRight': + this.imgGlobalStatus.arrowRight = true; + this.moveImgViewByHotkey(event, 'RIGHT'); + break; + } + }; + this.moveImgViewByHotkey = (event, orientation) => { + if (!orientation || !this.imgGlobalStatus.popup || !this.checkHotkeySettings(event, this.plugin.settings.moveTheImageHotkey)) + return; + switch (orientation) { + case 'UP': + this.mousemoveImgView(null, { offsetX: 0, offsetY: -this.plugin.settings.imageMoveSpeed }); + break; + case 'DOWN': + this.mousemoveImgView(null, { offsetX: 0, offsetY: this.plugin.settings.imageMoveSpeed }); + break; + case 'LEFT': + this.mousemoveImgView(null, { offsetX: -this.plugin.settings.imageMoveSpeed, offsetY: 0 }); + break; + case 'RIGHT': + this.mousemoveImgView(null, { offsetX: this.plugin.settings.imageMoveSpeed, offsetY: 0 }); + break; + case 'UP_LEFT': + this.mousemoveImgView(null, { + offsetX: -this.plugin.settings.imageMoveSpeed, + offsetY: -this.plugin.settings.imageMoveSpeed + }); + break; + case 'UP_RIGHT': + this.mousemoveImgView(null, { + offsetX: this.plugin.settings.imageMoveSpeed, + offsetY: -this.plugin.settings.imageMoveSpeed + }); + break; + case 'DOWN_LEFT': + this.mousemoveImgView(null, { + offsetX: -this.plugin.settings.imageMoveSpeed, + offsetY: this.plugin.settings.imageMoveSpeed + }); + break; + case 'DOWN_RIGHT': + this.mousemoveImgView(null, { + offsetX: this.plugin.settings.imageMoveSpeed, + offsetY: this.plugin.settings.imageMoveSpeed + }); + break; + } + }; + this.checkHotkeySettings = (event, hotkey) => { + // console.log("[oit] checkHotkeySettings: ", event.ctrlKey, event.altKey, event.shiftKey) + switch (hotkey) { + case "NONE": + return !event.ctrlKey && !event.altKey && !event.shiftKey; + case "CTRL": + return event.ctrlKey && !event.altKey && !event.shiftKey; + case "ALT": + return !event.ctrlKey && event.altKey && !event.shiftKey; + case "SHIFT": + return !event.ctrlKey && !event.altKey && event.shiftKey; + case "CTRL_ALT": + return event.ctrlKey && event.altKey && !event.shiftKey; + case "CTRL_SHIFT": + return event.ctrlKey && !event.altKey && event.shiftKey; + case "SHIFT_ALT": + return !event.ctrlKey && event.altKey && event.shiftKey; + case "CTRL_SHIFT_ALT": + return event.ctrlKey && event.altKey && event.shiftKey; + } + return false; + }; + this.mouseenterImgView = (event) => { + this.resetClickTimer(); + event.stopPropagation(); + event.preventDefault(); + this.getAndUpdateActiveImg(event); + // console.log('mouseenterImgView', event, this.imgGlobalStatus.activeImg); + }; + this.mousedownImgView = (event) => { + // console.log('mousedownImgView', event, this.imgGlobalStatus.activeImg, event.button); + event.stopPropagation(); + event.preventDefault(); + const activeImg = this.getAndUpdateActiveImg(event); + if (!activeImg) + return; + if (0 == event.button) { // left click + this.setClickTimer(activeImg); + this.setActiveImgZIndex(activeImg); + this.imgGlobalStatus.dragging = true; + // 鼠标相对于图片的位置 + activeImg.moveX = activeImg.imgViewEl.offsetLeft - event.clientX; + activeImg.moveY = activeImg.imgViewEl.offsetTop - event.clientY; + // 鼠标按下时持续触发/移动事件 + activeImg.imgViewEl.onmousemove = this.mousemoveImgView; + } + }; + /** + * move the image by mouse or keyboard + * @param event + * @param offsetSize + */ + this.mousemoveImgView = (event, offsetSize) => { + // console.log('mousemoveImgView', event, this.imgGlobalStatus.activeImg); + const activeImg = this.imgGlobalStatus.activeImg; + if (!activeImg) + return; + if (event) { + if (!this.imgGlobalStatus.dragging) + return; + // drag via mouse cursor (Both Mode) + activeImg.left = event.clientX + activeImg.moveX; + activeImg.top = event.clientY + activeImg.moveY; + } + else if (offsetSize) { + // move by arrow keys (Normal Mode) + activeImg.left += offsetSize.offsetX; + activeImg.top += offsetSize.offsetY; + } + else { + return; + } + // move the image + activeImg.imgViewEl.style.setProperty('margin-left', activeImg.left + 'px', 'important'); + activeImg.imgViewEl.style.setProperty('margin-top', activeImg.top + 'px', 'important'); + }; + this.mouseupImgView = (event) => { + var _a; + // console.log('mouseupImgView', event, this.imgGlobalStatus.activeImg); + this.imgGlobalStatus.dragging = false; + event.preventDefault(); + event.stopPropagation(); + const activeImg = this.imgGlobalStatus.activeImg; + if (activeImg) { + activeImg.imgViewEl.onmousemove = null; + if (2 == event.button) { // right click + (_a = this.menuView) === null || _a === void 0 ? void 0 : _a.show(event, activeImg); + } + } + }; + this.mouseleaveImgView = (event) => { + // console.log('mouseleaveImgView', event, this.imgGlobalStatus.activeImg, '>>> set null'); + this.imgGlobalStatus.dragging = false; + this.resetClickTimer(); + event.preventDefault(); + event.stopPropagation(); + const activeImg = this.imgGlobalStatus.activeImg; + if (activeImg) { + activeImg.imgViewEl.onmousemove = null; + this.setActiveImgForMouseEvent(null); // for pin mode + } + }; + this.setClickTimer = (activeImg) => { + ++this.imgGlobalStatus.clickCount; + clearTimeout(this.imgGlobalStatus.clickTimer); + this.imgGlobalStatus.clickTimer = setTimeout(() => { + const clickCount = this.imgGlobalStatus.clickCount; + this.resetClickTimer(); + if (2 === clickCount) { // double click + if (!activeImg) + activeImg = this.imgGlobalStatus.activeImg; + // console.log('mousedownImgView: double click...', activeImg.index); + this.clickImgToolbar(null, this.plugin.settings.doubleClickToolbar, activeImg); + } + }, 200); + }; + this.resetClickTimer = () => { + this.imgGlobalStatus.clickTimer = null; + this.imgGlobalStatus.clickCount = 0; + }; + this.getAndUpdateActiveImg = (event) => { + const targetEl = event.target; + let index; + if (!targetEl || !(index = targetEl.dataset.index)) + return; + const activeImg = this.imgInfo.imgList[parseInt(index)]; + if (activeImg && (!this.imgGlobalStatus.activeImg || activeImg.index !== this.imgGlobalStatus.activeImg.index)) { + this.setActiveImgForMouseEvent(activeImg); // update activeImg + } + // console.log('getAndUpdateActiveImg: ', activeImg) + return activeImg; + }; + this.mousewheelViewContainer = (event) => { + // event.preventDefault(); + event.stopPropagation(); + // @ts-ignore + this.zoomAndRender(0 < event.wheelDelta ? 0.1 : -0.1, event); + }; + this.zoomAndRender = (ratio, event, actualSize, activeImg) => { + if (!activeImg) { + activeImg = this.imgGlobalStatus.activeImg; + } + let activeImgViewEl; + if (!activeImg || !(activeImgViewEl = activeImg.imgViewEl)) + return; + let offsetSize = { offsetX: 0, offsetY: 0 }; + if (event) { + offsetSize.offsetX = event.offsetX; + offsetSize.offsetY = event.offsetY; + } + else { + offsetSize.offsetX = activeImg.curWidth / 2; + offsetSize.offsetY = activeImg.curHeight / 2; + } + const zoomData = ImgUtil.zoom(ratio, activeImg, offsetSize, actualSize); + this.renderImgTip(activeImg); + activeImgViewEl.setAttribute('width', zoomData.curWidth + 'px'); + activeImgViewEl.style.setProperty('margin-top', zoomData.top + 'px', 'important'); + activeImgViewEl.style.setProperty('margin-left', zoomData.left + 'px', 'important'); + }; + this.clickImgToolbar = (event, targetElClass, activeImg) => { + if (!targetElClass && !activeImg) { + if (!event) + return; + // comes from clicking toolbar + targetElClass = event.target.className; + activeImg = this.imgGlobalStatus.activeImg; + } + switch (targetElClass) { + case 'toolbar_zoom_to_100': + this.zoomAndRender(null, null, true, activeImg); + break; + case 'toolbar_zoom_in': + this.zoomAndRender(0.1); + break; + case 'toolbar_zoom_out': + this.zoomAndRender(-0.1); + break; + case 'toolbar_full_screen': + this.showPlayerImg(activeImg); + break; + case 'toolbar_refresh': + this.refreshImg(activeImg); + break; + case 'toolbar_rotate_left': + activeImg.rotate -= 90; + ImgUtil.transform(activeImg); + break; + case 'toolbar_rotate_right': + activeImg.rotate += 90; + ImgUtil.transform(activeImg); + break; + case 'toolbar_scale_x': + activeImg.scaleX = !activeImg.scaleX; + ImgUtil.transform(activeImg); + break; + case 'toolbar_scale_y': + activeImg.scaleY = !activeImg.scaleY; + ImgUtil.transform(activeImg); + break; + case 'toolbar_invert_color': + activeImg.invertColor = !activeImg.invertColor; + ImgUtil.invertImgColor(activeImg.imgViewEl, activeImg.invertColor); + break; + case 'toolbar_copy': + ImgUtil.copyImage(activeImg.imgViewEl, activeImg.curWidth, activeImg.curHeight); + break; + case 'toolbar_close': + this.closeContainerView(event, activeImg); + break; + } + }; + this.plugin = plugin; + } +} + +var Md5 = /** @class */ (function () { + function Md5() { + } + Md5.AddUnsigned = function (lX, lY) { + var lX4, lY4, lX8, lY8, lResult; + lX8 = (lX & 0x80000000); + lY8 = (lY & 0x80000000); + lX4 = (lX & 0x40000000); + lY4 = (lY & 0x40000000); + lResult = (lX & 0x3FFFFFFF) + (lY & 0x3FFFFFFF); + if (!!(lX4 & lY4)) { + return (lResult ^ 0x80000000 ^ lX8 ^ lY8); + } + if (!!(lX4 | lY4)) { + if (!!(lResult & 0x40000000)) { + return (lResult ^ 0xC0000000 ^ lX8 ^ lY8); + } + else { + return (lResult ^ 0x40000000 ^ lX8 ^ lY8); + } + } + else { + return (lResult ^ lX8 ^ lY8); + } + }; + Md5.FF = function (a, b, c, d, x, s, ac) { + a = this.AddUnsigned(a, this.AddUnsigned(this.AddUnsigned(this.F(b, c, d), x), ac)); + return this.AddUnsigned(this.RotateLeft(a, s), b); + }; + Md5.GG = function (a, b, c, d, x, s, ac) { + a = this.AddUnsigned(a, this.AddUnsigned(this.AddUnsigned(this.G(b, c, d), x), ac)); + return this.AddUnsigned(this.RotateLeft(a, s), b); + }; + Md5.HH = function (a, b, c, d, x, s, ac) { + a = this.AddUnsigned(a, this.AddUnsigned(this.AddUnsigned(this.H(b, c, d), x), ac)); + return this.AddUnsigned(this.RotateLeft(a, s), b); + }; + Md5.II = function (a, b, c, d, x, s, ac) { + a = this.AddUnsigned(a, this.AddUnsigned(this.AddUnsigned(this.I(b, c, d), x), ac)); + return this.AddUnsigned(this.RotateLeft(a, s), b); + }; + Md5.ConvertToWordArray = function (string) { + var lWordCount, lMessageLength = string.length, lNumberOfWords_temp1 = lMessageLength + 8, lNumberOfWords_temp2 = (lNumberOfWords_temp1 - (lNumberOfWords_temp1 % 64)) / 64, lNumberOfWords = (lNumberOfWords_temp2 + 1) * 16, lWordArray = Array(lNumberOfWords - 1), lBytePosition = 0, lByteCount = 0; + while (lByteCount < lMessageLength) { + lWordCount = (lByteCount - (lByteCount % 4)) / 4; + lBytePosition = (lByteCount % 4) * 8; + lWordArray[lWordCount] = (lWordArray[lWordCount] | (string.charCodeAt(lByteCount) << lBytePosition)); + lByteCount++; + } + lWordCount = (lByteCount - (lByteCount % 4)) / 4; + lBytePosition = (lByteCount % 4) * 8; + lWordArray[lWordCount] = lWordArray[lWordCount] | (0x80 << lBytePosition); + lWordArray[lNumberOfWords - 2] = lMessageLength << 3; + lWordArray[lNumberOfWords - 1] = lMessageLength >>> 29; + return lWordArray; + }; + Md5.WordToHex = function (lValue) { + var WordToHexValue = "", WordToHexValue_temp = "", lByte, lCount; + for (lCount = 0; lCount <= 3; lCount++) { + lByte = (lValue >>> (lCount * 8)) & 255; + WordToHexValue_temp = "0" + lByte.toString(16); + WordToHexValue = WordToHexValue + WordToHexValue_temp.substr(WordToHexValue_temp.length - 2, 2); + } + return WordToHexValue; + }; + Md5.Utf8Encode = function (string) { + var utftext = "", c; + string = string.replace(/\r\n/g, "\n"); + for (var n = 0; n < string.length; n++) { + c = string.charCodeAt(n); + if (c < 128) { + utftext += String.fromCharCode(c); + } + else if ((c > 127) && (c < 2048)) { + utftext += String.fromCharCode((c >> 6) | 192); + utftext += String.fromCharCode((c & 63) | 128); + } + else { + utftext += String.fromCharCode((c >> 12) | 224); + utftext += String.fromCharCode(((c >> 6) & 63) | 128); + utftext += String.fromCharCode((c & 63) | 128); + } + } + return utftext; + }; + Md5.init = function (string) { + var temp; + if (typeof string !== 'string') + string = JSON.stringify(string); + this._string = this.Utf8Encode(string); + this.x = this.ConvertToWordArray(this._string); + this.a = 0x67452301; + this.b = 0xEFCDAB89; + this.c = 0x98BADCFE; + this.d = 0x10325476; + for (this.k = 0; this.k < this.x.length; this.k += 16) { + this.AA = this.a; + this.BB = this.b; + this.CC = this.c; + this.DD = this.d; + this.a = this.FF(this.a, this.b, this.c, this.d, this.x[this.k], this.S11, 0xD76AA478); + this.d = this.FF(this.d, this.a, this.b, this.c, this.x[this.k + 1], this.S12, 0xE8C7B756); + this.c = this.FF(this.c, this.d, this.a, this.b, this.x[this.k + 2], this.S13, 0x242070DB); + this.b = this.FF(this.b, this.c, this.d, this.a, this.x[this.k + 3], this.S14, 0xC1BDCEEE); + this.a = this.FF(this.a, this.b, this.c, this.d, this.x[this.k + 4], this.S11, 0xF57C0FAF); + this.d = this.FF(this.d, this.a, this.b, this.c, this.x[this.k + 5], this.S12, 0x4787C62A); + this.c = this.FF(this.c, this.d, this.a, this.b, this.x[this.k + 6], this.S13, 0xA8304613); + this.b = this.FF(this.b, this.c, this.d, this.a, this.x[this.k + 7], this.S14, 0xFD469501); + this.a = this.FF(this.a, this.b, this.c, this.d, this.x[this.k + 8], this.S11, 0x698098D8); + this.d = this.FF(this.d, this.a, this.b, this.c, this.x[this.k + 9], this.S12, 0x8B44F7AF); + this.c = this.FF(this.c, this.d, this.a, this.b, this.x[this.k + 10], this.S13, 0xFFFF5BB1); + this.b = this.FF(this.b, this.c, this.d, this.a, this.x[this.k + 11], this.S14, 0x895CD7BE); + this.a = this.FF(this.a, this.b, this.c, this.d, this.x[this.k + 12], this.S11, 0x6B901122); + this.d = this.FF(this.d, this.a, this.b, this.c, this.x[this.k + 13], this.S12, 0xFD987193); + this.c = this.FF(this.c, this.d, this.a, this.b, this.x[this.k + 14], this.S13, 0xA679438E); + this.b = this.FF(this.b, this.c, this.d, this.a, this.x[this.k + 15], this.S14, 0x49B40821); + this.a = this.GG(this.a, this.b, this.c, this.d, this.x[this.k + 1], this.S21, 0xF61E2562); + this.d = this.GG(this.d, this.a, this.b, this.c, this.x[this.k + 6], this.S22, 0xC040B340); + this.c = this.GG(this.c, this.d, this.a, this.b, this.x[this.k + 11], this.S23, 0x265E5A51); + this.b = this.GG(this.b, this.c, this.d, this.a, this.x[this.k], this.S24, 0xE9B6C7AA); + this.a = this.GG(this.a, this.b, this.c, this.d, this.x[this.k + 5], this.S21, 0xD62F105D); + this.d = this.GG(this.d, this.a, this.b, this.c, this.x[this.k + 10], this.S22, 0x2441453); + this.c = this.GG(this.c, this.d, this.a, this.b, this.x[this.k + 15], this.S23, 0xD8A1E681); + this.b = this.GG(this.b, this.c, this.d, this.a, this.x[this.k + 4], this.S24, 0xE7D3FBC8); + this.a = this.GG(this.a, this.b, this.c, this.d, this.x[this.k + 9], this.S21, 0x21E1CDE6); + this.d = this.GG(this.d, this.a, this.b, this.c, this.x[this.k + 14], this.S22, 0xC33707D6); + this.c = this.GG(this.c, this.d, this.a, this.b, this.x[this.k + 3], this.S23, 0xF4D50D87); + this.b = this.GG(this.b, this.c, this.d, this.a, this.x[this.k + 8], this.S24, 0x455A14ED); + this.a = this.GG(this.a, this.b, this.c, this.d, this.x[this.k + 13], this.S21, 0xA9E3E905); + this.d = this.GG(this.d, this.a, this.b, this.c, this.x[this.k + 2], this.S22, 0xFCEFA3F8); + this.c = this.GG(this.c, this.d, this.a, this.b, this.x[this.k + 7], this.S23, 0x676F02D9); + this.b = this.GG(this.b, this.c, this.d, this.a, this.x[this.k + 12], this.S24, 0x8D2A4C8A); + this.a = this.HH(this.a, this.b, this.c, this.d, this.x[this.k + 5], this.S31, 0xFFFA3942); + this.d = this.HH(this.d, this.a, this.b, this.c, this.x[this.k + 8], this.S32, 0x8771F681); + this.c = this.HH(this.c, this.d, this.a, this.b, this.x[this.k + 11], this.S33, 0x6D9D6122); + this.b = this.HH(this.b, this.c, this.d, this.a, this.x[this.k + 14], this.S34, 0xFDE5380C); + this.a = this.HH(this.a, this.b, this.c, this.d, this.x[this.k + 1], this.S31, 0xA4BEEA44); + this.d = this.HH(this.d, this.a, this.b, this.c, this.x[this.k + 4], this.S32, 0x4BDECFA9); + this.c = this.HH(this.c, this.d, this.a, this.b, this.x[this.k + 7], this.S33, 0xF6BB4B60); + this.b = this.HH(this.b, this.c, this.d, this.a, this.x[this.k + 10], this.S34, 0xBEBFBC70); + this.a = this.HH(this.a, this.b, this.c, this.d, this.x[this.k + 13], this.S31, 0x289B7EC6); + this.d = this.HH(this.d, this.a, this.b, this.c, this.x[this.k], this.S32, 0xEAA127FA); + this.c = this.HH(this.c, this.d, this.a, this.b, this.x[this.k + 3], this.S33, 0xD4EF3085); + this.b = this.HH(this.b, this.c, this.d, this.a, this.x[this.k + 6], this.S34, 0x4881D05); + this.a = this.HH(this.a, this.b, this.c, this.d, this.x[this.k + 9], this.S31, 0xD9D4D039); + this.d = this.HH(this.d, this.a, this.b, this.c, this.x[this.k + 12], this.S32, 0xE6DB99E5); + this.c = this.HH(this.c, this.d, this.a, this.b, this.x[this.k + 15], this.S33, 0x1FA27CF8); + this.b = this.HH(this.b, this.c, this.d, this.a, this.x[this.k + 2], this.S34, 0xC4AC5665); + this.a = this.II(this.a, this.b, this.c, this.d, this.x[this.k], this.S41, 0xF4292244); + this.d = this.II(this.d, this.a, this.b, this.c, this.x[this.k + 7], this.S42, 0x432AFF97); + this.c = this.II(this.c, this.d, this.a, this.b, this.x[this.k + 14], this.S43, 0xAB9423A7); + this.b = this.II(this.b, this.c, this.d, this.a, this.x[this.k + 5], this.S44, 0xFC93A039); + this.a = this.II(this.a, this.b, this.c, this.d, this.x[this.k + 12], this.S41, 0x655B59C3); + this.d = this.II(this.d, this.a, this.b, this.c, this.x[this.k + 3], this.S42, 0x8F0CCC92); + this.c = this.II(this.c, this.d, this.a, this.b, this.x[this.k + 10], this.S43, 0xFFEFF47D); + this.b = this.II(this.b, this.c, this.d, this.a, this.x[this.k + 1], this.S44, 0x85845DD1); + this.a = this.II(this.a, this.b, this.c, this.d, this.x[this.k + 8], this.S41, 0x6FA87E4F); + this.d = this.II(this.d, this.a, this.b, this.c, this.x[this.k + 15], this.S42, 0xFE2CE6E0); + this.c = this.II(this.c, this.d, this.a, this.b, this.x[this.k + 6], this.S43, 0xA3014314); + this.b = this.II(this.b, this.c, this.d, this.a, this.x[this.k + 13], this.S44, 0x4E0811A1); + this.a = this.II(this.a, this.b, this.c, this.d, this.x[this.k + 4], this.S41, 0xF7537E82); + this.d = this.II(this.d, this.a, this.b, this.c, this.x[this.k + 11], this.S42, 0xBD3AF235); + this.c = this.II(this.c, this.d, this.a, this.b, this.x[this.k + 2], this.S43, 0x2AD7D2BB); + this.b = this.II(this.b, this.c, this.d, this.a, this.x[this.k + 9], this.S44, 0xEB86D391); + this.a = this.AddUnsigned(this.a, this.AA); + this.b = this.AddUnsigned(this.b, this.BB); + this.c = this.AddUnsigned(this.c, this.CC); + this.d = this.AddUnsigned(this.d, this.DD); + } + temp = this.WordToHex(this.a) + this.WordToHex(this.b) + this.WordToHex(this.c) + this.WordToHex(this.d); + return temp.toLowerCase(); + }; + Md5.x = Array(); + Md5.S11 = 7; + Md5.S12 = 12; + Md5.S13 = 17; + Md5.S14 = 22; + Md5.S21 = 5; + Md5.S22 = 9; + Md5.S23 = 14; + Md5.S24 = 20; + Md5.S31 = 4; + Md5.S32 = 11; + Md5.S33 = 16; + Md5.S34 = 23; + Md5.S41 = 6; + Md5.S42 = 10; + Md5.S43 = 15; + Md5.S44 = 21; + Md5.RotateLeft = function (lValue, iShiftBits) { return (lValue << iShiftBits) | (lValue >>> (32 - iShiftBits)); }; + Md5.F = function (x, y, z) { return (x & y) | ((~x) & z); }; + Md5.G = function (x, y, z) { return (x & z) | (y & (~z)); }; + Md5.H = function (x, y, z) { return (x ^ y ^ z); }; + Md5.I = function (x, y, z) { return (y ^ (x | (~z))); }; + return Md5; +}()); + +class GalleryImgCto { + constructor(alt, src) { + this.alt = alt; + this.src = src; + } +} +class GalleryImgCacheCto { + constructor(file, galleryImgList, mtime) { + this.file = file; + this.galleryImgList = galleryImgList; + this.mtime = mtime; + } +} + +class FileCto { + constructor(path, ctime, mtime) { + this.path = path; + this.ctime = ctime; + this.mtime = mtime; + } +} + +/* // const imgList: Array = parseMarkDown(plugin, activeView.sourceMode?.cmEditor, activeView.file.path); +export const parseMarkDown = (plugin: ImageToolkitPlugin, cm: CodeMirror.Editor, filePath: string) => { + let line, lineText; + for (let i = 0, lastLine = cm.lastLine(); i <= lastLine; i++) { + if (!(line = cm.lineInfo(i))) continue; + if (!(lineText = line.text)) continue; + console.debug((i + 1) + ' line: ' + lineText); + } +} */ +const parseActiveViewData = (plugin, lines, file) => { + if (!lines || 0 >= lines.length) + return null; + let lineText; + let isCodeArea = false; + let textArr; + const imgList = new Array(); + for (let i = 0, len = lines.length; i < len; i++) { + if (!(lineText = lines[i])) + continue; + // console.log((i + 1) + ' line: ' + lineText); + if (lineText.startsWith('```')) { + isCodeArea = !isCodeArea; + continue; + } + if (isCodeArea) + continue; + if (textArr = getNonCodeAreaTexts(lineText)) { + for (const text of textArr) { + extractImage(text, imgList); + } + } + else { + extractImage(lineText, imgList); + } + } + const filePath = file.path; + for (let i = 0, len = imgList.length; i < len; i++) { + const img = imgList[i]; + if (img.convert) { + const imageFile = plugin.app.metadataCache.getFirstLinkpathDest(decodeURIComponent(img.src), filePath); + img.src = imageFile ? plugin.app.vault.getResourcePath(imageFile) : ''; + } + img.hash = md5Img(img.alt, img.src); + img.match = null; + img.name = null; + } + return new GalleryImgCacheCto(new FileCto(file.path, file.stat.ctime, file.stat.mtime), imgList, new Date().getTime()); +}; +const getNonCodeAreaTexts = (lineText) => { + let textArr = []; + const idx1 = lineText.indexOf('`'); + if (0 > idx1) + return null; + const idx2 = lineText.lastIndexOf('`'); + if (idx1 === idx2) + return null; + if (idx1 > 0) + textArr.push(lineText.substring(0, idx1)); + if (lineText.length - 1 > idx2) + textArr.push(lineText.substring(idx2 + 1)); + return textArr; +}; +const IMAGE_LINK_REGEX1 = /\[\s*?(!\[(.*?)\]\((.*?)\))\s*?\]\(.*?\)/; // 1-link: [ ![alt1|alt2|...|altn|width](src) ](https://...) +// markdown: `![alt1|alt2|...|altn|width](src)` -> 1: alt (alt+width), 2: src +const RE_MARKDOWN_IMAGE = /!\[(.*?)\]\(\s*(.*?\.(jpe?g|png|svg|gif|bmp|webp))\s*\)/i; // 1: ![alt1|alt2|...|altn|width](src) +const IMAGE_LINK_REGEX2 = /\[\s*?(!\[\[(.*?[jpe?g|png|gif|svg|bmp].*?)\]\])\s*?\]\(.*?\)/i; // 2-link: [ ![[src|alt1|alt2|width]] ](https://...) +// RE_WIKILINK_IMAGE wikilink: `![[bird.png|alt1|alt2|2.1|50]]` -> 1: src+alt+width +const RE_WIKILINK_IMAGE = /!\[\[(.*?\.(jpe?g|png|svg|gif|bmp|webp).*?)\]\]/i; // 2: ![[src|alt1|alt2|width]] +const SRC_LINK_REGEX = /[a-z][a-z0-9+\-.]+:\/.*/i; // match link: http://, file://, app:// +const SRC_IMG_REGREX = /.*?\.jpe?g|png|gif|svg|bmp/i; // match image ext: .jpg/.jpeg/.png/.gif/.svg/.bmp +const IMG_TAG_LINK_SRC_REGEX = /).*?\/a>/i; // 3-a-img-src: +const IMG_TAG_SRC_REGEX = //i; // 3-img-src: +const IMG_TAG_ALT_REGEX = //i; // 3-img-alt: +const FULL_PATH_REGEX = /^[a-z]\:.*?[jpe?g|png|gif|svg|bmp]/i; +const BLOCKQUOTE_PREFIX = `#^`; +const IMG_MATCH_MIN_LEN = 7; +const extractImage = (text, imgList) => { + text = text.replace('\\|', '|'); + let img; + if (!(img = matchImage1(text))) { + if (!(img = matchImage2(text))) { + if (!(img = matchImageTag(text))) { + return; + } + } + } + imgList.push(img); + if (img.match) { + const idx = img.match.index + img.match[0].length; + if (idx > text.length - IMG_MATCH_MIN_LEN) + return; + extractImage(text.substring(idx), imgList); + } +}; +/** + * ![alt1|alt2|...|altn|width](src) + * @param text + * @returns + */ +const matchImage1 = (text) => { + var _a; + let match = text.match(IMAGE_LINK_REGEX1); // 1-link: [ ![alt1|alt2|...|altn|width](src) ](https://...) + let link = false; + let alt, src; + if (match) { + link = true; + alt = match[2]; + src = match[3]; + } + else { + match = text.match(RE_MARKDOWN_IMAGE); // 1: ![alt1|alt2|...|altn|width](src) + if (match) { + if (alt = match[1]) { + if (0 <= alt.indexOf('[') && 0 <= alt.indexOf(']')) + return; + } + src = match[2]; + if (src && src.startsWith(BLOCKQUOTE_PREFIX)) + return; + } + } + if (!match) + return null; + const img = new GalleryImgCto(); + img.link = link; + img.match = match; + img.alt = alt; + img.src = src; + let width; + if (img.src) { + if (SRC_LINK_REGEX.test(img.src)) { // 1.2: match link: http://, file://, app://local/ + if (img.src.startsWith('file://')) { + img.src = img.src.replace(/^file:\/+/, 'app://local/'); + } + } + else if (SRC_IMG_REGREX.test(img.src)) { // 1.3: match image ext: .jpg/.jpeg/.png/.gif/.svg/.bmp + const srcArr = img.src.split('/'); + if (srcArr && 0 < srcArr.length) { + img.name = srcArr[srcArr.length - 1]; + } + img.convert = true; + } + } + const altArr = (_a = img.alt) === null || _a === void 0 ? void 0 : _a.split('\|'); // match[1] = alt1|alt2|...|altn|width + if (altArr && 1 < altArr.length) { + if (/\d+/.test(width = altArr[altArr.length - 1])) { + img.alt = img.alt.substring(0, img.alt.length - width.length - 1); + } + } + return img; +}; +/** + * ![[src|alt1|alt2|width]] + * @param text + * @returns + */ +const matchImage2 = (text) => { + let match = text.match(IMAGE_LINK_REGEX2); // 2-link: [ ![[src|alt1|alt2|width]] ](https://...) + let link = false; + let content; + if (match) { + link = true; + content = match[2]; + } + else { + match = text.match(RE_WIKILINK_IMAGE); // 2: ![[src|alt1|alt2|width]] + content = match ? match[1] : null; + if (content && content.startsWith(BLOCKQUOTE_PREFIX)) + return; + } + if (!match) + return null; + const img = new GalleryImgCto(); + img.link = link; + img.match = match; + const contentArr = content === null || content === void 0 ? void 0 : content.split('|'); + if (contentArr && 0 < contentArr.length && (img.src = contentArr[0].trim())) { + const srcArr = img.src.split('/'); + if (srcArr && 0 < srcArr.length) { + img.name = srcArr[srcArr.length - 1]; + } + if (1 == contentArr.length) { + img.alt = img.src; + } + else { + img.alt = ''; + for (let i = 1; i < contentArr.length; i++) { + if (i == contentArr.length - 1 && /\d+/.test(contentArr[i])) + break; + if (img.alt) + img.alt += '|'; + img.alt += contentArr[i]; + } + } + img.convert = true; + } + return img; +}; +const matchImageTag = (text) => { + let match = text.match(IMG_TAG_LINK_SRC_REGEX); // 3-a-img-src: + let link = false; + if (match) { + link = true; + } + else { + match = text.match(IMG_TAG_SRC_REGEX); // 3-img-src: + } + if (!match) + return null; + const img = new GalleryImgCto(); + img.link = link; + img.match = match; + img.src = img.link ? match[2] : match[1]; + if (img.src) { + if (img.src.startsWith('file://')) { + img.src = img.src.replace(/^file:\/+/, 'app://local/'); + } + else if (FULL_PATH_REGEX.test(img.src)) { + img.src = 'app://local/' + img.src; + } + } + const matchAlt = text.match(IMG_TAG_ALT_REGEX); + img.alt = matchAlt ? matchAlt[1] : ''; + return img; +}; +const md5Img = (alt, src) => { + return Md5.init((alt ? alt : '') + '_' + src); +}; + +class GalleryNavbarView { + constructor(mainContainerView, plugin) { + // whether to display gallery navbar + this.state = false; + this.galleryNavbarEl = null; + this.galleryListEl = null; + this.galleryIsMousingDown = false; + this.galleryMouseDownClientX = 0; + this.galleryTranslateX = 0; + this.CACHE_LIMIT = 10; + this.CLICK_TIME = 150; + this.renderGalleryImg = (imgFooterEl) => __awaiter(this, void 0, void 0, function* () { + var _a; + if (this.state) + return; + // get all of images on the current editor + const activeView = this.plugin.app.workspace.getActiveViewOfType(obsidian.MarkdownView); + if (!activeView + || 'markdown' !== activeView.getViewType() + // modal-container: community plugin, flashcards (Space Repetition) + || 0 < this.mainContainerView.getDoc().getElementsByClassName('modal-container').length) { + if (this.galleryNavbarEl) + this.galleryNavbarEl.hidden = true; + if (this.galleryListEl) + this.galleryListEl.innerHTML = ''; + return; + } + // + this.initGalleryNavbar(imgFooterEl); + const activeFile = activeView.file; + let galleryImg = this.getGalleryImgCache(activeFile); + // let hitCache: boolean = true; + if (!galleryImg) { + // hitCache = false; + galleryImg = parseActiveViewData(this.plugin, (_a = activeView.data) === null || _a === void 0 ? void 0 : _a.split('\n'), activeFile); + this.setGalleryImgCache(galleryImg); + } + // console.log('oit-gallery-navbar: ' + (hitCache ? 'hit cache' : 'miss cache') + '!', galleryImg); + const imgList = galleryImg.galleryImgList; + const imgContextHash = this.getTargetImgContextHash(this.mainContainerView.getLastClickedImgEl(), activeView.containerEl, this.plugin.imgSelector); + let liEl, imgEl, liElActive; + let imgListEl = new Array(); + let targetImageIdx = -1, targetRealIdx = 0; + let isAddGalleryActive = false; + let prevHash, nextHash; + const viewImageWithLink = this.plugin.settings.viewImageWithLink; + for (let i = 0, len = imgList.length; i < len; i++) { + const img = imgList[i]; + if (!viewImageWithLink && img.link) + continue; + //
  • + this.galleryListEl.append(liEl = createEl('li')); + liEl.append(imgEl = createEl('img')); + imgEl.addClass('gallery-img', 'oit-img'); + imgEl.setAttr('alt', img.alt); + imgEl.setAttr('src', img.src); + imgListEl.push(imgEl); + this.mainContainerView.setImgViewDefaultBackground(imgEl); + // find the target image (which image is just clicked) + if (!imgContextHash || isAddGalleryActive) + continue; + if (imgContextHash[1] == img.hash) { + if (0 > targetImageIdx) { + targetImageIdx = i; + liElActive = liEl; + targetRealIdx = imgListEl.length; + } + if (0 == i) { + prevHash = null; + nextHash = 1 < len ? imgList[i + 1].hash : null; + } + else if (len - 1 == i) { + prevHash = imgList[i - 1].hash; + nextHash = null; + } + else { + prevHash = imgList[i - 1].hash; + nextHash = imgList[i + 1].hash; + } + if (imgContextHash[0] == prevHash && imgContextHash[2] == nextHash) { + isAddGalleryActive = true; + liElActive = liEl; + } + } + } + const realTotalNum = imgListEl.length; + this.mainContainerView.renderImgTitle(null, '[' + targetRealIdx + '/' + realTotalNum + ']'); + imgListEl.forEach((value, index) => { + value.dataset.index = '[' + (index + 1) + '/' + realTotalNum + ']'; + }); + if (0 <= targetImageIdx) { + if (liElActive) { + liElActive.addClass('gallery-active'); + if (this.settings.galleryImgBorderActive) { + liElActive.addClass('img-border-active'); + liElActive.style.setProperty('border-color', this.settings.galleryImgBorderActiveColor); + } + } + this.galleryTranslateX = (this.mainContainerView.getDoc().documentElement.clientWidth || this.mainContainerView.getDoc().body.clientWidth) / 2.5 - targetImageIdx * 52; + this.galleryListEl.style.transform = 'translateX(' + this.galleryTranslateX + 'px)'; + } + }); + this.initDefaultData = () => { + this.galleryMouseDownClientX = 0; + this.galleryTranslateX = 0; + if (this.galleryListEl) { + this.galleryListEl.style.transform = 'translateX(0px)'; + // remove all childs (li) of gallery-list + this.galleryListEl.innerHTML = ''; + } + }; + this.initGalleryNavbar = (imgFooterEl) => { + //