plugin.js 56 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829
  1. /**
  2. * Copyright (c) Tiny Technologies, Inc. All rights reserved.
  3. * Licensed under the LGPL or a commercial license.
  4. * For LGPL see License.txt in the project root for license information.
  5. * For commercial licenses see https://www.tiny.cloud/
  6. *
  7. * Version: 5.0.7 (2019-06-05)
  8. */
  9. (function () {
  10. var imagetools = (function (domGlobals) {
  11. 'use strict';
  12. var Cell = function (initial) {
  13. var value = initial;
  14. var get = function () {
  15. return value;
  16. };
  17. var set = function (v) {
  18. value = v;
  19. };
  20. var clone = function () {
  21. return Cell(get());
  22. };
  23. return {
  24. get: get,
  25. set: set,
  26. clone: clone
  27. };
  28. };
  29. var global = tinymce.util.Tools.resolve('tinymce.PluginManager');
  30. var global$1 = tinymce.util.Tools.resolve('tinymce.util.Tools');
  31. var compose = function (fa, fb) {
  32. return function () {
  33. var args = [];
  34. for (var _i = 0; _i < arguments.length; _i++) {
  35. args[_i] = arguments[_i];
  36. }
  37. return fa(fb.apply(null, args));
  38. };
  39. };
  40. var constant = function (value) {
  41. return function () {
  42. return value;
  43. };
  44. };
  45. var never = constant(false);
  46. var always = constant(true);
  47. var never$1 = never;
  48. var always$1 = always;
  49. var none = function () {
  50. return NONE;
  51. };
  52. var NONE = function () {
  53. var eq = function (o) {
  54. return o.isNone();
  55. };
  56. var call = function (thunk) {
  57. return thunk();
  58. };
  59. var id = function (n) {
  60. return n;
  61. };
  62. var noop = function () {
  63. };
  64. var nul = function () {
  65. return null;
  66. };
  67. var undef = function () {
  68. return undefined;
  69. };
  70. var me = {
  71. fold: function (n, s) {
  72. return n();
  73. },
  74. is: never$1,
  75. isSome: never$1,
  76. isNone: always$1,
  77. getOr: id,
  78. getOrThunk: call,
  79. getOrDie: function (msg) {
  80. throw new Error(msg || 'error: getOrDie called on none.');
  81. },
  82. getOrNull: nul,
  83. getOrUndefined: undef,
  84. or: id,
  85. orThunk: call,
  86. map: none,
  87. ap: none,
  88. each: noop,
  89. bind: none,
  90. flatten: none,
  91. exists: never$1,
  92. forall: always$1,
  93. filter: none,
  94. equals: eq,
  95. equals_: eq,
  96. toArray: function () {
  97. return [];
  98. },
  99. toString: constant('none()')
  100. };
  101. if (Object.freeze)
  102. Object.freeze(me);
  103. return me;
  104. }();
  105. var some = function (a) {
  106. var constant_a = function () {
  107. return a;
  108. };
  109. var self = function () {
  110. return me;
  111. };
  112. var map = function (f) {
  113. return some(f(a));
  114. };
  115. var bind = function (f) {
  116. return f(a);
  117. };
  118. var me = {
  119. fold: function (n, s) {
  120. return s(a);
  121. },
  122. is: function (v) {
  123. return a === v;
  124. },
  125. isSome: always$1,
  126. isNone: never$1,
  127. getOr: constant_a,
  128. getOrThunk: constant_a,
  129. getOrDie: constant_a,
  130. getOrNull: constant_a,
  131. getOrUndefined: constant_a,
  132. or: self,
  133. orThunk: self,
  134. map: map,
  135. ap: function (optfab) {
  136. return optfab.fold(none, function (fab) {
  137. return some(fab(a));
  138. });
  139. },
  140. each: function (f) {
  141. f(a);
  142. },
  143. bind: bind,
  144. flatten: constant_a,
  145. exists: bind,
  146. forall: bind,
  147. filter: function (f) {
  148. return f(a) ? me : NONE;
  149. },
  150. equals: function (o) {
  151. return o.is(a);
  152. },
  153. equals_: function (o, elementEq) {
  154. return o.fold(never$1, function (b) {
  155. return elementEq(a, b);
  156. });
  157. },
  158. toArray: function () {
  159. return [a];
  160. },
  161. toString: function () {
  162. return 'some(' + a + ')';
  163. }
  164. };
  165. return me;
  166. };
  167. var from = function (value) {
  168. return value === null || value === undefined ? NONE : some(value);
  169. };
  170. var Option = {
  171. some: some,
  172. none: none,
  173. from: from
  174. };
  175. var Global = typeof domGlobals.window !== 'undefined' ? domGlobals.window : Function('return this;')();
  176. var path = function (parts, scope) {
  177. var o = scope !== undefined && scope !== null ? scope : Global;
  178. for (var i = 0; i < parts.length && o !== undefined && o !== null; ++i)
  179. o = o[parts[i]];
  180. return o;
  181. };
  182. var resolve = function (p, scope) {
  183. var parts = p.split('.');
  184. return path(parts, scope);
  185. };
  186. var unsafe = function (name, scope) {
  187. return resolve(name, scope);
  188. };
  189. var getOrDie = function (name, scope) {
  190. var actual = unsafe(name, scope);
  191. if (actual === undefined || actual === null)
  192. throw name + ' not available on this browser';
  193. return actual;
  194. };
  195. var Global$1 = { getOrDie: getOrDie };
  196. function SandBlob (parts, properties) {
  197. var f = Global$1.getOrDie('Blob');
  198. return new f(parts, properties);
  199. }
  200. function FileReader () {
  201. var f = Global$1.getOrDie('FileReader');
  202. return new f();
  203. }
  204. function Uint8Array (arr) {
  205. var f = Global$1.getOrDie('Uint8Array');
  206. return new f(arr);
  207. }
  208. var requestAnimationFrame = function (callback) {
  209. var f = Global$1.getOrDie('requestAnimationFrame');
  210. f(callback);
  211. };
  212. var atob = function (base64) {
  213. var f = Global$1.getOrDie('atob');
  214. return f(base64);
  215. };
  216. var Window = {
  217. atob: atob,
  218. requestAnimationFrame: requestAnimationFrame
  219. };
  220. function create(width, height) {
  221. return resize(domGlobals.document.createElement('canvas'), width, height);
  222. }
  223. function clone(canvas) {
  224. var tCanvas = create(canvas.width, canvas.height);
  225. var ctx = get2dContext(tCanvas);
  226. ctx.drawImage(canvas, 0, 0);
  227. return tCanvas;
  228. }
  229. function get2dContext(canvas) {
  230. return canvas.getContext('2d');
  231. }
  232. function resize(canvas, width, height) {
  233. canvas.width = width;
  234. canvas.height = height;
  235. return canvas;
  236. }
  237. function getWidth(image) {
  238. return image.naturalWidth || image.width;
  239. }
  240. function getHeight(image) {
  241. return image.naturalHeight || image.height;
  242. }
  243. var promise = function () {
  244. var Promise = function (fn) {
  245. if (typeof this !== 'object') {
  246. throw new TypeError('Promises must be constructed via new');
  247. }
  248. if (typeof fn !== 'function') {
  249. throw new TypeError('not a function');
  250. }
  251. this._state = null;
  252. this._value = null;
  253. this._deferreds = [];
  254. doResolve(fn, bind(resolve, this), bind(reject, this));
  255. };
  256. var asap = Promise.immediateFn || typeof window.setImmediate === 'function' && window.setImmediate || function (fn) {
  257. domGlobals.setTimeout(fn, 1);
  258. };
  259. function bind(fn, thisArg) {
  260. return function () {
  261. return fn.apply(thisArg, arguments);
  262. };
  263. }
  264. var isArray = Array.isArray || function (value) {
  265. return Object.prototype.toString.call(value) === '[object Array]';
  266. };
  267. function handle(deferred) {
  268. var me = this;
  269. if (this._state === null) {
  270. this._deferreds.push(deferred);
  271. return;
  272. }
  273. asap(function () {
  274. var cb = me._state ? deferred.onFulfilled : deferred.onRejected;
  275. if (cb === null) {
  276. (me._state ? deferred.resolve : deferred.reject)(me._value);
  277. return;
  278. }
  279. var ret;
  280. try {
  281. ret = cb(me._value);
  282. } catch (e) {
  283. deferred.reject(e);
  284. return;
  285. }
  286. deferred.resolve(ret);
  287. });
  288. }
  289. function resolve(newValue) {
  290. try {
  291. if (newValue === this) {
  292. throw new TypeError('A promise cannot be resolved with itself.');
  293. }
  294. if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) {
  295. var then = newValue.then;
  296. if (typeof then === 'function') {
  297. doResolve(bind(then, newValue), bind(resolve, this), bind(reject, this));
  298. return;
  299. }
  300. }
  301. this._state = true;
  302. this._value = newValue;
  303. finale.call(this);
  304. } catch (e) {
  305. reject.call(this, e);
  306. }
  307. }
  308. function reject(newValue) {
  309. this._state = false;
  310. this._value = newValue;
  311. finale.call(this);
  312. }
  313. function finale() {
  314. for (var _i = 0, _a = this._deferreds; _i < _a.length; _i++) {
  315. var deferred = _a[_i];
  316. handle.call(this, deferred);
  317. }
  318. this._deferreds = [];
  319. }
  320. function Handler(onFulfilled, onRejected, resolve, reject) {
  321. this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null;
  322. this.onRejected = typeof onRejected === 'function' ? onRejected : null;
  323. this.resolve = resolve;
  324. this.reject = reject;
  325. }
  326. function doResolve(fn, onFulfilled, onRejected) {
  327. var done = false;
  328. try {
  329. fn(function (value) {
  330. if (done) {
  331. return;
  332. }
  333. done = true;
  334. onFulfilled(value);
  335. }, function (reason) {
  336. if (done) {
  337. return;
  338. }
  339. done = true;
  340. onRejected(reason);
  341. });
  342. } catch (ex) {
  343. if (done) {
  344. return;
  345. }
  346. done = true;
  347. onRejected(ex);
  348. }
  349. }
  350. Promise.prototype.catch = function (onRejected) {
  351. return this.then(null, onRejected);
  352. };
  353. Promise.prototype.then = function (onFulfilled, onRejected) {
  354. var me = this;
  355. return new Promise(function (resolve, reject) {
  356. handle.call(me, new Handler(onFulfilled, onRejected, resolve, reject));
  357. });
  358. };
  359. Promise.all = function () {
  360. var values = [];
  361. for (var _i = 0; _i < arguments.length; _i++) {
  362. values[_i] = arguments[_i];
  363. }
  364. var args = Array.prototype.slice.call(values.length === 1 && isArray(values[0]) ? values[0] : values);
  365. return new Promise(function (resolve, reject) {
  366. if (args.length === 0) {
  367. return resolve([]);
  368. }
  369. var remaining = args.length;
  370. function res(i, val) {
  371. try {
  372. if (val && (typeof val === 'object' || typeof val === 'function')) {
  373. var then = val.then;
  374. if (typeof then === 'function') {
  375. then.call(val, function (val) {
  376. res(i, val);
  377. }, reject);
  378. return;
  379. }
  380. }
  381. args[i] = val;
  382. if (--remaining === 0) {
  383. resolve(args);
  384. }
  385. } catch (ex) {
  386. reject(ex);
  387. }
  388. }
  389. for (var i = 0; i < args.length; i++) {
  390. res(i, args[i]);
  391. }
  392. });
  393. };
  394. Promise.resolve = function (value) {
  395. if (value && typeof value === 'object' && value.constructor === Promise) {
  396. return value;
  397. }
  398. return new Promise(function (resolve) {
  399. resolve(value);
  400. });
  401. };
  402. Promise.reject = function (reason) {
  403. return new Promise(function (resolve, reject) {
  404. reject(reason);
  405. });
  406. };
  407. Promise.race = function (values) {
  408. return new Promise(function (resolve, reject) {
  409. for (var _i = 0, values_1 = values; _i < values_1.length; _i++) {
  410. var value = values_1[_i];
  411. value.then(resolve, reject);
  412. }
  413. });
  414. };
  415. return Promise;
  416. };
  417. var Promise = window.Promise ? window.Promise : promise();
  418. function imageToBlob(image) {
  419. var src = image.src;
  420. if (src.indexOf('data:') === 0) {
  421. return dataUriToBlob(src);
  422. }
  423. return anyUriToBlob(src);
  424. }
  425. function blobToImage(blob) {
  426. return new Promise(function (resolve, reject) {
  427. var blobUrl = domGlobals.URL.createObjectURL(blob);
  428. var image = new domGlobals.Image();
  429. var removeListeners = function () {
  430. image.removeEventListener('load', loaded);
  431. image.removeEventListener('error', error);
  432. };
  433. function loaded() {
  434. removeListeners();
  435. resolve(image);
  436. }
  437. function error() {
  438. removeListeners();
  439. reject('Unable to load data of type ' + blob.type + ': ' + blobUrl);
  440. }
  441. image.addEventListener('load', loaded);
  442. image.addEventListener('error', error);
  443. image.src = blobUrl;
  444. if (image.complete) {
  445. loaded();
  446. }
  447. });
  448. }
  449. function anyUriToBlob(url) {
  450. return new Promise(function (resolve, reject) {
  451. var xhr = new domGlobals.XMLHttpRequest();
  452. xhr.open('GET', url, true);
  453. xhr.responseType = 'blob';
  454. xhr.onload = function () {
  455. if (this.status === 200) {
  456. resolve(this.response);
  457. }
  458. };
  459. xhr.onerror = function () {
  460. var _this = this;
  461. var corsError = function () {
  462. var obj = new Error('No access to download image');
  463. obj.code = 18;
  464. obj.name = 'SecurityError';
  465. return obj;
  466. };
  467. var genericError = function () {
  468. return new Error('Error ' + _this.status + ' downloading image');
  469. };
  470. reject(this.status === 0 ? corsError() : genericError());
  471. };
  472. xhr.send();
  473. });
  474. }
  475. function dataUriToBlobSync(uri) {
  476. var data = uri.split(',');
  477. var matches = /data:([^;]+)/.exec(data[0]);
  478. if (!matches) {
  479. return Option.none();
  480. }
  481. var mimetype = matches[1];
  482. var base64 = data[1];
  483. var sliceSize = 1024;
  484. var byteCharacters = Window.atob(base64);
  485. var bytesLength = byteCharacters.length;
  486. var slicesCount = Math.ceil(bytesLength / sliceSize);
  487. var byteArrays = new Array(slicesCount);
  488. for (var sliceIndex = 0; sliceIndex < slicesCount; ++sliceIndex) {
  489. var begin = sliceIndex * sliceSize;
  490. var end = Math.min(begin + sliceSize, bytesLength);
  491. var bytes = new Array(end - begin);
  492. for (var offset = begin, i = 0; offset < end; ++i, ++offset) {
  493. bytes[i] = byteCharacters[offset].charCodeAt(0);
  494. }
  495. byteArrays[sliceIndex] = Uint8Array(bytes);
  496. }
  497. return Option.some(SandBlob(byteArrays, { type: mimetype }));
  498. }
  499. function dataUriToBlob(uri) {
  500. return new Promise(function (resolve, reject) {
  501. dataUriToBlobSync(uri).fold(function () {
  502. reject('uri is not base64: ' + uri);
  503. }, resolve);
  504. });
  505. }
  506. function canvasToBlob(canvas, type, quality) {
  507. type = type || 'image/png';
  508. if (domGlobals.HTMLCanvasElement.prototype.toBlob) {
  509. return new Promise(function (resolve, reject) {
  510. canvas.toBlob(function (blob) {
  511. if (blob) {
  512. resolve(blob);
  513. } else {
  514. reject();
  515. }
  516. }, type, quality);
  517. });
  518. } else {
  519. return dataUriToBlob(canvas.toDataURL(type, quality));
  520. }
  521. }
  522. function canvasToDataURL(canvas, type, quality) {
  523. type = type || 'image/png';
  524. return canvas.toDataURL(type, quality);
  525. }
  526. function blobToCanvas(blob) {
  527. return blobToImage(blob).then(function (image) {
  528. revokeImageUrl(image);
  529. var canvas = create(getWidth(image), getHeight(image));
  530. var context = get2dContext(canvas);
  531. context.drawImage(image, 0, 0);
  532. return canvas;
  533. });
  534. }
  535. function blobToDataUri(blob) {
  536. return new Promise(function (resolve) {
  537. var reader = FileReader();
  538. reader.onloadend = function () {
  539. resolve(reader.result);
  540. };
  541. reader.readAsDataURL(blob);
  542. });
  543. }
  544. function revokeImageUrl(image) {
  545. domGlobals.URL.revokeObjectURL(image.src);
  546. }
  547. var blobToImage$1 = function (blob) {
  548. return blobToImage(blob);
  549. };
  550. var imageToBlob$1 = function (image) {
  551. return imageToBlob(image);
  552. };
  553. function create$1(getCanvas, blob, uri) {
  554. var initialType = blob.type;
  555. var getType = constant(initialType);
  556. function toBlob() {
  557. return Promise.resolve(blob);
  558. }
  559. function toDataURL() {
  560. return uri;
  561. }
  562. function toBase64() {
  563. return uri.split(',')[1];
  564. }
  565. function toAdjustedBlob(type, quality) {
  566. return getCanvas.then(function (canvas) {
  567. return canvasToBlob(canvas, type, quality);
  568. });
  569. }
  570. function toAdjustedDataURL(type, quality) {
  571. return getCanvas.then(function (canvas) {
  572. return canvasToDataURL(canvas, type, quality);
  573. });
  574. }
  575. function toAdjustedBase64(type, quality) {
  576. return toAdjustedDataURL(type, quality).then(function (dataurl) {
  577. return dataurl.split(',')[1];
  578. });
  579. }
  580. function toCanvas() {
  581. return getCanvas.then(clone);
  582. }
  583. return {
  584. getType: getType,
  585. toBlob: toBlob,
  586. toDataURL: toDataURL,
  587. toBase64: toBase64,
  588. toAdjustedBlob: toAdjustedBlob,
  589. toAdjustedDataURL: toAdjustedDataURL,
  590. toAdjustedBase64: toAdjustedBase64,
  591. toCanvas: toCanvas
  592. };
  593. }
  594. function fromBlob(blob) {
  595. return blobToDataUri(blob).then(function (uri) {
  596. return create$1(blobToCanvas(blob), blob, uri);
  597. });
  598. }
  599. function fromCanvas(canvas, type) {
  600. return canvasToBlob(canvas, type).then(function (blob) {
  601. return create$1(Promise.resolve(canvas), blob, canvas.toDataURL());
  602. });
  603. }
  604. function fromImage(image) {
  605. return imageToBlob(image).then(function (blob) {
  606. return fromBlob(blob);
  607. });
  608. }
  609. var fromBlobAndUrlSync = function (blob, url) {
  610. return create$1(blobToCanvas(blob), blob, url);
  611. };
  612. var ImageResult = /*#__PURE__*/Object.freeze({
  613. fromBlob: fromBlob,
  614. fromCanvas: fromCanvas,
  615. fromImage: fromImage,
  616. fromBlobAndUrlSync: fromBlobAndUrlSync
  617. });
  618. function rotate(ir, angle) {
  619. return ir.toCanvas().then(function (canvas) {
  620. return applyRotate(canvas, ir.getType(), angle);
  621. });
  622. }
  623. function applyRotate(image, type, angle) {
  624. var canvas = create(image.width, image.height);
  625. var context = get2dContext(canvas);
  626. var translateX = 0;
  627. var translateY = 0;
  628. angle = angle < 0 ? 360 + angle : angle;
  629. if (angle === 90 || angle === 270) {
  630. resize(canvas, canvas.height, canvas.width);
  631. }
  632. if (angle === 90 || angle === 180) {
  633. translateX = canvas.width;
  634. }
  635. if (angle === 270 || angle === 180) {
  636. translateY = canvas.height;
  637. }
  638. context.translate(translateX, translateY);
  639. context.rotate(angle * Math.PI / 180);
  640. context.drawImage(image, 0, 0);
  641. return fromCanvas(canvas, type);
  642. }
  643. function flip(ir, axis) {
  644. return ir.toCanvas().then(function (canvas) {
  645. return applyFlip(canvas, ir.getType(), axis);
  646. });
  647. }
  648. function applyFlip(image, type, axis) {
  649. var canvas = create(image.width, image.height);
  650. var context = get2dContext(canvas);
  651. if (axis === 'v') {
  652. context.scale(1, -1);
  653. context.drawImage(image, 0, -canvas.height);
  654. } else {
  655. context.scale(-1, 1);
  656. context.drawImage(image, -canvas.width, 0);
  657. }
  658. return fromCanvas(canvas, type);
  659. }
  660. var flip$1 = function (ir, axis) {
  661. return flip(ir, axis);
  662. };
  663. var rotate$1 = function (ir, angle) {
  664. return rotate(ir, angle);
  665. };
  666. var blobToImageResult = function (blob) {
  667. return fromBlob(blob);
  668. };
  669. var url = function () {
  670. return Global$1.getOrDie('URL');
  671. };
  672. var createObjectURL = function (blob) {
  673. return url().createObjectURL(blob);
  674. };
  675. var revokeObjectURL = function (u) {
  676. url().revokeObjectURL(u);
  677. };
  678. var URL = {
  679. createObjectURL: createObjectURL,
  680. revokeObjectURL: revokeObjectURL
  681. };
  682. var global$2 = tinymce.util.Tools.resolve('tinymce.util.Delay');
  683. var global$3 = tinymce.util.Tools.resolve('tinymce.util.Promise');
  684. var global$4 = tinymce.util.Tools.resolve('tinymce.util.URI');
  685. var getToolbarItems = function (editor) {
  686. return editor.getParam('imagetools_toolbar', 'rotateleft rotateright flipv fliph editimage imageoptions');
  687. };
  688. var getProxyUrl = function (editor) {
  689. return editor.getParam('imagetools_proxy');
  690. };
  691. var getCorsHosts = function (editor) {
  692. return editor.getParam('imagetools_cors_hosts', [], 'string[]');
  693. };
  694. var getCredentialsHosts = function (editor) {
  695. return editor.getParam('imagetools_credentials_hosts', [], 'string[]');
  696. };
  697. var getFetchImage = function (editor) {
  698. return Option.from(editor.getParam('imagetools_fetch_image', null, 'function'));
  699. };
  700. var getApiKey = function (editor) {
  701. return editor.getParam('api_key', editor.getParam('imagetools_api_key', '', 'string'), 'string');
  702. };
  703. var getUploadTimeout = function (editor) {
  704. return editor.getParam('images_upload_timeout', 30000, 'number');
  705. };
  706. var shouldReuseFilename = function (editor) {
  707. return editor.getParam('images_reuse_filename', false, 'boolean');
  708. };
  709. function getImageSize(img) {
  710. var width, height;
  711. function isPxValue(value) {
  712. return /^[0-9\.]+px$/.test(value);
  713. }
  714. width = img.style.width;
  715. height = img.style.height;
  716. if (width || height) {
  717. if (isPxValue(width) && isPxValue(height)) {
  718. return {
  719. w: parseInt(width, 10),
  720. h: parseInt(height, 10)
  721. };
  722. }
  723. return null;
  724. }
  725. width = img.width;
  726. height = img.height;
  727. if (width && height) {
  728. return {
  729. w: parseInt(width, 10),
  730. h: parseInt(height, 10)
  731. };
  732. }
  733. return null;
  734. }
  735. function setImageSize(img, size) {
  736. var width, height;
  737. if (size) {
  738. width = img.style.width;
  739. height = img.style.height;
  740. if (width || height) {
  741. img.style.width = size.w + 'px';
  742. img.style.height = size.h + 'px';
  743. img.removeAttribute('data-mce-style');
  744. }
  745. width = img.width;
  746. height = img.height;
  747. if (width || height) {
  748. img.setAttribute('width', size.w);
  749. img.setAttribute('height', size.h);
  750. }
  751. }
  752. }
  753. function getNaturalImageSize(img) {
  754. return {
  755. w: img.naturalWidth,
  756. h: img.naturalHeight
  757. };
  758. }
  759. var ImageSize = {
  760. getImageSize: getImageSize,
  761. setImageSize: setImageSize,
  762. getNaturalImageSize: getNaturalImageSize
  763. };
  764. var typeOf = function (x) {
  765. if (x === null)
  766. return 'null';
  767. var t = typeof x;
  768. if (t === 'object' && Array.prototype.isPrototypeOf(x))
  769. return 'array';
  770. if (t === 'object' && String.prototype.isPrototypeOf(x))
  771. return 'string';
  772. return t;
  773. };
  774. var isType = function (type) {
  775. return function (value) {
  776. return typeOf(value) === type;
  777. };
  778. };
  779. var isFunction = isType('function');
  780. var slice = Array.prototype.slice;
  781. var find = function (xs, pred) {
  782. for (var i = 0, len = xs.length; i < len; i++) {
  783. var x = xs[i];
  784. if (pred(x, i, xs)) {
  785. return Option.some(x);
  786. }
  787. }
  788. return Option.none();
  789. };
  790. var from$1 = isFunction(Array.from) ? Array.from : function (x) {
  791. return slice.call(x);
  792. };
  793. function XMLHttpRequest () {
  794. var f = Global$1.getOrDie('XMLHttpRequest');
  795. return new f();
  796. }
  797. var isValue = function (obj) {
  798. return obj !== null && obj !== undefined;
  799. };
  800. var traverse = function (json, path) {
  801. var value;
  802. value = path.reduce(function (result, key) {
  803. return isValue(result) ? result[key] : undefined;
  804. }, json);
  805. return isValue(value) ? value : null;
  806. };
  807. var requestUrlAsBlob = function (url, headers, withCredentials) {
  808. return new global$3(function (resolve) {
  809. var xhr;
  810. xhr = XMLHttpRequest();
  811. xhr.onreadystatechange = function () {
  812. if (xhr.readyState === 4) {
  813. resolve({
  814. status: xhr.status,
  815. blob: this.response
  816. });
  817. }
  818. };
  819. xhr.open('GET', url, true);
  820. xhr.withCredentials = withCredentials;
  821. global$1.each(headers, function (value, key) {
  822. xhr.setRequestHeader(key, value);
  823. });
  824. xhr.responseType = 'blob';
  825. xhr.send();
  826. });
  827. };
  828. var readBlob = function (blob) {
  829. return new global$3(function (resolve) {
  830. var fr = FileReader();
  831. fr.onload = function (e) {
  832. var data = e.target;
  833. resolve(data.result);
  834. };
  835. fr.readAsText(blob);
  836. });
  837. };
  838. var parseJson = function (text) {
  839. var json;
  840. try {
  841. json = JSON.parse(text);
  842. } catch (ex) {
  843. }
  844. return json;
  845. };
  846. var Utils = {
  847. traverse: traverse,
  848. readBlob: readBlob,
  849. requestUrlAsBlob: requestUrlAsBlob,
  850. parseJson: parseJson
  851. };
  852. var friendlyHttpErrors = [
  853. {
  854. code: 404,
  855. message: 'Could not find Image Proxy'
  856. },
  857. {
  858. code: 403,
  859. message: 'Rejected request'
  860. },
  861. {
  862. code: 0,
  863. message: 'Incorrect Image Proxy URL'
  864. }
  865. ];
  866. var friendlyServiceErrors = [
  867. {
  868. type: 'key_missing',
  869. message: 'The request did not include an api key.'
  870. },
  871. {
  872. type: 'key_not_found',
  873. message: 'The provided api key could not be found.'
  874. },
  875. {
  876. type: 'domain_not_trusted',
  877. message: 'The api key is not valid for the request origins.'
  878. }
  879. ];
  880. var isServiceErrorCode = function (code) {
  881. return code === 400 || code === 403 || code === 500;
  882. };
  883. var getHttpErrorMsg = function (status) {
  884. var message = find(friendlyHttpErrors, function (error) {
  885. return status === error.code;
  886. }).fold(constant('Unknown ImageProxy error'), function (error) {
  887. return error.message;
  888. });
  889. return 'ImageProxy HTTP error: ' + message;
  890. };
  891. var handleHttpError = function (status) {
  892. var message = getHttpErrorMsg(status);
  893. return global$3.reject(message);
  894. };
  895. var getServiceErrorMsg = function (type) {
  896. return find(friendlyServiceErrors, function (error) {
  897. return error.type === type;
  898. }).fold(constant('Unknown service error'), function (error) {
  899. return error.message;
  900. });
  901. };
  902. var getServiceError = function (text) {
  903. var serviceError = Utils.parseJson(text);
  904. var errorType = Utils.traverse(serviceError, [
  905. 'error',
  906. 'type'
  907. ]);
  908. var errorMsg = errorType ? getServiceErrorMsg(errorType) : 'Invalid JSON in service error message';
  909. return 'ImageProxy Service error: ' + errorMsg;
  910. };
  911. var handleServiceError = function (status, blob) {
  912. return Utils.readBlob(blob).then(function (text) {
  913. var serviceError = getServiceError(text);
  914. return global$3.reject(serviceError);
  915. });
  916. };
  917. var handleServiceErrorResponse = function (status, blob) {
  918. return isServiceErrorCode(status) ? handleServiceError(status, blob) : handleHttpError(status);
  919. };
  920. var Errors = {
  921. handleServiceErrorResponse: handleServiceErrorResponse,
  922. handleHttpError: handleHttpError,
  923. getHttpErrorMsg: getHttpErrorMsg,
  924. getServiceErrorMsg: getServiceErrorMsg
  925. };
  926. var appendApiKey = function (url, apiKey) {
  927. var separator = url.indexOf('?') === -1 ? '?' : '&';
  928. if (/[?&]apiKey=/.test(url) || !apiKey) {
  929. return url;
  930. } else {
  931. return url + separator + 'apiKey=' + encodeURIComponent(apiKey);
  932. }
  933. };
  934. var requestServiceBlob = function (url, apiKey) {
  935. var headers = {
  936. 'Content-Type': 'application/json;charset=UTF-8',
  937. 'tiny-api-key': apiKey
  938. };
  939. return Utils.requestUrlAsBlob(appendApiKey(url, apiKey), headers, false).then(function (result) {
  940. return result.status < 200 || result.status >= 300 ? Errors.handleServiceErrorResponse(result.status, result.blob) : global$3.resolve(result.blob);
  941. });
  942. };
  943. function requestBlob(url, withCredentials) {
  944. return Utils.requestUrlAsBlob(url, {}, withCredentials).then(function (result) {
  945. return result.status < 200 || result.status >= 300 ? Errors.handleHttpError(result.status) : global$3.resolve(result.blob);
  946. });
  947. }
  948. var getUrl = function (url, apiKey, withCredentials) {
  949. return apiKey ? requestServiceBlob(url, apiKey) : requestBlob(url, withCredentials);
  950. };
  951. var node = function () {
  952. var f = Global$1.getOrDie('Node');
  953. return f;
  954. };
  955. var compareDocumentPosition = function (a, b, match) {
  956. return (a.compareDocumentPosition(b) & match) !== 0;
  957. };
  958. var documentPositionPreceding = function (a, b) {
  959. return compareDocumentPosition(a, b, node().DOCUMENT_POSITION_PRECEDING);
  960. };
  961. var documentPositionContainedBy = function (a, b) {
  962. return compareDocumentPosition(a, b, node().DOCUMENT_POSITION_CONTAINED_BY);
  963. };
  964. var Node = {
  965. documentPositionPreceding: documentPositionPreceding,
  966. documentPositionContainedBy: documentPositionContainedBy
  967. };
  968. var cached = function (f) {
  969. var called = false;
  970. var r;
  971. return function () {
  972. var args = [];
  973. for (var _i = 0; _i < arguments.length; _i++) {
  974. args[_i] = arguments[_i];
  975. }
  976. if (!called) {
  977. called = true;
  978. r = f.apply(null, args);
  979. }
  980. return r;
  981. };
  982. };
  983. var firstMatch = function (regexes, s) {
  984. for (var i = 0; i < regexes.length; i++) {
  985. var x = regexes[i];
  986. if (x.test(s))
  987. return x;
  988. }
  989. return undefined;
  990. };
  991. var find$1 = function (regexes, agent) {
  992. var r = firstMatch(regexes, agent);
  993. if (!r)
  994. return {
  995. major: 0,
  996. minor: 0
  997. };
  998. var group = function (i) {
  999. return Number(agent.replace(r, '$' + i));
  1000. };
  1001. return nu(group(1), group(2));
  1002. };
  1003. var detect = function (versionRegexes, agent) {
  1004. var cleanedAgent = String(agent).toLowerCase();
  1005. if (versionRegexes.length === 0)
  1006. return unknown();
  1007. return find$1(versionRegexes, cleanedAgent);
  1008. };
  1009. var unknown = function () {
  1010. return nu(0, 0);
  1011. };
  1012. var nu = function (major, minor) {
  1013. return {
  1014. major: major,
  1015. minor: minor
  1016. };
  1017. };
  1018. var Version = {
  1019. nu: nu,
  1020. detect: detect,
  1021. unknown: unknown
  1022. };
  1023. var edge = 'Edge';
  1024. var chrome = 'Chrome';
  1025. var ie = 'IE';
  1026. var opera = 'Opera';
  1027. var firefox = 'Firefox';
  1028. var safari = 'Safari';
  1029. var isBrowser = function (name, current) {
  1030. return function () {
  1031. return current === name;
  1032. };
  1033. };
  1034. var unknown$1 = function () {
  1035. return nu$1({
  1036. current: undefined,
  1037. version: Version.unknown()
  1038. });
  1039. };
  1040. var nu$1 = function (info) {
  1041. var current = info.current;
  1042. var version = info.version;
  1043. return {
  1044. current: current,
  1045. version: version,
  1046. isEdge: isBrowser(edge, current),
  1047. isChrome: isBrowser(chrome, current),
  1048. isIE: isBrowser(ie, current),
  1049. isOpera: isBrowser(opera, current),
  1050. isFirefox: isBrowser(firefox, current),
  1051. isSafari: isBrowser(safari, current)
  1052. };
  1053. };
  1054. var Browser = {
  1055. unknown: unknown$1,
  1056. nu: nu$1,
  1057. edge: constant(edge),
  1058. chrome: constant(chrome),
  1059. ie: constant(ie),
  1060. opera: constant(opera),
  1061. firefox: constant(firefox),
  1062. safari: constant(safari)
  1063. };
  1064. var windows = 'Windows';
  1065. var ios = 'iOS';
  1066. var android = 'Android';
  1067. var linux = 'Linux';
  1068. var osx = 'OSX';
  1069. var solaris = 'Solaris';
  1070. var freebsd = 'FreeBSD';
  1071. var isOS = function (name, current) {
  1072. return function () {
  1073. return current === name;
  1074. };
  1075. };
  1076. var unknown$2 = function () {
  1077. return nu$2({
  1078. current: undefined,
  1079. version: Version.unknown()
  1080. });
  1081. };
  1082. var nu$2 = function (info) {
  1083. var current = info.current;
  1084. var version = info.version;
  1085. return {
  1086. current: current,
  1087. version: version,
  1088. isWindows: isOS(windows, current),
  1089. isiOS: isOS(ios, current),
  1090. isAndroid: isOS(android, current),
  1091. isOSX: isOS(osx, current),
  1092. isLinux: isOS(linux, current),
  1093. isSolaris: isOS(solaris, current),
  1094. isFreeBSD: isOS(freebsd, current)
  1095. };
  1096. };
  1097. var OperatingSystem = {
  1098. unknown: unknown$2,
  1099. nu: nu$2,
  1100. windows: constant(windows),
  1101. ios: constant(ios),
  1102. android: constant(android),
  1103. linux: constant(linux),
  1104. osx: constant(osx),
  1105. solaris: constant(solaris),
  1106. freebsd: constant(freebsd)
  1107. };
  1108. var DeviceType = function (os, browser, userAgent) {
  1109. var isiPad = os.isiOS() && /ipad/i.test(userAgent) === true;
  1110. var isiPhone = os.isiOS() && !isiPad;
  1111. var isAndroid3 = os.isAndroid() && os.version.major === 3;
  1112. var isAndroid4 = os.isAndroid() && os.version.major === 4;
  1113. var isTablet = isiPad || isAndroid3 || isAndroid4 && /mobile/i.test(userAgent) === true;
  1114. var isTouch = os.isiOS() || os.isAndroid();
  1115. var isPhone = isTouch && !isTablet;
  1116. var iOSwebview = browser.isSafari() && os.isiOS() && /safari/i.test(userAgent) === false;
  1117. return {
  1118. isiPad: constant(isiPad),
  1119. isiPhone: constant(isiPhone),
  1120. isTablet: constant(isTablet),
  1121. isPhone: constant(isPhone),
  1122. isTouch: constant(isTouch),
  1123. isAndroid: os.isAndroid,
  1124. isiOS: os.isiOS,
  1125. isWebView: constant(iOSwebview)
  1126. };
  1127. };
  1128. var detect$1 = function (candidates, userAgent) {
  1129. var agent = String(userAgent).toLowerCase();
  1130. return find(candidates, function (candidate) {
  1131. return candidate.search(agent);
  1132. });
  1133. };
  1134. var detectBrowser = function (browsers, userAgent) {
  1135. return detect$1(browsers, userAgent).map(function (browser) {
  1136. var version = Version.detect(browser.versionRegexes, userAgent);
  1137. return {
  1138. current: browser.name,
  1139. version: version
  1140. };
  1141. });
  1142. };
  1143. var detectOs = function (oses, userAgent) {
  1144. return detect$1(oses, userAgent).map(function (os) {
  1145. var version = Version.detect(os.versionRegexes, userAgent);
  1146. return {
  1147. current: os.name,
  1148. version: version
  1149. };
  1150. });
  1151. };
  1152. var UaString = {
  1153. detectBrowser: detectBrowser,
  1154. detectOs: detectOs
  1155. };
  1156. var contains = function (str, substr) {
  1157. return str.indexOf(substr) !== -1;
  1158. };
  1159. var normalVersionRegex = /.*?version\/\ ?([0-9]+)\.([0-9]+).*/;
  1160. var checkContains = function (target) {
  1161. return function (uastring) {
  1162. return contains(uastring, target);
  1163. };
  1164. };
  1165. var browsers = [
  1166. {
  1167. name: 'Edge',
  1168. versionRegexes: [/.*?edge\/ ?([0-9]+)\.([0-9]+)$/],
  1169. search: function (uastring) {
  1170. var monstrosity = contains(uastring, 'edge/') && contains(uastring, 'chrome') && contains(uastring, 'safari') && contains(uastring, 'applewebkit');
  1171. return monstrosity;
  1172. }
  1173. },
  1174. {
  1175. name: 'Chrome',
  1176. versionRegexes: [
  1177. /.*?chrome\/([0-9]+)\.([0-9]+).*/,
  1178. normalVersionRegex
  1179. ],
  1180. search: function (uastring) {
  1181. return contains(uastring, 'chrome') && !contains(uastring, 'chromeframe');
  1182. }
  1183. },
  1184. {
  1185. name: 'IE',
  1186. versionRegexes: [
  1187. /.*?msie\ ?([0-9]+)\.([0-9]+).*/,
  1188. /.*?rv:([0-9]+)\.([0-9]+).*/
  1189. ],
  1190. search: function (uastring) {
  1191. return contains(uastring, 'msie') || contains(uastring, 'trident');
  1192. }
  1193. },
  1194. {
  1195. name: 'Opera',
  1196. versionRegexes: [
  1197. normalVersionRegex,
  1198. /.*?opera\/([0-9]+)\.([0-9]+).*/
  1199. ],
  1200. search: checkContains('opera')
  1201. },
  1202. {
  1203. name: 'Firefox',
  1204. versionRegexes: [/.*?firefox\/\ ?([0-9]+)\.([0-9]+).*/],
  1205. search: checkContains('firefox')
  1206. },
  1207. {
  1208. name: 'Safari',
  1209. versionRegexes: [
  1210. normalVersionRegex,
  1211. /.*?cpu os ([0-9]+)_([0-9]+).*/
  1212. ],
  1213. search: function (uastring) {
  1214. return (contains(uastring, 'safari') || contains(uastring, 'mobile/')) && contains(uastring, 'applewebkit');
  1215. }
  1216. }
  1217. ];
  1218. var oses = [
  1219. {
  1220. name: 'Windows',
  1221. search: checkContains('win'),
  1222. versionRegexes: [/.*?windows\ nt\ ?([0-9]+)\.([0-9]+).*/]
  1223. },
  1224. {
  1225. name: 'iOS',
  1226. search: function (uastring) {
  1227. return contains(uastring, 'iphone') || contains(uastring, 'ipad');
  1228. },
  1229. versionRegexes: [
  1230. /.*?version\/\ ?([0-9]+)\.([0-9]+).*/,
  1231. /.*cpu os ([0-9]+)_([0-9]+).*/,
  1232. /.*cpu iphone os ([0-9]+)_([0-9]+).*/
  1233. ]
  1234. },
  1235. {
  1236. name: 'Android',
  1237. search: checkContains('android'),
  1238. versionRegexes: [/.*?android\ ?([0-9]+)\.([0-9]+).*/]
  1239. },
  1240. {
  1241. name: 'OSX',
  1242. search: checkContains('os x'),
  1243. versionRegexes: [/.*?os\ x\ ?([0-9]+)_([0-9]+).*/]
  1244. },
  1245. {
  1246. name: 'Linux',
  1247. search: checkContains('linux'),
  1248. versionRegexes: []
  1249. },
  1250. {
  1251. name: 'Solaris',
  1252. search: checkContains('sunos'),
  1253. versionRegexes: []
  1254. },
  1255. {
  1256. name: 'FreeBSD',
  1257. search: checkContains('freebsd'),
  1258. versionRegexes: []
  1259. }
  1260. ];
  1261. var PlatformInfo = {
  1262. browsers: constant(browsers),
  1263. oses: constant(oses)
  1264. };
  1265. var detect$2 = function (userAgent) {
  1266. var browsers = PlatformInfo.browsers();
  1267. var oses = PlatformInfo.oses();
  1268. var browser = UaString.detectBrowser(browsers, userAgent).fold(Browser.unknown, Browser.nu);
  1269. var os = UaString.detectOs(oses, userAgent).fold(OperatingSystem.unknown, OperatingSystem.nu);
  1270. var deviceType = DeviceType(os, browser, userAgent);
  1271. return {
  1272. browser: browser,
  1273. os: os,
  1274. deviceType: deviceType
  1275. };
  1276. };
  1277. var PlatformDetection = { detect: detect$2 };
  1278. var detect$3 = cached(function () {
  1279. var userAgent = domGlobals.navigator.userAgent;
  1280. return PlatformDetection.detect(userAgent);
  1281. });
  1282. var PlatformDetection$1 = { detect: detect$3 };
  1283. var fromHtml = function (html, scope) {
  1284. var doc = scope || domGlobals.document;
  1285. var div = doc.createElement('div');
  1286. div.innerHTML = html;
  1287. if (!div.hasChildNodes() || div.childNodes.length > 1) {
  1288. domGlobals.console.error('HTML does not have a single root node', html);
  1289. throw new Error('HTML must have a single root node');
  1290. }
  1291. return fromDom(div.childNodes[0]);
  1292. };
  1293. var fromTag = function (tag, scope) {
  1294. var doc = scope || domGlobals.document;
  1295. var node = doc.createElement(tag);
  1296. return fromDom(node);
  1297. };
  1298. var fromText = function (text, scope) {
  1299. var doc = scope || domGlobals.document;
  1300. var node = doc.createTextNode(text);
  1301. return fromDom(node);
  1302. };
  1303. var fromDom = function (node) {
  1304. if (node === null || node === undefined) {
  1305. throw new Error('Node cannot be null or undefined');
  1306. }
  1307. return { dom: constant(node) };
  1308. };
  1309. var fromPoint = function (docElm, x, y) {
  1310. var doc = docElm.dom();
  1311. return Option.from(doc.elementFromPoint(x, y)).map(fromDom);
  1312. };
  1313. var Element = {
  1314. fromHtml: fromHtml,
  1315. fromTag: fromTag,
  1316. fromText: fromText,
  1317. fromDom: fromDom,
  1318. fromPoint: fromPoint
  1319. };
  1320. var ATTRIBUTE = domGlobals.Node.ATTRIBUTE_NODE;
  1321. var CDATA_SECTION = domGlobals.Node.CDATA_SECTION_NODE;
  1322. var COMMENT = domGlobals.Node.COMMENT_NODE;
  1323. var DOCUMENT = domGlobals.Node.DOCUMENT_NODE;
  1324. var DOCUMENT_TYPE = domGlobals.Node.DOCUMENT_TYPE_NODE;
  1325. var DOCUMENT_FRAGMENT = domGlobals.Node.DOCUMENT_FRAGMENT_NODE;
  1326. var ELEMENT = domGlobals.Node.ELEMENT_NODE;
  1327. var TEXT = domGlobals.Node.TEXT_NODE;
  1328. var PROCESSING_INSTRUCTION = domGlobals.Node.PROCESSING_INSTRUCTION_NODE;
  1329. var ENTITY_REFERENCE = domGlobals.Node.ENTITY_REFERENCE_NODE;
  1330. var ENTITY = domGlobals.Node.ENTITY_NODE;
  1331. var NOTATION = domGlobals.Node.NOTATION_NODE;
  1332. var ELEMENT$1 = ELEMENT;
  1333. var is = function (element, selector) {
  1334. var elem = element.dom();
  1335. if (elem.nodeType !== ELEMENT$1) {
  1336. return false;
  1337. } else if (elem.matches !== undefined) {
  1338. return elem.matches(selector);
  1339. } else if (elem.msMatchesSelector !== undefined) {
  1340. return elem.msMatchesSelector(selector);
  1341. } else if (elem.webkitMatchesSelector !== undefined) {
  1342. return elem.webkitMatchesSelector(selector);
  1343. } else if (elem.mozMatchesSelector !== undefined) {
  1344. return elem.mozMatchesSelector(selector);
  1345. } else {
  1346. throw new Error('Browser lacks native selectors');
  1347. }
  1348. };
  1349. var regularContains = function (e1, e2) {
  1350. var d1 = e1.dom();
  1351. var d2 = e2.dom();
  1352. return d1 === d2 ? false : d1.contains(d2);
  1353. };
  1354. var ieContains = function (e1, e2) {
  1355. return Node.documentPositionContainedBy(e1.dom(), e2.dom());
  1356. };
  1357. var browser = PlatformDetection$1.detect().browser;
  1358. var contains$1 = browser.isIE() ? ieContains : regularContains;
  1359. var child = function (scope, predicate) {
  1360. var result = find(scope.dom().childNodes, compose(predicate, Element.fromDom));
  1361. return result.map(Element.fromDom);
  1362. };
  1363. var child$1 = function (scope, selector) {
  1364. return child(scope, function (e) {
  1365. return is(e, selector);
  1366. });
  1367. };
  1368. var count = 0;
  1369. var getFigureImg = function (elem) {
  1370. return child$1(Element.fromDom(elem), 'img');
  1371. };
  1372. var isFigure = function (editor, elem) {
  1373. return editor.dom.is(elem, 'figure');
  1374. };
  1375. var getEditableImage = function (editor, elem) {
  1376. var isImage = function (imgNode) {
  1377. return editor.dom.is(imgNode, 'img:not([data-mce-object],[data-mce-placeholder])');
  1378. };
  1379. var isEditable = function (imgNode) {
  1380. return isImage(imgNode) && (isLocalImage(editor, imgNode) || isCorsImage(editor, imgNode) || editor.settings.imagetools_proxy);
  1381. };
  1382. if (isFigure(editor, elem)) {
  1383. var imgOpt = getFigureImg(elem);
  1384. return imgOpt.map(function (img) {
  1385. return isEditable(img.dom()) ? Option.some(img.dom()) : Option.none();
  1386. });
  1387. }
  1388. return isEditable(elem) ? Option.some(elem) : Option.none();
  1389. };
  1390. var displayError = function (editor, error) {
  1391. editor.notificationManager.open({
  1392. text: error,
  1393. type: 'error'
  1394. });
  1395. };
  1396. var getSelectedImage = function (editor) {
  1397. var elem = editor.selection.getNode();
  1398. if (isFigure(editor, elem)) {
  1399. return getFigureImg(elem);
  1400. } else {
  1401. return Option.some(Element.fromDom(elem));
  1402. }
  1403. };
  1404. var extractFilename = function (editor, url) {
  1405. var m = url.match(/\/([^\/\?]+)?\.(?:jpeg|jpg|png|gif)(?:\?|$)/i);
  1406. if (m) {
  1407. return editor.dom.encode(m[1]);
  1408. }
  1409. return null;
  1410. };
  1411. var createId = function () {
  1412. return 'imagetools' + count++;
  1413. };
  1414. var isLocalImage = function (editor, img) {
  1415. var url = img.src;
  1416. return url.indexOf('data:') === 0 || url.indexOf('blob:') === 0 || new global$4(url).host === editor.documentBaseURI.host;
  1417. };
  1418. var isCorsImage = function (editor, img) {
  1419. return global$1.inArray(getCorsHosts(editor), new global$4(img.src).host) !== -1;
  1420. };
  1421. var isCorsWithCredentialsImage = function (editor, img) {
  1422. return global$1.inArray(getCredentialsHosts(editor), new global$4(img.src).host) !== -1;
  1423. };
  1424. var defaultFetchImage = function (editor, img) {
  1425. var src = img.src, apiKey;
  1426. if (isCorsImage(editor, img)) {
  1427. return getUrl(img.src, null, isCorsWithCredentialsImage(editor, img));
  1428. }
  1429. if (!isLocalImage(editor, img)) {
  1430. src = getProxyUrl(editor);
  1431. src += (src.indexOf('?') === -1 ? '?' : '&') + 'url=' + encodeURIComponent(img.src);
  1432. apiKey = getApiKey(editor);
  1433. return getUrl(src, apiKey, false);
  1434. }
  1435. return imageToBlob$1(img);
  1436. };
  1437. var imageToBlob$2 = function (editor, img) {
  1438. return getFetchImage(editor).fold(function () {
  1439. return defaultFetchImage(editor, img);
  1440. }, function (customFetchImage) {
  1441. return customFetchImage(img);
  1442. });
  1443. };
  1444. var findBlob = function (editor, img) {
  1445. var blobInfo;
  1446. blobInfo = editor.editorUpload.blobCache.getByUri(img.src);
  1447. if (blobInfo) {
  1448. return global$3.resolve(blobInfo.blob());
  1449. }
  1450. return imageToBlob$2(editor, img);
  1451. };
  1452. var startTimedUpload = function (editor, imageUploadTimerState) {
  1453. var imageUploadTimer = global$2.setEditorTimeout(editor, function () {
  1454. editor.editorUpload.uploadImagesAuto();
  1455. }, getUploadTimeout(editor));
  1456. imageUploadTimerState.set(imageUploadTimer);
  1457. };
  1458. var cancelTimedUpload = function (imageUploadTimerState) {
  1459. global$2.clearTimeout(imageUploadTimerState.get());
  1460. };
  1461. var updateSelectedImage = function (editor, ir, uploadImmediately, imageUploadTimerState, selectedImage, size) {
  1462. return ir.toBlob().then(function (blob) {
  1463. var uri, name, blobCache, blobInfo;
  1464. blobCache = editor.editorUpload.blobCache;
  1465. uri = selectedImage.src;
  1466. if (shouldReuseFilename(editor)) {
  1467. blobInfo = blobCache.getByUri(uri);
  1468. if (blobInfo) {
  1469. uri = blobInfo.uri();
  1470. name = blobInfo.name();
  1471. } else {
  1472. name = extractFilename(editor, uri);
  1473. }
  1474. }
  1475. blobInfo = blobCache.create({
  1476. id: createId(),
  1477. blob: blob,
  1478. base64: ir.toBase64(),
  1479. uri: uri,
  1480. name: name
  1481. });
  1482. blobCache.add(blobInfo);
  1483. editor.undoManager.transact(function () {
  1484. function imageLoadedHandler() {
  1485. editor.$(selectedImage).off('load', imageLoadedHandler);
  1486. editor.nodeChanged();
  1487. if (uploadImmediately) {
  1488. editor.editorUpload.uploadImagesAuto();
  1489. } else {
  1490. cancelTimedUpload(imageUploadTimerState);
  1491. startTimedUpload(editor, imageUploadTimerState);
  1492. }
  1493. }
  1494. editor.$(selectedImage).on('load', imageLoadedHandler);
  1495. if (size) {
  1496. editor.$(selectedImage).attr({
  1497. width: size.w,
  1498. height: size.h
  1499. });
  1500. }
  1501. editor.$(selectedImage).attr({ src: blobInfo.blobUri() }).removeAttr('data-mce-src');
  1502. });
  1503. return blobInfo;
  1504. });
  1505. };
  1506. var selectedImageOperation = function (editor, imageUploadTimerState, fn, size) {
  1507. return function () {
  1508. var imgOpt = getSelectedImage(editor);
  1509. return imgOpt.fold(function () {
  1510. displayError(editor, 'Could not find selected image');
  1511. }, function (img) {
  1512. return editor._scanForImages().then(function () {
  1513. return findBlob(editor, img.dom());
  1514. }).then(blobToImageResult).then(fn).then(function (imageResult) {
  1515. return updateSelectedImage(editor, imageResult, false, imageUploadTimerState, img.dom(), size);
  1516. }, function (error) {
  1517. displayError(editor, error);
  1518. });
  1519. });
  1520. };
  1521. };
  1522. var rotate$2 = function (editor, imageUploadTimerState, angle) {
  1523. return function () {
  1524. var imgOpt = getSelectedImage(editor);
  1525. var flippedSize = imgOpt.fold(function () {
  1526. return null;
  1527. }, function (img) {
  1528. var size = ImageSize.getImageSize(img.dom());
  1529. return size ? {
  1530. w: size.h,
  1531. h: size.w
  1532. } : null;
  1533. });
  1534. return selectedImageOperation(editor, imageUploadTimerState, function (imageResult) {
  1535. return rotate$1(imageResult, angle);
  1536. }, flippedSize)();
  1537. };
  1538. };
  1539. var flip$2 = function (editor, imageUploadTimerState, axis) {
  1540. return function () {
  1541. return selectedImageOperation(editor, imageUploadTimerState, function (imageResult) {
  1542. return flip$1(imageResult, axis);
  1543. })();
  1544. };
  1545. };
  1546. var handleDialogBlob = function (editor, imageUploadTimerState, img, originalSize, blob) {
  1547. return new global$3(function (resolve) {
  1548. blobToImage$1(blob).then(function (newImage) {
  1549. var newSize = ImageSize.getNaturalImageSize(newImage);
  1550. if (originalSize.w !== newSize.w || originalSize.h !== newSize.h) {
  1551. if (ImageSize.getImageSize(img)) {
  1552. ImageSize.setImageSize(img, newSize);
  1553. }
  1554. }
  1555. URL.revokeObjectURL(newImage.src);
  1556. return blob;
  1557. }).then(blobToImageResult).then(function (imageResult) {
  1558. return updateSelectedImage(editor, imageResult, true, imageUploadTimerState, img);
  1559. }, function () {
  1560. });
  1561. });
  1562. };
  1563. var Actions = {
  1564. rotate: rotate$2,
  1565. flip: flip$2,
  1566. getEditableImage: getEditableImage,
  1567. cancelTimedUpload: cancelTimedUpload,
  1568. findBlob: findBlob,
  1569. getSelectedImage: getSelectedImage,
  1570. handleDialogBlob: handleDialogBlob
  1571. };
  1572. var saveState = constant('save-state');
  1573. var disable = constant('disable');
  1574. var enable = constant('enable');
  1575. var createState = function (blob) {
  1576. return {
  1577. blob: blob,
  1578. url: URL.createObjectURL(blob)
  1579. };
  1580. };
  1581. var makeOpen = function (editor, imageUploadTimerState) {
  1582. return function () {
  1583. var getLoadedSpec = function (currentState) {
  1584. return {
  1585. title: 'Edit Image',
  1586. size: 'large',
  1587. body: {
  1588. type: 'panel',
  1589. items: [{
  1590. type: 'imagetools',
  1591. name: 'imagetools',
  1592. label: 'Edit Image',
  1593. currentState: currentState
  1594. }]
  1595. },
  1596. buttons: [
  1597. {
  1598. type: 'cancel',
  1599. name: 'cancel',
  1600. text: 'Cancel'
  1601. },
  1602. {
  1603. type: 'submit',
  1604. name: 'save',
  1605. text: 'Save',
  1606. primary: true,
  1607. disabled: true
  1608. }
  1609. ],
  1610. onSubmit: function (api) {
  1611. var blob = api.getData().imagetools.blob;
  1612. originalImgOpt.each(function (originalImg) {
  1613. originalSizeOpt.each(function (originalSize) {
  1614. Actions.handleDialogBlob(editor, imageUploadTimerState, originalImg.dom(), originalSize, blob);
  1615. });
  1616. });
  1617. api.close();
  1618. },
  1619. onCancel: function () {
  1620. },
  1621. onAction: function (api, details) {
  1622. switch (details.name) {
  1623. case saveState():
  1624. if (details.value) {
  1625. api.enable('save');
  1626. } else {
  1627. api.disable('save');
  1628. }
  1629. break;
  1630. case disable():
  1631. api.disable('save');
  1632. api.disable('cancel');
  1633. break;
  1634. case enable():
  1635. api.enable('cancel');
  1636. break;
  1637. }
  1638. }
  1639. };
  1640. };
  1641. var originalImgOpt = Actions.getSelectedImage(editor);
  1642. var originalSizeOpt = originalImgOpt.map(function (origImg) {
  1643. return ImageSize.getNaturalImageSize(origImg.dom());
  1644. });
  1645. var imgOpt = Actions.getSelectedImage(editor);
  1646. imgOpt.each(function (img) {
  1647. Actions.getEditableImage(editor, img.dom()).each(function (_) {
  1648. Actions.findBlob(editor, img.dom()).then(function (blob) {
  1649. var state = createState(blob);
  1650. editor.windowManager.open(getLoadedSpec(state));
  1651. });
  1652. });
  1653. });
  1654. };
  1655. };
  1656. var Dialog = { makeOpen: makeOpen };
  1657. var register = function (editor, imageUploadTimerState) {
  1658. global$1.each({
  1659. mceImageRotateLeft: Actions.rotate(editor, imageUploadTimerState, -90),
  1660. mceImageRotateRight: Actions.rotate(editor, imageUploadTimerState, 90),
  1661. mceImageFlipVertical: Actions.flip(editor, imageUploadTimerState, 'v'),
  1662. mceImageFlipHorizontal: Actions.flip(editor, imageUploadTimerState, 'h'),
  1663. mceEditImage: Dialog.makeOpen(editor, imageUploadTimerState)
  1664. }, function (fn, cmd) {
  1665. editor.addCommand(cmd, fn);
  1666. });
  1667. };
  1668. var Commands = { register: register };
  1669. var setup = function (editor, imageUploadTimerState, lastSelectedImageState) {
  1670. editor.on('NodeChange', function (e) {
  1671. var lastSelectedImage = lastSelectedImageState.get();
  1672. if (lastSelectedImage && lastSelectedImage.src !== e.element.src) {
  1673. Actions.cancelTimedUpload(imageUploadTimerState);
  1674. editor.editorUpload.uploadImagesAuto();
  1675. lastSelectedImageState.set(null);
  1676. }
  1677. Actions.getEditableImage(editor, e.element).each(lastSelectedImageState.set);
  1678. });
  1679. };
  1680. var UploadSelectedImage = { setup: setup };
  1681. var register$1 = function (editor) {
  1682. var cmd = function (command) {
  1683. return function () {
  1684. return editor.execCommand(command);
  1685. };
  1686. };
  1687. editor.ui.registry.addButton('rotateleft', {
  1688. tooltip: 'Rotate counterclockwise',
  1689. icon: 'rotate-left',
  1690. onAction: cmd('mceImageRotateLeft')
  1691. });
  1692. editor.ui.registry.addButton('rotateright', {
  1693. tooltip: 'Rotate clockwise',
  1694. icon: 'rotate-right',
  1695. onAction: cmd('mceImageRotateRight')
  1696. });
  1697. editor.ui.registry.addButton('flipv', {
  1698. tooltip: 'Flip vertically',
  1699. icon: 'flip-vertically',
  1700. onAction: cmd('mceImageFlipVertical')
  1701. });
  1702. editor.ui.registry.addButton('fliph', {
  1703. tooltip: 'Flip horizontally',
  1704. icon: 'flip-horizontally',
  1705. onAction: cmd('mceImageFlipHorizontal')
  1706. });
  1707. editor.ui.registry.addButton('editimage', {
  1708. tooltip: 'Edit image',
  1709. icon: 'edit-image',
  1710. onAction: cmd('mceEditImage'),
  1711. onSetup: function (buttonApi) {
  1712. var setDisabled = function () {
  1713. var elementOpt = Actions.getSelectedImage(editor);
  1714. elementOpt.each(function (element) {
  1715. var disabled = Actions.getEditableImage(editor, element.dom()).isNone();
  1716. buttonApi.setDisabled(disabled);
  1717. });
  1718. };
  1719. editor.on('NodeChange', setDisabled);
  1720. return function () {
  1721. editor.off('NodeChange', setDisabled);
  1722. };
  1723. }
  1724. });
  1725. editor.ui.registry.addButton('imageoptions', {
  1726. tooltip: 'Image options',
  1727. icon: 'image-options',
  1728. onAction: cmd('mceImage')
  1729. });
  1730. editor.ui.registry.addContextMenu('imagetools', {
  1731. update: function (element) {
  1732. return Actions.getEditableImage(editor, element).fold(function () {
  1733. return [];
  1734. }, function (_) {
  1735. return [{
  1736. text: 'Edit image',
  1737. icon: 'edit-image',
  1738. onAction: cmd('mceEditImage')
  1739. }];
  1740. });
  1741. }
  1742. });
  1743. };
  1744. var Buttons = { register: register$1 };
  1745. var register$2 = function (editor) {
  1746. editor.ui.registry.addContextToolbar('imagetools', {
  1747. items: getToolbarItems(editor),
  1748. predicate: function (elem) {
  1749. return Actions.getEditableImage(editor, elem).isSome();
  1750. },
  1751. position: 'node',
  1752. scope: 'node'
  1753. });
  1754. };
  1755. var ContextToolbar = { register: register$2 };
  1756. global.add('imagetools', function (editor) {
  1757. var imageUploadTimerState = Cell(0);
  1758. var lastSelectedImageState = Cell(null);
  1759. Commands.register(editor, imageUploadTimerState);
  1760. Buttons.register(editor);
  1761. ContextToolbar.register(editor);
  1762. UploadSelectedImage.setup(editor, imageUploadTimerState, lastSelectedImageState);
  1763. });
  1764. function Plugin () {
  1765. }
  1766. return Plugin;
  1767. }(window));
  1768. })();