@cyberyozh/text-editor 0.5.3 → 0.5.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/render.js CHANGED
@@ -255,17 +255,27 @@ var import_xml = __toESM(require("highlight.js/lib/languages/xml"));
255
255
  var import_lowlight = require("lowlight");
256
256
  var lowlight = (0, import_lowlight.createLowlight)(import_lowlight.common);
257
257
  lowlight.register("html", import_xml.default);
258
+ function languageFromClass(code, prefix) {
259
+ const languageClass = Array.from(code?.classList ?? []).find(
260
+ (className) => className.startsWith(prefix)
261
+ );
262
+ return languageClass ? languageClass.slice(prefix.length) : null;
263
+ }
258
264
  var BaseCodeBlock = import_extension_code_block_lowlight.CodeBlockLowlight.configure({
259
265
  lowlight
260
266
  }).extend({
261
267
  selectable: false,
262
268
  draggable: true,
263
269
  addAttributes() {
270
+ const { languageClassPrefix } = this.options;
264
271
  return {
265
272
  language: {
266
273
  default: null,
274
+ rendered: false,
267
275
  parseHTML: (element) => {
268
- return element.querySelector("code")?.getAttribute("data-language") || "bash";
276
+ const code = element.querySelector("code");
277
+ const fromClass = languageClassPrefix ? languageFromClass(code, languageClassPrefix) : null;
278
+ return fromClass || code?.getAttribute("data-language") || "bash";
269
279
  }
270
280
  }
271
281
  };
@@ -1584,52 +1594,53 @@ function find(str, type = null, opts = null) {
1584
1594
  }
1585
1595
 
1586
1596
  // src/extensions/base/link.ts
1587
- var isSameDomain = (url) => {
1588
- if (typeof window === "undefined") return false;
1597
+ var hostnameOf = (url) => {
1589
1598
  try {
1590
- return new URL(url).hostname === window.location.hostname;
1599
+ return new URL(url).hostname.toLowerCase();
1591
1600
  } catch {
1592
- return false;
1601
+ return null;
1593
1602
  }
1594
1603
  };
1595
- var isTrustedDomain = (url, trustedDomains) => {
1596
- try {
1597
- const { hostname } = new URL(url);
1598
- if (typeof window !== "undefined" && hostname === window.location.hostname) {
1599
- return true;
1600
- }
1601
- return trustedDomains.some((trusted) => {
1602
- const domain2 = trusted.toLowerCase();
1603
- return hostname === domain2 || hostname.endsWith(`.${domain2}`);
1604
- });
1605
- } catch {
1606
- return false;
1607
- }
1604
+ var isSameDomain = (url) => {
1605
+ if (typeof window === "undefined") return false;
1606
+ return hostnameOf(url) === window.location.hostname;
1607
+ };
1608
+ var matchesDomains = (url, domains) => {
1609
+ const hostname = hostnameOf(url);
1610
+ if (hostname === null) return false;
1611
+ return domains.some((candidate) => {
1612
+ const domain2 = candidate.toLowerCase();
1613
+ return hostname === domain2 || hostname.endsWith(`.${domain2}`);
1614
+ });
1615
+ };
1616
+ var isOwnDomain = (url, ownDomains) => isSameDomain(url) || matchesDomains(url, ownDomains);
1617
+ var isTrustedDomain = (url, trustedDomains) => isSameDomain(url) || matchesDomains(url, trustedDomains);
1618
+ var linkAttributes = (href, { ownDomains, trustedDomains }) => {
1619
+ const own = isOwnDomain(href, ownDomains);
1620
+ return {
1621
+ target: own ? "_self" : "_blank",
1622
+ rel: own || isTrustedDomain(href, trustedDomains) ? null : "noopener noreferrer nofollow"
1623
+ };
1608
1624
  };
1609
1625
  var LinkExtension = import_extension_link.default.extend({
1610
1626
  addOptions() {
1611
1627
  return {
1612
1628
  ...this.parent?.() ?? {},
1629
+ ownDomains: [],
1613
1630
  trustedDomains: []
1614
1631
  };
1615
1632
  },
1616
1633
  addAttributes() {
1617
- const { trustedDomains } = this.options;
1634
+ const domains = this.options;
1618
1635
  return {
1619
1636
  ...this.parent?.(),
1620
1637
  target: {
1621
1638
  default: "_blank",
1622
- parseHTML: (element) => {
1623
- const href = element.getAttribute("href") ?? "";
1624
- return isSameDomain(href) ? "_self" : "_blank";
1625
- }
1639
+ parseHTML: (element) => linkAttributes(element.getAttribute("href") ?? "", domains).target
1626
1640
  },
1627
1641
  rel: {
1628
1642
  default: null,
1629
- parseHTML: (element) => {
1630
- const href = element.getAttribute("href") ?? "";
1631
- return isTrustedDomain(href, trustedDomains) ? null : "noopener noreferrer nofollow";
1632
- }
1643
+ parseHTML: (element) => linkAttributes(element.getAttribute("href") ?? "", domains).rel
1633
1644
  }
1634
1645
  };
1635
1646
  },
@@ -1656,11 +1667,7 @@ var LinkExtension = import_extension_link.default.extend({
1656
1667
  type: this.type,
1657
1668
  getAttributes: (match) => {
1658
1669
  const href = match.data?.href ?? "";
1659
- return {
1660
- href,
1661
- target: isSameDomain(href) ? "_self" : "_blank",
1662
- rel: isTrustedDomain(href, this.options.trustedDomains) ? null : "noopener noreferrer nofollow"
1663
- };
1670
+ return { href, ...linkAttributes(href, this.options) };
1664
1671
  }
1665
1672
  })
1666
1673
  ];
@@ -2714,7 +2721,10 @@ function getSharedExtensions(options = {}) {
2714
2721
  link: false
2715
2722
  }),
2716
2723
  import_extension_highlight.default.configure({ multicolor: true }),
2717
- LinkExtension.configure({ trustedDomains: options.trustedDomains ?? [] }),
2724
+ LinkExtension.configure({
2725
+ ownDomains: options.ownDomains ?? [],
2726
+ trustedDomains: options.trustedDomains ?? []
2727
+ }),
2718
2728
  import_extension_superscript.default,
2719
2729
  import_extension_subscript.default,
2720
2730
  import_extension_text_align.default.configure({
@@ -2740,8 +2750,8 @@ function getSharedExtensions(options = {}) {
2740
2750
  }
2741
2751
 
2742
2752
  // src/extensions/render/get-render-extensions.ts
2743
- function getRenderExtensions() {
2744
- const sharedExtensions = getSharedExtensions();
2753
+ function getRenderExtensions(options = {}) {
2754
+ const sharedExtensions = getSharedExtensions(options);
2745
2755
  return [
2746
2756
  ...sharedExtensions,
2747
2757
  CopyableText,
@@ -3744,8 +3754,7 @@ function TiptapRender({ content, getImageById }) {
3744
3754
  }
3745
3755
 
3746
3756
  // src/utils/html-to-tiptap-content.ts
3747
- var import_core11 = require("@tiptap/core");
3748
- var import_extension_table2 = require("@tiptap/extension-table");
3757
+ var import_html = require("@tiptap/html");
3749
3758
  function isJSONContent(value) {
3750
3759
  return typeof value === "object" && value !== null && "type" in value && typeof value.type === "string";
3751
3760
  }
@@ -3765,10 +3774,8 @@ function htmlToTiptapContent(content, options = {}) {
3765
3774
  if (!content || content.trim() === "") {
3766
3775
  return { type: "doc", content: [{ type: "paragraph" }] };
3767
3776
  }
3768
- const sharedExtensions = getSharedExtensions(options);
3769
- const extensions = [...sharedExtensions, BaseFigure, import_extension_table2.TableKit, BaseCodeBlock];
3770
3777
  try {
3771
- return (0, import_core11.generateJSON)(content, extensions);
3778
+ return (0, import_html.generateJSON)(content, getRenderExtensions(options));
3772
3779
  } catch (error) {
3773
3780
  console.error("Failed to convert HTML to Tiptap content:", error);
3774
3781
  return { type: "doc", content: [{ type: "paragraph" }] };