mirror of
https://iceshrimp.dev/Crimekillz/jointrashposs.git
synced 2024-11-22 00:43:50 +01:00
(Add) AsideNav
This commit is contained in:
parent
6623b2acae
commit
98c9a32709
@ -1,3 +1,5 @@
|
||||
import type { NavItem } from '@nuxt/content/dist/runtime/types';
|
||||
|
||||
export function resolveObjPath(o: object, s: string): any {
|
||||
s = s.replace(/\[(\w+)\]/g, '.$1'); // convert indexes to properties
|
||||
s = s.replace(/^\./, ''); // strip a leading dot
|
||||
@ -40,7 +42,7 @@ export function isLocalPath(link: string, base?: string): boolean {
|
||||
|
||||
}
|
||||
|
||||
export const findDeepObject = (obj: Record<string, any>, condition: (v: any) => boolean): Record<string, any> | null => {
|
||||
export const findDeepObject = (obj: NavItem, condition: (v: NavItem) => boolean): NavItem | null => {
|
||||
if (condition(obj)) {
|
||||
return obj;
|
||||
}
|
||||
|
@ -2,14 +2,14 @@
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Permisson</th>
|
||||
<th>Description</th>
|
||||
<th>{{ $t('_api._permissions.title') }}</th>
|
||||
<th>{{ $t('_api._permissions.description') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="permission in permissions">
|
||||
<td><code>{{ permission }}</code></td>
|
||||
<td>{{ $t(`_api._permissions.${permission}`) }}</td>
|
||||
<td>{{ $t(`_api._permissions._types.${permission}`) }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
@ -1,61 +1,78 @@
|
||||
<template>
|
||||
<ul class="toc-links mb-4 space-y-2">
|
||||
<ul class="toc-links text-sm" :class="[
|
||||
`depth-${depth}`,
|
||||
depth === 1 ? 'mb-4' : 'mb-2',
|
||||
]">
|
||||
<li
|
||||
v-for="link in findDeepObject((links[0] as NavItem), (v) => realBasePath.replace(/\/$/, '') === v?._path.replace(/\/$/, ''))?.children ?? []"
|
||||
v-for="link in realLinks ?? []"
|
||||
:key="link.text"
|
||||
:class="[`depth-${link.depth}`]"
|
||||
:class="[
|
||||
depth === 2 && 'border-l-2 flex flex-col',
|
||||
path.includes(link._path) ? 'border-accent-500' : 'border-gray-300',
|
||||
]"
|
||||
>
|
||||
<GNuxtLink
|
||||
:to="link._path"
|
||||
@click.passive="emit('child-click');"
|
||||
:class="['hover:text-accent-600']"
|
||||
:class="[
|
||||
'block hover:text-accent-600',
|
||||
depth === 1 && 'text-base',
|
||||
depth === 2 ? 'px-2 py-1' : 'py-1',
|
||||
isSamePath(path, link._path) && 'text-accent-600 font-bold',
|
||||
]"
|
||||
>
|
||||
{{ link.text }}
|
||||
<div class="flex">
|
||||
<div v-if="link.children && link.children.filter((v) => !isSamePath(v._path, link._path)).length > 0" class="mr-2">
|
||||
<ArrowIco
|
||||
:class="[
|
||||
'transition-transform',
|
||||
path.includes(link._path) && 'rotate-90'
|
||||
]"
|
||||
/>
|
||||
</div>
|
||||
<div>{{ link.title }}</div>
|
||||
</div>
|
||||
</GNuxtLink>
|
||||
<AsideNav
|
||||
class="mt-2"
|
||||
v-if="link.children"
|
||||
:links="link.children"
|
||||
v-if="link.children && link.children.filter((v) => !isSamePath(v._path, link._path)).length > 0"
|
||||
v-show="path.includes(link._path)"
|
||||
:links="[link]"
|
||||
:depth="depth + 1"
|
||||
/>
|
||||
</li>
|
||||
</ul>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import type { PropType } from 'vue'
|
||||
import type { NavItem } from '@nuxt/content/dist/runtime/types'
|
||||
import { findDeepObject } from 'assets/js/misc';
|
||||
import { findDeepObject } from '@/assets/js/misc';
|
||||
import { isSamePath } from 'ufo';
|
||||
import ArrowIco from "bi/chevron-right.svg";
|
||||
|
||||
const props = defineProps({
|
||||
links: {
|
||||
type: Array as PropType<NavItem[]>,
|
||||
default: () => []
|
||||
},
|
||||
basePath: {
|
||||
type: String,
|
||||
default: '',
|
||||
}
|
||||
const props = withDefaults(defineProps<{
|
||||
links: NavItem[];
|
||||
depth?: number;
|
||||
}>(), {
|
||||
depth: 1,
|
||||
});
|
||||
|
||||
const { locale } = useI18n();
|
||||
const route = useRoute();
|
||||
const { path } = useRoute();
|
||||
|
||||
const realBasePath = computed<string>(() => {
|
||||
if (props.basePath) {
|
||||
return props.basePath;
|
||||
const realLinks = findDeepObject(props.links[0], (v) => {
|
||||
if (props.depth === 1) {
|
||||
return isSamePath(`/${locale.value}/docs/`, v._path);
|
||||
} else {
|
||||
return v._path.includes(props.links[0]._path);
|
||||
}
|
||||
return route.path.replace(/^.*\/docs/, `/${locale.value}/docs`);
|
||||
});
|
||||
})?.children?.filter((v) => !isSamePath(v._path, props.links[0]._path));
|
||||
|
||||
const emit = defineEmits(['move', 'child-click']);
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.toc-links ::v-deep(.depth-3) {
|
||||
@apply ml-2;
|
||||
}
|
||||
.toc-links ::v-deep(.depth-4) {
|
||||
@apply ml-4;
|
||||
.toc-links:not(.depth-1) {
|
||||
@apply ml-6;
|
||||
}
|
||||
</style>
|
@ -9,7 +9,7 @@
|
||||
</div>
|
||||
<ul class="hidden lg:col-span-4 lg:space-x-8 xl:space-x-10 lg:flex justify-center">
|
||||
<li v-for="item in NavData.center">
|
||||
<GNuxtLink :to="localePath(item.to)" :class="['rounded-full px-4 py-1.5 hover:bg-slate-300 dark:hover:bg-slate-800 hover:bg-opacity-50 bg-blend-multiply', { 'bg-slate-200 dark:bg-slate-800 font-bold': currentPath.replace(/\/$/, '').includes(localePath(item.to).replace(/\/$/, '')) }]">
|
||||
<GNuxtLink :to="localePath(item.to)" :class="['rounded-full px-4 py-1.5 hover:bg-slate-300 dark:hover:bg-slate-800 hover:bg-opacity-50 bg-blend-multiply', { 'bg-slate-200 dark:bg-slate-800 font-bold': currentPath.includes(item.to) }]">
|
||||
<component v-if="item.icon" :is="item.icon" class="h-5 w-5" />
|
||||
<template v-else>
|
||||
{{ $t(item.i18n) }}
|
||||
@ -77,9 +77,11 @@ const { locales, locale: currentLocale } = useI18n();
|
||||
const { path } = useRoute();
|
||||
const { afterEach } = useRouter();
|
||||
const currentPath = ref(path);
|
||||
|
||||
afterEach((to) => {
|
||||
currentPath.value = to.path;
|
||||
})
|
||||
});
|
||||
|
||||
const switchLocalePath = useSwitchLocalePath();
|
||||
const localePath = useLocalePath();
|
||||
|
||||
|
2
content/ja/docs/4.for-developers/_dir.yml
Normal file
2
content/ja/docs/4.for-developers/_dir.yml
Normal file
@ -0,0 +1,2 @@
|
||||
title: "開発者向け"
|
||||
description: "プラグイン・Play開発者や、APIを利用した外部アプリケーションの開発者向けリソース。"
|
@ -2,5 +2,10 @@
|
||||
<div class="text-slate-800 dark:text-slate-200 bg-slate-100 dark:bg-gray-900">
|
||||
<noscript class="block bg-accent-800 text-white text-center py-1.5 px-3 keep-all relative z-[10005]">Please turn on Javascript from your browser's settings.</noscript>
|
||||
ページが見つかりませんでした
|
||||
<pre>{{ error }}</pre>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
const error = useError();
|
||||
</script>
|
@ -6,13 +6,40 @@ useHead({
|
||||
class: 'scroll-pt-32 lg:scroll-pt-20',
|
||||
},
|
||||
});
|
||||
|
||||
const { locale } = useI18n();
|
||||
const { data: navigation } = await useAsyncData('navigation', () => fetchContentNavigation(queryContent(`/${locale.value}/docs/`)));
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="bg-white dark:bg-slate-950">
|
||||
<GNav @toggleNav="isNavOpen = !isNavOpen" :is-open="isNavOpen" :slim="true" :disable-shadow="true" />
|
||||
<div class="main-content">
|
||||
<slot></slot>
|
||||
<div class="relative container mx-auto max-w-screen-xl p-6 lg:py-0 grid docs-root pb-12">
|
||||
<slot name="spToc"></slot>
|
||||
<div class="hidden lg:block">
|
||||
<slot name="right">
|
||||
<div class="sticky top-16 h-[calc(100vh-4rem)] overflow-y-scroll border-r border-slate-200 dark:border-slate-700 py-6 pr-3">
|
||||
<DocsAsideNav :links="navigation ?? []" />
|
||||
</div>
|
||||
</slot>
|
||||
</div>
|
||||
<div class="pt-6 lg:p-6 w-full overflow-x-hidden">
|
||||
<slot name="main"></slot>
|
||||
</div>
|
||||
<div class="hidden lg:block text-sm">
|
||||
<slot name="left"></slot>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<GFooter class="bg-slate-100 dark:bg-gray-900" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
@screen lg {
|
||||
.docs-root {
|
||||
grid-template-columns: 16rem 1fr 14rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -160,3 +160,7 @@ _links:
|
||||
_aiChan:
|
||||
title: "藍"
|
||||
description: "Misskeyの看板娘、藍のウェブサイトです。"
|
||||
_api:
|
||||
_permissions:
|
||||
title: "権限"
|
||||
description: "説明"
|
@ -9,6 +9,7 @@
|
||||
"postinstall": "nuxt prepare"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/parser": "^7.22.16",
|
||||
"@modyfi/vite-plugin-yaml": "^1.0.4",
|
||||
"@nuxt/content": "^2.8.0",
|
||||
"@nuxtjs/color-mode": "^3.3.0",
|
||||
|
@ -1,19 +1,19 @@
|
||||
<template>
|
||||
<div class="relative container mx-auto max-w-screen-xl p-6 lg:py-0 grid docs-root pb-12">
|
||||
<NuxtLayout name="docs">
|
||||
<template #spToc>
|
||||
<div v-if="data?.body" class="lg:hidden sticky top-16 -mx-6 -mt-6 bg-white px-6 bg-opacity-60 backdrop-blur-lg z-[9890] border-b text-sm">
|
||||
<details :open="openState">
|
||||
<summary class="py-4 cursor-pointer">{{ $t('_docs._toc.title') }}</summary>
|
||||
<summary class="py-4 cursor-pointer">
|
||||
{{ $t('_docs._toc.title') }}
|
||||
</summary>
|
||||
<div class="pb-4 overflow-y-auto">
|
||||
<DocsTocLinks :links="data?.body.toc.links" @child-click="openState = false" />
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
<div class="hidden lg:block">
|
||||
<div class="sticky top-16 h-[calc(100vh-4rem)] overflow-y-scroll border-r border-slate-200 dark:border-slate-700 py-6 pr-6">
|
||||
<DocsAsideNav :links="navigation" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="pt-6 lg:p-6 w-full overflow-x-hidden">
|
||||
</template>
|
||||
|
||||
<template #main>
|
||||
<template v-if="data?.body">
|
||||
<ContentRenderer v-if="data.body.children.length > 0" :value="data" class="markdown-body w-full mb-6">
|
||||
</ContentRenderer>
|
||||
@ -25,14 +25,15 @@
|
||||
<MkIndex :is-dir="data?._file?.endsWith('index.md') || (!data?._file)" />
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div class="hidden lg:block text-sm">
|
||||
</template>
|
||||
|
||||
<template #left>
|
||||
<div class="sticky top-16 h-[calc(100vh-4rem)] overflow-y-auto py-6 pl-6">
|
||||
<h3 class="font-bold mb-6">{{ $t('_docs._toc.title') }}</h3>
|
||||
<DocsTocLinks v-if="data?.body" :links="data?.body.toc.links" class="break-words" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</NuxtLayout>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
@ -42,7 +43,7 @@ const { locale, locales } = useI18n();
|
||||
const openState = ref<boolean>(false);
|
||||
|
||||
definePageMeta({
|
||||
layout: 'docs',
|
||||
layout: false,
|
||||
});
|
||||
|
||||
defineI18nRoute({
|
||||
@ -55,7 +56,6 @@ const route = useRoute();
|
||||
const slugs = (route.params.slug as string[]).filter((v) => v !== '');
|
||||
|
||||
const { data } = await useAsyncData(`blog-${locale.value}-${slugs.join('-')}`, () => queryContent(`/${locale.value}/docs/${slugs.join('/')}`).findOne());
|
||||
const { data: navigation } = await useAsyncData('navigation', () => fetchContentNavigation(queryContent(`/${locale.value}/docs/${slugs[0]}`)));
|
||||
|
||||
if (!data.value) {
|
||||
throw createError({ statusCode: 404, statusMessage: 'page not found' });
|
||||
@ -63,11 +63,3 @@ if (!data.value) {
|
||||
|
||||
route.meta.title = data.value?.title;
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
@screen lg {
|
||||
.docs-root {
|
||||
grid-template-columns: 14rem 1fr 14rem;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -10,6 +10,9 @@ dependencies:
|
||||
version: 4.1.0
|
||||
|
||||
devDependencies:
|
||||
'@babel/parser':
|
||||
specifier: ^7.22.16
|
||||
version: 7.22.16
|
||||
'@modyfi/vite-plugin-yaml':
|
||||
specifier: ^1.0.4
|
||||
version: 1.0.4(vite@4.4.9)
|
||||
|
@ -2,7 +2,9 @@
|
||||
import { locales } from "@/nuxt.config";
|
||||
import * as misskey from "misskey-js";
|
||||
import yaml from "js-yaml";
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import { parse } from "@babel/parser";
|
||||
|
||||
// オブジェクト obj1 にないキーだけを、元オブジェクトにマージする関数
|
||||
function mergeObjects(obj1: Record<string, any>, obj2: Record<string, any>): Record<string, any> {
|
||||
@ -28,5 +30,18 @@ export function genApiTranslationFiles() {
|
||||
out._permissions[permission] = 'Untranslated / 未翻訳';
|
||||
});
|
||||
|
||||
// エンティティ(TODO)
|
||||
const endpointDTSPath = require.resolve('misskey-js', { paths: ['/built/api.types.d.ts'] });
|
||||
/*
|
||||
const ep = fs.readFileSync(endpointDTSPath, "utf-8");
|
||||
const parsedEP = parse(ep, {
|
||||
sourceType: "module",
|
||||
plugins: [[
|
||||
"typescript", {
|
||||
dts: true,
|
||||
},
|
||||
]],
|
||||
});
|
||||
|
||||
console.log(JSON.stringify(parsedEP));
|
||||
*/
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user