|
1 | 1 | <template>
|
2 | 2 | <BaseLayout>
|
3 | 3 | <Toast ref="toastRef" />
|
4 |
| - <Editor v-on:change="handleChange" v-bind:initialCode="state.code"></Editor> |
| 4 | + <Editor v-on:change="handleChange" v-bind:initialCode="state.code" v-bind:opsState="state.opsFromStorage"></Editor> |
5 | 5 | <Toolbar>
|
6 | 6 | <Menu triggerLabel="Menu">
|
7 |
| - <MenuItem label="Copy as Markdown" @click="handleCopyAsMD" |
8 |
| - modifier="⌘ + ⇧ + c" |
9 |
| - /> |
| 7 | + <MenuItem label="Copy as Markdown" @click="handleCopyAsMD" modifier="⌘ + ⇧ + c" /> |
10 | 8 | <MenuItem label="Copy as HTML" @click="handleCopyAsHTML" />
|
11 | 9 | <MenuItem label="Save File" modifier="⌘ + s" @click="handleSaveFile" />
|
12 |
| - <MenuItem |
13 |
| - label="Save File as HTML" |
14 |
| - modifier="⌘ + ⇧ + s " |
15 |
| - @click="handleSaveAsHTML" |
16 |
| - /> |
| 10 | + <MenuItem label="Save File as HTML" modifier="⌘ + ⇧ + s " @click="handleSaveAsHTML" /> |
17 | 11 | <MenuItem label="Save File as PDF" @click="handleSaveAsPDF" />
|
18 | 12 | <MenuItem label="Save File as Image" @click="handleSaveAsImage" />
|
19 | 13 | </Menu>
|
20 | 14 | <div class="flex align-center">
|
21 |
| - <Button |
22 |
| - class="trigger ghost" |
23 |
| - v-bind:class="{ active: state.copied }" |
24 |
| - @click="handleCopyAsHTML" |
25 |
| - > |
26 |
| - <svg |
27 |
| - v-if="!state.copied" |
28 |
| - xmlns="http://www.w3.org/2000/svg" |
29 |
| - width="24" |
30 |
| - height="24" |
31 |
| - viewBox="0 0 24 24" |
32 |
| - stroke-width="1.5" |
33 |
| - stroke="currentColor" |
34 |
| - fill="none" |
35 |
| - stroke-linecap="round" |
36 |
| - stroke-linejoin="round" |
37 |
| - > |
| 15 | + <Button class="trigger ghost" v-bind:class="{ active: state.copied }" @click="handleCopyAsHTML"> |
| 16 | + <svg v-if="!state.copied" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" |
| 17 | + stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"> |
38 | 18 | <path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
|
39 | 19 | <rect x="8" y="8" width="12" height="12" rx="2"></rect>
|
40 |
| - <path |
41 |
| - d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2" |
42 |
| - ></path> |
| 20 | + <path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2"></path> |
43 | 21 | </svg>
|
44 |
| - <svg |
45 |
| - v-if="state.copied" |
46 |
| - xmlns="http://www.w3.org/2000/svg" |
47 |
| - width="24" |
48 |
| - height="24" |
49 |
| - viewBox="0 0 24 24" |
50 |
| - stroke-width="1.5" |
51 |
| - stroke="currentColor" |
52 |
| - fill="none" |
53 |
| - stroke-linecap="round" |
54 |
| - stroke-linejoin="round" |
55 |
| - > |
| 22 | + <svg v-if="state.copied" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" |
| 23 | + stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"> |
56 | 24 | <path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
|
57 | 25 | <circle cx="12" cy="12" r="9"></circle>
|
58 | 26 | <path d="M9 12l2 2l4 -4"></path>
|
@@ -82,22 +50,32 @@ import html2pdf from "html2pdf.js";
|
82 | 50 | import getMDStyles from "../lib/get-md-styles";
|
83 | 51 | import toImage from "dom-to-image";
|
84 | 52 | import download from "downloadjs";
|
| 53 | +import { deltaToMarkdown } from "../lib/quill/delta-md.js"; |
85 | 54 |
|
86 | 55 | const toastRef = ref(null);
|
87 | 56 |
|
88 | 57 | const STORAGE_TOKEN = Symbol("reaper-mark").toString();
|
89 | 58 |
|
90 | 59 | const getDefaultCode = () => {
|
91 |
| - const existingCode = localStorage.getItem(STORAGE_TOKEN); |
92 |
| - if (existingCode && existingCode.length) { |
93 |
| - return existingCode; |
| 60 | + const existingState = localStorage.getItem(STORAGE_TOKEN); |
| 61 | + try { |
| 62 | + const ops = JSON.parse(existingState || []) |
| 63 | + const markdownText = deltaToMarkdown(ops) |
| 64 | + return markdownText; |
| 65 | + } catch (err) { |
| 66 | + return defaultMarkdownText |
94 | 67 | }
|
95 |
| - return defaultMarkdownText; |
| 68 | +}; |
| 69 | +
|
| 70 | +const getFromStorage = () => { |
| 71 | + const existingState = localStorage.getItem(STORAGE_TOKEN) || []; |
| 72 | + return existingState; |
96 | 73 | };
|
97 | 74 |
|
98 | 75 | const state = reactive({
|
99 | 76 | copied: false,
|
100 | 77 | code: getDefaultCode(),
|
| 78 | + opsFromStorage: getFromStorage(), |
101 | 79 | });
|
102 | 80 |
|
103 | 81 | onMounted(() => {
|
@@ -125,17 +103,17 @@ function shortcutListener(e) {
|
125 | 103 | }
|
126 | 104 | }
|
127 | 105 |
|
128 |
| -function handleChange(code) { |
| 106 | +function handleChange({ code, ops }) { |
129 | 107 | state.code = code;
|
130 |
| - localStorage.setItem(STORAGE_TOKEN, code); |
| 108 | + localStorage.setItem(STORAGE_TOKEN, ops); |
131 | 109 | }
|
132 | 110 |
|
133 |
| -async function handleCopyAsMD(){ |
| 111 | +async function handleCopyAsMD() { |
134 | 112 | if (!state.code) {
|
135 | 113 | return;
|
136 | 114 | }
|
137 |
| - await copy(state.code) |
138 |
| - state.copied = true |
| 115 | + await copy(state.code); |
| 116 | + state.copied = true; |
139 | 117 | setTimeout(() => {
|
140 | 118 | state.copied = false;
|
141 | 119 | }, 2500);
|
|
0 commit comments