Skip to content

Commit

Permalink
feat(theme): add custom components
Browse files Browse the repository at this point in the history
  • Loading branch information
Romakita committed Mar 11, 2024
1 parent 4168e2b commit 794f7e5
Show file tree
Hide file tree
Showing 29 changed files with 849 additions and 42 deletions.
1 change: 0 additions & 1 deletion .eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ module.exports = {
"no-empty": "off",
"prefer-const": "off",
"no-fallthrough": "off",
quotes: "double"
},
overrides: [
{
Expand Down
34 changes: 19 additions & 15 deletions docs/.vitepress/config.mts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {defineConfig} from "vitepress";
import {apiAnchor} from "./theme/markdown/api-anchor/api-anchor.js";

// https://vitepress.dev/reference/site-config
export default defineConfig({
Expand Down Expand Up @@ -27,6 +28,8 @@ export default defineConfig({
],

themeConfig: {
apiUrl: "https://tsed.io/api.json",
apiRedirectUrl: "https://api-docs.tsed.io",
search: {
provider: "algolia",
options: {
Expand All @@ -47,7 +50,7 @@ export default defineConfig({
{text: "What is Ts.ED?", link: "/introduction/what-is-tsed"},
{text: "Capabilities", link: "/introduction/capabilities"},
{text: "Installation", link: "/introduction/getting-started"},
{text: "Create your first controller", link: "/introduction/create-your-first-controller"},
{text: "Create your first controller", link: "/introduction/create-your-first-controller"}
]
},
{
Expand Down Expand Up @@ -259,13 +262,12 @@ export default defineConfig({
"/introduction/": [
{
text: "Introduction",
items:
[
{text: "What is Ts.ED?", link: "/introduction/what-is-tsed"},
{text: "Capabilities", link: "/introduction/capabilities"},
{text: "Installation", link: "/introduction/getting-started"},
{text: "Create your first controller", link: "/introduction/create-your-first-controller"}
]
items: [
{text: "What is Ts.ED?", link: "/introduction/what-is-tsed"},
{text: "Capabilities", link: "/introduction/capabilities"},
{text: "Installation", link: "/introduction/getting-started"},
{text: "Create your first controller", link: "/introduction/create-your-first-controller"}
]
},
{
text: "Migration",
Expand All @@ -278,13 +280,12 @@ export default defineConfig({
"/docs/": [
{
text: "Configuration",
items:
[
{text: "Options", link: "/docs/configuration/"},
{text: "Load config from file", link: "/docs/configuration/load-configuration-from-file"},
{text: "Express.js", link: "/docs/configuration/express"},
{text: "Koa.js", link: "/docs/configuration/koa"}
]
items: [
{text: "Options", link: "/docs/configuration/"},
{text: "Load config from file", link: "/docs/configuration/load-configuration-from-file"},
{text: "Express.js", link: "/docs/configuration/express"},
{text: "Koa.js", link: "/docs/configuration/koa"}
]
},
{
text: "Controllers",
Expand All @@ -306,6 +307,9 @@ export default defineConfig({
markdown: {
image: {
lazyLoading: true
},
config: (md) => {
md.use(apiAnchor);
}
}
});
73 changes: 73 additions & 0 deletions docs/.vitepress/theme/atoms/api-icon/ApiIcon.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
[data-name="ApiIcon"] {
@apply hidden font-source rounded-xs text-white text-xxs text-center mr-2;
width: 1rem;
height: 1rem;
line-height: 1.1rem;
box-shadow: 0 1px 2px rgba(10, 16, 20, 0.24);

&[data-type="class"] {
@apply bg-blue-900 inline-block;

&:before {
content: "C";
}
}

&[data-type="interface"] {
@apply bg-teal-500 inline-block;

&:before {
content: "I";
}
}

&[data-type="decorator"] {
@apply bg-blue-600 inline-block;
line-height: 1rem;

&:before {
content: "@";
}
}

&[data-type="type"] {
@apply bg-emerald-300 inline-block;

&:before {
content: "T";
}
}

&[data-type="service"],
&[data-type="provider"] {
@apply bg-pink-600 inline-block;

&:before {
content: "S";
}
}

&[data-type="function"] {
@apply bg-emerald-600 inline-block;

&:before {
content: "F";
}
}

&[data-type="const"] {
@apply bg-gray-800 inline-block;

&:before {
content: "K";
}
}

&[data-type="enum"] {
@apply bg-amber-600 inline-block;

&:before {
content: "E";
}
}
}
22 changes: 22 additions & 0 deletions docs/.vitepress/theme/atoms/api-icon/ApiIcon.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import ApiIcon from "./ApiIcon.vue";
import {render, screen} from "@testing-library/vue";

describe("<ApiIcon />", () => {
it("should render the component", () => {
render(ApiIcon);

expect(screen.getByTestId("ApiIcon")).toBeInTheDocument();
expect(screen.getByTestId("ApiIcon")).toHaveAttribute("data-type", "class");
});

it("should render the component", () => {
render(ApiIcon, {
props: {
type: "enum"
}
});

expect(screen.getByTestId("ApiIcon")).toBeInTheDocument();
expect(screen.getByTestId("ApiIcon")).toHaveAttribute("data-type", "enum");
});
});
33 changes: 33 additions & 0 deletions docs/.vitepress/theme/atoms/api-icon/ApiIcon.stories.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import type {Meta, StoryObj} from "@storybook/vue3";
import ApiIcon from "./ApiIcon.vue";

// More on how to set up stories at: https://storybook.js.org/docs/writing-stories
const meta = {
title: "ApiIcon",
component: ApiIcon,
// This component will have an automatically generated docsPage entry: https://storybook.js.org/docs/writing-docs/autodocs
tags: ["autodocs"],
parameters: {
layout: "centered"
},
argTypes: {
type: {
control: "select",
options: ["interface", "decorator", "class", "type", "enum", "const", "function", "service"]
}
},
args: {
type: "class"
} // default value,
} satisfies Meta<typeof ApiIcon>;

export default meta;
type Story = StoryObj<typeof meta>;
/*
*👇 Render functions are a framework specific feature to allow you control on how the component renders.
* See https://storybook.js.org/docs/api/csf
* to learn how to use render functions.
*/
export const Default: Story = {
args: {}
};
15 changes: 15 additions & 0 deletions docs/.vitepress/theme/atoms/api-icon/ApiIcon.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<script setup lang="ts">
import type {ApiSymbolType} from "../../composables/api/interfaces/Api.js";
import "./ApiIcon.css";
interface Props {
type: ApiSymbolType;
}
const props = withDefaults(defineProps<Props>(), {
type: "class"
});
</script>
<template>
<span data-name="ApiIcon" :data-type="props.type" data-testid="ApiIcon" />
</template>
13 changes: 13 additions & 0 deletions docs/.vitepress/theme/composables/api/__mocks__/useApiConfig.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
console.log("====> useApiConfig.ts <====");

export function useApiConfig() {
const ref = {
apiUrl: "https://tsed.io/api.json",
apiRedirectUrl: "https://api-docs.tsed.io",
value: undefined
};

ref.value = ref;

return ref;
}
26 changes: 26 additions & 0 deletions docs/.vitepress/theme/composables/api/interfaces/Api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
export interface ApiConfig {
apiUrl: string;
apiRedirectUrl: string;
}

export type ApiSymbolType = "interface" | "decorator" | "class" | "type" | "enum" | "const" | "function" | "service";
export type ApiSymbolStatus = "stable" | "deprecated" | "experimental" | "private" | "public";
export interface ApiSymbol {
path?: string;
symbolName: string;
symbolType: ApiSymbolType;
status: ApiSymbolStatus[];
module: string;
symbolLabel: string;
symbolCode: string;
}

export interface ApiResponse {
modules: Record<
string,
{
name?: string;
symbols: ApiSymbol[];
}
>;
}
48 changes: 48 additions & 0 deletions docs/.vitepress/theme/composables/api/mapSymbols.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import {mapSymbols} from "./mapSymbols.js";
import type {ApiResponse} from "./interfaces/Api.js";

describe("Map Symbols", () => {
it("should map symbols", () => {
const data = {
modules: {
"@tsed/core": {
symbols: [
{
path: "/api/core/types/decorators/Configurable",
symbolName: "Configurable",
module: "@tsed/core",
symbolType: "decorator",
symbolLabel: "Decorator",
symbolCode: "@",
status: ["stable"]
}
]
}
}
} satisfies ApiResponse;

const result = mapSymbols(data);

expect(result).toMatchInlineSnapshot(`
[
{
"labels": [
"stable",
],
"module": "@tsed/core",
"name": "Configurable",
"path": "/api/core/types/decorators/Configurable",
"status": [
"stable",
],
"symbolCode": "@",
"symbolLabel": "Decorator",
"symbolName": "Configurable",
"symbolType": "decorator",
"tags": "stable",
"type": "decorator",
},
]
`);
});
});
19 changes: 19 additions & 0 deletions docs/.vitepress/theme/composables/api/mapSymbols.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import type {ApiResponse} from "./interfaces/Api";

export function mapSymbols(items: ApiResponse) {
return Object.values(items.modules).reduce((symbols: any[], current) => {
return [
...symbols,
...current.symbols.map((symbol) => {
return {
...symbol,
// additional properties for the Api search tools
name: symbol.symbolName,
type: symbol.symbolType,
tags: symbol.status.join(","),
labels: symbol.status
};
})
];
}, []);
}
14 changes: 14 additions & 0 deletions docs/.vitepress/theme/composables/api/useApiConfig.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import {useApiConfig} from "./useApiConfig.js";

describe("useApiConfig", () => {
it("should return the correct api config", () => {
const ref: any = {
apiRedirectUrl: "https://api-docs.tsed.io",
apiUrl: "https://tsed.io/api.json",
value: undefined
};
ref.value = ref;

expect(useApiConfig()).toEqual(ref);
});
});
9 changes: 9 additions & 0 deletions docs/.vitepress/theme/composables/api/useApiConfig.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import {useData} from "vitepress/client";
import type {DefaultTheme} from "vitepress";
import type {ApiConfig} from "./interfaces/Api";

export function useApiConfig() {
const {theme} = useData<DefaultTheme.Config & ApiConfig>();

return theme;
}
34 changes: 34 additions & 0 deletions docs/.vitepress/theme/composables/api/useApiContent.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import {beforeEach} from "vitest";
import {useFavicon, useFetch} from "@vueuse/core";

Check warning on line 2 in docs/.vitepress/theme/composables/api/useApiContent.spec.ts

View workflow job for this annotation

GitHub Actions / lint

'useFavicon' is defined but never used
import {useApiContent} from "./useApiContent.js";

vi.mock("@vueuse/core");

describe("useApiContent", () => {
beforeEach(() => {
vi.mocked(useFetch).mockReturnValue({
get: vi.fn().mockReturnThis(),
json: vi.fn().mockReturnValue({
data: {
value: {
apiRedirectUrl: "https://api-docs.tsed.io",
apiUrl: "https://tsed.io/api.json"
}
}
})
} as any);
});
it("should fetch the Api.json content", () => {
const result = useApiContent();

expect(result).toEqual({
data: {
value: {
apiRedirectUrl: "https://api-docs.tsed.io",
apiUrl: "https://tsed.io/api.json"
}
}
});
expect(useFetch).toHaveBeenCalledWith("https://tsed.io/api.json");
});
});
Loading

0 comments on commit 794f7e5

Please sign in to comment.