@tnd028/strapi-plugin-tiptap-editor 0.0.1 → 0.0.2
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/_chunks/{Alignment-qMOzO-n2.mjs → Alignment-BTrqlTTh.mjs} +1 -1
- package/dist/_chunks/{Alignment-B0f2-LO0.js → Alignment-hS-tTWuJ.js} +1 -1
- package/dist/_chunks/{Blockquote-9wBGDz3L.mjs → Blockquote-DJUK1-BE.mjs} +1 -1
- package/dist/_chunks/{Blockquote-DeGUfK27.js → Blockquote-xNUeALuh.js} +1 -1
- package/dist/_chunks/{Bold-C-0g6Ayd.mjs → Bold-ByaAbROo.mjs} +1 -1
- package/dist/_chunks/{Bold-ClnPsPHt.js → Bold-CueKtObk.js} +1 -1
- package/dist/_chunks/{ColorAndHighlight-t1Ui5tcL.mjs → ColorAndHighlight-D53O4qn1.mjs} +6 -2
- package/dist/_chunks/{ColorAndHighlight-BMmtoSpj.js → ColorAndHighlight-DW64XLWJ.js} +6 -2
- package/dist/_chunks/CustomCard-DnOBubyS.mjs +151 -0
- package/dist/_chunks/CustomCard-pj8tTTbU.js +153 -0
- package/dist/_chunks/{Emoji-C-LQZ4Z3.js → Emoji-CEoQDS_x.js} +1 -1
- package/dist/_chunks/{Emoji-Bm1_vSh5.mjs → Emoji-CSN4sPHu.mjs} +1 -1
- package/dist/_chunks/{Heading-BDJqd1Qw.js → Heading-DMpM8l4P.js} +1 -1
- package/dist/_chunks/{Heading-BycRob5M.mjs → Heading-DV6F-wwl.mjs} +1 -1
- package/dist/_chunks/{HorizontalRule-CJlDmdma.js → HorizontalRule-BkDBP3Sn.js} +1 -1
- package/dist/_chunks/{HorizontalRule-CzQCeC3b.mjs → HorizontalRule-duJS5mkv.mjs} +1 -1
- package/dist/_chunks/{Iframe-DCBWSb0v.mjs → Iframe-BrjBTqYD.mjs} +1 -1
- package/dist/_chunks/{Iframe-Dyn_2cMB.js → Iframe-jTxffChk.js} +1 -1
- package/dist/_chunks/{ImagePlaceholder-DtrSuhf_.mjs → ImagePlaceholder-CYDho-h0.mjs} +1 -1
- package/dist/_chunks/{ImagePlaceholder-C14kojd5.js → ImagePlaceholder-Da68VBcm.js} +1 -1
- package/dist/_chunks/{Italic-BfpKX0KX.mjs → Italic-C0EqNpkt.mjs} +1 -1
- package/dist/_chunks/{Italic-DdhVL78v.js → Italic-DxsFIMhE.js} +1 -1
- package/dist/_chunks/{Link-DUV5Ybep.mjs → Link-CIkiGBxD.mjs} +1 -1
- package/dist/_chunks/{Link-BuYDqSqo.js → Link-u4PGWt-U.js} +1 -1
- package/dist/_chunks/{Lists-DsKxj3MD.mjs → Lists-B6BSkd5d.mjs} +1 -1
- package/dist/_chunks/{Lists-BKopoFR6.js → Lists-Bv_GF1oJ.js} +1 -1
- package/dist/_chunks/{Redo-1mEX1yOd.js → Redo-DUNTAtjb.js} +1 -1
- package/dist/_chunks/{Redo-Ca3VQxSe.mjs → Redo-De5pQoO6.mjs} +1 -1
- package/dist/_chunks/{SearchAndReplace-DzNdbTWJ.js → SearchAndReplace-DtSE0ubu.js} +1 -1
- package/dist/_chunks/{SearchAndReplace-DmU5DlWv.mjs → SearchAndReplace-QP8H8yFv.mjs} +1 -1
- package/dist/_chunks/{Strikethrough-BygxCHak.mjs → Strikethrough-BsanR8PL.mjs} +1 -1
- package/dist/_chunks/{Strikethrough-DQfR4OFk.js → Strikethrough-DoetuFNk.js} +1 -1
- package/dist/_chunks/{Table-DLaqBAbz.js → Table-B5VeLc9S.js} +1 -1
- package/dist/_chunks/{Table-BhbZ2Blv.mjs → Table-DevGt3tV.mjs} +1 -1
- package/dist/_chunks/{TiptapEditorInput-vfLsCt1p.js → TiptapEditorInput-CArezP4p.js} +96 -30
- package/dist/_chunks/{TiptapEditorInput-BDE09h5-.mjs → TiptapEditorInput-ChH1R_k4.mjs} +96 -30
- package/dist/_chunks/{Undo-BuT4OkoE.js → Undo-Bp_GQXYz.js} +1 -1
- package/dist/_chunks/{Undo-PL5n4axf.mjs → Undo-D7dSauIG.mjs} +1 -1
- package/dist/_chunks/{index-ku90UbIF.mjs → index-2RQ7z9sc.mjs} +9 -3
- package/dist/_chunks/{index-wYDv8vsJ.js → index-B6IeUCyh.js} +9 -3
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +1 -1
- package/dist/admin/src/components/editor/partials/ToolbarButtons.d.ts +1 -0
- package/dist/admin/src/components/editor/toolbars/CustomCard.d.ts +4 -0
- package/dist/admin/src/types.d.ts +1 -1
- package/dist/server/index.js +10 -4
- package/dist/server/index.mjs +10 -4
- package/package.json +2 -2
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
2
|
import { Table2, Table, ArrowUp, ArrowDown, ArrowLeft, ArrowRight, Rows3, Columns3, Trash2 } from "lucide-react";
|
|
3
3
|
import styled from "styled-components";
|
|
4
|
-
import { u as useEditorContext, D as DropdownMenu, a as DropdownMenuTrigger, T as ToolbarButton, b as DropdownMenuContent, c as DropdownMenuGroup, d as DropdownMenuItem, g as TooltipContent } from "./TiptapEditorInput-
|
|
4
|
+
import { u as useEditorContext, D as DropdownMenu, a as DropdownMenuTrigger, T as ToolbarButton, b as DropdownMenuContent, c as DropdownMenuGroup, d as DropdownMenuItem, g as TooltipContent } from "./TiptapEditorInput-ChH1R_k4.mjs";
|
|
5
5
|
const IconWrapper = styled.span`
|
|
6
6
|
display: flex;
|
|
7
7
|
align-items: center;
|
|
@@ -46,7 +46,7 @@ const clsx = require("clsx");
|
|
|
46
46
|
const Heading = require("@tiptap/extension-heading");
|
|
47
47
|
const designSystem = require("@strapi/design-system");
|
|
48
48
|
const Suggestion = require("@tiptap/suggestion");
|
|
49
|
-
const index = require("./index-
|
|
49
|
+
const index = require("./index-B6IeUCyh.js");
|
|
50
50
|
const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
|
|
51
51
|
function _interopNamespace(e) {
|
|
52
52
|
if (e && e.__esModule) return e;
|
|
@@ -431,6 +431,61 @@ const Button = React.forwardRef(
|
|
|
431
431
|
}
|
|
432
432
|
);
|
|
433
433
|
Button.displayName = "Button";
|
|
434
|
+
function normalizeYoutubeToEmbed(raw) {
|
|
435
|
+
const input = (raw ?? "").trim();
|
|
436
|
+
if (!input) return input;
|
|
437
|
+
if (/^https?:\/\/(www\.)?youtube\.com\/embed\//i.test(input)) {
|
|
438
|
+
return input;
|
|
439
|
+
}
|
|
440
|
+
let url;
|
|
441
|
+
try {
|
|
442
|
+
url = new URL(input);
|
|
443
|
+
} catch {
|
|
444
|
+
return input;
|
|
445
|
+
}
|
|
446
|
+
const host = url.hostname.replace(/^www\./i, "").toLowerCase();
|
|
447
|
+
const isYoutubeHost = host === "youtube.com" || host === "m.youtube.com";
|
|
448
|
+
const isYoutuBeHost = host === "youtu.be";
|
|
449
|
+
if (!isYoutubeHost && !isYoutuBeHost) return input;
|
|
450
|
+
let videoId = null;
|
|
451
|
+
if (isYoutuBeHost) {
|
|
452
|
+
videoId = url.pathname.split("/").filter(Boolean)[0] ?? null;
|
|
453
|
+
} else {
|
|
454
|
+
const pathname = url.pathname;
|
|
455
|
+
if (pathname === "/watch") {
|
|
456
|
+
videoId = url.searchParams.get("v");
|
|
457
|
+
} else if (pathname.startsWith("/shorts/")) {
|
|
458
|
+
videoId = pathname.split("/").filter(Boolean)[1] ?? null;
|
|
459
|
+
} else if (pathname.startsWith("/live/")) {
|
|
460
|
+
videoId = pathname.split("/").filter(Boolean)[1] ?? null;
|
|
461
|
+
} else if (pathname.startsWith("/embed/")) {
|
|
462
|
+
videoId = pathname.split("/").filter(Boolean)[1] ?? null;
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
if (!videoId) return input;
|
|
466
|
+
const embed = new URL(`https://www.youtube.com/embed/${videoId}`);
|
|
467
|
+
const list = url.searchParams.get("list");
|
|
468
|
+
const start2 = url.searchParams.get("start") ?? url.searchParams.get("t");
|
|
469
|
+
if (list) embed.searchParams.set("list", list);
|
|
470
|
+
if (start2) {
|
|
471
|
+
const seconds = parseYoutubeTimeToSeconds(start2);
|
|
472
|
+
embed.searchParams.set("start", seconds != null ? String(seconds) : start2);
|
|
473
|
+
}
|
|
474
|
+
return embed.toString();
|
|
475
|
+
}
|
|
476
|
+
function parseYoutubeTimeToSeconds(value) {
|
|
477
|
+
const v = (value ?? "").trim();
|
|
478
|
+
if (!v) return null;
|
|
479
|
+
if (/^\d+$/.test(v)) return Number(v);
|
|
480
|
+
const match = v.match(/^(?:(\d+)h)?(?:(\d+)m)?(?:(\d+)s)?$/i);
|
|
481
|
+
if (!match) return null;
|
|
482
|
+
const [, h, m, s] = match;
|
|
483
|
+
const hours = h ? Number(h) : 0;
|
|
484
|
+
const minutes = m ? Number(m) : 0;
|
|
485
|
+
const seconds = s ? Number(s) : 0;
|
|
486
|
+
const total = hours * 3600 + minutes * 60 + seconds;
|
|
487
|
+
return Number.isFinite(total) && total > 0 ? total : null;
|
|
488
|
+
}
|
|
434
489
|
const Iframe = core.Node.create({
|
|
435
490
|
name: "iframe",
|
|
436
491
|
group: "block",
|
|
@@ -476,7 +531,10 @@ const Iframe = core.Node.create({
|
|
|
476
531
|
return {
|
|
477
532
|
setIframe: (options) => ({ tr, dispatch }) => {
|
|
478
533
|
const { selection } = tr;
|
|
479
|
-
const node = this.type.create(
|
|
534
|
+
const node = this.type.create({
|
|
535
|
+
...options,
|
|
536
|
+
src: normalizeYoutubeToEmbed(options.src)
|
|
537
|
+
});
|
|
480
538
|
if (dispatch) {
|
|
481
539
|
tr.replaceRangeWith(selection.from, selection.to, node);
|
|
482
540
|
}
|
|
@@ -492,7 +550,7 @@ function TiptapIframeComponent({ node, selected, deleteNode, updateAttributes })
|
|
|
492
550
|
const [isEditing, setIsEditing] = React.useState(false);
|
|
493
551
|
const [tempSrc, setTempSrc] = React.useState(node.attrs.src || "");
|
|
494
552
|
const handleSave = () => {
|
|
495
|
-
updateAttributes({ src: tempSrc });
|
|
553
|
+
updateAttributes({ src: normalizeYoutubeToEmbed(tempSrc) });
|
|
496
554
|
setIsEditing(false);
|
|
497
555
|
};
|
|
498
556
|
return /* @__PURE__ */ jsxRuntime.jsxs(IframeWrapper, { $selected: selected, children: [
|
|
@@ -551,7 +609,6 @@ const IframeWrapper = styled__default.default(react.NodeViewWrapper)`
|
|
|
551
609
|
width: 100%;
|
|
552
610
|
min-height: 300px;
|
|
553
611
|
border: none;
|
|
554
|
-
border-radius: 4px;
|
|
555
612
|
}
|
|
556
613
|
|
|
557
614
|
input {
|
|
@@ -570,7 +627,6 @@ const Placeholder = styled__default.default.div`
|
|
|
570
627
|
color: #999;
|
|
571
628
|
font-style: italic;
|
|
572
629
|
background: #fafafa;
|
|
573
|
-
border-radius: 4px;
|
|
574
630
|
`;
|
|
575
631
|
function safelyResetPointerEvents(delay = 100) {
|
|
576
632
|
requestAnimationFrame(() => {
|
|
@@ -1814,92 +1870,97 @@ const StyledSeparator = styled__default.default(Separator)`
|
|
|
1814
1870
|
`;
|
|
1815
1871
|
const ToolbarDefinitions = {
|
|
1816
1872
|
// === GRUP 1: HEADING & TEXT STYLE ===
|
|
1873
|
+
customCard: React.lazy(
|
|
1874
|
+
() => Promise.resolve().then(() => require("./CustomCard-pj8tTTbU.js")).then((mod) => ({
|
|
1875
|
+
default: mod.CustomCardToolbar
|
|
1876
|
+
}))
|
|
1877
|
+
),
|
|
1817
1878
|
heading: React.lazy(
|
|
1818
|
-
() => Promise.resolve().then(() => require("./Heading-
|
|
1879
|
+
() => Promise.resolve().then(() => require("./Heading-DMpM8l4P.js")).then((mod) => ({
|
|
1819
1880
|
default: mod.HeadingToolbar
|
|
1820
1881
|
}))
|
|
1821
1882
|
),
|
|
1822
1883
|
bold: React.lazy(
|
|
1823
|
-
() => Promise.resolve().then(() => require("./Bold-
|
|
1884
|
+
() => Promise.resolve().then(() => require("./Bold-CueKtObk.js")).then((mod) => ({
|
|
1824
1885
|
default: mod.BoldToolbar
|
|
1825
1886
|
}))
|
|
1826
1887
|
),
|
|
1827
1888
|
italic: React.lazy(
|
|
1828
|
-
() => Promise.resolve().then(() => require("./Italic-
|
|
1889
|
+
() => Promise.resolve().then(() => require("./Italic-DxsFIMhE.js")).then((mod) => ({
|
|
1829
1890
|
default: mod.ItalicToolbar
|
|
1830
1891
|
}))
|
|
1831
1892
|
),
|
|
1832
1893
|
strikethrough: React.lazy(
|
|
1833
|
-
() => Promise.resolve().then(() => require("./Strikethrough-
|
|
1894
|
+
() => Promise.resolve().then(() => require("./Strikethrough-DoetuFNk.js")).then((mod) => ({
|
|
1834
1895
|
default: mod.StrikeThroughToolbar
|
|
1835
1896
|
}))
|
|
1836
1897
|
),
|
|
1837
1898
|
// === GRUP 2: LISTS & INDENTATION ===
|
|
1838
1899
|
lists: React.lazy(
|
|
1839
|
-
() => Promise.resolve().then(() => require("./Lists-
|
|
1900
|
+
() => Promise.resolve().then(() => require("./Lists-Bv_GF1oJ.js")).then((mod) => ({
|
|
1840
1901
|
default: mod.ListsToolbar
|
|
1841
1902
|
}))
|
|
1842
1903
|
),
|
|
1843
1904
|
blockquote: React.lazy(
|
|
1844
|
-
() => Promise.resolve().then(() => require("./Blockquote-
|
|
1905
|
+
() => Promise.resolve().then(() => require("./Blockquote-xNUeALuh.js")).then((mod) => ({
|
|
1845
1906
|
default: mod.BlockquoteToolbar
|
|
1846
1907
|
}))
|
|
1847
1908
|
),
|
|
1848
1909
|
// === GRUP 3: ALIGNMENT & FORMATTING ===
|
|
1849
1910
|
alignment: React.lazy(
|
|
1850
|
-
() => Promise.resolve().then(() => require("./Alignment-
|
|
1911
|
+
() => Promise.resolve().then(() => require("./Alignment-hS-tTWuJ.js")).then((mod) => ({
|
|
1851
1912
|
default: mod.AlignmentToolbar
|
|
1852
1913
|
}))
|
|
1853
1914
|
),
|
|
1854
1915
|
horizontalRule: React.lazy(
|
|
1855
|
-
() => Promise.resolve().then(() => require("./HorizontalRule-
|
|
1916
|
+
() => Promise.resolve().then(() => require("./HorizontalRule-BkDBP3Sn.js")).then((mod) => ({
|
|
1856
1917
|
default: mod.HorizontalRuleToolbar
|
|
1857
1918
|
}))
|
|
1858
1919
|
),
|
|
1859
1920
|
color: React.lazy(
|
|
1860
|
-
() => Promise.resolve().then(() => require("./ColorAndHighlight-
|
|
1921
|
+
() => Promise.resolve().then(() => require("./ColorAndHighlight-DW64XLWJ.js")).then((mod) => ({
|
|
1861
1922
|
default: mod.ColorAndHighlightToolbar
|
|
1862
1923
|
}))
|
|
1863
1924
|
),
|
|
1864
1925
|
// === GRUP 4: MEDIA & LINKS ===
|
|
1865
1926
|
link: React.lazy(
|
|
1866
|
-
() => Promise.resolve().then(() => require("./Link-
|
|
1927
|
+
() => Promise.resolve().then(() => require("./Link-u4PGWt-U.js")).then((mod) => ({
|
|
1867
1928
|
default: mod.LinkToolbar
|
|
1868
1929
|
}))
|
|
1869
1930
|
),
|
|
1870
1931
|
image: React.lazy(
|
|
1871
|
-
() => Promise.resolve().then(() => require("./ImagePlaceholder-
|
|
1932
|
+
() => Promise.resolve().then(() => require("./ImagePlaceholder-Da68VBcm.js")).then((mod) => ({
|
|
1872
1933
|
default: mod.ImagePlaceholderToolbar
|
|
1873
1934
|
}))
|
|
1874
1935
|
),
|
|
1875
1936
|
emoji: React.lazy(
|
|
1876
|
-
() => Promise.resolve().then(() => require("./Emoji-
|
|
1937
|
+
() => Promise.resolve().then(() => require("./Emoji-CEoQDS_x.js")).then((mod) => ({
|
|
1877
1938
|
default: mod.EmojiToolbar
|
|
1878
1939
|
}))
|
|
1879
1940
|
),
|
|
1880
1941
|
table: React.lazy(
|
|
1881
|
-
() => Promise.resolve().then(() => require("./Table-
|
|
1942
|
+
() => Promise.resolve().then(() => require("./Table-B5VeLc9S.js")).then((mod) => ({
|
|
1882
1943
|
default: mod.TableToolbar
|
|
1883
1944
|
}))
|
|
1884
1945
|
),
|
|
1885
1946
|
iframe: React.lazy(
|
|
1886
|
-
() => Promise.resolve().then(() => require("./Iframe-
|
|
1947
|
+
() => Promise.resolve().then(() => require("./Iframe-jTxffChk.js")).then((mod) => ({
|
|
1887
1948
|
default: mod.IframeToolbar
|
|
1888
1949
|
}))
|
|
1889
1950
|
),
|
|
1890
1951
|
// === GRUP 5: UTILS ===
|
|
1891
1952
|
undo: React.lazy(
|
|
1892
|
-
() => Promise.resolve().then(() => require("./Undo-
|
|
1953
|
+
() => Promise.resolve().then(() => require("./Undo-Bp_GQXYz.js")).then((mod) => ({
|
|
1893
1954
|
default: mod.UndoToolbar
|
|
1894
1955
|
}))
|
|
1895
1956
|
),
|
|
1896
1957
|
redo: React.lazy(
|
|
1897
|
-
() => Promise.resolve().then(() => require("./Redo-
|
|
1958
|
+
() => Promise.resolve().then(() => require("./Redo-DUNTAtjb.js")).then((mod) => ({
|
|
1898
1959
|
default: mod.RedoToolbar
|
|
1899
1960
|
}))
|
|
1900
1961
|
),
|
|
1901
1962
|
searchAndReplace: React.lazy(
|
|
1902
|
-
() => Promise.resolve().then(() => require("./SearchAndReplace-
|
|
1963
|
+
() => Promise.resolve().then(() => require("./SearchAndReplace-DtSE0ubu.js")).then((mod) => ({
|
|
1903
1964
|
default: mod.SearchAndReplaceToolbar
|
|
1904
1965
|
}))
|
|
1905
1966
|
)
|
|
@@ -2619,9 +2680,13 @@ const createExtensions = () => [
|
|
|
2619
2680
|
TextStyle__default.default
|
|
2620
2681
|
];
|
|
2621
2682
|
const getOutput = (editor, output) => {
|
|
2622
|
-
{
|
|
2683
|
+
if (output === "html") {
|
|
2684
|
+
return editor.getHTML();
|
|
2685
|
+
}
|
|
2686
|
+
if (output === "json") {
|
|
2623
2687
|
return editor.getJSON();
|
|
2624
2688
|
}
|
|
2689
|
+
return editor.getText();
|
|
2625
2690
|
};
|
|
2626
2691
|
const useEditor = ({
|
|
2627
2692
|
content,
|
|
@@ -2640,7 +2705,7 @@ const useEditor = ({
|
|
|
2640
2705
|
}, throttleDelay);
|
|
2641
2706
|
const handleUpdate = React.useCallback(
|
|
2642
2707
|
(editor2) => {
|
|
2643
|
-
return throttledSetValue(getOutput(editor2));
|
|
2708
|
+
return throttledSetValue(getOutput(editor2, output));
|
|
2644
2709
|
},
|
|
2645
2710
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
2646
2711
|
[output]
|
|
@@ -2654,7 +2719,7 @@ const useEditor = ({
|
|
|
2654
2719
|
[value]
|
|
2655
2720
|
);
|
|
2656
2721
|
const handleBlur = React.useCallback(
|
|
2657
|
-
(editor2) => onBlur?.(getOutput(editor2)),
|
|
2722
|
+
(editor2) => onBlur?.(getOutput(editor2, output)),
|
|
2658
2723
|
[output, onBlur]
|
|
2659
2724
|
);
|
|
2660
2725
|
const editor = react.useEditor({
|
|
@@ -3500,7 +3565,7 @@ const BaseEditor = React.forwardRef(
|
|
|
3500
3565
|
onUpdate: onChange,
|
|
3501
3566
|
value,
|
|
3502
3567
|
editable: !disabled,
|
|
3503
|
-
output: "
|
|
3568
|
+
output: options.output ?? "html"
|
|
3504
3569
|
});
|
|
3505
3570
|
React.useImperativeHandle(ref, () => editor, [editor]);
|
|
3506
3571
|
if (!editor) {
|
|
@@ -3708,7 +3773,7 @@ const CustomComponentRenderer = (props) => {
|
|
|
3708
3773
|
}
|
|
3709
3774
|
};
|
|
3710
3775
|
return /* @__PURE__ */ jsxRuntime.jsxs(Wrapper, { $selected: selected, children: [
|
|
3711
|
-
/* @__PURE__ */ jsxRuntime.jsx(Badge, { $type: node.attrs.type, children: node.attrs.type
|
|
3776
|
+
/* @__PURE__ */ jsxRuntime.jsx(Badge, { $type: node.attrs.type, children: node.attrs.type?.replace("custom", "") }),
|
|
3712
3777
|
renderPreview(),
|
|
3713
3778
|
editor.isEditable && /* @__PURE__ */ jsxRuntime.jsxs(Toolbar, { children: [
|
|
3714
3779
|
/* @__PURE__ */ jsxRuntime.jsx("button", { onClick: handleEdit, style: { width: 28, height: 28, border: "1px solid #ddd", borderRadius: 4, background: "white", display: "flex", alignItems: "center", justifyContent: "center" }, children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Edit3, { size: 14 }) }),
|
|
@@ -6595,7 +6660,8 @@ function ContentEditor({
|
|
|
6595
6660
|
"table",
|
|
6596
6661
|
"image",
|
|
6597
6662
|
"iframe",
|
|
6598
|
-
"emoji"
|
|
6663
|
+
"emoji",
|
|
6664
|
+
"customCard"
|
|
6599
6665
|
// "HTMLToolbar"
|
|
6600
6666
|
],
|
|
6601
6667
|
extensions = [],
|
|
@@ -6698,7 +6764,7 @@ const ContentEditorInput = React__default.default.memo(React__default.default.fo
|
|
|
6698
6764
|
target: {
|
|
6699
6765
|
name,
|
|
6700
6766
|
value: content,
|
|
6701
|
-
type: "
|
|
6767
|
+
type: "text"
|
|
6702
6768
|
}
|
|
6703
6769
|
};
|
|
6704
6770
|
onChange(evt);
|
|
@@ -6789,7 +6855,7 @@ const TextEditorInput = React__default.default.memo(React__default.default.forwa
|
|
|
6789
6855
|
target: {
|
|
6790
6856
|
name,
|
|
6791
6857
|
value: content,
|
|
6792
|
-
type: "
|
|
6858
|
+
type: "text"
|
|
6793
6859
|
}
|
|
6794
6860
|
};
|
|
6795
6861
|
onChange(evt);
|
|
@@ -45,7 +45,7 @@ import { clsx } from "clsx";
|
|
|
45
45
|
import Heading from "@tiptap/extension-heading";
|
|
46
46
|
import { Checkbox, Field, Flex } from "@strapi/design-system";
|
|
47
47
|
import Suggestion from "@tiptap/suggestion";
|
|
48
|
-
import { g as getPluginConfig } from "./index-
|
|
48
|
+
import { g as getPluginConfig } from "./index-2RQ7z9sc.mjs";
|
|
49
49
|
const validateFileOrBase64 = (input, options, originalFile, validFiles, errors) => {
|
|
50
50
|
const { isValidType, isValidSize } = checkTypeAndSize(input, options);
|
|
51
51
|
if (isValidType && isValidSize) {
|
|
@@ -377,6 +377,61 @@ const Button = forwardRef(
|
|
|
377
377
|
}
|
|
378
378
|
);
|
|
379
379
|
Button.displayName = "Button";
|
|
380
|
+
function normalizeYoutubeToEmbed(raw) {
|
|
381
|
+
const input = (raw ?? "").trim();
|
|
382
|
+
if (!input) return input;
|
|
383
|
+
if (/^https?:\/\/(www\.)?youtube\.com\/embed\//i.test(input)) {
|
|
384
|
+
return input;
|
|
385
|
+
}
|
|
386
|
+
let url;
|
|
387
|
+
try {
|
|
388
|
+
url = new URL(input);
|
|
389
|
+
} catch {
|
|
390
|
+
return input;
|
|
391
|
+
}
|
|
392
|
+
const host = url.hostname.replace(/^www\./i, "").toLowerCase();
|
|
393
|
+
const isYoutubeHost = host === "youtube.com" || host === "m.youtube.com";
|
|
394
|
+
const isYoutuBeHost = host === "youtu.be";
|
|
395
|
+
if (!isYoutubeHost && !isYoutuBeHost) return input;
|
|
396
|
+
let videoId = null;
|
|
397
|
+
if (isYoutuBeHost) {
|
|
398
|
+
videoId = url.pathname.split("/").filter(Boolean)[0] ?? null;
|
|
399
|
+
} else {
|
|
400
|
+
const pathname = url.pathname;
|
|
401
|
+
if (pathname === "/watch") {
|
|
402
|
+
videoId = url.searchParams.get("v");
|
|
403
|
+
} else if (pathname.startsWith("/shorts/")) {
|
|
404
|
+
videoId = pathname.split("/").filter(Boolean)[1] ?? null;
|
|
405
|
+
} else if (pathname.startsWith("/live/")) {
|
|
406
|
+
videoId = pathname.split("/").filter(Boolean)[1] ?? null;
|
|
407
|
+
} else if (pathname.startsWith("/embed/")) {
|
|
408
|
+
videoId = pathname.split("/").filter(Boolean)[1] ?? null;
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
if (!videoId) return input;
|
|
412
|
+
const embed = new URL(`https://www.youtube.com/embed/${videoId}`);
|
|
413
|
+
const list = url.searchParams.get("list");
|
|
414
|
+
const start2 = url.searchParams.get("start") ?? url.searchParams.get("t");
|
|
415
|
+
if (list) embed.searchParams.set("list", list);
|
|
416
|
+
if (start2) {
|
|
417
|
+
const seconds = parseYoutubeTimeToSeconds(start2);
|
|
418
|
+
embed.searchParams.set("start", seconds != null ? String(seconds) : start2);
|
|
419
|
+
}
|
|
420
|
+
return embed.toString();
|
|
421
|
+
}
|
|
422
|
+
function parseYoutubeTimeToSeconds(value) {
|
|
423
|
+
const v = (value ?? "").trim();
|
|
424
|
+
if (!v) return null;
|
|
425
|
+
if (/^\d+$/.test(v)) return Number(v);
|
|
426
|
+
const match = v.match(/^(?:(\d+)h)?(?:(\d+)m)?(?:(\d+)s)?$/i);
|
|
427
|
+
if (!match) return null;
|
|
428
|
+
const [, h, m, s] = match;
|
|
429
|
+
const hours = h ? Number(h) : 0;
|
|
430
|
+
const minutes = m ? Number(m) : 0;
|
|
431
|
+
const seconds = s ? Number(s) : 0;
|
|
432
|
+
const total = hours * 3600 + minutes * 60 + seconds;
|
|
433
|
+
return Number.isFinite(total) && total > 0 ? total : null;
|
|
434
|
+
}
|
|
380
435
|
const Iframe = Node.create({
|
|
381
436
|
name: "iframe",
|
|
382
437
|
group: "block",
|
|
@@ -422,7 +477,10 @@ const Iframe = Node.create({
|
|
|
422
477
|
return {
|
|
423
478
|
setIframe: (options) => ({ tr, dispatch }) => {
|
|
424
479
|
const { selection } = tr;
|
|
425
|
-
const node = this.type.create(
|
|
480
|
+
const node = this.type.create({
|
|
481
|
+
...options,
|
|
482
|
+
src: normalizeYoutubeToEmbed(options.src)
|
|
483
|
+
});
|
|
426
484
|
if (dispatch) {
|
|
427
485
|
tr.replaceRangeWith(selection.from, selection.to, node);
|
|
428
486
|
}
|
|
@@ -438,7 +496,7 @@ function TiptapIframeComponent({ node, selected, deleteNode, updateAttributes })
|
|
|
438
496
|
const [isEditing, setIsEditing] = useState(false);
|
|
439
497
|
const [tempSrc, setTempSrc] = useState(node.attrs.src || "");
|
|
440
498
|
const handleSave = () => {
|
|
441
|
-
updateAttributes({ src: tempSrc });
|
|
499
|
+
updateAttributes({ src: normalizeYoutubeToEmbed(tempSrc) });
|
|
442
500
|
setIsEditing(false);
|
|
443
501
|
};
|
|
444
502
|
return /* @__PURE__ */ jsxs(IframeWrapper, { $selected: selected, children: [
|
|
@@ -497,7 +555,6 @@ const IframeWrapper = styled(NodeViewWrapper)`
|
|
|
497
555
|
width: 100%;
|
|
498
556
|
min-height: 300px;
|
|
499
557
|
border: none;
|
|
500
|
-
border-radius: 4px;
|
|
501
558
|
}
|
|
502
559
|
|
|
503
560
|
input {
|
|
@@ -516,7 +573,6 @@ const Placeholder = styled.div`
|
|
|
516
573
|
color: #999;
|
|
517
574
|
font-style: italic;
|
|
518
575
|
background: #fafafa;
|
|
519
|
-
border-radius: 4px;
|
|
520
576
|
`;
|
|
521
577
|
function safelyResetPointerEvents(delay = 100) {
|
|
522
578
|
requestAnimationFrame(() => {
|
|
@@ -1760,92 +1816,97 @@ const StyledSeparator = styled(Separator)`
|
|
|
1760
1816
|
`;
|
|
1761
1817
|
const ToolbarDefinitions = {
|
|
1762
1818
|
// === GRUP 1: HEADING & TEXT STYLE ===
|
|
1819
|
+
customCard: lazy(
|
|
1820
|
+
() => import("./CustomCard-DnOBubyS.mjs").then((mod) => ({
|
|
1821
|
+
default: mod.CustomCardToolbar
|
|
1822
|
+
}))
|
|
1823
|
+
),
|
|
1763
1824
|
heading: lazy(
|
|
1764
|
-
() => import("./Heading-
|
|
1825
|
+
() => import("./Heading-DV6F-wwl.mjs").then((mod) => ({
|
|
1765
1826
|
default: mod.HeadingToolbar
|
|
1766
1827
|
}))
|
|
1767
1828
|
),
|
|
1768
1829
|
bold: lazy(
|
|
1769
|
-
() => import("./Bold-
|
|
1830
|
+
() => import("./Bold-ByaAbROo.mjs").then((mod) => ({
|
|
1770
1831
|
default: mod.BoldToolbar
|
|
1771
1832
|
}))
|
|
1772
1833
|
),
|
|
1773
1834
|
italic: lazy(
|
|
1774
|
-
() => import("./Italic-
|
|
1835
|
+
() => import("./Italic-C0EqNpkt.mjs").then((mod) => ({
|
|
1775
1836
|
default: mod.ItalicToolbar
|
|
1776
1837
|
}))
|
|
1777
1838
|
),
|
|
1778
1839
|
strikethrough: lazy(
|
|
1779
|
-
() => import("./Strikethrough-
|
|
1840
|
+
() => import("./Strikethrough-BsanR8PL.mjs").then((mod) => ({
|
|
1780
1841
|
default: mod.StrikeThroughToolbar
|
|
1781
1842
|
}))
|
|
1782
1843
|
),
|
|
1783
1844
|
// === GRUP 2: LISTS & INDENTATION ===
|
|
1784
1845
|
lists: lazy(
|
|
1785
|
-
() => import("./Lists-
|
|
1846
|
+
() => import("./Lists-B6BSkd5d.mjs").then((mod) => ({
|
|
1786
1847
|
default: mod.ListsToolbar
|
|
1787
1848
|
}))
|
|
1788
1849
|
),
|
|
1789
1850
|
blockquote: lazy(
|
|
1790
|
-
() => import("./Blockquote-
|
|
1851
|
+
() => import("./Blockquote-DJUK1-BE.mjs").then((mod) => ({
|
|
1791
1852
|
default: mod.BlockquoteToolbar
|
|
1792
1853
|
}))
|
|
1793
1854
|
),
|
|
1794
1855
|
// === GRUP 3: ALIGNMENT & FORMATTING ===
|
|
1795
1856
|
alignment: lazy(
|
|
1796
|
-
() => import("./Alignment-
|
|
1857
|
+
() => import("./Alignment-BTrqlTTh.mjs").then((mod) => ({
|
|
1797
1858
|
default: mod.AlignmentToolbar
|
|
1798
1859
|
}))
|
|
1799
1860
|
),
|
|
1800
1861
|
horizontalRule: lazy(
|
|
1801
|
-
() => import("./HorizontalRule-
|
|
1862
|
+
() => import("./HorizontalRule-duJS5mkv.mjs").then((mod) => ({
|
|
1802
1863
|
default: mod.HorizontalRuleToolbar
|
|
1803
1864
|
}))
|
|
1804
1865
|
),
|
|
1805
1866
|
color: lazy(
|
|
1806
|
-
() => import("./ColorAndHighlight-
|
|
1867
|
+
() => import("./ColorAndHighlight-D53O4qn1.mjs").then((mod) => ({
|
|
1807
1868
|
default: mod.ColorAndHighlightToolbar
|
|
1808
1869
|
}))
|
|
1809
1870
|
),
|
|
1810
1871
|
// === GRUP 4: MEDIA & LINKS ===
|
|
1811
1872
|
link: lazy(
|
|
1812
|
-
() => import("./Link-
|
|
1873
|
+
() => import("./Link-CIkiGBxD.mjs").then((mod) => ({
|
|
1813
1874
|
default: mod.LinkToolbar
|
|
1814
1875
|
}))
|
|
1815
1876
|
),
|
|
1816
1877
|
image: lazy(
|
|
1817
|
-
() => import("./ImagePlaceholder-
|
|
1878
|
+
() => import("./ImagePlaceholder-CYDho-h0.mjs").then((mod) => ({
|
|
1818
1879
|
default: mod.ImagePlaceholderToolbar
|
|
1819
1880
|
}))
|
|
1820
1881
|
),
|
|
1821
1882
|
emoji: lazy(
|
|
1822
|
-
() => import("./Emoji-
|
|
1883
|
+
() => import("./Emoji-CSN4sPHu.mjs").then((mod) => ({
|
|
1823
1884
|
default: mod.EmojiToolbar
|
|
1824
1885
|
}))
|
|
1825
1886
|
),
|
|
1826
1887
|
table: lazy(
|
|
1827
|
-
() => import("./Table-
|
|
1888
|
+
() => import("./Table-DevGt3tV.mjs").then((mod) => ({
|
|
1828
1889
|
default: mod.TableToolbar
|
|
1829
1890
|
}))
|
|
1830
1891
|
),
|
|
1831
1892
|
iframe: lazy(
|
|
1832
|
-
() => import("./Iframe-
|
|
1893
|
+
() => import("./Iframe-BrjBTqYD.mjs").then((mod) => ({
|
|
1833
1894
|
default: mod.IframeToolbar
|
|
1834
1895
|
}))
|
|
1835
1896
|
),
|
|
1836
1897
|
// === GRUP 5: UTILS ===
|
|
1837
1898
|
undo: lazy(
|
|
1838
|
-
() => import("./Undo-
|
|
1899
|
+
() => import("./Undo-D7dSauIG.mjs").then((mod) => ({
|
|
1839
1900
|
default: mod.UndoToolbar
|
|
1840
1901
|
}))
|
|
1841
1902
|
),
|
|
1842
1903
|
redo: lazy(
|
|
1843
|
-
() => import("./Redo-
|
|
1904
|
+
() => import("./Redo-De5pQoO6.mjs").then((mod) => ({
|
|
1844
1905
|
default: mod.RedoToolbar
|
|
1845
1906
|
}))
|
|
1846
1907
|
),
|
|
1847
1908
|
searchAndReplace: lazy(
|
|
1848
|
-
() => import("./SearchAndReplace-
|
|
1909
|
+
() => import("./SearchAndReplace-QP8H8yFv.mjs").then((mod) => ({
|
|
1849
1910
|
default: mod.SearchAndReplaceToolbar
|
|
1850
1911
|
}))
|
|
1851
1912
|
)
|
|
@@ -2565,9 +2626,13 @@ const createExtensions = () => [
|
|
|
2565
2626
|
TextStyle
|
|
2566
2627
|
];
|
|
2567
2628
|
const getOutput = (editor, output) => {
|
|
2568
|
-
{
|
|
2629
|
+
if (output === "html") {
|
|
2630
|
+
return editor.getHTML();
|
|
2631
|
+
}
|
|
2632
|
+
if (output === "json") {
|
|
2569
2633
|
return editor.getJSON();
|
|
2570
2634
|
}
|
|
2635
|
+
return editor.getText();
|
|
2571
2636
|
};
|
|
2572
2637
|
const useEditor = ({
|
|
2573
2638
|
content,
|
|
@@ -2586,7 +2651,7 @@ const useEditor = ({
|
|
|
2586
2651
|
}, throttleDelay);
|
|
2587
2652
|
const handleUpdate = useCallback(
|
|
2588
2653
|
(editor2) => {
|
|
2589
|
-
return throttledSetValue(getOutput(editor2));
|
|
2654
|
+
return throttledSetValue(getOutput(editor2, output));
|
|
2590
2655
|
},
|
|
2591
2656
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
2592
2657
|
[output]
|
|
@@ -2600,7 +2665,7 @@ const useEditor = ({
|
|
|
2600
2665
|
[value]
|
|
2601
2666
|
);
|
|
2602
2667
|
const handleBlur = useCallback(
|
|
2603
|
-
(editor2) => onBlur?.(getOutput(editor2)),
|
|
2668
|
+
(editor2) => onBlur?.(getOutput(editor2, output)),
|
|
2604
2669
|
[output, onBlur]
|
|
2605
2670
|
);
|
|
2606
2671
|
const editor = useEditor$1({
|
|
@@ -3446,7 +3511,7 @@ const BaseEditor = forwardRef(
|
|
|
3446
3511
|
onUpdate: onChange,
|
|
3447
3512
|
value,
|
|
3448
3513
|
editable: !disabled,
|
|
3449
|
-
output: "
|
|
3514
|
+
output: options.output ?? "html"
|
|
3450
3515
|
});
|
|
3451
3516
|
useImperativeHandle(ref, () => editor, [editor]);
|
|
3452
3517
|
if (!editor) {
|
|
@@ -3654,7 +3719,7 @@ const CustomComponentRenderer = (props) => {
|
|
|
3654
3719
|
}
|
|
3655
3720
|
};
|
|
3656
3721
|
return /* @__PURE__ */ jsxs(Wrapper, { $selected: selected, children: [
|
|
3657
|
-
/* @__PURE__ */ jsx(Badge, { $type: node.attrs.type, children: node.attrs.type
|
|
3722
|
+
/* @__PURE__ */ jsx(Badge, { $type: node.attrs.type, children: node.attrs.type?.replace("custom", "") }),
|
|
3658
3723
|
renderPreview(),
|
|
3659
3724
|
editor.isEditable && /* @__PURE__ */ jsxs(Toolbar, { children: [
|
|
3660
3725
|
/* @__PURE__ */ jsx("button", { onClick: handleEdit, style: { width: 28, height: 28, border: "1px solid #ddd", borderRadius: 4, background: "white", display: "flex", alignItems: "center", justifyContent: "center" }, children: /* @__PURE__ */ jsx(Edit3, { size: 14 }) }),
|
|
@@ -6541,7 +6606,8 @@ function ContentEditor({
|
|
|
6541
6606
|
"table",
|
|
6542
6607
|
"image",
|
|
6543
6608
|
"iframe",
|
|
6544
|
-
"emoji"
|
|
6609
|
+
"emoji",
|
|
6610
|
+
"customCard"
|
|
6545
6611
|
// "HTMLToolbar"
|
|
6546
6612
|
],
|
|
6547
6613
|
extensions = [],
|
|
@@ -6644,7 +6710,7 @@ const ContentEditorInput = React.memo(React.forwardRef(
|
|
|
6644
6710
|
target: {
|
|
6645
6711
|
name,
|
|
6646
6712
|
value: content,
|
|
6647
|
-
type: "
|
|
6713
|
+
type: "text"
|
|
6648
6714
|
}
|
|
6649
6715
|
};
|
|
6650
6716
|
onChange(evt);
|
|
@@ -6735,7 +6801,7 @@ const TextEditorInput = React.memo(React.forwardRef(
|
|
|
6735
6801
|
target: {
|
|
6736
6802
|
name,
|
|
6737
6803
|
value: content,
|
|
6738
|
-
type: "
|
|
6804
|
+
type: "text"
|
|
6739
6805
|
}
|
|
6740
6806
|
};
|
|
6741
6807
|
onChange(evt);
|
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
|
3
3
|
const jsxRuntime = require("react/jsx-runtime");
|
|
4
4
|
const React = require("react");
|
|
5
5
|
const lucideReact = require("lucide-react");
|
|
6
|
-
const TiptapEditorInput = require("./TiptapEditorInput-
|
|
6
|
+
const TiptapEditorInput = require("./TiptapEditorInput-CArezP4p.js");
|
|
7
7
|
const styled = require("styled-components");
|
|
8
8
|
const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
|
|
9
9
|
const styled__default = /* @__PURE__ */ _interopDefault(styled);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx } from "react/jsx-runtime";
|
|
2
2
|
import { forwardRef } from "react";
|
|
3
3
|
import { Undo2 } from "lucide-react";
|
|
4
|
-
import { u as useEditorContext, T as ToolbarButton } from "./TiptapEditorInput-
|
|
4
|
+
import { u as useEditorContext, T as ToolbarButton } from "./TiptapEditorInput-ChH1R_k4.mjs";
|
|
5
5
|
import styled from "styled-components";
|
|
6
6
|
const UndoIcon = styled(Undo2)`
|
|
7
7
|
width: 16px;
|
|
@@ -1031,11 +1031,17 @@ const colors = css`
|
|
|
1031
1031
|
--tiptap-color-body: ${theme.colors.neutral800};
|
|
1032
1032
|
--tiptap-color-heading: ${theme.colors.neutral900};
|
|
1033
1033
|
--tiptap-color-muted: ${theme.colors.neutral500};
|
|
1034
|
+
--tiptap-color-muted-2: ${theme.colors.neutral600};
|
|
1034
1035
|
--tiptap-color-border: ${theme.colors.neutral200};
|
|
1035
1036
|
--tiptap-color-bg: ${theme.colors.neutral0};
|
|
1036
1037
|
--tiptap-color-code-bg: ${theme.colors.neutral100};
|
|
1037
1038
|
--tiptap-color-primary: ${theme.colors.primary600};
|
|
1038
1039
|
--tiptap-color-ring: ${theme.colors.primary200};
|
|
1040
|
+
|
|
1041
|
+
/* Speaker card helpers */
|
|
1042
|
+
--tiptap-color-danger: ${theme.colors.danger500};
|
|
1043
|
+
--tiptap-color-desc-bg: ${theme.colors.primary700 ?? theme.colors.primary600};
|
|
1044
|
+
--tiptap-color-desc-fg: ${theme.colors.neutral0};
|
|
1039
1045
|
}
|
|
1040
1046
|
`}
|
|
1041
1047
|
`;
|
|
@@ -1304,11 +1310,11 @@ const index = {
|
|
|
1304
1310
|
* @param app - The Strapi administration application instance.
|
|
1305
1311
|
*/
|
|
1306
1312
|
async register(app) {
|
|
1307
|
-
console.log("Registering Tiptap Editor plugin (
|
|
1313
|
+
console.log("Registering Tiptap Editor plugin (Tiptap)...");
|
|
1308
1314
|
app.customFields.register({
|
|
1309
1315
|
name: "tiptap",
|
|
1310
1316
|
pluginId: PLUGIN_ID,
|
|
1311
|
-
type: "
|
|
1317
|
+
type: "richtext",
|
|
1312
1318
|
intlLabel: {
|
|
1313
1319
|
id: `${PLUGIN_ID}.tiptap.label`,
|
|
1314
1320
|
defaultMessage: "Tiptap Editor"
|
|
@@ -1319,7 +1325,7 @@ const index = {
|
|
|
1319
1325
|
},
|
|
1320
1326
|
icon: PluginIcon,
|
|
1321
1327
|
components: {
|
|
1322
|
-
Input: async () => import("./TiptapEditorInput-
|
|
1328
|
+
Input: async () => import("./TiptapEditorInput-ChH1R_k4.mjs").then((n) => n.i)
|
|
1323
1329
|
},
|
|
1324
1330
|
options: {
|
|
1325
1331
|
base: [
|