@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.d.mts +11 -0
- package/dist/editor.d.ts +11 -0
- package/dist/editor.js +93 -38
- package/dist/editor.js.map +1 -1
- package/dist/editor.mjs +93 -38
- package/dist/editor.mjs.map +1 -1
- package/dist/html.d.mts +28 -0
- package/dist/html.d.ts +28 -0
- package/dist/html.js +2803 -0
- package/dist/html.js.map +1 -0
- package/dist/html.mjs +2771 -0
- package/dist/html.mjs.map +1 -0
- package/dist/render.d.mts +5 -0
- package/dist/render.d.ts +5 -0
- package/dist/render.js +47 -40
- package/dist/render.js.map +1 -1
- package/dist/render.mjs +47 -40
- package/dist/render.mjs.map +1 -1
- package/package.json +7 -1
- package/src/editor/editor.tsx +8 -0
- package/src/extensions/base/code-block.test.ts +39 -0
- package/src/extensions/base/code-block.ts +15 -1
- package/src/extensions/base/link.test.ts +54 -1
- package/src/extensions/base/link.ts +47 -41
- package/src/extensions/editor/get-editor-extensions.ts +3 -1
- package/src/extensions/render/get-render-extensions.ts +6 -3
- package/src/html/html.test.ts +154 -0
- package/src/html/index.ts +29 -0
- package/src/utils/get-shared-extensions.ts +9 -1
- package/src/utils/html-to-tiptap-content.ts +5 -13
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
|
-
|
|
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
|
|
4293
|
-
if (typeof window === "undefined") return false;
|
|
4302
|
+
var hostnameOf = (url) => {
|
|
4294
4303
|
try {
|
|
4295
|
-
return new URL(url).hostname
|
|
4304
|
+
return new URL(url).hostname.toLowerCase();
|
|
4296
4305
|
} catch {
|
|
4297
|
-
return
|
|
4306
|
+
return null;
|
|
4298
4307
|
}
|
|
4299
4308
|
};
|
|
4300
|
-
var
|
|
4301
|
-
|
|
4302
|
-
|
|
4303
|
-
|
|
4304
|
-
|
|
4305
|
-
|
|
4306
|
-
|
|
4307
|
-
|
|
4308
|
-
|
|
4309
|
-
});
|
|
4310
|
-
}
|
|
4311
|
-
|
|
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
|
|
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({
|
|
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/
|
|
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,
|
|
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" }] };
|