embed.ts 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. // transplanted from https://github.com/jgraph/drawio-tools/blob/d46977060ffad70cae5a9059a2cbfcd8bcf420de/tools/convert.html
  2. import pako from 'pako';
  3. import xmldoc from 'xmldoc';
  4. export const extractCodeFromCompressedInput = (input: string): string => {
  5. const doc = new xmldoc.XmlDocument(input);
  6. return doc.valueWithPath('diagram');
  7. };
  8. const validateUncompressedData = (input: string): boolean => {
  9. return new RegExp('/<mxGraphModel/').test(input);
  10. };
  11. const validateCompressedData = (input: string): boolean => {
  12. let data = input;
  13. try {
  14. data = extractCodeFromCompressedInput(data);
  15. }
  16. catch (e) {
  17. // ignore
  18. }
  19. try {
  20. data = Buffer.from(data, 'base64').toString('binary');
  21. }
  22. catch (e) {
  23. throw new Error(`Base64 to binary failed: ${e}`);
  24. }
  25. if (data.length > 0) {
  26. try {
  27. data = pako.inflateRaw(Uint8Array.from(data, c => c.charCodeAt(0)), { to: 'string' });
  28. }
  29. catch (e) {
  30. throw new Error(`inflateRaw failed: ${e}`);
  31. }
  32. }
  33. try {
  34. data = decodeURIComponent(data);
  35. }
  36. catch (e) {
  37. throw new Error(`decodeURIComponent failed: ${e}`);
  38. }
  39. return true;
  40. };
  41. const escapeHTML = (string): string => {
  42. if (typeof string !== 'string') {
  43. return string;
  44. }
  45. return string.replace(/[&'`"<>]/g, (match): string => {
  46. return {
  47. '&': '&amp;',
  48. "'": '&#x27;',
  49. '`': '&#x60;',
  50. '"': '&quot;',
  51. '<': '&lt;',
  52. '>': '&gt;',
  53. }[match] ?? match;
  54. });
  55. };
  56. export const generateMxgraphData = (code: string): string => {
  57. const trimedCode = code.trim();
  58. if (!trimedCode) {
  59. return '';
  60. }
  61. // Evaluate the code is whether uncompressed data that are generated by v21.1.0 or above
  62. // see: https://github.com/jgraph/drawio/issues/3106#issuecomment-1479352026
  63. const isUncompressedData = validateUncompressedData(trimedCode);
  64. if (isUncompressedData) {
  65. validateCompressedData(trimedCode);
  66. }
  67. const xml = `
  68. <mxfile version="6.8.9" editor="www.draw.io" type="atlas">
  69. <mxAtlasLibraries/>
  70. <diagram>${isUncompressedData ? xmldoc.XmlDocument(trimedCode) : trimedCode}</diagram>
  71. </mxfile>
  72. `;
  73. // see options: https://drawio.freshdesk.com/support/solutions/articles/16000042542-embed-html
  74. const mxGraphData = {
  75. editable: false,
  76. highlight: '#0000ff',
  77. nav: false,
  78. toolbar: null,
  79. edit: null,
  80. resize: true,
  81. lightbox: 'false',
  82. xml,
  83. };
  84. return escapeHTML(JSON.stringify(mxGraphData));
  85. };