@cyberyozh/text-editor 0.4.0 → 0.5.0

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
@@ -4297,8 +4297,29 @@ var isSameDomain = (url) => {
4297
4297
  return false;
4298
4298
  }
4299
4299
  };
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
+ }
4313
+ };
4300
4314
  var LinkExtension = Link.extend({
4315
+ addOptions() {
4316
+ return {
4317
+ ...this.parent?.() ?? {},
4318
+ trustedDomains: []
4319
+ };
4320
+ },
4301
4321
  addAttributes() {
4322
+ const { trustedDomains } = this.options;
4302
4323
  return {
4303
4324
  ...this.parent?.(),
4304
4325
  target: {
@@ -4312,7 +4333,7 @@ var LinkExtension = Link.extend({
4312
4333
  default: null,
4313
4334
  parseHTML: (element) => {
4314
4335
  const href = element.getAttribute("href") ?? "";
4315
- return isSameDomain(href) ? null : "noopener noreferrer nofollow";
4336
+ return isTrustedDomain(href, trustedDomains) ? null : "noopener noreferrer nofollow";
4316
4337
  }
4317
4338
  }
4318
4339
  };
@@ -4330,15 +4351,20 @@ var LinkExtension = Link.extend({
4330
4351
  protocols,
4331
4352
  defaultProtocol
4332
4353
  })
4333
- ).filter((link) => this.options.shouldAutoLink?.(link.value) !== false).map((link) => ({ text: link.value, data: { href: link.href }, index: link.start })),
4354
+ ).filter(
4355
+ (link) => this.options.shouldAutoLink?.(link.value) !== false
4356
+ ).map((link) => ({
4357
+ text: link.value,
4358
+ data: { href: link.href },
4359
+ index: link.start
4360
+ })),
4334
4361
  type: this.type,
4335
4362
  getAttributes: (match) => {
4336
4363
  const href = match.data?.href ?? "";
4337
- const sameDomain = isSameDomain(href);
4338
4364
  return {
4339
4365
  href,
4340
- target: sameDomain ? "_self" : "_blank",
4341
- rel: sameDomain ? null : "noopener noreferrer nofollow"
4366
+ target: isSameDomain(href) ? "_self" : "_blank",
4367
+ rel: isTrustedDomain(href, this.options.trustedDomains) ? null : "noopener noreferrer nofollow"
4342
4368
  };
4343
4369
  }
4344
4370
  })
@@ -4353,7 +4379,11 @@ var LinkExtension = Link.extend({
4353
4379
  if (!view.editable) return false;
4354
4380
  const range = getMarkRange(view.state.doc.resolve(pos), this.type);
4355
4381
  if (!range) return false;
4356
- const selection = TextSelection3.create(view.state.doc, range.from, range.to);
4382
+ const selection = TextSelection3.create(
4383
+ view.state.doc,
4384
+ range.from,
4385
+ range.to
4386
+ );
4357
4387
  view.dispatch(view.state.tr.setSelection(selection));
4358
4388
  return true;
4359
4389
  }
@@ -6069,7 +6099,11 @@ var Commands = Extension.create({
6069
6099
 
6070
6100
  // src/utils/get-shared-extensions.ts
6071
6101
  import StarterKit from "@tiptap/starter-kit";
6072
- import { Details, DetailsContent, DetailsSummary } from "@tiptap/extension-details";
6102
+ import {
6103
+ Details,
6104
+ DetailsContent,
6105
+ DetailsSummary
6106
+ } from "@tiptap/extension-details";
6073
6107
  import Highlight from "@tiptap/extension-highlight";
6074
6108
  import Subscript from "@tiptap/extension-subscript";
6075
6109
  import Superscript from "@tiptap/extension-superscript";
@@ -6412,14 +6446,14 @@ var TextStyleKit = Extension6.create({
6412
6446
  });
6413
6447
 
6414
6448
  // src/utils/get-shared-extensions.ts
6415
- function getSharedExtensions() {
6449
+ function getSharedExtensions(options = {}) {
6416
6450
  return [
6417
6451
  StarterKit.configure({
6418
6452
  codeBlock: false,
6419
6453
  link: false
6420
6454
  }),
6421
6455
  Highlight.configure({ multicolor: true }),
6422
- LinkExtension,
6456
+ LinkExtension.configure({ trustedDomains: options.trustedDomains ?? [] }),
6423
6457
  Superscript,
6424
6458
  Subscript,
6425
6459
  TextAlign.configure({
@@ -6660,9 +6694,10 @@ function getEditorExtensions(options) {
6660
6694
  isEditable = false,
6661
6695
  getImageById,
6662
6696
  onKatexClick,
6663
- onFigureClick
6697
+ onFigureClick,
6698
+ trustedDomains
6664
6699
  } = options;
6665
- const sharedExtensions = getSharedExtensions();
6700
+ const sharedExtensions = getSharedExtensions({ trustedDomains });
6666
6701
  return [
6667
6702
  ...sharedExtensions,
6668
6703
  Callout2,
@@ -7721,7 +7756,8 @@ function TiptapContent({
7721
7756
  isEditable = true,
7722
7757
  isDisabled = false,
7723
7758
  lang,
7724
- error
7759
+ error,
7760
+ trustedDomains
7725
7761
  }) {
7726
7762
  const [linkDialogContext, setLinkDialogContext] = useState13(null);
7727
7763
  const [katexDialogContext, setKatexDialogContext] = useState13(
@@ -7756,6 +7792,7 @@ function TiptapContent({
7756
7792
  suggestion: createSuggestions(translations2, !!imageHandlers),
7757
7793
  isEditable: isEditable && !disabled,
7758
7794
  getImageById: imageHandlers?.getImage,
7795
+ trustedDomains,
7759
7796
  onKatexClick: (latex, pos) => {
7760
7797
  setKatexDialogContext({ latex, pos });
7761
7798
  openDialogCommand("katex");
@@ -7945,7 +7982,7 @@ import { TableKit as TableKit2 } from "@tiptap/extension-table";
7945
7982
  function isJSONContent(value) {
7946
7983
  return typeof value === "object" && value !== null && "type" in value && typeof value.type === "string";
7947
7984
  }
7948
- function htmlToTiptapContent(content) {
7985
+ function htmlToTiptapContent(content, options = {}) {
7949
7986
  if (isJSONContent(content)) {
7950
7987
  return content;
7951
7988
  }
@@ -7961,7 +7998,7 @@ function htmlToTiptapContent(content) {
7961
7998
  if (!content || content.trim() === "") {
7962
7999
  return { type: "doc", content: [{ type: "paragraph" }] };
7963
8000
  }
7964
- const sharedExtensions = getSharedExtensions();
8001
+ const sharedExtensions = getSharedExtensions(options);
7965
8002
  const extensions = [...sharedExtensions, BaseFigure, TableKit2, BaseCodeBlock];
7966
8003
  try {
7967
8004
  return generateJSON(content, extensions);