mirror of
https://iceshrimp.dev/Crimekillz/jointrashposs.git
synced 2024-11-22 08:53:49 +01:00
parent
dd24af3496
commit
ef7c1e00ac
@ -37,6 +37,13 @@ VuePressでは末尾が`.md`となるパス形式でしたが、Misskey-Hub-Next
|
|||||||
date: 2023-11-11
|
date: 2023-11-11
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### `thumbnail`
|
||||||
|
(現状ブログのみ)サムネイル画像を設定できます。URLまたはサイトディレクトリの絶対パスを入力してください
|
||||||
|
|
||||||
|
```yml
|
||||||
|
thumbnail: /img/blog/foo/bar.png
|
||||||
|
```
|
||||||
|
|
||||||
### `maxTocDepth`
|
### `maxTocDepth`
|
||||||
(Docsのみ)もくじの見出しを遡る限度を指定できます。`<h2>`タグまでにしたい場合は`2`を指定します。
|
(Docsのみ)もくじの見出しを遡る限度を指定できます。`<h2>`タグまでにしたい場合は`2`を指定します。
|
||||||
|
|
||||||
|
@ -5,8 +5,8 @@
|
|||||||
<LeftIco class="mr-2 stroke-1 stroke-current" />
|
<LeftIco class="mr-2 stroke-1 stroke-current" />
|
||||||
</GNuxtLink>
|
</GNuxtLink>
|
||||||
<p class="text-center mb-4">{{ $t('_blog.title') }}</p>
|
<p class="text-center mb-4">{{ $t('_blog.title') }}</p>
|
||||||
<h1 class="text-center font-bold text-2xl lg:text-3xl mb-4">{{ data.title }}</h1>
|
<h1 class="text-center font-bold text-2xl lg:text-3xl mb-4">{{ data?.title }}</h1>
|
||||||
<p class="text-center">{{ $d(new Date(data.date)) }}</p>
|
<p class="text-center">{{ $d(new Date(data?.date)) }}</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="bg-white dark:bg-slate-950 pb-12 lg:mt-12 pt-6 px-6">
|
<div class="bg-white dark:bg-slate-950 pb-12 lg:mt-12 pt-6 px-6">
|
||||||
<div class="mx-auto container max-w-screen-md markdown-body">
|
<div class="mx-auto container max-w-screen-md markdown-body">
|
||||||
@ -23,6 +23,9 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import LeftIco from 'bi/arrow-left.svg';
|
import LeftIco from 'bi/arrow-left.svg';
|
||||||
|
import { isLocalPath } from '~/assets/js/misc';
|
||||||
|
import { joinURL } from 'ufo';
|
||||||
|
import type { MiBlogParsedContent } from '~/types/content';
|
||||||
// 日本語でしか提供されない
|
// 日本語でしか提供されない
|
||||||
defineI18nRoute({
|
defineI18nRoute({
|
||||||
locales: ['ja'],
|
locales: ['ja'],
|
||||||
@ -31,7 +34,16 @@ defineI18nRoute({
|
|||||||
const localePath = useLocalePath();
|
const localePath = useLocalePath();
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const { data } = await useAsyncData(`blog-${route.params.slug}`, () => queryContent(`/blog/${route.params.slug}`).findOne())
|
const runtimeConfig = useRuntimeConfig();
|
||||||
|
const { data } = await useAsyncData(`blog-${route.params.slug}`, () => queryContent<MiBlogParsedContent>(`/blog/${route.params.slug}`).findOne());
|
||||||
|
|
||||||
|
if (data.value?.thumbnail) {
|
||||||
|
route.meta.thumbnail = isLocalPath(data.value.thumbnail) ? joinURL(runtimeConfig.public.baseUrl, data.value.thumbnail) : data.value.thumbnail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!data.value) {
|
||||||
|
throw createError({ statusCode: 404, statusMessage: 'page not found' });
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="grid docs-main">
|
<div class="grid docs-main">
|
||||||
<div class="lg:hidden sticky top-16 -mx-6 -mt-6 overflow-y-auto bg-slate-50 dark:bg-slate-900 z-[9890] border-b dark:border-slate-700 text-sm flex items-start">
|
<div class="lg:hidden sticky top-16 -mx-6 -mt-6 overflow-y-auto bg-slate-50 dark:bg-slate-900 z-[9890] border-b dark:border-slate-700 text-sm flex items-start">
|
||||||
<details v-if="data?.body && data.body.toc.links.length > 0" class="peer order-2 flex-grow flex-shrink-0" :open="openState">
|
<details v-if="data?.body && data.body.toc?.links.length > 0" class="peer order-2 flex-grow flex-shrink-0" :open="openState">
|
||||||
<summary class="py-4 cursor-pointer">
|
<summary class="py-4 cursor-pointer">
|
||||||
{{ $t('_docs._toc.title') }}
|
{{ $t('_docs._toc.title') }}
|
||||||
</summary>
|
</summary>
|
||||||
<div class="pb-4 px-6 max-h-[65vh] overflow-y-auto">
|
<div class="pb-4 px-6 max-h-[65vh] overflow-y-auto">
|
||||||
<DocsTocLinks :links="data?.body.toc.links" :max-depth="data?.maxTocDepth ?? undefined" @child-click="openState = false" />
|
<DocsTocLinks :links="data?.body.toc?.links" :max-depth="data?.maxTocDepth ?? undefined" @child-click="openState = false" />
|
||||||
</div>
|
</div>
|
||||||
</details>
|
</details>
|
||||||
<button @click="isAsideNavOpen = !isAsideNavOpen" class="p-4 order-1 dark:border-slate-800 border-r peer-open:border-b mr-2">
|
<button @click="isAsideNavOpen = !isAsideNavOpen" class="p-4 order-1 dark:border-slate-800 border-r peer-open:border-b mr-2">
|
||||||
@ -42,6 +42,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import AsideNavIco from 'bi/text-indent-left.svg';
|
import AsideNavIco from 'bi/text-indent-left.svg';
|
||||||
import ExtIco from 'bi/box-arrow-up-right.svg';
|
import ExtIco from 'bi/box-arrow-up-right.svg';
|
||||||
|
import type { MiDocsParsedContent } from '~/types/content';
|
||||||
|
|
||||||
const isAsideNavOpen = useState<boolean>('miHub_docs_asideNav_openState', () => false);
|
const isAsideNavOpen = useState<boolean>('miHub_docs_asideNav_openState', () => false);
|
||||||
|
|
||||||
@ -55,7 +56,7 @@ definePageMeta({
|
|||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const slugs = (route.params.slug as string[]).filter((v) => v !== '');
|
const slugs = (route.params.slug as string[]).filter((v) => v !== '');
|
||||||
|
|
||||||
const { data } = await useAsyncData(`docs-${locale.value}-${slugs.join('-')}`, () => queryContent(`/${locale.value}/docs/${slugs.join('/')}`).findOne());
|
const { data } = await useAsyncData(`docs-${locale.value}-${slugs.join('-')}`, () => queryContent<MiDocsParsedContent>(`/${locale.value}/docs/${slugs.join('/')}`).findOne());
|
||||||
|
|
||||||
if (!data.value) {
|
if (!data.value) {
|
||||||
throw createError({ statusCode: 404, statusMessage: 'page not found' });
|
throw createError({ statusCode: 404, statusMessage: 'page not found' });
|
||||||
|
29
types/content.ts
Normal file
29
types/content.ts
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
// Misskey Docs Frontmatter Types
|
||||||
|
import type { ParsedContent, MarkdownParsedContent } from '@nuxt/content/dist/runtime/types';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Docs Frontmatter の型定義
|
||||||
|
*
|
||||||
|
* `/content/<lang>/docs/` のフロントマターはこの形式で入力してください
|
||||||
|
*/
|
||||||
|
export interface MiDocsParsedContent extends MarkdownParsedContent {
|
||||||
|
/** もくじの見出しをさかのぼる限度 */
|
||||||
|
maxTocDepth?: number;
|
||||||
|
|
||||||
|
/** 前へ・次へボタンの階層考慮を無視 */
|
||||||
|
ignoreDirBasedNav?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Blog Frontmatter の型定義
|
||||||
|
*
|
||||||
|
* `/content/blog/` のフロントマターはこの形式で入力してください
|
||||||
|
*/
|
||||||
|
export interface MiBlogParsedContent extends MarkdownParsedContent {
|
||||||
|
/** サムネイル画像のURL・絶対パス */
|
||||||
|
thumbnail?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Docs API の型定義
|
||||||
|
*/
|
@ -1,15 +0,0 @@
|
|||||||
// Misskey Docs Frontmatter Types
|
|
||||||
import type { ParsedContent, MarkdownParsedContent } from '@nuxt/content/dist/runtime/types';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Docs Frontmatter の型定義
|
|
||||||
*
|
|
||||||
* `/content/<lang>/docs/` のフロントマターはこの形式で入力してください
|
|
||||||
*/
|
|
||||||
export interface MiDocsParsedContent extends MarkdownParsedContent {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Docs API の型定義
|
|
||||||
*/
|
|
Loading…
Reference in New Issue
Block a user