@liveblocks/react-ui
Version:
A set of React pre-built components for the Liveblocks products. Liveblocks is the all-in-one toolkit to build collaborative products like Figma, Notion, and more.
493 lines (489 loc) • 15.1 kB
JavaScript
'use strict';
var jsxRuntime = require('react/jsx-runtime');
var core = require('@liveblocks/core');
var reactSlot = require('@radix-ui/react-slot');
var marked = require('marked');
var react = require('react');
const defaultComponents = {
CodeBlock: ({ language, code }) => {
return /* @__PURE__ */ jsxRuntime.jsx("pre", {
"data-language": language ?? void 0,
children: /* @__PURE__ */ jsxRuntime.jsx("code", {
children: code
})
});
},
Link: ({ href, title, children }) => {
return /* @__PURE__ */ jsxRuntime.jsx("a", {
href,
title,
target: "_blank",
rel: "noopener noreferrer",
children
});
},
Heading: ({ level, children }) => {
const Heading = `h${level}`;
return /* @__PURE__ */ jsxRuntime.jsx(Heading, {
children
});
},
Image: ({ src, alt, title }) => {
return /* @__PURE__ */ jsxRuntime.jsx("img", {
src,
alt,
title
});
},
Blockquote: ({ children }) => {
return /* @__PURE__ */ jsxRuntime.jsx("blockquote", {
children
});
}
};
const Markdown = react.forwardRef(
({ content, components, asChild, ...props }, forwardedRef) => {
const Component = asChild ? reactSlot.Slot : "div";
const tokens = react.useMemo(() => {
return new marked.Lexer().lex(content);
}, [content]);
return /* @__PURE__ */ jsxRuntime.jsx(Component, {
...props,
ref: forwardedRef,
children: tokens.map((token, index) => {
return /* @__PURE__ */ jsxRuntime.jsx(MemoizedMarkdownBlockToken, {
token,
components
}, index);
})
});
}
);
const MemoizedMarkdownBlockToken = react.memo(
({
token,
components
}) => {
return /* @__PURE__ */ jsxRuntime.jsx(MarkdownBlockToken, {
token,
components
});
},
(prevProps, nextProps) => {
const prevToken = prevProps.token;
const nextToken = nextProps.token;
if (prevToken.raw.length !== nextToken.raw.length) {
return false;
}
if (prevToken.type !== nextToken.type) {
return false;
}
return prevToken.raw === nextToken.raw;
}
);
function MarkdownBlockToken({
token,
components
}) {
switch (token.type) {
case "space": {
return null;
}
case "code": {
let language = void 0;
if (token.lang !== void 0) {
language = token.lang.match(/^\S*/)?.[0] ?? void 0;
}
const CodeBlock = components?.CodeBlock ?? defaultComponents.CodeBlock;
return /* @__PURE__ */ jsxRuntime.jsx(CodeBlock, {
language,
code: token.text
});
}
case "blockquote": {
const tokens = [];
for (let i = 0; i < token.tokens.length; i++) {
switch (token.tokens[i].type) {
case "space":
case "code":
case "blockquote":
case "html":
case "heading":
case "hr":
case "list":
case "paragraph":
case "table": {
tokens.push(token.tokens[i]);
break;
}
case "text": {
const texts = [token.tokens[i]];
while (i + 1 < token.tokens.length && token.tokens[i + 1].type === "text") {
i++;
texts.push(token.tokens[i]);
}
tokens.push({
type: "paragraph",
tokens: texts,
raw: texts.map((text) => text.raw).join(""),
text: texts.map((text) => text.text).join("")
});
break;
}
default: {
continue;
}
}
}
const Blockquote = components?.Blockquote ?? defaultComponents.Blockquote;
return /* @__PURE__ */ jsxRuntime.jsx(Blockquote, {
children: tokens.map((token2, index) => {
return /* @__PURE__ */ jsxRuntime.jsx(MarkdownBlockToken, {
token: token2,
components
}, index);
})
});
}
case "html": {
return token.text;
}
case "heading": {
const Heading = components?.Heading ?? defaultComponents.Heading;
return /* @__PURE__ */ jsxRuntime.jsx(Heading, {
level: clampHeadingLevel(token.depth),
children: token.tokens.map((token2, index) => /* @__PURE__ */ jsxRuntime.jsx(MarkdownInlineToken, {
token: token2,
components
}, index))
});
}
case "hr": {
return /* @__PURE__ */ jsxRuntime.jsx("hr", {});
}
case "list": {
const ListTag = token.ordered ? "ol" : "ul";
return /* @__PURE__ */ jsxRuntime.jsx(ListTag, {
children: token.items.map((item, index) => {
if (item.loose) {
if (item.task) {
const tokens = [...item.tokens];
if (tokens[0]?.type === "paragraph") {
const token2 = tokens[0];
token2.tokens.unshift(
{
type: "checkbox",
checked: item.checked,
raw: ""
},
{
type: "text",
text: " ",
raw: " ",
escaped: false
}
);
} else {
tokens.unshift(
{
type: "checkbox",
checked: item.checked,
raw: ""
},
{
type: "text",
text: " ",
raw: " ",
escaped: false
}
);
}
const items = [];
for (let i = 0; i < tokens.length; i++) {
switch (tokens[i].type) {
case "space":
case "code":
case "blockquote":
case "html":
case "heading":
case "hr":
case "list":
case "paragraph":
case "table": {
items.push(tokens[i]);
break;
}
case "text":
case "checkbox": {
const texts = [
tokens[i]
];
while (i + 1 < tokens.length && tokens[i + 1].type === "text") {
i++;
texts.push(tokens[i]);
}
items.push({
type: "paragraph",
tokens: texts,
raw: texts.map((text) => text.raw).join(""),
text: texts.map((text) => text.text).join("")
});
break;
}
default: {
continue;
}
}
}
return /* @__PURE__ */ jsxRuntime.jsx("li", {
children: items.map((token2, index2) => {
return /* @__PURE__ */ jsxRuntime.jsx(MarkdownBlockToken, {
token: token2,
components
}, index2);
})
}, index);
} else {
const tokens = [];
for (let i = 0; i < item.tokens.length; i++) {
switch (item.tokens[i].type) {
case "space":
case "code":
case "blockquote":
case "html":
case "heading":
case "hr":
case "list":
case "paragraph":
case "table": {
tokens.push(item.tokens[i]);
break;
}
case "text": {
const texts = [
item.tokens[i]
];
while (i + 1 < item.tokens.length && item.tokens[i + 1].type === "text") {
i++;
texts.push(item.tokens[i]);
}
tokens.push({
type: "paragraph",
tokens: texts,
raw: texts.map((text) => text.raw).join(""),
text: texts.map((text) => text.text).join("")
});
break;
}
default: {
continue;
}
}
}
return /* @__PURE__ */ jsxRuntime.jsx("li", {
children: tokens.map((token2, index2) => {
return /* @__PURE__ */ jsxRuntime.jsx(MarkdownBlockToken, {
token: token2,
components
}, index2);
})
}, index);
}
} else {
const Items = item.tokens.map((token2, index2) => {
switch (token2.type) {
case "space":
case "code":
case "blockquote":
case "html":
case "heading":
case "hr":
case "list":
case "paragraph":
case "table": {
return /* @__PURE__ */ jsxRuntime.jsx(MarkdownBlockToken, {
token: token2,
components
}, index2);
}
case "text": {
return /* @__PURE__ */ jsxRuntime.jsx(MarkdownInlineToken, {
token: token2,
components
}, index2);
}
default: {
return null;
}
}
});
if (item.task) {
return /* @__PURE__ */ jsxRuntime.jsxs("li", {
children: [
/* @__PURE__ */ jsxRuntime.jsx("input", {
type: "checkbox",
disabled: true,
checked: item.checked
}),
" ",
Items
]
}, index);
} else {
return /* @__PURE__ */ jsxRuntime.jsx("li", {
children: Items
}, index);
}
}
})
});
}
case "paragraph": {
return /* @__PURE__ */ jsxRuntime.jsx("p", {
children: token.tokens.map((token2, index) => /* @__PURE__ */ jsxRuntime.jsx(MarkdownInlineToken, {
token: token2,
components
}, index))
});
}
case "table": {
return /* @__PURE__ */ jsxRuntime.jsxs("table", {
children: [
/* @__PURE__ */ jsxRuntime.jsx("thead", {
children: /* @__PURE__ */ jsxRuntime.jsx("tr", {
children: token.header.map((cell, index) => {
return /* @__PURE__ */ jsxRuntime.jsx("th", {
align: cell.align ?? void 0,
children: cell.tokens.map((token2, index2) => /* @__PURE__ */ jsxRuntime.jsx(MarkdownInlineToken, {
token: token2,
components
}, index2))
}, index);
})
})
}),
/* @__PURE__ */ jsxRuntime.jsx("tbody", {
children: token.rows.map((row, index) => {
return /* @__PURE__ */ jsxRuntime.jsx("tr", {
children: row.map((cell, index2) => {
return /* @__PURE__ */ jsxRuntime.jsx("td", {
align: cell.align ?? void 0,
children: cell.tokens.map((token2, index3) => /* @__PURE__ */ jsxRuntime.jsx(MarkdownInlineToken, {
token: token2,
components
}, index3))
}, index2);
})
}, index);
})
})
]
});
}
}
}
function MarkdownInlineToken({
token,
components
}) {
switch (token.type) {
case "strong": {
return /* @__PURE__ */ jsxRuntime.jsx("strong", {
children: token.tokens.map((token2, index) => /* @__PURE__ */ jsxRuntime.jsx(MarkdownInlineToken, {
token: token2,
components
}, index))
});
}
case "em": {
return /* @__PURE__ */ jsxRuntime.jsx("em", {
children: token.tokens.map((token2, index) => /* @__PURE__ */ jsxRuntime.jsx(MarkdownInlineToken, {
token: token2,
components
}, index))
});
}
case "codespan": {
return /* @__PURE__ */ jsxRuntime.jsx("code", {
children: parseHtmlEntities(token.text)
});
}
case "br": {
return /* @__PURE__ */ jsxRuntime.jsx("br", {});
}
case "del": {
return /* @__PURE__ */ jsxRuntime.jsx("del", {
children: token.tokens.map((token2, index) => /* @__PURE__ */ jsxRuntime.jsx(MarkdownInlineToken, {
token: token2,
components
}, index))
});
}
case "link": {
const href = core.sanitizeUrl(token.href);
if (href === null) {
return token.tokens.map((token2, index) => /* @__PURE__ */ jsxRuntime.jsx(MarkdownInlineToken, {
token: token2,
components
}, index));
}
const Link = components?.Link ?? defaultComponents.Link;
return /* @__PURE__ */ jsxRuntime.jsx(Link, {
href,
title: token.title ?? void 0,
children: token.tokens.map((token2, index) => /* @__PURE__ */ jsxRuntime.jsx(MarkdownInlineToken, {
token: token2,
components
}, index))
});
}
case "image": {
const href = core.sanitizeUrl(token.href);
if (href === null) {
return token.text;
}
const Image = components?.Image ?? defaultComponents.Image;
return /* @__PURE__ */ jsxRuntime.jsx(Image, {
src: href,
alt: token.text,
title: token.title ?? void 0
});
}
case "text": {
if (token.tokens !== void 0) {
return token.tokens.map((token2, index) => /* @__PURE__ */ jsxRuntime.jsx(MarkdownInlineToken, {
token: token2,
components
}, index));
} else {
return parseHtmlEntities(token.text);
}
}
case "escape": {
return token.text;
}
case "checkbox": {
return /* @__PURE__ */ jsxRuntime.jsx("input", {
type: "checkbox",
disabled: true,
checked: token.checked
});
}
default: {
return null;
}
}
}
function parseHtmlEntities(input) {
const document = new DOMParser().parseFromString(
`<!doctype html><body>${input}`,
"text/html"
);
return document.body.textContent;
}
function clampHeadingLevel(level) {
return Math.max(1, Math.min(6, level));
}
exports.Markdown = Markdown;
exports.MarkdownBlockToken = MarkdownBlockToken;
//# sourceMappingURL=Markdown.cjs.map