contentScript.js 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949
  1. (function()
  2. {
  3. // Specifies if images should be changed for dark mode
  4. var convertImages = true;
  5. var backgroundColor = '#2F3437';
  6. var convertAttrib = 'data-drawio-src';
  7. var editor = 'https://embed.diagrams.net/?embedInline=1&libraries=1&configure=1';
  8. //editor = 'https://test.draw.io/?dev=1&embedInline=1&libraries=1&configure=1';
  9. var notionScrollers = document.getElementsByClassName('notion-scroller vertical');
  10. var notionFrames = document.getElementsByClassName('notion-frame');
  11. var dark = document.body.className.includes('dark');
  12. var initialized = false;
  13. var activeImage = null;
  14. var editBlockId = null;
  15. var iframe = document.createElement('iframe');
  16. iframe.style.position = 'absolute';
  17. iframe.style.border = '0';
  18. iframe.style.top = '0px';
  19. iframe.style.left = '0px';
  20. iframe.style.width = '100%';
  21. iframe.style.height = '100%';
  22. iframe.style.zIndex = '4';
  23. function invertImage(img, done)
  24. {
  25. var req = new XMLHttpRequest();
  26. req.addEventListener('load', function()
  27. {
  28. if (req.status >= 200 && req.status <= 299 && this.responseXML != null)
  29. {
  30. img.src = createSvgDataUri(invertSvg(this.responseXML));
  31. }
  32. done();
  33. });
  34. req.open('GET', img.src);
  35. req.send();
  36. };
  37. function installInverter(img)
  38. {
  39. var busy = false;
  40. img.setAttribute(convertAttrib, img.src);
  41. if (dark)
  42. {
  43. busy = true;
  44. invertImage(img, function()
  45. {
  46. busy = false;
  47. });
  48. }
  49. var mutationObserver = new MutationObserver(function(evt)
  50. {
  51. if (!isSvgDataUri(img.src) && img.src != '' && !busy)
  52. {
  53. if (dark)
  54. {
  55. busy = true;
  56. img.setAttribute(convertAttrib, img.src);
  57. invertImage(img, function()
  58. {
  59. busy = false;
  60. });
  61. }
  62. }
  63. });
  64. mutationObserver.observe(img, {attributes: true});
  65. };
  66. function darkModeChanged()
  67. {
  68. if (activeImage != null)
  69. {
  70. iframe.contentWindow.postMessage(JSON.stringify(
  71. {action: 'exit'}), '*');
  72. }
  73. var imgs = document.getElementsByTagName('img');
  74. for (var i = 0; i < imgs.length; i++)
  75. {
  76. var src = imgs[i].getAttribute(convertAttrib);
  77. if (src != null)
  78. {
  79. if (!isSvgDataUri(imgs[i].src))
  80. {
  81. src = imgs[i].src;
  82. imgs[i].src = '';
  83. imgs[i].src = src;
  84. }
  85. else
  86. {
  87. imgs[i].src = src;
  88. }
  89. }
  90. }
  91. };
  92. function editImage(img, isNew, onChange)
  93. {
  94. iframe.doResize = function(msg)
  95. {
  96. setFullscreen(msg.fullscreen);
  97. img.style.width = msg.rect.width + 'px';
  98. img.style.height = (msg.rect.height - 22) + 'px';
  99. };
  100. var prev = img.parentNode.style.cursor;
  101. img.parentNode.style.cursor = 'wait';
  102. iframe.style.cursor = 'wait';
  103. iframe.doInit = function(errorCode)
  104. {
  105. if (errorCode != null)
  106. {
  107. img.parentNode.style.cursor = prev;
  108. onChange({});
  109. alert('Error ' + errorCode + ': Cannot load editor');
  110. }
  111. else
  112. {
  113. setControlsVisible(img, false);
  114. crossfade(img, iframe);
  115. iframe.style.cursor = '';
  116. img.parentNode.style.cursor = prev;
  117. }
  118. };
  119. iframe.doUpdate = onChange;
  120. startEditor(img, isNew);
  121. };
  122. function startEditor(img, isNew)
  123. {
  124. var req = new XMLHttpRequest();
  125. req.addEventListener('load', function()
  126. {
  127. if (req.status >= 200 && req.status <= 299)
  128. {
  129. try
  130. {
  131. var rect = img.parentNode.getBoundingClientRect();
  132. var r = iframe.parentNode.getBoundingClientRect();
  133. if (rect.y < r.y + 66 || rect.y > iframe.parentNode.scrollTop + r.height)
  134. {
  135. img.scrollIntoView();
  136. iframe.parentNode.scrollTop -= 60
  137. rect = img.parentNode.getBoundingClientRect();
  138. }
  139. var border = 8;
  140. rect.x -= border + 3 + r.x;
  141. rect.y -= border + 3 - iframe.parentNode.scrollTop + r.y;
  142. rect.width += 2 * border + 2;
  143. rect.height = (isNew) ? Math.max(rect.height, 500) : rect.height + 2 * border + 2;
  144. iframe.contentWindow.postMessage(JSON.stringify(
  145. {action: 'load', xml: this.responseText, border: border,
  146. background: '#ffffff', rect: rect, dark: dark,
  147. viewport: getViewport()}), '*');
  148. updateFrame();
  149. }
  150. catch (e)
  151. {
  152. iframe.doInit(e.message);
  153. }
  154. }
  155. else
  156. {
  157. iframe.doInit(req.status);
  158. }
  159. });
  160. req.open('GET', img.src);
  161. req.send();
  162. };
  163. function installEditor(img, filename, url)
  164. {
  165. img.parentNode.addEventListener('click', function()
  166. {
  167. if (!initialized)
  168. {
  169. var prev = img.parentNode.style.cursor;
  170. img.parentNode.style.cursor = 'not-allowed';
  171. window.setTimeout(function()
  172. {
  173. img.parentNode.style.cursor = prev;
  174. }, 300);
  175. }
  176. else
  177. {
  178. prepareEditor(img, filename, url);
  179. }
  180. });
  181. };
  182. function editBlock(id)
  183. {
  184. editBlockId = id;
  185. };
  186. function mergeChanges(url)
  187. {
  188. var req = new XMLHttpRequest();
  189. req.addEventListener('load', function()
  190. {
  191. if (req.status >= 200 && req.status <= 299)
  192. {
  193. iframe.contentWindow.postMessage(JSON.stringify({action: 'merge',
  194. xml: this.responseText}), '*');
  195. }
  196. });
  197. req.open('GET', url);
  198. req.send();
  199. };
  200. var lastSnapshot = null;
  201. function prepareEditor(img, filename, url, isNew)
  202. {
  203. if (!iframe.busy)
  204. {
  205. var elt = document.activeElement;
  206. iframe.busy = true;
  207. activeImage = img;
  208. var width = img.style.width;
  209. var height = img.style.height;
  210. var boxSizing = img.style.boxSizing;
  211. // Listens for remote changes
  212. var mutationObserver = new MutationObserver(function(evt)
  213. {
  214. if (!isSvgDataUri(img.src) && url != img.src &&
  215. activeImage == img)
  216. {
  217. url = img.src;
  218. mergeChanges(url);
  219. }
  220. });
  221. mutationObserver.observe(img, {attributes: true});
  222. editImage(img, isNew, function(msg, override)
  223. {
  224. if (msg.data != null && msg.exit != null &&
  225. !msg.exit && !override)
  226. {
  227. lastSnapshot = msg;
  228. }
  229. else
  230. {
  231. var rect = iframe.getBoundingClientRect();
  232. mutationObserver.disconnect();
  233. setFullscreen(false);
  234. img.style.width = width;
  235. img.style.height = height;
  236. img.style.boxSizing = boxSizing;
  237. imageChanged(img, filename, msg.data);
  238. crossfade(iframe, img, function()
  239. {
  240. setControlsVisible(img, true);
  241. iframe.busy = false;
  242. lastSnapshot = null;
  243. activeImage = null;
  244. if (msg != null && msg.point != null)
  245. {
  246. var temp = document.elementFromPoint(rect.x + msg.point.x, rect.y + msg.point.y);
  247. if (temp != null && temp.click != null)
  248. {
  249. elt = temp;
  250. elt.click();
  251. }
  252. }
  253. elt.focus();
  254. });
  255. }
  256. });
  257. }
  258. };
  259. function imageChanged(img, filename, data)
  260. {
  261. if (data != null)
  262. {
  263. var svg = getSvg(data);
  264. replaceDiagram({blockId: getBlockId(img), filename: filename, data: svg}, function(msg)
  265. {
  266. if (msg.error != null)
  267. {
  268. alert('Error ' + msg.errStatus + ': Cannot update diagram');
  269. }
  270. });
  271. if (dark && convertImages)
  272. {
  273. data = createSvgDataUri(invertSvg(new DOMParser().
  274. parseFromString(svg, 'text/xml')));
  275. }
  276. // Restores state and shows preview
  277. img.setAttribute('src', data);
  278. }
  279. iframe.style.width = '100%';
  280. iframe.style.height = '100%';
  281. iframe.doUpdate = null;
  282. iframe.doResize = null;
  283. };
  284. window.addEventListener('message', function(evt)
  285. {
  286. if (evt, evt.source === iframe.contentWindow)
  287. {
  288. var msg = JSON.parse(evt.data);
  289. if (msg.event == 'init')
  290. {
  291. initialized = true;
  292. }
  293. else if (msg.event == 'configure')
  294. {
  295. iframe.contentWindow.postMessage(JSON.stringify({action: 'configure',
  296. config: {
  297. darkColor: backgroundColor,
  298. settingsName: 'notion'
  299. }
  300. }), '*');
  301. }
  302. else if (msg.event == 'load' && iframe.doInit != null)
  303. {
  304. iframe.doInit();
  305. }
  306. else if ((msg.event == 'export' || msg.event == 'exit') &&
  307. iframe.doUpdate != null)
  308. {
  309. iframe.doUpdate(msg);
  310. }
  311. else if (msg.event == 'resize' && iframe.doResize != null)
  312. {
  313. iframe.doResize(msg);
  314. }
  315. }
  316. });
  317. var checked = [];
  318. function updateChecked()
  319. {
  320. var temp = [];
  321. // Forgets old images
  322. for (var i = 0; i < checked.length; i++)
  323. {
  324. if (document.body.contains(checked[i]))
  325. {
  326. temp.push(checked[i]);
  327. }
  328. }
  329. return temp;
  330. };
  331. function checkDiagram(img)
  332. {
  333. var filename = getFilename(img.src);
  334. var result = false;
  335. if (filename.endsWith('.drawio.svg'))
  336. {
  337. installEditor(img, filename, img.src);
  338. if (convertImages)
  339. {
  340. installInverter(img);
  341. }
  342. if (editBlockId != null && getBlockId(img) == editBlockId)
  343. {
  344. editBlockId = null;
  345. prepareEditor(img, filename, img.src, true);
  346. }
  347. result = true;
  348. }
  349. return result;
  350. };
  351. function checkImage(img)
  352. {
  353. if (checked.indexOf(img) < 0)
  354. {
  355. checked.push(img);
  356. if (!checkDiagram(img))
  357. {
  358. var mutationObserver = new MutationObserver(function()
  359. {
  360. if (checkDiagram(img))
  361. {
  362. mutationObserver.disconnect();
  363. }
  364. });
  365. mutationObserver.observe(img, {attributes: true});
  366. }
  367. };
  368. };
  369. function scrollHandler()
  370. {
  371. if (iframe.style.visibility != 'hidden')
  372. {
  373. iframe.contentWindow.postMessage(JSON.stringify(
  374. {action: 'viewport', viewport: getViewport()}), '*');
  375. }
  376. };
  377. // Creates a snapshot in case ppl click off the diagram so that it
  378. // is removed from the DOM (eg, if they click on the background or
  379. // if they click in the navigation).
  380. iframe.addEventListener('mouseleave', function()
  381. {
  382. if (activeImage != null && iframe.contentWindow != null)
  383. {
  384. iframe.contentWindow.postMessage(JSON.stringify(
  385. {action: 'snapshot'}), '*');
  386. }
  387. }, true);
  388. function checkFrame()
  389. {
  390. // Checks if pending snapshot exists
  391. if (iframe.doUpdate != null && lastSnapshot != null &&
  392. !document.body.contains(iframe))
  393. {
  394. iframe.doUpdate(lastSnapshot, true);
  395. }
  396. // Checks if parent node was removed and reinserts editor
  397. // Adding to body would avoid this but doesn't allow
  398. // the iframe to be scrolled with the page content.
  399. // LATER: Can we use cloneNode to avoid this?
  400. if (notionScrollers.length > 0 &&
  401. !notionScrollers[notionScrollers.length - 1].contains(iframe))
  402. {
  403. if (iframe.parentNode != null)
  404. {
  405. iframe.parentNode.removeEventListener('scroll', scrollHandler);
  406. }
  407. initialized = false;
  408. iframe.busy = false;
  409. iframe.style.visibility = 'hidden';
  410. notionScrollers[notionScrollers.length - 1].appendChild(iframe);
  411. iframe.setAttribute('src', editor);
  412. iframe.parentNode.addEventListener('scroll', scrollHandler);
  413. }
  414. };
  415. function checkImages()
  416. {
  417. // Removes old images
  418. // LATER: Move to other listener with fewer invocations
  419. checked = updateChecked();
  420. var imgs = document.getElementsByTagName('img');
  421. for (var i = 0; i < imgs.length; i++)
  422. {
  423. checkImage(imgs[i]);
  424. }
  425. };
  426. function getViewport()
  427. {
  428. var viewport = iframe.parentNode.getBoundingClientRect();
  429. viewport.x = iframe.parentNode.scrollLeft;
  430. viewport.y = iframe.parentNode.scrollTop;
  431. return viewport;
  432. };
  433. function pageChanged()
  434. {
  435. checkFrame();
  436. checkImages();
  437. };
  438. function installDarkModeListener()
  439. {
  440. new MutationObserver(pageChanged).observe(
  441. document.body, {childList: true,
  442. subtree: true});
  443. new MutationObserver(function()
  444. {
  445. var newDark = document.body.className.includes('dark');
  446. if (newDark != dark)
  447. {
  448. dark = newDark;
  449. darkModeChanged();
  450. }
  451. }).observe(document.body, {attributes: true});
  452. }
  453. installDarkModeListener();
  454. window.addEventListener('resize', function()
  455. {
  456. if (iframe.style.visibility != 'hidden')
  457. {
  458. iframe.contentWindow.postMessage(JSON.stringify(
  459. {action: 'viewport', viewport: getViewport()}), '*');
  460. updateFrame();
  461. }
  462. });
  463. var fullscreen = false;
  464. var prevOverflow = null;
  465. function updateFrame()
  466. {
  467. if (fullscreen)
  468. {
  469. var r = notionFrames[0].getBoundingClientRect();
  470. prevOverflow = document.body.style.overflow;
  471. document.body.style.overflow = 'hidden';
  472. iframe.style.position = 'fixed';
  473. iframe.style.top = r.y + 'px';
  474. iframe.style.left = r.x + 'px';
  475. iframe.style.width = r.width + 'px';
  476. iframe.style.height = r.height + 'px';
  477. }
  478. else
  479. {
  480. document.body.style.overflow = prevOverflow;
  481. iframe.style.position = 'absolute';
  482. iframe.style.left = '0px';
  483. iframe.style.top = '0px';
  484. iframe.style.width = iframe.parentNode.clientWidth + 'px';
  485. iframe.style.height = iframe.parentNode.scrollHeight + 'px';
  486. }
  487. };
  488. function setFullscreen(value)
  489. {
  490. if (fullscreen != value)
  491. {
  492. fullscreen = value;
  493. updateFrame();
  494. }
  495. };
  496. function setControlsVisible(img, visible)
  497. {
  498. try
  499. {
  500. // Hides halo
  501. img.parentNode.parentNode.parentNode.parentNode.parentNode.
  502. nextSibling.style.visibility = 'hidden';
  503. iframe.parentNode.nextSibling.style.visibility =
  504. (visible) ? '' : 'hidden';
  505. }
  506. catch (e)
  507. {
  508. // ignore
  509. }
  510. };
  511. function invertSvg(doc)
  512. {
  513. var defs = doc.getElementsByTagName('defs');
  514. var style = doc.createElementNS('http://www.w3.org/2000/svg', 'style');
  515. style.appendChild(doc.createTextNode(
  516. '[stroke="rgb(0, 0, 0)"] {stroke: #f0f0f0}\n' +
  517. '[stroke="rgb(255, 255, 255)"] {stroke: ' + backgroundColor + '}\n' +
  518. '[fill="rgb(0, 0, 0)"] {fill: #f0f0f0}\n' +
  519. '[fill="rgb(255, 255, 255)"] {fill: ' + backgroundColor + '}\n' +
  520. 'g[fill="rgb(0, 0, 0)"] text {fill: #f0f0f0}\n' +
  521. 'div[data-drawio-colors*="color: rgb(0, 0, 0)"] div ' +
  522. '{color: #f0f0f0 !important;}\n' +
  523. 'div[data-drawio-colors*="background-color: rgb(255, 255, 255)"] div ' +
  524. '{background-color: ' + backgroundColor + ' !important;}' +
  525. 'div[data-drawio-colors*="border-color: rgb(0, 0, 0)"] div ' +
  526. '{border-color: #f0f0f0 !important;}' +
  527. 'div[data-drawio-colors*="background-color: rgb(255, 255, 255)"] ' +
  528. '{background-color: ' + backgroundColor + ' !important;}' +
  529. 'div[data-drawio-colors*="border-color: rgb(0, 0, 0)"] ' +
  530. '{border-color: #f0f0f0 !important;}' +
  531. // Invert old rgba output
  532. '[stroke="rgba(0, 0, 0, 1)"] {stroke: #f0f0f0}\n' +
  533. '[stroke="rgba(255, 255, 255, 1)"] {stroke: ' + backgroundColor + '}\n' +
  534. '[fill="rgba(0, 0, 0, 1)"] {fill: #f0f0f0}\n' +
  535. '[fill="rgba(255, 255, 255, 1)"] {fill: ' + backgroundColor + '}\n' +
  536. 'g[fill="rgba(0, 0, 0, 1)"] text {fill: #f0f0f0}\n' +
  537. 'div[data-drawio-colors*="color: rgba(0, 0, 0, 1)"] div ' +
  538. '{color: #f0f0f0 !important;}\n' +
  539. 'div[data-drawio-colors*="background-color: rgba(255, 255, 255, 1)"] div ' +
  540. '{background-color: ' + backgroundColor + ' !important;}' +
  541. 'div[data-drawio-colors*="border-color: rgba(0, 0, 0, 1)"] div ' +
  542. '{border-color: #f0f0f0 !important;}' +
  543. 'div[data-drawio-colors*="background-color: rgba(255, 255, 255, 1)"] ' +
  544. '{background-color: ' + backgroundColor + ' !important;}' +
  545. 'div[data-drawio-colors*="border-color: rgba(0, 0, 0, 1)"] ' +
  546. '{border-color: #f0f0f0 !important;}'));
  547. defs[0].appendChild(style);
  548. if (doc.documentElement.style.backgroundColor == 'rgb(255, 255, 255)')
  549. {
  550. doc.documentElement.style.backgroundColor = backgroundColor;
  551. var g = doc.getElementsByTagName('g');
  552. if (g != null && g.length > 0 && g[0].getAttribute('filter') == 'url(#dropShadow)')
  553. {
  554. g[0].removeAttribute('filter');
  555. }
  556. }
  557. return doc;
  558. };
  559. function isSvgDataUri(url)
  560. {
  561. return url.startsWith('data:image/svg+xml;base64,');
  562. };
  563. function createSvgDataUri(doc)
  564. {
  565. return 'data:image/svg+xml;base64,' +
  566. btoa(unescape(encodeURIComponent(
  567. new XMLSerializer().serializeToString(
  568. doc.documentElement))));
  569. };
  570. function getSvg(data)
  571. {
  572. return '<?xml version="1.0" encoding="UTF-8"?>\n' +
  573. '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">\n' +
  574. decodeURIComponent(escape(atob(data.substring(data.indexOf(',') + 1))));
  575. };
  576. function getFilename(url)
  577. {
  578. var tokens = url.split('?')[0].split('/');
  579. var filename = tokens[tokens.length - 1];
  580. if (filename.startsWith('https%3A%2F%2F'))
  581. {
  582. filename = getFilename(decodeURIComponent(filename));
  583. }
  584. return filename;
  585. };
  586. function getBlockId(node)
  587. {
  588. var blockId = null;
  589. while (blockId == null && node != null && node != document.body)
  590. {
  591. blockId = node.getAttribute('data-block-id');
  592. node = node.parentNode;
  593. }
  594. return blockId;
  595. };
  596. function crossfade(source, target, done)
  597. {
  598. target.style.visibility = '';
  599. window.setTimeout(function()
  600. {
  601. source.style.visibility = 'hidden';
  602. if (done != null)
  603. {
  604. done();
  605. }
  606. }, 50);
  607. };
  608. function extractId(url, isBlock)
  609. {
  610. if (isBlock)
  611. {
  612. url = url.split('#').pop();
  613. }
  614. let id = url.split('/').pop().split('&p=').pop().split('?p=').pop().split('?').shift().split('-').pop().split('&').shift();
  615. //Return the id in the form 12345678-1234-5678-1234-567812345678
  616. return id.substring(0,8) + '-' + id.substring(8, 12) + '-' + id.substring(12, 16) +
  617. '-' + id.substring(16, 20) + '-' + id.substring(20);
  618. };
  619. function uuidv4()
  620. {
  621. return ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, c =>
  622. (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
  623. );
  624. }
  625. function callNotionAPI(api, data, onsuccess, onerror, origMsg, absUrl, method, directData, mimeType, respAsTxt)
  626. {
  627. fetch(absUrl || ('https://www.notion.so/api/v3/' + api),
  628. { method: method || 'post',
  629. body: directData? data : JSON.stringify(data),
  630. headers: {'Content-Type': mimeType || 'application/json'}})
  631. .then(async res =>
  632. {
  633. try
  634. {
  635. if (res.ok)
  636. {
  637. onsuccess(respAsTxt? await res.text() : await res.json());
  638. }
  639. else
  640. {
  641. origMsg = origMsg || {};
  642. origMsg.error = true;
  643. origMsg.errStatus = res.status;
  644. onerror(origMsg);
  645. try
  646. {
  647. console.log(await res.json());
  648. }
  649. catch(e){}
  650. }
  651. }
  652. catch(e)
  653. {
  654. console.log(e);
  655. origMsg.error = true;
  656. onerror(origMsg);
  657. }
  658. })
  659. .catch((err) =>
  660. {
  661. console.log(err);
  662. origMsg.error = true;
  663. onerror(origMsg);
  664. });
  665. };
  666. function replaceDiagram(msg, sendResponse)
  667. {
  668. callNotionAPI('loadUserContent', {},
  669. function(data)
  670. {
  671. let userId = Object.keys(data.recordMap.notion_user)[0];
  672. let blockId = msg.blockId;
  673. //Upload the file
  674. callNotionAPI('getUploadFileUrl', {bucket: 'secure', name: msg.filename, contentType: 'image/svg+xml'},
  675. function(urls)
  676. {
  677. let ts = Date.now();
  678. let url = urls.url;
  679. const S3_URL_PREFIX = 'https://s3-us-west-2.amazonaws.com/secure.notion-static.com/';
  680. let fileId = url.substring(S3_URL_PREFIX.length).split('/')[0];
  681. callNotionAPI(null, msg.data, function()
  682. {
  683. //Update Image block with file info
  684. callNotionAPI('saveTransactions', {
  685. 'requestId': uuidv4(),
  686. 'transactions': [{
  687. 'id': uuidv4(),
  688. 'operations': [
  689. {'id': blockId, 'path': ['format', 'display_source'],
  690. 'args': url,
  691. 'command': 'set', 'table': 'block'
  692. },
  693. {
  694. 'args': {'last_edited_by_id': userId, 'last_edited_by_table': 'notion_user', 'last_edited_time': ts},
  695. 'command': 'update', 'id': blockId, 'path': [], 'table': 'block'
  696. },
  697. {'id': blockId, 'path': ['properties', 'source'],
  698. 'args': [[url]],
  699. 'command': 'set', 'table': 'block'
  700. },
  701. {
  702. 'args': {'last_edited_by_id': userId, 'last_edited_by_table': 'notion_user', 'last_edited_time': ts},
  703. 'command': 'update', 'id': blockId, 'path': [], 'table': 'block'
  704. },
  705. {'id': blockId, 'path': ['file_ids', 0],
  706. 'args': fileId,
  707. 'command': 'set', 'table': 'block'
  708. },
  709. {
  710. 'args': {'last_edited_by_id': userId, 'last_edited_by_table': 'notion_user', 'last_edited_time': ts},
  711. 'command': 'update', 'id': blockId, 'path': [], 'table': 'block'
  712. }
  713. ]
  714. }]
  715. },
  716. function()
  717. {
  718. msg.newUrl = url;
  719. sendResponse(msg);
  720. }, sendResponse, msg);
  721. }, sendResponse, msg, urls.signedPutUrl, 'put', true, 'image/svg+xml', true);
  722. }, sendResponse, msg);
  723. }, sendResponse, msg);
  724. };
  725. chrome.runtime.onMessage.addListener(function(msg, sender, sendResponse)
  726. {
  727. switch (msg.msg)
  728. {
  729. case 'insertDiagram':
  730. // Stops active editing
  731. if (activeImage != null)
  732. {
  733. iframe.contentWindow.postMessage(JSON.stringify(
  734. {action: 'exit'}), '*');
  735. }
  736. //Get user ID
  737. callNotionAPI('loadUserContent', {},
  738. function(data)
  739. {
  740. let userId = Object.keys(data.recordMap.notion_user)[0];
  741. let blockId = uuidv4();
  742. let pageId = msg.pageId || extractId(window.location.href);
  743. let ts = Date.now();
  744. //Add Image block
  745. callNotionAPI('saveTransactions', {
  746. 'requestId': uuidv4(),
  747. 'transactions': [{
  748. 'id': uuidv4(),
  749. 'operations': [
  750. {'id': blockId, 'path': [],
  751. 'args': {'id': blockId, 'version': 1, 'alive': true, 'created_by_id': userId, 'created_by_table': 'notion_user',
  752. 'created_time': ts, 'parent_id': pageId, 'parent_table': 'block', 'type': 'image', 'child_list_key': null},
  753. 'command': 'set', 'table': 'block'
  754. },
  755. {
  756. 'args': {'last_edited_by_id': userId, 'last_edited_by_table': 'notion_user', 'last_edited_time': ts},
  757. 'command': 'update', 'id': blockId, 'path': [], 'table': 'block'
  758. },
  759. {'id': pageId, 'path': ['content'],
  760. 'args': {'id': blockId},
  761. 'command': 'listAfter', 'table': 'block'
  762. },
  763. {
  764. 'args': {'last_edited_by_id': userId, 'last_edited_by_table': 'notion_user', 'last_edited_time': ts},
  765. 'command': 'update', 'id': pageId, 'path': [], 'table': 'block'
  766. },
  767. {
  768. 'args': {'last_edited_by_id': userId, 'last_edited_by_table': 'notion_user', 'last_edited_time': ts},
  769. 'command': 'update', 'id': pageId, 'path': [], 'table': 'block'
  770. },
  771. {
  772. 'args': {'last_edited_by_id': userId, 'last_edited_by_table': 'notion_user', 'last_edited_time': ts},
  773. 'command': 'update', 'id': blockId, 'path': [], 'table': 'block'
  774. }
  775. ]
  776. }]
  777. },
  778. function()
  779. {
  780. //Now, upload the file
  781. callNotionAPI('getUploadFileUrl', {bucket: 'secure', name: msg.filename, contentType: 'image/svg+xml'},
  782. function(urls)
  783. {
  784. ts = Date.now();
  785. let url = urls.url;
  786. const S3_URL_PREFIX = 'https://s3-us-west-2.amazonaws.com/secure.notion-static.com/';
  787. let fileId = url.substring(S3_URL_PREFIX.length).split('/')[0];
  788. callNotionAPI(null, msg.data, function()
  789. {
  790. //Update Image block with file info
  791. callNotionAPI('saveTransactions', {
  792. 'requestId': uuidv4(),
  793. 'transactions': [{
  794. 'id': uuidv4(),
  795. 'operations': [
  796. {'id': blockId, 'path': ['format', 'display_source'],
  797. 'args': url,
  798. 'command': 'set', 'table': 'block'
  799. },
  800. {
  801. 'args': {'last_edited_by_id': userId, 'last_edited_by_table': 'notion_user', 'last_edited_time': ts},
  802. 'command': 'update', 'id': blockId, 'path': [], 'table': 'block'
  803. },
  804. {'id': blockId, 'path': ['properties', 'source'],
  805. 'args': [[url]],
  806. 'command': 'set', 'table': 'block'
  807. },
  808. {
  809. 'args': {'last_edited_by_id': userId, 'last_edited_by_table': 'notion_user', 'last_edited_time': ts},
  810. 'command': 'update', 'id': blockId, 'path': [], 'table': 'block'
  811. },
  812. {'id': blockId, 'path': ['file_ids', 0],
  813. 'args': fileId,
  814. 'command': 'set', 'table': 'block'
  815. },
  816. {
  817. 'args': {'last_edited_by_id': userId, 'last_edited_by_table': 'notion_user', 'last_edited_time': ts},
  818. 'command': 'update', 'id': blockId, 'path': [], 'table': 'block'
  819. }
  820. ]
  821. }]
  822. },
  823. function()
  824. {
  825. msg.newBlock = {id: blockId, url: url};
  826. editBlock(blockId);
  827. sendResponse(msg);
  828. }, sendResponse, msg);
  829. }, sendResponse, msg, urls.signedPutUrl, 'put', true, 'image/svg+xml', true);
  830. }, sendResponse, msg);
  831. }, sendResponse, msg);
  832. }, sendResponse, msg);
  833. break;
  834. }
  835. return true;
  836. });
  837. })();