Fix Canvas initial position and add tags popover
This commit is contained in:
parent
a55b98e07a
commit
a228b7d222
7
app.vue
7
app.vue
|
|
@ -1,8 +1,13 @@
|
|||
<script setup lang="ts">
|
||||
const { data: tags } = await useAsyncData('tags', queryContent('/tags').findOne);
|
||||
|
||||
provide('tags', tags);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="published-container print is-readable-line-width has-navigation has-graph has-outline" style="">
|
||||
<div class="site-body">
|
||||
<LeftComponent />
|
||||
<NuxtLoadingIndicator />
|
||||
<MainComponent />
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1008,6 +1008,22 @@ html {
|
|||
--font-mermaid: var(--font-text);
|
||||
}
|
||||
|
||||
.preload {
|
||||
padding: 20px;
|
||||
white-space: pre-wrap;
|
||||
overflow-wrap: break-word
|
||||
}
|
||||
|
||||
@keyframes rotate {
|
||||
from {
|
||||
transform: rotate(0)
|
||||
}
|
||||
|
||||
to {
|
||||
transform: rotate(360deg)
|
||||
}
|
||||
}
|
||||
|
||||
audio {
|
||||
outline: none;
|
||||
}
|
||||
|
|
@ -2778,7 +2794,7 @@ body:not(.native-scrollbars) * {
|
|||
position: absolute;
|
||||
z-index: var(--layer-popover);
|
||||
max-width: 80vw;
|
||||
min-height: 60px;
|
||||
min-height: 30px;
|
||||
overflow: hidden;
|
||||
width: fit-content;
|
||||
padding: 0;
|
||||
|
|
@ -2835,6 +2851,18 @@ body:not(.native-scrollbars) * {
|
|||
overflow: auto;
|
||||
}
|
||||
|
||||
.popover.hover-popover>.tag-embed {
|
||||
min-height: initial;
|
||||
height: initial;
|
||||
max-height: initial;
|
||||
width: 400px;
|
||||
}
|
||||
|
||||
.popover.hover-popover>.tag-embed {
|
||||
min-height: initial;
|
||||
height: initial;
|
||||
}
|
||||
|
||||
.popover.hover-popover>.canvas-embed {
|
||||
min-height: 350px;
|
||||
}
|
||||
|
|
@ -2848,6 +2876,15 @@ body:not(.native-scrollbars) * {
|
|||
padding: var(--file-margins);
|
||||
}
|
||||
|
||||
.popover.hover-popover>.tag-embed>.markdown-embed-content>.markdown-preview-view {
|
||||
padding: var(--size-4-3) var(--size-4-6);
|
||||
}
|
||||
|
||||
.popover.hover-popover>.tag-embed p {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.popover.hover-popover>.markdown-embed .mod-header+div>*:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,29 +11,40 @@ const props = defineProps<Props>();
|
|||
|
||||
let dragging = false, posX = 0, posY = 0, dispX = ref(0), dispY = ref(0), minZoom = ref(0.3), zoom = ref(1);
|
||||
let centerX = ref(0), centerY = ref(0), canvas = ref<HTMLDivElement>();
|
||||
let minX = ref(+Infinity), minY = ref(+Infinity), maxX = ref(-Infinity), maxY = ref(-Infinity);
|
||||
let bbox = ref<DOMRect>();
|
||||
|
||||
onMounted(async () => {
|
||||
await nextTick();
|
||||
let minX = +Infinity, minY = +Infinity, maxX = -Infinity, maxY = -Infinity;
|
||||
let _minX = +Infinity, _minY = +Infinity, _maxX = -Infinity, _maxY = -Infinity;
|
||||
|
||||
props.canvas.body.nodes.forEach((e) => {
|
||||
minX = Math.min(minX, e.x);
|
||||
minY = Math.min(minY, e.y);
|
||||
maxX = Math.max(maxX, e.x + e.width);
|
||||
maxY = Math.max(maxY, e.y + e.height);
|
||||
_minX = Math.min(_minX, e.x);
|
||||
_minY = Math.min(_minY, e.y);
|
||||
_maxX = Math.max(_maxX, e.x + e.width);
|
||||
_maxY = Math.max(_maxY, e.y + e.height);
|
||||
});
|
||||
|
||||
minZoom.value = Math.min((canvas.value?.clientWidth ?? 0) / (maxX - minX), (canvas.value?.clientHeight ?? 0) / (maxY - minY)) * 0.9;
|
||||
minX.value = _minX = _minX - 32;
|
||||
minY.value = _minY = _minY - 32;
|
||||
maxX.value = _maxX = _maxX + 32;
|
||||
maxY.value = _maxY = _maxY + 32;
|
||||
|
||||
centerX.value = (canvas.value?.clientWidth ?? 0) / 2;
|
||||
centerY.value = (canvas.value?.clientHeight ?? 0) / 2;
|
||||
minZoom.value = zoom.value = Math.min((canvas.value?.clientWidth ?? 0) / (_maxX - _minX), (canvas.value?.clientHeight ?? 0) / (_maxY - _minY)) * 0.9;
|
||||
|
||||
dispX.value = -(canvas.value?.clientWidth ?? 0) / 2;
|
||||
dispY.value = -(canvas.value?.clientHeight ?? 0) / 2;
|
||||
bbox.value = canvas.value?.getBoundingClientRect();
|
||||
|
||||
await nextTick();
|
||||
|
||||
centerX.value = (bbox.value?.width ?? 0) / 2;
|
||||
centerY.value = (bbox.value?.height ?? 0) / 2;
|
||||
|
||||
dispX.value = -(_maxX + _minX) / 2;
|
||||
dispY.value = -(_maxY + _minY) / 2;
|
||||
})
|
||||
|
||||
const onPointerDown = (event) => {
|
||||
const onPointerDown = (event: PointerEvent) => {
|
||||
if (event.isPrimary === false) return;
|
||||
event.target.setPointerCapture(event.pointerId);
|
||||
dragging = true;
|
||||
|
||||
posX = event.clientX;
|
||||
|
|
@ -43,7 +54,7 @@ const onPointerDown = (event) => {
|
|||
document.addEventListener('pointerup', onPointerUp);
|
||||
}
|
||||
|
||||
const onPointerMove = (event) => {
|
||||
const onPointerMove = (event: PointerEvent) => {
|
||||
if (event.isPrimary === false) return;
|
||||
dispX.value -= (posX - event.clientX) / zoom.value;
|
||||
dispY.value -= (posY - event.clientY) / zoom.value;
|
||||
|
|
@ -52,7 +63,7 @@ const onPointerMove = (event) => {
|
|||
posY = event.clientY;
|
||||
}
|
||||
|
||||
const onPointerUp = (event) => {
|
||||
const onPointerUp = (event: PointerEvent) => {
|
||||
if (event.isPrimary === false) return;
|
||||
dragging = false;
|
||||
document.removeEventListener('pointermove', onPointerMove);
|
||||
|
|
@ -68,6 +79,11 @@ const onWheel = (event: WheelEvent) => {
|
|||
zoom.value = minZoom.value;
|
||||
}
|
||||
|
||||
const reset = (event: PointerEvent) => {
|
||||
zoom.value = minZoom.value;
|
||||
dispX.value = -(maxX.value + minX.value) / 2;
|
||||
dispY.value = -(maxY.value + minY.value) / 2;
|
||||
}
|
||||
function clamp(x: number, min: number, max: number): number {
|
||||
if (x > max)
|
||||
return max;
|
||||
|
|
@ -115,7 +131,7 @@ function mK(e: { minX: number, minY: number, maxX: number, maxY: number }, t: 'b
|
|||
return { x: e.minX, y: (e.minY + e.maxY) / 2 };
|
||||
}
|
||||
}
|
||||
function bbox(node: CanvasNode): { minX: number, minY: number, maxX: number, maxY: number } {
|
||||
function getBbox(node: CanvasNode): { minX: number, minY: number, maxX: number, maxY: number } {
|
||||
return { minX: node.x, minY: node.y, maxX: node.x + node.width, maxY: node.y + node.height };
|
||||
}
|
||||
function path(from: CanvasNode, fromSide: 'bottom' | 'top' | 'left' | 'right', to: CanvasNode, toSide: 'bottom' | 'top' | 'left' | 'right'): any {
|
||||
|
|
@ -127,8 +143,8 @@ function path(from: CanvasNode, fromSide: 'bottom' | 'top' | 'left' | 'right', t
|
|||
toSide: '',
|
||||
}
|
||||
}
|
||||
const a = mK(bbox(from), fromSide),
|
||||
l = mK(bbox(to), toSide);
|
||||
const a = mK(getBbox(from), fromSide),
|
||||
l = mK(getBbox(to), toSide);
|
||||
return bezier(a, fromSide, l, toSide);
|
||||
}
|
||||
function bezier(from: { x: number, y: number }, fromSide: 'bottom' | 'top' | 'left' | 'right', to: { x: number, y: number }, toSide: 'bottom' | 'top' | 'left' | 'right'): any {
|
||||
|
|
@ -142,7 +158,7 @@ function bezier(from: { x: number, y: number }, fromSide: 'bottom' | 'top' | 'le
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<div @pointerdown="onPointerDown" @wheel.passive="onWheel"
|
||||
<div ref="canvas" @pointerdown="onPointerDown" @wheel.passive="onWheel"
|
||||
@touchstart.prevent="" @dragstart.prevent="" class="canvas-wrapper node-insert-event mod-zoomed-out">
|
||||
<div class="canvas-controls" style="z-index: 421;">
|
||||
<div class="canvas-control-group">
|
||||
|
|
@ -158,7 +174,7 @@ function bezier(from: { x: number, y: number }, fromSide: 'bottom' | 'top' | 'le
|
|||
<path d="M21 3v5h-5"></path>
|
||||
</svg>
|
||||
</div>
|
||||
<div @click="zoom = minZoom; dispX = -(canvas?.clientWidth ?? 0) / 2; dispY = -(canvas?.clientHeight ?? 0) / 2;" class="canvas-control-item" aria-label="Zoom to fit" data-tooltip-position="left">
|
||||
<div @click="reset" class="canvas-control-item" aria-label="Zoom to fit" data-tooltip-position="left">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="svg-icon lucide-maximize">
|
||||
<path d="M8 3H5a2 2 0 0 0-2 2v3"></path>
|
||||
<path d="M21 8V5a2 2 0 0 0-2-2h-3"></path>
|
||||
|
|
@ -173,7 +189,7 @@ function bezier(from: { x: number, y: number }, fromSide: 'bottom' | 'top' | 'le
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div ref="canvas" class="canvas" :style="{transform: `translate(${centerX}px, ${centerY}px) scale(${zoom}) translate(${dispX}px, ${dispY}px)`}">
|
||||
<div class="canvas" :style="{transform: `translate(${centerX}px, ${centerY}px) scale(${zoom}) translate(${dispX}px, ${dispY}px)`}">
|
||||
<svg class="canvas-edges">
|
||||
<CanvasEdge v-for="edge of props.canvas.body.edges" :key="edge.id" :path="path(getNode(edge.fromNode)!, edge.fromSide, getNode(edge.toNode)!, edge.toSide)" :color="edge.color"/>
|
||||
</svg>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<div class="site-body-left-column">
|
||||
<div class="site-body-left-column-inner">
|
||||
<NuxtLink class="site-body-left-column-site-logo" aria-label="Developer Documentation logo" :href="'/Home'">
|
||||
<NuxtLink class="site-body-left-column-site-logo" aria-label="Developer Documentation logo" :href="'/'">
|
||||
<img aria-hidden="true" src="https://publish-01.obsidian.md/access/caa27d6312fe5c26ebc657cc609543be/Assets/obsidian-lockup-docs.svg" style="">
|
||||
</NuxtLink>
|
||||
<NuxtLink class="site-body-left-column-site-name" aria-label="Accueil" :href="'/Home'">Accueil</NuxtLink>
|
||||
|
|
@ -15,7 +15,7 @@
|
|||
</div>
|
||||
<div class="tree-item-children">
|
||||
<ContentNavigation v-slot="{ navigation }">
|
||||
<NavigationLink v-if="!!navigation" v-for="link of navigation" :link="link" />
|
||||
<NavigationLink v-if="!!navigation" v-for="link of navigation.filter(e => !['/tags', '/'].includes(e?._path ?? ''))" :link="link" />
|
||||
</ContentNavigation>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -31,14 +31,14 @@ const collapsed = ref(!useRoute().path.startsWith(props.link._path));
|
|||
<path d="M3 8L12 17L21 8"></path>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="tree-item-inner">{{ props.link.title }}</div>
|
||||
<div class="tree-item-inner">{{ link.title }}</div>
|
||||
</div>
|
||||
<div v-if="!collapsed" class="tree-item-children">
|
||||
<NavigationLink v-if="hasChildren" v-for="link of props.link.children" :link="link"/>
|
||||
<NavigationLink v-if="hasChildren" v-for="l of link.children" :link="l"/>
|
||||
</div>
|
||||
</template>
|
||||
<NuxtLink v-else class="tree-item-self" :to="props.link._path" :active-class="'mod-active'">
|
||||
<div class="tree-item-inner">{{ props.link.title }}</div>
|
||||
<NuxtLink v-else class="tree-item-self" :to="link._path" :active-class="'mod-active'">
|
||||
<div class="tree-item-inner">{{ link.title }}<span v-if="link"></span></div>
|
||||
</NuxtLink>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -19,7 +19,7 @@ const hasChildren = computed(() => {
|
|||
<template>
|
||||
<div class="tree-item">
|
||||
<div class="tree-item-self" :class="{'is-clickable': hasChildren}" data-path="{{ props.link.title }}">
|
||||
<a class="tree-item-inner" :href="'#' + props.link.id">{{ props.link.text }}</a>
|
||||
<NuxtLink no-prefetch class="tree-item-inner" :href="{hash: '#' + props.link.id}">{{ props.link.text }}</NuxtLink>
|
||||
</div>
|
||||
<div class="tree-item-children">
|
||||
<TocLink v-if="hasChildren" v-for="link of props.link.children" :link="link" />
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ interface ParsedContentExtended extends Omit<ParsedContent, 'body'> {
|
|||
body: MarkdownRoot | CanvasContent | null;
|
||||
}
|
||||
|
||||
const tags = inject('tags') as ParsedContent;
|
||||
const props = defineProps({
|
||||
href: {
|
||||
type: String,
|
||||
|
|
@ -16,7 +17,7 @@ const props = defineProps({
|
|||
default: undefined,
|
||||
required: false
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
function sluggify(s: string): string {
|
||||
return s
|
||||
|
|
@ -29,28 +30,20 @@ function sluggify(s: string): string {
|
|||
function flatten(val: TocLink[]): TocLink[] {
|
||||
return val.flatMap ? val?.flatMap((e: TocLink) => e.children ? [e, ...flatten(e.children)] : e) : val;
|
||||
}
|
||||
|
||||
const link = (props.href.startsWith('/') ? '' : '/') + (props.href.includes('#') ? props.href.substring(0, props.href.indexOf('#')) : props.href).replace(/\..*$/, '').replace("/index", '');
|
||||
const anchor = props.href.includes('#') ? props.href.substring(props.href.indexOf('#'), props.href.length) : '';
|
||||
let content = ref<ParsedContentExtended>(), loading = ref(true);
|
||||
|
||||
if(props.href !== '')
|
||||
{
|
||||
queryContent().where({ _path: new RegExp("/" + sluggify(link) + '$', 'i') }).findOne().then((result: ParsedContentExtended) => {
|
||||
content.value = result;
|
||||
function handleResult(result: ParsedContentExtended, tag: boolean = false) {
|
||||
loading.value = false;
|
||||
let body = result.body;
|
||||
let body: MarkdownRoot | CanvasContent | null = JSON.parse(JSON.stringify(result.body));
|
||||
|
||||
if (anchor && result && body) {
|
||||
if (result._type == 'markdown' && (body as MarkdownRoot).children) {
|
||||
body = body as MarkdownRoot;
|
||||
const id = flatten(body?.toc?.links ?? []).find(e => "#" + sluggify(e.id) === anchor);
|
||||
const id = flatten(body?.toc?.links ?? []).find(e => "#" + sluggify(e.id) === anchor.replaceAll('/', ''));
|
||||
const tag = `h${id?.depth ?? 0}`;
|
||||
|
||||
const startIdx = body.children.findIndex(e => e.tag === tag && e?.props?.id === id?.id) ?? 0;
|
||||
const nbr = body.children.findIndex((e, i) => i > startIdx && e.tag?.match(new RegExp(`h[1-${id?.depth ?? 1}]`)));
|
||||
|
||||
body.children = body.children.splice(startIdx, (nbr === -1 ? body.children.length : nbr) - startIdx);
|
||||
body.children = [...body.children].splice(startIdx + (tag ? 1 : 0), (nbr === -1 ? body.children.length : nbr) - (startIdx + (tag ? 1 : 0)));
|
||||
}
|
||||
else if (result._type == 'canvas') {
|
||||
body = body as CanvasContent;
|
||||
|
|
@ -60,9 +53,36 @@ if(props.href !== '')
|
|||
body.edges = body.edges.filter(e => nodes?.includes(e.fromNode) && nodes?.includes(e.toNode));
|
||||
}
|
||||
}
|
||||
}).catch(() => {
|
||||
|
||||
content.value = JSON.parse(JSON.stringify({ ...result, body: body }));
|
||||
}
|
||||
|
||||
const link = (props.href.startsWith('/') ? '' : '/') + (props.href.includes('#') ? props.href.substring(0, props.href.indexOf('#')) : props.href).replace(/\..*$/, '').replace("/index", '');
|
||||
const anchor = props.href.includes('#') ? props.href.substring(props.href.indexOf('#'), props.href.length) : '';
|
||||
let content = ref<ParsedContentExtended | null | undefined>(null), loading = ref(false), isTag = ref(false);
|
||||
|
||||
function loadContent()
|
||||
{
|
||||
loading.value = true;
|
||||
if(props.href !== '' && !props.href.startsWith('/tags#'))
|
||||
{
|
||||
queryContent().where({ _path: new RegExp("/" + sluggify(link) + '$', 'i') }).findOne().then(handleResult).catch(() => {
|
||||
loading.value = false;
|
||||
content.value = undefined;
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
isTag.value = true;
|
||||
|
||||
if(tags.value)
|
||||
handleResult(tags.value, true);
|
||||
else
|
||||
{
|
||||
loading.value = false;
|
||||
content.value = undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const hovered = ref(false), pos = ref<any>();
|
||||
|
|
@ -81,10 +101,13 @@ function showPreview(e: Event, bbox: boolean) {
|
|||
if(rect.right + 550 < window.innerWidth)
|
||||
r.left = rect.left + "px";
|
||||
else
|
||||
r.right = (window.innerWidth - rect.left + 4) + "px";
|
||||
r.right = (window.innerWidth - rect.right + 4) + "px";
|
||||
pos.value = r;
|
||||
}
|
||||
hovered.value = true;
|
||||
|
||||
if(content.value === null)
|
||||
loadContent();
|
||||
}
|
||||
function hidePreview(e: Event) {
|
||||
timeout = setTimeout(() => hovered.value = false, 300);
|
||||
|
|
@ -93,17 +116,17 @@ function hidePreview(e: Event) {
|
|||
|
||||
<template >
|
||||
<template v-if="href !== ''">
|
||||
<NuxtLink custom no-prefetch v-slot="{ href: hrefSlot, navigate }" :href="{ path: content?._path ?? link, hash: anchor }" :target="target">
|
||||
<a :href="hrefSlot" @click="navigate" @mouseenter="(e) => showPreview(e, true)" @mouseleave="hidePreview" v-bind="$attrs"><slot ></slot></a>
|
||||
<NuxtLink custom no-prefetch v-slot="{ href: hrefSlot, navigate }" :href="isTag ? undefined : { path: content?._path ?? link, hash: anchor }" :target="target">
|
||||
<a :href="hrefSlot" @click="(isTag ? (e: Event) => e.preventDefault() : navigate)" @mouseenter="(e) => showPreview(e, true)" @mouseleave="hidePreview" v-bind="$attrs"><slot ></slot></a>
|
||||
</NuxtLink>
|
||||
<Teleport to="body" v-if="hovered && (loading || !!content)">
|
||||
<div class="popover hover-popover is-loaded" :style="pos" @mouseenter="(e) => showPreview(e, false)" @mouseleave="hidePreview">
|
||||
<template v-if="!!content">
|
||||
<div class="markdown-embed" v-if="content._type == 'markdown' && ((content as ParsedContent)?.body?.children?.length ?? 0) > 0">
|
||||
<div class="markdown-embed" :class="{'tag-embed': isTag}" v-if="content._type == 'markdown' && ((content as ParsedContent)?.body?.children?.length ?? 0) > 0">
|
||||
<div class="markdown-embed-content">
|
||||
<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="content?.title">{{ content?.title }}</h1>
|
||||
<h1 v-if="content?.title && !isTag">{{ content?.title }}</h1>
|
||||
<ContentRenderer :key="content._id" :value="content"/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -116,12 +139,14 @@ function hidePreview(e: Event) {
|
|||
<div class="not-found-container">
|
||||
<div class="not-found-image"></div>
|
||||
<div class="not-found-title">Impossible de prévisualiser</div>
|
||||
<div class="not-found-description">Cliquez sur le lien pour accéder au contenu</div>
|
||||
<div v-if="!isTag" class="not-found-description">Cliquez sur le lien pour accéder au contenu</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<div v-else>
|
||||
|
||||
<div v-else class="preload" style="text-align:center">
|
||||
<svg style="width:50px" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
||||
<path style="transform-origin:50px 50px;animation:1s linear infinite rotate" fill="currentColor" d="M73,50c0-12.7-10.3-23-23-23S27,37.3,27,50 M30.9,50c0-10.5,8.5-19.1,19.1-19.1S69.1,39.5,69.1,50"/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</Teleport>
|
||||
|
|
|
|||
|
|
@ -1,20 +0,0 @@
|
|||
<template>
|
||||
<div class="render-container-inner" >
|
||||
<div class="publish-renderer">
|
||||
<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>Bonjour :)</h1>
|
||||
</div>
|
||||
</div>
|
||||
<div class="extra-title">
|
||||
<span class="extra-title-text">Home</span>
|
||||
<span aria-label="Close page" role="button">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="svg-icon lucide-x">
|
||||
<line x1="18" y1="6" x2="6" y2="18"></line>
|
||||
<line x1="6" y1="6" x2="18" y2="18"></line>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -1,13 +1,6 @@
|
|||
<script setup lang="ts">
|
||||
const { page } = useContent()
|
||||
|
||||
/*function toggleCollapse(e: HTMLElement)
|
||||
{
|
||||
e.classList.toggle('is-collapsed');
|
||||
const children = [...e.children];
|
||||
children.splice(0, 1);
|
||||
children.forEach(e => e.classList);
|
||||
}*/
|
||||
useContentHead(page);
|
||||
|
||||
onMounted(() => {
|
||||
document.querySelectorAll('.callout.is-collapsible .callout-title').forEach(e => {
|
||||
|
|
|
|||
|
|
@ -1,3 +0,0 @@
|
|||
<template>
|
||||
Tags
|
||||
</template>
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
<script setup lang="ts">
|
||||
const query = await queryContent().where({
|
||||
tags: { $exists: true }
|
||||
}).find();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div v-for="article in query" :key="article._path">
|
||||
<h2>{{ article.title }}</h2>
|
||||
<p>{{ article.description }}</p>
|
||||
</div>
|
||||
</template>
|
||||
Loading…
Reference in New Issue