105 lines
3.2 KiB
Vue
105 lines
3.2 KiB
Vue
<style>
|
|
.editor
|
|
{
|
|
white-space: pre-line;
|
|
overflow: auto;
|
|
outline: none;
|
|
box-shadow: none !important;
|
|
}
|
|
</style>
|
|
|
|
<template>
|
|
<div class="editor" contenteditable>
|
|
<template
|
|
v-if="model && model.length > 0">
|
|
<MarkdownRenderer
|
|
v-if="node"
|
|
:key="key"
|
|
:node="node"
|
|
:proses="{
|
|
'a': LiveA,
|
|
'h1': LiveH1,
|
|
'h2': LiveH2,
|
|
'h3': LiveH3,
|
|
'h4': LiveH4,
|
|
'h5': LiveH5,
|
|
'h6': LiveH6,
|
|
'blockquote': LiveBlockquote,
|
|
}"
|
|
></MarkdownRenderer>
|
|
</template>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import LiveA from "~/components/prose/live/LiveA.vue";
|
|
import LiveH1 from "~/components/prose/live/LiveH1.vue";
|
|
import LiveH2 from "~/components/prose/live/LiveH2.vue";
|
|
import LiveH3 from "~/components/prose/live/LiveH3.vue";
|
|
import LiveH4 from "~/components/prose/live/LiveH4.vue";
|
|
import LiveH5 from "~/components/prose/live/LiveH5.vue";
|
|
import LiveH6 from "~/components/prose/live/LiveH6.vue";
|
|
import LiveBlockquote from "~/components/prose/ProseBlockquote.vue";
|
|
|
|
import { hash } from 'ohash'
|
|
import { watch, computed } from 'vue'
|
|
import type { Root } from 'hast';
|
|
import { diffLines as diff } from 'diff';
|
|
|
|
const model = defineModel<string>();
|
|
|
|
const parser = useMarkdown();
|
|
const key = computed(() => hash(model.value));
|
|
|
|
const node = ref<Root>();
|
|
|
|
watch(model, async (value, old) => {
|
|
if(value && old)
|
|
{
|
|
if(node.value)
|
|
{
|
|
let content = "", line = 0, pos = -1, len = 0, child;
|
|
const d = diff(old, value);
|
|
const children = node.value?.children.filter(e => e.hasOwnProperty('position'));
|
|
|
|
for(let i = 0; i < d.length; i++)
|
|
{
|
|
if(d[i].added) //Nouvelle ligne
|
|
{
|
|
const next = d.length > i ? d[i + 1] : undefined;
|
|
if(pos === -1 && (!next || !next.removed)) //Nouvelle ligne
|
|
{
|
|
child = children.filter(e => e.position?.start.line <= line && e.position?.end.line >= line); //Je cherche tout les blocs qui était inclus dans les lignes éditées.
|
|
if(child.length > 0)
|
|
{
|
|
pos = child[0].position?.start.offset ?? 0; //Je pars du premier caractère du bloc
|
|
len += (child[child.length - 1].position?.end.offset ?? 0) + 1; //Je m'arrete au dernier caractère du bloc + le \n
|
|
}
|
|
}
|
|
len += d[i].value.length; // J'ajoute le nouveau nombre de caractère
|
|
}
|
|
else if(d[i].removed) //Ancienne ligne
|
|
{
|
|
child = children.filter(e => e.position?.start.line <= line + 1 && e.position?.end.line >= line + (d[i].count ?? 1)); //Je cherche tout les blocs qui était inclus dans les lignes éditées.
|
|
if(child.length > 0)
|
|
{
|
|
pos = child[0].position?.start.offset ?? 0; //Je pars du premier caractère du bloc
|
|
len += child[child.length - 1].position?.end.offset ?? 0 + 1; //Je m'arrete au dernier caractère du bloc
|
|
len -= d[i].value.length; //Je supprime l'ancien nombre de caractère
|
|
}
|
|
}
|
|
else
|
|
{
|
|
line += d[i].count ?? 0;
|
|
}
|
|
}
|
|
|
|
node.value = parser(value);
|
|
}
|
|
else
|
|
{
|
|
node.value = parser(value);
|
|
}
|
|
}
|
|
}, { immediate: true });
|
|
</script> |