obsidian-visualiser/components/EditableMarkdown.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>