main.js 176 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425
  1. 'use strict';
  2. var obsidian = require('obsidian');
  3. var crypto = require('crypto');
  4. /******************************************************************************
  5. Copyright (c) Microsoft Corporation.
  6. Permission to use, copy, modify, and/or distribute this software for any
  7. purpose with or without fee is hereby granted.
  8. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
  9. REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  10. AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
  11. INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  12. LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
  13. OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  14. PERFORMANCE OF THIS SOFTWARE.
  15. ***************************************************************************** */
  16. function __awaiter(thisArg, _arguments, P, generator) {
  17. function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
  18. return new (P || (P = Promise))(function (resolve, reject) {
  19. function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
  20. function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
  21. function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
  22. step((generator = generator.apply(thisArg, _arguments || [])).next());
  23. });
  24. }
  25. typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
  26. var e = new Error(message);
  27. return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
  28. };
  29. // العربية
  30. var ar = {};
  31. // čeština
  32. var cz = {};
  33. // Dansk
  34. var da = {};
  35. // Deutsch
  36. var de = {};
  37. // English
  38. var en = {
  39. // settings
  40. IMAGE_TOOLKIT_SETTINGS_TITLE: 'Image Toolkit Settings',
  41. // >>>Common Settings:
  42. COMMON_SETTINGS: 'Common Settings:',
  43. VIEW_MODE_NAME: 'Choose a mode to view images',
  44. VIEW_MODE_NORMAL: '🖼 Normal',
  45. VIEW_MODE_PIN: '📌 Pin',
  46. // >>>View Trigger Settings:
  47. VIEW_TRIGGER_SETTINGS: 'View Trigger Settings:',
  48. VIEW_IMAGE_GLOBAL_NAME: 'Click and view an image globally',
  49. VIEW_IMAGE_GLOBAL_DESC: 'You can zoom, rotate, drag, and invert it on the popup layer when clicking an image.',
  50. VIEW_IMAGE_IN_EDITOR_NAME: 'Click and view an image in the Editor Area',
  51. VIEW_IMAGE_IN_EDITOR_DESC: 'Turn on this option if you want to click and view an image in the Editor Area.',
  52. // CPB = COMMUNITY_PLUGINS_BROWSER
  53. VIEW_IMAGE_IN_CPB_NAME: 'Click and view an image in the Community Plugins browser',
  54. VIEW_IMAGE_IN_CPB_DESC: 'Turn on this option if you want to click and view an image in the Community Plugins browser.',
  55. VIEW_IMAGE_WITH_A_LINK_NAME: 'Click and view an image with a link',
  56. 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.)',
  57. VIEW_IMAGE_OTHER_NAME: 'Click and view in the other areas except the above',
  58. VIEW_IMAGE_OTHER_DESC: 'Except for the above mentioned, it also supports other areas, like some modal user interface components.',
  59. // >>> PIN_MODE_SETTINGS
  60. PIN_MODE_SETTINGS: "Pin Mode Settings:",
  61. PIN_MODE_NAME: "📌 Pin an image",
  62. 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)",
  63. PIN_MAXIMUM_NAME: "The maximum images you can pin",
  64. PIN_COVER_NAME: "Cover mode",
  65. PIN_COVER_DESC: "After those pinned images reach maximum, you can cover the earliest pinned image when you click an image once again.",
  66. PIN_MAXIMUM_NOTICE: "Exceeded maximum images you can pin (non cover mode)",
  67. // >>>View Detail Settings:
  68. VIEW_DETAILS_SETTINGS: 'View Detail Settings:',
  69. IMAGE_MOVE_SPEED_NAME: 'Set the moving speed of the image',
  70. 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.',
  71. IMAGE_TIP_TOGGLE_NAME: "Display the image's zoom number",
  72. IMAGE_TIP_TOGGLE_DESC: "Turn on this option if you want to display the zoom number when you zoom the image.",
  73. IMG_FULL_SCREEN_MODE_NAME: 'Full-screen preview mode',
  74. // preview mode options:
  75. FIT: 'Fit',
  76. FILL: 'Fill',
  77. STRETCH: 'Stretch',
  78. IMG_VIEW_BACKGROUND_COLOR_NAME: "Set the background color of the previewed image (Only support the image with transparent background)",
  79. // >>>Image Border Settings:
  80. IMAGE_BORDER_SETTINGS: 'Image Border Settings:',
  81. IMAGE_BORDER_TOGGLE_NAME: "Display the image's border",
  82. IMAGE_BORDER_TOGGLE_DESC: "The clicked image's border can be displayed after you exit previewing and close the popup layer.",
  83. IMAGE_BORDER_WIDTH_NAME: "Set the image's border width",
  84. IMAGE_BORDER_STYLE_NAME: "Set the image's border style",
  85. IMAGE_BORDER_COLOR_NAME: "Set the image's border color",
  86. // IMG_BORDER_WIDTH options:
  87. THIN: 'thin',
  88. MEDIUM: 'medium',
  89. THICK: 'thick',
  90. // IMG_BORDER_STYLE options:
  91. //HIDDEN: 'hidden',
  92. DOTTED: 'dotted',
  93. DASHED: 'dashed',
  94. SOLID: 'solid',
  95. DOUBLE: 'double',
  96. GROOVE: 'groove',
  97. RIDGE: 'ridge',
  98. INSET: 'inset',
  99. OUTSET: 'outset',
  100. // IMAGE_BORDER_COLOR_NAME options:
  101. BLACK: 'black',
  102. BLUE: 'blue',
  103. DARK_GREEN: 'dark green',
  104. GREEN: 'green',
  105. LIME: 'lime',
  106. STEEL_BLUE: 'steel blue',
  107. INDIGO: 'indigo',
  108. PURPLE: 'purple',
  109. GRAY: 'gray',
  110. DARK_RED: 'dark red',
  111. LIGHT_GREEN: 'light green',
  112. BROWN: 'brown',
  113. LIGHT_BLUE: 'light blue',
  114. SILVER: 'silver',
  115. RED: 'red',
  116. PINK: 'pink',
  117. ORANGE: 'orange',
  118. GOLD: 'gold',
  119. YELLOW: 'yellow',
  120. // >>>Gallery Navbar Settings:
  121. GALLERY_NAVBAR_SETTINGS: 'Gallery Navbar Settings (Experimental):',
  122. GALLERY_NAVBAR_TOGGLE_NAME: "Display gallery navbar",
  123. GALLERY_NAVBAR_TOGGLE_DESC: "All of the images in the current pane view can be displayed at the bottom of the popup layer.",
  124. GALLERY_NAVBAR_DEFAULT_COLOR_NAME: "Set the background color of the gallery navbar (default state)",
  125. GALLERY_NAVBAR_HOVER_COLOR_NAME: "Set the background color of the gallery navbar (hovering state)",
  126. GALLERY_IMG_BORDER_TOGGLE_NAME: "Display the selected image on the gallery navbar",
  127. 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.",
  128. GALLERY_IMG_BORDER_ACTIVE_COLOR_NAME: 'Set the border color of the selected image',
  129. // >>>HOTKEYS_SETTINGS:
  130. HOTKEY_SETTINGS: "Hotkey Settings:",
  131. 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)",
  132. MOVE_THE_IMAGE_NAME: "Set the hotkey for moving the image",
  133. MOVE_THE_IMAGE_DESC: "You can move the image on the popup layer by hotkey.",
  134. SWITCH_THE_IMAGE_NAME: "Set the hotkey for switching the image",
  135. 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.)",
  136. DOUBLE_CLICK_TOOLBAR_NAME: "Double click",
  137. VIEW_TRIGGER_HOTKEY_NAME: "Set the hotkey for triggering viewing an image",
  138. 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.",
  139. // MODIFIER_HOTKEYS
  140. NONE: "None",
  141. CTRL: "Ctrl",
  142. ALT: "Alt",
  143. SHIFT: "Shift",
  144. CTRL_ALT: "Ctrl+Alt",
  145. CTRL_SHIFT: "Ctrl+Shift",
  146. SHIFT_ALT: "Shift+Alt",
  147. CTRL_SHIFT_ALT: "Ctrl+Shift+Alt",
  148. // toolbar icon title
  149. ZOOM_TO_100: "zoom to 100%",
  150. ZOOM_IN: "zoom in",
  151. ZOOM_OUT: "zoom out",
  152. FULL_SCREEN: 'full screen',
  153. REFRESH: "refresh",
  154. ROTATE_LEFT: "rotate left",
  155. ROTATE_RIGHT: "rotate right",
  156. SCALE_X: 'flip along x-axis',
  157. SCALE_Y: 'flip along y-axis',
  158. INVERT_COLOR: 'invert color',
  159. COPY: 'copy',
  160. CLOSE: 'close',
  161. // tip:
  162. COPY_IMAGE_SUCCESS: 'Copy the image successfully!',
  163. COPY_IMAGE_ERROR: 'Fail to copy the image!'
  164. };
  165. // British English
  166. var enGB = {};
  167. // Español
  168. var es = {};
  169. // français
  170. var fr = {};
  171. // हिन्दी
  172. var hi = {};
  173. // Bahasa Indonesia
  174. var id = {};
  175. // Italiano
  176. var it = {};
  177. // 日本語
  178. var ja = {};
  179. // 한국어
  180. var ko = {};
  181. // Nederlands
  182. var nl = {};
  183. // Norsk
  184. var no = {};
  185. // język polski
  186. var pl = {};
  187. // Português
  188. var pt = {};
  189. // Português do Brasil
  190. // Brazilian Portuguese
  191. var ptBR = {};
  192. // Română
  193. var ro = {};
  194. // русский
  195. var ru = {};
  196. // Türkçe
  197. var tr = {};
  198. // 简体中文
  199. var zhCN = {
  200. // settings
  201. IMAGE_TOOLKIT_SETTINGS_TITLE: "Image Toolkit 设置",
  202. // >>>Common Settings:
  203. COMMON_SETTINGS: '通用设置:',
  204. VIEW_MODE_NAME: '选择查看模式',
  205. VIEW_MODE_NORMAL: '🖼 普通',
  206. VIEW_MODE_PIN: '📌 贴图',
  207. // >>> 预览触发配置:
  208. VIEW_TRIGGER_SETTINGS: '预览触发配置:',
  209. VIEW_IMAGE_GLOBAL_NAME: '支持全局预览图片',
  210. VIEW_IMAGE_GLOBAL_DESC: '开启后,在任何地方点击图片都可以弹出预览界面,可对图片进行缩放、旋转、拖动、和反色等。',
  211. VIEW_IMAGE_IN_EDITOR_NAME: '支持在编辑区域预览图片',
  212. VIEW_IMAGE_IN_EDITOR_DESC: '开启后,支持在编辑区域,点击图片预览。',
  213. // CPB = COMMUNITY_PLUGINS_BROWSER
  214. VIEW_IMAGE_IN_CPB_NAME: '支持在社区插件页面预览图片',
  215. VIEW_IMAGE_IN_CPB_DESC: '开启后,支持在社区插件页面,点击图片预览。',
  216. VIEW_IMAGE_WITH_A_LINK_NAME: '支持预览带链接的图片',
  217. VIEW_IMAGE_WITH_A_LINK_DESC: '开启后,支持点击带链接的图片(注意:点击该图片,会同时打开浏览器访问指定地址和弹出预览图片)',
  218. VIEW_IMAGE_OTHER_NAME: '支持除上述其他地方来预览图片',
  219. VIEW_IMAGE_OTHER_DESC: '除上述支持范围外,还支持一些其他区域,如Modal用户界面组件。',
  220. // >>> PIN_MODE_SETTINGS
  221. PIN_MODE_SETTINGS: "贴图模式设置:",
  222. PIN_MODE_NAME: "📌 将所点击的图片贴到屏幕上",
  223. PIN_MODE_DESC: "你可以将当前所点击的图片贴到屏幕上,并且可以通过右击图片选择更多操作(按 Esc 关闭已贴图片的展示)",
  224. PIN_MAXIMUM_NAME: "最大贴图数量",
  225. PIN_COVER_NAME: "覆盖模式",
  226. PIN_COVER_DESC: "当贴图数量达到最大值后,此时再次点击图片,该图片会覆盖最早弹出的那个贴图。",
  227. PIN_MAXIMUM_NOTICE: "超过最大Pin图设置(非覆盖模式)",
  228. // >>>查看细节设置:
  229. VIEW_DETAILS_SETTINGS: '查看细节设置:',
  230. IMAGE_MOVE_SPEED_NAME: '图片移动速度设置',
  231. IMAGE_MOVE_SPEED_DESC: '当使用键盘(上、下、左、右)移动图片时,可对图片移动速度进行设置。',
  232. IMAGE_TIP_TOGGLE_NAME: "展示缩放比例提示",
  233. IMAGE_TIP_TOGGLE_DESC: "开启后,当你缩放图片时会展示当前缩放的比例。",
  234. IMG_FULL_SCREEN_MODE_NAME: '全屏预览模式',
  235. // 全屏预览模式 下拉:
  236. FIT: '自适应',
  237. FILL: '填充',
  238. STRETCH: '拉伸',
  239. IMG_VIEW_BACKGROUND_COLOR_NAME: "设置预览图片的背景色(仅对透明背景的图片生效)",
  240. // >>>图片边框设置:
  241. IMAGE_BORDER_SETTINGS: '图片边框设置:',
  242. IMAGE_BORDER_TOGGLE_NAME: "展示被点击图片的边框",
  243. IMAGE_BORDER_TOGGLE_DESC: "当离开图片预览和关闭弹出层后,突出展示被点击图片的边框。",
  244. IMAGE_BORDER_WIDTH_NAME: "设置图片边框宽度",
  245. IMAGE_BORDER_STYLE_NAME: "设置图片边框样式",
  246. IMAGE_BORDER_COLOR_NAME: "设置图片边框颜色",
  247. // IMG_BORDER_WIDTH 下拉:
  248. THIN: '较细',
  249. MEDIUM: '正常',
  250. THICK: '较粗',
  251. // IMG_BORDER_STYLE 下拉:
  252. //HIDDEN: '隐藏',
  253. DOTTED: '点状',
  254. DASHED: '虚线',
  255. SOLID: '实线',
  256. DOUBLE: '双线',
  257. GROOVE: '凹槽',
  258. RIDGE: ' 垄状',
  259. INSET: '凹边',
  260. OUTSET: '凸边',
  261. // IMAGE_BORDER_COLOR_NAME 下拉:
  262. BLACK: '黑色',
  263. BLUE: '蓝色',
  264. DARK_GREEN: '深绿色',
  265. GREEN: '绿色',
  266. LIME: '淡黄绿色',
  267. STEEL_BLUE: '钢青色',
  268. INDIGO: '靛蓝色',
  269. PURPLE: '紫色',
  270. GRAY: '灰色',
  271. DARK_RED: '深红色',
  272. LIGHT_GREEN: '浅绿色',
  273. BROWN: '棕色',
  274. LIGHT_BLUE: '浅蓝色',
  275. SILVER: '银色',
  276. RED: '红色',
  277. PINK: '粉红色',
  278. ORANGE: '橘黄色',
  279. GOLD: '金色',
  280. YELLOW: '黄色',
  281. // >>>Gallery Navbar Settings:
  282. GALLERY_NAVBAR_SETTINGS: '图片导航设置 (体验版):',
  283. GALLERY_NAVBAR_TOGGLE_NAME: "展示图片导航",
  284. GALLERY_NAVBAR_TOGGLE_DESC: "当前文档的所有图片会展示在弹出层的底部,可随意切换展示不同图片。",
  285. GALLERY_NAVBAR_DEFAULT_COLOR_NAME: "设置图片导航底栏背景色(默认展示)",
  286. GALLERY_NAVBAR_HOVER_COLOR_NAME: "设置图片导航底栏背景色(鼠标悬浮时)",
  287. GALLERY_IMG_BORDER_TOGGLE_NAME: "展示图片导航上被选中的图片",
  288. GALLERY_IMG_BORDER_TOGGLE_DESC: "当你选中正查看某一图片,对应图片导航底栏上将突出显示该缩略图片的边框。",
  289. GALLERY_IMG_BORDER_ACTIVE_COLOR_NAME: '设置被选中图片的边框色',
  290. // >>>HOTKEYS_SETTINGS:
  291. HOTKEY_SETTINGS: "快捷键设置:",
  292. HOTKEY_SETTINGS_DESC: "📢 你无法为'移动图片'和'切换图片'设置相同的快捷键。(不支持贴图模式)",
  293. MOVE_THE_IMAGE_NAME: "为移动图片设置快捷键",
  294. MOVE_THE_IMAGE_DESC: "你可以利用快捷键来移动弹出层上的图片。",
  295. SWITCH_THE_IMAGE_NAME: "为切换图片设置快捷键",
  296. SWITCH_THE_IMAGE_DESC: "你可以利用快捷键来切换在图片导航栏上的图片至上一张/下一张。(注意: 仅当开启“展示图片导航”后,才能使用该快捷键来控制切换图片。)",
  297. DOUBLE_CLICK_TOOLBAR_NAME: "双击",
  298. VIEW_TRIGGER_HOTKEY_NAME: "为触发弹出查看图片设置快捷键",
  299. VIEW_TRIGGER_HOTKEY_DESC: "当你设置为“无”,你可以直接点击预览图片;否则,须按住已配置的修改键(Ctrl、Alt、Shift)才能点击查看某个图片。",
  300. // MODIFIER_HOTKEYS
  301. NONE: "无",
  302. // toolbar icon title
  303. ZOOM_TO_100: "缩放至100%",
  304. ZOOM_IN: "放大",
  305. ZOOM_OUT: "缩小",
  306. FULL_SCREEN: "全屏",
  307. REFRESH: "刷新",
  308. ROTATE_LEFT: "左旋",
  309. ROTATE_RIGHT: "右旋",
  310. SCALE_X: 'x轴翻转',
  311. SCALE_Y: 'y轴翻转',
  312. INVERT_COLOR: '反色',
  313. COPY: '复制',
  314. CLOSE: '关闭',
  315. // tip:
  316. COPY_IMAGE_SUCCESS: '拷贝图片成功!',
  317. COPY_IMAGE_ERROR: '拷贝图片失败!'
  318. };
  319. // 繁體中文
  320. var zhTW = {
  321. // settings
  322. IMAGE_TOOLKIT_SETTINGS_TITLE: "image toolkit 設定",
  323. // toolbar icon title
  324. ZOOM_IN: "放大",
  325. ZOOM_OUT: "縮小",
  326. FULL_SCREEN: '全螢幕',
  327. REFRESH: "重整",
  328. ROTATE_LEFT: "向左旋轉",
  329. ROTATE_RIGHT: "向右旋轉",
  330. SCALE_X: 'x 軸縮放',
  331. SCALE_Y: 'y 軸縮放',
  332. INVERT_COLOR: '色彩反轉',
  333. COPY: '複製',
  334. COPY_IMAGE_SUCCESS: '成功複製圖片!'
  335. };
  336. const localeMap = {
  337. ar,
  338. cs: cz,
  339. da,
  340. de,
  341. en,
  342. "en-gb": enGB,
  343. es,
  344. fr,
  345. hi,
  346. id,
  347. it,
  348. ja,
  349. ko,
  350. nl,
  351. nn: no,
  352. pl,
  353. pt,
  354. "pt-br": ptBR,
  355. ro,
  356. ru,
  357. tr,
  358. "zh-cn": zhCN,
  359. "zh-tw": zhTW,
  360. };
  361. const locale = localeMap[obsidian.moment.locale()];
  362. function t(str) {
  363. if (!locale) {
  364. console.error("[oit] Image toolkit locale not found", obsidian.moment.locale());
  365. }
  366. return (locale && locale[str]) || en[str];
  367. }
  368. var ViewMode;
  369. (function (ViewMode) {
  370. ViewMode["Normal"] = "Normal";
  371. ViewMode["Pin"] = "Pin";
  372. })(ViewMode || (ViewMode = {}));
  373. const DEFAULT_VIEW_MODE = ViewMode.Normal;
  374. const OIT_CLASS = {
  375. CONTAINER_ROOT: 'oit',
  376. CONTAINER_NORMAL: 'oit-normal',
  377. CONTAINER_PIN: 'oit-pin',
  378. // the place for storing images
  379. IMG_CONTAINER: 'oit-img-container',
  380. IMG_VIEW: 'oit-img-view',
  381. IMG_TTP: 'oit-img-tip',
  382. IMG_FOOTER: 'oit-img-footer',
  383. IMG_TITLE: 'oit-img-title',
  384. IMG_TITLE_NAME: 'oit-img-title-name',
  385. IMG_TITLE_INDEX: 'oit-img-title-index',
  386. IMG_TOOLBAR: 'oit-img-toolbar',
  387. IMG_PLAYER: 'img-player',
  388. IMG_FULLSCREEN: 'img-fullscreen',
  389. };
  390. const ZOOM_FACTOR = 0.8;
  391. const IMG_VIEW_MIN = 30;
  392. const ICONS = [{
  393. id: 'zoom-to-100',
  394. svg: `<g> <path id="svg_1" d="m42,6c-18.8,0 -34,15.2 -34,34s15.2,34 34,34c7.4,0 14.3,-2.4 19.9,-6.4l26.3,26.3l5.6,-5.6l-26,-26.1c5.1,-6 8.2,-13.7 8.2,-22.1c0,-18.9 -15.2,-34.1 -34,-34.1zm0,4c16.6,0 30,13.4 30,30s-13.4,30 -30,30s-30,-13.4 -30,-30s13.4,-30 30,-30z" stroke-width="2" stroke="currentColor" fill="currentColor"/> <text font-weight="bold" xml:space="preserve" text-anchor="start" font-family="Noto Sans JP" font-size="24" id="svg_2" y="48.5" x="24" stroke-width="0" stroke="#000" fill="#000000">1:1</text> </g>`
  395. }];
  396. const SEPARATOR_SYMBOL = "---";
  397. const TOOLBAR_CONF = [{
  398. title: "ZOOM_TO_100",
  399. class: 'toolbar_zoom_to_100',
  400. icon: 'zoom-to-100',
  401. enableToolbarIcon: true,
  402. enableMenu: true,
  403. enableHotKey: true
  404. }, {
  405. title: "ZOOM_IN",
  406. class: 'toolbar_zoom_in',
  407. icon: 'zoom-in',
  408. enableToolbarIcon: true,
  409. enableMenu: false,
  410. enableHotKey: true
  411. }, {
  412. title: "ZOOM_OUT",
  413. class: 'toolbar_zoom_out',
  414. icon: 'zoom-out',
  415. enableToolbarIcon: true,
  416. enableMenu: false,
  417. enableHotKey: true
  418. }, {
  419. title: "FULL_SCREEN",
  420. class: 'toolbar_full_screen',
  421. icon: 'expand',
  422. enableToolbarIcon: true,
  423. enableMenu: true,
  424. enableHotKey: true
  425. }, {
  426. title: "REFRESH",
  427. class: 'toolbar_refresh',
  428. icon: 'refresh-ccw',
  429. enableToolbarIcon: true,
  430. enableMenu: true,
  431. enableHotKey: true
  432. }, {
  433. title: "ROTATE_LEFT",
  434. class: 'toolbar_rotate_left',
  435. icon: 'rotate-ccw',
  436. enableToolbarIcon: true,
  437. enableMenu: true,
  438. enableHotKey: true
  439. }, {
  440. title: "ROTATE_RIGHT",
  441. class: 'toolbar_rotate_right',
  442. icon: 'rotate-cw',
  443. enableToolbarIcon: true,
  444. enableMenu: true,
  445. enableHotKey: true
  446. }, {
  447. title: "SCALE_X",
  448. class: 'toolbar_scale_x',
  449. icon: 'move-horizontal',
  450. enableToolbarIcon: true,
  451. enableMenu: true,
  452. enableHotKey: true
  453. }, {
  454. title: "SCALE_Y",
  455. class: 'toolbar_scale_y',
  456. icon: 'move-vertical',
  457. enableToolbarIcon: true,
  458. enableMenu: true,
  459. enableHotKey: true
  460. }, {
  461. title: "INVERT_COLOR",
  462. class: 'toolbar_invert_color',
  463. icon: 'droplet',
  464. enableToolbarIcon: true,
  465. enableMenu: true,
  466. enableHotKey: true
  467. }, {
  468. title: "COPY",
  469. class: 'toolbar_copy',
  470. icon: 'copy',
  471. enableToolbarIcon: true,
  472. enableMenu: true,
  473. enableHotKey: true
  474. }, {
  475. title: SEPARATOR_SYMBOL,
  476. enableToolbarIcon: false,
  477. enableMenu: true,
  478. enableHotKey: false
  479. }, {
  480. title: "CLOSE",
  481. class: 'toolbar_close',
  482. icon: 'trash',
  483. enableToolbarIcon: false,
  484. enableMenu: true,
  485. enableHotKey: true
  486. }];
  487. const IMG_FULL_SCREEN_MODE = {
  488. FIT: 'FIT',
  489. FILL: 'FILL',
  490. STRETCH: 'STRETCH'
  491. };
  492. const VIEW_IMG_SELECTOR = {
  493. EDITOR_AREAS: `.workspace-leaf-content[data-type='markdown'] img,.workspace-leaf-content[data-type='image'] img`,
  494. EDITOR_AREAS_NO_LINK: `.workspace-leaf-content[data-type='markdown'] img:not(a img),.workspace-leaf-content[data-type='image'] img:not(a img)`,
  495. CPB: `.community-modal-details img`,
  496. CPB_NO_LINK: `.community-modal-details img:not(a img)`,
  497. OTHER: `.modal-content img`,
  498. OTHER_NO_LINK: `.modal-content img:not(a img)`,
  499. };
  500. const IMG_BORDER_WIDTH = {
  501. THIN: 'thin',
  502. MEDIUM: 'medium',
  503. THICK: 'thick'
  504. };
  505. const IMG_BORDER_STYLE = {
  506. // HIDDEN: 'hidden',
  507. DOTTED: 'dotted',
  508. DASHED: 'dashed',
  509. SOLID: 'solid',
  510. DOUBLE: 'double',
  511. GROOVE: 'groove',
  512. RIDGE: 'ridge',
  513. INSET: 'inset',
  514. OUTSET: 'outset'
  515. };
  516. // https://www.runoob.com/cssref/css-colorsfull.html
  517. const IMG_BORDER_COLOR = {
  518. BLACK: 'black',
  519. BLUE: 'blue',
  520. DARK_GREEN: 'darkgreen',
  521. GREEN: 'green',
  522. LIME: 'lime',
  523. STEEL_BLUE: 'steelblue',
  524. INDIGO: 'indigo',
  525. PURPLE: 'purple',
  526. GRAY: 'gray',
  527. DARK_RED: 'darkred',
  528. LIGHT_GREEN: 'lightgreen',
  529. BROWN: 'brown',
  530. LIGHT_BLUE: 'lightblue',
  531. SILVER: 'silver',
  532. RED: 'red',
  533. PINK: 'pink',
  534. ORANGE: 'orange',
  535. GOLD: 'gold',
  536. YELLOW: 'yellow'
  537. };
  538. const GALLERY_NAVBAR_DEFAULT_COLOR = '#0000001A'; // rgba(0, 0, 0, 0.1)
  539. const GALLERY_NAVBAR_HOVER_COLOR = '#0000004D'; // rgba(0, 0, 0, 0.3)
  540. const GALLERY_IMG_BORDER_ACTIVE_COLOR = '#FF0000'; // red
  541. const MODIFIER_HOTKEYS = {
  542. NONE: "NONE",
  543. CTRL: "CTRL",
  544. ALT: "ALT",
  545. SHIFT: "SHIFT",
  546. CTRL_ALT: "CTRL_ALT",
  547. CTRL_SHIFT: "CTRL_SHIFT",
  548. SHIFT_ALT: "SHIFT_ALT",
  549. CTRL_SHIFT_ALT: "CTRL_SHIFT_ALT"
  550. };
  551. const MOVE_THE_IMAGE = {
  552. CODE: "MOVE_THE_IMAGE",
  553. DEFAULT_HOTKEY: MODIFIER_HOTKEYS.NONE,
  554. SVG: `<svg width="56" height="37" xmlns="http://www.w3.org/2000/svg" class="icon"><path fill="none" d="M-1 -1H57V38H-1z"/><g><path stroke="null" fill="#707070" d="M19.001 16.067V1.928C19.001.864 19.865 0 20.93 0h14.142c1.064 0 1.928.864 1.928 1.928v14.14a1.929 1.929 0 01-1.928 1.927H20.929a1.929 1.929 0 01-1.928-1.928zm4.805-5.909l2.908-3.032v7.334c0 .535.43.964.965.964h.642c.535 0 .965-.43.965-.964V7.126l2.908 3.032a.965.965 0 001.378.017l.438-.442a.96.96 0 000-1.362l-5.327-5.33a.96.96 0 00-1.362 0l-5.335 5.33a.96.96 0 000 1.362l.438.441a.97.97 0 001.382-.016zM36.999 20.933v14.139A1.929 1.929 0 0135.07 37H20.929a1.929 1.929 0 01-1.928-1.928v-14.14c0-1.064.864-1.927 1.928-1.927h14.142c1.064 0 1.928.863 1.928 1.928zm-4.805 5.909l-2.908 3.032V22.54a.962.962 0 00-.965-.964h-.642a.962.962 0 00-.965.964v7.334l-2.908-3.032a.965.965 0 00-1.378-.016l-.438.441a.96.96 0 000 1.362l5.327 5.33a.96.96 0 001.362 0l5.335-5.33a.96.96 0 000-1.362l-.438-.441a.97.97 0 00-1.382.016zM16.068 37.001H1.93a1.929 1.929 0 01-1.928-1.928V20.932c0-1.065.864-1.928 1.928-1.928h14.14c1.064 0 1.927.863 1.927 1.928v14.14a1.929 1.929 0 01-1.928 1.93zm-5.908-4.804l-3.033-2.909h7.335c.534 0 .964-.43.964-.964v-.643a.962.962 0 00-.964-.964H7.127l3.033-2.909a.965.965 0 00.016-1.378l-.442-.438a.96.96 0 00-1.362 0l-5.33 5.327a.96.96 0 000 1.362l5.33 5.335a.96.96 0 001.362 0l.442-.438a.97.97 0 00-.016-1.381zM39.932 19.004H54.07c1.064 0 1.928.863 1.928 1.928v14.14a1.929 1.929 0 01-1.928 1.93H39.93a1.929 1.929 0 01-1.927-1.93v-14.14c0-1.065.863-1.928 1.928-1.928zm5.908 4.804l3.033 2.909h-7.335a.962.962 0 00-.964.964v.643c0 .534.43.964.964.964h7.335l-3.033 2.909a.965.965 0 00-.016 1.377l.442.438a.96.96 0 001.362 0l5.33-5.327a.96.96 0 000-1.362l-5.33-5.335a.96.96 0 00-1.362 0l-.442.438a.97.97 0 00.016 1.382z"/></g></svg>`
  555. };
  556. const SWITCH_THE_IMAGE = {
  557. CODE: "SWITCH_THE_IMAGE",
  558. DEFAULT_HOTKEY: MODIFIER_HOTKEYS.CTRL,
  559. SVG: `<svg width="37" height="18" xmlns="http://www.w3.org/2000/svg" class="icon"><path fill="none" d="M-1 -1H38V19H-1z"/><g><path stroke="null" fill="#707070" d="M16.068 17.999H1.93A1.929 1.929 0 01.001 16.07V1.929C.001.865.865.001 1.93.001h14.14c1.064 0 1.927.864 1.927 1.928v14.142a1.929 1.929 0 01-1.928 1.928zm-5.908-4.805l-3.033-2.908h7.335c.534 0 .964-.43.964-.965V8.68a.962.962 0 00-.964-.965H7.127l3.033-2.908a.965.965 0 00.016-1.378l-.442-.438a.96.96 0 00-1.362 0l-5.33 5.327a.96.96 0 000 1.362l5.33 5.335a.96.96 0 001.362 0l.442-.438a.97.97 0 00-.016-1.382zM20.932.001H35.07c1.064 0 1.928.864 1.928 1.928v14.142a1.929 1.929 0 01-1.928 1.928H20.93a1.929 1.929 0 01-1.927-1.928V1.929c0-1.064.863-1.928 1.928-1.928zm5.908 4.805l3.033 2.908h-7.335a.962.962 0 00-.964.965v.642c0 .535.43.965.964.965h7.335l-3.033 2.908a.965.965 0 00-.016 1.378l.442.438a.96.96 0 001.362 0l5.33-5.327a.96.96 0 000-1.362l-5.33-5.335a.96.96 0 00-1.362 0l-.442.438a.97.97 0 00.016 1.382z"/></g></svg>`
  560. };
  561. const IMG_DEFAULT_BACKGROUND_COLOR = '#00000000';
  562. function getDefaultExportFromCjs (x) {
  563. return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
  564. }
  565. function createCommonjsModule(fn) {
  566. var module = { exports: {} };
  567. return fn(module, module.exports), module.exports;
  568. }
  569. /*! Pickr 1.9.1 MIT | https://github.com/Simonwep/pickr */
  570. var pickr_min = createCommonjsModule(function (module, exports) {
  571. !function(t,e){module.exports=e();}(self,(()=>(()=>{var t={d:(e,o)=>{for(var n in o)t.o(o,n)&&!t.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:o[n]});},o:(t,e)=>Object.prototype.hasOwnProperty.call(t,e),r:t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0});}},e={};t.d(e,{default:()=>E});var o={};function n(t,e,o,n,i={}){e instanceof HTMLCollection||e instanceof NodeList?e=Array.from(e):Array.isArray(e)||(e=[e]),Array.isArray(o)||(o=[o]);for(const s of e)for(const e of o)s[t](e,n,{capture:!1,...i});return Array.prototype.slice.call(arguments,1)}t.r(o),t.d(o,{adjustableInputNumbers:()=>p,createElementFromString:()=>r,createFromTemplate:()=>a,eventPath:()=>l,off:()=>s,on:()=>i,resolveElement:()=>c});const i=n.bind(null,"addEventListener"),s=n.bind(null,"removeEventListener");function r(t){const e=document.createElement("div");return e.innerHTML=t.trim(),e.firstElementChild}function a(t){const e=(t,e)=>{const o=t.getAttribute(e);return t.removeAttribute(e),o},o=(t,n={})=>{const i=e(t,":obj"),s=e(t,":ref"),r=i?n[i]={}:n;s&&(n[s]=t);for(const n of Array.from(t.children)){const t=e(n,":arr"),i=o(n,t?{}:r);t&&(r[t]||(r[t]=[])).push(Object.keys(i).length?i:n);}return n};return o(r(t))}function l(t){let e=t.path||t.composedPath&&t.composedPath();if(e)return e;let o=t.target.parentElement;for(e=[t.target,o];o=o.parentElement;)e.push(o);return e.push(document,window),e}function c(t){return t instanceof Element?t:"string"==typeof t?t.split(/>>/g).reduce(((t,e,o,n)=>(t=t.querySelector(e),o<n.length-1?t.shadowRoot:t)),document):null}function p(t,e=(t=>t)){function o(o){const n=[.001,.01,.1][Number(o.shiftKey||2*o.ctrlKey)]*(o.deltaY<0?1:-1);let i=0,s=t.selectionStart;t.value=t.value.replace(/[\d.]+/g,((t,o)=>o<=s&&o+t.length>=s?(s=o,e(Number(t),n,i)):(i++,t))),t.focus(),t.setSelectionRange(s,s),o.preventDefault(),t.dispatchEvent(new Event("input"));}i(t,"focus",(()=>i(window,"wheel",o,{passive:!1}))),i(t,"blur",(()=>s(window,"wheel",o)));}const{min:u,max:h,floor:d,round:m}=Math;function f(t,e,o){e/=100,o/=100;const n=d(t=t/360*6),i=t-n,s=o*(1-e),r=o*(1-i*e),a=o*(1-(1-i)*e),l=n%6;return [255*[o,r,s,s,a,o][l],255*[a,o,o,r,s,s][l],255*[s,s,a,o,o,r][l]]}function v(t,e,o){const n=(2-(e/=100))*(o/=100)/2;return 0!==n&&(e=1===n?0:n<.5?e*o/(2*n):e*o/(2-2*n)),[t,100*e,100*n]}function b(t,e,o){const n=u(t/=255,e/=255,o/=255),i=h(t,e,o),s=i-n;let r,a;if(0===s)r=a=0;else {a=s/i;const n=((i-t)/6+s/2)/s,l=((i-e)/6+s/2)/s,c=((i-o)/6+s/2)/s;t===i?r=c-l:e===i?r=1/3+n-c:o===i&&(r=2/3+l-n),r<0?r+=1:r>1&&(r-=1);}return [360*r,100*a,100*i]}function y(t,e,o,n){e/=100,o/=100;return [...b(255*(1-u(1,(t/=100)*(1-(n/=100))+n)),255*(1-u(1,e*(1-n)+n)),255*(1-u(1,o*(1-n)+n)))]}function g(t,e,o){e/=100;const n=2*(e*=(o/=100)<.5?o:1-o)/(o+e)*100,i=100*(o+e);return [t,isNaN(n)?0:n,i]}function _(t){return b(...t.match(/.{2}/g).map((t=>parseInt(t,16))))}function w(t){t=t.match(/^[a-zA-Z]+$/)?function(t){if("black"===t.toLowerCase())return "#000";const e=document.createElement("canvas").getContext("2d");return e.fillStyle=t,"#000"===e.fillStyle?null:e.fillStyle}(t):t;const e={cmyk:/^cmyk\D+([\d.]+)\D+([\d.]+)\D+([\d.]+)\D+([\d.]+)/i,rgba:/^rgba?\D+([\d.]+)(%?)\D+([\d.]+)(%?)\D+([\d.]+)(%?)\D*?(([\d.]+)(%?)|$)/i,hsla:/^hsla?\D+([\d.]+)\D+([\d.]+)\D+([\d.]+)\D*?(([\d.]+)(%?)|$)/i,hsva:/^hsva?\D+([\d.]+)\D+([\d.]+)\D+([\d.]+)\D*?(([\d.]+)(%?)|$)/i,hexa:/^#?(([\dA-Fa-f]{3,4})|([\dA-Fa-f]{6})|([\dA-Fa-f]{8}))$/i},o=t=>t.map((t=>/^(|\d+)\.\d+|\d+$/.test(t)?Number(t):void 0));let n;t:for(const i in e)if(n=e[i].exec(t))switch(i){case"cmyk":{const[,t,e,s,r]=o(n);if(t>100||e>100||s>100||r>100)break t;return {values:y(t,e,s,r),type:i}}case"rgba":{let[,t,,e,,s,,,r]=o(n);if(t="%"===n[2]?t/100*255:t,e="%"===n[4]?e/100*255:e,s="%"===n[6]?s/100*255:s,r="%"===n[9]?r/100:r,t>255||e>255||s>255||r<0||r>1)break t;return {values:[...b(t,e,s),r],a:r,type:i}}case"hexa":{let[,t]=n;4!==t.length&&3!==t.length||(t=t.split("").map((t=>t+t)).join(""));const e=t.substring(0,6);let o=t.substring(6);return o=o?parseInt(o,16)/255:void 0,{values:[..._(e),o],a:o,type:i}}case"hsla":{let[,t,e,s,,r]=o(n);if(r="%"===n[6]?r/100:r,t>360||e>100||s>100||r<0||r>1)break t;return {values:[...g(t,e,s),r],a:r,type:i}}case"hsva":{let[,t,e,s,,r]=o(n);if(r="%"===n[6]?r/100:r,t>360||e>100||s>100||r<0||r>1)break t;return {values:[t,e,s,r],a:r,type:i}}}return {values:null,type:null}}function A(t=0,e=0,o=0,n=1){const i=(t,e)=>(o=-1)=>e(~o?t.map((t=>Number(t.toFixed(o)))):t),s={h:t,s:e,v:o,a:n,toHSVA(){const t=[s.h,s.s,s.v,s.a];return t.toString=i(t,(t=>`hsva(${t[0]}, ${t[1]}%, ${t[2]}%, ${s.a})`)),t},toHSLA(){const t=[...v(s.h,s.s,s.v),s.a];return t.toString=i(t,(t=>`hsla(${t[0]}, ${t[1]}%, ${t[2]}%, ${s.a})`)),t},toRGBA(){const t=[...f(s.h,s.s,s.v),s.a];return t.toString=i(t,(t=>`rgba(${t[0]}, ${t[1]}, ${t[2]}, ${s.a})`)),t},toCMYK(){const t=function(t,e,o){const n=f(t,e,o),i=n[0]/255,s=n[1]/255,r=n[2]/255,a=u(1-i,1-s,1-r);return [100*(1===a?0:(1-i-a)/(1-a)),100*(1===a?0:(1-s-a)/(1-a)),100*(1===a?0:(1-r-a)/(1-a)),100*a]}(s.h,s.s,s.v);return t.toString=i(t,(t=>`cmyk(${t[0]}%, ${t[1]}%, ${t[2]}%, ${t[3]}%)`)),t},toHEXA(){const t=function(t,e,o){return f(t,e,o).map((t=>m(t).toString(16).padStart(2,"0")))}(s.h,s.s,s.v),e=s.a>=1?"":Number((255*s.a).toFixed(0)).toString(16).toUpperCase().padStart(2,"0");return e&&t.push(e),t.toString=()=>`#${t.join("").toUpperCase()}`,t},clone:()=>A(s.h,s.s,s.v,s.a)};return s}const $=t=>Math.max(Math.min(t,1),0);function C(t){const e={options:Object.assign({lock:null,onchange:()=>0,onstop:()=>0},t),_keyboard(t){const{options:o}=e,{type:n,key:i}=t;if(document.activeElement===o.wrapper){const{lock:o}=e.options,s="ArrowUp"===i,r="ArrowRight"===i,a="ArrowDown"===i,l="ArrowLeft"===i;if("keydown"===n&&(s||r||a||l)){let n=0,i=0;"v"===o?n=s||r?1:-1:"h"===o?n=s||r?-1:1:(i=s?-1:a?1:0,n=l?-1:r?1:0),e.update($(e.cache.x+.01*n),$(e.cache.y+.01*i)),t.preventDefault();}else i.startsWith("Arrow")&&(e.options.onstop(),t.preventDefault());}},_tapstart(t){i(document,["mouseup","touchend","touchcancel"],e._tapstop),i(document,["mousemove","touchmove"],e._tapmove),t.cancelable&&t.preventDefault(),e._tapmove(t);},_tapmove(t){const{options:o,cache:n}=e,{lock:i,element:s,wrapper:r}=o,a=r.getBoundingClientRect();let l=0,c=0;if(t){const e=t&&t.touches&&t.touches[0];l=t?(e||t).clientX:0,c=t?(e||t).clientY:0,l<a.left?l=a.left:l>a.left+a.width&&(l=a.left+a.width),c<a.top?c=a.top:c>a.top+a.height&&(c=a.top+a.height),l-=a.left,c-=a.top;}else n&&(l=n.x*a.width,c=n.y*a.height);"h"!==i&&(s.style.left=`calc(${l/a.width*100}% - ${s.offsetWidth/2}px)`),"v"!==i&&(s.style.top=`calc(${c/a.height*100}% - ${s.offsetHeight/2}px)`),e.cache={x:l/a.width,y:c/a.height};const p=$(l/a.width),u=$(c/a.height);switch(i){case"v":return o.onchange(p);case"h":return o.onchange(u);default:return o.onchange(p,u)}},_tapstop(){e.options.onstop(),s(document,["mouseup","touchend","touchcancel"],e._tapstop),s(document,["mousemove","touchmove"],e._tapmove);},trigger(){e._tapmove();},update(t=0,o=0){const{left:n,top:i,width:s,height:r}=e.options.wrapper.getBoundingClientRect();"h"===e.options.lock&&(o=t),e._tapmove({clientX:n+s*t,clientY:i+r*o});},destroy(){const{options:t,_tapstart:o,_keyboard:n}=e;s(document,["keydown","keyup"],n),s([t.wrapper,t.element],"mousedown",o),s([t.wrapper,t.element],"touchstart",o,{passive:!1});}},{options:o,_tapstart:n,_keyboard:r}=e;return i([o.wrapper,o.element],"mousedown",n),i([o.wrapper,o.element],"touchstart",n,{passive:!1}),i(document,["keydown","keyup"],r),e}function k(t={}){t=Object.assign({onchange:()=>0,className:"",elements:[]},t);const e=i(t.elements,"click",(e=>{t.elements.forEach((o=>o.classList[e.target===o?"add":"remove"](t.className))),t.onchange(e),e.stopPropagation();}));return {destroy:()=>s(...e)}}const S={variantFlipOrder:{start:"sme",middle:"mse",end:"ems"},positionFlipOrder:{top:"tbrl",right:"rltb",bottom:"btrl",left:"lrbt"},position:"bottom",margin:8,padding:0},O=(t,e,o)=>{const n="object"!=typeof t||t instanceof HTMLElement?{reference:t,popper:e,...o}:t;return {update(t=n){const{reference:e,popper:o}=Object.assign(n,t);if(!o||!e)throw new Error("Popper- or reference-element missing.");return ((t,e,o)=>{const{container:n,arrow:i,margin:s,padding:r,position:a,variantFlipOrder:l,positionFlipOrder:c}={container:document.documentElement.getBoundingClientRect(),...S,...o},{left:p,top:u}=e.style;e.style.left="0",e.style.top="0";const h=t.getBoundingClientRect(),d=e.getBoundingClientRect(),m={t:h.top-d.height-s,b:h.bottom+s,r:h.right+s,l:h.left-d.width-s},f={vs:h.left,vm:h.left+h.width/2-d.width/2,ve:h.left+h.width-d.width,hs:h.top,hm:h.bottom-h.height/2-d.height/2,he:h.bottom-d.height},[v,b="middle"]=a.split("-"),y=c[v],g=l[b],{top:_,left:w,bottom:A,right:$}=n;for(const t of y){const o="t"===t||"b"===t;let n=m[t];const[s,a]=o?["top","left"]:["left","top"],[l,c]=o?[d.height,d.width]:[d.width,d.height],[p,u]=o?[A,$]:[$,A],[v,b]=o?[_,w]:[w,_];if(!(n<v||n+l+r>p))for(const p of g){let m=f[(o?"v":"h")+p];if(!(m<b||m+c+r>u)){if(m-=d[a],n-=d[s],e.style[a]=`${m}px`,e.style[s]=`${n}px`,i){const e=o?h.width/2:h.height/2,r=c/2,u=e>r,d=m+{s:u?r:e,m:r,e:u?r:c-e}[p],f=n+{t:l,b:0,r:0,l}[t];i.style[a]=`${d}px`,i.style[s]=`${f}px`;}return t+p}}}return e.style.left=p,e.style.top=u,null})(e,o,n)}}};class E{static utils=o;static version="1.9.1";static I18N_DEFAULTS={"ui:dialog":"color picker dialog","btn:toggle":"toggle color picker dialog","btn:swatch":"color swatch","btn:last-color":"use previous color","btn:save":"Save","btn:cancel":"Cancel","btn:clear":"Clear","aria:btn:save":"save and close","aria:btn:cancel":"cancel and close","aria:btn:clear":"clear and close","aria:input":"color input field","aria:palette":"color selection area","aria:hue":"hue selection slider","aria:opacity":"selection slider"};static DEFAULT_OPTIONS={appClass:null,theme:"classic",useAsButton:!1,padding:8,disabled:!1,comparison:!0,closeOnScroll:!1,outputPrecision:0,lockOpacity:!1,autoReposition:!0,container:"body",components:{interaction:{}},i18n:{},swatches:null,inline:!1,sliders:null,default:"#42445a",defaultRepresentation:null,position:"bottom-middle",adjustableNumbers:!0,showAlways:!1,closeWithKey:"Escape"};_initializingActive=!0;_recalc=!0;_nanopop=null;_root=null;_color=A();_lastColor=A();_swatchColors=[];_setupAnimationFrame=null;_eventListener={init:[],save:[],hide:[],show:[],clear:[],change:[],changestop:[],cancel:[],swatchselect:[]};constructor(t){this.options=t=Object.assign({...E.DEFAULT_OPTIONS},t);const{swatches:e,components:o,theme:n,sliders:i,lockOpacity:s,padding:r}=t;["nano","monolith"].includes(n)&&!i&&(t.sliders="h"),o.interaction||(o.interaction={});const{preview:a,opacity:l,hue:c,palette:p}=o;o.opacity=!s&&l,o.palette=p||a||l||c,this._preBuild(),this._buildComponents(),this._bindEvents(),this._finalBuild(),e&&e.length&&e.forEach((t=>this.addSwatch(t)));const{button:u,app:h}=this._root;this._nanopop=O(u,h,{margin:r}),u.setAttribute("role","button"),u.setAttribute("aria-label",this._t("btn:toggle"));const d=this;this._setupAnimationFrame=requestAnimationFrame((function e(){if(!h.offsetWidth)return requestAnimationFrame(e);d.setColor(t.default),d._rePositioningPicker(),t.defaultRepresentation&&(d._representation=t.defaultRepresentation,d.setColorRepresentation(d._representation)),t.showAlways&&d.show(),d._initializingActive=!1,d._emit("init");}));}static create=t=>new E(t);_preBuild(){const{options:t}=this;for(const e of ["el","container"])t[e]=c(t[e]);this._root=(t=>{const{components:e,useAsButton:o,inline:n,appClass:i,theme:s,lockOpacity:r}=t.options,l=t=>t?"":'style="display:none" hidden',c=e=>t._t(e),p=a(`\n <div :ref="root" class="pickr">\n\n ${o?"":'<button type="button" :ref="button" class="pcr-button"></button>'}\n\n <div :ref="app" class="pcr-app ${i||""}" data-theme="${s}" ${n?'style="position: unset"':""} aria-label="${c("ui:dialog")}" role="window">\n <div class="pcr-selection" ${l(e.palette)}>\n <div :obj="preview" class="pcr-color-preview" ${l(e.preview)}>\n <button type="button" :ref="lastColor" class="pcr-last-color" aria-label="${c("btn:last-color")}"></button>\n <div :ref="currentColor" class="pcr-current-color"></div>\n </div>\n\n <div :obj="palette" class="pcr-color-palette">\n <div :ref="picker" class="pcr-picker"></div>\n <div :ref="palette" class="pcr-palette" tabindex="0" aria-label="${c("aria:palette")}" role="listbox"></div>\n </div>\n\n <div :obj="hue" class="pcr-color-chooser" ${l(e.hue)}>\n <div :ref="picker" class="pcr-picker"></div>\n <div :ref="slider" class="pcr-hue pcr-slider" tabindex="0" aria-label="${c("aria:hue")}" role="slider"></div>\n </div>\n\n <div :obj="opacity" class="pcr-color-opacity" ${l(e.opacity)}>\n <div :ref="picker" class="pcr-picker"></div>\n <div :ref="slider" class="pcr-opacity pcr-slider" tabindex="0" aria-label="${c("aria:opacity")}" role="slider"></div>\n </div>\n </div>\n\n <div class="pcr-swatches ${e.palette?"":"pcr-last"}" :ref="swatches"></div>\n\n <div :obj="interaction" class="pcr-interaction" ${l(Object.keys(e.interaction).length)}>\n <input :ref="result" class="pcr-result" type="text" spellcheck="false" ${l(e.interaction.input)} aria-label="${c("aria:input")}">\n\n <input :arr="options" class="pcr-type" data-type="HEXA" value="${r?"HEX":"HEXA"}" type="button" ${l(e.interaction.hex)}>\n <input :arr="options" class="pcr-type" data-type="RGBA" value="${r?"RGB":"RGBA"}" type="button" ${l(e.interaction.rgba)}>\n <input :arr="options" class="pcr-type" data-type="HSLA" value="${r?"HSL":"HSLA"}" type="button" ${l(e.interaction.hsla)}>\n <input :arr="options" class="pcr-type" data-type="HSVA" value="${r?"HSV":"HSVA"}" type="button" ${l(e.interaction.hsva)}>\n <input :arr="options" class="pcr-type" data-type="CMYK" value="CMYK" type="button" ${l(e.interaction.cmyk)}>\n\n <input :ref="save" class="pcr-save" value="${c("btn:save")}" type="button" ${l(e.interaction.save)} aria-label="${c("aria:btn:save")}">\n <input :ref="cancel" class="pcr-cancel" value="${c("btn:cancel")}" type="button" ${l(e.interaction.cancel)} aria-label="${c("aria:btn:cancel")}">\n <input :ref="clear" class="pcr-clear" value="${c("btn:clear")}" type="button" ${l(e.interaction.clear)} aria-label="${c("aria:btn:clear")}">\n </div>\n </div>\n </div>\n `),u=p.interaction;return u.options.find((t=>!t.hidden&&!t.classList.add("active"))),u.type=()=>u.options.find((t=>t.classList.contains("active"))),p})(this),t.useAsButton&&(this._root.button=t.el),t.container.appendChild(this._root.root);}_finalBuild(){const t=this.options,e=this._root;if(t.container.removeChild(e.root),t.inline){const o=t.el.parentElement;t.el.nextSibling?o.insertBefore(e.app,t.el.nextSibling):o.appendChild(e.app);}else t.container.appendChild(e.app);t.useAsButton?t.inline&&t.el.remove():t.el.parentNode.replaceChild(e.root,t.el),t.disabled&&this.disable(),t.comparison||(e.button.style.transition="none",t.useAsButton||(e.preview.lastColor.style.transition="none")),this.hide();}_buildComponents(){const t=this,e=this.options.components,o=(t.options.sliders||"v").repeat(2),[n,i]=o.match(/^[vh]+$/g)?o:[],s=()=>this._color||(this._color=this._lastColor.clone()),r={palette:C({element:t._root.palette.picker,wrapper:t._root.palette.palette,onstop:()=>t._emit("changestop","slider",t),onchange(o,n){if(!e.palette)return;const i=s(),{_root:r,options:a}=t,{lastColor:l,currentColor:c}=r.preview;t._recalc&&(i.s=100*o,i.v=100-100*n,i.v<0&&(i.v=0),t._updateOutput("slider"));const p=i.toRGBA().toString(0);this.element.style.background=p,this.wrapper.style.background=`\n linear-gradient(to top, rgba(0, 0, 0, ${i.a}), transparent),\n linear-gradient(to left, hsla(${i.h}, 100%, 50%, ${i.a}), rgba(255, 255, 255, ${i.a}))\n `,a.comparison?a.useAsButton||t._lastColor||l.style.setProperty("--pcr-color",p):(r.button.style.setProperty("--pcr-color",p),r.button.classList.remove("clear"));const u=i.toHEXA().toString();for(const{el:e,color:o}of t._swatchColors)e.classList[u===o.toHEXA().toString()?"add":"remove"]("pcr-active");c.style.setProperty("--pcr-color",p);}}),hue:C({lock:"v"===i?"h":"v",element:t._root.hue.picker,wrapper:t._root.hue.slider,onstop:()=>t._emit("changestop","slider",t),onchange(o){if(!e.hue||!e.palette)return;const n=s();t._recalc&&(n.h=360*o),this.element.style.backgroundColor=`hsl(${n.h}, 100%, 50%)`,r.palette.trigger();}}),opacity:C({lock:"v"===n?"h":"v",element:t._root.opacity.picker,wrapper:t._root.opacity.slider,onstop:()=>t._emit("changestop","slider",t),onchange(o){if(!e.opacity||!e.palette)return;const n=s();t._recalc&&(n.a=Math.round(100*o)/100),this.element.style.background=`rgba(0, 0, 0, ${n.a})`,r.palette.trigger();}}),selectable:k({elements:t._root.interaction.options,className:"active",onchange(e){t._representation=e.target.getAttribute("data-type").toUpperCase(),t._recalc&&t._updateOutput("swatch");}})};this._components=r;}_bindEvents(){const{_root:t,options:e}=this,o=[i(t.interaction.clear,"click",(()=>this._clearColor())),i([t.interaction.cancel,t.preview.lastColor],"click",(()=>{this.setHSVA(...(this._lastColor||this._color).toHSVA(),!0),this._emit("cancel");})),i(t.interaction.save,"click",(()=>{!this.applyColor()&&!e.showAlways&&this.hide();})),i(t.interaction.result,["keyup","input"],(t=>{this.setColor(t.target.value,!0)&&!this._initializingActive&&(this._emit("change",this._color,"input",this),this._emit("changestop","input",this)),t.stopImmediatePropagation();})),i(t.interaction.result,["focus","blur"],(t=>{this._recalc="blur"===t.type,this._recalc&&this._updateOutput(null);})),i([t.palette.palette,t.palette.picker,t.hue.slider,t.hue.picker,t.opacity.slider,t.opacity.picker],["mousedown","touchstart"],(()=>this._recalc=!0),{passive:!0})];if(!e.showAlways){const n=e.closeWithKey;o.push(i(t.button,"click",(()=>this.isOpen()?this.hide():this.show())),i(document,"keyup",(t=>this.isOpen()&&(t.key===n||t.code===n)&&this.hide())),i(document,["touchstart","mousedown"],(e=>{this.isOpen()&&!l(e).some((e=>e===t.app||e===t.button))&&this.hide();}),{capture:!0}));}if(e.adjustableNumbers){const e={rgba:[255,255,255,1],hsva:[360,100,100,1],hsla:[360,100,100,1],cmyk:[100,100,100,100]};p(t.interaction.result,((t,o,n)=>{const i=e[this.getColorRepresentation().toLowerCase()];if(i){const e=i[n],s=t+(e>=100?1e3*o:o);return s<=0?0:Number((s<e?s:e).toPrecision(3))}return t}));}if(e.autoReposition&&!e.inline){let t=null;const n=this;o.push(i(window,["scroll","resize"],(()=>{n.isOpen()&&(e.closeOnScroll&&n.hide(),null===t?(t=setTimeout((()=>t=null),100),requestAnimationFrame((function e(){n._rePositioningPicker(),null!==t&&requestAnimationFrame(e);}))):(clearTimeout(t),t=setTimeout((()=>t=null),100)));}),{capture:!0}));}this._eventBindings=o;}_rePositioningPicker(){const{options:t}=this;if(!t.inline){if(!this._nanopop.update({container:document.body.getBoundingClientRect(),position:t.position})){const t=this._root.app,e=t.getBoundingClientRect();t.style.top=(window.innerHeight-e.height)/2+"px",t.style.left=(window.innerWidth-e.width)/2+"px";}}}_updateOutput(t){const{_root:e,_color:o,options:n}=this;if(e.interaction.type()){const t=`to${e.interaction.type().getAttribute("data-type")}`;e.interaction.result.value="function"==typeof o[t]?o[t]().toString(n.outputPrecision):"";}!this._initializingActive&&this._recalc&&this._emit("change",o,t,this);}_clearColor(t=!1){const{_root:e,options:o}=this;o.useAsButton||e.button.style.setProperty("--pcr-color","rgba(0, 0, 0, 0.15)"),e.button.classList.add("clear"),o.showAlways||this.hide(),this._lastColor=null,this._initializingActive||t||(this._emit("save",null),this._emit("clear"));}_parseLocalColor(t){const{values:e,type:o,a:n}=w(t),{lockOpacity:i}=this.options,s=void 0!==n&&1!==n;return e&&3===e.length&&(e[3]=void 0),{values:!e||i&&s?null:e,type:o}}_t(t){return this.options.i18n[t]||E.I18N_DEFAULTS[t]}_emit(t,...e){this._eventListener[t].forEach((t=>t(...e,this)));}on(t,e){return this._eventListener[t].push(e),this}off(t,e){const o=this._eventListener[t]||[],n=o.indexOf(e);return ~n&&o.splice(n,1),this}addSwatch(t){const{values:e}=this._parseLocalColor(t);if(e){const{_swatchColors:t,_root:o}=this,n=A(...e),s=r(`<button type="button" style="--pcr-color: ${n.toRGBA().toString(0)}" aria-label="${this._t("btn:swatch")}"/>`);return o.swatches.appendChild(s),t.push({el:s,color:n}),this._eventBindings.push(i(s,"click",(()=>{this.setHSVA(...n.toHSVA(),!0),this._emit("swatchselect",n),this._emit("change",n,"swatch",this);}))),!0}return !1}removeSwatch(t){const e=this._swatchColors[t];if(e){const{el:o}=e;return this._root.swatches.removeChild(o),this._swatchColors.splice(t,1),!0}return !1}applyColor(t=!1){const{preview:e,button:o}=this._root,n=this._color.toRGBA().toString(0);return e.lastColor.style.setProperty("--pcr-color",n),this.options.useAsButton||o.style.setProperty("--pcr-color",n),o.classList.remove("clear"),this._lastColor=this._color.clone(),this._initializingActive||t||this._emit("save",this._color),this}destroy(){cancelAnimationFrame(this._setupAnimationFrame),this._eventBindings.forEach((t=>s(...t))),Object.keys(this._components).forEach((t=>this._components[t].destroy()));}destroyAndRemove(){this.destroy();const{root:t,app:e}=this._root;t.parentElement&&t.parentElement.removeChild(t),e.parentElement.removeChild(e),Object.keys(this).forEach((t=>this[t]=null));}hide(){return !!this.isOpen()&&(this._root.app.classList.remove("visible"),this._emit("hide"),!0)}show(){return !this.options.disabled&&!this.isOpen()&&(this._root.app.classList.add("visible"),this._rePositioningPicker(),this._emit("show",this._color),this)}isOpen(){return this._root.app.classList.contains("visible")}setHSVA(t=360,e=0,o=0,n=1,i=!1){const s=this._recalc;if(this._recalc=!1,t<0||t>360||e<0||e>100||o<0||o>100||n<0||n>1)return !1;this._color=A(t,e,o,n);const{hue:r,opacity:a,palette:l}=this._components;return r.update(t/360),a.update(n),l.update(e/100,1-o/100),i||this.applyColor(),s&&this._updateOutput(),this._recalc=s,!0}setColor(t,e=!1){if(null===t)return this._clearColor(e),!0;const{values:o,type:n}=this._parseLocalColor(t);if(o){const t=n.toUpperCase(),{options:i}=this._root.interaction,s=i.find((e=>e.getAttribute("data-type")===t));if(s&&!s.hidden)for(const t of i)t.classList[t===s?"add":"remove"]("active");return !!this.setHSVA(...o,e)&&this.setColorRepresentation(t)}return !1}setColorRepresentation(t){return t=t.toUpperCase(),!!this._root.interaction.options.find((e=>e.getAttribute("data-type").startsWith(t)&&!e.click()))}getColorRepresentation(){return this._representation}getColor(){return this._color}getSelectedColor(){return this._lastColor}getRoot(){return this._root}disable(){return this.hide(),this.options.disabled=!0,this._root.button.classList.add("disabled"),this}enable(){return this.options.disabled=!1,this._root.button.classList.remove("disabled"),this}}return e=e.default})()));
  572. });
  573. var Pickr = /*@__PURE__*/getDefaultExportFromCjs(pickr_min);
  574. const DEFAULT_SETTINGS = {
  575. viewMode: ViewMode.Normal,
  576. viewImageInEditor: true,
  577. viewImageInCPB: true,
  578. viewImageWithLink: true,
  579. viewImageOther: true,
  580. // pinMode: false,
  581. pinMaximum: 3,
  582. pinCoverMode: true,
  583. imageMoveSpeed: 10,
  584. imgTipToggle: true,
  585. imgFullScreenMode: IMG_FULL_SCREEN_MODE.FIT,
  586. imgViewBackgroundColor: IMG_DEFAULT_BACKGROUND_COLOR,
  587. imageBorderToggle: false,
  588. imageBorderWidth: IMG_BORDER_WIDTH.MEDIUM,
  589. imageBorderStyle: IMG_BORDER_STYLE.SOLID,
  590. imageBorderColor: IMG_BORDER_COLOR.RED,
  591. galleryNavbarToggle: true,
  592. galleryNavbarDefaultColor: GALLERY_NAVBAR_DEFAULT_COLOR,
  593. galleryNavbarHoverColor: GALLERY_NAVBAR_HOVER_COLOR,
  594. galleryImgBorderActive: true,
  595. galleryImgBorderActiveColor: GALLERY_IMG_BORDER_ACTIVE_COLOR,
  596. // hotkeys conf
  597. moveTheImageHotkey: MOVE_THE_IMAGE.DEFAULT_HOTKEY,
  598. switchTheImageHotkey: SWITCH_THE_IMAGE.DEFAULT_HOTKEY,
  599. doubleClickToolbar: TOOLBAR_CONF[3].class,
  600. viewTriggerHotkey: MODIFIER_HOTKEYS.NONE
  601. };
  602. class ImageToolkitSettingTab extends obsidian.PluginSettingTab {
  603. constructor(app, plugin) {
  604. super(app, plugin);
  605. this.plugin = plugin;
  606. }
  607. display() {
  608. let { containerEl } = this;
  609. containerEl.empty();
  610. containerEl.createEl('h2', { text: t("IMAGE_TOOLKIT_SETTINGS_TITLE") });
  611. // Common Settings:
  612. this.displayCommonSettings(containerEl);
  613. // View Trigger Settings:
  614. this.displayViewTriggerSettings(containerEl);
  615. // Pin Mode Settings:
  616. this.displayPinModeSettings(containerEl);
  617. //region >>> VIEW_DETAILS_SETTINGS
  618. containerEl.createEl('h3', { text: t("VIEW_DETAILS_SETTINGS") });
  619. let imgMoveSpeedScaleText;
  620. new obsidian.Setting(containerEl)
  621. .setName(t("IMAGE_MOVE_SPEED_NAME"))
  622. .setDesc(t("IMAGE_MOVE_SPEED_DESC"))
  623. .addSlider(slider => slider
  624. .setLimits(1, 30, 1)
  625. .setValue(this.plugin.settings.imageMoveSpeed)
  626. .onChange((value) => __awaiter(this, void 0, void 0, function* () {
  627. imgMoveSpeedScaleText.innerText = " " + value.toString();
  628. this.plugin.settings.imageMoveSpeed = value;
  629. this.plugin.saveSettings();
  630. })))
  631. .settingEl.createDiv('', (el) => {
  632. imgMoveSpeedScaleText = el;
  633. el.style.minWidth = "2.3em";
  634. el.style.textAlign = "right";
  635. el.innerText = " " + this.plugin.settings.imageMoveSpeed.toString();
  636. });
  637. new obsidian.Setting(containerEl)
  638. .setName(t("IMAGE_TIP_TOGGLE_NAME"))
  639. .setDesc(t("IMAGE_TIP_TOGGLE_DESC"))
  640. .addToggle(toggle => toggle
  641. .setValue(this.plugin.settings.imgTipToggle)
  642. .onChange((value) => __awaiter(this, void 0, void 0, function* () {
  643. this.plugin.settings.imgTipToggle = value;
  644. yield this.plugin.saveSettings();
  645. })));
  646. new obsidian.Setting(containerEl)
  647. .setName(t("IMG_FULL_SCREEN_MODE_NAME"))
  648. .addDropdown((dropdown) => __awaiter(this, void 0, void 0, function* () {
  649. for (const key in IMG_FULL_SCREEN_MODE) {
  650. // @ts-ignore
  651. dropdown.addOption(key, t(key));
  652. }
  653. dropdown.setValue(this.plugin.settings.imgFullScreenMode);
  654. dropdown.onChange((option) => __awaiter(this, void 0, void 0, function* () {
  655. this.plugin.settings.imgFullScreenMode = option;
  656. yield this.plugin.saveSettings();
  657. }));
  658. }));
  659. this.createPickrSetting(containerEl, 'IMG_VIEW_BACKGROUND_COLOR_NAME', IMG_DEFAULT_BACKGROUND_COLOR);
  660. //endregion
  661. //region >>> IMAGE_BORDER_SETTINGS
  662. containerEl.createEl('h3', { text: t("IMAGE_BORDER_SETTINGS") });
  663. new obsidian.Setting(containerEl)
  664. .setName(t("IMAGE_BORDER_TOGGLE_NAME"))
  665. .setDesc(t("IMAGE_BORDER_TOGGLE_DESC"))
  666. .addToggle(toggle => toggle
  667. .setValue(this.plugin.settings.imageBorderToggle)
  668. .onChange((value) => __awaiter(this, void 0, void 0, function* () {
  669. this.plugin.settings.imageBorderToggle = value;
  670. yield this.plugin.saveSettings();
  671. })));
  672. new obsidian.Setting(containerEl)
  673. .setName(t("IMAGE_BORDER_WIDTH_NAME"))
  674. .addDropdown((dropdown) => __awaiter(this, void 0, void 0, function* () {
  675. for (const key in IMG_BORDER_WIDTH) {
  676. // @ts-ignore
  677. dropdown.addOption(IMG_BORDER_WIDTH[key], t(key));
  678. }
  679. dropdown.setValue(this.plugin.settings.imageBorderWidth);
  680. dropdown.onChange((option) => __awaiter(this, void 0, void 0, function* () {
  681. this.plugin.settings.imageBorderWidth = option;
  682. yield this.plugin.saveSettings();
  683. }));
  684. }));
  685. new obsidian.Setting(containerEl)
  686. .setName(t("IMAGE_BORDER_STYLE_NAME"))
  687. .addDropdown((dropdown) => __awaiter(this, void 0, void 0, function* () {
  688. for (const key in IMG_BORDER_STYLE) {
  689. // @ts-ignore
  690. dropdown.addOption(IMG_BORDER_STYLE[key], t(key));
  691. }
  692. dropdown.setValue(this.plugin.settings.imageBorderStyle);
  693. dropdown.onChange((option) => __awaiter(this, void 0, void 0, function* () {
  694. this.plugin.settings.imageBorderStyle = option;
  695. yield this.plugin.saveSettings();
  696. }));
  697. }));
  698. new obsidian.Setting(containerEl)
  699. .setName(t("IMAGE_BORDER_COLOR_NAME"))
  700. .addDropdown((dropdown) => __awaiter(this, void 0, void 0, function* () {
  701. for (const key in IMG_BORDER_COLOR) {
  702. // @ts-ignore
  703. dropdown.addOption(IMG_BORDER_COLOR[key], t(key));
  704. }
  705. dropdown.setValue(this.plugin.settings.imageBorderColor);
  706. dropdown.onChange((option) => __awaiter(this, void 0, void 0, function* () {
  707. this.plugin.settings.imageBorderColor = option;
  708. yield this.plugin.saveSettings();
  709. }));
  710. }));
  711. //endregion
  712. //region >>> GALLERY_NAVBAR_SETTINGS
  713. let galleryNavbarDefaultColorSetting, galleryNavbarHoverColorSetting, galleryImgBorderToggleSetting, galleryImgBorderActiveColorSetting;
  714. containerEl.createEl('h3', { text: t("GALLERY_NAVBAR_SETTINGS") });
  715. new obsidian.Setting(containerEl)
  716. .setName(t("GALLERY_NAVBAR_TOGGLE_NAME"))
  717. .setDesc(t("GALLERY_NAVBAR_TOGGLE_DESC"))
  718. .addToggle(toggle => toggle
  719. .setValue(this.plugin.settings.galleryNavbarToggle)
  720. .onChange((value) => __awaiter(this, void 0, void 0, function* () {
  721. this.plugin.settings.galleryNavbarToggle = value;
  722. this.switchSettingsDisabled(!value, galleryNavbarDefaultColorSetting, galleryNavbarHoverColorSetting, galleryImgBorderToggleSetting, galleryImgBorderActiveColorSetting);
  723. yield this.plugin.saveSettings();
  724. })));
  725. galleryNavbarDefaultColorSetting = this.createPickrSetting(containerEl, 'GALLERY_NAVBAR_DEFAULT_COLOR_NAME', GALLERY_NAVBAR_DEFAULT_COLOR);
  726. galleryNavbarHoverColorSetting = this.createPickrSetting(containerEl, 'GALLERY_NAVBAR_HOVER_COLOR_NAME', GALLERY_NAVBAR_HOVER_COLOR);
  727. galleryImgBorderToggleSetting = new obsidian.Setting(containerEl)
  728. .setName(t("GALLERY_IMG_BORDER_TOGGLE_NAME"))
  729. .setDesc(t("GALLERY_IMG_BORDER_TOGGLE_DESC"))
  730. .addToggle(toggle => toggle
  731. .setValue(this.plugin.settings.galleryImgBorderActive)
  732. .onChange((value) => __awaiter(this, void 0, void 0, function* () {
  733. this.plugin.settings.galleryImgBorderActive = value;
  734. yield this.plugin.saveSettings();
  735. })));
  736. galleryImgBorderActiveColorSetting = this.createPickrSetting(containerEl, 'GALLERY_IMG_BORDER_ACTIVE_COLOR_NAME', GALLERY_IMG_BORDER_ACTIVE_COLOR);
  737. this.switchSettingsDisabled(!this.plugin.settings.galleryNavbarToggle, galleryNavbarDefaultColorSetting, galleryNavbarHoverColorSetting, galleryImgBorderToggleSetting, galleryImgBorderActiveColorSetting);
  738. //endregion
  739. //region >>> HOTKEYS_SETTINGS
  740. containerEl.createEl('h3', { text: t("HOTKEY_SETTINGS") });
  741. containerEl.createEl('p', { text: t("HOTKEY_SETTINGS_DESC") });
  742. if (this.plugin.settings.moveTheImageHotkey === this.plugin.settings.switchTheImageHotkey) {
  743. this.plugin.settings.moveTheImageHotkey = MOVE_THE_IMAGE.DEFAULT_HOTKEY;
  744. }
  745. const moveTheImageSetting = new obsidian.Setting(containerEl)
  746. .setName(t("MOVE_THE_IMAGE_NAME"))
  747. .setDesc(t("MOVE_THE_IMAGE_DESC"))
  748. .addDropdown((dropdown) => __awaiter(this, void 0, void 0, function* () {
  749. dropdown.addOptions(this.getDropdownOptions());
  750. dropdown.setValue(this.plugin.settings.moveTheImageHotkey);
  751. dropdown.onChange((option) => __awaiter(this, void 0, void 0, function* () {
  752. this.plugin.settings.moveTheImageHotkey = option;
  753. this.checkDropdownOptions(MOVE_THE_IMAGE.CODE, switchTheImageSetting);
  754. yield this.plugin.saveSettings();
  755. }));
  756. })).then((setting) => {
  757. setting.controlEl.appendChild(createDiv('setting-editor-extra-setting-button hotkeys-settings-plus', (el) => {
  758. el.innerHTML = "+";
  759. }));
  760. setting.controlEl.appendChild(createDiv('setting-editor-extra-setting-button', (el) => {
  761. el.innerHTML = MOVE_THE_IMAGE.SVG;
  762. }));
  763. });
  764. if (this.plugin.settings.switchTheImageHotkey === this.plugin.settings.moveTheImageHotkey) {
  765. this.plugin.settings.switchTheImageHotkey = SWITCH_THE_IMAGE.DEFAULT_HOTKEY;
  766. }
  767. const switchTheImageSetting = new obsidian.Setting(containerEl)
  768. .setName(t("SWITCH_THE_IMAGE_NAME"))
  769. .setDesc(t("SWITCH_THE_IMAGE_DESC"))
  770. .addDropdown((dropdown) => __awaiter(this, void 0, void 0, function* () {
  771. dropdown.addOptions(this.getDropdownOptions());
  772. dropdown.setValue(this.plugin.settings.switchTheImageHotkey);
  773. dropdown.onChange((option) => __awaiter(this, void 0, void 0, function* () {
  774. this.plugin.settings.switchTheImageHotkey = option;
  775. this.checkDropdownOptions(SWITCH_THE_IMAGE.CODE, moveTheImageSetting);
  776. yield this.plugin.saveSettings();
  777. }));
  778. })).then((setting) => {
  779. setting.controlEl.appendChild(createDiv('setting-editor-extra-setting-button hotkeys-settings-plus', (el) => {
  780. el.innerHTML = "+";
  781. }));
  782. setting.controlEl.appendChild(createDiv('setting-editor-extra-setting-button', (el) => {
  783. el.innerHTML = SWITCH_THE_IMAGE.SVG;
  784. }));
  785. });
  786. if (switchTheImageSetting) {
  787. this.checkDropdownOptions(MOVE_THE_IMAGE.CODE, switchTheImageSetting);
  788. }
  789. if (moveTheImageSetting) {
  790. this.checkDropdownOptions(SWITCH_THE_IMAGE.CODE, moveTheImageSetting);
  791. }
  792. new obsidian.Setting(containerEl)
  793. .setName(t("DOUBLE_CLICK_TOOLBAR_NAME"))
  794. .addDropdown((dropdown) => __awaiter(this, void 0, void 0, function* () {
  795. for (const conf of TOOLBAR_CONF) {
  796. if (!conf.enableHotKey)
  797. continue;
  798. // @ts-ignore
  799. dropdown.addOption(conf.class, t(conf.title));
  800. }
  801. dropdown.setValue(this.plugin.settings.doubleClickToolbar);
  802. dropdown.onChange((option) => __awaiter(this, void 0, void 0, function* () {
  803. this.plugin.settings.doubleClickToolbar = option;
  804. yield this.plugin.saveSettings();
  805. }));
  806. }));
  807. new obsidian.Setting(containerEl)
  808. .setName(t("VIEW_TRIGGER_HOTKEY_NAME"))
  809. .setDesc(t("VIEW_TRIGGER_HOTKEY_DESC"))
  810. .addDropdown((dropdown) => __awaiter(this, void 0, void 0, function* () {
  811. dropdown.addOptions(this.getDropdownOptions());
  812. dropdown.setValue(this.plugin.settings.viewTriggerHotkey);
  813. dropdown.onChange((option) => __awaiter(this, void 0, void 0, function* () {
  814. this.plugin.settings.viewTriggerHotkey = option;
  815. yield this.plugin.saveSettings();
  816. }));
  817. }));
  818. //endregion
  819. }
  820. displayCommonSettings(containerEl) {
  821. containerEl.createEl('h3', { text: t('COMMON_SETTINGS') });
  822. new obsidian.Setting(containerEl)
  823. .setName(t("VIEW_MODE_NAME"))
  824. .addDropdown((dropdown) => __awaiter(this, void 0, void 0, function* () {
  825. for (const key in ViewMode) {
  826. // @ts-ignore
  827. dropdown.addOption(key, t('VIEW_MODE_' + key.toUpperCase()));
  828. }
  829. dropdown.setValue(this.plugin.settings.viewMode);
  830. dropdown.onChange((option) => __awaiter(this, void 0, void 0, function* () {
  831. yield this.plugin.switchViewMode(option);
  832. }));
  833. }));
  834. }
  835. displayViewTriggerSettings(containerEl) {
  836. containerEl.createEl('h3', { text: t("VIEW_TRIGGER_SETTINGS") });
  837. new obsidian.Setting(containerEl)
  838. .setName(t("VIEW_IMAGE_IN_EDITOR_NAME"))
  839. .setDesc(t("VIEW_IMAGE_IN_EDITOR_DESC"))
  840. .addToggle(toggle => toggle
  841. .setValue(this.plugin.settings.viewImageInEditor)
  842. .onChange((value) => __awaiter(this, void 0, void 0, function* () {
  843. this.plugin.settings.viewImageInEditor = value;
  844. this.plugin.refreshViewTrigger();
  845. yield this.plugin.saveSettings();
  846. })));
  847. new obsidian.Setting(containerEl)
  848. .setName(t("VIEW_IMAGE_IN_CPB_NAME"))
  849. .setDesc(t("VIEW_IMAGE_IN_CPB_DESC"))
  850. .addToggle(toggle => toggle
  851. .setValue(this.plugin.settings.viewImageInCPB)
  852. .onChange((value) => __awaiter(this, void 0, void 0, function* () {
  853. this.plugin.settings.viewImageInCPB = value;
  854. this.plugin.refreshViewTrigger();
  855. yield this.plugin.saveSettings();
  856. })));
  857. new obsidian.Setting(containerEl)
  858. .setName(t("VIEW_IMAGE_WITH_A_LINK_NAME"))
  859. .setDesc(t("VIEW_IMAGE_WITH_A_LINK_DESC"))
  860. .addToggle(toggle => toggle
  861. .setValue(this.plugin.settings.viewImageWithLink)
  862. .onChange((value) => __awaiter(this, void 0, void 0, function* () {
  863. this.plugin.settings.viewImageWithLink = value;
  864. this.plugin.refreshViewTrigger();
  865. yield this.plugin.saveSettings();
  866. })));
  867. new obsidian.Setting(containerEl)
  868. .setName(t("VIEW_IMAGE_OTHER_NAME"))
  869. .setDesc(t("VIEW_IMAGE_OTHER_DESC"))
  870. .addToggle(toggle => toggle
  871. .setValue(this.plugin.settings.viewImageOther)
  872. .onChange((value) => __awaiter(this, void 0, void 0, function* () {
  873. this.plugin.settings.viewImageOther = value;
  874. this.plugin.refreshViewTrigger();
  875. yield this.plugin.saveSettings();
  876. })));
  877. }
  878. displayPinModeSettings(containerEl) {
  879. //region >>> PIN_MODE_SETTINGS
  880. let pinMaximumSetting;
  881. containerEl.createEl('h3', { text: t("PIN_MODE_SETTINGS") });
  882. /*new Setting(containerEl)
  883. .setName(t("PIN_MODE_NAME"))
  884. .setDesc(t("PIN_MODE_DESC"))
  885. .addToggle(toggle => toggle
  886. .setValue(this.plugin.settings.pinMode)
  887. .onChange(async (value) => {
  888. this.plugin.settings.pinMode = value;
  889. this.switchSettingsDisabled(!value, pinMaximumSetting, pinCoverSetting);
  890. //this.plugin.togglePinMode(value);
  891. await this.plugin.saveSettings();
  892. }));*/
  893. let pinMaximumScaleText;
  894. pinMaximumSetting = new obsidian.Setting(containerEl)
  895. .setName(t("PIN_MAXIMUM_NAME"))
  896. .addSlider(slider => slider
  897. .setLimits(1, 5, 1)
  898. .setValue(this.plugin.settings.pinMaximum)
  899. .onChange((value) => __awaiter(this, void 0, void 0, function* () {
  900. pinMaximumScaleText.innerText = " " + value.toString();
  901. this.plugin.settings.pinMaximum = value;
  902. // this.plugin.containerView?.setPinMaximum(value);
  903. this.plugin.saveSettings();
  904. })));
  905. pinMaximumSetting.settingEl.createDiv('', (el) => {
  906. pinMaximumScaleText = el;
  907. el.style.minWidth = "2.3em";
  908. el.style.textAlign = "right";
  909. el.innerText = " " + this.plugin.settings.pinMaximum.toString();
  910. });
  911. new obsidian.Setting(containerEl)
  912. .setName(t("PIN_COVER_NAME"))
  913. .setDesc(t("PIN_COVER_DESC"))
  914. .addToggle(toggle => toggle
  915. .setValue(this.plugin.settings.pinCoverMode)
  916. .onChange((value) => __awaiter(this, void 0, void 0, function* () {
  917. this.plugin.settings.pinCoverMode = value;
  918. yield this.plugin.saveSettings();
  919. })));
  920. //this.switchSettingsDisabled(!this.plugin.settings.pinMode, pinMaximumSetting, pinCoverSetting);
  921. //endregion
  922. }
  923. switchSettingsDisabled(disabled, ...settings) {
  924. for (const setting of settings) {
  925. setting === null || setting === void 0 ? void 0 : setting.setDisabled(disabled);
  926. }
  927. }
  928. createPickrSetting(containerEl, name, defaultColor) {
  929. let pickrDefault;
  930. if ('GALLERY_NAVBAR_DEFAULT_COLOR_NAME' === name) {
  931. pickrDefault = this.plugin.settings.galleryNavbarDefaultColor;
  932. }
  933. else if ('GALLERY_NAVBAR_HOVER_COLOR_NAME' === name) {
  934. pickrDefault = this.plugin.settings.galleryNavbarHoverColor;
  935. }
  936. else if ('GALLERY_IMG_BORDER_ACTIVE_COLOR_NAME' === name) {
  937. pickrDefault = this.plugin.settings.galleryImgBorderActiveColor;
  938. }
  939. else if ('IMG_VIEW_BACKGROUND_COLOR_NAME' === name) {
  940. pickrDefault = this.plugin.settings.imgViewBackgroundColor;
  941. }
  942. else {
  943. pickrDefault = defaultColor;
  944. }
  945. let pickr;
  946. return new obsidian.Setting(containerEl)
  947. // @ts-ignore
  948. .setName(t(name))
  949. .then((setting) => {
  950. pickr = Pickr.create({
  951. el: setting.controlEl.createDiv({ cls: "picker" }),
  952. theme: 'nano',
  953. position: "left-middle",
  954. lockOpacity: false,
  955. default: pickrDefault,
  956. swatches: [],
  957. components: {
  958. preview: true,
  959. hue: true,
  960. opacity: true,
  961. interaction: {
  962. hex: true,
  963. rgba: true,
  964. hsla: false,
  965. input: true,
  966. cancel: true,
  967. save: true,
  968. },
  969. }
  970. })
  971. .on('show', (color, instance) => {
  972. if (!this.plugin.settings.galleryNavbarToggle)
  973. pickr === null || pickr === void 0 ? void 0 : pickr.hide();
  974. const { result } = pickr.getRoot().interaction;
  975. requestAnimationFrame(() => requestAnimationFrame(() => result.select()));
  976. })
  977. .on('save', (color, instance) => {
  978. if (!color)
  979. return;
  980. instance.hide();
  981. const savedColor = color.toHEXA().toString();
  982. instance.addSwatch(savedColor);
  983. this.setAndSavePickrSetting(name, savedColor);
  984. })
  985. .on('cancel', (instance) => {
  986. instance.hide();
  987. });
  988. })
  989. .addExtraButton((btn) => {
  990. btn.setIcon("reset")
  991. .onClick(() => {
  992. pickr.setColor(defaultColor);
  993. this.setAndSavePickrSetting(name, defaultColor);
  994. })
  995. .setTooltip('restore default color');
  996. });
  997. }
  998. setAndSavePickrSetting(name, savedColor) {
  999. if ('GALLERY_NAVBAR_DEFAULT_COLOR_NAME' === name) {
  1000. this.plugin.settings.galleryNavbarDefaultColor = savedColor;
  1001. }
  1002. else if ('GALLERY_NAVBAR_HOVER_COLOR_NAME' === name) {
  1003. this.plugin.settings.galleryNavbarHoverColor = savedColor;
  1004. }
  1005. else if ('GALLERY_IMG_BORDER_ACTIVE_COLOR_NAME' === name) {
  1006. this.plugin.settings.galleryImgBorderActiveColor = savedColor;
  1007. }
  1008. else if ('IMG_VIEW_BACKGROUND_COLOR_NAME' === name) {
  1009. this.plugin.settings.imgViewBackgroundColor = savedColor;
  1010. // this.plugin.containerView?.setImgViewDefaultBackgroundForImgList();
  1011. this.plugin.getAllContainerViews().forEach(container => {
  1012. container.setImgViewDefaultBackgroundForImgList();
  1013. });
  1014. }
  1015. this.plugin.saveSettings();
  1016. }
  1017. getDropdownOptions() {
  1018. let options = {};
  1019. for (const key in MODIFIER_HOTKEYS) {
  1020. //@ts-ignore
  1021. options[key] = t(key);
  1022. }
  1023. return options;
  1024. }
  1025. checkDropdownOptions(code, setting) {
  1026. if (!setting || !setting.controlEl)
  1027. return;
  1028. const optionElList = setting.controlEl.getElementsByClassName('dropdown')[0].getElementsByTagName('option');
  1029. for (let i = 0, size = optionElList.length; i < size; i++) {
  1030. if (code === MOVE_THE_IMAGE.CODE) {
  1031. optionElList[i].disabled = optionElList[i].value === this.plugin.settings.moveTheImageHotkey;
  1032. }
  1033. else if (code === SWITCH_THE_IMAGE.CODE) {
  1034. optionElList[i].disabled = optionElList[i].value === this.plugin.settings.switchTheImageHotkey;
  1035. }
  1036. }
  1037. }
  1038. }
  1039. /**
  1040. * ts class object: image operating status
  1041. */
  1042. class ImgStatusCto {
  1043. constructor() {
  1044. // true: the popup layer of viewing image is displayed
  1045. this.popup = false;
  1046. // whether the image is being dragged
  1047. this.dragging = false;
  1048. // keybord pressing status
  1049. this.arrowUp = false;
  1050. this.arrowDown = false;
  1051. this.arrowLeft = false;
  1052. this.arrowRight = false;
  1053. this.fullScreen = false;
  1054. this.activeImgZIndex = 0; /*--layer-status-bar*/
  1055. this.clickCount = 0;
  1056. }
  1057. }
  1058. /**
  1059. * ts class object: image information including all html elements
  1060. */
  1061. class ImgInfoCto {
  1062. constructor() {
  1063. this.imgList = new Array();
  1064. this.getPopupImgNum = () => {
  1065. let num = 0;
  1066. for (const imgCto of this.imgList) {
  1067. if (imgCto.popup)
  1068. num++;
  1069. }
  1070. return num;
  1071. };
  1072. }
  1073. }
  1074. class ImgCto {
  1075. constructor(index, mtime, imgViewEl) {
  1076. this.popup = false;
  1077. this.zIndex = 0;
  1078. this.curWidth = 0; // image's current width
  1079. this.curHeight = 0;
  1080. this.realWidth = 0; // image's real width
  1081. this.realHeight = 0;
  1082. this.left = 0; // margin-left
  1083. this.top = 0; // margin-top
  1084. this.moveX = 0; // 鼠标相对于图片的位置
  1085. this.moveY = 0;
  1086. this.rotate = 0; // rotateDeg
  1087. this.invertColor = false;
  1088. this.scaleX = false; // scaleX(-1)
  1089. this.scaleY = false; // scaleY(-1)
  1090. this.fullScreen = false; // whether the image is being previewed in full-screen mode
  1091. this.defaultImgStyle = {
  1092. transform: 'none',
  1093. filter: 'none',
  1094. mixBlendMode: 'normal',
  1095. borderWidth: '',
  1096. borderStyle: '',
  1097. borderColor: ''
  1098. };
  1099. this.index = index;
  1100. this.mtime = mtime;
  1101. this.imgViewEl = imgViewEl;
  1102. }
  1103. }
  1104. /**
  1105. * Image utility class
  1106. */
  1107. class ImgUtil {
  1108. static copyText(text) {
  1109. navigator.clipboard.writeText(text)
  1110. .then(() => {
  1111. //console.log('copyText:', copyText);
  1112. })
  1113. .catch(err => {
  1114. console.error('copy text error', err);
  1115. });
  1116. }
  1117. static copyImage(imgEle, width, height) {
  1118. let image = new Image();
  1119. image.crossOrigin = 'anonymous';
  1120. image.src = imgEle.src;
  1121. image.onload = () => {
  1122. const canvas = document.createElement('canvas');
  1123. canvas.width = image.width;
  1124. canvas.height = image.height;
  1125. const ctx = canvas.getContext('2d');
  1126. ctx.fillStyle = '#fff';
  1127. ctx.fillRect(0, 0, canvas.width, canvas.height);
  1128. ctx.drawImage(image, 0, 0);
  1129. try {
  1130. canvas.toBlob((blob) => __awaiter(this, void 0, void 0, function* () {
  1131. yield navigator.clipboard.write([new ClipboardItem({ "image/png": blob })])
  1132. .then(() => {
  1133. new obsidian.Notice(t("COPY_IMAGE_SUCCESS"));
  1134. }, () => {
  1135. new obsidian.Notice(t("COPY_IMAGE_ERROR"));
  1136. });
  1137. }));
  1138. }
  1139. catch (error) {
  1140. new obsidian.Notice(t("COPY_IMAGE_ERROR"));
  1141. console.error(error);
  1142. }
  1143. };
  1144. image.onerror = () => {
  1145. new obsidian.Notice(t("COPY_IMAGE_ERROR"));
  1146. };
  1147. }
  1148. }
  1149. ImgUtil.calculateImgZoomSize = (realImg, imgCto, windowWidth, windowHeight) => {
  1150. if (!windowWidth) {
  1151. windowWidth = document.documentElement.clientWidth || document.body.clientWidth;
  1152. }
  1153. if (!windowHeight) {
  1154. windowHeight = (document.documentElement.clientHeight || document.body.clientHeight) - 100;
  1155. }
  1156. const windowZoomWidth = windowWidth * ZOOM_FACTOR;
  1157. const windowZoomHeight = windowHeight * ZOOM_FACTOR;
  1158. let tempWidth = realImg.width, tempHeight = realImg.height;
  1159. if (realImg.height > windowZoomHeight) {
  1160. tempHeight = windowZoomHeight;
  1161. if ((tempWidth = tempHeight / realImg.height * realImg.width) > windowZoomWidth) {
  1162. tempWidth = windowZoomWidth;
  1163. }
  1164. }
  1165. else if (realImg.width > windowZoomWidth) {
  1166. tempWidth = windowZoomWidth;
  1167. tempHeight = tempWidth / realImg.width * realImg.height;
  1168. }
  1169. tempHeight = tempWidth * realImg.height / realImg.width;
  1170. // cache image info: curWidth, curHeight, realWidth, realHeight, left, top
  1171. imgCto.left = (windowWidth - tempWidth) / 2;
  1172. imgCto.top = (windowHeight - tempHeight) / 2;
  1173. imgCto.curWidth = tempWidth;
  1174. imgCto.curHeight = tempHeight;
  1175. imgCto.realWidth = realImg.width;
  1176. imgCto.realHeight = realImg.height;
  1177. /* console.log('calculateImgZoomSize', 'realImg: ' + realImg.width + ',' + realImg.height,
  1178. 'tempSize: ' + tempWidth + ',' + tempHeight,
  1179. 'windowZoomSize: ' + windowZoomWidth + ',' + windowZoomHeight,
  1180. 'windowSize: ' + windowWidth + ',' + windowHeight); */
  1181. return imgCto;
  1182. };
  1183. /**
  1184. * zoom an image
  1185. * @param ratio
  1186. * @param targetImgInfo
  1187. * @param offsetSize
  1188. * @param actualSize
  1189. * @returns
  1190. */
  1191. ImgUtil.zoom = (ratio, targetImgInfo, offsetSize, actualSize) => {
  1192. let zoomRatio;
  1193. if (!actualSize) {
  1194. const zoomInFlag = ratio > 0;
  1195. ratio = zoomInFlag ? 1 + ratio : 1 / (1 - ratio);
  1196. zoomRatio = targetImgInfo.curWidth * ratio / targetImgInfo.realWidth;
  1197. }
  1198. // Snap to 100% zoom when we pass over it
  1199. const curRatio = targetImgInfo.curWidth / targetImgInfo.realWidth;
  1200. if (actualSize || (curRatio < 1 && zoomRatio > 1) || (curRatio > 1 && zoomRatio < 1)) {
  1201. // set zoom ratio to 100%
  1202. zoomRatio = 1;
  1203. // reduce snap offset ratio accordingly
  1204. ratio = 1 / curRatio;
  1205. }
  1206. let newWidth = targetImgInfo.realWidth * zoomRatio;
  1207. let newHeight = targetImgInfo.realHeight * zoomRatio;
  1208. if (IMG_VIEW_MIN >= newWidth || IMG_VIEW_MIN >= newHeight) {
  1209. // set minimum width or height
  1210. if (IMG_VIEW_MIN >= newWidth) {
  1211. newWidth = IMG_VIEW_MIN;
  1212. newHeight = (newWidth * targetImgInfo.realHeight) / targetImgInfo.realWidth;
  1213. }
  1214. else {
  1215. newHeight = IMG_VIEW_MIN;
  1216. newWidth = (newHeight * targetImgInfo.realWidth) / targetImgInfo.realHeight;
  1217. }
  1218. ratio = 1;
  1219. }
  1220. const left = targetImgInfo.left + offsetSize.offsetX * (1 - ratio);
  1221. const top = targetImgInfo.top + offsetSize.offsetY * (1 - ratio);
  1222. // cache image info: curWidth, curHeight, left, top
  1223. targetImgInfo.curWidth = newWidth;
  1224. targetImgInfo.curHeight = newHeight;
  1225. targetImgInfo.left = left;
  1226. targetImgInfo.top = top;
  1227. // return { newWidth, left, top };
  1228. return targetImgInfo;
  1229. };
  1230. ImgUtil.transform = (targetImgInfo) => {
  1231. let transform = 'rotate(' + targetImgInfo.rotate + 'deg)';
  1232. if (targetImgInfo.scaleX) {
  1233. transform += ' scaleX(-1)';
  1234. }
  1235. if (targetImgInfo.scaleY) {
  1236. transform += ' scaleY(-1)';
  1237. }
  1238. targetImgInfo.imgViewEl.style.setProperty('transform', transform);
  1239. };
  1240. ImgUtil.rotate = (degree, targetImgInfo) => {
  1241. targetImgInfo.imgViewEl.style.setProperty('transform', 'rotate(' + (targetImgInfo.rotate += degree) + 'deg)');
  1242. };
  1243. ImgUtil.invertImgColor = (imgEle, open) => {
  1244. if (open) {
  1245. imgEle.style.setProperty('filter', 'invert(1) hue-rotate(180deg)');
  1246. imgEle.style.setProperty('mix-blend-mode', 'screen');
  1247. }
  1248. else {
  1249. imgEle.style.setProperty('filter', 'none');
  1250. imgEle.style.setProperty('mix-blend-mode', 'normal');
  1251. }
  1252. // open ? imgEle.addClass('image-toolkit-img-invert') : imgEle.removeClass('image-toolkit-img-invert');
  1253. };
  1254. class ContainerView {
  1255. constructor(plugin) {
  1256. this.lastClickedImgDefaultStyle = {
  1257. borderWidth: '',
  1258. borderStyle: '',
  1259. borderColor: ''
  1260. };
  1261. this.imgGlobalStatus = new ImgStatusCto();
  1262. this.imgInfo = new ImgInfoCto();
  1263. this.getViewMode = () => {
  1264. return this.plugin.settings.viewMode;
  1265. };
  1266. this.isPinMode = () => {
  1267. return ViewMode.Pin === this.getViewMode();
  1268. };
  1269. this.isNormalMode = () => {
  1270. return ViewMode.Normal === this.getViewMode();
  1271. };
  1272. this.setMenuView = (menuView) => {
  1273. this.menuView = menuView;
  1274. };
  1275. this.getPlugin = () => {
  1276. return this.plugin;
  1277. };
  1278. this.getLastClickedImgEl = () => {
  1279. return this.lastClickedImgEl;
  1280. };
  1281. this.getActiveImg = () => {
  1282. return this.imgGlobalStatus.activeImg;
  1283. };
  1284. this.getDoc = () => {
  1285. return this.doc;
  1286. };
  1287. /*public setPinMaximum = (val: number) => {
  1288. this.pinMaximum = val;
  1289. }*/
  1290. this.getOitContainerViewEl = () => {
  1291. return this.imgInfo.imgContainerEl;
  1292. };
  1293. this.getParentContainerEl = (targetEl) => {
  1294. if (!targetEl) {
  1295. return this.parentContainerEl;
  1296. }
  1297. if (!this.parentContainerEl) {
  1298. this.parentContainerEl = targetEl.matchParent('body');
  1299. this.doc = this.parentContainerEl.ownerDocument;
  1300. }
  1301. return this.parentContainerEl;
  1302. };
  1303. //region ================== Container View & Init ========================
  1304. /**
  1305. * Render when clicking an image (core step)
  1306. * @param targetEl clicked image's element
  1307. * @returns
  1308. */
  1309. this.renderContainer = (targetEl) => {
  1310. if (!this.checkStatus())
  1311. return;
  1312. const matchedImg = this.initContainerView(targetEl, this.getParentContainerEl(targetEl));
  1313. if (!matchedImg)
  1314. return;
  1315. this.openOitContainerView(matchedImg);
  1316. this.renderGalleryNavbar();
  1317. this.refreshImg(matchedImg, targetEl.src, targetEl.alt);
  1318. matchedImg.mtime = new Date().getTime();
  1319. };
  1320. /**
  1321. * initContainerDom ->
  1322. * @param targetEl
  1323. * @param parentContainerEl targetEl's body
  1324. */
  1325. this.initContainerView = (targetEl, parentContainerEl) => {
  1326. const matchedImg = this.initContainerDom(parentContainerEl);
  1327. if (!matchedImg)
  1328. return null;
  1329. matchedImg.targetOriginalImgEl = targetEl;
  1330. this.restoreBorderForLastClickedImg();
  1331. this.initDefaultData(matchedImg, window.getComputedStyle(targetEl));
  1332. this.addBorderForLastClickedImg(targetEl);
  1333. this.addOrRemoveEvents(matchedImg, true); // add events
  1334. return matchedImg;
  1335. };
  1336. this.removeOitContainerView = () => {
  1337. var _a;
  1338. this.restoreBorderForLastClickedImg();
  1339. this.removeGalleryNavbar();
  1340. (_a = this.imgInfo.oitContainerEl) === null || _a === void 0 ? void 0 : _a.remove();
  1341. this.imgInfo.oitContainerEl = null;
  1342. this.imgInfo.imgContainerEl = null;
  1343. this.imgGlobalStatus.dragging = false;
  1344. this.imgGlobalStatus.popup = false;
  1345. this.imgGlobalStatus.activeImgZIndex = 0;
  1346. this.imgGlobalStatus.fullScreen = false;
  1347. this.imgGlobalStatus.activeImg = null;
  1348. // clear imgList
  1349. this.imgInfo.imgList.length = 0;
  1350. };
  1351. this.checkStatus = () => {
  1352. const viewMode = this.plugin.getViewMode();
  1353. if (!viewMode)
  1354. return false;
  1355. // none of popped-up-images
  1356. if (!this.imgGlobalStatus.popup)
  1357. return true;
  1358. // Pin mode && Cover mode
  1359. if (this.isPinMode() && this.plugin.settings.pinCoverMode)
  1360. return true;
  1361. // configured max images > current pop-up images
  1362. if (this.getConfiguredPinMaximum() > this.imgInfo.getPopupImgNum())
  1363. return true;
  1364. new obsidian.Notice(t("PIN_MAXIMUM_NOTICE"));
  1365. return false;
  1366. };
  1367. this.getConfiguredPinMaximum = () => {
  1368. if (this.isPinMode())
  1369. return this.plugin.settings.pinMaximum;
  1370. return 1;
  1371. };
  1372. this.initDefaultData = (matchedImg, targetImgStyle) => {
  1373. if (targetImgStyle) {
  1374. matchedImg.defaultImgStyle.transform = 'none';
  1375. matchedImg.defaultImgStyle.filter = targetImgStyle.filter;
  1376. matchedImg.defaultImgStyle.mixBlendMode = targetImgStyle.mixBlendMode;
  1377. matchedImg.defaultImgStyle.borderWidth = targetImgStyle.borderWidth;
  1378. matchedImg.defaultImgStyle.borderStyle = targetImgStyle.borderStyle;
  1379. matchedImg.defaultImgStyle.borderColor = targetImgStyle.borderColor;
  1380. this.lastClickedImgDefaultStyle.borderWidth = targetImgStyle.borderWidth;
  1381. this.lastClickedImgDefaultStyle.borderStyle = targetImgStyle.borderStyle;
  1382. this.lastClickedImgDefaultStyle.borderColor = targetImgStyle.borderColor;
  1383. }
  1384. this.imgGlobalStatus.dragging = false;
  1385. this.imgGlobalStatus.arrowUp = false;
  1386. this.imgGlobalStatus.arrowDown = false;
  1387. this.imgGlobalStatus.arrowLeft = false;
  1388. this.imgGlobalStatus.arrowRight = false;
  1389. matchedImg.invertColor = false;
  1390. matchedImg.scaleX = false;
  1391. matchedImg.scaleY = false;
  1392. matchedImg.fullScreen = false;
  1393. if (!this.imgGlobalStatus.popup) {
  1394. this.resetClickTimer();
  1395. }
  1396. };
  1397. /**
  1398. * set 'data-oit-target' and lastClickedImgEl
  1399. * @param targetEl
  1400. */
  1401. this.setLastClickedImg = (targetEl) => {
  1402. if (!targetEl)
  1403. return;
  1404. // 'data-oit-target' is set for locating current image
  1405. targetEl.setAttribute('data-oit-target', '1');
  1406. this.lastClickedImgEl = targetEl;
  1407. };
  1408. //endregion
  1409. //region ================== (Original) Image Border ========================
  1410. this.addBorderForLastClickedImg = (targetEl) => {
  1411. this.setLastClickedImg(targetEl);
  1412. if (!targetEl || !this.plugin.settings.imageBorderToggle)
  1413. return;
  1414. const lastClickedImgStyle = targetEl === null || targetEl === void 0 ? void 0 : targetEl.style;
  1415. if (!lastClickedImgStyle)
  1416. return;
  1417. lastClickedImgStyle.setProperty('border-width', this.plugin.settings.imageBorderWidth);
  1418. lastClickedImgStyle.setProperty('border-style', this.plugin.settings.imageBorderStyle);
  1419. lastClickedImgStyle.setProperty('border-color', this.plugin.settings.imageBorderColor);
  1420. };
  1421. /**
  1422. * remove 'data-oit-target'
  1423. * restore default border style
  1424. */
  1425. this.restoreBorderForLastClickedImg = () => {
  1426. if (!this.lastClickedImgEl)
  1427. return;
  1428. this.lastClickedImgEl.removeAttribute('data-oit-target');
  1429. const lastClickedImgStyle = this.lastClickedImgEl.style;
  1430. if (lastClickedImgStyle) {
  1431. lastClickedImgStyle.setProperty('border-width', this.lastClickedImgDefaultStyle.borderWidth);
  1432. lastClickedImgStyle.setProperty('border-style', this.lastClickedImgDefaultStyle.borderStyle);
  1433. lastClickedImgStyle.setProperty('border-color', this.lastClickedImgDefaultStyle.borderColor);
  1434. }
  1435. };
  1436. //endregion
  1437. //region ================== Image ========================
  1438. this.updateImgViewElAndList = (imgInfo) => {
  1439. if (!(imgInfo === null || imgInfo === void 0 ? void 0 : imgInfo.imgContainerEl))
  1440. return;
  1441. const pinMaximum = this.getConfiguredPinMaximum();
  1442. const imgNum = this.imgInfo.imgList.length;
  1443. if (pinMaximum < imgNum) {
  1444. // remove all imgViewEl and imgList
  1445. imgInfo.imgContainerEl.innerHTML = '';
  1446. // clear imgList
  1447. imgInfo.imgList.length = 0;
  1448. }
  1449. // let isUpdate: boolean = false;
  1450. const curTime = new Date().getTime();
  1451. for (let i = imgNum; i < pinMaximum; i++) {
  1452. // <div class="oit-img-container"> `<img class='oit-img-view' data-index='0' src='' alt=''>` </div>
  1453. let imgViewEl = createEl('img');
  1454. imgViewEl.addClass(OIT_CLASS.IMG_VIEW);
  1455. imgViewEl.hidden = true; // hide 'oit-img-view' for now
  1456. imgViewEl.dataset.index = i + ''; // set data-index
  1457. this.setImgViewDefaultBackground(imgViewEl);
  1458. imgInfo.imgContainerEl.appendChild(imgViewEl);
  1459. // cache imgList
  1460. imgInfo.imgList.push(new ImgCto(i, curTime, imgViewEl));
  1461. // isUpdate = true;
  1462. }
  1463. };
  1464. this.getMatchedImg = () => {
  1465. let earliestImg;
  1466. for (const img of this.imgInfo.imgList) {
  1467. if (!earliestImg || earliestImg.mtime > img.mtime)
  1468. earliestImg = img;
  1469. if (img.popup)
  1470. continue;
  1471. return img;
  1472. }
  1473. if (this.plugin.settings.pinCoverMode) {
  1474. return earliestImg;
  1475. }
  1476. return null;
  1477. };
  1478. /**
  1479. * it may from: renderContainerView(), switch GalleryNavbarView, click toolbar_refresh
  1480. * @param imgCto
  1481. * @param imgSrc
  1482. * @param imgAlt
  1483. * @param imgTitleIndex
  1484. */
  1485. this.refreshImg = (imgCto, imgSrc, imgAlt, imgTitleIndex) => {
  1486. if (!imgSrc)
  1487. imgSrc = imgCto.imgViewEl.src;
  1488. if (!imgAlt)
  1489. imgAlt = imgCto.imgViewEl.alt;
  1490. this.renderImgTitle(imgAlt, imgTitleIndex);
  1491. if (imgSrc) {
  1492. if (imgCto.refreshImgInterval) {
  1493. clearInterval(imgCto.refreshImgInterval);
  1494. imgCto.refreshImgInterval = null;
  1495. }
  1496. let realImg = new Image();
  1497. realImg.src = imgSrc;
  1498. imgCto.refreshImgInterval = setInterval((realImg) => {
  1499. var _a, _b;
  1500. if (realImg.width > 0 || realImg.height > 0) {
  1501. clearInterval(imgCto.refreshImgInterval);
  1502. imgCto.refreshImgInterval = null;
  1503. 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);
  1504. this.renderImgView(imgCto.imgViewEl, imgSrc, imgAlt);
  1505. this.renderImgTip(imgCto);
  1506. imgCto.imgViewEl.style.setProperty('transform', imgCto.defaultImgStyle.transform);
  1507. imgCto.imgViewEl.style.setProperty('filter', imgCto.defaultImgStyle.filter);
  1508. imgCto.imgViewEl.style.setProperty('mix-blend-mode', imgCto.defaultImgStyle.mixBlendMode);
  1509. }
  1510. }, 40, realImg);
  1511. }
  1512. };
  1513. this.renderImgTitle = (name, index) => {
  1514. };
  1515. this.setImgViewPosition = (imgZoomSize, rotate) => {
  1516. const imgViewEl = imgZoomSize.imgViewEl;
  1517. if (!imgViewEl)
  1518. return;
  1519. if (imgZoomSize) {
  1520. imgViewEl.setAttribute('width', imgZoomSize.curWidth + 'px');
  1521. imgViewEl.style.setProperty('margin-top', imgZoomSize.top + 'px', 'important');
  1522. imgViewEl.style.setProperty('margin-left', imgZoomSize.left + 'px', 'important');
  1523. }
  1524. const rotateDeg = rotate ? rotate : 0;
  1525. imgViewEl.style.transform = 'rotate(' + rotateDeg + 'deg)';
  1526. imgZoomSize.rotate = rotateDeg;
  1527. };
  1528. this.renderImgView = (imgViewEl, src, alt) => {
  1529. if (!imgViewEl)
  1530. return;
  1531. imgViewEl.setAttribute('src', src);
  1532. imgViewEl.setAttribute('alt', alt);
  1533. imgViewEl.hidden = !src && !alt;
  1534. };
  1535. this.renderImgTip = (activeImg) => {
  1536. if (!activeImg)
  1537. activeImg = this.imgGlobalStatus.activeImg;
  1538. if (activeImg && this.imgInfo.imgTipEl && activeImg.realWidth > 0 && activeImg.curWidth > 0) {
  1539. if (this.imgInfo.imgTipTimeout) {
  1540. clearTimeout(this.imgInfo.imgTipTimeout);
  1541. }
  1542. if (this.plugin.settings.imgTipToggle) {
  1543. this.imgInfo.imgTipEl.hidden = false; // display 'oit-img-tip'
  1544. const ratio = activeImg.curWidth * 100 / activeImg.realWidth;
  1545. const isSingleDigit = 10 > ratio;
  1546. const width = isSingleDigit ? 20 : 40;
  1547. const left = activeImg.left + activeImg.curWidth / 2 - width / 2;
  1548. const top = activeImg.top + activeImg.curHeight / 2 - 10;
  1549. this.imgInfo.imgTipEl.style.setProperty("width", width + 'px');
  1550. this.imgInfo.imgTipEl.style.setProperty("font-size", isSingleDigit || 100 >= activeImg.curWidth ? 'xx-small' : 'x-small');
  1551. this.imgInfo.imgTipEl.style.setProperty("left", left + 'px');
  1552. this.imgInfo.imgTipEl.style.setProperty("top", top + 'px');
  1553. this.imgInfo.imgTipEl.style.setProperty("z-index", activeImg.zIndex + '');
  1554. this.imgInfo.imgTipEl.setText(parseInt(ratio + '') + '%');
  1555. this.imgInfo.imgTipTimeout = setTimeout(() => {
  1556. this.imgInfo.imgTipEl.hidden = true;
  1557. }, 1000);
  1558. }
  1559. else {
  1560. this.imgInfo.imgTipEl.hidden = true; // hide 'oit-img-tip'
  1561. this.imgInfo.imgTipTimeout = null;
  1562. }
  1563. }
  1564. };
  1565. this.setImgViewDefaultBackgroundForImgList = () => {
  1566. for (const imgCto of this.imgInfo.imgList) {
  1567. this.setImgViewDefaultBackground(imgCto.imgViewEl);
  1568. }
  1569. };
  1570. this.setImgViewDefaultBackground = (imgViewEl) => {
  1571. if (!imgViewEl)
  1572. return;
  1573. if (this.plugin.settings.imgViewBackgroundColor && IMG_DEFAULT_BACKGROUND_COLOR != this.plugin.settings.imgViewBackgroundColor) {
  1574. imgViewEl.removeClass('img-default-background');
  1575. imgViewEl.style.setProperty('background-color', this.plugin.settings.imgViewBackgroundColor);
  1576. }
  1577. else {
  1578. imgViewEl.addClass('img-default-background');
  1579. imgViewEl.style.removeProperty('background-color');
  1580. }
  1581. };
  1582. this.setActiveImgZIndex = (activeImg) => {
  1583. };
  1584. //endregion
  1585. //region ================== Gallery NavBar ========================
  1586. this.switchImageOnGalleryNavBar = (event, next) => {
  1587. };
  1588. this.renderGalleryNavbar = () => {
  1589. };
  1590. this.removeGalleryNavbar = () => {
  1591. };
  1592. //endregion
  1593. //region ================== full screen ========================
  1594. /**
  1595. * full-screen mode
  1596. */
  1597. this.showPlayerImg = (activeImg) => {
  1598. if (!activeImg && !(activeImg = this.imgGlobalStatus.activeImg))
  1599. return;
  1600. this.imgGlobalStatus.fullScreen = true;
  1601. activeImg.fullScreen = true;
  1602. // activeImg.imgViewEl.style.setProperty('display', 'none', 'important'); // hide imgViewEl
  1603. // this.imgInfoCto.imgFooterEl?.style.setProperty('display', 'none'); // hide 'oit-img-footer'
  1604. // show the img-player
  1605. this.imgInfo.imgPlayerEl.style.setProperty('display', 'block');
  1606. this.imgInfo.imgPlayerEl.style.setProperty('z-index', (this.imgGlobalStatus.activeImgZIndex + 10) + '');
  1607. this.imgInfo.imgPlayerEl.addEventListener('click', this.closePlayerImg);
  1608. const windowWidth = this.doc.documentElement.clientWidth || this.doc.body.clientWidth;
  1609. const windowHeight = this.doc.documentElement.clientHeight || this.doc.body.clientHeight;
  1610. let newWidth, newHeight;
  1611. let top = 0;
  1612. if (IMG_FULL_SCREEN_MODE.STRETCH == this.plugin.settings.imgFullScreenMode) {
  1613. newWidth = windowWidth + 'px';
  1614. newHeight = windowHeight + 'px';
  1615. }
  1616. else if (IMG_FULL_SCREEN_MODE.FILL == this.plugin.settings.imgFullScreenMode) {
  1617. newWidth = '100%';
  1618. newHeight = '100%';
  1619. }
  1620. else {
  1621. // fit
  1622. const widthRatio = windowWidth / activeImg.realWidth;
  1623. const heightRatio = windowHeight / activeImg.realHeight;
  1624. if (widthRatio <= heightRatio) {
  1625. newWidth = windowWidth;
  1626. newHeight = widthRatio * activeImg.realHeight;
  1627. }
  1628. else {
  1629. newHeight = windowHeight;
  1630. newWidth = heightRatio * activeImg.realWidth;
  1631. }
  1632. top = (windowHeight - newHeight) / 2;
  1633. newWidth = newWidth + 'px';
  1634. newHeight = newHeight + 'px';
  1635. }
  1636. const imgPlayerImgViewEl = this.imgInfo.imgPlayerImgViewEl;
  1637. if (imgPlayerImgViewEl) {
  1638. imgPlayerImgViewEl.setAttribute('src', activeImg.imgViewEl.src);
  1639. imgPlayerImgViewEl.setAttribute('alt', activeImg.imgViewEl.alt);
  1640. imgPlayerImgViewEl.setAttribute('width', newWidth);
  1641. imgPlayerImgViewEl.setAttribute('height', newHeight);
  1642. imgPlayerImgViewEl.style.setProperty('margin-top', top + 'px');
  1643. //this.imgInfo.imgPlayerImgViewEl.style.setProperty('margin-left', left + 'px');
  1644. this.setImgViewDefaultBackground(imgPlayerImgViewEl);
  1645. }
  1646. };
  1647. /**
  1648. * close full screen
  1649. */
  1650. this.closePlayerImg = () => {
  1651. for (const imgCto of this.imgInfo.imgList) {
  1652. if (!imgCto.fullScreen)
  1653. continue;
  1654. // show the popped up image
  1655. // imgCto.imgViewEl?.style.setProperty('display', 'block', 'important');
  1656. // this.imgInfoCto.imgFooterEl?.style.setProperty('display', 'block');
  1657. }
  1658. // hide full screen
  1659. if (this.imgInfo.imgPlayerEl) {
  1660. this.imgInfo.imgPlayerEl.style.setProperty('display', 'none'); // hide 'img-player'
  1661. this.imgInfo.imgPlayerEl.removeEventListener('click', this.closePlayerImg);
  1662. }
  1663. if (this.imgInfo.imgPlayerImgViewEl) {
  1664. this.imgInfo.imgPlayerImgViewEl.setAttribute('src', '');
  1665. this.imgInfo.imgPlayerImgViewEl.setAttribute('alt', '');
  1666. }
  1667. this.imgGlobalStatus.fullScreen = false;
  1668. };
  1669. //endregion
  1670. //region ================== events ========================
  1671. this.addOrRemoveEvents = (matchedImg, isAdd) => {
  1672. if (isAdd) {
  1673. if (!this.imgGlobalStatus.popup) {
  1674. this.doc.addEventListener('keydown', this.triggerKeydown);
  1675. this.doc.addEventListener('keyup', this.triggerKeyup);
  1676. }
  1677. if (this.isNormalMode()) {
  1678. // click event: hide container view
  1679. this.imgInfo.oitContainerEl.addEventListener('click', this.closeContainerView);
  1680. }
  1681. matchedImg.imgViewEl.addEventListener('mouseenter', this.mouseenterImgView);
  1682. matchedImg.imgViewEl.addEventListener('mouseleave', this.mouseleaveImgView);
  1683. // drag the image via mouse
  1684. matchedImg.imgViewEl.addEventListener('mousedown', this.mousedownImgView);
  1685. matchedImg.imgViewEl.addEventListener('mouseup', this.mouseupImgView);
  1686. // zoom the image via mouse wheel
  1687. matchedImg.imgViewEl.addEventListener('mousewheel', this.mousewheelViewContainer, { passive: true });
  1688. }
  1689. else {
  1690. if (!this.imgGlobalStatus.popup) {
  1691. this.doc.removeEventListener('keydown', this.triggerKeydown);
  1692. this.doc.removeEventListener('keyup', this.triggerKeyup);
  1693. if (this.imgGlobalStatus.clickTimer) {
  1694. clearTimeout(this.imgGlobalStatus.clickTimer);
  1695. this.imgGlobalStatus.clickTimer = null;
  1696. this.imgGlobalStatus.clickCount = 0;
  1697. }
  1698. }
  1699. if (!this.isPinMode()) {
  1700. this.imgInfo.oitContainerEl.removeEventListener('click', this.closeContainerView);
  1701. }
  1702. matchedImg.imgViewEl.removeEventListener('mouseenter', this.mouseenterImgView);
  1703. matchedImg.imgViewEl.removeEventListener('mouseleave', this.mouseleaveImgView);
  1704. matchedImg.imgViewEl.removeEventListener('mousedown', this.mousedownImgView);
  1705. matchedImg.imgViewEl.removeEventListener('mouseup', this.mouseupImgView);
  1706. matchedImg.imgViewEl.removeEventListener('mousewheel', this.mousewheelViewContainer);
  1707. if (matchedImg.refreshImgInterval) {
  1708. clearInterval(matchedImg.refreshImgInterval);
  1709. matchedImg.refreshImgInterval = null;
  1710. }
  1711. }
  1712. };
  1713. this.triggerKeyup = (event) => {
  1714. // console.log('keyup', event, event.key);
  1715. const key = event.key;
  1716. if (!key)
  1717. return;
  1718. if (!('Escape' === key)) {
  1719. event.preventDefault();
  1720. event.stopPropagation();
  1721. }
  1722. switch (key) {
  1723. case 'Escape':
  1724. // close full screen, hide container view
  1725. this.imgGlobalStatus.fullScreen ? this.closePlayerImg() : this.closeContainerView();
  1726. break;
  1727. case 'ArrowUp':
  1728. this.imgGlobalStatus.arrowUp = false;
  1729. break;
  1730. case 'ArrowDown':
  1731. this.imgGlobalStatus.arrowDown = false;
  1732. break;
  1733. case 'ArrowLeft':
  1734. this.imgGlobalStatus.arrowLeft = false;
  1735. // switch to the previous image on the gallery navBar
  1736. this.switchImageOnGalleryNavBar(event, false);
  1737. break;
  1738. case 'ArrowRight':
  1739. this.imgGlobalStatus.arrowRight = false;
  1740. // switch to the next image on the gallery navBar
  1741. this.switchImageOnGalleryNavBar(event, true);
  1742. break;
  1743. }
  1744. };
  1745. /**
  1746. * move the image by keyboard
  1747. * @param event
  1748. */
  1749. this.triggerKeydown = (event) => {
  1750. //console.log('keydown', event, event.key, this.imgStatus);
  1751. if (this.isPinMode())
  1752. return;
  1753. event.preventDefault();
  1754. event.stopPropagation();
  1755. if (this.imgGlobalStatus.arrowUp && this.imgGlobalStatus.arrowLeft) {
  1756. this.moveImgViewByHotkey(event, 'UP_LEFT');
  1757. return;
  1758. }
  1759. else if (this.imgGlobalStatus.arrowUp && this.imgGlobalStatus.arrowRight) {
  1760. this.moveImgViewByHotkey(event, 'UP_RIGHT');
  1761. return;
  1762. }
  1763. else if (this.imgGlobalStatus.arrowDown && this.imgGlobalStatus.arrowLeft) {
  1764. this.moveImgViewByHotkey(event, 'DOWN_LEFT');
  1765. return;
  1766. }
  1767. else if (this.imgGlobalStatus.arrowDown && this.imgGlobalStatus.arrowRight) {
  1768. this.moveImgViewByHotkey(event, 'DOWN_RIGHT');
  1769. return;
  1770. }
  1771. switch (event.key) {
  1772. case 'ArrowUp':
  1773. this.imgGlobalStatus.arrowUp = true;
  1774. this.moveImgViewByHotkey(event, 'UP');
  1775. break;
  1776. case 'ArrowDown':
  1777. this.imgGlobalStatus.arrowDown = true;
  1778. this.moveImgViewByHotkey(event, 'DOWN');
  1779. break;
  1780. case 'ArrowLeft':
  1781. this.imgGlobalStatus.arrowLeft = true;
  1782. this.moveImgViewByHotkey(event, 'LEFT');
  1783. break;
  1784. case 'ArrowRight':
  1785. this.imgGlobalStatus.arrowRight = true;
  1786. this.moveImgViewByHotkey(event, 'RIGHT');
  1787. break;
  1788. }
  1789. };
  1790. this.moveImgViewByHotkey = (event, orientation) => {
  1791. if (!orientation || !this.imgGlobalStatus.popup || !this.checkHotkeySettings(event, this.plugin.settings.moveTheImageHotkey))
  1792. return;
  1793. switch (orientation) {
  1794. case 'UP':
  1795. this.mousemoveImgView(null, { offsetX: 0, offsetY: -this.plugin.settings.imageMoveSpeed });
  1796. break;
  1797. case 'DOWN':
  1798. this.mousemoveImgView(null, { offsetX: 0, offsetY: this.plugin.settings.imageMoveSpeed });
  1799. break;
  1800. case 'LEFT':
  1801. this.mousemoveImgView(null, { offsetX: -this.plugin.settings.imageMoveSpeed, offsetY: 0 });
  1802. break;
  1803. case 'RIGHT':
  1804. this.mousemoveImgView(null, { offsetX: this.plugin.settings.imageMoveSpeed, offsetY: 0 });
  1805. break;
  1806. case 'UP_LEFT':
  1807. this.mousemoveImgView(null, {
  1808. offsetX: -this.plugin.settings.imageMoveSpeed,
  1809. offsetY: -this.plugin.settings.imageMoveSpeed
  1810. });
  1811. break;
  1812. case 'UP_RIGHT':
  1813. this.mousemoveImgView(null, {
  1814. offsetX: this.plugin.settings.imageMoveSpeed,
  1815. offsetY: -this.plugin.settings.imageMoveSpeed
  1816. });
  1817. break;
  1818. case 'DOWN_LEFT':
  1819. this.mousemoveImgView(null, {
  1820. offsetX: -this.plugin.settings.imageMoveSpeed,
  1821. offsetY: this.plugin.settings.imageMoveSpeed
  1822. });
  1823. break;
  1824. case 'DOWN_RIGHT':
  1825. this.mousemoveImgView(null, {
  1826. offsetX: this.plugin.settings.imageMoveSpeed,
  1827. offsetY: this.plugin.settings.imageMoveSpeed
  1828. });
  1829. break;
  1830. }
  1831. };
  1832. this.checkHotkeySettings = (event, hotkey) => {
  1833. // console.log("[oit] checkHotkeySettings: ", event.ctrlKey, event.altKey, event.shiftKey)
  1834. switch (hotkey) {
  1835. case "NONE":
  1836. return !event.ctrlKey && !event.altKey && !event.shiftKey;
  1837. case "CTRL":
  1838. return event.ctrlKey && !event.altKey && !event.shiftKey;
  1839. case "ALT":
  1840. return !event.ctrlKey && event.altKey && !event.shiftKey;
  1841. case "SHIFT":
  1842. return !event.ctrlKey && !event.altKey && event.shiftKey;
  1843. case "CTRL_ALT":
  1844. return event.ctrlKey && event.altKey && !event.shiftKey;
  1845. case "CTRL_SHIFT":
  1846. return event.ctrlKey && !event.altKey && event.shiftKey;
  1847. case "SHIFT_ALT":
  1848. return !event.ctrlKey && event.altKey && event.shiftKey;
  1849. case "CTRL_SHIFT_ALT":
  1850. return event.ctrlKey && event.altKey && event.shiftKey;
  1851. }
  1852. return false;
  1853. };
  1854. this.mouseenterImgView = (event) => {
  1855. this.resetClickTimer();
  1856. event.stopPropagation();
  1857. event.preventDefault();
  1858. this.getAndUpdateActiveImg(event);
  1859. // console.log('mouseenterImgView', event, this.imgGlobalStatus.activeImg);
  1860. };
  1861. this.mousedownImgView = (event) => {
  1862. // console.log('mousedownImgView', event, this.imgGlobalStatus.activeImg, event.button);
  1863. event.stopPropagation();
  1864. event.preventDefault();
  1865. const activeImg = this.getAndUpdateActiveImg(event);
  1866. if (!activeImg)
  1867. return;
  1868. if (0 == event.button) { // left click
  1869. this.setClickTimer(activeImg);
  1870. this.setActiveImgZIndex(activeImg);
  1871. this.imgGlobalStatus.dragging = true;
  1872. // 鼠标相对于图片的位置
  1873. activeImg.moveX = activeImg.imgViewEl.offsetLeft - event.clientX;
  1874. activeImg.moveY = activeImg.imgViewEl.offsetTop - event.clientY;
  1875. // 鼠标按下时持续触发/移动事件
  1876. activeImg.imgViewEl.onmousemove = this.mousemoveImgView;
  1877. }
  1878. };
  1879. /**
  1880. * move the image by mouse or keyboard
  1881. * @param event
  1882. * @param offsetSize
  1883. */
  1884. this.mousemoveImgView = (event, offsetSize) => {
  1885. // console.log('mousemoveImgView', event, this.imgGlobalStatus.activeImg);
  1886. const activeImg = this.imgGlobalStatus.activeImg;
  1887. if (!activeImg)
  1888. return;
  1889. if (event) {
  1890. if (!this.imgGlobalStatus.dragging)
  1891. return;
  1892. // drag via mouse cursor (Both Mode)
  1893. activeImg.left = event.clientX + activeImg.moveX;
  1894. activeImg.top = event.clientY + activeImg.moveY;
  1895. }
  1896. else if (offsetSize) {
  1897. // move by arrow keys (Normal Mode)
  1898. activeImg.left += offsetSize.offsetX;
  1899. activeImg.top += offsetSize.offsetY;
  1900. }
  1901. else {
  1902. return;
  1903. }
  1904. // move the image
  1905. activeImg.imgViewEl.style.setProperty('margin-left', activeImg.left + 'px', 'important');
  1906. activeImg.imgViewEl.style.setProperty('margin-top', activeImg.top + 'px', 'important');
  1907. };
  1908. this.mouseupImgView = (event) => {
  1909. var _a;
  1910. // console.log('mouseupImgView', event, this.imgGlobalStatus.activeImg);
  1911. this.imgGlobalStatus.dragging = false;
  1912. event.preventDefault();
  1913. event.stopPropagation();
  1914. const activeImg = this.imgGlobalStatus.activeImg;
  1915. if (activeImg) {
  1916. activeImg.imgViewEl.onmousemove = null;
  1917. if (2 == event.button) { // right click
  1918. (_a = this.menuView) === null || _a === void 0 ? void 0 : _a.show(event, activeImg);
  1919. }
  1920. }
  1921. };
  1922. this.mouseleaveImgView = (event) => {
  1923. // console.log('mouseleaveImgView', event, this.imgGlobalStatus.activeImg, '>>> set null');
  1924. this.imgGlobalStatus.dragging = false;
  1925. this.resetClickTimer();
  1926. event.preventDefault();
  1927. event.stopPropagation();
  1928. const activeImg = this.imgGlobalStatus.activeImg;
  1929. if (activeImg) {
  1930. activeImg.imgViewEl.onmousemove = null;
  1931. this.setActiveImgForMouseEvent(null); // for pin mode
  1932. }
  1933. };
  1934. this.setClickTimer = (activeImg) => {
  1935. ++this.imgGlobalStatus.clickCount;
  1936. clearTimeout(this.imgGlobalStatus.clickTimer);
  1937. this.imgGlobalStatus.clickTimer = setTimeout(() => {
  1938. const clickCount = this.imgGlobalStatus.clickCount;
  1939. this.resetClickTimer();
  1940. if (2 === clickCount) { // double click
  1941. if (!activeImg)
  1942. activeImg = this.imgGlobalStatus.activeImg;
  1943. // console.log('mousedownImgView: double click...', activeImg.index);
  1944. this.clickImgToolbar(null, this.plugin.settings.doubleClickToolbar, activeImg);
  1945. }
  1946. }, 200);
  1947. };
  1948. this.resetClickTimer = () => {
  1949. this.imgGlobalStatus.clickTimer = null;
  1950. this.imgGlobalStatus.clickCount = 0;
  1951. };
  1952. this.getAndUpdateActiveImg = (event) => {
  1953. const targetEl = event.target;
  1954. let index;
  1955. if (!targetEl || !(index = targetEl.dataset.index))
  1956. return;
  1957. const activeImg = this.imgInfo.imgList[parseInt(index)];
  1958. if (activeImg && (!this.imgGlobalStatus.activeImg || activeImg.index !== this.imgGlobalStatus.activeImg.index)) {
  1959. this.setActiveImgForMouseEvent(activeImg); // update activeImg
  1960. }
  1961. // console.log('getAndUpdateActiveImg: ', activeImg)
  1962. return activeImg;
  1963. };
  1964. this.mousewheelViewContainer = (event) => {
  1965. // event.preventDefault();
  1966. event.stopPropagation();
  1967. // @ts-ignore
  1968. this.zoomAndRender(0 < event.wheelDelta ? 0.1 : -0.1, event);
  1969. };
  1970. this.zoomAndRender = (ratio, event, actualSize, activeImg) => {
  1971. if (!activeImg) {
  1972. activeImg = this.imgGlobalStatus.activeImg;
  1973. }
  1974. let activeImgViewEl;
  1975. if (!activeImg || !(activeImgViewEl = activeImg.imgViewEl))
  1976. return;
  1977. let offsetSize = { offsetX: 0, offsetY: 0 };
  1978. if (event) {
  1979. offsetSize.offsetX = event.offsetX;
  1980. offsetSize.offsetY = event.offsetY;
  1981. }
  1982. else {
  1983. offsetSize.offsetX = activeImg.curWidth / 2;
  1984. offsetSize.offsetY = activeImg.curHeight / 2;
  1985. }
  1986. const zoomData = ImgUtil.zoom(ratio, activeImg, offsetSize, actualSize);
  1987. this.renderImgTip(activeImg);
  1988. activeImgViewEl.setAttribute('width', zoomData.curWidth + 'px');
  1989. activeImgViewEl.style.setProperty('margin-top', zoomData.top + 'px', 'important');
  1990. activeImgViewEl.style.setProperty('margin-left', zoomData.left + 'px', 'important');
  1991. };
  1992. this.clickImgToolbar = (event, targetElClass, activeImg) => {
  1993. if (!targetElClass && !activeImg) {
  1994. if (!event)
  1995. return;
  1996. // comes from clicking toolbar
  1997. targetElClass = event.target.className;
  1998. activeImg = this.imgGlobalStatus.activeImg;
  1999. }
  2000. switch (targetElClass) {
  2001. case 'toolbar_zoom_to_100':
  2002. this.zoomAndRender(null, null, true, activeImg);
  2003. break;
  2004. case 'toolbar_zoom_in':
  2005. this.zoomAndRender(0.1);
  2006. break;
  2007. case 'toolbar_zoom_out':
  2008. this.zoomAndRender(-0.1);
  2009. break;
  2010. case 'toolbar_full_screen':
  2011. this.showPlayerImg(activeImg);
  2012. break;
  2013. case 'toolbar_refresh':
  2014. this.refreshImg(activeImg);
  2015. break;
  2016. case 'toolbar_rotate_left':
  2017. activeImg.rotate -= 90;
  2018. ImgUtil.transform(activeImg);
  2019. break;
  2020. case 'toolbar_rotate_right':
  2021. activeImg.rotate += 90;
  2022. ImgUtil.transform(activeImg);
  2023. break;
  2024. case 'toolbar_scale_x':
  2025. activeImg.scaleX = !activeImg.scaleX;
  2026. ImgUtil.transform(activeImg);
  2027. break;
  2028. case 'toolbar_scale_y':
  2029. activeImg.scaleY = !activeImg.scaleY;
  2030. ImgUtil.transform(activeImg);
  2031. break;
  2032. case 'toolbar_invert_color':
  2033. activeImg.invertColor = !activeImg.invertColor;
  2034. ImgUtil.invertImgColor(activeImg.imgViewEl, activeImg.invertColor);
  2035. break;
  2036. case 'toolbar_copy':
  2037. ImgUtil.copyImage(activeImg.imgViewEl, activeImg.curWidth, activeImg.curHeight);
  2038. break;
  2039. case 'toolbar_close':
  2040. this.closeContainerView(event, activeImg);
  2041. break;
  2042. }
  2043. };
  2044. this.plugin = plugin;
  2045. }
  2046. }
  2047. var Md5 = /** @class */ (function () {
  2048. function Md5() {
  2049. }
  2050. Md5.AddUnsigned = function (lX, lY) {
  2051. var lX4, lY4, lX8, lY8, lResult;
  2052. lX8 = (lX & 0x80000000);
  2053. lY8 = (lY & 0x80000000);
  2054. lX4 = (lX & 0x40000000);
  2055. lY4 = (lY & 0x40000000);
  2056. lResult = (lX & 0x3FFFFFFF) + (lY & 0x3FFFFFFF);
  2057. if (!!(lX4 & lY4)) {
  2058. return (lResult ^ 0x80000000 ^ lX8 ^ lY8);
  2059. }
  2060. if (!!(lX4 | lY4)) {
  2061. if (!!(lResult & 0x40000000)) {
  2062. return (lResult ^ 0xC0000000 ^ lX8 ^ lY8);
  2063. }
  2064. else {
  2065. return (lResult ^ 0x40000000 ^ lX8 ^ lY8);
  2066. }
  2067. }
  2068. else {
  2069. return (lResult ^ lX8 ^ lY8);
  2070. }
  2071. };
  2072. Md5.FF = function (a, b, c, d, x, s, ac) {
  2073. a = this.AddUnsigned(a, this.AddUnsigned(this.AddUnsigned(this.F(b, c, d), x), ac));
  2074. return this.AddUnsigned(this.RotateLeft(a, s), b);
  2075. };
  2076. Md5.GG = function (a, b, c, d, x, s, ac) {
  2077. a = this.AddUnsigned(a, this.AddUnsigned(this.AddUnsigned(this.G(b, c, d), x), ac));
  2078. return this.AddUnsigned(this.RotateLeft(a, s), b);
  2079. };
  2080. Md5.HH = function (a, b, c, d, x, s, ac) {
  2081. a = this.AddUnsigned(a, this.AddUnsigned(this.AddUnsigned(this.H(b, c, d), x), ac));
  2082. return this.AddUnsigned(this.RotateLeft(a, s), b);
  2083. };
  2084. Md5.II = function (a, b, c, d, x, s, ac) {
  2085. a = this.AddUnsigned(a, this.AddUnsigned(this.AddUnsigned(this.I(b, c, d), x), ac));
  2086. return this.AddUnsigned(this.RotateLeft(a, s), b);
  2087. };
  2088. Md5.ConvertToWordArray = function (string) {
  2089. 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;
  2090. while (lByteCount < lMessageLength) {
  2091. lWordCount = (lByteCount - (lByteCount % 4)) / 4;
  2092. lBytePosition = (lByteCount % 4) * 8;
  2093. lWordArray[lWordCount] = (lWordArray[lWordCount] | (string.charCodeAt(lByteCount) << lBytePosition));
  2094. lByteCount++;
  2095. }
  2096. lWordCount = (lByteCount - (lByteCount % 4)) / 4;
  2097. lBytePosition = (lByteCount % 4) * 8;
  2098. lWordArray[lWordCount] = lWordArray[lWordCount] | (0x80 << lBytePosition);
  2099. lWordArray[lNumberOfWords - 2] = lMessageLength << 3;
  2100. lWordArray[lNumberOfWords - 1] = lMessageLength >>> 29;
  2101. return lWordArray;
  2102. };
  2103. Md5.WordToHex = function (lValue) {
  2104. var WordToHexValue = "", WordToHexValue_temp = "", lByte, lCount;
  2105. for (lCount = 0; lCount <= 3; lCount++) {
  2106. lByte = (lValue >>> (lCount * 8)) & 255;
  2107. WordToHexValue_temp = "0" + lByte.toString(16);
  2108. WordToHexValue = WordToHexValue + WordToHexValue_temp.substr(WordToHexValue_temp.length - 2, 2);
  2109. }
  2110. return WordToHexValue;
  2111. };
  2112. Md5.Utf8Encode = function (string) {
  2113. var utftext = "", c;
  2114. string = string.replace(/\r\n/g, "\n");
  2115. for (var n = 0; n < string.length; n++) {
  2116. c = string.charCodeAt(n);
  2117. if (c < 128) {
  2118. utftext += String.fromCharCode(c);
  2119. }
  2120. else if ((c > 127) && (c < 2048)) {
  2121. utftext += String.fromCharCode((c >> 6) | 192);
  2122. utftext += String.fromCharCode((c & 63) | 128);
  2123. }
  2124. else {
  2125. utftext += String.fromCharCode((c >> 12) | 224);
  2126. utftext += String.fromCharCode(((c >> 6) & 63) | 128);
  2127. utftext += String.fromCharCode((c & 63) | 128);
  2128. }
  2129. }
  2130. return utftext;
  2131. };
  2132. Md5.init = function (string) {
  2133. var temp;
  2134. if (typeof string !== 'string')
  2135. string = JSON.stringify(string);
  2136. this._string = this.Utf8Encode(string);
  2137. this.x = this.ConvertToWordArray(this._string);
  2138. this.a = 0x67452301;
  2139. this.b = 0xEFCDAB89;
  2140. this.c = 0x98BADCFE;
  2141. this.d = 0x10325476;
  2142. for (this.k = 0; this.k < this.x.length; this.k += 16) {
  2143. this.AA = this.a;
  2144. this.BB = this.b;
  2145. this.CC = this.c;
  2146. this.DD = this.d;
  2147. this.a = this.FF(this.a, this.b, this.c, this.d, this.x[this.k], this.S11, 0xD76AA478);
  2148. this.d = this.FF(this.d, this.a, this.b, this.c, this.x[this.k + 1], this.S12, 0xE8C7B756);
  2149. this.c = this.FF(this.c, this.d, this.a, this.b, this.x[this.k + 2], this.S13, 0x242070DB);
  2150. this.b = this.FF(this.b, this.c, this.d, this.a, this.x[this.k + 3], this.S14, 0xC1BDCEEE);
  2151. this.a = this.FF(this.a, this.b, this.c, this.d, this.x[this.k + 4], this.S11, 0xF57C0FAF);
  2152. this.d = this.FF(this.d, this.a, this.b, this.c, this.x[this.k + 5], this.S12, 0x4787C62A);
  2153. this.c = this.FF(this.c, this.d, this.a, this.b, this.x[this.k + 6], this.S13, 0xA8304613);
  2154. this.b = this.FF(this.b, this.c, this.d, this.a, this.x[this.k + 7], this.S14, 0xFD469501);
  2155. this.a = this.FF(this.a, this.b, this.c, this.d, this.x[this.k + 8], this.S11, 0x698098D8);
  2156. this.d = this.FF(this.d, this.a, this.b, this.c, this.x[this.k + 9], this.S12, 0x8B44F7AF);
  2157. this.c = this.FF(this.c, this.d, this.a, this.b, this.x[this.k + 10], this.S13, 0xFFFF5BB1);
  2158. this.b = this.FF(this.b, this.c, this.d, this.a, this.x[this.k + 11], this.S14, 0x895CD7BE);
  2159. this.a = this.FF(this.a, this.b, this.c, this.d, this.x[this.k + 12], this.S11, 0x6B901122);
  2160. this.d = this.FF(this.d, this.a, this.b, this.c, this.x[this.k + 13], this.S12, 0xFD987193);
  2161. this.c = this.FF(this.c, this.d, this.a, this.b, this.x[this.k + 14], this.S13, 0xA679438E);
  2162. this.b = this.FF(this.b, this.c, this.d, this.a, this.x[this.k + 15], this.S14, 0x49B40821);
  2163. this.a = this.GG(this.a, this.b, this.c, this.d, this.x[this.k + 1], this.S21, 0xF61E2562);
  2164. this.d = this.GG(this.d, this.a, this.b, this.c, this.x[this.k + 6], this.S22, 0xC040B340);
  2165. this.c = this.GG(this.c, this.d, this.a, this.b, this.x[this.k + 11], this.S23, 0x265E5A51);
  2166. this.b = this.GG(this.b, this.c, this.d, this.a, this.x[this.k], this.S24, 0xE9B6C7AA);
  2167. this.a = this.GG(this.a, this.b, this.c, this.d, this.x[this.k + 5], this.S21, 0xD62F105D);
  2168. this.d = this.GG(this.d, this.a, this.b, this.c, this.x[this.k + 10], this.S22, 0x2441453);
  2169. this.c = this.GG(this.c, this.d, this.a, this.b, this.x[this.k + 15], this.S23, 0xD8A1E681);
  2170. this.b = this.GG(this.b, this.c, this.d, this.a, this.x[this.k + 4], this.S24, 0xE7D3FBC8);
  2171. this.a = this.GG(this.a, this.b, this.c, this.d, this.x[this.k + 9], this.S21, 0x21E1CDE6);
  2172. this.d = this.GG(this.d, this.a, this.b, this.c, this.x[this.k + 14], this.S22, 0xC33707D6);
  2173. this.c = this.GG(this.c, this.d, this.a, this.b, this.x[this.k + 3], this.S23, 0xF4D50D87);
  2174. this.b = this.GG(this.b, this.c, this.d, this.a, this.x[this.k + 8], this.S24, 0x455A14ED);
  2175. this.a = this.GG(this.a, this.b, this.c, this.d, this.x[this.k + 13], this.S21, 0xA9E3E905);
  2176. this.d = this.GG(this.d, this.a, this.b, this.c, this.x[this.k + 2], this.S22, 0xFCEFA3F8);
  2177. this.c = this.GG(this.c, this.d, this.a, this.b, this.x[this.k + 7], this.S23, 0x676F02D9);
  2178. this.b = this.GG(this.b, this.c, this.d, this.a, this.x[this.k + 12], this.S24, 0x8D2A4C8A);
  2179. this.a = this.HH(this.a, this.b, this.c, this.d, this.x[this.k + 5], this.S31, 0xFFFA3942);
  2180. this.d = this.HH(this.d, this.a, this.b, this.c, this.x[this.k + 8], this.S32, 0x8771F681);
  2181. this.c = this.HH(this.c, this.d, this.a, this.b, this.x[this.k + 11], this.S33, 0x6D9D6122);
  2182. this.b = this.HH(this.b, this.c, this.d, this.a, this.x[this.k + 14], this.S34, 0xFDE5380C);
  2183. this.a = this.HH(this.a, this.b, this.c, this.d, this.x[this.k + 1], this.S31, 0xA4BEEA44);
  2184. this.d = this.HH(this.d, this.a, this.b, this.c, this.x[this.k + 4], this.S32, 0x4BDECFA9);
  2185. this.c = this.HH(this.c, this.d, this.a, this.b, this.x[this.k + 7], this.S33, 0xF6BB4B60);
  2186. this.b = this.HH(this.b, this.c, this.d, this.a, this.x[this.k + 10], this.S34, 0xBEBFBC70);
  2187. this.a = this.HH(this.a, this.b, this.c, this.d, this.x[this.k + 13], this.S31, 0x289B7EC6);
  2188. this.d = this.HH(this.d, this.a, this.b, this.c, this.x[this.k], this.S32, 0xEAA127FA);
  2189. this.c = this.HH(this.c, this.d, this.a, this.b, this.x[this.k + 3], this.S33, 0xD4EF3085);
  2190. this.b = this.HH(this.b, this.c, this.d, this.a, this.x[this.k + 6], this.S34, 0x4881D05);
  2191. this.a = this.HH(this.a, this.b, this.c, this.d, this.x[this.k + 9], this.S31, 0xD9D4D039);
  2192. this.d = this.HH(this.d, this.a, this.b, this.c, this.x[this.k + 12], this.S32, 0xE6DB99E5);
  2193. this.c = this.HH(this.c, this.d, this.a, this.b, this.x[this.k + 15], this.S33, 0x1FA27CF8);
  2194. this.b = this.HH(this.b, this.c, this.d, this.a, this.x[this.k + 2], this.S34, 0xC4AC5665);
  2195. this.a = this.II(this.a, this.b, this.c, this.d, this.x[this.k], this.S41, 0xF4292244);
  2196. this.d = this.II(this.d, this.a, this.b, this.c, this.x[this.k + 7], this.S42, 0x432AFF97);
  2197. this.c = this.II(this.c, this.d, this.a, this.b, this.x[this.k + 14], this.S43, 0xAB9423A7);
  2198. this.b = this.II(this.b, this.c, this.d, this.a, this.x[this.k + 5], this.S44, 0xFC93A039);
  2199. this.a = this.II(this.a, this.b, this.c, this.d, this.x[this.k + 12], this.S41, 0x655B59C3);
  2200. this.d = this.II(this.d, this.a, this.b, this.c, this.x[this.k + 3], this.S42, 0x8F0CCC92);
  2201. this.c = this.II(this.c, this.d, this.a, this.b, this.x[this.k + 10], this.S43, 0xFFEFF47D);
  2202. this.b = this.II(this.b, this.c, this.d, this.a, this.x[this.k + 1], this.S44, 0x85845DD1);
  2203. this.a = this.II(this.a, this.b, this.c, this.d, this.x[this.k + 8], this.S41, 0x6FA87E4F);
  2204. this.d = this.II(this.d, this.a, this.b, this.c, this.x[this.k + 15], this.S42, 0xFE2CE6E0);
  2205. this.c = this.II(this.c, this.d, this.a, this.b, this.x[this.k + 6], this.S43, 0xA3014314);
  2206. this.b = this.II(this.b, this.c, this.d, this.a, this.x[this.k + 13], this.S44, 0x4E0811A1);
  2207. this.a = this.II(this.a, this.b, this.c, this.d, this.x[this.k + 4], this.S41, 0xF7537E82);
  2208. this.d = this.II(this.d, this.a, this.b, this.c, this.x[this.k + 11], this.S42, 0xBD3AF235);
  2209. this.c = this.II(this.c, this.d, this.a, this.b, this.x[this.k + 2], this.S43, 0x2AD7D2BB);
  2210. this.b = this.II(this.b, this.c, this.d, this.a, this.x[this.k + 9], this.S44, 0xEB86D391);
  2211. this.a = this.AddUnsigned(this.a, this.AA);
  2212. this.b = this.AddUnsigned(this.b, this.BB);
  2213. this.c = this.AddUnsigned(this.c, this.CC);
  2214. this.d = this.AddUnsigned(this.d, this.DD);
  2215. }
  2216. temp = this.WordToHex(this.a) + this.WordToHex(this.b) + this.WordToHex(this.c) + this.WordToHex(this.d);
  2217. return temp.toLowerCase();
  2218. };
  2219. Md5.x = Array();
  2220. Md5.S11 = 7;
  2221. Md5.S12 = 12;
  2222. Md5.S13 = 17;
  2223. Md5.S14 = 22;
  2224. Md5.S21 = 5;
  2225. Md5.S22 = 9;
  2226. Md5.S23 = 14;
  2227. Md5.S24 = 20;
  2228. Md5.S31 = 4;
  2229. Md5.S32 = 11;
  2230. Md5.S33 = 16;
  2231. Md5.S34 = 23;
  2232. Md5.S41 = 6;
  2233. Md5.S42 = 10;
  2234. Md5.S43 = 15;
  2235. Md5.S44 = 21;
  2236. Md5.RotateLeft = function (lValue, iShiftBits) { return (lValue << iShiftBits) | (lValue >>> (32 - iShiftBits)); };
  2237. Md5.F = function (x, y, z) { return (x & y) | ((~x) & z); };
  2238. Md5.G = function (x, y, z) { return (x & z) | (y & (~z)); };
  2239. Md5.H = function (x, y, z) { return (x ^ y ^ z); };
  2240. Md5.I = function (x, y, z) { return (y ^ (x | (~z))); };
  2241. return Md5;
  2242. }());
  2243. class GalleryImgCto {
  2244. constructor(alt, src) {
  2245. this.alt = alt;
  2246. this.src = src;
  2247. }
  2248. }
  2249. class GalleryImgCacheCto {
  2250. constructor(file, galleryImgList, mtime) {
  2251. this.file = file;
  2252. this.galleryImgList = galleryImgList;
  2253. this.mtime = mtime;
  2254. }
  2255. }
  2256. class FileCto {
  2257. constructor(path, ctime, mtime) {
  2258. this.path = path;
  2259. this.ctime = ctime;
  2260. this.mtime = mtime;
  2261. }
  2262. }
  2263. /* // const imgList: Array<GalleryImg> = parseMarkDown(plugin, activeView.sourceMode?.cmEditor, activeView.file.path);
  2264. export const parseMarkDown = (plugin: ImageToolkitPlugin, cm: CodeMirror.Editor, filePath: string) => {
  2265. let line, lineText;
  2266. for (let i = 0, lastLine = cm.lastLine(); i <= lastLine; i++) {
  2267. if (!(line = cm.lineInfo(i))) continue;
  2268. if (!(lineText = line.text)) continue;
  2269. console.debug((i + 1) + ' line: ' + lineText);
  2270. }
  2271. } */
  2272. const parseActiveViewData = (plugin, lines, file) => {
  2273. if (!lines || 0 >= lines.length)
  2274. return null;
  2275. let lineText;
  2276. let isCodeArea = false;
  2277. let textArr;
  2278. const imgList = new Array();
  2279. for (let i = 0, len = lines.length; i < len; i++) {
  2280. if (!(lineText = lines[i]))
  2281. continue;
  2282. // console.log((i + 1) + ' line: ' + lineText);
  2283. if (lineText.startsWith('```')) {
  2284. isCodeArea = !isCodeArea;
  2285. continue;
  2286. }
  2287. if (isCodeArea)
  2288. continue;
  2289. if (textArr = getNonCodeAreaTexts(lineText)) {
  2290. for (const text of textArr) {
  2291. extractImage(text, imgList);
  2292. }
  2293. }
  2294. else {
  2295. extractImage(lineText, imgList);
  2296. }
  2297. }
  2298. const filePath = file.path;
  2299. for (let i = 0, len = imgList.length; i < len; i++) {
  2300. const img = imgList[i];
  2301. if (img.convert) {
  2302. const imageFile = plugin.app.metadataCache.getFirstLinkpathDest(decodeURIComponent(img.src), filePath);
  2303. img.src = imageFile ? plugin.app.vault.getResourcePath(imageFile) : '';
  2304. }
  2305. img.hash = md5Img(img.alt, img.src);
  2306. img.match = null;
  2307. img.name = null;
  2308. }
  2309. return new GalleryImgCacheCto(new FileCto(file.path, file.stat.ctime, file.stat.mtime), imgList, new Date().getTime());
  2310. };
  2311. const getNonCodeAreaTexts = (lineText) => {
  2312. let textArr = [];
  2313. const idx1 = lineText.indexOf('`');
  2314. if (0 > idx1)
  2315. return null;
  2316. const idx2 = lineText.lastIndexOf('`');
  2317. if (idx1 === idx2)
  2318. return null;
  2319. if (idx1 > 0)
  2320. textArr.push(lineText.substring(0, idx1));
  2321. if (lineText.length - 1 > idx2)
  2322. textArr.push(lineText.substring(idx2 + 1));
  2323. return textArr;
  2324. };
  2325. const IMAGE_LINK_REGEX1 = /\[\s*?(!\[(.*?)\]\((.*?)\))\s*?\]\(.*?\)/; // 1-link: [ ![alt1|alt2|...|altn|width](src) ](https://...)
  2326. // markdown: `![alt1|alt2|...|altn|width](src)` -> 1: alt (alt+width), 2: src
  2327. const RE_MARKDOWN_IMAGE = /!\[(.*?)\]\(\s*(.*?\.(jpe?g|png|svg|gif|bmp|webp))\s*\)/i; // 1: ![alt1|alt2|...|altn|width](src)
  2328. const IMAGE_LINK_REGEX2 = /\[\s*?(!\[\[(.*?[jpe?g|png|gif|svg|bmp].*?)\]\])\s*?\]\(.*?\)/i; // 2-link: [ ![[src|alt1|alt2|width]] ](https://...)
  2329. // RE_WIKILINK_IMAGE wikilink: `![[bird.png|alt1|alt2|2.1|50]]` -> 1: src+alt+width
  2330. const RE_WIKILINK_IMAGE = /!\[\[(.*?\.(jpe?g|png|svg|gif|bmp|webp).*?)\]\]/i; // 2: ![[src|alt1|alt2|width]]
  2331. const SRC_LINK_REGEX = /[a-z][a-z0-9+\-.]+:\/.*/i; // match link: http://, file://, app://
  2332. const SRC_IMG_REGREX = /.*?\.jpe?g|png|gif|svg|bmp/i; // match image ext: .jpg/.jpeg/.png/.gif/.svg/.bmp
  2333. const IMG_TAG_LINK_SRC_REGEX = /<a.*?(<img.*?src=[\'"](.*?)[\'"].*?\/?>).*?\/a>/i; // 3-a-img-src: <a> <img ... src=''/> </a>
  2334. const IMG_TAG_SRC_REGEX = /<img.*?src=[\'"](.*?)[\'"].*?\/?>/i; // 3-img-src: <img ... src='' />
  2335. const IMG_TAG_ALT_REGEX = /<img.*?alt=[\'"](.*?)[\'"].*?\/?>/i; // 3-img-alt: <img ... alt='' />
  2336. const FULL_PATH_REGEX = /^[a-z]\:.*?[jpe?g|png|gif|svg|bmp]/i;
  2337. const BLOCKQUOTE_PREFIX = `#^`;
  2338. const IMG_MATCH_MIN_LEN = 7;
  2339. const extractImage = (text, imgList) => {
  2340. text = text.replace('\\|', '|');
  2341. let img;
  2342. if (!(img = matchImage1(text))) {
  2343. if (!(img = matchImage2(text))) {
  2344. if (!(img = matchImageTag(text))) {
  2345. return;
  2346. }
  2347. }
  2348. }
  2349. imgList.push(img);
  2350. if (img.match) {
  2351. const idx = img.match.index + img.match[0].length;
  2352. if (idx > text.length - IMG_MATCH_MIN_LEN)
  2353. return;
  2354. extractImage(text.substring(idx), imgList);
  2355. }
  2356. };
  2357. /**
  2358. * ![alt1|alt2|...|altn|width](src)
  2359. * @param text
  2360. * @returns
  2361. */
  2362. const matchImage1 = (text) => {
  2363. var _a;
  2364. let match = text.match(IMAGE_LINK_REGEX1); // 1-link: [ ![alt1|alt2|...|altn|width](src) ](https://...)
  2365. let link = false;
  2366. let alt, src;
  2367. if (match) {
  2368. link = true;
  2369. alt = match[2];
  2370. src = match[3];
  2371. }
  2372. else {
  2373. match = text.match(RE_MARKDOWN_IMAGE); // 1: ![alt1|alt2|...|altn|width](src)
  2374. if (match) {
  2375. if (alt = match[1]) {
  2376. if (0 <= alt.indexOf('[') && 0 <= alt.indexOf(']'))
  2377. return;
  2378. }
  2379. src = match[2];
  2380. if (src && src.startsWith(BLOCKQUOTE_PREFIX))
  2381. return;
  2382. }
  2383. }
  2384. if (!match)
  2385. return null;
  2386. const img = new GalleryImgCto();
  2387. img.link = link;
  2388. img.match = match;
  2389. img.alt = alt;
  2390. img.src = src;
  2391. let width;
  2392. if (img.src) {
  2393. if (SRC_LINK_REGEX.test(img.src)) { // 1.2: match link: http://, file://, app://local/
  2394. if (img.src.startsWith('file://')) {
  2395. img.src = img.src.replace(/^file:\/+/, 'app://local/');
  2396. }
  2397. }
  2398. else if (SRC_IMG_REGREX.test(img.src)) { // 1.3: match image ext: .jpg/.jpeg/.png/.gif/.svg/.bmp
  2399. const srcArr = img.src.split('/');
  2400. if (srcArr && 0 < srcArr.length) {
  2401. img.name = srcArr[srcArr.length - 1];
  2402. }
  2403. img.convert = true;
  2404. }
  2405. }
  2406. const altArr = (_a = img.alt) === null || _a === void 0 ? void 0 : _a.split('\|'); // match[1] = alt1|alt2|...|altn|width
  2407. if (altArr && 1 < altArr.length) {
  2408. if (/\d+/.test(width = altArr[altArr.length - 1])) {
  2409. img.alt = img.alt.substring(0, img.alt.length - width.length - 1);
  2410. }
  2411. }
  2412. return img;
  2413. };
  2414. /**
  2415. * ![[src|alt1|alt2|width]]
  2416. * @param text
  2417. * @returns
  2418. */
  2419. const matchImage2 = (text) => {
  2420. let match = text.match(IMAGE_LINK_REGEX2); // 2-link: [ ![[src|alt1|alt2|width]] ](https://...)
  2421. let link = false;
  2422. let content;
  2423. if (match) {
  2424. link = true;
  2425. content = match[2];
  2426. }
  2427. else {
  2428. match = text.match(RE_WIKILINK_IMAGE); // 2: ![[src|alt1|alt2|width]]
  2429. content = match ? match[1] : null;
  2430. if (content && content.startsWith(BLOCKQUOTE_PREFIX))
  2431. return;
  2432. }
  2433. if (!match)
  2434. return null;
  2435. const img = new GalleryImgCto();
  2436. img.link = link;
  2437. img.match = match;
  2438. const contentArr = content === null || content === void 0 ? void 0 : content.split('|');
  2439. if (contentArr && 0 < contentArr.length && (img.src = contentArr[0].trim())) {
  2440. const srcArr = img.src.split('/');
  2441. if (srcArr && 0 < srcArr.length) {
  2442. img.name = srcArr[srcArr.length - 1];
  2443. }
  2444. if (1 == contentArr.length) {
  2445. img.alt = img.src;
  2446. }
  2447. else {
  2448. img.alt = '';
  2449. for (let i = 1; i < contentArr.length; i++) {
  2450. if (i == contentArr.length - 1 && /\d+/.test(contentArr[i]))
  2451. break;
  2452. if (img.alt)
  2453. img.alt += '|';
  2454. img.alt += contentArr[i];
  2455. }
  2456. }
  2457. img.convert = true;
  2458. }
  2459. return img;
  2460. };
  2461. const matchImageTag = (text) => {
  2462. let match = text.match(IMG_TAG_LINK_SRC_REGEX); // 3-a-img-src: <a> <img ... src=''/> </a>
  2463. let link = false;
  2464. if (match) {
  2465. link = true;
  2466. }
  2467. else {
  2468. match = text.match(IMG_TAG_SRC_REGEX); // 3-img-src: <img ... src='' />
  2469. }
  2470. if (!match)
  2471. return null;
  2472. const img = new GalleryImgCto();
  2473. img.link = link;
  2474. img.match = match;
  2475. img.src = img.link ? match[2] : match[1];
  2476. if (img.src) {
  2477. if (img.src.startsWith('file://')) {
  2478. img.src = img.src.replace(/^file:\/+/, 'app://local/');
  2479. }
  2480. else if (FULL_PATH_REGEX.test(img.src)) {
  2481. img.src = 'app://local/' + img.src;
  2482. }
  2483. }
  2484. const matchAlt = text.match(IMG_TAG_ALT_REGEX);
  2485. img.alt = matchAlt ? matchAlt[1] : '';
  2486. return img;
  2487. };
  2488. const md5Img = (alt, src) => {
  2489. return Md5.init((alt ? alt : '') + '_' + src);
  2490. };
  2491. class GalleryNavbarView {
  2492. constructor(mainContainerView, plugin) {
  2493. // whether to display gallery navbar
  2494. this.state = false;
  2495. this.galleryNavbarEl = null;
  2496. this.galleryListEl = null;
  2497. this.galleryIsMousingDown = false;
  2498. this.galleryMouseDownClientX = 0;
  2499. this.galleryTranslateX = 0;
  2500. this.CACHE_LIMIT = 10;
  2501. this.CLICK_TIME = 150;
  2502. this.renderGalleryImg = (imgFooterEl) => __awaiter(this, void 0, void 0, function* () {
  2503. var _a;
  2504. if (this.state)
  2505. return;
  2506. // get all of images on the current editor
  2507. const activeView = this.plugin.app.workspace.getActiveViewOfType(obsidian.MarkdownView);
  2508. if (!activeView
  2509. || 'markdown' !== activeView.getViewType()
  2510. // modal-container: community plugin, flashcards (Space Repetition)
  2511. || 0 < this.mainContainerView.getDoc().getElementsByClassName('modal-container').length) {
  2512. if (this.galleryNavbarEl)
  2513. this.galleryNavbarEl.hidden = true;
  2514. if (this.galleryListEl)
  2515. this.galleryListEl.innerHTML = '';
  2516. return;
  2517. }
  2518. // <div class="gallery-navbar"> <ul class="gallery-list"> <li> <img src='' alt=''> </li> <li...> <ul> </div>
  2519. this.initGalleryNavbar(imgFooterEl);
  2520. const activeFile = activeView.file;
  2521. let galleryImg = this.getGalleryImgCache(activeFile);
  2522. // let hitCache: boolean = true;
  2523. if (!galleryImg) {
  2524. // hitCache = false;
  2525. galleryImg = parseActiveViewData(this.plugin, (_a = activeView.data) === null || _a === void 0 ? void 0 : _a.split('\n'), activeFile);
  2526. this.setGalleryImgCache(galleryImg);
  2527. }
  2528. // console.log('oit-gallery-navbar: ' + (hitCache ? 'hit cache' : 'miss cache') + '!', galleryImg);
  2529. const imgList = galleryImg.galleryImgList;
  2530. const imgContextHash = this.getTargetImgContextHash(this.mainContainerView.getLastClickedImgEl(), activeView.containerEl, this.plugin.imgSelector);
  2531. let liEl, imgEl, liElActive;
  2532. let imgListEl = new Array();
  2533. let targetImageIdx = -1, targetRealIdx = 0;
  2534. let isAddGalleryActive = false;
  2535. let prevHash, nextHash;
  2536. const viewImageWithLink = this.plugin.settings.viewImageWithLink;
  2537. for (let i = 0, len = imgList.length; i < len; i++) {
  2538. const img = imgList[i];
  2539. if (!viewImageWithLink && img.link)
  2540. continue;
  2541. // <li> <img class='gallery-img' src='' alt=''> </li>
  2542. this.galleryListEl.append(liEl = createEl('li'));
  2543. liEl.append(imgEl = createEl('img'));
  2544. imgEl.addClass('gallery-img', 'oit-img');
  2545. imgEl.setAttr('alt', img.alt);
  2546. imgEl.setAttr('src', img.src);
  2547. imgListEl.push(imgEl);
  2548. this.mainContainerView.setImgViewDefaultBackground(imgEl);
  2549. // find the target image (which image is just clicked)
  2550. if (!imgContextHash || isAddGalleryActive)
  2551. continue;
  2552. if (imgContextHash[1] == img.hash) {
  2553. if (0 > targetImageIdx) {
  2554. targetImageIdx = i;
  2555. liElActive = liEl;
  2556. targetRealIdx = imgListEl.length;
  2557. }
  2558. if (0 == i) {
  2559. prevHash = null;
  2560. nextHash = 1 < len ? imgList[i + 1].hash : null;
  2561. }
  2562. else if (len - 1 == i) {
  2563. prevHash = imgList[i - 1].hash;
  2564. nextHash = null;
  2565. }
  2566. else {
  2567. prevHash = imgList[i - 1].hash;
  2568. nextHash = imgList[i + 1].hash;
  2569. }
  2570. if (imgContextHash[0] == prevHash && imgContextHash[2] == nextHash) {
  2571. isAddGalleryActive = true;
  2572. liElActive = liEl;
  2573. }
  2574. }
  2575. }
  2576. const realTotalNum = imgListEl.length;
  2577. this.mainContainerView.renderImgTitle(null, '[' + targetRealIdx + '/' + realTotalNum + ']');
  2578. imgListEl.forEach((value, index) => {
  2579. value.dataset.index = '[' + (index + 1) + '/' + realTotalNum + ']';
  2580. });
  2581. if (0 <= targetImageIdx) {
  2582. if (liElActive) {
  2583. liElActive.addClass('gallery-active');
  2584. if (this.settings.galleryImgBorderActive) {
  2585. liElActive.addClass('img-border-active');
  2586. liElActive.style.setProperty('border-color', this.settings.galleryImgBorderActiveColor);
  2587. }
  2588. }
  2589. this.galleryTranslateX = (this.mainContainerView.getDoc().documentElement.clientWidth || this.mainContainerView.getDoc().body.clientWidth) / 2.5 - targetImageIdx * 52;
  2590. this.galleryListEl.style.transform = 'translateX(' + this.galleryTranslateX + 'px)';
  2591. }
  2592. });
  2593. this.initDefaultData = () => {
  2594. this.galleryMouseDownClientX = 0;
  2595. this.galleryTranslateX = 0;
  2596. if (this.galleryListEl) {
  2597. this.galleryListEl.style.transform = 'translateX(0px)';
  2598. // remove all childs (li) of gallery-list
  2599. this.galleryListEl.innerHTML = '';
  2600. }
  2601. };
  2602. this.initGalleryNavbar = (imgFooterEl) => {
  2603. // <div class="gallery-navbar">
  2604. if (!this.galleryNavbarEl) {
  2605. // imgInfo.imgFooterEl.append(galleryNavbarEl = createDiv());
  2606. imgFooterEl.append(this.galleryNavbarEl = createDiv());
  2607. this.galleryNavbarEl.addClass('gallery-navbar');
  2608. this.galleryNavbarEl.onmouseover = () => {
  2609. this.galleryNavbarEl.style.setProperty('background-color', this.settings.galleryNavbarHoverColor);
  2610. };
  2611. this.galleryNavbarEl.onmouseout = () => {
  2612. this.galleryNavbarEl.style.setProperty('background-color', this.settings.galleryNavbarDefaultColor);
  2613. };
  2614. // add events
  2615. this.galleryNavbarEl.addEventListener('mousedown', this.mouseDownGallery);
  2616. this.galleryNavbarEl.addEventListener('mousemove', this.mouseMoveGallery);
  2617. this.galleryNavbarEl.addEventListener('mouseup', this.mouseUpGallery);
  2618. this.galleryNavbarEl.addEventListener('mouseleave', this.mouseLeaveGallery);
  2619. }
  2620. this.galleryNavbarEl.style.setProperty('background-color', this.settings.galleryNavbarDefaultColor);
  2621. if (!this.galleryListEl) {
  2622. this.galleryNavbarEl.append(this.galleryListEl = createEl('ul')); // <ul class="gallery-list">
  2623. this.galleryListEl.addClass('gallery-list');
  2624. }
  2625. this.initDefaultData();
  2626. this.galleryNavbarEl.hidden = false; // display 'gallery-navbar'
  2627. this.state = true;
  2628. };
  2629. this.closeGalleryNavbar = () => {
  2630. if (!this.state)
  2631. return;
  2632. this.galleryNavbarEl.hidden = true; // hide 'gallery-navbar'
  2633. this.state = false;
  2634. this.initDefaultData();
  2635. };
  2636. this.remove = () => {
  2637. var _a, _b;
  2638. this.state = false;
  2639. (_a = this.galleryNavbarEl) === null || _a === void 0 ? void 0 : _a.remove();
  2640. (_b = this.galleryListEl) === null || _b === void 0 ? void 0 : _b.remove();
  2641. this.galleryNavbarEl = null;
  2642. this.galleryListEl = null;
  2643. this.galleryIsMousingDown = false;
  2644. this.galleryMouseDownClientX = 0;
  2645. this.galleryTranslateX = 0;
  2646. this.mouseDownTime = null;
  2647. GalleryNavbarView.GALLERY_IMG_CACHE = new Map();
  2648. this.initDefaultData();
  2649. };
  2650. this.getTargetImgContextHash = (targetImgEl, containerEl, imageSelector) => {
  2651. let imgEl;
  2652. let targetImgHash = null;
  2653. let targetIdx = -1;
  2654. const imgs = containerEl.querySelectorAll(imageSelector);
  2655. // console.log('IMAGE_SELECTOR>>', imageSelector, imgs);
  2656. const len = imgs.length;
  2657. for (let i = 0; i < len; i++) {
  2658. if ((imgEl = imgs[i])) {
  2659. if ('1' == imgEl.getAttribute('data-oit-target')) {
  2660. targetIdx = i;
  2661. targetImgHash = md5Img(imgEl.alt, imgEl.src);
  2662. break;
  2663. }
  2664. }
  2665. }
  2666. if (0 > targetIdx)
  2667. targetImgHash = md5Img(targetImgEl.alt, targetImgEl.src);
  2668. let prevHash, nextHash;
  2669. if (0 == targetIdx) {
  2670. prevHash = null;
  2671. nextHash = 1 < len ? md5Img(imgs[1].alt, imgs[1].src) : null;
  2672. }
  2673. else if (len - 1 == targetIdx) {
  2674. prevHash = md5Img(imgs[targetIdx - 1].alt, imgs[targetIdx - 1].src);
  2675. nextHash = null;
  2676. }
  2677. else {
  2678. prevHash = md5Img(imgs[targetIdx - 1].alt, imgs[targetIdx - 1].src);
  2679. nextHash = md5Img(imgs[targetIdx + 1].alt, imgs[targetIdx + 1].src);
  2680. }
  2681. return [prevHash, targetImgHash, nextHash];
  2682. };
  2683. this.activateImage = (liEl, imgEL) => {
  2684. if (!liEl || 'LI' !== liEl.tagName)
  2685. return;
  2686. if (!imgEL) {
  2687. const imgELList = liEl.getElementsByTagName('img');
  2688. if (imgELList && 0 < imgELList.length) {
  2689. imgEL = imgELList[0];
  2690. }
  2691. }
  2692. if (imgEL) {
  2693. const activeImg = this.mainContainerView.getActiveImg();
  2694. this.mainContainerView.initDefaultData(activeImg, imgEL.style);
  2695. this.mainContainerView.refreshImg(activeImg, imgEL.src, imgEL.alt || '', imgEL.dataset.index);
  2696. }
  2697. liEl.addClass('gallery-active');
  2698. if (this.settings.galleryImgBorderActive) {
  2699. liEl.addClass('img-border-active');
  2700. liEl.style.setProperty('border-color', this.settings.galleryImgBorderActiveColor);
  2701. }
  2702. };
  2703. this.deactivateImage = (liEl) => {
  2704. if (!liEl)
  2705. return;
  2706. liEl.removeClass('gallery-active');
  2707. if (liEl.hasClass('img-border-active')) {
  2708. liEl.removeClass('img-border-active');
  2709. liEl.style.removeProperty('border-color');
  2710. }
  2711. };
  2712. this.clickGalleryImg = (event) => {
  2713. const targetEl = event.target;
  2714. if (!targetEl || 'IMG' !== targetEl.tagName)
  2715. return;
  2716. if (this.galleryListEl) {
  2717. const liElList = this.galleryListEl.getElementsByClassName('gallery-active');
  2718. for (let i = 0, len = liElList.length; i < len; i++) {
  2719. this.deactivateImage(liElList[i]);
  2720. }
  2721. }
  2722. this.activateImage(targetEl.parentElement, targetEl);
  2723. };
  2724. /**
  2725. * switch the image on the gallery navbar
  2726. * @param next true: switch to the next image; false: switch to the previous image
  2727. */
  2728. this.switchImage = (next) => {
  2729. if (!this.state || !this.galleryListEl)
  2730. return;
  2731. const liElList = this.galleryListEl.getElementsByTagName('li');
  2732. if (!liElList || 0 >= liElList.length)
  2733. return;
  2734. let liEl;
  2735. let toSwitchIdx = -1;
  2736. for (let i = 0, len = liElList.length; i < len; i++) {
  2737. if (!(liEl = liElList[i]))
  2738. continue;
  2739. if (liEl.hasClass('gallery-active')) {
  2740. toSwitchIdx = next ? (len <= (i + 1) ? 0 : i + 1) : (0 == i ? len - 1 : i - 1);
  2741. this.deactivateImage(liEl);
  2742. break;
  2743. }
  2744. }
  2745. if (0 >= toSwitchIdx) {
  2746. toSwitchIdx = 0;
  2747. }
  2748. this.activateImage(liElList[toSwitchIdx]);
  2749. };
  2750. this.mouseDownGallery = (event) => {
  2751. // console.log('mouse Down Gallery...');
  2752. event.preventDefault();
  2753. event.stopPropagation();
  2754. this.mouseDownTime = new Date().getTime();
  2755. this.galleryIsMousingDown = true;
  2756. this.galleryMouseDownClientX = event.clientX;
  2757. };
  2758. this.mouseMoveGallery = (event) => {
  2759. // console.log('mouse Move Gallery...');
  2760. event.preventDefault();
  2761. event.stopPropagation();
  2762. if (!this.galleryIsMousingDown)
  2763. return;
  2764. let moveDistance = event.clientX - this.galleryMouseDownClientX;
  2765. if (4 > Math.abs(moveDistance))
  2766. return;
  2767. this.galleryMouseDownClientX = event.clientX;
  2768. this.galleryTranslateX += moveDistance;
  2769. const windowWidth = this.mainContainerView.getDoc().documentElement.clientWidth || this.mainContainerView.getDoc().body.clientWidth;
  2770. const imgLiWidth = (this.galleryListEl.childElementCount - 1) * 52;
  2771. // console.log('move...', 'windowWidth=' + windowWidth, 'galleryTranslateX=' + galleryTranslateX, 'li count=' + imgInfo.galleryList.childElementCount);
  2772. if (this.galleryTranslateX + 50 >= windowWidth)
  2773. this.galleryTranslateX = windowWidth - 50;
  2774. if (0 > this.galleryTranslateX + imgLiWidth)
  2775. this.galleryTranslateX = -imgLiWidth;
  2776. this.galleryListEl.style.transform = 'translateX(' + this.galleryTranslateX + 'px)';
  2777. };
  2778. this.mouseUpGallery = (event) => {
  2779. // console.log('mouse Up Gallery>>>', event.target);
  2780. event.preventDefault();
  2781. event.stopPropagation();
  2782. this.galleryIsMousingDown = false;
  2783. if (!this.mouseDownTime || this.CLICK_TIME > new Date().getTime() - this.mouseDownTime) {
  2784. this.clickGalleryImg(event);
  2785. }
  2786. this.mouseDownTime = null;
  2787. };
  2788. this.mouseLeaveGallery = (event) => {
  2789. // console.log('mouse Leave Gallery>>>', event.target);
  2790. event.preventDefault();
  2791. event.stopPropagation();
  2792. this.galleryIsMousingDown = false;
  2793. this.mouseDownTime = null;
  2794. };
  2795. this.getGalleryImgCache = (file) => {
  2796. if (!file)
  2797. return null;
  2798. const md5File = this.md5File(file.path, file.stat.ctime);
  2799. if (!md5File)
  2800. return null;
  2801. const galleryImgCache = GalleryNavbarView.GALLERY_IMG_CACHE.get(md5File);
  2802. if (galleryImgCache && file.stat.mtime !== galleryImgCache.file.mtime) {
  2803. GalleryNavbarView.GALLERY_IMG_CACHE.delete(md5File);
  2804. return null;
  2805. }
  2806. return galleryImgCache;
  2807. };
  2808. this.setGalleryImgCache = (galleryImg) => {
  2809. const md5File = this.md5File(galleryImg.file.path, galleryImg.file.ctime);
  2810. if (!md5File)
  2811. return;
  2812. this.trimGalleryImgCache();
  2813. GalleryNavbarView.GALLERY_IMG_CACHE.set(md5File, galleryImg);
  2814. };
  2815. this.trimGalleryImgCache = () => {
  2816. if (GalleryNavbarView.GALLERY_IMG_CACHE.size < this.CACHE_LIMIT)
  2817. return;
  2818. let earliestMtime, earliestKey;
  2819. GalleryNavbarView.GALLERY_IMG_CACHE.forEach((value, key) => {
  2820. if (!earliestMtime) {
  2821. earliestMtime = value.mtime;
  2822. earliestKey = key;
  2823. }
  2824. else {
  2825. if (earliestMtime > value.mtime) {
  2826. earliestMtime = value.mtime;
  2827. earliestKey = key;
  2828. }
  2829. }
  2830. });
  2831. if (earliestKey) {
  2832. GalleryNavbarView.GALLERY_IMG_CACHE.delete(earliestKey);
  2833. }
  2834. };
  2835. this.md5File = (path, ctime) => {
  2836. if (!path || !ctime)
  2837. return;
  2838. return Md5.init(path + '_' + ctime);
  2839. };
  2840. this.mainContainerView = mainContainerView;
  2841. this.plugin = plugin;
  2842. this.settings = plugin.settings;
  2843. }
  2844. }
  2845. GalleryNavbarView.GALLERY_IMG_CACHE = new Map();
  2846. class NormalContainerView extends ContainerView {
  2847. constructor(plugin) {
  2848. super(plugin);
  2849. //region ================== Container View ========================
  2850. this.initContainerDom = (parentContainerEl) => {
  2851. let imgCto;
  2852. if (!this.imgInfo.oitContainerEl) {
  2853. // init `oit-normal` dom at first time
  2854. // <div class="oit oit-normal"> ... <div>
  2855. (this.imgInfo.oitContainerEl = createDiv()).addClass(OIT_CLASS.CONTAINER_ROOT, OIT_CLASS.CONTAINER_NORMAL);
  2856. parentContainerEl.appendChild(this.imgInfo.oitContainerEl);
  2857. // 1. <div class="oit-img-container">...</div>
  2858. this.imgInfo.oitContainerEl.append(this.imgInfo.imgContainerEl = createDiv(OIT_CLASS.IMG_CONTAINER));
  2859. // 1.1. <div class="oit-img-container"> `<img class="oit-img-view" src="" alt="">` </div>
  2860. this.updateImgViewElAndList(this.imgInfo);
  2861. // 2. <div class="oit-img-tip"></div>
  2862. this.imgInfo.oitContainerEl.appendChild(this.imgInfo.imgTipEl = createDiv(OIT_CLASS.IMG_TTP));
  2863. this.imgInfo.imgTipEl.hidden = true;
  2864. // 3. <div class="oit-img-footer"> ... <div>
  2865. this.imgInfo.oitContainerEl.appendChild(this.imgInfo.imgFooterEl = createDiv(OIT_CLASS.IMG_FOOTER));
  2866. // 3.1. <div class="oit-img-title"></div>
  2867. this.imgInfo.imgFooterEl.appendChild(this.imgInfo.imgTitleEl = createDiv(OIT_CLASS.IMG_TITLE));
  2868. // <span class="oit-img-title-name"></span>
  2869. this.imgInfo.imgTitleEl.appendChild(this.imgInfo.imgTitleNameEl = createSpan(OIT_CLASS.IMG_TITLE_NAME));
  2870. // <span class="oit-img-title-index"></span>
  2871. this.imgInfo.imgTitleEl.appendChild(this.imgInfo.imgTitleIndexEl = createSpan(OIT_CLASS.IMG_TITLE_INDEX));
  2872. // 3.2. <ul class="oit-img-toolbar">
  2873. const imgToolbarUlEL = createEl('ul');
  2874. imgToolbarUlEL.addClass(OIT_CLASS.IMG_TOOLBAR);
  2875. this.imgInfo.imgFooterEl.appendChild(imgToolbarUlEL);
  2876. let toolbarLi;
  2877. for (const toolbar of TOOLBAR_CONF) {
  2878. if (!toolbar.enableToolbarIcon)
  2879. continue;
  2880. imgToolbarUlEL.appendChild(toolbarLi = createEl('li'));
  2881. toolbarLi.addClass(toolbar.class);
  2882. toolbarLi.setAttribute('alt', toolbar.title);
  2883. // @ts-ignore
  2884. toolbarLi.setAttribute('title', t(toolbar.title));
  2885. }
  2886. // add event: for oit-img-toolbar ul
  2887. imgToolbarUlEL.addEventListener('click', this.clickImgToolbar);
  2888. // <div class="img-player"> <img class='img-fullscreen' src=''> </div>
  2889. this.imgInfo.oitContainerEl.appendChild(this.imgInfo.imgPlayerEl = createDiv(OIT_CLASS.IMG_PLAYER)); // img-player for full screen mode
  2890. this.imgInfo.imgPlayerEl.appendChild(this.imgInfo.imgPlayerImgViewEl = createEl('img'));
  2891. this.imgInfo.imgPlayerImgViewEl.addClass(OIT_CLASS.IMG_FULLSCREEN);
  2892. }
  2893. imgCto = this.imgInfo.imgList[0];
  2894. this.imgGlobalStatus.activeImg = imgCto;
  2895. return imgCto;
  2896. };
  2897. this.openOitContainerView = (matchedImg) => {
  2898. if (!this.imgInfo.oitContainerEl) {
  2899. console.error('obsidian-image-toolkit: oit-*-container-view has not been initialized!');
  2900. return;
  2901. }
  2902. matchedImg.popup = true;
  2903. this.imgGlobalStatus.popup = true;
  2904. // display 'oit-normal'
  2905. this.imgInfo.oitContainerEl.style.setProperty('display', 'block');
  2906. };
  2907. this.closeContainerView = (event, activeImg) => {
  2908. if (event) {
  2909. const target = event.target;
  2910. if (!target || !(target.hasClass(OIT_CLASS.CONTAINER_ROOT) || target.hasClass(OIT_CLASS.IMG_CONTAINER)))
  2911. return;
  2912. }
  2913. if (!activeImg && !(activeImg = this.imgGlobalStatus.activeImg))
  2914. return;
  2915. if (this.imgInfo.oitContainerEl) {
  2916. this.imgInfo.oitContainerEl.style.setProperty('display', 'none'); // hide 'oit-normal'
  2917. this.renderImgTitle('', '');
  2918. this.renderImgView(activeImg.imgViewEl, '', '');
  2919. // remove events
  2920. this.imgGlobalStatus.popup = false;
  2921. activeImg.popup = false;
  2922. activeImg.mtime = 0;
  2923. this.addOrRemoveEvents(activeImg, false);
  2924. }
  2925. if (this.plugin.settings.galleryNavbarToggle && this.galleryNavbarView) {
  2926. this.galleryNavbarView.closeGalleryNavbar();
  2927. }
  2928. };
  2929. //endregion
  2930. //region ================== Gallery Navbar ========================
  2931. this.renderGalleryNavbar = () => {
  2932. // <div class="gallery-navbar"> <ul class="gallery-list"> <li> <img src='' alt=''> </li> <li...> <ul> </div>
  2933. if (!this.plugin.settings.galleryNavbarToggle)
  2934. return;
  2935. if (!this.galleryNavbarView) {
  2936. this.galleryNavbarView = new GalleryNavbarView(this, this.plugin);
  2937. }
  2938. this.galleryNavbarView.renderGalleryImg(this.imgInfo.imgFooterEl);
  2939. };
  2940. this.removeGalleryNavbar = () => {
  2941. if (!this.galleryNavbarView)
  2942. return;
  2943. this.galleryNavbarView.remove();
  2944. this.galleryNavbarView = null;
  2945. };
  2946. //endregion
  2947. this.renderImgTitle = (name, index) => {
  2948. var _a, _b;
  2949. if (undefined !== name && null !== name)
  2950. (_a = this.imgInfo.imgTitleNameEl) === null || _a === void 0 ? void 0 : _a.setText(name);
  2951. if (undefined !== index && null !== index)
  2952. (_b = this.imgInfo.imgTitleIndexEl) === null || _b === void 0 ? void 0 : _b.setText(' ' + index);
  2953. };
  2954. this.switchImageOnGalleryNavBar = (event, next) => {
  2955. var _a;
  2956. if (!this.checkHotkeySettings(event, this.plugin.settings.switchTheImageHotkey))
  2957. return;
  2958. (_a = this.galleryNavbarView) === null || _a === void 0 ? void 0 : _a.switchImage(next);
  2959. };
  2960. }
  2961. setActiveImgForMouseEvent(imgCto) {
  2962. }
  2963. }
  2964. /**
  2965. * Right click menu
  2966. */
  2967. class MenuView {
  2968. constructor(pinContainerView) {
  2969. this.init = () => {
  2970. if (this.menu)
  2971. return;
  2972. this.menu = new obsidian.Menu();
  2973. for (const itemConf of TOOLBAR_CONF) {
  2974. if (!itemConf.enableMenu)
  2975. continue;
  2976. if (SEPARATOR_SYMBOL === itemConf.title) {
  2977. this.menu.addSeparator();
  2978. continue;
  2979. }
  2980. this.menu.addItem(item => {
  2981. if (itemConf.icon)
  2982. item.setIcon(itemConf.icon);
  2983. // @ts-ignore
  2984. item.setTitle(t(itemConf.title))
  2985. .onClick(() => {
  2986. this.pinContainerView.clickImgToolbar(null, itemConf.class, MenuView.activeImg);
  2987. });
  2988. });
  2989. }
  2990. };
  2991. this.show = (event, activeImg) => {
  2992. MenuView.activeImg = activeImg;
  2993. this.init();
  2994. this.menu.showAtPosition({ x: event.clientX, y: event.clientY });
  2995. };
  2996. this.pinContainerView = pinContainerView;
  2997. }
  2998. }
  2999. /**
  3000. * PinContainerView: Pin an image on the top
  3001. * @Support: move an image by mouse; close an image by Esc
  3002. * @Nonsupport: move an image by keyboard; display gallery navbar
  3003. */
  3004. class PinContainerView extends ContainerView {
  3005. constructor(plugin /*, viewMode: ViewMode*/) {
  3006. super(plugin /*, viewMode, plugin.settings.pinMaximum*/);
  3007. //region ================== Container View ========================
  3008. this.initContainerDom = (parentContainerEl) => {
  3009. /*
  3010. <div class="oit-pin-container-view">
  3011. <div class="oit-img-container">
  3012. <img class="oit-img-view" data-index='0' src="" alt="">
  3013. <img class="oit-img-view" data-index='1' src="" alt="">
  3014. ...
  3015. </div>
  3016. </div>
  3017. */
  3018. if (!this.imgInfo.oitContainerEl) { // init at first time
  3019. // create: <div class="oit oit-pin">
  3020. (this.imgInfo.oitContainerEl = createDiv()).addClass(OIT_CLASS.CONTAINER_ROOT, OIT_CLASS.CONTAINER_PIN);
  3021. parentContainerEl.appendChild(this.imgInfo.oitContainerEl);
  3022. // <div class="oit oit-pin"> <div class="oit-img-container"/> </div>
  3023. this.imgInfo.oitContainerEl.append(this.imgInfo.imgContainerEl = createDiv(OIT_CLASS.IMG_CONTAINER));
  3024. // <div class="oit-img-tip"></div>
  3025. this.imgInfo.oitContainerEl.appendChild(this.imgInfo.imgTipEl = createDiv(OIT_CLASS.IMG_TTP)); // oit-img-tip
  3026. this.imgInfo.imgTipEl.hidden = true; // hide 'oit-img-tip'
  3027. // <div class="img-player"> <img class='img-fullscreen' src=''> </div>
  3028. this.imgInfo.oitContainerEl.appendChild(this.imgInfo.imgPlayerEl = createDiv(OIT_CLASS.IMG_PLAYER)); // img-player for full screen mode
  3029. this.imgInfo.imgPlayerEl.appendChild(this.imgInfo.imgPlayerImgViewEl = createEl('img'));
  3030. this.imgInfo.imgPlayerImgViewEl.addClass(OIT_CLASS.IMG_FULLSCREEN);
  3031. }
  3032. // <div class="oit-img-container"> <img class="oit-img-view" src="" alt=""> </div>
  3033. this.updateImgViewElAndList(this.imgInfo);
  3034. return this.getMatchedImg();
  3035. };
  3036. this.openOitContainerView = (matchedImg) => {
  3037. if (!this.imgInfo.oitContainerEl) {
  3038. console.error('obsidian-image-toolkit: oit-*-container-view has not been initialized!');
  3039. return;
  3040. }
  3041. matchedImg.popup = true;
  3042. if (!this.imgGlobalStatus.popup) {
  3043. this.imgGlobalStatus.popup = true;
  3044. this.imgGlobalStatus.activeImgZIndex = 0;
  3045. this.imgInfo.imgList.forEach(value => {
  3046. value.zIndex = 0;
  3047. });
  3048. }
  3049. else {
  3050. matchedImg.zIndex = (++this.imgGlobalStatus.activeImgZIndex);
  3051. }
  3052. matchedImg.imgViewEl.style.setProperty('z-index', matchedImg.zIndex + '');
  3053. // display 'oit-pin-container-view'
  3054. this.imgInfo.oitContainerEl.style.setProperty('display', 'block');
  3055. };
  3056. /**
  3057. * hide container view
  3058. * @param event not null: click event; null: keyboard event (Esc)
  3059. * @param activeImg
  3060. */
  3061. this.closeContainerView = (event, activeImg) => {
  3062. if (event && !activeImg) {
  3063. // PinContainerView doesn't need click event to hide container for now
  3064. return;
  3065. }
  3066. if (!this.imgInfo.oitContainerEl)
  3067. return;
  3068. if (!activeImg && !(activeImg = this.imgGlobalStatus.activeImg))
  3069. return;
  3070. // console.log('closeContainerView', event, activeImg)
  3071. this.renderImgView(activeImg.imgViewEl, '', '');
  3072. activeImg.popup = false;
  3073. activeImg.mtime = 0;
  3074. let globalPopupFlag = false;
  3075. for (const imgCto of this.imgInfo.imgList) {
  3076. if (imgCto.popup) {
  3077. globalPopupFlag = true;
  3078. break;
  3079. }
  3080. }
  3081. if (!globalPopupFlag) {
  3082. this.imgInfo.oitContainerEl.style.setProperty('display', 'none'); // hide 'oit-pin-container-view'
  3083. this.imgGlobalStatus.activeImgZIndex = 0;
  3084. this.imgInfo.imgList.forEach(value => {
  3085. value.zIndex = 0;
  3086. });
  3087. }
  3088. this.imgGlobalStatus.popup = globalPopupFlag;
  3089. this.addOrRemoveEvents(activeImg, false);
  3090. };
  3091. //endregion
  3092. this.setActiveImgZIndex = (activeImg) => {
  3093. var _a;
  3094. let isUpdate = false;
  3095. for (const imgCto of this.imgInfo.imgList) {
  3096. if (activeImg.index !== imgCto.index && activeImg.zIndex <= imgCto.zIndex) {
  3097. isUpdate = true;
  3098. break;
  3099. }
  3100. }
  3101. if (isUpdate) {
  3102. activeImg.zIndex = (++this.imgGlobalStatus.activeImgZIndex);
  3103. (_a = activeImg.imgViewEl) === null || _a === void 0 ? void 0 : _a.style.setProperty("z-index", activeImg.zIndex + '');
  3104. }
  3105. };
  3106. this.setMenuView(new MenuView(this));
  3107. }
  3108. setActiveImgForMouseEvent(imgCto) {
  3109. this.imgGlobalStatus.activeImg = imgCto;
  3110. }
  3111. }
  3112. class ContainerFactory {
  3113. constructor() {
  3114. // popout window containers: hash -> ContainerView
  3115. this.popoutContainers = new Map();
  3116. this.setMainContainer = (container) => {
  3117. this.mainContainer = container;
  3118. };
  3119. this.getMainContainer = () => {
  3120. return this.mainContainer;
  3121. };
  3122. this.setPopoutContainer = (key, container) => {
  3123. this.popoutContainers.set(key, container);
  3124. };
  3125. this.getPopoutContainer = (key) => {
  3126. return this.popoutContainers.get(key);
  3127. };
  3128. this.getPopoutContainers = () => {
  3129. return this.popoutContainers;
  3130. };
  3131. this.getContainer = (targetEl) => {
  3132. const bodyEl = targetEl === null || targetEl === void 0 ? void 0 : targetEl.matchParent('body');
  3133. if (!bodyEl)
  3134. return null;
  3135. const oitEventKey = bodyEl.getAttribute('data-oit-event');
  3136. if (oitEventKey) {
  3137. //popout window
  3138. return this.getPopoutContainer(oitEventKey);
  3139. }
  3140. return this.mainContainer;
  3141. };
  3142. this.getAllContainers = () => {
  3143. let allContainerViews = [this.mainContainer];
  3144. for (let value of this.popoutContainers.values()) {
  3145. allContainerViews.push(value);
  3146. }
  3147. return allContainerViews;
  3148. };
  3149. this.clearAll = () => {
  3150. this.mainContainer = null;
  3151. this.popoutContainers.clear();
  3152. };
  3153. }
  3154. }
  3155. class ImageToolkitPlugin extends obsidian.Plugin {
  3156. constructor() {
  3157. super(...arguments);
  3158. this.containerFactory = new ContainerFactory();
  3159. this.imgSelector = ``;
  3160. this.addIcons = () => __awaiter(this, void 0, void 0, function* () {
  3161. for (const icon of ICONS) {
  3162. obsidian.addIcon(icon.id, icon.svg);
  3163. }
  3164. });
  3165. this.getViewMode = () => {
  3166. return this.settings.viewMode;
  3167. };
  3168. this.setViewMode = (viewMode) => {
  3169. return this.settings.viewMode = viewMode;
  3170. };
  3171. this.checkViewMode = (viewMode) => __awaiter(this, void 0, void 0, function* () {
  3172. for (const key in ViewMode) {
  3173. if (key == viewMode) {
  3174. return;
  3175. }
  3176. }
  3177. this.setViewMode(DEFAULT_VIEW_MODE);
  3178. console.log('[oit] Reset view mode: %s', DEFAULT_VIEW_MODE);
  3179. yield this.saveSettings();
  3180. });
  3181. this.getAllContainerViews = () => {
  3182. return this.containerFactory.getAllContainers();
  3183. };
  3184. this.initContainer = (viewMode, popoutWindowEventId) => __awaiter(this, void 0, void 0, function* () {
  3185. const container = yield this.initContainerByViewMode(viewMode);
  3186. if (!container) {
  3187. console.error('[oit] Cannot init container');
  3188. return;
  3189. }
  3190. if (popoutWindowEventId) {
  3191. // popoutWindowEventId will be recorded into data-oit-event'of body tag
  3192. this.containerFactory.setPopoutContainer(popoutWindowEventId, container);
  3193. }
  3194. else {
  3195. this.containerFactory.setMainContainer(container);
  3196. }
  3197. });
  3198. this.initContainerByViewMode = (viewMode, fromDefault) => __awaiter(this, void 0, void 0, function* () {
  3199. switch (viewMode) {
  3200. case ViewMode.Normal:
  3201. return new NormalContainerView(this);
  3202. case ViewMode.Pin:
  3203. return new PinContainerView(this);
  3204. default:
  3205. if (fromDefault) {
  3206. return null;
  3207. }
  3208. this.setViewMode(viewMode = DEFAULT_VIEW_MODE);
  3209. yield this.saveSettings();
  3210. console.log('[oit] Reset view mode to: %s', viewMode);
  3211. return this.initContainerByViewMode(viewMode, true);
  3212. }
  3213. });
  3214. this.isImageElement = (imgEl) => {
  3215. return imgEl && 'IMG' === imgEl.tagName;
  3216. };
  3217. this.isClickable = (targetEl, event) => {
  3218. let container;
  3219. if (this.isImageElement(targetEl)
  3220. && (container = this.containerFactory.getContainer(targetEl))
  3221. && container.checkHotkeySettings(event, this.settings.viewTriggerHotkey)) {
  3222. return container;
  3223. }
  3224. return null;
  3225. };
  3226. this.switchViewMode = (viewMode) => __awaiter(this, void 0, void 0, function* () {
  3227. this.settings.viewMode = viewMode;
  3228. yield this.saveSettings();
  3229. this.getAllContainerViews().forEach(container => {
  3230. var _a;
  3231. container.removeOitContainerView();
  3232. this.initContainer(viewMode, (_a = container.getParentContainerEl()) === null || _a === void 0 ? void 0 : _a.getAttribute('data-oit-event'));
  3233. });
  3234. });
  3235. /**
  3236. * refresh events for main container
  3237. */
  3238. this.refreshViewTrigger = (doc) => {
  3239. // .workspace-leaf-content[data-type='markdown'] img,.workspace-leaf-content[data-type='image'] img
  3240. const viewImageInEditor = this.settings.viewImageInEditor;
  3241. // .community-modal-details img
  3242. const viewImageInCPB = this.settings.viewImageInCPB;
  3243. // false: ... img:not(a img)
  3244. const viewImageWithLink = this.settings.viewImageWithLink;
  3245. // #sr-flashcard-view img
  3246. const viewImageOther = this.settings.viewImageOther;
  3247. if (!doc) {
  3248. doc = document;
  3249. }
  3250. if (this.imgSelector) {
  3251. doc.off('click', this.imgSelector, this.clickImage);
  3252. doc.off('mouseover', this.imgSelector, this.mouseoverImg);
  3253. doc.off('mouseout', this.imgSelector, this.mouseoutImg);
  3254. }
  3255. if (!viewImageOther && !viewImageInEditor && !viewImageInCPB && !viewImageWithLink) {
  3256. return;
  3257. }
  3258. let selector = ``;
  3259. if (viewImageInEditor) {
  3260. selector += (viewImageWithLink ? VIEW_IMG_SELECTOR.EDITOR_AREAS : VIEW_IMG_SELECTOR.EDITOR_AREAS_NO_LINK);
  3261. }
  3262. if (viewImageInCPB) {
  3263. selector += (1 < selector.length ? `,` : ``) + (viewImageWithLink ? VIEW_IMG_SELECTOR.CPB : VIEW_IMG_SELECTOR.CPB_NO_LINK);
  3264. }
  3265. if (viewImageOther) {
  3266. selector += (1 < selector.length ? `,` : ``) + (viewImageWithLink ? VIEW_IMG_SELECTOR.OTHER : VIEW_IMG_SELECTOR.OTHER_NO_LINK);
  3267. }
  3268. if (selector) {
  3269. this.imgSelector = selector;
  3270. // doc.onclick = (event: MouseEvent) =>{
  3271. // console.log(event.target);
  3272. // }
  3273. doc.on('click', this.imgSelector, this.clickImage);
  3274. doc.on('mouseover', this.imgSelector, this.mouseoverImg);
  3275. doc.on('mouseout', this.imgSelector, this.mouseoutImg);
  3276. }
  3277. };
  3278. this.clickImage = (event) => {
  3279. const targetEl = event.target;
  3280. let container = this.isClickable(targetEl, event);
  3281. if (container) {
  3282. container.renderContainer(targetEl);
  3283. }
  3284. };
  3285. this.mouseoverImg = (event) => {
  3286. const targetEl = event.target;
  3287. if (!this.isClickable(targetEl, event)) {
  3288. return;
  3289. }
  3290. if (null == targetEl.getAttribute(ImageToolkitPlugin.IMG_ORIGIN_CURSOR)) {
  3291. targetEl.setAttribute(ImageToolkitPlugin.IMG_ORIGIN_CURSOR, targetEl.style.cursor || '');
  3292. }
  3293. targetEl.style.cursor = 'zoom-in';
  3294. };
  3295. this.mouseoutImg = (event) => {
  3296. const targetEl = event.target;
  3297. if (!this.isClickable(targetEl, event)) {
  3298. return;
  3299. }
  3300. targetEl.style.cursor = targetEl.getAttribute(ImageToolkitPlugin.IMG_ORIGIN_CURSOR);
  3301. };
  3302. }
  3303. onload() {
  3304. return __awaiter(this, void 0, void 0, function* () {
  3305. console.log('loading %s plugin v%s ...', this.manifest.id, this.manifest.version);
  3306. yield this.loadSettings();
  3307. this.addSettingTab(new ImageToolkitSettingTab(this.app, this));
  3308. // this.registerCommands();
  3309. yield this.initContainer(this.settings.viewMode);
  3310. this.refreshViewTrigger();
  3311. // addEventListener for opened new windows
  3312. this.app.workspace.on('layout-change', () => {
  3313. this.app.workspace.iterateAllLeaves((leaf) => {
  3314. var _a;
  3315. if (['markdown', 'image'].includes((_a = leaf.getViewState()) === null || _a === void 0 ? void 0 : _a.type)) {
  3316. const bodyEl = leaf.view.containerEl.matchParent('body');
  3317. if (bodyEl === null || bodyEl === void 0 ? void 0 : bodyEl.hasClass('is-popout-window')) {
  3318. if (!bodyEl.hasAttribute(ImageToolkitPlugin.POPOUT_WINDOW_EVENT)) {
  3319. console.log('popout leaf:', leaf, leaf.getDisplayText());
  3320. const eventId = crypto.randomUUID();
  3321. this.initContainer(this.settings.viewMode, eventId);
  3322. bodyEl.setAttr(ImageToolkitPlugin.POPOUT_WINDOW_EVENT, eventId);
  3323. this.refreshViewTrigger(bodyEl.ownerDocument);
  3324. }
  3325. }
  3326. }
  3327. });
  3328. });
  3329. });
  3330. }
  3331. onunload() {
  3332. console.log('unloading ' + this.manifest.id + ' plugin...');
  3333. this.getAllContainerViews().forEach(container => {
  3334. container.removeOitContainerView();
  3335. });
  3336. this.containerFactory.clearAll();
  3337. document.off('click', this.imgSelector, this.clickImage);
  3338. document.off('mouseover', this.imgSelector, this.mouseoverImg);
  3339. document.off('mouseout', this.imgSelector, this.mouseoutImg);
  3340. }
  3341. loadSettings() {
  3342. return __awaiter(this, void 0, void 0, function* () {
  3343. this.settings = Object.assign({}, DEFAULT_SETTINGS, yield this.loadData());
  3344. yield this.checkViewMode(this.getViewMode());
  3345. yield this.addIcons();
  3346. });
  3347. }
  3348. saveSettings() {
  3349. return __awaiter(this, void 0, void 0, function* () {
  3350. yield this.saveData(this.settings);
  3351. });
  3352. }
  3353. registerCommands() {
  3354. return __awaiter(this, void 0, void 0, function* () {
  3355. /* this.addCommand({
  3356. "id": "oit-move-up-image",
  3357. "name": "move up the image",
  3358. hotkeys: [{ modifiers: ["Ctrl"], key: "ArrowUp" }],
  3359. checkCallback: (checking: boolean) => {
  3360. if (checking) return false;
  3361. this.containerView.moveImgViewByHotkey('UP');
  3362. },
  3363. }); */
  3364. });
  3365. }
  3366. }
  3367. ImageToolkitPlugin.IMG_ORIGIN_CURSOR = 'data-oit-origin-cursor';
  3368. // data-oit-event: 标识new window是否已addEventListener for click
  3369. ImageToolkitPlugin.POPOUT_WINDOW_EVENT = 'data-oit-event';
  3370. module.exports = ImageToolkitPlugin;
  3371. /* nosourcemap */