# 快速开始

安装基础包，创建编辑器，再试用输入、格式与撤销。

这一页创建一个能输入文字的编辑器，使用 Core、常用内容扩展和浏览器原生 DOM 视图。Vue 项目可以直接跟随[单组件教程](/build/project)。

## 安装基础能力

```sh [终端]
pnpm add @quirekit/core@alpha @quirekit/starter-kit@alpha @quirekit/dom-view@alpha @quirekit/pm-view@alpha
```

这些基础包均为 MIT，使用同一发布批次。Core 提供实例与命令；StarterKit 提供段落、标题和常用格式；DOM 视图接收浏览器输入，PM 基础样式处理空白与选区显示。

## 创建编辑器

页面中准备一个 `id="editor"` 的元素，在它出现后创建实例：

```ts [创建实例]
import { Editor } from '@quirekit/core'
import { StarterKit } from '@quirekit/starter-kit'
import { DomViewExtension } from '@quirekit/dom-view'
import '@quirekit/pm-view/style/prosemirror.css'

const editor = new Editor({
  element: document.getElementById('editor'),
  mode: 'dom',
  extensions: [StarterKit, DomViewExtension],
  content: '<p>Hello, QuireKit.</p>',
})
```

`element` 决定放在哪里，`extensions` 决定支持什么内容与行为，`content` 提供初始正文。现在点击文字就能输入，也可以用快捷键加粗和撤销。

## 试用按钮与内容

下面在同一个编辑器上增加了加粗、撤销与下载按钮。选中文字，点击加粗，再撤销。下载 JSON 可以看到实际修改后的文档结构。

### core/editor.vue

```vue
<script setup lang="ts">
import { computed, onBeforeUnmount, onMounted, ref, shallowRef } from "vue";
import type { Editor } from "@quirekit/core";
import { QuireButton } from "@quirekit/ui/vue";
import { createExampleEditor } from "./create";
import { downloadJson } from "../shared/download";
import "@quirekit/pm-view/style/prosemirror.css";

const props = withDefaults(defineProps<{
  /** Initial copy and control language. */ locale?: "zh-CN" | "en";
  /** Visible controls for the capability being demonstrated. */ tools?: "formatting" | "structure";
}>(), { locale: "zh-CN" });
const host = ref<HTMLElement>();
const instance = shallowRef<Editor>();
const copy = computed(() => props.locale === "en"
  ? { bold: "Bold", undo: "Undo", save: "Download JSON", label: "Editable document" }
  : { bold: "加粗", undo: "撤销", save: "下载 JSON", label: "可编辑文档" });
onMounted(() => { if (host.value) instance.value = createExampleEditor(host.value, props.locale); });
onBeforeUnmount(() => instance.value?.destroy());
/** Downloads the actual editor state instead of a second copy maintained by the UI. */
function download(): void { if (instance.value) downloadJson(instance.value.getJSON(), "quirekit-document.json"); }
</script>
<template>
  <div class="core-example">
    <div class="core-example-tools">
      <QuireButton variant="outline" @click="instance?.chain().focus().toggleBold().run()">{{ copy.bold }}</QuireButton>
      <template v-if="tools === 'formatting'">
        <QuireButton variant="outline" @click="instance?.chain().focus().toggleItalic().run()">{{ locale === 'en' ? 'Italic' : '斜体' }}</QuireButton>
        <QuireButton variant="outline" @click="instance?.chain().focus().toggleUnderline().run()">{{ locale === 'en' ? 'Underline' : '下划线' }}</QuireButton>
      </template>
      <template v-if="tools === 'structure'">
        <QuireButton variant="outline" @click="instance?.chain().focus().toggleHeading({ level: 2 }).run()">{{ locale === 'en' ? 'Heading 2' : '二级标题' }}</QuireButton>
        <QuireButton variant="outline" @click="instance?.chain().focus().toggleBulletList().run()">{{ locale === 'en' ? 'Bullet list' : '项目列表' }}</QuireButton>
      </template>
      <QuireButton variant="outline" @click="instance?.chain().focus().undo().run()">{{ copy.undo }}</QuireButton>
      <QuireButton variant="outline" @click="download">{{ copy.save }}</QuireButton>
    </div>
    <div ref="host" class="core-example-document" role="group" :aria-label="copy.label" />
  </div>
</template>
<style scoped>
.core-example { padding: 20px; background: var(--qk-color-surface-page); }
.core-example-tools { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 20px; }
.core-example-document { border: 1px solid var(--qk-color-border-default); border-radius: 6px; padding: 20px; text-align: start; }
.core-example-document :deep(.ProseMirror) { min-height: 180px; line-height: 1.8; }
/* A writing surface expresses focus through its caret and selection, without a second frame. */
.core-example-document :deep(.ProseMirror:focus), .core-example-document :deep(.ProseMirror:focus-visible) { outline: none; box-shadow: none; }
.core-example-document :deep(h2) { font-size: 22px; margin: 0 0 12px; }
.core-example-document :deep(p) { margin: 8px 0; }
</style>

```

### core/create.ts

```ts
import { Editor } from "@quirekit/core";
import { StarterKit } from "@quirekit/starter-kit";
import { DomViewExtension } from "@quirekit/dom-view";
import { writingShortcuts } from "./shortcuts";

/**
 * Mounts a minimal editor with the Tiptap-style Core API and an explicit native DOM view.
 * @param element - Browser-owned mount target.
 * @param locale - Language for initial sample copy only.
 * @returns The caller-owned editor; destroy it when its host unmounts.
 */
export function createExampleEditor(element: HTMLElement, locale: "zh-CN" | "en"): Editor {
  return new Editor({
    element,
    mode: "dom",
    extensions: [StarterKit, DomViewExtension, writingShortcuts],
    content: { type: "doc", content: [
      { type: "heading", attrs: { level: 2 }, content: [{ type: "text", text: locale === "en" ? "Start with your words." : "从你写下的文字开始。" }] },
      { type: "paragraph", content: [{ type: "text", text: locale === "en" ? "Select some text, make it bold, or add a new paragraph. This is a real QuireKit Core editor." : "选择一段文字，加粗，或另起一段。这里运行的是真实的 QuireKit Core 编辑器。" }] },
    ] },
  });
}

```

### core/shortcuts.ts

```ts
import { Extension } from "@quirekit/core";

/** A host-authored behavior extension using the same typed command registry as the toolbar. */
export const writingShortcuts = Extension.create({
  name: "writingShortcuts",
  /** @returns A keyboard binding that participates in the editor's existing history. */
  addKeyboardShortcuts() {
    return { "Mod-Shift-b": () => this.editor?.commands.toggleBold() ?? false };
  },
});

```

### shared/download.ts

```ts
/**
 * Downloads canonical JSON through a short-lived browser URL.
 * @param document - Serializable canonical content.
 * @param name - Download filename chosen by the host.
 */
export function downloadJson(document: unknown, name: string): void {
  const url = URL.createObjectURL(new Blob([JSON.stringify(document, null, 2)], { type: "application/json" }));
  const link = window.document.createElement("a");
  link.href = url;
  link.download = name;
  link.click();
  window.setTimeout(() => URL.revokeObjectURL(url), 1000);
}

```

这里的 `core/editor.vue` 放按钮，`core/create.ts` 创建实例，`core/shortcuts.ts` 演示扩展快捷键，`shared/download.ts` 负责下载。源码文件选择器可按需查阅；带控件的示例另需 UI 主题与样式配置。

## 离开页面时释放

```ts [页面或组件退出时]
editor.destroy()
```

不要在创建后立刻销毁；在组件卸载或结束使用时调用。示例里的编辑只保留在当前会话，自己的产品需要另外接入[保存与恢复](/guide/persistence)。

接下来可以读 [Vue 接入](/guide/vue)、[文档与 Schema](/concepts/document)，或沿[构建自己的编辑器](/build)加入 Canvas 和产品界面。
