DrawioCommunicationHelper.ts 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. import loggerFactory from '~/utils/logger';
  2. const logger = loggerFactory('growi:cli:DrawioCommunicationHelper');
  3. export type DrawioConfig = {
  4. css: string;
  5. customFonts: string[];
  6. compressXml: boolean;
  7. };
  8. export type DrawioCommunicationCallbackOptions = {
  9. onClose?: () => void;
  10. onSave?: (drawioData: string) => void;
  11. };
  12. export class DrawioCommunicationHelper {
  13. drawioUri: string;
  14. drawioConfig: DrawioConfig;
  15. callbackOpts?: DrawioCommunicationCallbackOptions;
  16. constructor(
  17. drawioUri: string,
  18. drawioConfig: DrawioConfig,
  19. callbackOpts?: DrawioCommunicationCallbackOptions,
  20. ) {
  21. this.drawioUri = drawioUri;
  22. this.drawioConfig = drawioConfig;
  23. this.callbackOpts = callbackOpts;
  24. }
  25. onReceiveMessage(event: MessageEvent, drawioMxFile: string | null): void {
  26. // check origin
  27. if (event.origin != null && this.drawioUri != null) {
  28. const originUrl = new URL(event.origin);
  29. const drawioUrl = new URL(this.drawioUri);
  30. if (originUrl.origin !== drawioUrl.origin) {
  31. logger.debug(
  32. `Skipping the event because the origins are mismatched. expected: '${drawioUrl.origin}', actual: '${originUrl.origin}'`,
  33. );
  34. return;
  35. }
  36. }
  37. // configure
  38. if (event.data === '{"event":"configure"}') {
  39. if (event.source == null) {
  40. return;
  41. }
  42. // refs:
  43. // * https://desk.draw.io/support/solutions/articles/16000103852-how-to-customise-the-draw-io-interface
  44. // * https://desk.draw.io/support/solutions/articles/16000042544-how-does-embed-mode-work-
  45. // * https://desk.draw.io/support/solutions/articles/16000058316-how-to-configure-draw-io-
  46. event.source.postMessage(
  47. JSON.stringify({
  48. action: 'configure',
  49. config: this.drawioConfig,
  50. }),
  51. { targetOrigin: '*' },
  52. );
  53. return;
  54. }
  55. // restore diagram data
  56. if (event.data === 'ready') {
  57. event.source?.postMessage(drawioMxFile, { targetOrigin: '*' });
  58. return;
  59. }
  60. if (typeof event.data === 'string' && event.data.match(/mxfile/)) {
  61. if (event.data.length > 0) {
  62. const parser = new DOMParser();
  63. const dom = parser.parseFromString(event.data, 'text/xml');
  64. const drawioData = dom.getElementsByTagName('diagram')[0].innerHTML;
  65. /*
  66. * Saving Drawio will be implemented by the following tasks
  67. * https://redmine.weseek.co.jp/issues/100845
  68. * https://redmine.weseek.co.jp/issues/104507
  69. */
  70. this.callbackOpts?.onSave?.(drawioData);
  71. }
  72. this.callbackOpts?.onClose?.();
  73. return;
  74. }
  75. if (typeof event.data === 'string' && event.data.length === 0) {
  76. this.callbackOpts?.onClose?.();
  77. return;
  78. }
  79. // NOTHING DONE. (Receive unknown iframe message.)
  80. }
  81. }