@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.mjs CHANGED
@@ -218,17 +218,27 @@ import html from "highlight.js/lib/languages/xml";
218
218
  import { common, createLowlight } from "lowlight";
219
219
  var lowlight = createLowlight(common);
220
220
  lowlight.register("html", html);
221
+ function languageFromClass(code, prefix) {
222
+ const languageClass = Array.from(code?.classList ?? []).find(
223
+ (className) => className.startsWith(prefix)
224
+ );
225
+ return languageClass ? languageClass.slice(prefix.length) : null;
226
+ }
221
227
  var BaseCodeBlock = CodeBlockLowlight.configure({
222
228
  lowlight
223
229
  }).extend({
224
230
  selectable: false,
225
231
  draggable: true,
226
232
  addAttributes() {
233
+ const { languageClassPrefix } = this.options;
227
234
  return {
228
235
  language: {
229
236
  default: null,
237
+ rendered: false,
230
238
  parseHTML: (element) => {
231
- return element.querySelector("code")?.getAttribute("data-language") || "bash";
239
+ const code = element.querySelector("code");
240
+ const fromClass = languageClassPrefix ? languageFromClass(code, languageClassPrefix) : null;
241
+ return fromClass || code?.getAttribute("data-language") || "bash";
232
242
  }
233
243
  }
234
244
  };
@@ -1547,52 +1557,53 @@ function find(str, type = null, opts = null) {
1547
1557
  }
1548
1558
 
1549
1559
  // src/extensions/base/link.ts
1550
- var isSameDomain = (url) => {
1551
- if (typeof window === "undefined") return false;
1560
+ var hostnameOf = (url) => {
1552
1561
  try {
1553
- return new URL(url).hostname === window.location.hostname;
1562
+ return new URL(url).hostname.toLowerCase();
1554
1563
  } catch {
1555
- return false;
1564
+ return null;
1556
1565
  }
1557
1566
  };
1558
- var isTrustedDomain = (url, trustedDomains) => {
1559
- try {
1560
- const { hostname } = new URL(url);
1561
- if (typeof window !== "undefined" && hostname === window.location.hostname) {
1562
- return true;
1563
- }
1564
- return trustedDomains.some((trusted) => {
1565
- const domain2 = trusted.toLowerCase();
1566
- return hostname === domain2 || hostname.endsWith(`.${domain2}`);
1567
- });
1568
- } catch {
1569
- return false;
1570
- }
1567
+ var isSameDomain = (url) => {
1568
+ if (typeof window === "undefined") return false;
1569
+ return hostnameOf(url) === window.location.hostname;
1570
+ };
1571
+ var matchesDomains = (url, domains) => {
1572
+ const hostname = hostnameOf(url);
1573
+ if (hostname === null) return false;
1574
+ return domains.some((candidate) => {
1575
+ const domain2 = candidate.toLowerCase();
1576
+ return hostname === domain2 || hostname.endsWith(`.${domain2}`);
1577
+ });
1578
+ };
1579
+ var isOwnDomain = (url, ownDomains) => isSameDomain(url) || matchesDomains(url, ownDomains);
1580
+ var isTrustedDomain = (url, trustedDomains) => isSameDomain(url) || matchesDomains(url, trustedDomains);
1581
+ var linkAttributes = (href, { ownDomains, trustedDomains }) => {
1582
+ const own = isOwnDomain(href, ownDomains);
1583
+ return {
1584
+ target: own ? "_self" : "_blank",
1585
+ rel: own || isTrustedDomain(href, trustedDomains) ? null : "noopener noreferrer nofollow"
1586
+ };
1571
1587
  };
1572
1588
  var LinkExtension = Link.extend({
1573
1589
  addOptions() {
1574
1590
  return {
1575
1591
  ...this.parent?.() ?? {},
1592
+ ownDomains: [],
1576
1593
  trustedDomains: []
1577
1594
  };
1578
1595
  },
1579
1596
  addAttributes() {
1580
- const { trustedDomains } = this.options;
1597
+ const domains = this.options;
1581
1598
  return {
1582
1599
  ...this.parent?.(),
1583
1600
  target: {
1584
1601
  default: "_blank",
1585
- parseHTML: (element) => {
1586
- const href = element.getAttribute("href") ?? "";
1587
- return isSameDomain(href) ? "_self" : "_blank";
1588
- }
1602
+ parseHTML: (element) => linkAttributes(element.getAttribute("href") ?? "", domains).target
1589
1603
  },
1590
1604
  rel: {
1591
1605
  default: null,
1592
- parseHTML: (element) => {
1593
- const href = element.getAttribute("href") ?? "";
1594
- return isTrustedDomain(href, trustedDomains) ? null : "noopener noreferrer nofollow";
1595
- }
1606
+ parseHTML: (element) => linkAttributes(element.getAttribute("href") ?? "", domains).rel
1596
1607
  }
1597
1608
  };
1598
1609
  },
@@ -1619,11 +1630,7 @@ var LinkExtension = Link.extend({
1619
1630
  type: this.type,
1620
1631
  getAttributes: (match) => {
1621
1632
  const href = match.data?.href ?? "";
1622
- return {
1623
- href,
1624
- target: isSameDomain(href) ? "_self" : "_blank",
1625
- rel: isTrustedDomain(href, this.options.trustedDomains) ? null : "noopener noreferrer nofollow"
1626
- };
1633
+ return { href, ...linkAttributes(href, this.options) };
1627
1634
  }
1628
1635
  })
1629
1636
  ];
@@ -2681,7 +2688,10 @@ function getSharedExtensions(options = {}) {
2681
2688
  link: false
2682
2689
  }),
2683
2690
  Highlight.configure({ multicolor: true }),
2684
- LinkExtension.configure({ trustedDomains: options.trustedDomains ?? [] }),
2691
+ LinkExtension.configure({
2692
+ ownDomains: options.ownDomains ?? [],
2693
+ trustedDomains: options.trustedDomains ?? []
2694
+ }),
2685
2695
  Superscript,
2686
2696
  Subscript,
2687
2697
  TextAlign.configure({
@@ -2707,8 +2717,8 @@ function getSharedExtensions(options = {}) {
2707
2717
  }
2708
2718
 
2709
2719
  // src/extensions/render/get-render-extensions.ts
2710
- function getRenderExtensions() {
2711
- const sharedExtensions = getSharedExtensions();
2720
+ function getRenderExtensions(options = {}) {
2721
+ const sharedExtensions = getSharedExtensions(options);
2712
2722
  return [
2713
2723
  ...sharedExtensions,
2714
2724
  CopyableText,
@@ -3711,8 +3721,7 @@ function TiptapRender({ content, getImageById }) {
3711
3721
  }
3712
3722
 
3713
3723
  // src/utils/html-to-tiptap-content.ts
3714
- import { generateJSON } from "@tiptap/core";
3715
- import { TableKit as TableKit2 } from "@tiptap/extension-table";
3724
+ import { generateJSON } from "@tiptap/html";
3716
3725
  function isJSONContent(value) {
3717
3726
  return typeof value === "object" && value !== null && "type" in value && typeof value.type === "string";
3718
3727
  }
@@ -3732,10 +3741,8 @@ function htmlToTiptapContent(content, options = {}) {
3732
3741
  if (!content || content.trim() === "") {
3733
3742
  return { type: "doc", content: [{ type: "paragraph" }] };
3734
3743
  }
3735
- const sharedExtensions = getSharedExtensions(options);
3736
- const extensions = [...sharedExtensions, BaseFigure, TableKit2, BaseCodeBlock];
3737
3744
  try {
3738
- return generateJSON(content, extensions);
3745
+ return generateJSON(content, getRenderExtensions(options));
3739
3746
  } catch (error) {
3740
3747
  console.error("Failed to convert HTML to Tiptap content:", error);
3741
3748
  return { type: "doc", content: [{ type: "paragraph" }] };