feat: add valaxy-theme-press for docs

This commit is contained in:
YunYouJun 2022-07-11 23:33:21 +08:00
parent 2a6fdcc70b
commit 2e6c4ca208
35 changed files with 744 additions and 3 deletions

5
docs/README.md Normal file
View File

@ -0,0 +1,5 @@
# docs
Docs for valaxy.
Use theme [valaxy-theme-press](./packages/valaxy-theme-press).

35
docs/components.d.ts vendored Normal file
View File

@ -0,0 +1,35 @@
// generated by unplugin-vue-components
// We suggest you to commit this file into source control
// Read more: https://github.com/vuejs/core/pull/3399
import '@vue/runtime-core'
export {}
declare module '@vue/runtime-core' {
export interface GlobalComponents {
404: typeof import('./../packages/valaxy-theme-press/layouts/404.vue')['default']
AppLink: typeof import('./../packages/valaxy/client/components/AppLink.vue')['default']
Default: typeof import('./../packages/valaxy-theme-press/layouts/default.vue')['default']
Home: typeof import('./../packages/valaxy-theme-press/layouts/home.vue')['default']
Layout: typeof import('./../packages/valaxy-theme-press/layouts/layout.vue')['default']
Post: typeof import('./../packages/valaxy-theme-press/layouts/post.vue')['default']
PressArticle: typeof import('./../packages/valaxy-theme-press/components/PressArticle.vue')['default']
PressArticleCard: typeof import('./../packages/valaxy-theme-press/components/PressArticleCard.vue')['default']
PressAuthor: typeof import('./../packages/valaxy-theme-press/components/PressAuthor.vue')['default']
PressDate: typeof import('./../packages/valaxy-theme-press/components/PressDate.vue')['default']
PressHeader: typeof import('./../packages/valaxy-theme-press/components/PressHeader.vue')['default']
PressNav: typeof import('./../packages/valaxy-theme-press/components/PressNav.vue')['default']
PressPostList: typeof import('./../packages/valaxy-theme-press/components/PressPostList.vue')['default']
PressToggleLocale: typeof import('./../packages/valaxy-theme-press/components/PressToggleLocale.vue')['default']
README: typeof import('./../packages/valaxy/client/layouts/README.md')['default']
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
ValaxyCopyright: typeof import('./../packages/valaxy/client/components/ValaxyCopyright.vue')['default']
ValaxyHamburger: typeof import('./../packages/valaxy/client/components/ValaxyHamburger.vue')['default']
ValaxyMain: typeof import('./../packages/valaxy-theme-press/components/ValaxyMain.vue')['default']
ValaxyMd: typeof import('./../packages/valaxy/client/components/ValaxyMd.vue')['default']
ValaxyOverlay: typeof import('./../packages/valaxy/client/components/ValaxyOverlay.vue')['default']
ValaxyPagination: typeof import('./../packages/valaxy/client/components/ValaxyPagination.vue')['default']
ValaxySidebar: typeof import('./../packages/valaxy/client/components/ValaxySidebar.vue')['default']
}
}

20
docs/package.json Normal file
View File

@ -0,0 +1,20 @@
{
"name": "valaxy-docs",
"private": true,
"scripts": {
"build": "npm run build:ssg && npm run rss",
"build:spa": "valaxy build",
"build:ssg": "valaxy build --ssg",
"dev": "nodemon -w \"../packages/valaxy/dist/*.js\" --exec \"valaxy .\"",
"rss": "valaxy rss",
"serve": "vite preview"
},
"dependencies": {
"valaxy": "link:../packages/valaxy",
"valaxy-theme-yun": "link:../packages/valaxy-theme-yun"
},
"devDependencies": {
"@waline/client": "^2.6.1",
"nodemon": "^2.0.19"
}
}

0
docs/pages/index.md Normal file
View File

View File

@ -0,0 +1,5 @@
---
title: Hello Theme Press
---
Hello Valaxy Theme Press

1
docs/public/CNAME Normal file
View File

@ -0,0 +1 @@
valaxy.site

5
docs/public/favicon.svg Normal file
View File

@ -0,0 +1,5 @@
<svg width="100" height="70" viewBox="0 0 100 70" fill="#0078e7" xmlns="http://www.w3.org/2000/svg">
<path d="M44 35L27.5 44.5263V25.4737L44 35Z" />
<path d="M74 35C74 39.9706 69.9706 44 65 44C60.0294 44 56 39.9706 56 35C56 30.0294 60.0294 26 65 26C69.9706 26 74 30.0294 74 35Z" />
<path fill-rule="evenodd" clip-rule="evenodd" d="M85 0H15V15H0V55H15V70H85V55H100V15H85V0ZM85 15H15V55H85V15Z" />
</svg>

After

Width:  |  Height:  |  Size: 403 B

9
docs/valaxy.config.ts Normal file
View File

@ -0,0 +1,9 @@
import { defineConfig } from 'valaxy'
export default defineConfig({
title: 'Valaxy',
url: 'https://valaxy.site',
theme: 'press',
themeConfig: {},
})

View File

@ -25,11 +25,15 @@
"build:valaxy": "pnpm -C packages/valaxy run build",
"build:theme": "pnpm -C packages/valaxy-theme-yun run build",
"build:demo": "pnpm -C demo/yun run build",
"build:docs": "pnpm -C docs run build",
"ci:publish": "zx scripts/publish.mjs",
"demo": "pnpm -C demo/yun run dev",
"dev:lib": "pnpm -C packages/valaxy run dev",
"dev:theme": "pnpm -C packages/valaxy-theme-yun run dev",
"dev": "pnpm -r --filter=./packages/** --parallel run dev",
"docs": "pnpm -C docs run dev",
"press": "pnpm -C packages/valaxy-theme-press run dev",
"press:build": "pnpm -C packages/valaxy-theme-press run build",
"lint": "eslint .",
"prepublishOnly": "npm run build",
"release": "tsx scripts/release.ts",
@ -54,6 +58,7 @@
"tsx": "^3.7.1",
"typescript": "^4.7.4",
"valaxy": "workspace:*",
"valaxy-theme-press": "workspace:*",
"valaxy-theme-yun": "workspace:*",
"vitest": "^0.18.0",
"vue-tsc": "0.38.3",

View File

@ -0,0 +1,85 @@
<script setup lang="ts">
import { computed } from 'vue'
import { useRoute } from 'vue-router'
import { useFrontmatter, usePostList } from 'valaxy'
const frontmatter = useFrontmatter()
const route = useRoute()
const posts = usePostList()
function findCurrentIndex() {
return posts.value.findIndex(p => p.href === route.path)
}
const nextPost = computed(() => posts.value[findCurrentIndex() - 1])
const prevPost = computed(() => posts.value[findCurrentIndex() + 1])
</script>
<template>
<article class="xl:divide-y xl:divide-gray-200">
<header class="pt-6 xl:pb-10 space-y-1 text-center">
<PressDate :date="frontmatter.date" />
<h1
class="
text-3xl
leading-9
font-extrabold
text-gray-900
tracking-tight
sm:text-4xl sm:leading-10
md:text-5xl md:leading-14
"
>
{{ frontmatter.title }}
</h1>
</header>
<div
class="
divide-y
xl:divide-y-0
divide-gray-200
xl:grid xl:grid-cols-4 xl:gap-x-10
pb-16
xl:pb-20
"
style="grid-template-rows: auto 1fr"
>
<PressAuthor v-if="frontmatter.author" :frontmatter="frontmatter" />
<div class="divide-y divide-gray-200 xl:pb-0 xl:col-span-3 xl:row-span-2">
<router-view />
</div>
<footer
class="
text-sm
font-medium
leading-5
divide-y divide-gray-200
xl:col-start-1 xl:row-start-2
"
>
<div v-if="nextPost" class="py-8">
<h2 class="text-xs tracking-wide uppercase text-gray-500">
Next Article
</h2>
<div class="link">
<a :href="nextPost.href">{{ nextPost.title }}</a>
</div>
</div>
<div v-if="prevPost" class="py-8">
<h2 class="text-xs tracking-wide uppercase text-gray-500">
Previous Article
</h2>
<div class="link">
<a :href="prevPost.href">{{ prevPost.title }}</a>
</div>
</div>
<div class="pt-8">
<a class="link" href="/"> Back to the blog</a>
</div>
</footer>
</div>
</article>
</template>

View File

@ -0,0 +1,28 @@
<script lang="ts" setup>
import type { Post } from 'valaxy'
defineProps<{
post: Post
}>()
</script>
<template>
<article class="space-y-2 xl:grid xl:grid-cols-4 xl:space-y-0 xl:items-baseline">
<PressDate :date="post.date" />
<div class="space-y-5 xl:col-span-3">
<div class="space-y-6">
<h2 class="text-2xl leading-8 font-bold tracking-tight">
<a class="text-gray-900" :href="post.path">{{ post.title }}</a>
</h2>
<div
v-if="post.excerpt"
class="prose max-w-none text-gray-500"
v-html="post.excerpt"
/>
</div>
<div class="text-base leading-6 font-medium">
<a class="link" aria-label="read more" :href="post.path">Read more </a>
</div>
</div>
</article>
</template>

View File

@ -0,0 +1,55 @@
<script setup lang="ts">
import type { Post } from 'valaxy'
defineProps<{
frontmatter: Post
}>()
</script>
<template>
<dl class="pt-6 pb-10 xl:pt-11 xl:border-b xl:border-gray-200">
<dt class="sr-only">
Authors
</dt>
<dd>
<ul
class="
flex
justify-center
xl:block
space-x-8
sm:space-x-12
xl:space-x-0 xl:space-y-8
"
>
<li class="flex items-center space-x-2">
<img
v-if="frontmatter.gravatar"
:src="`https://gravatar.com/avatar/${frontmatter.gravatar}`"
alt="author image"
class="w-10 h-10 rounded-full"
>
<dl class="text-sm font-medium leading-5 whitespace-nowrap">
<dt class="sr-only">
Name
</dt>
<dd class="text-gray-900">
{{ frontmatter.author }}
</dd>
<dt v-if="frontmatter.twitter" class="sr-only">
Twitter
</dt>
<dd v-if="frontmatter.twitter">
<a
:href="`https://twitter.com/${frontmatter.twitter}`"
target="_blank"
rel="noopnener noreferrer"
class="link"
>{{ frontmatter.twitter }}</a>
</dd>
</dl>
</li>
</ul>
</dd>
</dl>
</template>

View File

@ -0,0 +1,21 @@
<script lang="ts" setup>
import { formatDate } from 'valaxy'
import { computed } from 'vue'
const props = defineProps<{
date?: Date | number | string
}>()
const datetime = computed(() => formatDate(props.date || ''))
</script>
<template>
<dl>
<dt class="sr-only">
Published on
</dt>
<dd class="text-base leading-6 font-medium text-gray-500">
<time :datetime="datetime">{{ datetime }}</time>
</dd>
</dl>
</template>

View File

@ -0,0 +1,26 @@
<script lang="ts" setup>
import { useConfig } from 'valaxy'
const config = useConfig()
</script>
<template>
<div class="pt-6 pb-8 space-y-2 md:space-y-5">
<h1
class="
text-3xl
leading-9
font-extrabold
text-gray-900
tracking-tight
sm:text-4xl sm:leading-10
md:text-6xl md:leading-14
"
>
{{ config.title }}
</h1>
<p class="text-lg leading-7 text-gray-500">
{{ config.subtitle }}
</p>
</div>
</template>

View File

@ -0,0 +1,38 @@
<script lang="ts" setup>
import { useConfig } from 'valaxy'
import { computed } from 'vue'
import { useRoute } from 'vue-router'
import { useThemeConfig } from '../composables'
const route = useRoute()
const isIndex = computed(() => route.path.replace(/index.html$/, '') === '/')
const config = useConfig()
const themeConfig = useThemeConfig()
</script>
<template>
<nav w="full" class="flex justify-between items-center py-10 font-bold">
<a class="text-xl" href="/" :aria-label="config.title">
<img
class="inline-block mr-2"
style="width: 50px; height: 35px"
alt="logo"
:src="config.favicon"
>
<span v-if="!isIndex" class="hidden md:inline">{{ config.title }}</span>
</a>
<div class="text-sm text-gray-500 leading-5">
<template v-for="(item, i) in themeConfig.nav" :key="i">
<a
class="hover:text-gray-700"
:href="item.link"
target="_blank"
rel="noopener"
>{{ item.text }}</a>
<span v-if="i !== themeConfig.nav.length - 1" class="mr-2 ml-2">·</span>
</template>
</div>
</nav>
</template>

View File

@ -0,0 +1,26 @@
<script setup lang="ts">
import { computed } from 'vue'
import type { Post } from 'valaxy'
import { usePostList } from 'valaxy'
const props = withDefaults(defineProps<{
type?: string
posts?: Post[]
curPage?: number
}>(), {
curPage: 1,
})
const routes = usePostList({ type: props.type || '' })
const posts = computed(() => props.posts || routes.value)
</script>
<template>
<ul class="divide-y divide-gray-200">
<Transition v-for="post, i in posts" :key="i" name="fade">
<li class="py-12">
<PressArticleCard :post="post" />
</li>
</Transition>
</ul>
</template>

View File

@ -0,0 +1,13 @@
<script lang="ts" setup>
import { useI18n } from 'vue-i18n'
import { useLocale } from 'valaxy'
const { t, locale } = useI18n()
const { toggleLocales } = useLocale()
</script>
<template>
<button class="yun-icon-btn" :title="t('button.toggle_langs')" style="color:var(--va-c-text)" @click="toggleLocales">
<div i-ri-translate class="transition transform" :class="locale === 'en' ? 'rotate-y-180' : ''" />
</button>
</template>

View File

@ -0,0 +1,45 @@
<script lang="ts" setup>
import type { PageData, Post } from 'valaxy'
import { useConfig } from 'valaxy'
defineProps<{
frontmatter: Post
data?: PageData
}>()
const config = useConfig()
</script>
<template>
<main>
<div w="full" flex="~">
<slot name="main">
<div class="content" flex="~ col grow" w="full" p="l-4 lt-md:0">
<slot name="main-header" />
<slot name="main-header-after" />
<slot name="main-content">
<div class="markdown-body prose max-w-none pb-8">
<ValaxyMd :frontmatter="frontmatter">
<slot name="main-content-md" />
<slot />
</ValaxyMd>
</div>
<slot name="main-content-after" />
</slot>
</div>
<slot name="main-nav-before" />
<slot name="main-nav" />
<slot name="main-nav-after" />
<slot v-if="config.comment.enable && frontmatter.comment !== false" name="comment" />
<slot name="footer" />
</slot>
</div>
<slot name="aside" />
</main>
</template>

View File

@ -0,0 +1,12 @@
import { computed } from 'vue'
import { useConfig } from 'valaxy'
import type { ThemeConfig } from '../types'
/**
* getThemeConfig
* @returns
*/
export function useThemeConfig<T = ThemeConfig>() {
const config = useConfig<T>()
return computed(() => config!.value.themeConfig)
}

View File

@ -0,0 +1 @@
export * from './config'

View File

@ -0,0 +1,27 @@
import type { ThemeConfig, ThemeUserConfig } from '../types'
export const anonymousImage = 'https://cdn.yunyoujun.cn/img/avatar/none.jpg'
/**
* Default Config
*/
export const defaultThemeConfig: ThemeConfig = {
outlineTitle: 'On this page',
colors: {
primary: '#0078E7',
},
}
export default defaultThemeConfig
/**
* generateSafelist by config
* @param themeConfig
* @returns
*/
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export function generateSafelist(themeConfig: ThemeUserConfig) {
const safelist: string[] = []
return safelist
}

View File

@ -0,0 +1,25 @@
<script lang="ts" setup>
import { useRouter } from 'vue-router'
import { useI18n } from 'vue-i18n'
const router = useRouter()
const { t } = useI18n()
</script>
<template>
<Layout>
<template #content>
<div text="center">
<div text-4xl>
<div i-ri-alarm-warning-line inline-block />
</div>
<router-view />
<div>
<button btn text-sm m="3 t8" @click="router.back()">
{{ t('button.back') }}
</button>
</div>
</div>
</template>
</Layout>
</template>

View File

@ -0,0 +1,5 @@
<template>
<Layout>
<router-view />
</Layout>
</template>

View File

@ -0,0 +1,11 @@
<template>
<Layout>
<div class="divide-y divide-gray-200">
<PressHeader />
<slot>
<router-view />
</slot>
</div>
</Layout>
</template>

View File

@ -0,0 +1,45 @@
<template>
<div class="antialiased">
<div class="max-w-3xl mx-auto px-4 sm:px-6 xl:max-w-5xl xl:px-0">
<PressNav />
</div>
<main class="max-w-3xl mx-auto px-4 sm:px-6 xl:max-w-5xl xl:px-0">
<slot>
<router-view v-slot="{ Component }">
<component :is="Component">
<template #main-header>
<slot name="main-header" />
</template>
<template #main-header-after>
<slot name="main-header-after" />
</template>
<template #main>
<slot name="main" />
</template>
<template #main-content>
<slot name="main-content" />
</template>
<template #main-content-after>
<slot name="main-content-after" />
</template>
<template #main-nav-before>
<slot name="main-nav-before" />
</template>
<template #main-nav-after>
<slot name="main-nav-after" />
</template>
<template #aside-custom>
<slot name="aside-custom" />
</template>
<template #footer>
<slot name="footer" />
</template>
</component>
</router-view>
</slot>
</main>
</div>
</template>

View File

@ -0,0 +1,5 @@
<template>
<Layout>
<PressArticle />
</Layout>
</template>

View File

@ -0,0 +1,43 @@
import { defineThemePlugin } from 'valaxy'
import type { ResolvedValaxyOptions } from 'valaxy'
import type { Plugin } from 'vite'
export * from '../config'
export * from '../types'
export interface UserOptions {
colors: {
primary: string
}
}
function ThemeYunVitePlugin(options: ResolvedValaxyOptions): Plugin {
const themeConfig = options.config.themeConfig
return {
name: 'valaxy-theme-yun',
enforce: 'pre',
config() {
return {
css: {
preprocessorOptions: {
scss: {
additionalData: `$c-primary: ${themeConfig.colors?.primary || '#0078E7'} !default;`,
},
},
},
optimizeDeps: {
exclude: ['@docsearch/js'],
},
}
},
}
}
export default defineThemePlugin((options) => {
return {
vite: {
plugins: [ThemeYunVitePlugin(options)],
},
}
})

View File

@ -0,0 +1,47 @@
{
"name": "valaxy-theme-press",
"version": "0.0.1",
"description": "Docs Theme for Valaxy",
"author": {
"email": "me@yunyoujun.cn",
"name": "YunYouJun",
"url": "https://www.yunyoujun.cn"
},
"maintainers": [],
"homepage": "https://press.valaxy.site",
"repository": {
"type": "git",
"url": "https://github.com/YunYouJun/valaxy/tree/main/packages/valaxy-theme-press"
},
"exports": {
".": {
"require": "./dist/index.js",
"import": "./dist/index.mjs"
},
"./*": "./*"
},
"main": "dist/index.js",
"module": "dist/index.mjs",
"types": "dist/index.d.ts",
"scripts": {
"build": "rimraf dist && tsup",
"dev": "tsup --watch"
},
"dependencies": {
"@docsearch/css": "^3.1.1",
"@docsearch/js": "^3.1.1"
},
"devDependencies": {
"valaxy": "workspace:*"
},
"pnpm": {
"peerDependencyRules": {
"ignoreMissing": [
"@algolia/client-search",
"@types/react",
"react",
"react-dom"
]
}
}
}

View File

@ -0,0 +1,8 @@
<template>
<PressPostList />
</template>
<route lang="yaml">
meta:
layout: home
</route>

View File

@ -0,0 +1,27 @@
{
// we need tsconfig.json to compile without
// error: This is likely not portable. A type annotation is necessary.
"compilerOptions": {
"allowJs": true,
"baseUrl": ".",
"module": "ESNext",
"target": "ESNext",
"lib": ["DOM", "ESNext"],
"strict": true,
"esModuleInterop": true,
"jsx": "preserve",
"skipLibCheck": true,
"moduleResolution": "node",
"resolveJsonModule": true,
"noUnusedLocals": true,
"strictNullChecks": true,
"forceConsistentCasingInFileNames": true,
"types": [
"vite/client",
"vue/ref-macros",
"vite-plugin-pages/client",
"vite-plugin-vue-layouts/client"
]
},
"exclude": ["**/dist/**", "node_modules"]
}

View File

@ -0,0 +1,16 @@
import { defineConfig } from 'tsup'
export default defineConfig((options) => {
return {
entry: ['node/index.ts'],
// disable for dev watch before valaxy watch
clean: !options.watch,
dts: true,
format: ['cjs', 'esm'],
minify: !options.watch,
external: [
'valaxy',
'vite',
],
}
})

View File

@ -0,0 +1,25 @@
export namespace DocsTheme {
export type Config = ThemeConfig
export type Sidebar = any
}
/**
* Theme Config
*/
export interface ThemeConfig {
/**
* toc title
* @default 'On this page'
*/
outlineTitle: string
colors: {
/**
* primary color
* @default '#0078E7'
*/
primary: string
}
}
export type ThemeUserConfig = Partial<ThemeConfig>

View File

@ -29,17 +29,15 @@ function ThemeYunVitePlugin(options: ResolvedValaxyOptions): Plugin {
optimizeDeps: {
exclude: ['@docsearch/js'],
},
valaxy: {},
}
},
}
}
const themeYun = defineThemePlugin((options) => {
export default defineThemePlugin((options) => {
return {
vite: {
plugins: [ThemeYunVitePlugin(options)],
},
}
})
export default themeYun

View File

@ -63,6 +63,17 @@ export function useConfig<ThemeConfig = any>() {
return config!
}
/**
* You can use like this: import { useThemeConfig } from 'valaxy-theme-xxx'
* if you want to: import { useThemeConfig } from 'valaxy'
* you need pass themeConfig by yourself
* @returns
*/
export function useThemeConfig<T = Record<string, any>>() {
const config = useConfig<T>()
return computed(() => config!.value.themeConfig)
}
export interface ValaxyData<T = any> {
page: Ref<PageData>
theme: Ref<T>

View File

@ -19,6 +19,7 @@ importers:
tsx: ^3.7.1
typescript: ^4.7.4
valaxy: workspace:*
valaxy-theme-press: workspace:*
valaxy-theme-yun: workspace:*
vitest: ^0.18.0
vue-tsc: 0.38.3
@ -39,6 +40,7 @@ importers:
tsx: 3.7.1
typescript: 4.7.4
valaxy: link:packages/valaxy
valaxy-theme-press: link:packages/valaxy-theme-press
valaxy-theme-yun: link:packages/valaxy-theme-yun
vitest: 0.18.0
vue-tsc: 0.38.3_typescript@4.7.4
@ -202,6 +204,17 @@ importers:
diacritics: 1.3.0
https-localhost: 4.7.1
packages/valaxy-theme-press:
specifiers:
'@docsearch/css': ^3.1.1
'@docsearch/js': ^3.1.1
valaxy: workspace:*
dependencies:
'@docsearch/css': 3.1.1
'@docsearch/js': 3.1.1
devDependencies:
valaxy: link:../valaxy
packages/valaxy-theme-yun:
specifiers:
'@docsearch/css': ^3.1.1