Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: add docs #2

Merged
merged 14 commits into from
Nov 8, 2023
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ dist
.cache
.output

# Vitepress
**/.vitepress/cache


# Env
.env

Expand Down
3 changes: 3 additions & 0 deletions docs/.vitepress/components/demo-block/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import DemoBlock from "./src/index.vue";

export default DemoBlock;
42 changes: 42 additions & 0 deletions docs/.vitepress/components/demo-block/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import type { ExtractPropTypes } from "vue";

export const demoProps = {
github: {
type: String,
default: "https://github.com/chizukicn/hoci"
},
codeSandBox: {
type: String,
default: "https://codesandbox.io/"
},
highlightedCode: {
type: String,
default: ""
},
code: {
type: String,
default: ""
},
title: {
type: String,
default: ""
},
desc: {
type: String,
default: ""
},
lang: {
type: String,
default: "vue"
},
expand: {
type: Boolean,
default: false
},
src: {
type: String,
default: ""
}
} as const;

export type ODemoProps = ExtractPropTypes<typeof demoProps>;
83 changes: 83 additions & 0 deletions docs/.vitepress/components/demo-block/src/index.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<script lang='ts' setup name="demo-block">
import { computed } from "vue";
import { isClient, useClipboard, useToggle } from "@vueuse/core";
import { usePlayground } from "./playground";
import { demoProps } from "./index";
const props = defineProps(demoProps);
const decodedHighlightedCode = computed(() =>
decodeURIComponent(props.highlightedCode)
);
const { copy, copied } = useClipboard({ source: decodeURIComponent(props.code) });
const [value, toggle] = useToggle();
const editOnPlayground = () => {
if (props.code) {
const { link } = usePlayground(props.code);
if (!isClient) {
return;
};
window.open(link);
}
};
</script>

<template>
<ClientOnly>
<div v-bind="$attrs" class="mt-6">
<div class="p-8 c-#282f38 b-1 border-light-700 b-solid rounded-sm dark:bg-dark-700 dark:border-#4C4D4F flex [&:o-button-base]:!c-context vp-raw bg">
<slot />
</div>
<div class="relative">
<div class="flex justify-end pt-3 gap-2">
<a class="relative outline-none flex justify-center items-center w-7 h-7 p-0 rounded-full border border-light-900 dark:border-dark-900 bg-white dark:bg-#38383A cursor-pointer hover:bg-#E5E6EB dark:hover:bg-dark:300" group @click="editOnPlayground">
<div class="o-demo_action_icon i-carbon:chemistry" />
<div class="o-demo_tooltip" group-hover:opacity-100>
Edit in Playground
</div>
</a>
<a class="relative outline-none flex justify-center items-center w-7 h-7 p-0 rounded-full border border-light-900 dark:border-dark-900 bg-white dark:bg-#38383A cursor-pointer hover:bg-#E5E6EB dark:hover:bg-dark:300" group :href="github" target="_blank">
<div class="o-demo_action_icon i-carbon-logo-github" />
<div class="o-demo_tooltip" group-hover:opacity-100>
Edit on GitHub
</div>
</a>
<a class="relative outline-none flex justify-center items-center w-7 h-7 p-0 rounded-full border border-light-900 dark:border-dark-900 bg-white dark:bg-#38383A cursor-pointer hover:bg-#E5E6EB dark:hover:bg-dark:300" group @click="copy()">
<div class="o-demo_action_icon i-carbon:copy" />
<div class="o-demo_tooltip" group-hover:opacity-100>
{{ copied ? 'Copied' : 'Copy code' }}
</div>
</a>
<a class="relative outline-none flex justify-center items-center w-7 h-7 p-0 rounded-full border border-light-900 dark:border-dark-900 bg-white dark:bg-#38383A cursor-pointer hover:bg-#E5E6EB dark:hover:bg-dark:300" group @click="toggle()">
<div class="o-demo_action_icon i-carbon:fit-to-width" />
<div class="o-demo_tooltip" group-hover:opacity-100>
{{ value ? 'Hidden code' : 'Show code' }}
</div>
</a>
</div>
<div v-show="value" :class="`language-${lang} extra-class`" v-html="decodedHighlightedCode" />
</div>
</div>
</ClientOnly>
</template>

<style scoped lang="scss">
@keyframes fade-in {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
.showcode-enter-active {
animation: fade-in 200ms;
}
.showcode-leave-active {
animation: fade-in reverse 200ms;
}
</style>
21 changes: 21 additions & 0 deletions docs/.vitepress/components/demo-block/src/playground.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
const playgroundUrl = (import.meta as any).env.DEV ? "http://localhost:5173/play/" : "https://onu.zyob.top/play/";

function utoa(data: string) {
return btoa(unescape(encodeURIComponent(data)));
}

const MAIN_FILE_NAME = "App.vue";

export const usePlayground = (source: string) => {
const code = decodeURIComponent(source);
const originCode = {
[MAIN_FILE_NAME]: code
};

const encoded = utoa(JSON.stringify(originCode));
const link = `${playgroundUrl}#${encoded}`;
return {
encoded,
link
};
};
58 changes: 58 additions & 0 deletions docs/.vitepress/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { defineConfig } from "vitepress";
import type { DefaultTheme } from "vitepress/types/default-theme";
import { applyPlugins } from "./plugins/code";

const guideSidebar = (): DefaultTheme.SidebarItem[] => {
return [
{
text: "快速开始",
link: "quickstart"
}
];
};

const componentSidebar = (): DefaultTheme.SidebarItem[] => {
return [
{
text: "Affix (固钉)",
link: "affix"
},
{
text: "Selection (选择器)",
link: "selection"
}
];
};

// https://vitepress.dev/reference/site-config
export default defineConfig({
title: "hoci",
description: "a headless components library for vue3",
markdown: {
config: (md) => {
applyPlugins(md);
}
},
themeConfig: {
// https://vitepress.dev/reference/default-theme-config
nav: [
{ text: "指南", link: "/guide/quickstart" },
{ text: "组件", link: "/component/selection" }
],

sidebar: {
"/guide/": {
base: "/guide/",
items: guideSidebar()
},
"/component/": {
base: "/component/",
items: componentSidebar()
}
},

socialLinks: [
{ icon: "github", link: "https://github.com/chizukicn/hoci" }
]
}
});
2 changes: 2 additions & 0 deletions docs/.vitepress/plugins/code/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export const FenceDemoTag = "vue:demo";
export const DemoTag = "demo";
20 changes: 20 additions & 0 deletions docs/.vitepress/plugins/code/fencePlugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import type { MarkdownRenderer } from "vitepress";
import { FenceDemoTag } from "./constants";
import { genDemoByCode } from "./utils";

export function fencePlugin(md: MarkdownRenderer) {
const defaultRender = md.renderer.rules.fence;

md.renderer.rules.fence = (tokens, idx, options, env, self) => {
const token = tokens[idx];
if (token.info.trim() !== FenceDemoTag) {
return defaultRender!(tokens, idx, options, env, self);
};

const content = token.content;
const path = env.path;

const demoScripts = genDemoByCode(md, env, path, content);
return demoScripts;
};
}
7 changes: 7 additions & 0 deletions docs/.vitepress/plugins/code/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { demoBlockPlugin } from "./plugin-demo-block";
import { fencePlugin } from "./fencePlugin";

export function applyPlugins(md: markdownit) {
md.use(fencePlugin);
md.use(demoBlockPlugin);
}
67 changes: 67 additions & 0 deletions docs/.vitepress/plugins/code/plugin-demo-block.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { dirname, resolve } from "node:path";
import fsExtra from "fs-extra";
import { baseParse } from "@vue/compiler-core";
import type { AttributeNode, ElementNode } from "@vue/compiler-core";
import type { MarkdownRenderer } from "vitepress";
import { DemoTag } from "./constants";
import { getDemoComponent } from "./utils";

function getPropsMap(attrs: AttributeNode[]) {
const map: Record<string, string | undefined> = {};
for (const { name, value } of attrs) {
map[name] = value?.content;
};

return map;
}

export function parseProps(content: string) {
const ast = baseParse(content);
const demoElement = ast.children[0] as ElementNode;

const props = getPropsMap(demoElement.props as AttributeNode[]);

return props;
}

export function demoBlockPlugin(md: MarkdownRenderer) {
const addRenderRule = (type: string) => {
const defaultRender = md.renderer.rules[type];

md.renderer.rules[type] = (tokens, idx, options, env, self) => {
const token = tokens[idx];
const content = token.content.trim();

if (!content.startsWith(`<${DemoTag} `)) {
return defaultRender!(tokens, idx, options, env, self);
};

const { path } = env;

const props = parseProps(content);

if (!props.src) {
return defaultRender!(tokens, idx, options, env, self);
};

const frontmatter = env.frontmatter;

const mdDir = dirname(frontmatter.realPath ?? path);
const srcPath = resolve(mdDir, props.src);
const code = fsExtra.readFileSync(srcPath, "utf-8");

const demoScripts = getDemoComponent(md, env, {
title: props.title,
desc: props.desc,
path: srcPath,
code,
...props
});

return demoScripts;
};
};

addRenderRule("html_block");
addRenderRule("html_inline");
}
7 changes: 7 additions & 0 deletions docs/.vitepress/plugins/code/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export interface DemoInfos {
title?: string
desc?: string
path: string
code: string
lang?: string
}
Loading