reactjs-tiptap-editor
Version:
A modern WYSIWYG rich text editor based on tiptap and shadcn ui for React
427 lines (426 loc) • 12.7 kB
JavaScript
import { h as v, j as x, N as k, k as y, n as S, m as I } from "./clsx-DaPvp9ji.js";
import { jsxs as f, jsx as d, Fragment as P } from "react/jsx-runtime";
import { useState as M, useCallback as R } from "react";
import { Resizable as N } from "re-resizable";
import { g as l } from "./dom-dataset-CIEeltF6.js";
import { G as j, j as U, B as q, u as A, d as L, A as D } from "./index-RcSPeQHn.js";
import "./theme.js";
const m = {
youtube: {
example: "https://www.youtube.com/watch?v=I4sMhHbHYXM",
src: "https://www.youtube.com/embed/I4sMhHbHYXM",
srcPrefix: "https://www.youtube.com/embed",
linkRule: [
/(?:https?:\/\/)?(?:www\.)?(?:youtube\.com\/(?:[^\s/]+\/\S+\/|(?:v|e(?:mbed)?)\/|\S*?[&?]v=)|youtu\.be\/)([\w-]{11})/
]
},
youku: {
example: "https://v.youku.com/v_show/id_XNDM0NDM4MTcy.html?spm=a2h0c.8166622.PhoneSokuUgc_4.dtitle",
src: "https://player.youku.com/embed/XNDM0NDM4MTcy",
srcPrefix: "https://player.youku.com/embed",
linkRule: [String.raw`v.youku.com\/v_show\/id_\w+\=*`],
idRule: String.raw`id_\w+\=*`
},
bilibili: {
example: "https://www.bilibili.com/video/BV1EJ411u7DN",
src: "https://player.bilibili.com/player.html?bvid=BV1EJ411u7DN",
srcPrefix: "https://player.bilibili.com/player.html?bvid",
linkRule: [String.raw`www.bilibili.com\/video\/\w+`]
},
qqvideo: {
example: "https://v.qq.com/x/cover/mzc0020006aw1mn/u0033nvzb5v.html",
src: "https://v.qq.com/txp/iframe/player.html?vid=u0033nvzb5v",
srcPrefix: "https://v.qq.com/txp/iframe/player.html?vid",
linkRule: [String.raw`v.qq.com\/x\/cover\/\w+\/\w+`]
},
amap: {
example: "https://ditu.amap.com/",
src: "https://www.amap.com/place/B000A45467",
srcPrefix: "",
linkRule: [String.raw`\.amap\.com`]
},
baidu_map: {
example: "https://j.map.baidu.com/15/fo",
src: "https://j.map.baidu.com/15/fo",
srcPrefix: "",
linkRule: [String.raw`map\.baidu\.com`]
},
modao: {
example: "https://free.modao.cc/app/2cd26580a6717a147454df7470e7ec464093cba3/embed/v2#screen=sk71k6d1dfxulzx",
src: "https://free.modao.cc/app/6UkpAxcGE3nPz52GLqhnOZgC7MATBSy/embed/v2",
srcPrefix: "",
linkRule: [String.raw`https:\/\/\w+.modao.cc\/app\/\w+\/embed\/v2`],
tips: "Modao > More > Share > Embed > COPY"
},
lanhu: {
example: "https://lanhuapp.com/link/#/invite?sid=evP7L",
src: "https://lanhuapp.com/url/evP7L",
srcPrefix: "",
linkRule: [String.raw`https:\/\/lanhuapp.com\/url\/\w+`],
tips: "Lanhu > Project > Share > Copy Link"
},
figma: {
example: "https://www.figma.com/file/aS9uSgPXoNpaPkzbjNcK8v/Demo?node-id=0%3A1",
src: "https://www.figma.com/file/aS9uSgPXoNpaPkzbjNcK8v/Demo?node-id=0%3A1",
srcPrefix: "https://www.figma.com/embed?embed_host=share&url",
linkRule: [String.raw`https:\/\/www.figma.com\/file\/\w+`]
},
canva: {
example: "https://www.canva.cn/design/DAD61-t29UI/view",
src: "https://www.canva.cn/design/DAD61-t29UI/view",
srcPrefix: "",
linkRule: [String.raw`https:\/\/www.canva.cn\/design\/.+\/view`]
},
processon: {
example: "https://www.processon.com/embed/5ea99d8607912948b0e6fe78",
src: "https://www.processon.com/embed/5ea99d8607912948b0e6fe78",
srcPrefix: "",
linkRule: [String.raw`https:\/\/www.processon.com\/embed\/\w+`]
},
codepen: {
example: "https://codepen.io/mekery/embed/YzyrKOJ",
src: "https://codepen.io/mekery/embed/YzyrKOJ",
srcPrefix: "",
linkRule: [String.raw`https:\/\/codepen.io\/.+\/embed\/\w+`]
},
jinshuju: {
example: "https://jinshuju.net/f/q9YvVf",
src: "https://jinshuju.net/f/q9YvVf",
srcPrefix: "",
linkRule: [String.raw`https:\/\/jinshuju.net\/f\/\w+`]
},
iframe: {
example: "https://v.youku.com/v_show/id_XNDM0NDM4MTcy.html",
src: "https://player.youku.com/embed/XNDM0NDM4MTcy",
srcPrefix: "",
linkRule: [".+"]
},
googlemaps: {
example: "https://goo.gl/maps/8Ys8b4K1ZJY2",
src: "https://www.google.com/maps/embed?pb=https://goo.gl/maps/8Ys8b4K1ZJY2",
srcPrefix: "",
linkRule: [String.raw`https:\/\/goo.gl\/maps\/\w+`]
}
};
function _(e) {
const t = m.youtube, i = e.matchedUrl;
e.validLink = !0;
const r = i.split("="), n = r.length;
if (n > 0) {
const c = r[n - 1];
e.src = `${t.srcPrefix}/${c}`, e.validId = !0;
}
return e;
}
function $(e) {
const t = m.youku, i = e.matchedUrl, r = t.idRule, n = new RegExp(r), c = i.match(n);
if (c && c.length > 0) {
const o = c[0].slice(3);
e.validId = !0, e.src = `${t.srcPrefix}/${o}`;
} else
e.validId = !1;
return e;
}
function T(e) {
const t = m.bilibili, r = e.matchedUrl.split("/"), n = r.length;
if (n > 0) {
const c = r[n - 1];
e.src = `${t.srcPrefix}=${c}`, e.validId = !0;
}
return e;
}
function Y(e) {
const t = m.qqvideo, r = e.matchedUrl.split("/"), n = r.length;
if (n > 0) {
const c = r[n - 1];
e.src = `${t.srcPrefix}=${c}`, e.validId = !0;
}
return e;
}
function z(e, t) {
return t.src = e, t.validId = !0, t;
}
function C(e, t) {
return t.src = e, t.validId = !0, t;
}
function E(e, t) {
return t.src = e, t.validId = !0, t.originalLink = e, t;
}
function H(e) {
return e.src = e.matchedUrl, e.validId = !0, e.originalLink = e.src, e;
}
function B(e) {
return e.src = e.matchedUrl, e.validId = !0, e.originalLink = e.src, e;
}
function V(e) {
const t = m.figma;
return e.src = `${t.srcPrefix}=${encodeURIComponent(e.matchedUrl)}`, e.validId = !0, e.originalLink = e.matchedUrl, e;
}
function K(e, t) {
return t.src = `${t.matchedUrl}?embed`, t.validId = !0, t.originalLink = e, t;
}
function O(e, t) {
return t.src = `${t.matchedUrl}`, t.validId = !0, t.originalLink = e, t;
}
function X(e) {
return e.src = `${e.matchedUrl}`, e.validId = !0, e.originalLink = e.src, e;
}
function J(e, t) {
return t.src = `${t.matchedUrl}?background=white&banner=show&embedded=true`, t.validId = !0, t.originalLink = e, t;
}
function W(e, t) {
return t.src = `${t.matchedUrl}`, t.validId = !0, t.originalLink = e, t;
}
function F(e, t, i) {
if (e === "googlemaps")
return i.validLink = !0, i.matchedUrl = t, i;
const n = m[e].linkRule;
for (const c of n) {
const o = new RegExp(c), a = t.match(o);
if (a && a.length > 0)
return i.validLink = !0, i.matchedUrl = e === "youtube" ? a[1] : a[0], i;
}
return i;
}
function G(e) {
var i, r;
let t = "iframe";
return ((i = e.includes) != null && i.call(e, "youtube") || (r = e.includes) != null && r.call(e, "youtu.be")) && (t = "youtube"), e.includes("youku") && (t = "youku"), e.includes("bilibili") && (t = "bilibili"), e.includes("qq") && (t = "qqvideo"), e.includes("amap") && (t = "amap"), e.includes("map.baidu") && (t = "baidu_map"), (e.includes("google.com/maps") || e.includes("maps.app.goo.gl")) && (t = "googlemaps"), e.includes("modao") && (t = "modao"), e.includes("lanhuapp") && (t = "lanhu"), e.includes("figma") && (t = "figma"), e.includes("canva") && (t = "canva"), e.includes("processon") && (t = "processon"), e.includes("codepen") && (t = "codepen"), e.includes("jinshuju") && (t = "jinshuju"), e.includes("iframe") && (t = "iframe"), t;
}
function Z(e) {
let t = {
validLink: !1,
validId: !1,
matchedUrl: "",
originalLink: e,
src: ""
};
const i = G(e);
if (t = F(i, e, t), !t.validLink)
return t;
switch (i) {
case "youtube":
return _(t);
case "youku":
return $(t);
case "bilibili":
return T(t);
case "qqvideo":
return Y(t);
case "amap":
return z(e, t);
case "baidu_map":
return C(e, t);
case "googlemaps":
return E(e, t);
case "modao":
return H(t);
case "lanhu":
return B(t);
case "figma":
return V(t);
case "canva":
return K(e, t);
case "processon":
return O(e, t);
case "codepen":
return X(t);
case "jinshuju":
return J(e, t);
case "iframe":
return W(e, t);
default:
return e;
}
}
const Q = "_wrap_5y04w_1", ee = "_innerWrap_5y04w_15", w = {
wrap: Q,
innerWrap: ee
};
function te({ editor: e, node: t, updateAttributes: i }) {
const r = j(), { src: n, width: c, height: o } = t.attrs, [a, p] = M("");
function u() {
if (!a)
return;
const s = Z(a);
e.chain().updateAttributes(b.name, {
src: (s == null ? void 0 : s.src) || a
}).setNodeSelection(e.state.selection.from).focus().run();
}
const g = R(
(s) => {
i({ width: s.width, height: s.height });
},
[i]
);
return /* @__PURE__ */ f(v, { children: [
!n && /* @__PURE__ */ f("div", { className: "richtext-mx-auto richtext-my-[12px] richtext-flex richtext-max-w-[600px] richtext-items-center richtext-justify-center richtext-gap-[10px] richtext-rounded-[12px] richtext-border richtext-border-solid richtext-border-border richtext-p-[10px]", children: [
/* @__PURE__ */ d(
U,
{
autoFocus: !0,
className: "richtext-flex-1",
onInput: (s) => p(s.target.value),
placeholder: "Enter link",
type: "url",
value: a
}
),
/* @__PURE__ */ d(
q,
{
className: "richtext-w-[60px]",
onClick: u,
children: "OK"
}
)
] }),
n && /* @__PURE__ */ d(
N,
{
size: { width: Number.parseInt(c), height: Number.parseInt(o) },
onResizeStop: (s, ie, re, h) => {
g({
width: Number.parseInt(c) + h.width,
height: Number.parseInt(o) + h.height
});
},
children: /* @__PURE__ */ d("div", { className: x(w.wrap, "render-wrapper"), children: /* @__PURE__ */ d(
"div",
{
className: w.innerWrap,
style: { pointerEvents: r ? "none" : "auto" },
children: /* @__PURE__ */ d(
"iframe",
{
className: "richtext-my-[12px] ",
src: n
}
)
}
) })
}
)
] });
}
function pe() {
const e = A(b.name), {
icon: t = void 0,
tooltip: i = void 0,
shortcutKeys: r = void 0,
tooltipOptions: n = {},
action: c = void 0,
isActive: o = void 0
} = (e == null ? void 0 : e.componentProps) ?? {}, { editorDisabled: a, update: p } = L(o), u = () => {
a || c && (c(), p());
};
return e ? /* @__PURE__ */ d(
D,
{
action: u,
disabled: a,
icon: t,
shortcutKeys: r,
tooltip: i,
tooltipOptions: n
}
) : /* @__PURE__ */ d(P, {});
}
const b = /* @__PURE__ */ k.create({
name: "iframe",
content: "",
marks: "",
group: "block",
selectable: !0,
atom: !0,
draggable: !0,
addOptions() {
var e;
return {
...(e = this.parent) == null ? void 0 : e.call(this),
HTMLAttributes: {
class: "iframe"
},
button: ({
editor: t,
extension: i,
t: r
}) => ({
componentProps: {
action: (n) => t.commands.setIframe(n),
upload: i.options.upload,
// isActive: () => editor.can().setIframe({}),
icon: "Iframe",
tooltip: r("editor.iframe.tooltip")
}
})
};
},
addAttributes() {
return {
width: {
default: 600,
parseHTML: l("width")
},
height: {
default: 300,
parseHTML: l("height")
},
src: {
default: null,
parseHTML: l("src")
},
defaultShowPicker: {
default: !1
},
frameborder: {
default: 0
},
allowfullscreen: {
default: this.options.allowFullscreen,
parseHTML: () => this.options.allowFullscreen
}
};
},
parseHTML() {
return [
{
tag: "iframe"
}
];
},
renderHTML({ HTMLAttributes: e }) {
return ["iframe", I(this.options.HTMLAttributes, e)];
},
addCommands() {
return {
setIframe: (e) => ({ tr: t, commands: i, chain: r }) => {
var c, o, a;
if (((a = (o = (c = t.selection) == null ? void 0 : c.node) == null ? void 0 : o.type) == null ? void 0 : a.name) == this.name)
return i.updateAttributes(this.name, e);
const n = e || { url: "" };
return r().insertContent({
type: this.name,
attrs: n
}).run();
}
};
},
addInputRules() {
return [
S({
find: /^\$iframe\$$/,
type: this.type,
getAttributes: () => ({ width: "100%" })
})
];
},
addNodeView() {
return y(te);
}
});
export {
b as I,
pe as R,
Z as g
};