update note content

This commit is contained in:
2023-05-13 08:09:52 +02:00
parent 69cec28fb6
commit 8eb7e57203
6 changed files with 85 additions and 8 deletions

40
package-lock.json generated
View File

@@ -31,12 +31,14 @@
"lodash-es": "^4.17.21",
"marked": "^4.3.0",
"shortid": "^2.2.16",
"turndown": "^7.1.2",
"vue": "^3.3.1"
},
"devDependencies": {
"@types/dompurify": "^3.0.2",
"@types/lodash-es": "^4.17.7",
"@types/shortid": "^0.0.29",
"@types/turndown": "^5.0.1",
"@vitejs/plugin-vue": "^4.2.2",
"autoprefixer": "^10.4.14",
"postcss": "^8.4.23",
@@ -1545,6 +1547,12 @@
"integrity": "sha512-NfQ4gyz38SL8sDNrSixxU2Os1a5xcdFxipAFxYEuLUlvU2uDwS4NUpsImcf1//SlWItCVMMLiylsxbmNMToV/g==",
"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": {
"version": "0.0.17",
"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",
"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": {
"version": "3.0.2",
"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",
"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": {
"version": "5.0.4",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz",
@@ -5021,6 +5042,12 @@
"integrity": "sha512-NfQ4gyz38SL8sDNrSixxU2Os1a5xcdFxipAFxYEuLUlvU2uDwS4NUpsImcf1//SlWItCVMMLiylsxbmNMToV/g==",
"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": {
"version": "0.0.17",
"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",
"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": {
"version": "3.0.2",
"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",
"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": {
"version": "5.0.4",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz",

View File

@@ -32,12 +32,14 @@
"lodash-es": "^4.17.21",
"marked": "^4.3.0",
"shortid": "^2.2.16",
"turndown": "^7.1.2",
"vue": "^3.3.1"
},
"devDependencies": {
"@types/dompurify": "^3.0.2",
"@types/lodash-es": "^4.17.7",
"@types/shortid": "^0.0.29",
"@types/turndown": "^5.0.1",
"@vitejs/plugin-vue": "^4.2.2",
"autoprefixer": "^10.4.14",
"postcss": "^8.4.23",

View File

@@ -20,13 +20,15 @@ const emit = defineEmits<{
const noteTitle = ref(props.note.title)
watch(noteTitle, () => {
const updatedNote: Note = {
...props.note,
title: noteTitle.value,
}
const updatedNote: Note = { ...props.note, title: noteTitle.value }
emit('update', updatedNote)
})
const updateNoteContent = (content: string) => {
const updatedNote: Note = { ...props.note, content }
emit('update', updatedNote)
}
const references = computed<Note[]>(() => {
const relations = notesRelations.value[props.note.id]
return relations
@@ -67,6 +69,7 @@ const setRoot = async (closeModal: () => Promise<Boolean>) => {
<NoteEditor
class="h-100 flex-1 overflow-auto"
:note="activeNote"
@update="updateNoteContent"
v-if="activeNote"
/>
<NoteReferences :references="references" />

View File

@@ -12,16 +12,20 @@ import ParagraphPlugin from '@ckeditor/ckeditor5-paragraph/src/paragraph'
import ListPlugin from '@ckeditor/ckeditor5-list/src/list'
import AutoformatPlugin from '@ckeditor/ckeditor5-autoformat/src/autoformat'
import ContextedPlugin from '@/ckeditor/ContextedPlugin'
import { mdToHtml } from '@/utils/markdown'
import { mdToHtml, htmlToMd } from '@/utils/markdown'
import { getNoteByTitle, setActiveNote } from '@/composables/useNotes'
import Autocomplete from '@/components/Autocomplete.vue'
const props = defineProps<{ note: Note }>()
const emit = defineEmits<{
update: [mdText: string]
}>()
const html = mdToHtml(props.note.content)
const editor = BalloonEditor
const editorData = html
const editorData = ref<string>(html)
const editorConfig = {
plugins: [
EssentialsPlugin,
@@ -36,7 +40,6 @@ const editorConfig = {
AutoformatPlugin,
ContextedPlugin,
],
toolbar: {
items: [
'bold',
@@ -51,9 +54,11 @@ const editorConfig = {
'numberedList',
],
},
placeholder: 'Click here to start typing...',
}
const editorElement = ref<HTMLInputElement | null>(null)
watch(editorData, () => emit('update', htmlToMd(editorData.value)))
const handleClick = ({ data }: { data: any }) => {
const noteTitle = data.domTarget.textContent as string

View File

@@ -91,6 +91,7 @@ export const updateNote = (noteId: string, note: BaseNote) => {
modified: new Date().getTime(),
}
baseNotes[noteId] = updatedNote
console.log(note)
}
export const addNote = (title: string, content: string, goToNote: boolean = false) => {

View File

@@ -1,7 +1,8 @@
import { marked } from 'marked'
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 html = DOMPurify.sanitize(marked.parse(mdText, { renderer }))
@@ -14,3 +15,28 @@ export function mdToHtml(mdText: string) {
})
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
}