Skip to content

Commit

Permalink
refactor: Improve editor demo
Browse files Browse the repository at this point in the history
  • Loading branch information
areknawo committed Oct 18, 2023
1 parent 6aa8a40 commit aa6a0c5
Show file tree
Hide file tree
Showing 12 changed files with 538 additions and 103 deletions.
10 changes: 8 additions & 2 deletions apps/backend/extensions/src/routes/mdx/output-transformer.ts
Expand Up @@ -287,7 +287,9 @@ const mdxAsyncOutputTransformer = async (
const content = await transformContentNode(
contentWalker as JSONContentNodeWalker<JSONContentNode["doc"]>
);
const frontmatter = dump(
const { __extensions__, ...customData } = contentPiece?.customData || {};

let frontmatter = dump(
{
...(contentPiece?.canonicalLink && { canonicalLink: contentPiece.canonicalLink }),
...(contentPiece?.coverUrl && { coverUrl: contentPiece.coverUrl }),
Expand All @@ -297,11 +299,15 @@ const mdxAsyncOutputTransformer = async (
...(contentPiece?.date && { date: dayjs(contentPiece.date).format("YYYY-MM-DD") }),
...(contentPiece?.slug && { slug: contentPiece.slug }),
...(contentPiece?.title && { title: contentPiece.title }),
...(contentPiece?.customData || {})
...customData
},
{ skipInvalid: true, forceQuotes: true, quotingType: '"' }
);

if (frontmatter.trim() === "{}") {
frontmatter = "";
}

return (
await format(
`${frontmatter ? "---" : ""}\n${frontmatter.trim()}\n${
Expand Down
3 changes: 2 additions & 1 deletion apps/docs/src/components/content/card.astro
Expand Up @@ -20,7 +20,8 @@ const { props } = Astro;
><BaseCard
class={clsx(
"w-full flex flex-col m-0 p-0 gap-2 items-start h-full",
props.gradient ? "hover:bg-gradient-to-bl" : "!hover:bg-gray-200 !dark:hover:bg-gray-700"
props.gradient && "hover:bg-gradient-to-bl",
!props.gradient && "bg-gray-100 dark:bg-gray-900 !hover:bg-gray-200 !dark:hover:bg-gray-700"
)}
color={props.gradient ? "primary" : "base"}
>
Expand Down
1 change: 1 addition & 0 deletions apps/web/src/assets/icons/index.ts
Expand Up @@ -3,3 +3,4 @@ export * from "./discord";
export * from "./google";
export * from "./hashnode";
export * from "./logo";
export * from "./mdx";
3 changes: 3 additions & 0 deletions apps/web/src/assets/icons/mdx.ts
@@ -0,0 +1,3 @@
const mdxIcon = `M.79 7.12h22.42c.436 0 .79.355.79.792v8.176a.79.79 0 0 1-.79.79H.79a.79.79 0 0 1-.79-.79V7.912a.79.79 0 0 1 .79-.791V7.12Zm2.507 7.605v-3.122l1.89 1.89L7.12 11.56v3.122h1.055v-5.67l-2.99 2.99L2.24 9.056v5.67h1.055v-.001Zm8.44-1.845l-1.474-1.473l-.746.746l2.747 2.747l2.745-2.747l-.746-.746l-1.473 1.473v-4h-1.054v4Zm10.041.987l-2.175-2.175l2.22-2.22l-.746-.746l-2.22 2.22l-2.22-2.22l-.747.746l2.22 2.22l-2.176 2.177l.746.746l2.177-2.177l2.176 2.175l.745-.746Z`;

export { mdxIcon };
4 changes: 2 additions & 2 deletions apps/web/src/layout/toolbar/index.tsx
Expand Up @@ -94,7 +94,7 @@ const toolbarViews: Record<string, Component<Record<string, any>>> = {
variant="text"
text="soft"
label="Usage guide"
link="https://docs.vrite.io/content-editor"
link="https://docs.vrite.io/usage-guide/content-editor"
target="_blank"
/>
<IconButton
Expand Down Expand Up @@ -132,7 +132,7 @@ const toolbarViews: Record<string, Component<Record<string, any>>> = {
class="m-0"
variant="text"
text="soft"
link="https://docs.vrite.io/content-editor"
link="https://docs.vrite.io/usage-guide/content-editor"
target="_blank"
/>
</Tooltip>
Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/views/editor/menus/bubble/format.tsx
@@ -1,5 +1,5 @@
import clsx from "clsx";
import { Component, For, createSignal } from "solid-js";
import { Component, For, createEffect, createSignal } from "solid-js";
import { SolidEditor } from "@vrite/tiptap-solid";
import {
mdiFormatBold,
Expand Down
4 changes: 1 addition & 3 deletions apps/web/src/views/editor/menus/bubble/index.tsx
Expand Up @@ -22,9 +22,7 @@ interface BubbleMenuProps {
const BubbleMenu: Component<BubbleMenuProps> = (props) => {
const [mode, setMode] = createSignal<BubbleMenuMode>("format");

props.editor.on("selectionUpdate", ({ editor }) => {
const { selection } = editor.state;

props.editor.on("selectionUpdate", () => {
if (props.editor.state.selection instanceof CellSelection) {
setMode("table");
} else if (!props.editor.state.selection.empty) {
Expand Down
68 changes: 54 additions & 14 deletions apps/web/src/views/editor/menus/export/index.tsx
Expand Up @@ -19,10 +19,12 @@ import {
useAuthenticatedUserData,
useClient,
useCommandPalette,
useNotifications
useNotifications,
useSharedState
} from "#context";
import { formatCode } from "#lib/code-editor";
import { escapeHTML } from "#lib/utils";
import { mdxIcon } from "#assets/icons";

interface ExportMenuProps {
editedContentPiece?: App.ContentPieceWithAdditionalData;
Expand All @@ -32,34 +34,33 @@ interface ExportMenuProps {
onClick?(): void;
}

type ExportType = "html" | "json" | "md" | "mdx";

const ExportMenu: Component<ExportMenuProps> = (props) => {
const createSharedSignal = useSharedState();
const client = useClient();
const [editor] = createSharedSignal("editor");
const { registerCommand = () => {} } = useCommandPalette() || {};
const { workspaceSettings = () => null } = useAuthenticatedUserData() || {};
const { notify } = useNotifications();
const [loading, setLoading] = createSignal(false);
const [exportMenuOpened, setExportMenuOpened] = createSignal(false);
const [exportDropdownOpened, setExportDropdownOpened] = createSignal(false);
const [code, setCode] = createSignal("");
const [exportType, setExportType] = createSignal<"html" | "json" | "md">("html");
const loadContent = async (type: "html" | "json" | "md"): Promise<string | undefined> => {
const [exportType, setExportType] = createSignal<ExportType>("html");
const loadContent = async (type: ExportType): Promise<string | undefined> => {
try {
let { content } = props;

if (!content && props.editedContentPiece) {
const contentPiece = await client.contentPieces.get.query({
content: true,
id: props.editedContentPiece.id
});

content = contentPiece.content as JSONContent;
content = (editor()?.getJSON() as JSONContent) || { type: "doc", content: [] };
}

const prettierConfig = JSON.parse(workspaceSettings()?.prettierConfig || "{}");

if (type === "html") {
if (!content) return;
if (!content) return;

if (type === "html") {
return formatCode(
htmlOutputTransformer(content).replace(/<code>((?:.|\n)+?)<\/code>/g, (_, code) => {
return `<code>${escapeHTML(code)}</code>`;
Expand All @@ -70,18 +71,40 @@ const ExportMenu: Component<ExportMenuProps> = (props) => {
}

if (type === "md") {
if (!content) return;

return formatCode(gfmOutputTransformer(content), "markdown", prettierConfig);
}

if (type === "mdx") {
try {
const response = await fetch("https://extensions.vrite.io/mdx/output", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
data: [
{
content,
metadata: props.editedContentPiece || {}
}
]
})
});
const [result] = await response.json();

return result;
} catch (error) {
return;
}
}

return formatCode(JSON.stringify(content), "json", prettierConfig);
} catch (e) {
notify({ type: "error", text: "Couldn't export the content" });
setLoading(false);
}
};
const exportContent = async (type: "html" | "json" | "md"): Promise<void> => {
const exportContent = async (type: ExportType): Promise<void> => {
setExportDropdownOpened(false);
setLoading(true);

Expand Down Expand Up @@ -125,6 +148,14 @@ const ExportMenu: Component<ExportMenuProps> = (props) => {
action() {
exportContent("md");
}
},
{
category: "editor",
icon: mdxIcon,
name: "Export MDX",
action() {
exportContent("mdx");
}
}
]);

Expand Down Expand Up @@ -178,6 +209,15 @@ const ExportMenu: Component<ExportMenuProps> = (props) => {
class="justify-start w-full m-0"
onClick={() => exportContent("md")}
/>
<IconButton
path={mdxIcon}
text="soft"
variant="text"
label="MDX"
disabled={loading()}
class="justify-start w-full m-0"
onClick={() => exportContent("mdx")}
/>
</div>
</Dropdown>
<Overlay
Expand Down
3 changes: 2 additions & 1 deletion apps/web/src/views/standalone-editor/editor.tsx
Expand Up @@ -171,7 +171,8 @@ const Editor: Component = () => {
}

if (
["element", "image", "codeBlock", "embed", "horizontalRule"].some((name) => {
isNodeSelection &&
["horizontalRule", "image", "codeBlock", "embed", "element"].some((name) => {
return editor.isActive(name);
})
) {
Expand Down
3 changes: 1 addition & 2 deletions apps/web/src/views/standalone-editor/initial-content.ts
@@ -1,4 +1,3 @@
const initialContent = `<h1>Welcome to Vrite Editor πŸš€</h1><p><strong>Vrite Editor</strong> is an <a target="_blank" rel="noopener noreferrer nofollow" href="https://github.com/vriteio/vrite">open-source</a>, minimalistic WYSIWYG Markdown editor.</p><h2>Features</h2><p><strong>Integrated Monaco editor and Prettier for code snippets</strong></p><pre><code class="language-javascript">console.log("Hello World!");
</code></pre><p><strong>Tables! πŸŽ‰</strong></p><table><tbody><tr><th colspan="1" rowspan="1"><p>Header 1</p></th><th colspan="1" rowspan="1"><p>Header 2</p></th><th colspan="1" rowspan="1"><p>Header 3</p></th></tr><tr><td colspan="1" rowspan="1"><p>Cell 1A</p></td><td colspan="1" rowspan="1"><p>Cell 1B</p></td><td colspan="1" rowspan="1"><p>Cell 1C</p></td></tr><tr><td colspan="1" rowspan="1"><p>Cell 2A</p></td><td colspan="1" rowspan="1"><p>Cell 2B</p></td><td colspan="1" rowspan="1"><p>Cell 2C</p></td></tr><tr><td colspan="1" rowspan="1"><p>Cell 3A</p></td><td colspan="1" rowspan="1"><p>Cell 3B</p></td><td colspan="1" rowspan="1"><p>Cell 3C</p></td></tr></tbody></table><p><strong>Embeds πŸŽ₯</strong></p><iframe src="https://www.youtube.com/embed/dQw4w9WgXcQ" data-embed="youtube" data-input="https://www.youtube.com/embed/dQw4w9WgXcQ"></iframe><p><strong>Zen mode</strong>, <strong>Markdown/HTML export</strong>, <strong>Stats</strong></p><p>Check out the top-right corner!</p><p><strong>A lot more stuff!</strong></p><p>Full usage guide here: <a target="_blank" rel="noopener noreferrer nofollow" href="https://docs.vrite.io/content-editor">https://docs.vrite.io/content-editor</a></p><h2>What is Vrite?</h2><p>Vrite Editor is a local, standalone, editor extracted from a larger project β€” <strong>Vrite</strong> β€” <a target="_blank" rel="noopener noreferrer nofollow" href="https://vrite.io">open-source, headless CMS for technical content</a>. If you’re interested in <strong>real-time collaboration</strong>, Kanban-based content management, GPT integration, customization and API access to your content, check out the full version of Vrite by <a target="_blank" rel="noopener noreferrer nofollow" href="https://app.vrite.io">signing in</a> using the button in the top-right corner.</p><img src="https://assets.vrite.io/64957f5b1f760acf4204d146/AFSfsVOvYWDOUUa3I2JL0.png" alt="Vrite dashboard" width="100%"><p>Some links to check out:</p><ul><li><p>🌟 <strong>Star Vrite on GitHub</strong> β€” <a target="_blank" rel="noopener noreferrer nofollow" href="https://github.com/vriteio/vrite">https://github.com/vriteio/vrite</a></p></li><li><p>🐞 <strong>Report bugs</strong> β€” <a target="_blank" rel="noopener noreferrer nofollow" href="https://github.com/vriteio/vrite/issues">https://github.com/vriteio/vrite/issues</a></p></li><li><p>🐦 <strong>Follow on Twitter</strong> β€” <a target="_blank" rel="noopener noreferrer nofollow" href="https://twitter.com/vriteio">https://twitter.com/vriteio</a></p></li><li><p>πŸ’¬ <strong>Join Vrite Discord</strong> β€” <a target="_blank" rel="noopener noreferrer nofollow" href="https://discord.gg/yYqDWyKnqE">https://discord.gg/yYqDWyKnqE</a></p></li><li><p>ℹ️ <strong>Learn more about Vrite</strong> β€” <a target="_blank" rel="noopener noreferrer nofollow" href="https://vrite.io">https://vrite.io</a></p></li><li><p>πŸ“• <strong>Vrite documentation</strong> β€” <a target="_blank" rel="noopener noreferrer nofollow" href="https://docs.vrite.io">https://docs.vrite.io</a></p></li></ul><p></p>`;
const initialContent = `<h1 dir="auto" data-slug="welcome-to-vrite-editor">Welcome to Vrite Editor πŸš€</h1><p dir="auto"><a target="_blank" rel="noopener noreferrer nofollow" href="https://github.com/vriteio/vrite">Open-source</a>, minimalistic WYSIWYG Markdown editor.</p><h2 dir="auto" data-slug="features">Features</h2><p dir="auto"><strong>Integrated Monaco editor and Prettier for code snippets</strong></p><pre><code class="language-javascript">console.log("Hello World!");</code></pre><p dir="auto"><strong>Tables! πŸŽ‰</strong></p><table><tbody><tr><th colspan="1" rowspan="1"><p dir="auto">Header 1</p></th><th colspan="1" rowspan="1"><p dir="auto">Header 2</p></th><th colspan="1" rowspan="1"><p dir="auto">Header 3</p></th></tr><tr><td colspan="1" rowspan="1"><p dir="auto">Cell 1A</p></td><td colspan="1" rowspan="1"><p dir="auto">Cell 1B</p></td><td colspan="1" rowspan="1"><p dir="auto">Cell 1C</p></td></tr><tr><td colspan="1" rowspan="1"><p dir="auto">Cell 2A</p></td><td colspan="1" rowspan="1"><p dir="auto">Cell 2B</p></td><td colspan="1" rowspan="1"><p dir="auto">Cell 2C</p></td></tr><tr><td colspan="1" rowspan="1"><p dir="auto">Cell 3A</p></td><td colspan="1" rowspan="1"><p dir="auto">Cell 3B</p></td><td colspan="1" rowspan="1"><p dir="auto">Cell 3C</p></td></tr></tbody></table><p dir="auto"><strong>Embeds πŸŽ₯</strong></p><iframe src="https://www.youtube.com/embed/dQw4w9WgXcQ" data-embed="youtube" data-input="https://www.youtube.com/embed/dQw4w9WgXcQ"></iframe><p dir="auto"><strong>Zen mode</strong>, <strong>Markdown/HTML export</strong>, <strong>Stats</strong></p><p dir="auto">Check out the top-right corner!</p><p dir="auto"><strong>A lot more stuff!</strong></p><p dir="auto">Full usage guide here: <a target="_blank" rel="noopener noreferrer nofollow" href="https://docs.vrite.io/content-editor">https://docs.vrite.io/content-editor</a></p><h2 dir="auto" data-slug="what-is-vrite">What is Vrite?</h2><p dir="auto"><a target="_blank" rel="noopener noreferrer nofollow" href="https://vrite.io">Vrite</a> is an <a target="_blank" rel="noopener noreferrer nofollow" href="https://github.com/vriteio/vrite">open-source</a>, collaborative, developer content platform for documentation, knowledge bases, and technical blogs.</p><p dir="auto">With an extensible, collaborative editor, content management dashboard, and features like semantic search, GitHub sync, and more β€” all accessible via powerful API β€” Vrite aims to provide an all-in-one experience for creating, managing, and publishing all kinds of technical content. </p><img src="http://localhost:8888/65017ed7b0e627e259623b8a/q0HUeyQ1aeElfzaZkdNWn.png" alt="Vrite Kanban dashboard" width="100%" aspectratio="1.5855758880516684"><p dir="auto">Some links to check out:</p><ul dir="auto"><li><p dir="auto">🌟 <strong>Star Vrite on GitHub</strong> β€” <a target="_blank" rel="noopener noreferrer nofollow" href="https://github.com/vriteio/vrite">https://github.com/vriteio/vrite</a></p></li><li><p dir="auto">🐞 <strong>Report bugs</strong> β€” <a target="_blank" rel="noopener noreferrer nofollow" href="https://github.com/vriteio/vrite/issues">https://github.com/vriteio/vrite/issues</a></p></li><li><p dir="auto">🐦 <strong>Follow on Twitter</strong> β€” <a target="_blank" rel="noopener noreferrer nofollow" href="https://twitter.com/vriteio">https://twitter.com/vriteio</a></p></li><li><p dir="auto">πŸ’¬ <strong>Join Vrite Discord</strong> β€” <a target="_blank" rel="noopener noreferrer nofollow" href="https://discord.gg/yYqDWyKnqE">https://discord.gg/yYqDWyKnqE</a></p></li><li><p dir="auto">ℹ️ <strong>Learn more about Vrite</strong> β€” <a target="_blank" rel="noopener noreferrer nofollow" href="https://vrite.io">https://vrite.io</a></p></li><li><p dir="auto">πŸ“• <strong>Vrite documentation</strong> β€” <a target="_blank" rel="noopener noreferrer nofollow" href="https://docs.vrite.io">https://docs.vrite.io</a></p></li></ul><p dir="auto"></p>`;

export { initialContent };
4 changes: 2 additions & 2 deletions apps/web/src/views/workspaces/view.tsx
Expand Up @@ -124,7 +124,7 @@ const WorkspacesView: Component = () => {

return (
<div class="relative">
<Card class="flex flex-col m-0 p-0 gap-2 items-start w-96 max-h-xl overflow-hidden">
<Card class="flex flex-col m-0 p-0 gap-2 items-start w-96 max-h-xl h-full overflow-hidden">
<div class="flex flex-col justify-center items-start pl-3 pr-4 pt-3 w-full">
<Show when={createWorkspaceSectionOpened()}>
<IconButton
Expand Down Expand Up @@ -165,7 +165,7 @@ const WorkspacesView: Component = () => {
}
>
<div class="flex flex-col justify-center items-center gap-2 w-full pl-4 pr-2 pb-4 overflow-hidden h-full">
<div class="relative overflow-hidden grid w-full">
<div class="relative overflow-hidden grid w-full h-full">
<ScrollShadow
scrollableContainerRef={scrollableContainerRef}
onScrollEnd={loadMore}
Expand Down

0 comments on commit aa6a0c5

Please sign in to comment.