You've already forked obsidian-visualiser
Markdown editor in progress + Login and session process completed
This commit is contained in:
105
components/EditableMarkdown.vue
Normal file
105
components/EditableMarkdown.vue
Normal file
@@ -0,0 +1,105 @@
|
||||
<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>
|
||||
@@ -8,6 +8,8 @@ const props = defineProps<Prop>();
|
||||
const model = defineModel<string>();
|
||||
|
||||
const err = ref<string | boolean | undefined>(props.error);
|
||||
|
||||
watchEffect(() => err.value = props.error);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
@@ -13,15 +13,17 @@ const { data: navigation, execute, status, error } = await useFetch(() => `/api/
|
||||
immediate: false,
|
||||
});
|
||||
|
||||
if(route.params.projectId && project.value !== 0)
|
||||
{
|
||||
showing.value = true;
|
||||
execute();
|
||||
}
|
||||
else
|
||||
{
|
||||
showing.value = false;
|
||||
}
|
||||
watch(route, () => {
|
||||
if(route.params.projectId && project.value !== 0)
|
||||
{
|
||||
showing.value = true;
|
||||
execute();
|
||||
}
|
||||
else
|
||||
{
|
||||
showing.value = false;
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
@@ -1,89 +1,26 @@
|
||||
<template>
|
||||
<slot
|
||||
:data="data?.data"
|
||||
:body="data?.body"
|
||||
:toc="data?.toc"
|
||||
:excerpt="data?.excerpt"
|
||||
:error="error"
|
||||
>
|
||||
<MDCRenderer
|
||||
v-if="body"
|
||||
:tag="tag"
|
||||
:class="props.class"
|
||||
:body="body"
|
||||
:data="data?.data"
|
||||
:unwrap="props.unwrap"
|
||||
:components="{
|
||||
a: ProseA,
|
||||
h1: ProseH1,
|
||||
h2: ProseH2,
|
||||
h3: ProseH3,
|
||||
h4: ProseH4,
|
||||
h5: ProseH5,
|
||||
h6: ProseH6,
|
||||
blockquote: ProseBlockquote,
|
||||
}"
|
||||
/>
|
||||
</slot>
|
||||
<template
|
||||
v-if="model && model.length > 0">
|
||||
<MarkdownRenderer :key="key" v-if="node" :node="node"></MarkdownRenderer>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import ProseA from "~/components/content/prose/ProseA.vue";
|
||||
import ProseH1 from "~/components/content/prose/ProseH1.vue";
|
||||
import ProseH2 from "~/components/content/prose/ProseH2.vue";
|
||||
import ProseH3 from "~/components/content/prose/ProseH3.vue";
|
||||
import ProseH4 from "~/components/content/prose/ProseH4.vue";
|
||||
import ProseH5 from "~/components/content/prose/ProseH5.vue";
|
||||
import ProseH6 from "~/components/content/prose/ProseH6.vue";
|
||||
import ProseBlockquote from "~/components/content/prose/ProseBlockquote.vue";
|
||||
|
||||
import { hash } from 'ohash'
|
||||
import { useAsyncData } from 'nuxt/app'
|
||||
import { watch, computed } from 'vue'
|
||||
import type { Root } from 'hast';
|
||||
|
||||
const props = defineProps({
|
||||
tag: {
|
||||
type: [String, Boolean],
|
||||
default: 'div'
|
||||
},
|
||||
content: {
|
||||
type: [String, Object],
|
||||
required: true
|
||||
},
|
||||
excerpt: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
class: {
|
||||
type: [String, Array, Object],
|
||||
default: ''
|
||||
},
|
||||
unwrap: {
|
||||
type: [Boolean, String],
|
||||
default: false
|
||||
}
|
||||
})
|
||||
const model = defineModel<number>({
|
||||
default: 0,
|
||||
});
|
||||
const model = defineModel<string>();
|
||||
|
||||
const parser = useMarkdown();
|
||||
const key = computed(() => hash(props.content))
|
||||
const key = computed(() => hash(model.value));
|
||||
|
||||
const { data, refresh, error } = await useAsyncData(key.value, async () => {
|
||||
const timer = performance.now();
|
||||
if (typeof props.content !== 'string') {
|
||||
model.value = performance.now() - timer;
|
||||
return props.content
|
||||
const node = ref<Root>();
|
||||
|
||||
watch(model, async () => {
|
||||
if(model.value && model.value)
|
||||
{
|
||||
node.value = parser(model.value);
|
||||
}
|
||||
const result = await parser(props.content);
|
||||
model.value = performance.now() - timer;
|
||||
return result;
|
||||
})
|
||||
|
||||
const body = computed(() => props.excerpt ? data.value?.excerpt : data.value?.body)
|
||||
|
||||
watch(() => props.content, () => {
|
||||
refresh()
|
||||
})
|
||||
}, { immediate: true });
|
||||
</script>
|
||||
121
components/MarkdownRenderer.vue
Normal file
121
components/MarkdownRenderer.vue
Normal file
@@ -0,0 +1,121 @@
|
||||
<script lang="ts">
|
||||
import type { Node, Text, Element, Comment, Root } from 'hast';
|
||||
import { Text as HText, Comment as HComment } from 'vue';
|
||||
|
||||
import ProseP from '~/components/prose/ProseP.vue';
|
||||
import ProseA from '~/components/prose/ProseA.vue';
|
||||
import ProseBlockquote from '~/components/prose/ProseBlockquote.vue';
|
||||
import ProseCode from '~/components/prose/ProseCode.vue';
|
||||
import ProsePre from '~/components/prose/ProsePre.vue';
|
||||
import ProseEm from '~/components/prose/ProseEm.vue';
|
||||
import ProseH1 from '~/components/prose/ProseH1.vue';
|
||||
import ProseH2 from '~/components/prose/ProseH2.vue';
|
||||
import ProseH3 from '~/components/prose/ProseH3.vue';
|
||||
import ProseH4 from '~/components/prose/ProseH4.vue';
|
||||
import ProseH5 from '~/components/prose/ProseH5.vue';
|
||||
import ProseH6 from '~/components/prose/ProseH6.vue';
|
||||
import ProseHr from '~/components/prose/ProseHr.vue';
|
||||
import ProseImg from '~/components/prose/ProseImg.vue';
|
||||
import ProseUl from '~/components/prose/ProseUl.vue';
|
||||
import ProseOl from '~/components/prose/ProseOl.vue';
|
||||
import ProseLi from '~/components/prose/ProseLi.vue';
|
||||
import ProseStrong from '~/components/prose/ProseStrong.vue';
|
||||
import ProseTable from '~/components/prose/ProseTable.vue';
|
||||
import ProseThead from '~/components/prose/ProseThead.vue';
|
||||
import ProseTbody from '~/components/prose/ProseTbody.vue';
|
||||
import ProseTd from '~/components/prose/ProseTd.vue';
|
||||
import ProseTh from '~/components/prose/ProseTh.vue';
|
||||
import ProseTr from '~/components/prose/ProseTr.vue';
|
||||
import ProseScript from '~/components/prose/ProseScript.vue';
|
||||
|
||||
const proseList = {
|
||||
"p": ProseP,
|
||||
"a": ProseA,
|
||||
"blockquote": ProseBlockquote,
|
||||
"code": ProseCode,
|
||||
"pre": ProsePre,
|
||||
"em": ProseEm,
|
||||
"h1": ProseH1,
|
||||
"h2": ProseH2,
|
||||
"h3": ProseH3,
|
||||
"h4": ProseH4,
|
||||
"h5": ProseH5,
|
||||
"h6": ProseH6,
|
||||
"hr": ProseHr,
|
||||
"img": ProseImg,
|
||||
"ul": ProseUl,
|
||||
"ol": ProseOl,
|
||||
"li": ProseLi,
|
||||
"strong": ProseStrong,
|
||||
"table": ProseTable,
|
||||
"thead": ProseThead,
|
||||
"tbody": ProseTbody,
|
||||
"td": ProseTd,
|
||||
"th": ProseTh,
|
||||
"tr": ProseTr,
|
||||
"script": ProseScript
|
||||
};
|
||||
|
||||
export default defineComponent({
|
||||
name: 'MarkdownRenderer',
|
||||
props: {
|
||||
node: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
proses: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
node: {
|
||||
handler: function(val, old) {
|
||||
|
||||
},
|
||||
deep: true,
|
||||
}
|
||||
},
|
||||
async setup(props) {
|
||||
if(props.proses)
|
||||
{
|
||||
for(const prose of Object.keys(props.proses))
|
||||
{
|
||||
if(typeof props.proses[prose] === 'string')
|
||||
props.proses[prose] = await resolveComponent(props.proses[prose]);
|
||||
}
|
||||
}
|
||||
return { tags: Object.assign({}, proseList, props.proses) };
|
||||
},
|
||||
render(ctx: any) {
|
||||
const { node, tags } = ctx;
|
||||
|
||||
const div = h('div', null, (node as Root).children.map(e => renderNode(e, tags)).filter(e => !!e));
|
||||
return div;
|
||||
}
|
||||
});
|
||||
|
||||
function renderNode(node: Node, tags: Record<string, any>): VNode | undefined
|
||||
{
|
||||
if(node.type === 'text')
|
||||
{
|
||||
const text = node as Text;
|
||||
if(text.value.length > 0 && text.value !== '\n')
|
||||
return h(HText, (node as Text).value);
|
||||
}
|
||||
else if(node.type === 'comment')
|
||||
{
|
||||
const comment = node as Comment;
|
||||
if(comment.value.length > 0 && comment.value !== '\n')
|
||||
return h(HComment, (node as Comment).value);
|
||||
}
|
||||
else if(node.type === 'element')
|
||||
{
|
||||
const element = node as Element;
|
||||
|
||||
return h(tags[element.tagName], { ...element.properties, class: element.properties.className }, element.children.map(e => renderNode(e, tags)).filter(e => !!e));
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
</script>
|
||||
@@ -43,7 +43,7 @@ if(props.node.color !== undefined)
|
||||
<div v-if="node.text?.length > 0" class="markdown-embed-content node-insert-event" style="">
|
||||
<div class="markdown-preview-view markdown-rendered node-insert-event show-indentation-guide allow-fold-headings allow-fold-lists">
|
||||
<div class="markdown-preview-sizer markdown-preview-section">
|
||||
<Markdown :content="node.text"/>
|
||||
<Markdown v-model="node.text"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import type { Navigation } from '~/server/api/project/[projectId]/navigation.get';
|
||||
import type { Navigation } from '~/types/api';
|
||||
|
||||
interface Props {
|
||||
link: Navigation;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<div class="markdown-preview-view markdown-rendered node-insert-event hide-title">
|
||||
<div class="markdown-preview-sizer markdown-preview-section" style="padding-bottom: 0px;">
|
||||
<h1 v-if="page[0]?.title">{{ page[0]?.title }}</h1>
|
||||
<Markdown :content="page[0].content" />
|
||||
<Markdown v-model="page[0].content" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
5
components/prose/ProseBlockquote.vue
Normal file
5
components/prose/ProseBlockquote.vue
Normal file
@@ -0,0 +1,5 @@
|
||||
<template>
|
||||
<blockquote>
|
||||
<slot />
|
||||
</blockquote>
|
||||
</template>
|
||||
3
components/prose/ProseCode.vue
Normal file
3
components/prose/ProseCode.vue
Normal file
@@ -0,0 +1,3 @@
|
||||
<template>
|
||||
<code><slot /></code>
|
||||
</template>
|
||||
5
components/prose/ProseEm.vue
Normal file
5
components/prose/ProseEm.vue
Normal file
@@ -0,0 +1,5 @@
|
||||
<template>
|
||||
<em>
|
||||
<slot />
|
||||
</em>
|
||||
</template>
|
||||
@@ -1,7 +1,11 @@
|
||||
<template>
|
||||
<h1 :id="id"><slot></slot></h1>
|
||||
<h1 :id="id">
|
||||
<slot />
|
||||
</h1>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
const props = defineProps<{ id?: string }>()
|
||||
</script>
|
||||
|
||||
const generate = computed(() => props.id)
|
||||
</script>
|
||||
@@ -1,7 +1,11 @@
|
||||
<template>
|
||||
<h2 :id="id"><slot></slot></h2>
|
||||
<h2 :id="id">
|
||||
<slot />
|
||||
</h2>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
const props = defineProps<{ id?: string }>()
|
||||
</script>
|
||||
|
||||
const generate = computed(() => props.id)
|
||||
</script>
|
||||
@@ -1,7 +1,11 @@
|
||||
<template>
|
||||
<h3 :id="id"><slot></slot></h3>
|
||||
<h3 :id="id">
|
||||
<slot />
|
||||
</h3>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
const props = defineProps<{ id?: string }>()
|
||||
</script>
|
||||
|
||||
const generate = computed(() => props.id)
|
||||
</script>
|
||||
@@ -1,7 +1,11 @@
|
||||
<template>
|
||||
<h4 :id="id"><slot></slot></h4>
|
||||
<h4 :id="id">
|
||||
<slot />
|
||||
</h4>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
const props = defineProps<{ id?: string }>()
|
||||
</script>
|
||||
|
||||
const generate = computed(() => props.id)
|
||||
</script>
|
||||
@@ -1,7 +1,11 @@
|
||||
<template>
|
||||
<h5 :id="id"><slot></slot></h5>
|
||||
<h5 :id="id">
|
||||
<slot />
|
||||
</h5>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
const props = defineProps<{ id?: string }>()
|
||||
</script>
|
||||
|
||||
const generate = computed(() => props.id)
|
||||
</script>
|
||||
@@ -1,7 +1,11 @@
|
||||
<template>
|
||||
<h6 :id="id"><slot></slot></h6>
|
||||
<h6 :id="id">
|
||||
<slot />
|
||||
</h6>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
const props = defineProps<{ id?: string }>()
|
||||
</script>
|
||||
|
||||
const generate = computed(() => props.id)
|
||||
</script>
|
||||
3
components/prose/ProseHr.vue
Normal file
3
components/prose/ProseHr.vue
Normal file
@@ -0,0 +1,3 @@
|
||||
<template>
|
||||
<hr>
|
||||
</template>
|
||||
42
components/prose/ProseImg.vue
Normal file
42
components/prose/ProseImg.vue
Normal file
@@ -0,0 +1,42 @@
|
||||
<template>
|
||||
<img
|
||||
:src="refinedSrc"
|
||||
:alt="alt"
|
||||
:width="width"
|
||||
:height="height"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { withTrailingSlash, withLeadingSlash, joinURL } from 'ufo'
|
||||
import { useRuntimeConfig, computed, resolveComponent } from '#imports'
|
||||
|
||||
const props = defineProps({
|
||||
src: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
alt: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
width: {
|
||||
type: [String, Number],
|
||||
default: undefined
|
||||
},
|
||||
height: {
|
||||
type: [String, Number],
|
||||
default: undefined
|
||||
}
|
||||
})
|
||||
|
||||
const refinedSrc = computed(() => {
|
||||
if (props.src?.startsWith('/') && !props.src.startsWith('//')) {
|
||||
const _base = withLeadingSlash(withTrailingSlash(useRuntimeConfig().app.baseURL))
|
||||
if (_base !== '/' && !props.src.startsWith(_base)) {
|
||||
return joinURL(_base, props.src)
|
||||
}
|
||||
}
|
||||
return props.src
|
||||
})
|
||||
</script>
|
||||
3
components/prose/ProseLi.vue
Normal file
3
components/prose/ProseLi.vue
Normal file
@@ -0,0 +1,3 @@
|
||||
<template>
|
||||
<li><slot /></li>
|
||||
</template>
|
||||
5
components/prose/ProseOl.vue
Normal file
5
components/prose/ProseOl.vue
Normal file
@@ -0,0 +1,5 @@
|
||||
<template>
|
||||
<ol>
|
||||
<slot />
|
||||
</ol>
|
||||
</template>
|
||||
3
components/prose/ProseP.vue
Normal file
3
components/prose/ProseP.vue
Normal file
@@ -0,0 +1,3 @@
|
||||
<template>
|
||||
<p><slot /></p>
|
||||
</template>
|
||||
36
components/prose/ProsePre.vue
Normal file
36
components/prose/ProsePre.vue
Normal file
@@ -0,0 +1,36 @@
|
||||
<template>
|
||||
<pre :class="$props.class"><slot /></pre>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
defineProps({
|
||||
code: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
language: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
filename: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
highlights: {
|
||||
type: Array as () => number[],
|
||||
default: () => []
|
||||
},
|
||||
meta: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
class: {
|
||||
type: String,
|
||||
default: null
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style>
|
||||
pre code .line{display:block}
|
||||
</style>
|
||||
15
components/prose/ProseScript.vue
Normal file
15
components/prose/ProseScript.vue
Normal file
@@ -0,0 +1,15 @@
|
||||
<template>
|
||||
<div v-if="isDev">
|
||||
Rendering the <code>script</code> element is dangerous and is disabled by default. Consider implementing your own <code>ProseScript</code> element to have control over script rendering.
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
defineProps({
|
||||
src: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
})
|
||||
const isDev = import.meta.dev
|
||||
</script>
|
||||
5
components/prose/ProseStrong.vue
Normal file
5
components/prose/ProseStrong.vue
Normal file
@@ -0,0 +1,5 @@
|
||||
<template>
|
||||
<strong>
|
||||
<slot />
|
||||
</strong>
|
||||
</template>
|
||||
5
components/prose/ProseTable.vue
Normal file
5
components/prose/ProseTable.vue
Normal file
@@ -0,0 +1,5 @@
|
||||
<template>
|
||||
<table>
|
||||
<slot />
|
||||
</table>
|
||||
</template>
|
||||
5
components/prose/ProseTbody.vue
Normal file
5
components/prose/ProseTbody.vue
Normal file
@@ -0,0 +1,5 @@
|
||||
<template>
|
||||
<tbody>
|
||||
<slot />
|
||||
</tbody>
|
||||
</template>
|
||||
5
components/prose/ProseTd.vue
Normal file
5
components/prose/ProseTd.vue
Normal file
@@ -0,0 +1,5 @@
|
||||
<template>
|
||||
<td>
|
||||
<slot />
|
||||
</td>
|
||||
</template>
|
||||
5
components/prose/ProseTh.vue
Normal file
5
components/prose/ProseTh.vue
Normal file
@@ -0,0 +1,5 @@
|
||||
<template>
|
||||
<th>
|
||||
<slot />
|
||||
</th>
|
||||
</template>
|
||||
5
components/prose/ProseThead.vue
Normal file
5
components/prose/ProseThead.vue
Normal file
@@ -0,0 +1,5 @@
|
||||
<template>
|
||||
<thead>
|
||||
<slot />
|
||||
</thead>
|
||||
</template>
|
||||
5
components/prose/ProseTr.vue
Normal file
5
components/prose/ProseTr.vue
Normal file
@@ -0,0 +1,5 @@
|
||||
<template>
|
||||
<tr>
|
||||
<slot />
|
||||
</tr>
|
||||
</template>
|
||||
5
components/prose/ProseUl.vue
Normal file
5
components/prose/ProseUl.vue
Normal file
@@ -0,0 +1,5 @@
|
||||
<template>
|
||||
<ul>
|
||||
<slot />
|
||||
</ul>
|
||||
</template>
|
||||
5
components/prose/live/LiveA.vue
Normal file
5
components/prose/live/LiveA.vue
Normal file
@@ -0,0 +1,5 @@
|
||||
<template>
|
||||
<a>
|
||||
<slot></slot>
|
||||
</a>
|
||||
</template>
|
||||
12
components/prose/live/LiveBlockquote.vue
Normal file
12
components/prose/live/LiveBlockquote.vue
Normal file
@@ -0,0 +1,12 @@
|
||||
<template>
|
||||
<span v-if="focused">> </span>
|
||||
<blockquote ref="el" @focusin="focused = true" @focusout="focused = false">
|
||||
<slot />
|
||||
</blockquote>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
const focused = ref(false);
|
||||
|
||||
watch(focused, console.log);
|
||||
</script>
|
||||
3
components/prose/live/LiveH1.vue
Normal file
3
components/prose/live/LiveH1.vue
Normal file
@@ -0,0 +1,3 @@
|
||||
<template>
|
||||
<span v-show="false"># </span><h1><slot></slot></h1>
|
||||
</template>
|
||||
12
components/prose/live/LiveH2.vue
Normal file
12
components/prose/live/LiveH2.vue
Normal file
@@ -0,0 +1,12 @@
|
||||
<template>
|
||||
<span v-show="focused">## </span><h2><slot></slot></h2>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
const props = defineProps({
|
||||
focused: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
})
|
||||
</script>
|
||||
3
components/prose/live/LiveH3.vue
Normal file
3
components/prose/live/LiveH3.vue
Normal file
@@ -0,0 +1,3 @@
|
||||
<template>
|
||||
<span v-show="false">### </span><h3><slot></slot></h3>
|
||||
</template>
|
||||
3
components/prose/live/LiveH4.vue
Normal file
3
components/prose/live/LiveH4.vue
Normal file
@@ -0,0 +1,3 @@
|
||||
<template>
|
||||
<span v-show="false">#### </span><h4><slot></slot></h4>
|
||||
</template>
|
||||
3
components/prose/live/LiveH5.vue
Normal file
3
components/prose/live/LiveH5.vue
Normal file
@@ -0,0 +1,3 @@
|
||||
<template>
|
||||
<span v-show="false">##### </span><h5><slot></slot></h5>
|
||||
</template>
|
||||
3
components/prose/live/LiveH6.vue
Normal file
3
components/prose/live/LiveH6.vue
Normal file
@@ -0,0 +1,3 @@
|
||||
<template>
|
||||
<span v-show="false">###### </span><h6><slot></slot></h6>
|
||||
</template>
|
||||
Reference in New Issue
Block a user