docs: move docs (#369)

Co-authored-by: wawa0584 <60140118+WestonSeyler@users.noreply.github.com>
Co-authored-by: 三咲智子 Kevin Deng <sxzz@sxzz.moe>
This commit is contained in:
yuyin 2024-03-10 01:36:05 +08:00 committed by GitHub
parent 99fb6d9e1c
commit 83d6795cee
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
44 changed files with 3737 additions and 97 deletions

8
.gitignore vendored
View File

@ -7,3 +7,11 @@ dist
node_modules
temp
.eslintcache
# docs
docs/showcase/*.md
!docs/showcase/index.md
docs/.vitepress/cache
docs/.vitepress/components.d.ts
docs/.env
docs/.vitepress/data/repository.json

2
.npmrc Normal file
View File

@ -0,0 +1,2 @@
ignore-workspace-root-check=true
shell-emulator=true

1
docs/.env.example Normal file
View File

@ -0,0 +1 @@
GITHUB_TOKEN=

View File

@ -0,0 +1,40 @@
<script setup lang="ts">
defineProps<{
owner: string
name: string
stars: number
forks: number
}>()
</script>
<template>
<div flex gap-3 items-center justify-end>
<div class="flex items-center text-gray-500 dark:text-gray-300 cursor-default">
<i class="i-heroicons-star-solid" />
<span ml-1>
{{ stars.toLocaleString() }}
</span>
</div>
<div class="flex items-center text-gray-500 dark:text-gray-300 cursor-default">
<i class="i-lucide-git-fork" />
<span ml-1>
{{ forks.toLocaleString() }}
</span>
</div>
<a target="_blank" :href="`https://github.com/${owner}/${name}`">
<div class="flex text-gray-400" hover="text-gray-900" dark:hover="text-gray-200">
<i class="i-radix-icons-github-logo" />
<i class="i-heroicons-arrow-up-right-20-solid h-3 w-3" />
</div>
</a>
<a target="_blank" :href="`https://www.npmjs.com/package/${name}`">
<div class="flex text-gray-400" hover="text-#C12127">
<i class="i-simple-icons-npm " />
<i class="i-heroicons-arrow-up-right-20-solid h-3 w-3" />
</div>
</a>
</div>
</template>

View File

@ -0,0 +1,56 @@
<script setup lang="ts">
import { data as repositoryData } from '../data/repository.data'
</script>
<template>
<div flex="~ wrap" gap-3 items-center>
<a
v-for="(item, index) in repositoryData" :key="index"
w-20rem h-42 px-4 py-3 cursor-pointer
border="1 solid $vp-c-divider" rounded-md
important-transition-all duration-400
hover="shadow-md bg-$vp-c-bg-soft"
:href="`/showcase/${item.name}`"
flex="~ col"
justify-between
>
<div flex items-center gap-2>
<img :src="item.owner?.avatarUrl" rounded-full w-4 h-4 alt="">
<span dark="text-gray-400" text-gray-500 text-16px>{{ item.owner.login }}/</span>
</div>
<div font-semibold dark="text-gray-200" text-gray-900 text-16px>
{{ item.name }}
</div>
<div text-gray-500 dark="text-gray-400" flex-auto mt-2 text-14px>
<span line-clamp-2>
{{ item.description }}
</span>
</div>
<div flex gap-5>
<div flex items-center gap-1>
<div
w-3 h-3 rounded-full :style="{
'background-color': item.primaryLanguage.color,
}"
/>
<div text="14px gray-500" dark="text-gray-400">{{ item.primaryLanguage.name }}</div>
</div>
<div flex items-center gap-1 text="14px gray-500" dark="text-gray-400">
<i class="i-radix-icons-star" />
<div>{{ (item.stargazers.totalCount).toLocaleString() }}</div>
</div>
<div flex items-center gap-1 text="14px gray-500" dark="text-gray-400">
<i class="i-lucide-git-fork" />
<div>{{ (item.forkCount).toLocaleString() }}</div>
</div>
</div>
</a>
</div>
</template>
<style scoped>
a {
cursor: pointer;
text-decoration: none!important;
}
</style>

88
docs/.vitepress/config.ts Normal file
View File

@ -0,0 +1,88 @@
import MarkdownItGitHubAlerts from 'markdown-it-github-alerts'
import { defineConfig } from 'vitepress'
import { transformerTwoslash } from 'vitepress-plugin-twoslash'
import { repositoryMeta } from './data/meta'
import { description, ogImage, title } from './constance'
import vite from './vite.config'
// https://vitepress.dev/reference/site-config
export default defineConfig({
title,
description,
lastUpdated: true,
themeConfig: {
// https://vitepress.dev/reference/default-theme-config
nav: [
{ text: 'Guide', link: '/guide/', activeMatch: '/guide/' },
{ text: 'Showcase', link: '/showcase/', activeMatch: '/showcase/' },
],
search: {
provider: 'local',
},
logo: {
light: '/logo_light.svg',
dark: '/logo_dark.svg',
},
sidebar: {
'/': [
{
text: 'Guide',
items: [
{ text: 'Getting Started', link: '/guide/' },
// { text: 'Why Unplugin', link: '/guide/why' },
{ text: 'Plugin Conventions', link: '/guide/plugin-conventions' },
],
},
{
text: 'Showcase',
link: '/showcase/',
items: [
{
text: 'Overview',
link: '/showcase/',
},
...repositoryMeta.map(repo => (
{
text: repo.name,
link: `/showcase/${repo.name}`,
}
)),
],
},
],
},
socialLinks: [
{ icon: 'github', link: 'https://github.com/unplugin' },
],
footer: {
message: 'Released under the MIT License.',
copyright: 'Copyright (c) 2021-PRESENT UnJS Team',
},
},
head: [
['meta', { name: 'theme-color', content: '#ffffff' }],
['link', { rel: 'icon', href: '/logo.svg', type: 'image/svg+xml' }],
['meta', { name: 'author', content: 'Nuxt Contrib' }],
['meta', { property: 'og:title', content: title }],
['meta', { property: 'og:image', content: ogImage }],
['meta', { property: 'og:description', content: description }],
['meta', { name: 'twitter:card', content: 'summary_large_image' }],
['meta', { name: 'twitter:image', content: ogImage }],
['meta', { name: 'viewport', content: 'width=device-width, initial-scale=1.0, viewport-fit=cover' }],
],
markdown: {
config: (md: any) => {
md.use(MarkdownItGitHubAlerts)
},
codeTransformers: [
transformerTwoslash(),
],
},
ignoreDeadLinks: true,
vite: vite as any,
})

View File

@ -0,0 +1,4 @@
export const title = 'Unplugin'
export const description = 'Unified plugin system. Support Vite, Rollup, webpack, esbuild, and every frameworks on top of them.'
export const url = 'https://unplugin.vercel.app/'
export const ogImage = `${url}/og.png`

View File

@ -0,0 +1,135 @@
import 'dotenv/config'
import { writeFileSync } from 'node:fs'
import { dirname, join } from 'node:path'
import { fileURLToPath } from 'node:url'
import { env } from 'node:process'
import { $fetch } from 'ofetch'
import { consola } from 'consola'
import type { Repository } from './repository.data'
import { repositoryMeta } from './meta'
const GITHUB_TOKEN = env.GITHUB_TOKEN
const gql = `#graphql
query repositoryQuery($owner: String!, $name: String!, $readme: String!) {
repository(owner: $owner, name: $name) {
name
stargazers {
totalCount
}
owner {
avatarUrl
login
}
description
primaryLanguage {
name
color
}
forkCount
object(expression: $readme) {
... on Blob {
text
}
}
}
}`
async function fetchRepo(meta: {
owner: string
name: string
readme?: string
}) {
const { owner, name, readme } = meta
const _readme = readme || 'main:README.md'
try {
const results = await $fetch('https://api.github.com/graphql', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${GITHUB_TOKEN}`,
},
body: JSON.stringify({
query: gql,
variables: {
owner,
name,
readme: _readme,
},
}),
})
const repositoryInfo = results.data.repository as Repository
const markdownFrontmatter = `---
title: ${repositoryInfo.name}
owner: ${repositoryInfo.owner.login}
name: ${repositoryInfo.name}
stars: ${repositoryInfo.stargazers.totalCount}
forks: ${repositoryInfo.forkCount}
outline: deep
---
<RepoInfo :owner="$frontmatter.owner" :name="$frontmatter.name" :stars="$frontmatter.stars" :forks="$frontmatter.forks" />
---
`
writeFileSync(
join(dirname(fileURLToPath(import.meta.url)), `../../showcase/${name}.md`),
markdownFrontmatter + repositoryInfo.object.text,
)
consola.success(`[${name}.md]: generate success`)
return repositoryInfo
}
catch (error) {
consola.error(`[${name}.md]: generate failed: ${error}`)
}
}
function main() {
if (!GITHUB_TOKEN) {
consola.error('GITHUB_TOKEN is missing, please refer to https://github.com/unplugin/docs#development')
return false
}
const fetchs = repositoryMeta.map((repository) => {
return fetchRepo({
name: repository.name,
owner: repository.owner,
readme: repository.defaultBranch ? `${repository.defaultBranch}:README.md` : 'main:README.md',
})
})
Promise.allSettled(fetchs).then((res) => {
const repoMeta = res?.map((item) => {
if (item.status === 'fulfilled') {
return {
name: item.value?.name,
stargazers: item.value?.stargazers,
owner: item.value?.owner,
description: item.value?.description,
url: item.value?.url,
isTemplate: item.value?.isTemplate,
primaryLanguage: item.value?.primaryLanguage,
forkCount: item.value?.forkCount,
}
}
return null
})?.filter(item => item && item.name)
writeFileSync(
join(dirname(fileURLToPath(import.meta.url)), './repository.json'),
JSON.stringify(repoMeta, null, 2),
)
consola.success('[repository.json] generate success!')
consola.success('All files generate done!')
}).catch((error) => {
consola.error(error)
})
}
main()

View File

@ -0,0 +1,52 @@
export const repositoryMeta = [
{
owner: 'unplugin',
name: 'unplugin-vue-components',
},
{
owner: 'unplugin',
name: 'unplugin-icons',
},
{
owner: 'unplugin',
name: 'unplugin-auto-import',
},
{
owner: 'unplugin',
name: 'unplugin-vue2-script-setup',
},
{
owner: 'unplugin',
name: 'unplugin-vue-markdown',
},
{
owner: 'unplugin',
name: 'unplugin-swc',
},
{
owner: 'unplugin',
name: 'unplugin-turbo-console',
},
{
owner: 'unplugin',
name: 'unplugin-imagemin',
},
{
owner: 'unplugin',
name: 'unplugin-vue-cssvars',
defaultBranch: 'master',
},
{
owner: 'unplugin',
name: 'unplugin-vue',
},
{
owner: 'unplugin',
name: 'unplugin-macros',
},
{
owner: 'unplugin',
name: 'unplugin-vue-ce',
defaultBranch: 'master',
},
]

View File

@ -0,0 +1,36 @@
import { readFileSync } from 'node:fs'
import { dirname, join } from 'node:path'
import { fileURLToPath } from 'node:url'
export interface Repository {
name: string
stargazers: {
totalCount: number
}
owner: {
avatarUrl: string
login: string
}
description: string
url: string
isTemplate: boolean
primaryLanguage: {
name: string
color: string
}
forkCount: number
object: {
text: string
}
}
declare const data: Repository[]
export { data }
export default {
watch: ['./repository.json'],
load() {
const fileContent = readFileSync(join(dirname(fileURLToPath(import.meta.url)), './repository.json'), 'utf-8')
return JSON.parse(fileContent)
},
}

View File

@ -0,0 +1,92 @@
import { basename } from 'node:path'
import type { PluginOption } from 'vite'
import { repositoryMeta } from '../data/meta'
const repos = repositoryMeta.map(({ name }) => `${name}`)
export function MarkdownTransform(): PluginOption {
const MARKDOWN_LINK_RE = /(?<link>\[.*?]\((?<url>.*?)\)|<img.*?src="(?<url2>.*?)".*?>)/g
const GH_RAW_URL = 'https://raw.githubusercontent.com'
const GH_URL = 'https://github.com/unplugin'
const images = ['png', 'jpg', 'jpeg', 'gif', 'svg'].map(ext => `.${ext}`)
return {
name: 'unplugin-md-transform',
enforce: 'pre',
async transform(code, id) {
// only transform markdown on meta files
if (!repos.includes(basename(id, '.md')))
return null
// https://github.com/unplugin/unplugin-vue-components/blob/main/README.md?plain=1#L66
// Manual add line break
code = code.replaceAll('<br>', '<br> \n')
// https://github.com/unplugin/unplugin-icons/blob/main/README.md?plain=1#L425
code = code.replaceAll(' < ', ' &lt; ').replaceAll(' > ', ' &gt; ')
// replace markdown img link
// code reference: https://github.com/unjs/ungh/blob/main/utils/markdown.ts
const { name, owner, defaultBranch } = repositoryMeta.find(({ name }) => name === basename(id, '.md'))!
const _defaultBranch = defaultBranch || 'main'
code = code.replaceAll(MARKDOWN_LINK_RE, (match, _, url: string | undefined, url2: string) => {
const path = url || url2
// If path is already a URL, return the match
if (path.startsWith('http') || path.startsWith('https'))
return match
// handle images and links differently
return match.includes('<img') || images.some(ext => match.includes(ext))
? match.replace(path, `${GH_RAW_URL}/${owner}/${name}/${_defaultBranch}/${path.replace(/^\.\//, '')}`)
: match.replace(path, `${GH_URL}/${name}/tree/${_defaultBranch}/${path.replace(/^\.\//, '')}`)
})
let useCode = code
let idx = 0
while (true) {
const detailIdx = useCode.indexOf('<details>', idx)
if (detailIdx === -1)
break
const summaryIdx = useCode.indexOf('<summary>', idx + 10)
if (summaryIdx === -1)
break
const endSummaryIdx = useCode.indexOf('</summary>', summaryIdx + 10)
if (endSummaryIdx === -1)
break
const title = useCode.slice(summaryIdx + 9, endSummaryIdx)
.trim()
.replaceAll('<br>', '')
.replaceAll('<br/>', '')
.replaceAll('<br />', '')
const endDetailIdx = useCode.indexOf('</details>', endSummaryIdx + 11)
if (endDetailIdx === -1)
break
const detailBody = useCode.slice(endSummaryIdx + 10, endDetailIdx)
.trim()
.replaceAll('<br>', '')
.replaceAll('<br/>', '')
.replaceAll('<br />', '')
let rest = useCode.slice(endDetailIdx + 11).trim()
// additional <br> in some readme packages between details
if (rest.startsWith('<br>'))
rest = rest.slice(4)
if (rest.startsWith('<br/>'))
rest = rest.slice(5)
if (rest.startsWith('<br />'))
rest = rest.slice(6)
useCode = `${useCode.slice(0, detailIdx)}\n::: details ${title}\n\n${detailBody}\n:::\n`
idx = useCode.length
useCode += rest
}
return useCode
},
}
}

View File

@ -0,0 +1,46 @@
<script setup lang="ts">
import { useData } from 'vitepress'
import DefaultTheme from 'vitepress/theme'
import { nextTick, provide } from 'vue'
const { isDark } = useData()
function enableTransitions() {
return 'startViewTransition' in document
&& window.matchMedia('(prefers-reduced-motion: no-preference)').matches
}
provide('toggle-appearance', async ({ clientX: x, clientY: y }: MouseEvent) => {
if (!enableTransitions()) {
isDark.value = !isDark.value
return
}
const clipPath = [
`circle(0px at ${x}px ${y}px)`,
`circle(${Math.hypot(
Math.max(x, innerWidth - x),
Math.max(y, innerHeight - y),
)}px at ${x}px ${y}px)`,
]
// @ts-expect-error any
await document.startViewTransition(async () => {
isDark.value = !isDark.value
await nextTick()
}).ready
document.documentElement.animate(
{ clipPath: isDark.value ? clipPath.reverse() : clipPath },
{
duration: 300,
easing: 'ease-in',
pseudoElement: `::view-transition-${isDark.value ? 'old' : 'new'}(root)`,
},
)
})
</script>
<template>
<DefaultTheme.Layout />
</template>

View File

@ -0,0 +1,20 @@
// https://vitepress.dev/guide/custom-theme
import { h } from 'vue'
import type { EnhanceAppContext } from 'vitepress'
import DefaultTheme from 'vitepress/theme'
import TwoSlashFloatingVue from 'vitepress-plugin-twoslash/client'
import CustomLayout from './CustomLayout.vue'
import 'vitepress-plugin-twoslash/style.css'
import 'uno.css'
import './style.css'
export default {
extends: DefaultTheme,
Layout: () => {
return h(CustomLayout)
},
enhanceApp({ app }: EnhanceAppContext) {
app.use(TwoSlashFloatingVue as any)
},
}

View File

@ -0,0 +1,130 @@
@import 'markdown-it-github-alerts/styles/github-colors-light.css';
@import 'markdown-it-github-alerts/styles/github-colors-dark-media.css';
@import 'markdown-it-github-alerts/styles/github-base.css';
:root {
--vp-c-brand-1: #000;
--vp-c-brand-2: #383838;
--vp-c-brand-3: #09090b;
--vp-button-brand-bg: #171717;
--vp-c-text-2: #444;
}
.dark {
--vp-c-brand-1: #fff;
--vp-c-brand-2: #71717a;
--vp-c-brand-3: #52525b;
--vp-c-brand-soft: #09090b50;
--vp-c-text-2: #999;
--vp-button-brand-bg: #ededed;
--vp-button-brand-text: #0a0a0a;
--vp-button-brand-hover-bg:#dad9d9;
--vp-button-brand-hover-text: #383838;
--vp-button-brand-active-text: #09090b;
--vp-home-hero-name-background: -webkit-linear-gradient(
0deg,
#fff 30%,
#d1d5db 0%
)!important;
}
:root {
--vp-c-default-1: var(--vp-c-gray-1);
--vp-c-default-2: var(--vp-c-gray-2);
--vp-c-default-3: var(--vp-c-gray-3);
--vp-c-default-soft: var(--vp-c-gray-soft);
--vp-c-tip-1: var(--vp-c-brand-1);
--vp-c-tip-2: var(--vp-c-brand-2);
--vp-c-tip-3: var(--vp-c-brand-3);
--vp-c-tip-soft: var(--vp-c-brand-soft);
--vp-c-warning-1: var(--vp-c-yellow-1);
--vp-c-warning-2: var(--vp-c-yellow-2);
--vp-c-warning-3: var(--vp-c-yellow-3);
--vp-c-warning-soft: var(--vp-c-yellow-soft);
--vp-c-danger-1: var(--vp-c-red-1);
--vp-c-danger-2: var(--vp-c-red-2);
--vp-c-danger-3: var(--vp-c-red-3);
--vp-c-danger-soft: var(--vp-c-red-soft);
}
/**
* Component: Button
* -------------------------------------------------------------------------- */
:root {
--vp-button-brand-border: transparent;
--vp-button-brand-hover-border: transparent;
--vp-button-brand-active-border: transparent;
--vp-button-brand-active-bg: var(--vp-c-brand-1);
}
/**
* Component: Home
* -------------------------------------------------------------------------- */
:root {
--vp-home-hero-name-color: transparent;
--vp-home-hero-name-background: -webkit-linear-gradient(
0deg,
#333 30%,
#888 1%
);
}
/**
* Component: Custom Block
* -------------------------------------------------------------------------- */
:root {
--vp-custom-block-tip-border: transparent;
--vp-custom-block-tip-text: var(--vp-c-text-1);
--vp-custom-block-tip-bg: var(--vp-c-brand-soft);
--vp-custom-block-tip-code-bg: var(--vp-c-brand-soft);
}
/**
* Component: Algolia
* -------------------------------------------------------------------------- */
.DocSearch {
--docsearch-primary-color: var(--vp-c-brand-1) !important;
}
a > img {
display: inline;
}
img[src*="features"] {
height: auto;
width: 48px;
}
img[src*="/features/rspack"] {
margin-bottom: 28px!important;
}
details > summary:hover {
cursor: pointer;
user-select: none;
}
::view-transition-old(root),
::view-transition-new(root) {
animation: none;
mix-blend-mode: normal;
}
::view-transition-old(root) {
z-index: 1;
}
::view-transition-new(root) {
z-index: 9999;
}
.dark::view-transition-old(root) {
z-index: 9999;
}
.dark::view-transition-new(root) {
z-index: 1;
}

View File

@ -0,0 +1,14 @@
import { defineConfig, presetAttributify, presetIcons, presetUno, transformerDirectives } from 'unocss'
export default defineConfig({
presets: [
presetUno(),
presetAttributify(),
presetIcons({
scale: 1.2,
}),
],
transformers: [
transformerDirectives(),
],
})

View File

@ -0,0 +1,23 @@
import { fileURLToPath } from 'node:url'
import { defineConfig } from 'vite'
import Components from 'unplugin-vue-components/vite'
import Unocss from 'unocss/vite'
import Icons from 'unplugin-icons/vite'
import { MarkdownTransform } from './plugins/markdownTransform'
export default defineConfig({
plugins: [
MarkdownTransform(),
Components({
include: [/\.vue/, /\.md/],
dirs: '.vitepress/components',
dts: '.vitepress/components.d.ts',
}),
Unocss(fileURLToPath(new URL('./uno.config.ts', import.meta.url))),
Icons(),
],
// https://github.com/antfu/shikiji/issues/86
ssr: {
noExternal: ['shikiji-twoslash', 'vitepress-plugin-twoslash'],
},
})

37
docs/README.md Normal file
View File

@ -0,0 +1,37 @@
<p align="center">
<img src="https://raw.githubusercontent.com/unplugin/docs/main/public/logo.svg">
</p>
<h1 align="center">
Unplugin
</h1>
<p align="center">
Unified plugin system, Support Vite, Rollup, webpack, esbuild, and more
</p>
<p align="center">
<a href="https://unplugin.vercel.app">Documentation</a>
</p>
## Development
This project use [GitHub GraphQL API](https://docs.github.com/en/graphql) to generate the showcase data. So you need to create a [GitHub Personal Access Token](https://github.com/settings/personal-access-tokens/new) first.
```bash
cp .env.example .env
```
```ini
# .env
GITHUB_TOKEN=<YOUR_TOKEN>
```
### Generate files
```bash
pnpm gen-files
```
## Contributing
Please refer to https://github.com/antfu/contribute

49
docs/api-examples.md Normal file
View File

@ -0,0 +1,49 @@
---
outline: deep
---
# Runtime API Examples
This page demonstrates usage of some of the runtime APIs provided by VitePress.
The main `useData()` API can be used to access site, theme, and page data for the current page. It works in both `.md` and `.vue` files:
```md
<script setup>
import { useData } from 'vitepress'
const { theme, page, frontmatter } = useData()
</script>
## Results
### Theme Data
<pre>{{ theme }}</pre>
### Page Data
<pre>{{ page }}</pre>
### Page Frontmatter
<pre>{{ frontmatter }}</pre>
```
<script setup>
import { useData } from 'vitepress'
const { site, theme, page, frontmatter } = useData()
</script>
## Results
### Theme Data
<pre>{{ theme }}</pre>
### Page Data
<pre>{{ page }}</pre>
### Page Frontmatter
<pre>{{ frontmatter }}</pre>
## More
Check out the documentation for the [full list of runtime APIs](https://vitepress.dev/reference/runtime-api#usedata).

349
docs/guide/index.md Normal file
View File

@ -0,0 +1,349 @@
---
outline: deep
lastUpdated: false
---
# Getting Started
## Overview
**Unplugin** is a library that offers an unified plugin system for various build tools. It extends the excellent [Rollup plugin API](https://rollupjs.org/plugin-development/#plugins-overview) to serve as the standard plugin interface, and provides a compatibility layer based on the build tools employed.
**Unplugin** current supports:
- [Vite](https://vitejs.dev/)
- [Rollup](https://rollupjs.org/)
- [webpack](https://webpack.js.org/)
- [esbuild](https://esbuild.github.io/)
- [Rspack](https://www.rspack.dev/) <span style="color: #ca8a04"><strong>(⚠️ experimental)</strong></span>
- [Rolldown](https://rolldown.rs/) <span style="color: #ca8a04"><strong>(⚠️ experimental)</strong></span>
## Trying It Online
You can try **Unplugin** in your browser directly.
[![open](/open_in_codeflow.svg)](https://stackblitz.com/~/github.com/yuyinws/unplugin-starter?file=src/index.ts)
## Creating an Unplugin package
```shell
npx degit unplugin/unplugin-starter unplugin-starter
```
> Check the [unplugin-starter](https://github.com/unplugin/unplugin-starter) repository for more details.
## Plugin Installation
### Pre-requisites
- Node.js 14.0.0 or later
::: warning
We will discontinue support for Node.js v14 & v16 in the next major release.
Please consider upgrading to Node.js v18 or higher.
:::
### Install package
::: code-group
```bash [npm]
npm install unplugin-starter --save-dev
```
```bash [yarn]
yarn add unplugin-starter -D
```
```bash [pnpm]
pnpm add unplugin-starter -D
```
```bash [bun]
bun add unplugin-starter -D
```
:::
### Bundler & Framework Integration
::: code-group
```ts [Vite]
// vite.config.ts
import Starter from 'unplugin-starter/vite'
export default defineConfig({
plugins: [
Starter({ /* options */ }),
],
})
```
```js [Rollup]
// rollup.config.js
import Starter from 'unplugin-starter/rollup'
export default {
plugins: [
Starter({ /* options */ }),
],
}
```
```js [webpack]
// webpack.config.js
module.exports = {
/* ... */
plugins: [
require('unplugin-starter/webpack')({ /* options */ })
]
}
```
```js [Rspack]
// rspack.config.js
module.exports = {
/* ... */
plugins: [
require('unplugin-starter/rspack')({ /* options */ })
]
}
```
```js [esbuild]
// esbuild.config.js
import { build } from 'esbuild'
import Starter from 'unplugin-starter/esbuild'
build({
plugins: [Starter()],
})
```
```js [Vue-CLI]
// vue.config.js
module.exports = {
configureWebpack: {
plugins: [
require('unplugin-starter/webpack')({ /* options */ }),
],
},
}
```
```js [Nuxt]
// nuxt.config.ts
export default defineNuxtConfig({
modules: [
['unplugin-starter/nuxt', { /* options */ }],
],
})
```
```js [Astro]
// astro.config.mjs
import { defineConfig } from 'astro/config'
import Starter from 'unplugin-turbo-console/astro'
// https://astro.build/config
export default defineConfig({
integrations: [
Starter()
]
})
```
## Supported Hooks
| Hook | Rollup | Vite | webpack 4 | webpack 5 | esbuild | Rspack |
| ----------------------------------------------------------------------------------| :-------------: | :--: | :-------: | :-------: | :-----------: | :----: |
| [`enforce`](https://vitejs.dev/guide/api-plugin.html#plugin-ordering) | ❌ <sup>1</sup> | ✅ | ✅ | ✅ | ❌ <sup>1</sup> | ✅ |
| [`buildStart`](https://rollupjs.org/plugin-development/#buildstart) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| [`resolveId`](https://rollupjs.org/plugin-development/#resolveid) | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ |
| `loadInclude`<sup>2</sup> | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| [`load`](https://rollupjs.org/plugin-development/#load) | ✅ | ✅ | ✅ | ✅ | ✅ <sup>3</sup> | ✅ |
| `transformInclude`<sup>2</sup> | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| [`transform`](https://rollupjs.org/plugin-development/#transform) | ✅ | ✅ | ✅ | ✅ | ✅ <sup>3</sup> | ✅ |
| [`watchChange`](https://rollupjs.org/plugin-development/#watchchange) | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ |
| [`buildEnd`](https://rollupjs.org/plugin-development/#buildend) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| [`writeBundle`](https://rollupjs.org/plugin-development/#writebundle)<sup>4</sup> | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
::: details Notice
1. Rollup and esbuild do not support using `enforce` to control the order of plugins. Users need to maintain the order manually.
2. webpack's id filter is outside of loader logic; an additional hook is needed for better perf on webpack. In Rollup and Vite, this hook has been polyfilled to match the behaviors. See for the following usage examples.
3. Although esbuild can handle both JavaScript and CSS and many other file formats, you can only return JavaScript in `load` and `transform` results.
4. Currently, `writeBundle` is only serves as a hook for the timing. It doesn't pass any arguments.
:::
### Usage
```ts{12-14,16-18} twoslash
import type { UnpluginFactory } from 'unplugin'
import { createUnplugin } from 'unplugin'
export interface Options {
// define your plugin options here
}
export const unpluginFactory: UnpluginFactory<Options | undefined> = options => ({
name: 'unplugin-starter',
// webpack's id filter is outside of loader logic,
// an additional hook is needed for better perf on webpack
transformInclude(id) {
return id.endsWith('main.ts')
},
// just like rollup transform
transform(code) {
return code.replace(/<template>/, '<template><div>Injected</div>')
},
// more hooks coming
})
export const unplugin = /* #__PURE__ */ createUnplugin(unpluginFactory)
export default unplugin
export const vitePlugin = unplugin.vite
export const rollupPlugin = unplugin.rollup
export const webpackPlugin = unplugin.webpack
export const rspackPlugin = unplugin.rspack
export const esbuildPlugin = unplugin.esbuild
```
## Supported Context
| Context | Rollup | Vite | webpack 4 | webpack 5 | esbuild | Rspack |
| -------------------------------------------------------------------------- | :----: | :--: | :-------: | :-------: | :-----: | :----: |
| [`this.parse`](https://rollupjs.org/plugin-development/#this-parse) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| [`this.addWatchFile`](https://rollupjs.org/plugin-development/#this-addwatchfile) | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ |
| [`this.emitFile`](https://rollupjs.org/plugin-development/#this-emitfile)<sup>1</sup> | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| [`this.getWatchFiles`](https://rollupjs.org/plugin-development/#this-getwatchfiles) | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ |
| [`this.warn`](https://rollupjs.org/plugin-development/#this-warn) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| [`this.error`](https://rollupjs.org/plugin-development/#this-error) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
::: info Notice
1. Currently, [`this.emitFile`](https://rollupjs.org/plugin-development/#thisemitfile) only supports the `EmittedAsset` variant.
:::
## Nested Plugins
Since `v0.10.0`, **Unplugin** supports constructing multiple nested plugins to behave like a single one.
### Bundler Supported
| Rollup | Vite | webpack 4 | webpack 5 | Rspack | esbuild |
| :--------------------: | :--: | :-------: | :-------: | :----: | :----------: |
| ✅ `>=3.1`<sup>1</sup> | ✅ | ✅ | ✅ | ✅ | ✅ (v1.8.0+) |
::: details Notice
1. Rollup supports nested plugins since [v3.1.0](https://github.com/rollup/rollup/releases/tag/v3.1.0). Plugin author should ask users to have a Rollup version of `>=3.1.0` when using nested plugins. For single plugin format, **Unplugin** works for any version of Rollup.
:::
### Usage
```ts twoslash
import type { UnpluginFactory } from 'unplugin'
import { createUnplugin } from 'unplugin'
export interface Options {
// define your plugin options here
}
export const unpluginFactory: UnpluginFactory<Options | undefined> = options => (
[
{
name: 'plugin-a',
transform(code) {
return code.replace(/<template>/, '<template><div>Injected</div>')
},
},
{
name: 'plugin-b',
resolveId(id) {
return id
},
},
]
)
export const unplugin = /* #__PURE__ */ createUnplugin(unpluginFactory)
export default unplugin
```
## Bundler-Specific Logic
While **Unplugin** provides compatible layers for some hooks, the functionality of it is limited to the common subset of the build's plugins capability. For more advanced bundler-specific usages, **Unplugin** provides an escape hatch for that.
### Hooks
```ts {9,18,24,27,30,33} twoslash
import type { UnpluginFactory } from 'unplugin'
import { createUnplugin } from 'unplugin'
export interface Options {
// define your plugin options here
}
export const unpluginFactory: UnpluginFactory<Options | undefined> = (options, meta) => {
console.log(meta.framework) // vite rollup webpack esbuild rspack
return {
name: 'unplugin-starter',
transform(code) {
return code.replace(/<template>/, '<template><div>Injected</div>')
},
transformInclude(id) {
return id.endsWith('main.ts')
},
vite: {
// Vite plugin
configureServer(server) {
// configure Vite server
},
},
rollup: {
// Rollup plugin
},
webpack(complier) {
// Configure webpack compiler
},
rspack(complier) {
// Configure webpack compiler
},
esbuild: {
// Change the filter of onResolve and onLoad
// onResolveFilter?: RegExp,
// onLoadFilter?: RegExp,
// Tell esbuild how to interpret the contents. By default Unplugin tries to guess the loader
// from file extension (eg: .js -> "js", .jsx -> 'jsx')
// loader?: (Loader | (code: string, id: string) => Loader)
// Or you can completely replace the setup logic
// setup?: EsbuildPlugin.setup,
},
}
}
export const unplugin = /* #__PURE__ */ createUnplugin(unpluginFactory)
export default unplugin
```
### Plugins
The package exports a set of functions in place of `createUnplugin` that allow for the creation of plugins for specific bundlers.
Each of the function takes the same generic factory argument as `createUnplugin`.
```ts
import {
createEsbuildPlugin,
createRollupPlugin,
createRspackPlugin,
createVitePlugin,
createWebpackPlugin
} from 'unplugin'
const vitePlugin = createVitePlugin({ /* options */ })
const rollupPlugin = createRollupPlugin({ /* options */ })
const esbuildPlugin = createEsbuildPlugin({ /* options */ })
const webpackPlugin = createWebpackPlugin({ /* options */ })
const rspackPlugin = createRspackPlugin({ /* options */ })
```

View File

@ -0,0 +1,25 @@
---
aside: false
lastUpdated: false
---
# Plugin Conventions
To have a better community and ecosystem, we encourage plugin authors to follow these conventions when creating unplugins.
- Plugins powered by Unplugin should have a clear name with `unplugin-` prefix.
- Include `unplugin` keyword in `package.json`.
- To provide better DX, packages could export 2 kinds of entry points:
- Default export: the returned value of `createUnplugin` function
```ts
import UnpluginFeature from 'unplugin-feature'
```
- Subpath exports: properties of the returned value of `createUnplugin` function for each bundler users
```ts
import VitePlugin from 'unplugin-feature/vite'
```
- Refer to [unplugin-starter](https://github.com/unplugin/unplugin-starter) for more details about this setup.

View File

@ -0,0 +1,7 @@
---
lastUpdated: false
---
# Why Unplugin
TODO

60
docs/index.md Normal file
View File

@ -0,0 +1,60 @@
---
layout: home
sidebar: false
hero:
name: Unplugin
text: The Unified<br>Plugin System
tagline: Supports Vite, Rollup, webpack, esbuild, and every framework built on top of them.
image:
light: /logo_light.svg
dark: /logo_dark.svg
alt: Unplugin
actions:
- theme: brand
text: Getting Started
link: /guide/
- theme: alt
text: Showcase
link: /showcase/
- theme: alt
text: View on GitHub
link: https://github.com/unjs/unplugin
features:
- title: Vite
details: Next Generation Frontend Tooling.
link: https://vitejs.dev/
icon:
src: /features/vitejs.svg
- title: Rollup
details: Next Generation ES module bundler.
link: https://rollupjs.org/
icon:
src: /features/rollup.svg
- title: webpack
details: A static module bundler for modern JavaScript applications.
link: https://webpack.js.org/
icon:
src: /features/webpack.svg
- title: esbuild
details: An extremely fast bundler for the web.
link: https://esbuild.github.io/
icon:
src: /features/esbuild.svg
- title: Rspack
details: A fast Rust-based web bundler.
link: https://www.rspack.dev/
icon:
src: /features/rspack.png
- title: More
details: More supported bundlers...
link: /guide/#supported-hooks
icon:
src: /features/more.svg
---

85
docs/markdown-examples.md Normal file
View File

@ -0,0 +1,85 @@
# Markdown Extension Examples
This page demonstrates some of the built-in markdown extensions provided by VitePress.
## Syntax Highlighting
VitePress provides Syntax Highlighting powered by [Shiki](https://github.com/shikijs/shiki), with additional features like line-highlighting:
**Input**
````md
```js{4}
export default {
data () {
return {
msg: 'Highlighted!'
}
}
}
```
````
**Output**
```js{4}
export default {
data () {
return {
msg: 'Highlighted!'
}
}
}
```
## Custom Containers
**Input**
```md
::: info
This is an info box.
:::
::: tip
This is a tip.
:::
::: warning
This is a warning.
:::
::: danger
This is a dangerous warning.
:::
::: details
This is a details block.
:::
```
**Output**
::: info
This is an info box.
:::
::: tip
This is a tip.
:::
::: warning
This is a warning.
:::
::: danger
This is a dangerous warning.
:::
::: details
This is a details block.
:::
## More
Check out the documentation for the [full list of markdown extensions](https://vitepress.dev/guide/markdown).

32
docs/package.json Normal file
View File

@ -0,0 +1,32 @@
{
"name": "unplugin-docs",
"type": "module",
"private": true,
"scripts": {
"gen-files": "tsx ./.vitepress/data/gen-files.ts",
"dev": "vitepress dev --open",
"build": "pnpm gen-files && vitepress build",
"lint": "eslint . && case-police '**/*.md'"
},
"devDependencies": {
"@iconify-json/heroicons": "^1.1.19",
"@iconify-json/lucide": "^1.1.160",
"@iconify-json/radix-icons": "^1.1.14",
"@iconify-json/simple-icons": "^1.1.90",
"case-police": "^0.6.1",
"consola": "^3.2.3",
"dotenv": "^16.4.1",
"eslint": "^8.57.0",
"markdown-it": "^14.0.0",
"markdown-it-github-alerts": "^0.3.0",
"ofetch": "^1.3.3",
"tsx": "^4.7.0",
"unocss": "^0.58.4",
"unplugin": "workspace:*",
"unplugin-icons": "^0.18.3",
"unplugin-vue-components": "^0.26.0",
"vitepress": "1.0.0-rc.40",
"vitepress-plugin-twoslash": "^0.10.2",
"vue": "^3.4.15"
}
}

BIN
docs/public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1,29 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 128 128">
<g>
<path
d="M47.7 107.1c-5.5-5-7.2-15.7-4.9-23.4 4 4.9 9.6 6.4 15.4 7.3 8.9 1.3 17.6.8 25.9-3.2l2.8-1.7a18 18 0 0 1-7.2 20l-5.5 3.8c-5.6 3.8-7.2 8.2-5 14.7l.2.7a14 14 0 0 1-6.6-5.6 15.8 15.8 0 0 1-2.6-8.6c0-1.5 0-3-.2-4.5-.5-3.7-2.2-5.3-5.5-5.4-3.3-.1-5.9 2-6.6 5.2l-.2.7Z" />
<path
d="M16 82.4s16.5-8 33-8l12.4-38.3c.5-2 1.8-3.2 3.3-3.2 1.6 0 3 1.3 3.4 3.2l12.4 38.3c19.6 0 33 8 33 8l-28-76c-.8-2.3-2.2-3.7-4-3.7H48c-1.8 0-3.1 1.4-4 3.7l-28 76Z" />
</g>
<path fill="url(#a)"
d="M47.7 107.1c-5.5-5-7.2-15.7-4.9-23.4 4 4.9 9.6 6.4 15.4 7.3 8.9 1.3 17.6.8 25.9-3.2l2.8-1.7a18 18 0 0 1-7.2 20l-5.5 3.8c-5.6 3.8-7.2 8.2-5 14.7l.2.7a14 14 0 0 1-6.6-5.6 15.8 15.8 0 0 1-2.6-8.6c0-1.5 0-3-.2-4.5-.5-3.7-2.2-5.3-5.5-5.4-3.3-.1-5.9 2-6.6 5.2l-.2.7Z" />
<defs>
<linearGradient id="a" x1="64.7" x2="77.4" y1="119.2" y2="77.4" gradientUnits="userSpaceOnUse">
<stop stop-color="#D83333" />
<stop offset="1" stop-color="#F041FF" />
</linearGradient>
</defs>
<style>
g {
fill: #000;
}
@media (prefers-color-scheme: dark) {
g {
fill: #FFF;
}
}
</style>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1,4 @@
<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg">
<circle cx="100" cy="100" r="100" fill="#FFCF00"/>
<path d="M47.5 52.5L95 100l-47.5 47.5m60-95L155 100l-47.5 47.5" fill="none" stroke="#191919" stroke-width="24"/>
</svg>

After

Width:  |  Height:  |  Size: 241 B

View File

@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 15 15">
<path fill="#888888" fill-rule="evenodd"
d="M3.625 7.5a1.125 1.125 0 1 1-2.25 0a1.125 1.125 0 0 1 2.25 0m5 0a1.125 1.125 0 1 1-2.25 0a1.125 1.125 0 0 1 2.25 0M12.5 8.625a1.125 1.125 0 1 0 0-2.25a1.125 1.125 0 0 0 0 2.25"
clip-rule="evenodd" />
</svg>

After

Width:  |  Height:  |  Size: 345 B

View File

@ -0,0 +1,5 @@
<svg viewBox="0 0 256 168" xmlns="http://www.w3.org/2000/svg" width="256" height="168"
preserveAspectRatio="xMidYMid">
<path fill="#00DC82"
d="M143.618 167.029h95.166c3.023 0 5.992-.771 8.61-2.237a16.963 16.963 0 0 0 6.302-6.115 16.324 16.324 0 0 0 2.304-8.352c0-2.932-.799-5.811-2.312-8.35L189.778 34.6a16.966 16.966 0 0 0-6.301-6.113 17.626 17.626 0 0 0-8.608-2.238c-3.023 0-5.991.772-8.609 2.238a16.964 16.964 0 0 0-6.3 6.113l-16.342 27.473-31.95-53.724a16.973 16.973 0 0 0-6.304-6.112A17.638 17.638 0 0 0 96.754 0c-3.022 0-5.992.772-8.61 2.237a16.973 16.973 0 0 0-6.303 6.112L2.31 141.975A16.302 16.302 0 0 0 0 150.325c0 2.932.793 5.813 2.304 8.352a16.964 16.964 0 0 0 6.302 6.115 17.628 17.628 0 0 0 8.61 2.237h59.737c23.669 0 41.123-10.084 53.134-29.758l29.159-48.983 15.618-26.215 46.874 78.742h-62.492l-15.628 26.214Zm-67.64-26.24-41.688-.01L96.782 35.796l31.181 52.492-20.877 35.084c-7.976 12.765-17.037 17.416-31.107 17.416Z" />
</svg>

After

Width:  |  Height:  |  Size: 954 B

View File

@ -0,0 +1,62 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 800">
<path
d="M706.075 263.386c0-47.098-12.335-91.253-34.062-129.52-57.611-59.2939-182.927-73.0309-214.045-.281-31.96 74.573 53.686 157.556 91.113 150.967 47.659-8.41-8.411-117.746-8.411-117.746 72.89 137.371 56.07 95.319-75.694 221.475-131.763 126.156-266.33 392.346-285.954 403.56-.841.561-1.682.982-2.664 1.402h516.821c9.111 0 14.999-9.672 10.934-17.802L568.985 507.989c-2.943-5.747-.841-12.896 4.766-16.12 79.058-45.416 132.324-130.642 132.324-228.483Z"
fill="url(#a)" />
<path
d="M706.075 263.386c0-47.098-12.335-91.253-34.062-129.52-57.611-59.2939-182.927-73.0309-214.045-.281-31.96 74.573 53.686 157.556 91.113 150.967 47.659-8.41-8.411-117.746-8.411-117.746 72.89 137.371 56.07 95.319-75.694 221.475-131.763 126.156-266.33 392.346-285.954 403.56-.841.561-1.682.982-2.664 1.402h516.821c9.111 0 14.999-9.672 10.934-17.802L568.985 507.989c-2.943-5.747-.841-12.896 4.766-16.12 79.058-45.416 132.324-130.642 132.324-228.483Z"
fill="url(#b)" />
<path
d="M179.022 791.843c19.625-11.214 154.192-277.544 285.955-403.7 131.763-126.157 148.584-84.105 75.694-221.475 0 0-278.946 391.085-379.871 584.525"
fill="url(#c)" />
<path
d="M218.271 441.407C406.665 95.0378 431.335 60.1345 529.457 60.1345c51.584 0 103.588 23.2689 137.23 64.6205C620.85 50.8831 539.689 1.4017 446.754 0H126.738c-6.729 0-12.196 5.4668-12.196 12.1951V657.275c19.064-49.201 51.444-119.568 103.729-215.868Z"
fill="url(#d)" />
<path
d="M464.977 388.142C333.213 514.299 198.646 780.629 179.022 791.843c-19.624 11.214-52.565 12.615-70.087-7.009-18.6429-20.886-47.6588-54.668 109.336-343.426C406.664 95.039 431.335 60.1357 529.457 60.1357c51.584 0 103.588 23.2689 137.23 64.6203 1.822 2.944 3.644 6.027 5.467 9.111-57.612-59.2933-182.927-73.0304-214.046-.28-31.96 74.572 53.687 157.555 91.113 150.967 47.659-8.41-8.41-117.746-8.41-117.746 72.75 137.23 55.929 95.178-75.834 221.334Z"
fill="url(#e)" />
<path opacity=".3"
d="M233.69 456.828C422.083 110.458 446.754 75.5549 544.876 75.5549c42.472 0 85.225 15.8396 117.746 44.4351-33.642-38.4077-83.544-59.8543-133.165-59.8543-98.122 0-122.793 34.9033-311.186 381.2723C61.2762 730.166 90.2921 763.948 108.935 784.834c2.664 2.944 5.747 5.467 8.971 7.57-16.4-23.83-23.689-79.199 115.784-335.576Z"
fill="url(#f)" />
<defs>
<linearGradient id="a" x1="318.451" y1="426.059" x2="534.319" y2="476.522"
gradientUnits="userSpaceOnUse">
<stop stop-color="#FF6533" />
<stop offset=".157" stop-color="#FF5633" />
<stop offset=".434" stop-color="#FF4333" />
<stop offset=".714" stop-color="#FF3733" />
<stop offset="1" stop-color="#F33" />
</linearGradient>
<linearGradient id="b" x1="284.688" y1="354.502" x2="671.569" y2="654.474"
gradientUnits="userSpaceOnUse">
<stop stop-color="#BF3338" />
<stop offset="1" stop-color="#F33" />
</linearGradient>
<linearGradient id="c" x1="297.309" y1="413.593" x2="353.379" y2="472.466"
gradientUnits="userSpaceOnUse">
<stop stop-color="#FF6533" />
<stop offset=".157" stop-color="#FF5633" />
<stop offset=".434" stop-color="#FF4333" />
<stop offset=".714" stop-color="#FF3733" />
<stop offset="1" stop-color="#F33" />
</linearGradient>
<linearGradient id="d" x1="399.251" y1="514.938" x2="382.43" y2="273.839"
gradientUnits="userSpaceOnUse">
<stop stop-color="#FF6533" />
<stop offset=".157" stop-color="#FF5633" />
<stop offset=".434" stop-color="#FF4333" />
<stop offset=".714" stop-color="#FF3733" />
<stop offset="1" stop-color="#F33" />
</linearGradient>
<linearGradient id="e" x1="326.38" y1="409.461" x2="406.024" y2="463.62"
gradientUnits="userSpaceOnUse">
<stop stop-color="#FBB040" />
<stop offset="1" stop-color="#FB8840" />
</linearGradient>
<linearGradient id="f" x1="407.972" y1="103.25" x2="326.671" y2="997.559"
gradientUnits="userSpaceOnUse">
<stop stop-color="#fff" />
<stop offset="1" stop-color="#fff" stop-opacity="0" />
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

View File

@ -0,0 +1,15 @@
<svg width="48" height="48" viewBox="0 0 410 404" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M399.641 59.5246L215.643 388.545C211.844 395.338 202.084 395.378 198.228 388.618L10.5817 59.5563C6.38087 52.1896 12.6802 43.2665 21.0281 44.7586L205.223 77.6824C206.398 77.8924 207.601 77.8904 208.776 77.6763L389.119 44.8058C397.439 43.2894 403.768 52.1434 399.641 59.5246Z" fill="url(#paint0_linear)"/>
<path d="M292.965 1.5744L156.801 28.2552C154.563 28.6937 152.906 30.5903 152.771 32.8664L144.395 174.33C144.198 177.662 147.258 180.248 150.51 179.498L188.42 170.749C191.967 169.931 195.172 173.055 194.443 176.622L183.18 231.775C182.422 235.487 185.907 238.661 189.532 237.56L212.947 230.446C216.577 229.344 220.065 232.527 219.297 236.242L201.398 322.875C200.278 328.294 207.486 331.249 210.492 326.603L212.5 323.5L323.454 102.072C325.312 98.3645 322.108 94.137 318.036 94.9228L279.014 102.454C275.347 103.161 272.227 99.746 273.262 96.1583L298.731 7.86689C299.767 4.27314 296.636 0.855181 292.965 1.5744Z" fill="url(#paint1_linear)"/>
<defs>
<linearGradient id="paint0_linear" x1="6.00017" y1="32.9999" x2="235" y2="344" gradientUnits="userSpaceOnUse">
<stop stop-color="#41D1FF"/>
<stop offset="1" stop-color="#BD34FE"/>
</linearGradient>
<linearGradient id="paint1_linear" x1="194.651" y1="8.81818" x2="236.076" y2="292.989" gradientUnits="userSpaceOnUse">
<stop stop-color="#FFEA83"/>
<stop offset="0.0833333" stop-color="#FFDD35"/>
<stop offset="1" stop-color="#FFA800"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1,9 @@
<svg viewBox="0 0 600 600" xmlns="http://www.w3.org/2000/svg">
<path d="m300 .1 265 149.9v299.9l-265 149.9-265-149.9v-299.9z" fill="#fff" />
<path
d="m517.7 439.5-208.9 118.3v-92l130.2-71.7zm14.3-12.9v-247.2l-76.4 44.1v159zm-450.5 12.9 208.9 118.2v-92l-130.2-71.6zm-14.3-12.9v-247.2l76.4 44.1v159zm8.9-263.2 214.3-121.2v89l-137.3 75.5-1.1.6zm446.9 0-214.2-121.2v89l137.2 75.6 1.1.6z"
fill="#8ed6fb" />
<path
d="m290.4 444.8-128.4-70.7v-139.9l128.4 74.1zm18.4 0 128.4-70.6v-140l-128.4 74.1zm-138.2-226.8 129-70.9 128.9 70.9-128.9 74.4z"
fill="#1c78c0" />
</svg>

After

Width:  |  Height:  |  Size: 583 B

51
docs/public/logo.svg Normal file
View File

@ -0,0 +1,51 @@
<svg width="256" height="256" viewBox="0 0 256 256" fill="none" xmlns="http://www.w3.org/2000/svg">
<style>
#circle {
stroke: #333;
}
#line {
stroke: #888;
}
@media (prefers-color-scheme: dark) {
#circle {
stroke: #e3e3e3;
}
#line {
stroke: #d1d5db;
}
}
</style>
<g clip-path="url(#clip0_2_38)">
<mask id="mask0_2_38" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="0"
width="256" height="256">
<path d="M256 0H0V256H256V0Z" fill="white" />
</mask>
<g mask="url(#mask0_2_38)">
<path id="line" d="M72.9779 273.931L73.3264 179.19" stroke-opacity="0.35"
stroke-width="12" stroke-linecap="round" stroke-linejoin="round" />
<path
d="M34.0078 82.4634H73.3264L112.645 82.4633M49.3954 47.931V81.4343M97.2574 47.931V81.4343"
id="line" stroke-opacity="0.35" stroke-width="12" stroke-linecap="round"
stroke-linejoin="round" />
<path
d="M112.645 82.4633C112.645 82.4633 112.645 126.821 112.645 134.661C112.645 142.5 111.806 147.085 109.876 151.945C107.946 156.806 105.067 162.232 101.405 165.966C97.7441 169.7 93.375 172.666 88.5536 174.69C83.7322 176.715 78.5555 177.758 73.3262 177.758C68.0969 177.758 62.9201 176.715 58.0987 174.69C53.2773 172.666 48.9082 169.7 45.247 165.966C41.5857 162.232 38.7059 156.806 36.7761 151.945C34.8462 147.085 33.905 139.889 34.0076 134.661V82.4634"
id="circle" stroke-width="12" stroke-linecap="round" stroke-linejoin="round" />
<path d="M182.667 -18.2371L182.319 76.5033" id="line" stroke-opacity="0.35"
stroke-width="12" stroke-linecap="round" stroke-linejoin="round" />
<path d="M221.637 173.23H182.319H143M206.25 207.763V174.259M158.388 207.763V174.26"
id="line" stroke-opacity="0.35" stroke-width="12" stroke-linecap="round"
stroke-linejoin="round" />
<path
d="M143 173.23C143 173.23 143 128.872 143 121.033C143 113.194 143.839 108.609 145.769 103.748C147.699 98.8883 150.578 93.4618 154.24 89.728C157.901 85.9943 162.27 83.0282 167.091 81.0034C171.913 78.9785 177.09 77.9356 182.319 77.9356C187.548 77.9356 192.725 78.9785 197.546 81.0034C202.368 83.0282 206.737 85.9943 210.398 89.7281C214.059 93.4618 216.939 98.8883 218.869 103.748C220.799 108.609 221.74 115.805 221.637 121.033V173.23"
id="circle" stroke-width="12" stroke-linecap="round" stroke-linejoin="round" />
</g>
</g>
<defs>
<clipPath id="clip0_2_38">
<rect width="256" height="256" fill="white" />
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

41
docs/public/logo_dark.svg Normal file
View File

@ -0,0 +1,41 @@
<svg width="256" height="256" viewBox="0 0 256 256" fill="none" xmlns="http://www.w3.org/2000/svg">
<style>
#circle {
stroke: #e3e3e3;
}
#line {
stroke: #d1d5db;
}
</style>
<g clip-path="url(#clip0_2_38)">
<mask id="mask0_2_38" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="0"
width="256" height="256">
<path d="M256 0H0V256H256V0Z" fill="white" />
</mask>
<g mask="url(#mask0_2_38)">
<path id="line" d="M72.9779 273.931L73.3264 179.19" stroke-opacity="0.35"
stroke-width="12" stroke-linecap="round" stroke-linejoin="round" />
<path
d="M34.0078 82.4634H73.3264L112.645 82.4633M49.3954 47.931V81.4343M97.2574 47.931V81.4343"
id="line" stroke-opacity="0.35" stroke-width="12" stroke-linecap="round"
stroke-linejoin="round" />
<path
d="M112.645 82.4633C112.645 82.4633 112.645 126.821 112.645 134.661C112.645 142.5 111.806 147.085 109.876 151.945C107.946 156.806 105.067 162.232 101.405 165.966C97.7441 169.7 93.375 172.666 88.5536 174.69C83.7322 176.715 78.5555 177.758 73.3262 177.758C68.0969 177.758 62.9201 176.715 58.0987 174.69C53.2773 172.666 48.9082 169.7 45.247 165.966C41.5857 162.232 38.7059 156.806 36.7761 151.945C34.8462 147.085 33.905 139.889 34.0076 134.661V82.4634"
id="circle" stroke-width="12" stroke-linecap="round" stroke-linejoin="round" />
<path d="M182.667 -18.2371L182.319 76.5033" id="line" stroke-opacity="0.35"
stroke-width="12" stroke-linecap="round" stroke-linejoin="round" />
<path d="M221.637 173.23H182.319H143M206.25 207.763V174.259M158.388 207.763V174.26"
id="line" stroke-opacity="0.35" stroke-width="12" stroke-linecap="round"
stroke-linejoin="round" />
<path
d="M143 173.23C143 173.23 143 128.872 143 121.033C143 113.194 143.839 108.609 145.769 103.748C147.699 98.8883 150.578 93.4618 154.24 89.728C157.901 85.9943 162.27 83.0282 167.091 81.0034C171.913 78.9785 177.09 77.9356 182.319 77.9356C187.548 77.9356 192.725 78.9785 197.546 81.0034C202.368 83.0282 206.737 85.9943 210.398 89.7281C214.059 93.4618 216.939 98.8883 218.869 103.748C220.799 108.609 221.74 115.805 221.637 121.033V173.23"
id="circle" stroke-width="12" stroke-linecap="round" stroke-linejoin="round" />
</g>
</g>
<defs>
<clipPath id="clip0_2_38">
<rect width="256" height="256" fill="white" />
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -0,0 +1,41 @@
<svg width="256" height="256" viewBox="0 0 256 256" fill="none" xmlns="http://www.w3.org/2000/svg">
<style>
#circle {
stroke: #333;
}
#line {
stroke: #888;
}
</style>
<g clip-path="url(#clip0_2_38)">
<mask id="mask0_2_38" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="0"
width="256" height="256">
<path d="M256 0H0V256H256V0Z" fill="white" />
</mask>
<g mask="url(#mask0_2_38)">
<path id="line" d="M72.9779 273.931L73.3264 179.19" stroke-opacity="0.35"
stroke-width="12" stroke-linecap="round" stroke-linejoin="round" />
<path
d="M34.0078 82.4634H73.3264L112.645 82.4633M49.3954 47.931V81.4343M97.2574 47.931V81.4343"
id="line" stroke-opacity="0.35" stroke-width="12" stroke-linecap="round"
stroke-linejoin="round" />
<path
d="M112.645 82.4633C112.645 82.4633 112.645 126.821 112.645 134.661C112.645 142.5 111.806 147.085 109.876 151.945C107.946 156.806 105.067 162.232 101.405 165.966C97.7441 169.7 93.375 172.666 88.5536 174.69C83.7322 176.715 78.5555 177.758 73.3262 177.758C68.0969 177.758 62.9201 176.715 58.0987 174.69C53.2773 172.666 48.9082 169.7 45.247 165.966C41.5857 162.232 38.7059 156.806 36.7761 151.945C34.8462 147.085 33.905 139.889 34.0076 134.661V82.4634"
id="circle" stroke-width="12" stroke-linecap="round" stroke-linejoin="round" />
<path d="M182.667 -18.2371L182.319 76.5033" id="line" stroke-opacity="0.35"
stroke-width="12" stroke-linecap="round" stroke-linejoin="round" />
<path d="M221.637 173.23H182.319H143M206.25 207.763V174.259M158.388 207.763V174.26"
id="line" stroke-opacity="0.35" stroke-width="12" stroke-linecap="round"
stroke-linejoin="round" />
<path
d="M143 173.23C143 173.23 143 128.872 143 121.033C143 113.194 143.839 108.609 145.769 103.748C147.699 98.8883 150.578 93.4618 154.24 89.728C157.901 85.9943 162.27 83.0282 167.091 81.0034C171.913 78.9785 177.09 77.9356 182.319 77.9356C187.548 77.9356 192.725 78.9785 197.546 81.0034C202.368 83.0282 206.737 85.9943 210.398 89.7281C214.059 93.4618 216.939 98.8883 218.869 103.748C220.799 108.609 221.74 115.805 221.637 121.033V173.23"
id="circle" stroke-width="12" stroke-linecap="round" stroke-linejoin="round" />
</g>
</g>
<defs>
<clipPath id="clip0_2_38">
<rect width="256" height="256" fill="white" />
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

BIN
docs/public/og.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 9.7 KiB

15
docs/showcase/index.md Normal file
View File

@ -0,0 +1,15 @@
---
aside: false
---
# Overview
Here are a few unplugins maintained by the unplugin team, find more on [npm](https://www.npmjs.com/search?ranking=popularity&q=keywords%3Aunplugin).
<Repositories />
::: info Join us!
We have started a [GitHub organization](https://github.com/unplugin) to host and collaborate on popular unplugins. You can go there to find more plugins maintained by the unplugin team or even join us with your own plugins!
:::

3
netlify.toml Normal file
View File

@ -0,0 +1,3 @@
[build]
command = "pnpm build && pnpm docs:build"
publish = "docs/dist"

View File

@ -33,6 +33,9 @@
"lint": "eslint --cache .",
"lint:fix": "nr lint --fix",
"typecheck": "tsc --noEmit",
"docs:dev": "pnpm -C docs run dev",
"docs:build": "pnpm -C docs run build",
"docs:gen-files": "pnpm -C docs run gen-files",
"prepublishOnly": "nr build",
"release": "bumpp --all -x 'npx conventional-changelog -p angular -i CHANGELOG.md -s' && npm publish",
"test": "nr test:build && vitest run --pool=forks",

2154
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

2
pnpm-workspace.yaml Normal file
View File

@ -0,0 +1,2 @@
packages:
- docs

View File

@ -21,6 +21,7 @@
},
"include": [
"src",
"test"
"test",
"docs/.vitepress"
]
}