@cyberyozh/text-editor 0.5.2 → 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 +9 -3
- 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/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
|
-
|
|
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
|
|
1551
|
-
if (typeof window === "undefined") return false;
|
|
1560
|
+
var hostnameOf = (url) => {
|
|
1552
1561
|
try {
|
|
1553
|
-
return new URL(url).hostname
|
|
1562
|
+
return new URL(url).hostname.toLowerCase();
|
|
1554
1563
|
} catch {
|
|
1555
|
-
return
|
|
1564
|
+
return null;
|
|
1556
1565
|
}
|
|
1557
1566
|
};
|
|
1558
|
-
var
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
});
|
|
1568
|
-
}
|
|
1569
|
-
|
|
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
|
|
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({
|
|
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/
|
|
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,
|
|
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" }] };
|