@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/editor.mjs CHANGED
@@ -2960,17 +2960,27 @@ import html from "highlight.js/lib/languages/xml";
2960
2960
  import { common, createLowlight } from "lowlight";
2961
2961
  var lowlight = createLowlight(common);
2962
2962
  lowlight.register("html", html);
2963
+ function languageFromClass(code, prefix) {
2964
+ const languageClass = Array.from(code?.classList ?? []).find(
2965
+ (className) => className.startsWith(prefix)
2966
+ );
2967
+ return languageClass ? languageClass.slice(prefix.length) : null;
2968
+ }
2963
2969
  var BaseCodeBlock = CodeBlockLowlight.configure({
2964
2970
  lowlight
2965
2971
  }).extend({
2966
2972
  selectable: false,
2967
2973
  draggable: true,
2968
2974
  addAttributes() {
2975
+ const { languageClassPrefix } = this.options;
2969
2976
  return {
2970
2977
  language: {
2971
2978
  default: null,
2979
+ rendered: false,
2972
2980
  parseHTML: (element) => {
2973
- return element.querySelector("code")?.getAttribute("data-language") || "bash";
2981
+ const code = element.querySelector("code");
2982
+ const fromClass = languageClassPrefix ? languageFromClass(code, languageClassPrefix) : null;
2983
+ return fromClass || code?.getAttribute("data-language") || "bash";
2974
2984
  }
2975
2985
  }
2976
2986
  };
@@ -4289,52 +4299,53 @@ function find(str, type = null, opts = null) {
4289
4299
  }
4290
4300
 
4291
4301
  // src/extensions/base/link.ts
4292
- var isSameDomain = (url) => {
4293
- if (typeof window === "undefined") return false;
4302
+ var hostnameOf = (url) => {
4294
4303
  try {
4295
- return new URL(url).hostname === window.location.hostname;
4304
+ return new URL(url).hostname.toLowerCase();
4296
4305
  } catch {
4297
- return false;
4306
+ return null;
4298
4307
  }
4299
4308
  };
4300
- var isTrustedDomain = (url, trustedDomains) => {
4301
- try {
4302
- const { hostname } = new URL(url);
4303
- if (typeof window !== "undefined" && hostname === window.location.hostname) {
4304
- return true;
4305
- }
4306
- return trustedDomains.some((trusted) => {
4307
- const domain2 = trusted.toLowerCase();
4308
- return hostname === domain2 || hostname.endsWith(`.${domain2}`);
4309
- });
4310
- } catch {
4311
- return false;
4312
- }
4309
+ var isSameDomain = (url) => {
4310
+ if (typeof window === "undefined") return false;
4311
+ return hostnameOf(url) === window.location.hostname;
4312
+ };
4313
+ var matchesDomains = (url, domains) => {
4314
+ const hostname = hostnameOf(url);
4315
+ if (hostname === null) return false;
4316
+ return domains.some((candidate) => {
4317
+ const domain2 = candidate.toLowerCase();
4318
+ return hostname === domain2 || hostname.endsWith(`.${domain2}`);
4319
+ });
4320
+ };
4321
+ var isOwnDomain = (url, ownDomains) => isSameDomain(url) || matchesDomains(url, ownDomains);
4322
+ var isTrustedDomain = (url, trustedDomains) => isSameDomain(url) || matchesDomains(url, trustedDomains);
4323
+ var linkAttributes = (href, { ownDomains, trustedDomains }) => {
4324
+ const own = isOwnDomain(href, ownDomains);
4325
+ return {
4326
+ target: own ? "_self" : "_blank",
4327
+ rel: own || isTrustedDomain(href, trustedDomains) ? null : "noopener noreferrer nofollow"
4328
+ };
4313
4329
  };
4314
4330
  var LinkExtension = Link.extend({
4315
4331
  addOptions() {
4316
4332
  return {
4317
4333
  ...this.parent?.() ?? {},
4334
+ ownDomains: [],
4318
4335
  trustedDomains: []
4319
4336
  };
4320
4337
  },
4321
4338
  addAttributes() {
4322
- const { trustedDomains } = this.options;
4339
+ const domains = this.options;
4323
4340
  return {
4324
4341
  ...this.parent?.(),
4325
4342
  target: {
4326
4343
  default: "_blank",
4327
- parseHTML: (element) => {
4328
- const href = element.getAttribute("href") ?? "";
4329
- return isSameDomain(href) ? "_self" : "_blank";
4330
- }
4344
+ parseHTML: (element) => linkAttributes(element.getAttribute("href") ?? "", domains).target
4331
4345
  },
4332
4346
  rel: {
4333
4347
  default: null,
4334
- parseHTML: (element) => {
4335
- const href = element.getAttribute("href") ?? "";
4336
- return isTrustedDomain(href, trustedDomains) ? null : "noopener noreferrer nofollow";
4337
- }
4348
+ parseHTML: (element) => linkAttributes(element.getAttribute("href") ?? "", domains).rel
4338
4349
  }
4339
4350
  };
4340
4351
  },
@@ -4361,11 +4372,7 @@ var LinkExtension = Link.extend({
4361
4372
  type: this.type,
4362
4373
  getAttributes: (match) => {
4363
4374
  const href = match.data?.href ?? "";
4364
- return {
4365
- href,
4366
- target: isSameDomain(href) ? "_self" : "_blank",
4367
- rel: isTrustedDomain(href, this.options.trustedDomains) ? null : "noopener noreferrer nofollow"
4368
- };
4375
+ return { href, ...linkAttributes(href, this.options) };
4369
4376
  }
4370
4377
  })
4371
4378
  ];
@@ -6361,7 +6368,10 @@ function getSharedExtensions(options = {}) {
6361
6368
  link: false
6362
6369
  }),
6363
6370
  Highlight.configure({ multicolor: true }),
6364
- LinkExtension.configure({ trustedDomains: options.trustedDomains ?? [] }),
6371
+ LinkExtension.configure({
6372
+ ownDomains: options.ownDomains ?? [],
6373
+ trustedDomains: options.trustedDomains ?? []
6374
+ }),
6365
6375
  Superscript,
6366
6376
  Subscript,
6367
6377
  TextAlign.configure({
@@ -6603,9 +6613,10 @@ function getEditorExtensions(options) {
6603
6613
  getImageById,
6604
6614
  onKatexClick,
6605
6615
  onFigureClick,
6616
+ ownDomains,
6606
6617
  trustedDomains
6607
6618
  } = options;
6608
- const sharedExtensions = getSharedExtensions({ trustedDomains });
6619
+ const sharedExtensions = getSharedExtensions({ ownDomains, trustedDomains });
6609
6620
  return [
6610
6621
  ...sharedExtensions,
6611
6622
  Callout2,
@@ -7671,6 +7682,7 @@ function TiptapContent({
7671
7682
  isDisabled = false,
7672
7683
  lang,
7673
7684
  error,
7685
+ ownDomains,
7674
7686
  trustedDomains
7675
7687
  }) {
7676
7688
  const [linkDialogContext, setLinkDialogContext] = useState13(null);
@@ -7706,6 +7718,7 @@ function TiptapContent({
7706
7718
  suggestion: createSuggestions(translations2, !!imageHandlers),
7707
7719
  isEditable: isEditable && !disabled,
7708
7720
  getImageById: imageHandlers?.getImage,
7721
+ ownDomains,
7709
7722
  trustedDomains,
7710
7723
  onKatexClick: (latex, pos) => {
7711
7724
  setKatexDialogContext({ latex, pos });
@@ -7891,8 +7904,52 @@ var Tiptap = (props) => {
7891
7904
  };
7892
7905
 
7893
7906
  // src/utils/html-to-tiptap-content.ts
7894
- import { generateJSON } from "@tiptap/core";
7907
+ import { generateJSON } from "@tiptap/html";
7908
+
7909
+ // src/extensions/render/get-render-extensions.ts
7910
+ import { Mathematics as Mathematics2 } from "@tiptap/extension-mathematics";
7895
7911
  import { TableKit as TableKit2 } from "@tiptap/extension-table";
7912
+ function getRenderExtensions(options = {}) {
7913
+ const sharedExtensions = getSharedExtensions(options);
7914
+ return [
7915
+ ...sharedExtensions,
7916
+ CopyableText,
7917
+ BaseCallout,
7918
+ BaseCodeBlock,
7919
+ BaseCustomQuote,
7920
+ BaseCustomQuoteText,
7921
+ BaseCustomQuoteAuthor,
7922
+ BaseCustomQuoteSign,
7923
+ BasePrompt,
7924
+ BasePromptHeader,
7925
+ BasePromptContent,
7926
+ BaseVideo,
7927
+ BaseFigure,
7928
+ TableKit2.configure({
7929
+ table: { resizable: false, renderWrapper: true }
7930
+ }),
7931
+ Mathematics2.configure({
7932
+ katexOptions: {
7933
+ throwOnError: false
7934
+ }
7935
+ }),
7936
+ // ========================================================================
7937
+ // Legacy Extensions (Deprecated - for backward compatibility only)
7938
+ // ========================================================================
7939
+ BaseLegacyBookAlert,
7940
+ BaseLegacyBookTip,
7941
+ BaseLegacySEQuote,
7942
+ BaseLegacyPromptSE,
7943
+ BaseLegacyPromptSEHeader,
7944
+ BaseLegacyPromptSEContent,
7945
+ BaseLegacyCustomBlockquote,
7946
+ BaseLegacyYouTube,
7947
+ BaseLegacyFigure
7948
+ // Update
7949
+ ];
7950
+ }
7951
+
7952
+ // src/utils/html-to-tiptap-content.ts
7896
7953
  function isJSONContent(value) {
7897
7954
  return typeof value === "object" && value !== null && "type" in value && typeof value.type === "string";
7898
7955
  }
@@ -7912,10 +7969,8 @@ function htmlToTiptapContent(content, options = {}) {
7912
7969
  if (!content || content.trim() === "") {
7913
7970
  return { type: "doc", content: [{ type: "paragraph" }] };
7914
7971
  }
7915
- const sharedExtensions = getSharedExtensions(options);
7916
- const extensions = [...sharedExtensions, BaseFigure, TableKit2, BaseCodeBlock];
7917
7972
  try {
7918
- return generateJSON(content, extensions);
7973
+ return generateJSON(content, getRenderExtensions(options));
7919
7974
  } catch (error) {
7920
7975
  console.error("Failed to convert HTML to Tiptap content:", error);
7921
7976
  return { type: "doc", content: [{ type: "paragraph" }] };