You've already forked obsidian-visualiser
Add gitea content searching and fix lots of things
This commit is contained in:
@@ -6,9 +6,21 @@ interface Props {
|
||||
zoom: number;
|
||||
}
|
||||
|
||||
function getColor(color: string): string
|
||||
{
|
||||
if(props.node?.color?.startsWith('#'))
|
||||
return hexToRgb(color);
|
||||
else
|
||||
return getComputedStyle(document.body, null).getPropertyValue('--canvas-color-' + props.node.color);
|
||||
}
|
||||
function hexToRgb(hex: string): string
|
||||
{
|
||||
return `${parseInt(hex.substring(1, 3), 16)}, ${parseInt(hex.substring(3, 5), 16)}, ${parseInt(hex.substring(5, 7), 16)}`;
|
||||
return `${parseInt(hex.substring(1, 3), 16)},${parseInt(hex.substring(3, 5), 16)},${parseInt(hex.substring(5, 7), 16)}`;
|
||||
}
|
||||
function darken(rgb: string): boolean
|
||||
{
|
||||
const [r, g, b] = rgb.split(',');
|
||||
return (299 * parseInt(r) + 587 * parseInt(g) + 114 * parseInt(b)) / 1e3 >= 150;
|
||||
}
|
||||
|
||||
const props = defineProps<Props>();
|
||||
@@ -25,7 +37,7 @@ if(props.node.color !== undefined)
|
||||
<template>
|
||||
<div class="canvas-node" :class="classes" :style="{transform: `translate(${node.x}px, ${node.y}px)`, width: `${node.width}px`, height: `${node.height}px`, '--canvas-node-width': `${node.width}px`, '--canvas-node-height': `${node.height}px`, '--canvas-color': props.node?.color?.startsWith('#') ? hexToRgb(props.node.color) : undefined}">
|
||||
<div class="canvas-node-container">
|
||||
<template v-if="props.node.type === 'group' || props.zoom > 0.5">
|
||||
<template v-if="props.node.type === 'group' || props.zoom > 0.4">
|
||||
<div class="canvas-node-content markdown-embed">
|
||||
<div v-if="props.node.text?.body?.children?.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">
|
||||
@@ -48,6 +60,6 @@ if(props.node.color !== undefined)
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div v-if="props.node.type === 'group' && props.node.label !== undefined" class="canvas-group-label">{{ props.node.label }}</div>
|
||||
<div v-if="props.node.type === 'group' && props.node.label !== undefined" class="canvas-group-label" :class="{'mod-foreground-dark': darken(getColor(props?.node?.color ?? '')), 'mod-foreground-light': !darken(getColor(props?.node?.color ?? ''))}">{{ props.node.label }}</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -1,17 +1,11 @@
|
||||
<script setup lang="ts">
|
||||
import("~/assets/canvas.css")
|
||||
|
||||
import type { CanvasNode, CanvasEdge } from '~/types/canvas';
|
||||
import type { Canvas, CanvasNode } from '~/types/canvas';
|
||||
|
||||
interface CanvasProps
|
||||
{
|
||||
_id: string;
|
||||
_type: string;
|
||||
body: { nodes: CanvasNode[], edges: CanvasEdge[] };
|
||||
}
|
||||
interface Props
|
||||
{
|
||||
canvas: CanvasProps;
|
||||
canvas: Canvas;
|
||||
}
|
||||
const props = defineProps<Props>();
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
<script setup lang="ts">
|
||||
import type { ParsedContent } from '@nuxt/content/dist/runtime/types';
|
||||
import type { MarkdownRoot, ParsedContent, TocLink } from '@nuxt/content/dist/runtime/types';
|
||||
import type { Canvas, CanvasContent } from '~/types/canvas';
|
||||
|
||||
interface ParsedContentExtended extends Omit<ParsedContent, 'body'> {
|
||||
body: MarkdownRoot | CanvasContent | null;
|
||||
}
|
||||
|
||||
const props = defineProps({
|
||||
href: {
|
||||
@@ -27,26 +32,58 @@ function flatten(val: TocLink[]): TocLink[] {
|
||||
|
||||
const link = (props.href.includes('#') ? props.href.substring(0, props.href.indexOf('#')) : props.href).replace(/\..*$/, '');
|
||||
const anchor = props.href.includes('#') ? props.href.substring(props.href.indexOf('#'), props.href.length) : '';
|
||||
let content: ParsedContent;
|
||||
try {
|
||||
content = await queryContent().where({ _path: new RegExp(sluggify(link) + '$', 'i') }).findOne();
|
||||
if(anchor && !!content && content._type == 'markdown' && content.body && content.body.children)
|
||||
let content = ref<ParsedContentExtended>(), loading = ref(true);
|
||||
|
||||
queryContent().where({ _path: new RegExp("/" + sluggify(link) + '$', 'i') }).findOne().then((result: ParsedContentExtended) => {
|
||||
content.value = result;
|
||||
loading.value = false;
|
||||
let body = result.body;
|
||||
|
||||
if(anchor && result && body)
|
||||
{
|
||||
const id = flatten(content.body.toc?.links).find(e => "#" + sluggify(e.id) === anchor);
|
||||
const tag = `h${id?.depth ?? 0}`;
|
||||
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 tag = `h${id?.depth ?? 0}`;
|
||||
|
||||
const startIdx = content.body.children.findIndex(e => e.tag === tag && e?.props?.id === id?.id) ?? 0;
|
||||
const nbr = content.body.children.findIndex((e, i) => i > startIdx && e.tag?.match(new RegExp(`h[1-${id?.depth ?? 1}]`))) ?? content.body.children.length;
|
||||
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}]`)));
|
||||
|
||||
content.body.children = content.body.children.splice(startIdx, nbr - startIdx);
|
||||
body.children = body.children.splice(startIdx, (nbr === -1 ? body.children.length : nbr) - startIdx);
|
||||
}
|
||||
else if(result._type == 'canvas')
|
||||
{
|
||||
body = body as CanvasContent;
|
||||
const nodes = body?.groups?.find(e => "#" + sluggify(e.name) === anchor)?.nodes;
|
||||
|
||||
body.nodes = body.nodes.filter(e => nodes?.includes(e.id));
|
||||
body.edges = body.edges.filter(e => nodes?.includes(e.fromNode) && nodes?.includes(e.toNode));
|
||||
}
|
||||
}
|
||||
} catch (e) {}
|
||||
}).catch(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
|
||||
const hovered = ref(false), pos = ref<DOMRect>();
|
||||
const hovered = ref(false), pos = ref<any>();
|
||||
let timeout: NodeJS.Timeout;
|
||||
function showPreview(e: Event, bbox: boolean) {
|
||||
clearTimeout(timeout);
|
||||
!!bbox && (pos.value = (e.currentTarget as HTMLElement)?.getBoundingClientRect());
|
||||
if(bbox)
|
||||
{
|
||||
const target = e.currentTarget as HTMLElement;
|
||||
const rect = target?.getBoundingClientRect();
|
||||
const r: any = {};
|
||||
if(rect.bottom + 450 < window.innerHeight)
|
||||
r.top = (rect.bottom + 4) + "px";
|
||||
else
|
||||
r.bottom = (window.innerHeight - rect.top + 4) + "px";
|
||||
if(rect.right + 550 < window.innerWidth)
|
||||
r.left = rect.left + "px";
|
||||
else
|
||||
r.right = (window.innerWidth - rect.left + 4) + "px";
|
||||
pos.value = r;
|
||||
}
|
||||
hovered.value = true;
|
||||
}
|
||||
function hidePreview(e: Event) {
|
||||
@@ -55,28 +92,35 @@ function hidePreview(e: Event) {
|
||||
</script>
|
||||
|
||||
<template >
|
||||
<NuxtLink custom no-prefetch v-slot="{ href: hrefSlot, navigate }" :to="(content?._path ?? href + anchor) ?? href" :target="target">
|
||||
<NuxtLink custom no-prefetch v-slot="{ href: hrefSlot, navigate }" :to="(content?._path ?? link + anchor) ?? href" :target="target">
|
||||
<a :href="hrefSlot" @click="navigate" @mouseenter="(e) => showPreview(e, true)" @mouseleave="hidePreview" v-bind="$attrs"><slot ></slot></a>
|
||||
</NuxtLink>
|
||||
<Teleport to="body" v-if="hovered && !!content">
|
||||
<div class="popover hover-popover is-loaded" :style="{ top: (pos.bottom + 4) + 'px', left: pos.left + 'px' }" @mouseenter="(e) => showPreview(e, false)" @mouseleave="hidePreview">
|
||||
<div class="markdown-embed" v-if="content._type == 'markdown'">
|
||||
<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>
|
||||
<ContentRenderer :key="content._id" :value="content"/>
|
||||
<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-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>
|
||||
<ContentRenderer :key="content._id" :value="content"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<CanvasRenderer v-else-if="content._type == 'canvas'" :key="content._id" :canvas="content" />
|
||||
<div v-else>
|
||||
<div class="not-found-container">
|
||||
<div class="not-found-image"></div>
|
||||
<div class="not-found-title">Impossible d'afficher</div>
|
||||
<div class="not-found-description">Cette page est actuellement vide et impossible à traiter</div>
|
||||
<div v-else-if="content._type == 'canvas'" class="canvas-embed is-loaded">
|
||||
<CanvasRenderer :key="content._id" :canvas="(content as Canvas)" />
|
||||
</div>
|
||||
<div class="markdown-embed" v-else>
|
||||
<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>
|
||||
</div>
|
||||
</template>
|
||||
<div v-else>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</Teleport>
|
||||
|
||||
Reference in New Issue
Block a user