no message
This commit is contained in:
parent
bb1b91b6a6
commit
78823734da
@ -7,5 +7,9 @@
|
|||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { TiptapEditor, ThemeToggle, useTiptapContext } from "@tiptap/component";
|
import { TiptapEditor, ThemeToggle, useTiptapContext } from "@tiptap/component";
|
||||||
useTiptapContext();
|
import { onMounted } from "vue";
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
// useTiptapContext();
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -1,58 +1,47 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="mb-2">
|
<div class="flex items-center justify-between">
|
||||||
<button
|
<button
|
||||||
class="inline-flex items-center justify-center px-3 py-2 text-sm transition-colors rounded-md hover:bg-accent hover:text-accent-foreground"
|
class="inline-flex items-center justify-center px-3 py-2 text-sm transition-colors border rounded-md hover:bg-accent hover:text-accent-foreground"
|
||||||
@click="locale.setLang('zhHans')"
|
@click="locale.setLang('zhHans')"
|
||||||
>
|
>
|
||||||
中文
|
中文
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
class="inline-flex items-center justify-center px-3 py-2 text-sm transition-colors rounded-md hover:bg-accent hover:text-accent-foreground"
|
class="inline-flex items-center justify-center px-3 py-2 text-sm transition-colors border rounded-md hover:bg-accent hover:text-accent-foreground"
|
||||||
@click="locale.setLang('en')"
|
@click="locale.setLang('en')"
|
||||||
>
|
>
|
||||||
English
|
English
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
class="inline-flex items-center justify-center px-3 py-2 text-sm transition-colors rounded-md hover:bg-accent hover:text-accent-foreground"
|
class="inline-flex items-center justify-center px-3 py-2 text-sm transition-colors border rounded-md hover:bg-accent hover:text-accent-foreground"
|
||||||
@click="emit('toggle-minimal')"
|
@click="state.minimal = !state.minimal"
|
||||||
>
|
>
|
||||||
{{ minimal ? "Full" : "Minimal" }}
|
{{ state.minimal ? "Full" : "Minimal" }}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
class="inline-flex items-center justify-center px-3 py-2 text-sm transition-colors rounded-md hover:bg-accent hover:text-accent-foreground"
|
class="inline-flex items-center justify-center px-3 py-2 text-sm transition-colors border rounded-md hover:bg-accent hover:text-accent-foreground"
|
||||||
@click="emit('toggle-toolbar')"
|
@click="state.hideToolbar = !state.hideToolbar"
|
||||||
>
|
>
|
||||||
{{ !hideToolbar ? "Hide Toolbar" : "Show Toolbar" }}
|
{{ !state.hideToolbar ? "Hide Toolbar" : "Show Toolbar" }}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
class="inline-flex items-center justify-center px-3 py-2 text-sm transition-colors rounded-md hover:bg-accent hover:text-accent-foreground"
|
class="inline-flex items-center justify-center px-3 py-2 text-sm transition-colors border rounded-md hover:bg-accent hover:text-accent-foreground"
|
||||||
@click="emit('toggle-menubar')"
|
@click="state.hideMenubar = !state.hideMenubar"
|
||||||
>
|
>
|
||||||
{{ !hideMenubar ? "Hide Menubar" : "Show Menubar" }}
|
{{ !state.hideMenubar ? "Hide Menubar" : "Show Menubar" }}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
class="inline-flex items-center justify-center px-3 py-2 text-sm transition-colors rounded-md hover:bg-accent hover:text-accent-foreground"
|
class="inline-flex items-center justify-center px-3 py-2 text-sm transition-colors border rounded-md hover:bg-accent hover:text-accent-foreground"
|
||||||
@click="emit('toggle-editable')"
|
@click="state.disabled = !state.disabled"
|
||||||
>
|
>
|
||||||
{{ disabled ? "Editable" : "Readonly" }}
|
{{ state.disabled ? "Editable" : "Readonly" }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { locale } from "echo-editor";
|
import { locale } from "echo-editor";
|
||||||
|
import { useTiptapContext } from "../context/useTiptapStore";
|
||||||
|
|
||||||
defineProps<{
|
const { state } = useTiptapContext();
|
||||||
minimal: boolean;
|
|
||||||
hideToolbar: boolean;
|
|
||||||
hideMenubar: boolean;
|
|
||||||
disabled: boolean;
|
|
||||||
}>();
|
|
||||||
|
|
||||||
const emit = defineEmits([
|
|
||||||
"toggle-minimal",
|
|
||||||
"toggle-toolbar",
|
|
||||||
"toggle-menubar",
|
|
||||||
"toggle-editable",
|
|
||||||
]);
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { provide, inject, reactive, readonly, type InjectionKey } from "vue";
|
import { provide, inject, reactive, type InjectionKey } from "vue";
|
||||||
|
|
||||||
const TiptapStoreKey: InjectionKey<TiptapStore> = Symbol("TiptapStore");
|
const TiptapStoreKey: InjectionKey<TiptapStore> = Symbol("TiptapStore");
|
||||||
|
|
||||||
@ -11,18 +11,8 @@ export interface TiptapState {
|
|||||||
minimal: boolean;
|
minimal: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TiptapActions {
|
|
||||||
toggleMinimal: () => void;
|
|
||||||
updateContent: (newContent: string) => void;
|
|
||||||
setTheme: (theme: string) => void;
|
|
||||||
toggleToolbar: () => void;
|
|
||||||
toggleMenubar: () => void;
|
|
||||||
toggleEditable: () => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type TiptapStore = {
|
export type TiptapStore = {
|
||||||
state: Readonly<TiptapState>;
|
state: TiptapState;
|
||||||
actions: TiptapActions;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export function useTiptapStore(initialState?: Partial<TiptapState>) {
|
export function useTiptapStore(initialState?: Partial<TiptapState>) {
|
||||||
@ -36,42 +26,8 @@ export function useTiptapStore(initialState?: Partial<TiptapState>) {
|
|||||||
...initialState,
|
...initialState,
|
||||||
});
|
});
|
||||||
|
|
||||||
const toggleMinimal = () => {
|
|
||||||
state.minimal = !state.minimal;
|
|
||||||
};
|
|
||||||
|
|
||||||
const updateContent = (newContent: string) => {
|
|
||||||
state.content = newContent;
|
|
||||||
};
|
|
||||||
|
|
||||||
const setTheme = (theme: string) => {
|
|
||||||
state.theme = theme;
|
|
||||||
};
|
|
||||||
|
|
||||||
const toggleToolbar = () => {
|
|
||||||
state.hideToolbar = !state.hideToolbar;
|
|
||||||
};
|
|
||||||
|
|
||||||
const toggleMenubar = () => {
|
|
||||||
state.hideMenubar = !state.hideMenubar;
|
|
||||||
};
|
|
||||||
|
|
||||||
const toggleEditable = () => {
|
|
||||||
state.disabled = !state.disabled;
|
|
||||||
};
|
|
||||||
|
|
||||||
const actions: TiptapActions = {
|
|
||||||
toggleMinimal,
|
|
||||||
updateContent,
|
|
||||||
setTheme,
|
|
||||||
toggleToolbar,
|
|
||||||
toggleMenubar,
|
|
||||||
toggleEditable,
|
|
||||||
};
|
|
||||||
|
|
||||||
const store: TiptapStore = {
|
const store: TiptapStore = {
|
||||||
state: readonly(state),
|
state: state,
|
||||||
actions,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
provide(TiptapStoreKey, store);
|
provide(TiptapStoreKey, store);
|
||||||
|
|||||||
@ -1,5 +1,12 @@
|
|||||||
import TiptapEditor from "./views/index.vue";
|
import TiptapEditor from "./views/index.vue";
|
||||||
import { useTiptapStore, useTiptapContext } from "./context/useTiptapStore";
|
import { useTiptapStore, useTiptapContext } from "./context/useTiptapStore";
|
||||||
import { ThemeToggle } from "echo-editor";
|
import { ThemeToggle } from "echo-editor";
|
||||||
|
import EditorActions from "./components/EditorActions.vue";
|
||||||
|
|
||||||
export { TiptapEditor, ThemeToggle, useTiptapStore, useTiptapContext };
|
export {
|
||||||
|
TiptapEditor,
|
||||||
|
ThemeToggle,
|
||||||
|
useTiptapStore,
|
||||||
|
useTiptapContext,
|
||||||
|
EditorActions,
|
||||||
|
};
|
||||||
|
|||||||
@ -1,19 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="min-h-screen bg-background">
|
<div class="">
|
||||||
<EditorActions
|
<EditorActions />
|
||||||
:minimal="state.minimal"
|
|
||||||
:hide-toolbar="state.hideToolbar"
|
|
||||||
:hide-menubar="state.hideMenubar"
|
|
||||||
:disabled="state.disabled"
|
|
||||||
@toggle-minimal="actions.toggleMinimal"
|
|
||||||
@toggle-toolbar="actions.toggleToolbar"
|
|
||||||
@toggle-menubar="actions.toggleMenubar"
|
|
||||||
@toggle-editable="actions.toggleEditable"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<echo-editor
|
<echo-editor
|
||||||
:model-value="state.content"
|
:model-value="state.content"
|
||||||
@update:model-value="actions.updateContent"
|
|
||||||
:extensions="editorExtensions"
|
:extensions="editorExtensions"
|
||||||
:hideToolbar="state.hideToolbar"
|
:hideToolbar="state.hideToolbar"
|
||||||
:hideMenubar="state.hideMenubar || state.minimal"
|
:hideMenubar="state.hideMenubar || state.minimal"
|
||||||
@ -21,13 +10,11 @@
|
|||||||
:disabled="state.disabled"
|
:disabled="state.disabled"
|
||||||
:maxHeight="512"
|
:maxHeight="512"
|
||||||
output="html"
|
output="html"
|
||||||
:theme="state.theme"
|
@update:theme="state.theme"
|
||||||
@update:theme="actions.setTheme"
|
@update:model-value="state.content"
|
||||||
:dark="state.theme === 'dark'"
|
:dark="state.theme === 'dark'"
|
||||||
|
:theme="state.theme"
|
||||||
/>
|
/>
|
||||||
<HtmlOutput :content="state.content" />
|
|
||||||
|
|
||||||
minimal : {{ state.minimal }}
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
@ -35,7 +22,6 @@ import { computed } from "vue";
|
|||||||
import { EchoEditor } from "echo-editor";
|
import { EchoEditor } from "echo-editor";
|
||||||
import { DEMO_CONTENT } from "./initContent";
|
import { DEMO_CONTENT } from "./initContent";
|
||||||
import EditorActions from "../components/EditorActions.vue";
|
import EditorActions from "../components/EditorActions.vue";
|
||||||
import HtmlOutput from "../components/HtmlOutput.vue";
|
|
||||||
import { useEditorConfig } from "../components/useEditorConfig";
|
import { useEditorConfig } from "../components/useEditorConfig";
|
||||||
import { useTiptapStore, type TiptapState } from "../context/useTiptapStore";
|
import { useTiptapStore, type TiptapState } from "../context/useTiptapStore";
|
||||||
|
|
||||||
@ -46,12 +32,14 @@ const props = defineProps<{
|
|||||||
initialState?: Partial<TiptapState>;
|
initialState?: Partial<TiptapState>;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const { state, actions } = useTiptapStore({
|
const { state } = useTiptapStore({
|
||||||
...props.initialState,
|
...props.initialState,
|
||||||
content: props.initialState?.content || DEMO_CONTENT,
|
content: props.initialState?.content || DEMO_CONTENT,
|
||||||
});
|
});
|
||||||
|
|
||||||
const editorExtensions = computed(
|
console.log("Tiptap state:", state);
|
||||||
() => useEditorConfig(state.minimal).extensions
|
|
||||||
);
|
const editorExtensions = computed(() => {
|
||||||
|
return useEditorConfig(state.minimal).extensions.value;
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -1,279 +1,3 @@
|
|||||||
export const DEMO_CONTENT = {
|
export const DEMO_CONTENT = `
|
||||||
type: "doc",
|
<h1 style="text-align: center">Echo Editor</h1><p style="text-align: left">A modern WYSIWYG AI rich text editor based on <a target="_blank" rel="noopener noreferrer nofollow" class="link" href="https://github.com/scrumpy/tiptap" stricturl="true">tiptap</a> and <a target="_blank" rel="noopener noreferrer nofollow" class="link" href="https://www.shadcn-vue.com/" stricturl="true">shadcn ui</a> for Vue.js</p><p style="text-align: left"></p><p style="text-align: left"></p><p style="text-align: left"></p><img height="auto" style="margin-left: auto; margin-right: auto; text-align: center" src="https://picsum.photos/1920/1080.webp?t=1" flipx="false" flipy="false" originwidth="500" originheight="281.25" width="500"><p style="text-align: left"></p><div data-type="horizontalRule"><hr></div><h2 style="text-align: left">Demo</h2><p style="text-align: left">👉<a target="_blank" rel="noopener noreferrer nofollow" class="link" href="https://echo-editor.jzcloud.site/" stricturl="true">Demo</a></p><h2 style="text-align: left">Features</h2><ul style="list-style-type: disc"><li><p style="text-align: left">Use <a target="_blank" rel="noopener noreferrer nofollow" class="link" href="https://www.shadcn-vue.com/" stricturl="true">shadcn ui</a> components</p></li><li><p style="text-align: left">Markdown support</p></li><li><p style="text-align: left">TypeScript support</p></li><li><p style="text-align: left">I18n support</p></li><li><p style="text-align: left">Vue 3.x support</p></li><li><p style="text-align: left">Slash Command</p></li><li><p style="text-align: left">Dark Mode</p></li><li><p style="text-align: left">Multi Column</p></li><li><p style="text-align: left">AI Power</p></li><li><p style="text-align: left">Embed</p></li><li><p style="text-align: left">TailwindCss</p></li></ul><h2 style="text-align: left">Installation</h2><pre vnode="true" code="pnpm add echo-editor // or or yarn add echo-editor // or or npm i echo-editor -S" language="bash" linenumbers="true" wordwrap="false" tabsize="2" shouldfocus="false"><code>pnpm add echo-editor // or or yarn add echo-editor // or or npm i echo-editor -S</code></pre><h3 style="text-align: left">install plugin</h3><pre vnode="true" code="import { createApp } from 'vue' import App from './App.vue' import EchoEditor from 'echo-editor' import 'echo-editor/style.css' const app = createApp(App) app.use(EchoEditor) app.mount('#app')" language="typescript" linenumbers="true" wordwrap="false" tabsize="2" shouldfocus="false"><code>import { createApp } from 'vue' import App from './App.vue' import EchoEditor from 'echo-editor' import 'echo-editor/style.css' const app = createApp(App) app.use(EchoEditor) app.mount('#app')</code></pre><p style="text-align: left"></p>
|
||||||
content: [
|
`;
|
||||||
{
|
|
||||||
type: "heading",
|
|
||||||
attrs: { textAlign: "center", indent: 0, lineHeight: null, level: 1 },
|
|
||||||
content: [{ type: "text", text: "Echo Editor" }],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "paragraph",
|
|
||||||
attrs: { textAlign: "left", indent: 0, lineHeight: null },
|
|
||||||
content: [
|
|
||||||
{
|
|
||||||
type: "text",
|
|
||||||
text: "A modern WYSIWYG AI rich text editor based on ",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "text",
|
|
||||||
marks: [
|
|
||||||
{
|
|
||||||
type: "link",
|
|
||||||
attrs: {
|
|
||||||
href: "https://github.com/scrumpy/tiptap",
|
|
||||||
target: "_blank",
|
|
||||||
rel: "noopener noreferrer nofollow",
|
|
||||||
class: "link",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
text: "tiptap",
|
|
||||||
},
|
|
||||||
{ type: "text", text: " and " },
|
|
||||||
{
|
|
||||||
type: "text",
|
|
||||||
marks: [
|
|
||||||
{
|
|
||||||
type: "link",
|
|
||||||
attrs: {
|
|
||||||
href: "https://www.shadcn-vue.com/",
|
|
||||||
target: "_blank",
|
|
||||||
rel: "noopener noreferrer nofollow",
|
|
||||||
class: "link",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
text: "shadcn ui",
|
|
||||||
},
|
|
||||||
{ type: "text", text: " for Vue.js" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "paragraph",
|
|
||||||
attrs: { textAlign: "left", indent: 0, lineHeight: null },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "paragraph",
|
|
||||||
attrs: { textAlign: "left", indent: 0, lineHeight: null },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "paragraph",
|
|
||||||
attrs: { textAlign: "left", indent: 0, lineHeight: null },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "image",
|
|
||||||
attrs: {
|
|
||||||
textAlign: "center",
|
|
||||||
src: "https://picsum.photos/1920/1080.webp?t=1",
|
|
||||||
alt: null,
|
|
||||||
title: null,
|
|
||||||
width: 500,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "paragraph",
|
|
||||||
attrs: { textAlign: "left", indent: 0, lineHeight: null },
|
|
||||||
},
|
|
||||||
{ type: "horizontalRule" },
|
|
||||||
{
|
|
||||||
type: "heading",
|
|
||||||
attrs: { textAlign: "left", indent: 0, lineHeight: null, level: 2 },
|
|
||||||
content: [{ type: "text", text: "Demo" }],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "paragraph",
|
|
||||||
attrs: { textAlign: "left", indent: 0, lineHeight: null },
|
|
||||||
content: [
|
|
||||||
{ type: "text", text: "👉" },
|
|
||||||
{
|
|
||||||
type: "text",
|
|
||||||
marks: [
|
|
||||||
{
|
|
||||||
type: "link",
|
|
||||||
attrs: {
|
|
||||||
href: "https://echo-editor.jzcloud.site/",
|
|
||||||
target: "_blank",
|
|
||||||
rel: "noopener noreferrer nofollow",
|
|
||||||
class: "link",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
text: "Demo",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "heading",
|
|
||||||
attrs: { textAlign: "left", indent: 0, lineHeight: null, level: 2 },
|
|
||||||
content: [{ type: "text", text: "Features" }],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "bulletList",
|
|
||||||
attrs: { listStyleType: "disc" },
|
|
||||||
content: [
|
|
||||||
{
|
|
||||||
type: "listItem",
|
|
||||||
content: [
|
|
||||||
{
|
|
||||||
type: "paragraph",
|
|
||||||
attrs: { textAlign: "left", indent: 0, lineHeight: null },
|
|
||||||
content: [
|
|
||||||
{ type: "text", text: "Use " },
|
|
||||||
{
|
|
||||||
type: "text",
|
|
||||||
marks: [
|
|
||||||
{
|
|
||||||
type: "link",
|
|
||||||
attrs: {
|
|
||||||
href: "https://www.shadcn-vue.com/",
|
|
||||||
target: "_blank",
|
|
||||||
rel: "noopener noreferrer nofollow",
|
|
||||||
class: "link",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
text: "shadcn ui",
|
|
||||||
},
|
|
||||||
{ type: "text", text: " components" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "listItem",
|
|
||||||
content: [
|
|
||||||
{
|
|
||||||
type: "paragraph",
|
|
||||||
attrs: { textAlign: "left", indent: 0, lineHeight: null },
|
|
||||||
content: [{ type: "text", text: "Markdown support" }],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "listItem",
|
|
||||||
content: [
|
|
||||||
{
|
|
||||||
type: "paragraph",
|
|
||||||
attrs: { textAlign: "left", indent: 0, lineHeight: null },
|
|
||||||
content: [{ type: "text", text: "TypeScript support" }],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "listItem",
|
|
||||||
content: [
|
|
||||||
{
|
|
||||||
type: "paragraph",
|
|
||||||
attrs: { textAlign: "left", indent: 0, lineHeight: null },
|
|
||||||
content: [{ type: "text", text: "I18n support" }],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "listItem",
|
|
||||||
content: [
|
|
||||||
{
|
|
||||||
type: "paragraph",
|
|
||||||
attrs: { textAlign: "left", indent: 0, lineHeight: null },
|
|
||||||
content: [{ type: "text", text: "Vue 3.x support" }],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "listItem",
|
|
||||||
content: [
|
|
||||||
{
|
|
||||||
type: "paragraph",
|
|
||||||
attrs: { textAlign: "left", indent: 0, lineHeight: null },
|
|
||||||
content: [{ type: "text", text: "Slash Command" }],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "listItem",
|
|
||||||
content: [
|
|
||||||
{
|
|
||||||
type: "paragraph",
|
|
||||||
attrs: { textAlign: "left", indent: 0, lineHeight: null },
|
|
||||||
content: [{ type: "text", text: "Dark Mode" }],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "listItem",
|
|
||||||
content: [
|
|
||||||
{
|
|
||||||
type: "paragraph",
|
|
||||||
attrs: { textAlign: "left", indent: 0, lineHeight: null },
|
|
||||||
content: [{ type: "text", text: "Multi Column" }],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "listItem",
|
|
||||||
content: [
|
|
||||||
{
|
|
||||||
type: "paragraph",
|
|
||||||
attrs: { textAlign: "left", indent: 0, lineHeight: null },
|
|
||||||
content: [{ type: "text", text: "AI Power" }],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "listItem",
|
|
||||||
content: [
|
|
||||||
{
|
|
||||||
type: "paragraph",
|
|
||||||
attrs: { textAlign: "left", indent: 0, lineHeight: null },
|
|
||||||
content: [{ type: "text", text: "Embed" }],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "listItem",
|
|
||||||
content: [
|
|
||||||
{
|
|
||||||
type: "paragraph",
|
|
||||||
attrs: { textAlign: "left", indent: 0, lineHeight: null },
|
|
||||||
content: [{ type: "text", text: "TailwindCss" }],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "heading",
|
|
||||||
attrs: { textAlign: "left", indent: 0, lineHeight: null, level: 2 },
|
|
||||||
content: [{ type: "text", text: "Installation" }],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "codeBlock",
|
|
||||||
attrs: { language: "bash" },
|
|
||||||
content: [
|
|
||||||
{
|
|
||||||
type: "text",
|
|
||||||
text: "pnpm add echo-editor\n// or\nor yarn add echo-editor\n// or\nor npm i echo-editor -S",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "heading",
|
|
||||||
attrs: { textAlign: "left", indent: 0, lineHeight: null, level: 3 },
|
|
||||||
content: [{ type: "text", text: "install plugin" }],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "codeBlock",
|
|
||||||
attrs: { language: "typescript" },
|
|
||||||
content: [
|
|
||||||
{
|
|
||||||
type: "text",
|
|
||||||
text: "import { createApp } from 'vue'\nimport App from './App.vue'\nimport EchoEditor from 'echo-editor'\nimport 'echo-editor/style.css'\nconst app = createApp(App)\napp.use(EchoEditor)\napp.mount('#app')",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "paragraph",
|
|
||||||
attrs: { textAlign: "left", indent: 0, lineHeight: null },
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user