[{"data":1,"prerenderedAt":544},["ShallowReactive",2],{"quirekit-doc:\u002Fen\u002Fbuild\u002Fproject":3},{"id":4,"title":5,"body":6,"description":534,"extension":535,"keywords":536,"locale":537,"meta":538,"navigation":186,"order":36,"path":539,"section":540,"seo":541,"stem":542,"__hash__":543},"docs\u002Fbuild\u002Fproject.en.md","Build your first editor",{"type":7,"value":8,"toc":528},"minimark",[9,13,16,21,58,76,80,87,387,405,414,418,429,492,495,499,503,516,524],[10,11,12],"p",{},"This chapter adds an editor to a Vue page. Start with the browser's native DOM view to learn Core; later chapters add Canvas, pagination and your product interface.",[10,14,15],{},"You should be familiar with Vue components and lifecycle hooks, and have Node.js and pnpm installed. In an existing Vue 3 project, start with the dependency installation.",[17,18,20],"h2",{"id":19},"_1-prepare-a-vue-project","1. Prepare a Vue project",[22,23,29],"pre",{"className":24,"code":25,"filename":26,"language":27,"meta":28,"style":28},"language-sh shiki shiki-themes github-light github-light github-dark","pnpm create vite my-editor --template vue-ts\ncd my-editor\npnpm install\npnpm add @quirekit\u002Fcore@alpha @quirekit\u002Fstarter-kit@alpha @quirekit\u002Fdom-view@alpha @quirekit\u002Fpm-view@alpha\n","Terminal","sh","",[30,31,32,40,46,52],"code",{"__ignoreMap":28},[33,34,37],"span",{"class":35,"line":36},"line",1,[33,38,39],{},"pnpm create vite my-editor --template vue-ts\n",[33,41,43],{"class":35,"line":42},2,[33,44,45],{},"cd my-editor\n",[33,47,49],{"class":35,"line":48},3,[33,50,51],{},"pnpm install\n",[33,53,55],{"class":35,"line":54},4,[33,56,57],{},"pnpm add @quirekit\u002Fcore@alpha @quirekit\u002Fstarter-kit@alpha @quirekit\u002Fdom-view@alpha @quirekit\u002Fpm-view@alpha\n",[10,59,60,63,64,67,68,71,72,75],{},[30,61,62],{},"core"," manages content and commands. ",[30,65,66],{},"starter-kit"," provides paragraphs, headings and common formatting. ",[30,69,70],{},"dom-view"," displays editable DOM, and the ",[30,73,74],{},"pm-view"," stylesheet preserves whitespace and native selection presentation. Use matching QuireKit release versions.",[17,77,79],{"id":78},"_2-create-an-editor-component","2. Create an editor component",[10,81,82,83,86],{},"Create ",[30,84,85],{},"src\u002FEditor.vue",". Vue supplies an empty element; Editor manages its editable contents after mounting.",[22,88,92],{"className":89,"code":90,"filename":85,"language":91,"meta":28,"style":28},"language-vue shiki shiki-themes github-light github-light github-dark","\u003Cscript setup lang=\"ts\">\nimport { onBeforeUnmount, onMounted, ref } from 'vue'\nimport { Editor } from '@quirekit\u002Fcore'\nimport { StarterKit } from '@quirekit\u002Fstarter-kit'\nimport { DomViewExtension } from '@quirekit\u002Fdom-view'\nimport '@quirekit\u002Fpm-view\u002Fstyle\u002Fprosemirror.css'\n\nconst element = ref\u003CHTMLElement>()\nlet editor: Editor | undefined\n\nonMounted(() => {\n  editor = new Editor({\n    element: element.value,\n    mode: 'dom',\n    extensions: [StarterKit, DomViewExtension],\n    content: '\u003Cp>My first QuireKit editor.\u003C\u002Fp>',\n  })\n})\n\nonBeforeUnmount(() => editor?.destroy())\n\u003C\u002Fscript>\n\n\u003Ctemplate>\u003Cdiv ref=\"element\" \u002F>\u003C\u002Ftemplate>\n","vue",[30,93,94,121,136,148,160,173,181,188,212,233,238,253,269,275,287,293,304,310,316,321,340,350,355],{"__ignoreMap":28},[33,95,96,100,104,108,111,114,118],{"class":35,"line":36},[33,97,99],{"class":98},"sVPnS","\u003C",[33,101,103],{"class":102},"su0ou","script",[33,105,107],{"class":106},"sgQzM"," setup",[33,109,110],{"class":106}," lang",[33,112,113],{"class":98},"=",[33,115,117],{"class":116},"s-HEn","\"ts\"",[33,119,120],{"class":98},">\n",[33,122,123,127,130,133],{"class":35,"line":42},[33,124,126],{"class":125},"sDD9d","import",[33,128,129],{"class":98}," { onBeforeUnmount, onMounted, ref } ",[33,131,132],{"class":125},"from",[33,134,135],{"class":116}," 'vue'\n",[33,137,138,140,143,145],{"class":35,"line":48},[33,139,126],{"class":125},[33,141,142],{"class":98}," { Editor } ",[33,144,132],{"class":125},[33,146,147],{"class":116}," '@quirekit\u002Fcore'\n",[33,149,150,152,155,157],{"class":35,"line":54},[33,151,126],{"class":125},[33,153,154],{"class":98}," { StarterKit } ",[33,156,132],{"class":125},[33,158,159],{"class":116}," '@quirekit\u002Fstarter-kit'\n",[33,161,163,165,168,170],{"class":35,"line":162},5,[33,164,126],{"class":125},[33,166,167],{"class":98}," { DomViewExtension } ",[33,169,132],{"class":125},[33,171,172],{"class":116}," '@quirekit\u002Fdom-view'\n",[33,174,176,178],{"class":35,"line":175},6,[33,177,126],{"class":125},[33,179,180],{"class":116}," '@quirekit\u002Fpm-view\u002Fstyle\u002Fprosemirror.css'\n",[33,182,184],{"class":35,"line":183},7,[33,185,187],{"emptyLinePlaceholder":186},true,"\n",[33,189,191,194,198,201,204,206,209],{"class":35,"line":190},8,[33,192,193],{"class":125},"const",[33,195,197],{"class":196},"sUNQB"," element",[33,199,200],{"class":125}," =",[33,202,203],{"class":106}," ref",[33,205,99],{"class":98},[33,207,208],{"class":106},"HTMLElement",[33,210,211],{"class":98},">()\n",[33,213,215,218,221,224,227,230],{"class":35,"line":214},9,[33,216,217],{"class":125},"let",[33,219,220],{"class":98}," editor",[33,222,223],{"class":125},":",[33,225,226],{"class":106}," Editor",[33,228,229],{"class":125}," |",[33,231,232],{"class":196}," undefined\n",[33,234,236],{"class":35,"line":235},10,[33,237,187],{"emptyLinePlaceholder":186},[33,239,241,244,247,250],{"class":35,"line":240},11,[33,242,243],{"class":106},"onMounted",[33,245,246],{"class":98},"(() ",[33,248,249],{"class":125},"=>",[33,251,252],{"class":98}," {\n",[33,254,256,259,261,264,266],{"class":35,"line":255},12,[33,257,258],{"class":98},"  editor ",[33,260,113],{"class":125},[33,262,263],{"class":125}," new",[33,265,226],{"class":106},[33,267,268],{"class":98},"({\n",[33,270,272],{"class":35,"line":271},13,[33,273,274],{"class":98},"    element: element.value,\n",[33,276,278,281,284],{"class":35,"line":277},14,[33,279,280],{"class":98},"    mode: ",[33,282,283],{"class":116},"'dom'",[33,285,286],{"class":98},",\n",[33,288,290],{"class":35,"line":289},15,[33,291,292],{"class":98},"    extensions: [StarterKit, DomViewExtension],\n",[33,294,296,299,302],{"class":35,"line":295},16,[33,297,298],{"class":98},"    content: ",[33,300,301],{"class":116},"'\u003Cp>My first QuireKit editor.\u003C\u002Fp>'",[33,303,286],{"class":98},[33,305,307],{"class":35,"line":306},17,[33,308,309],{"class":98},"  })\n",[33,311,313],{"class":35,"line":312},18,[33,314,315],{"class":98},"})\n",[33,317,319],{"class":35,"line":318},19,[33,320,187],{"emptyLinePlaceholder":186},[33,322,324,327,329,331,334,337],{"class":35,"line":323},20,[33,325,326],{"class":106},"onBeforeUnmount",[33,328,246],{"class":98},[33,330,249],{"class":125},[33,332,333],{"class":98}," editor?.",[33,335,336],{"class":106},"destroy",[33,338,339],{"class":98},"())\n",[33,341,343,346,348],{"class":35,"line":342},21,[33,344,345],{"class":98},"\u003C\u002F",[33,347,103],{"class":102},[33,349,120],{"class":98},[33,351,353],{"class":35,"line":352},22,[33,354,187],{"emptyLinePlaceholder":186},[33,356,358,360,363,366,369,371,373,376,380,383,385],{"class":35,"line":357},23,[33,359,99],{"class":98},[33,361,362],{"class":102},"template",[33,364,365],{"class":98},">\u003C",[33,367,368],{"class":102},"div",[33,370,203],{"class":106},[33,372,113],{"class":98},[33,374,375],{"class":116},"\"element\"",[33,377,379],{"class":378},"shEpO"," \u002F",[33,381,382],{"class":98},">\u003C\u002F",[33,384,362],{"class":102},[33,386,120],{"class":98},[10,388,389,392,393,396,397,400,401,404],{},[30,390,391],{},"element"," selects the display location, ",[30,394,395],{},"extensions"," determines supported content, and ",[30,398,399],{},"content"," supplies the initial document. ",[30,402,403],{},"mode: 'dom'"," selects the installed DOM view. Create the instance once, rather than recreating it on each edit.",[10,406,407,409,410,413],{},[30,408,243],{}," waits for the host element; ",[30,411,412],{},"destroy()"," releases the view and listeners. With SSR, the server renders only the outer element and the browser creates the editor.",[17,415,417],{"id":416},"_3-use-it-in-your-page","3. Use it in your page",[10,419,420,421,424,425,428],{},"Import the component in ",[30,422,423],{},"src\u002FApp.vue",", then run ",[30,426,427],{},"pnpm dev",".",[22,430,432],{"className":89,"code":431,"filename":423,"language":91,"meta":28,"style":28},"\u003Cscript setup lang=\"ts\">\nimport Editor from '.\u002FEditor.vue'\n\u003C\u002Fscript>\n\n\u003Ctemplate>\u003CEditor \u002F>\u003C\u002Ftemplate>\n",[30,433,434,450,462,470,474],{"__ignoreMap":28},[33,435,436,438,440,442,444,446,448],{"class":35,"line":36},[33,437,99],{"class":98},[33,439,103],{"class":102},[33,441,107],{"class":106},[33,443,110],{"class":106},[33,445,113],{"class":98},[33,447,117],{"class":116},[33,449,120],{"class":98},[33,451,452,454,457,459],{"class":35,"line":42},[33,453,126],{"class":125},[33,455,456],{"class":98}," Editor ",[33,458,132],{"class":125},[33,460,461],{"class":116}," '.\u002FEditor.vue'\n",[33,463,464,466,468],{"class":35,"line":48},[33,465,345],{"class":98},[33,467,103],{"class":102},[33,469,120],{"class":98},[33,471,472],{"class":35,"line":54},[33,473,187],{"emptyLinePlaceholder":186},[33,475,476,478,480,482,485,488,490],{"class":35,"line":162},[33,477,99],{"class":98},[33,479,362],{"class":102},[33,481,365],{"class":98},[33,483,484],{"class":102},"Editor",[33,486,487],{"class":98}," \u002F>\u003C\u002F",[33,489,362],{"class":102},[33,491,120],{"class":98},[10,493,494],{},"Click to type, drag to select, and use your system undo shortcut. This example uses the same integration and has just one component source file.",[496,497],"docs-demo",{"name":498},"tutorial\u002Feditor",[17,500,502],{"id":501},"what-comes-next","What comes next",[10,504,505,506,511,512,428],{},"The editor has no toolbar or paginated workspace yet. Learn ",[507,508,510],"a",{"href":509},"\u002Fen\u002Fbuild\u002Fmodel","the document model"," next: how structured content works and why articles and Word documents use different extensions. Then ",[507,513,515],{"href":514},"\u002Fen\u002Fbuild\u002Fview","mount Canvas\u002FSVG",[10,517,518,519,523],{},"Already familiar with these basics? The ",[507,520,522],{"href":521},"\u002Fen\u002Fbuild\u002Freference","complete workspace reference"," explains the files for state management and file operations individually.",[525,526,527],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sVPnS, html code.shiki .sVPnS{--shiki-default:#24292E;--shiki-light:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .su0ou, html code.shiki .su0ou{--shiki-default:#22863A;--shiki-light:#22863A;--shiki-dark:#85E89D}html pre.shiki code .sgQzM, html code.shiki .sgQzM{--shiki-default:#6F42C1;--shiki-light:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .s-HEn, html code.shiki .s-HEn{--shiki-default:#032F62;--shiki-light:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sDD9d, html code.shiki .sDD9d{--shiki-default:#D73A49;--shiki-light:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sUNQB, html code.shiki .sUNQB{--shiki-default:#005CC5;--shiki-light:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .shEpO, html code.shiki .shEpO{--shiki-default:#B31D28;--shiki-default-font-style:italic;--shiki-light:#B31D28;--shiki-light-font-style:italic;--shiki-dark:#FDAEB7;--shiki-dark-font-style:italic}",{"title":28,"searchDepth":42,"depth":42,"links":529},[530,531,532,533],{"id":19,"depth":42,"text":20},{"id":78,"depth":42,"text":79},{"id":416,"depth":42,"text":417},{"id":501,"depth":42,"text":502},"Start with one Vue component and understand creation, mounting and cleanup.","md",null,"en",{},"\u002Fen\u002Fbuild\u002Fproject","Build a product",{"title":5,"description":534},"build\u002Fproject.en","UDdzXIumyBR7QCR6_4Fiu792hVb51FNTO79tn2KNdKg",1793045210203]