{"version":3,"file":"XMarkdown.min.mjs","sources":["../../../../src/shapes/canvasx/XMarkdown.ts"],"sourcesContent":["import { classRegistry } from '../../ClassRegistry';\nimport { XTextbase } from '../canvasx/XTextbase';\nimport html2canvas from 'html2canvas';\nimport { FabricImage } from '../../shapes/Image';\nimport hljs from 'highlight.js'; // https://highlightjs.org\n\n//@ts-ignore\nimport markdownit from 'markdown-it';\n//@ts-ignore\nimport javascript from 'highlight.js/lib/languages/javascript';\nimport { WidgetMarkdownInterface, EntityKeys } from './type/widget.entity.markdown';\nimport { WidgetType } from './type/widget.type';\n\nhljs.registerLanguage('javascript', javascript);\n\n\n\nclass XMarkdown extends XTextbase implements WidgetMarkdownInterface {\n  public markdownText: string;\n  isEditing: boolean = false;\n  private renderedImage: FabricImage | null = null;\n  private md: any;\n\n  static type: WidgetType = 'XMarkdown';\n  static objType: WidgetType = 'XMarkdown';\n  constructor(text: string, options: WidgetMarkdownInterface) {\n\n    super(text, options);\n    this.markdownText = options?.markdownText || text;\n    this.objType = 'XMarkdown';\n    // full options list (defaults)\n    this.md = markdownit({\n      // Enable HTML tags in source\n      html: true,\n\n      // Use '/' to close single tags (<br />).\n      // This is only for full CommonMark compatibility.\n      xhtmlOut: false,\n\n      // Convert '\\n' in paragraphs into <br>\n      breaks: false,\n\n      // CSS language prefix for fenced blocks. Can be\n      // useful for external highlighters.\n      langPrefix: 'language-',\n\n      // Autoconvert URL-like text to links\n      linkify: false,\n\n      // Enable some language-neutral replacement + quotes beautification\n      // For the full list of replacements, see https://github.com/markdown-it/markdown-it/blob/master/lib/rules_core/replacements.mjs\n      typographer: true,\n\n      // Double + single quotes replacement pairs, when typographer enabled,\n      // and smartquotes on. Could be either a String or an Array.\n      //\n      // For example, you can use '«»„“' for Russian, '„“‚‘' for German,\n      // and ['«\\xA0', '\\xA0»', '‹\\xA0', '\\xA0›'] for French (including nbsp).\n      quotes: '“”‘’',\n\n      // Highlighter function. Should return escaped HTML,\n      // or '' if the source string is not changed and should be escaped externally.\n      // If result starts with <pre... internal wrapper is skipped.\n      highlight: function (str: string, lang: string) {\n        if (lang && hljs.getLanguage(lang)) {\n          try {\n            return hljs.highlight(str, { language: lang }).value;\n          } catch (__) { }\n        }\n\n        return ''; // use external default escaping\n      },\n    });\n    Object.assign(this, options);\n\n    this.on('editing:entered', this.onEditingEntered.bind(this));\n    this.on('editing:exited', this.onEditingExited.bind(this));\n    this.on('scaling', this.onScaling.bind(this));\n    this.on('resizing', this.onScaled.bind(this));\n    this.renderMarkdown();\n  }\n\n\n\n  private onEditingEntered() {\n    this.isEditing = true;\n    this.text = this.markdownText;\n    this.dirty = true;\n    this.canvas?.renderAll();\n  }\n\n  private onEditingExited() {\n    this.isEditing = false;\n    this.markdownText = this.text;\n    this.renderMarkdown();\n  }\n\n  private onScaling() {\n    this.renderMarkdown();\n    // Optional: You can add any logic needed during scaling\n  }\n\n  private onScaled() {\n    this.renderMarkdown();\n  }\n\n  async renderMarkdown() {\n    if (this.isEditing) return;\n\n    const html = this.md.render(this.markdownText);\n    this.parseHtmlToImage(html).then((img) => {\n      this.renderedImage = img;\n      this.dirty = true;\n      this.canvas?.renderAll();\n    });\n  }\n\n\n  getObject() {\n    const entityKeys: string[] = EntityKeys;\n    const result: Record<string, any> = {};\n\n    entityKeys.forEach((key) => {\n      if (key in this) {\n        result[key] = (this as any)[key];\n      }\n    });\n\n    return result;\n  }\n\n  private parseHtmlToImage(html: string): Promise<FabricImage> {\n    return new Promise((resolve) => {\n      const blob = new Blob([html], { type: 'text/html' });\n      const url = URL.createObjectURL(blob);\n\n      const iframe = document.createElement('iframe');\n      iframe.style.width = `${this.width}px`;\n      iframe.style.height = `${this.height}px`;\n      iframe.style.visibility = 'hidden';\n      iframe.style.position = 'absolute';\n      iframe.style.left = '-9999px';\n      document.body.appendChild(iframe);\n\n      iframe.onload = async () => {\n        if (iframe.contentDocument) {\n          const style = iframe.contentDocument.createElement('style');\n          style.textContent = `\n            body { \n              font-family: Arial, sans-serif; \n              font-size: 14px; \n              line-height: 1.6; \n              color: #333; \n              padding: 20px; \n              margin: 0;\n              width: ${this.width}px;\n              height: ${this.height}px;\n            }\n            h1, h2, h3, h4, h5, h6 { margin-top: 0; }\n            ul, ol { padding-left: 20px; }\n          /* Code block styling */\ncode {\n  background-color: #f5f5f5; /* Slightly lighter background for better contrast */\n  padding: 3px 5px; /* More padding for better spacing */\n  border-radius: 5px; /* Smoother border radius */\n  font-family: 'Courier New', Courier, monospace; /* Monospace font for code */\n}\n\npre {\n  background-color: #f5f5f5; /* Matching background color with inline code */\n  padding: 12px; /* Slightly more padding for comfort */\n  border-radius: 5px; /* Smoother border radius */\n  overflow-x: auto; /* Ensure horizontal scroll for long code lines */\n  font-family: 'Courier New', Courier, monospace; /* Monospace font for code */\n}\n\npre code {\n  display: block;\n}\n\n/* Table styling */\ntable {\n  border-collapse: collapse;\n \n  margin-bottom: 1em; /* Add some margin below tables */\n  font-family: Arial, sans-serif; /* Better font for readability */\n}\n\ntable, th, td {\n  border: 1px solid #ddd; /* Lighter border color for a cleaner look */\n}\n\nth, td {\n  padding: 10px; /* More padding for better spacing */\n  text-align: left;\n}\n\nth {\n  background-color: #f2f2f2; /* Slight background color for headers */\n  font-weight: bold; /* Bold headers */\n}\n\ntd {\n  background-color: #fff; /* Ensure a white background for table cells */\n}\n\n/* Additional table row hover effect */\ntr:hover {\n  background-color: #f1f1f1; /* Highlight row on hover */\n}\n          `;\n          iframe.contentDocument.head.appendChild(style);\n        }\n\n        iframe.contentDocument!.body.innerHTML = html;\n\n        await new Promise((resolve) => setTimeout(resolve, 100)); // Small delay to ensure styles are applied\n\n        const canvas = await html2canvas(\n          iframe.contentDocument?.body as HTMLElement\n        );\n        const img = await FabricImage.fromURL(canvas.toDataURL());\n        img.set({\n          left: this.left,\n          top: this.top,\n          width: this.width,\n          height: this.height,\n          scaleX: 1,\n          scaleY: 1,\n        });\n        resolve(img);\n\n        document.body.removeChild(iframe);\n        URL.revokeObjectURL(url);\n      };\n\n      iframe.src = url;\n    });\n  }\n\n  setMarkdown(newMarkdownText: string) {\n    this.markdownText = newMarkdownText;\n    if (this.isEditing) {\n      this.text = this.markdownText;\n      this.dirty = true;\n    } else {\n      this.renderMarkdown();\n    }\n    this.canvas?.renderAll();\n  }\n\n  _render(ctx: CanvasRenderingContext2D) {\n    if (this.isEditing) {\n      super._render(ctx);\n    } else if (this.renderedImage) {\n      this.renderedImage._render(ctx);\n    }\n  }\n}\n\nexport { XMarkdown };\n\nclassRegistry.setClass(XMarkdown);\n"],"names":["hljs","registerLanguage","javascript","XMarkdown","XTextbase","constructor","text","options","super","_defineProperty","this","markdownText","objType","md","markdownit","html","xhtmlOut","breaks","langPrefix","linkify","typographer","quotes","highlight","str","lang","getLanguage","language","value","__","Object","assign","on","onEditingEntered","bind","onEditingExited","onScaling","onScaled","renderMarkdown","_this$canvas","isEditing","dirty","canvas","renderAll","render","parseHtmlToImage","then","img","_this$canvas2","renderedImage","getObject","result","EntityKeys","forEach","key","Promise","resolve","blob","Blob","type","url","URL","createObjectURL","iframe","document","createElement","style","width","concat","height","visibility","position","left","body","appendChild","onload","async","_iframe$contentDocume","contentDocument","textContent","head","innerHTML","setTimeout","html2canvas","FabricImage","fromURL","toDataURL","set","top","scaleX","scaleY","removeChild","revokeObjectURL","src","setMarkdown","newMarkdownText","_this$canvas3","_render","ctx","classRegistry","setClass"],"mappings":"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"}