update note content
This commit is contained in:
40
package-lock.json
generated
40
package-lock.json
generated
@@ -31,12 +31,14 @@
|
|||||||
"lodash-es": "^4.17.21",
|
"lodash-es": "^4.17.21",
|
||||||
"marked": "^4.3.0",
|
"marked": "^4.3.0",
|
||||||
"shortid": "^2.2.16",
|
"shortid": "^2.2.16",
|
||||||
|
"turndown": "^7.1.2",
|
||||||
"vue": "^3.3.1"
|
"vue": "^3.3.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/dompurify": "^3.0.2",
|
"@types/dompurify": "^3.0.2",
|
||||||
"@types/lodash-es": "^4.17.7",
|
"@types/lodash-es": "^4.17.7",
|
||||||
"@types/shortid": "^0.0.29",
|
"@types/shortid": "^0.0.29",
|
||||||
|
"@types/turndown": "^5.0.1",
|
||||||
"@vitejs/plugin-vue": "^4.2.2",
|
"@vitejs/plugin-vue": "^4.2.2",
|
||||||
"autoprefixer": "^10.4.14",
|
"autoprefixer": "^10.4.14",
|
||||||
"postcss": "^8.4.23",
|
"postcss": "^8.4.23",
|
||||||
@@ -1545,6 +1547,12 @@
|
|||||||
"integrity": "sha512-NfQ4gyz38SL8sDNrSixxU2Os1a5xcdFxipAFxYEuLUlvU2uDwS4NUpsImcf1//SlWItCVMMLiylsxbmNMToV/g==",
|
"integrity": "sha512-NfQ4gyz38SL8sDNrSixxU2Os1a5xcdFxipAFxYEuLUlvU2uDwS4NUpsImcf1//SlWItCVMMLiylsxbmNMToV/g==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/turndown": {
|
||||||
|
"version": "5.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/turndown/-/turndown-5.0.1.tgz",
|
||||||
|
"integrity": "sha512-N8Ad4e3oJxh9n9BiZx9cbe/0M3kqDpOTm2wzj13wdDUxDPjfjloWIJaquZzWE1cYTAHpjOH3rcTnXQdpEfS/SQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/@types/web-bluetooth": {
|
"node_modules/@types/web-bluetooth": {
|
||||||
"version": "0.0.17",
|
"version": "0.0.17",
|
||||||
"resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.17.tgz",
|
"resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.17.tgz",
|
||||||
@@ -2255,6 +2263,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz",
|
||||||
"integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA=="
|
"integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA=="
|
||||||
},
|
},
|
||||||
|
"node_modules/domino": {
|
||||||
|
"version": "2.1.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/domino/-/domino-2.1.6.tgz",
|
||||||
|
"integrity": "sha512-3VdM/SXBZX2omc9JF9nOPCtDaYQ67BGp5CoLpIQlO2KCAPETs8TcDHacF26jXadGbvUteZzRTeos2fhID5+ucQ=="
|
||||||
|
},
|
||||||
"node_modules/dompurify": {
|
"node_modules/dompurify": {
|
||||||
"version": "3.0.2",
|
"version": "3.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.0.2.tgz",
|
||||||
@@ -3585,6 +3598,14 @@
|
|||||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz",
|
||||||
"integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg=="
|
"integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg=="
|
||||||
},
|
},
|
||||||
|
"node_modules/turndown": {
|
||||||
|
"version": "7.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/turndown/-/turndown-7.1.2.tgz",
|
||||||
|
"integrity": "sha512-ntI9R7fcUKjqBP6QU8rBK2Ehyt8LAzt3UBT9JR9tgo6GtuKvyUzpayWmeMKJw1DPdXzktvtIT8m2mVXz+bL/Qg==",
|
||||||
|
"dependencies": {
|
||||||
|
"domino": "^2.1.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/typescript": {
|
"node_modules/typescript": {
|
||||||
"version": "5.0.4",
|
"version": "5.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz",
|
||||||
@@ -5021,6 +5042,12 @@
|
|||||||
"integrity": "sha512-NfQ4gyz38SL8sDNrSixxU2Os1a5xcdFxipAFxYEuLUlvU2uDwS4NUpsImcf1//SlWItCVMMLiylsxbmNMToV/g==",
|
"integrity": "sha512-NfQ4gyz38SL8sDNrSixxU2Os1a5xcdFxipAFxYEuLUlvU2uDwS4NUpsImcf1//SlWItCVMMLiylsxbmNMToV/g==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"@types/turndown": {
|
||||||
|
"version": "5.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/turndown/-/turndown-5.0.1.tgz",
|
||||||
|
"integrity": "sha512-N8Ad4e3oJxh9n9BiZx9cbe/0M3kqDpOTm2wzj13wdDUxDPjfjloWIJaquZzWE1cYTAHpjOH3rcTnXQdpEfS/SQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"@types/web-bluetooth": {
|
"@types/web-bluetooth": {
|
||||||
"version": "0.0.17",
|
"version": "0.0.17",
|
||||||
"resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.17.tgz",
|
"resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.17.tgz",
|
||||||
@@ -5518,6 +5545,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz",
|
||||||
"integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA=="
|
"integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA=="
|
||||||
},
|
},
|
||||||
|
"domino": {
|
||||||
|
"version": "2.1.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/domino/-/domino-2.1.6.tgz",
|
||||||
|
"integrity": "sha512-3VdM/SXBZX2omc9JF9nOPCtDaYQ67BGp5CoLpIQlO2KCAPETs8TcDHacF26jXadGbvUteZzRTeos2fhID5+ucQ=="
|
||||||
|
},
|
||||||
"dompurify": {
|
"dompurify": {
|
||||||
"version": "3.0.2",
|
"version": "3.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.0.2.tgz",
|
||||||
@@ -6392,6 +6424,14 @@
|
|||||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz",
|
||||||
"integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg=="
|
"integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg=="
|
||||||
},
|
},
|
||||||
|
"turndown": {
|
||||||
|
"version": "7.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/turndown/-/turndown-7.1.2.tgz",
|
||||||
|
"integrity": "sha512-ntI9R7fcUKjqBP6QU8rBK2Ehyt8LAzt3UBT9JR9tgo6GtuKvyUzpayWmeMKJw1DPdXzktvtIT8m2mVXz+bL/Qg==",
|
||||||
|
"requires": {
|
||||||
|
"domino": "^2.1.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"typescript": {
|
"typescript": {
|
||||||
"version": "5.0.4",
|
"version": "5.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz",
|
||||||
|
|||||||
@@ -32,12 +32,14 @@
|
|||||||
"lodash-es": "^4.17.21",
|
"lodash-es": "^4.17.21",
|
||||||
"marked": "^4.3.0",
|
"marked": "^4.3.0",
|
||||||
"shortid": "^2.2.16",
|
"shortid": "^2.2.16",
|
||||||
|
"turndown": "^7.1.2",
|
||||||
"vue": "^3.3.1"
|
"vue": "^3.3.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/dompurify": "^3.0.2",
|
"@types/dompurify": "^3.0.2",
|
||||||
"@types/lodash-es": "^4.17.7",
|
"@types/lodash-es": "^4.17.7",
|
||||||
"@types/shortid": "^0.0.29",
|
"@types/shortid": "^0.0.29",
|
||||||
|
"@types/turndown": "^5.0.1",
|
||||||
"@vitejs/plugin-vue": "^4.2.2",
|
"@vitejs/plugin-vue": "^4.2.2",
|
||||||
"autoprefixer": "^10.4.14",
|
"autoprefixer": "^10.4.14",
|
||||||
"postcss": "^8.4.23",
|
"postcss": "^8.4.23",
|
||||||
|
|||||||
@@ -20,13 +20,15 @@ const emit = defineEmits<{
|
|||||||
|
|
||||||
const noteTitle = ref(props.note.title)
|
const noteTitle = ref(props.note.title)
|
||||||
watch(noteTitle, () => {
|
watch(noteTitle, () => {
|
||||||
const updatedNote: Note = {
|
const updatedNote: Note = { ...props.note, title: noteTitle.value }
|
||||||
...props.note,
|
|
||||||
title: noteTitle.value,
|
|
||||||
}
|
|
||||||
emit('update', updatedNote)
|
emit('update', updatedNote)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const updateNoteContent = (content: string) => {
|
||||||
|
const updatedNote: Note = { ...props.note, content }
|
||||||
|
emit('update', updatedNote)
|
||||||
|
}
|
||||||
|
|
||||||
const references = computed<Note[]>(() => {
|
const references = computed<Note[]>(() => {
|
||||||
const relations = notesRelations.value[props.note.id]
|
const relations = notesRelations.value[props.note.id]
|
||||||
return relations
|
return relations
|
||||||
@@ -67,6 +69,7 @@ const setRoot = async (closeModal: () => Promise<Boolean>) => {
|
|||||||
<NoteEditor
|
<NoteEditor
|
||||||
class="h-100 flex-1 overflow-auto"
|
class="h-100 flex-1 overflow-auto"
|
||||||
:note="activeNote"
|
:note="activeNote"
|
||||||
|
@update="updateNoteContent"
|
||||||
v-if="activeNote"
|
v-if="activeNote"
|
||||||
/>
|
/>
|
||||||
<NoteReferences :references="references" />
|
<NoteReferences :references="references" />
|
||||||
|
|||||||
@@ -12,16 +12,20 @@ import ParagraphPlugin from '@ckeditor/ckeditor5-paragraph/src/paragraph'
|
|||||||
import ListPlugin from '@ckeditor/ckeditor5-list/src/list'
|
import ListPlugin from '@ckeditor/ckeditor5-list/src/list'
|
||||||
import AutoformatPlugin from '@ckeditor/ckeditor5-autoformat/src/autoformat'
|
import AutoformatPlugin from '@ckeditor/ckeditor5-autoformat/src/autoformat'
|
||||||
import ContextedPlugin from '@/ckeditor/ContextedPlugin'
|
import ContextedPlugin from '@/ckeditor/ContextedPlugin'
|
||||||
import { mdToHtml } from '@/utils/markdown'
|
import { mdToHtml, htmlToMd } from '@/utils/markdown'
|
||||||
import { getNoteByTitle, setActiveNote } from '@/composables/useNotes'
|
import { getNoteByTitle, setActiveNote } from '@/composables/useNotes'
|
||||||
import Autocomplete from '@/components/Autocomplete.vue'
|
import Autocomplete from '@/components/Autocomplete.vue'
|
||||||
|
|
||||||
const props = defineProps<{ note: Note }>()
|
const props = defineProps<{ note: Note }>()
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
update: [mdText: string]
|
||||||
|
}>()
|
||||||
|
|
||||||
const html = mdToHtml(props.note.content)
|
const html = mdToHtml(props.note.content)
|
||||||
|
|
||||||
const editor = BalloonEditor
|
const editor = BalloonEditor
|
||||||
const editorData = html
|
const editorData = ref<string>(html)
|
||||||
const editorConfig = {
|
const editorConfig = {
|
||||||
plugins: [
|
plugins: [
|
||||||
EssentialsPlugin,
|
EssentialsPlugin,
|
||||||
@@ -36,7 +40,6 @@ const editorConfig = {
|
|||||||
AutoformatPlugin,
|
AutoformatPlugin,
|
||||||
ContextedPlugin,
|
ContextedPlugin,
|
||||||
],
|
],
|
||||||
|
|
||||||
toolbar: {
|
toolbar: {
|
||||||
items: [
|
items: [
|
||||||
'bold',
|
'bold',
|
||||||
@@ -51,9 +54,11 @@ const editorConfig = {
|
|||||||
'numberedList',
|
'numberedList',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
placeholder: 'Click here to start typing...',
|
||||||
}
|
}
|
||||||
|
|
||||||
const editorElement = ref<HTMLInputElement | null>(null)
|
const editorElement = ref<HTMLInputElement | null>(null)
|
||||||
|
watch(editorData, () => emit('update', htmlToMd(editorData.value)))
|
||||||
|
|
||||||
const handleClick = ({ data }: { data: any }) => {
|
const handleClick = ({ data }: { data: any }) => {
|
||||||
const noteTitle = data.domTarget.textContent as string
|
const noteTitle = data.domTarget.textContent as string
|
||||||
|
|||||||
@@ -91,6 +91,7 @@ export const updateNote = (noteId: string, note: BaseNote) => {
|
|||||||
modified: new Date().getTime(),
|
modified: new Date().getTime(),
|
||||||
}
|
}
|
||||||
baseNotes[noteId] = updatedNote
|
baseNotes[noteId] = updatedNote
|
||||||
|
console.log(note)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const addNote = (title: string, content: string, goToNote: boolean = false) => {
|
export const addNote = (title: string, content: string, goToNote: boolean = false) => {
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import { marked } from 'marked'
|
import { marked } from 'marked'
|
||||||
import DOMPurify from 'dompurify'
|
import DOMPurify from 'dompurify'
|
||||||
|
import Turndown from 'turndown'
|
||||||
|
|
||||||
export function mdToHtml(mdText: string) {
|
export function mdToHtml(mdText: string): string {
|
||||||
const renderer = new marked.Renderer()
|
const renderer = new marked.Renderer()
|
||||||
|
|
||||||
const html = DOMPurify.sanitize(marked.parse(mdText, { renderer }))
|
const html = DOMPurify.sanitize(marked.parse(mdText, { renderer }))
|
||||||
@@ -14,3 +15,28 @@ export function mdToHtml(mdText: string) {
|
|||||||
})
|
})
|
||||||
return doc.body.innerHTML
|
return doc.body.innerHTML
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function htmlToMd(htmlText: string): string {
|
||||||
|
const turndown = new Turndown({ headingStyle: 'atx' })
|
||||||
|
const escapes = [
|
||||||
|
[/\\/g, '\\\\'],
|
||||||
|
[/\*/g, '\\*'],
|
||||||
|
[/^-/g, '\\-'],
|
||||||
|
[/^\+ /g, '\\+ '],
|
||||||
|
[/^(=+)/g, '\\$1'],
|
||||||
|
[/^(#{1,6}) /g, '\\$1 '],
|
||||||
|
[/`/g, '\\`'],
|
||||||
|
[/^~~~/g, '\\~~~'],
|
||||||
|
// [/\[/g, '\\['],
|
||||||
|
// [/\]/g, '\\]'],
|
||||||
|
[/^>/g, '\\>'],
|
||||||
|
[/_/g, '\\_'],
|
||||||
|
[/^(\d+)\. /g, '$1\\. '],
|
||||||
|
]
|
||||||
|
turndown.escape = (string) =>
|
||||||
|
escapes.reduce((accumulator, escape) => {
|
||||||
|
return accumulator.replace(escape[0], escape[1] as string)
|
||||||
|
}, string)
|
||||||
|
const md = turndown.turndown(htmlText)
|
||||||
|
return md
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user