aboutsummaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorShinigami <[email protected]>2022-08-22 23:38:15 +0800
committerGitHub <[email protected]>2022-08-22 17:38:15 +0200
commit0866ee9217e5e0b60e1c5f604e3576fb2604a3d5 (patch)
treeb54c310380b6892bacf5552d1dde4b325f00b09c /docs
parentf684a14ddc3729c74f8434db68324269ae9a640f (diff)
downloadfaker-0866ee9217e5e0b60e1c5f604e3576fb2604a3d5.tar.xz
faker-0866ee9217e5e0b60e1c5f604e3576fb2604a3d5.zip
docs: searchable api (#1253)
Diffstat (limited to 'docs')
-rw-r--r--docs/.vitepress/config.ts5
-rw-r--r--docs/api/.gitignore8
-rw-r--r--docs/api/ApiIndex.vue240
-rw-r--r--docs/api/api-types.ts26
-rw-r--r--docs/api/index.md12
5 files changed, 291 insertions, 0 deletions
diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts
index 44a1ec79..87733d59 100644
--- a/docs/.vitepress/config.ts
+++ b/docs/.vitepress/config.ts
@@ -85,6 +85,11 @@ export default defineConfig({
nav: [
{ text: 'Guide', link: '/guide/' },
{
+ text: 'API',
+ activeMatch: `^/api/`,
+ link: '/api/',
+ },
+ {
text: 'Ecosystem',
items: [{ text: 'StackBlitz ', link: 'https://fakerjs.dev/new' }],
},
diff --git a/docs/api/.gitignore b/docs/api/.gitignore
index 3d5066c5..fc720b3c 100644
--- a/docs/api/.gitignore
+++ b/docs/api/.gitignore
@@ -1,3 +1,11 @@
+# Markdown
*.md
+!index.md
!localization.md
+
+# TypeScript
+*.ts
+!api-types.ts
+
+# JSON
*.json
diff --git a/docs/api/ApiIndex.vue b/docs/api/ApiIndex.vue
new file mode 100644
index 00000000..0846d9f2
--- /dev/null
+++ b/docs/api/ApiIndex.vue
@@ -0,0 +1,240 @@
+<!-- This content is mostly copied over from https://github.com/vuejs/docs/blob/main/src/api/ApiIndex.vue -->
+
+<script setup lang="ts">
+import { computed, ref } from 'vue';
+import apiSearchIndex from './api-search-index.json';
+import { APIGroup } from './api-types';
+
+const query = ref('');
+const normalize = (s: string) => s.toLowerCase().replace(/-/g, ' ');
+
+const filtered = computed(() => {
+ const q = normalize(query.value);
+ const matches = (text: string) => normalize(text).includes(q);
+
+ return (apiSearchIndex as APIGroup[])
+ .map((section) => {
+ // section title match
+ if (matches(section.text)) {
+ return section;
+ }
+
+ // filter groups
+ const matchedGroups = section.items
+ .map((item) => {
+ // group title match
+ if (matches(item.text)) {
+ return item;
+ }
+ // filter headers
+ const matchedHeaders = item.headers.filter(
+ ({ text, anchor }) => matches(text) || matches(anchor)
+ );
+ return matchedHeaders.length
+ ? { text: item.text, link: item.link, headers: matchedHeaders }
+ : null;
+ })
+ .filter((i) => i);
+
+ return matchedGroups.length
+ ? { text: section.text, items: matchedGroups }
+ : null;
+ })
+ .filter((i) => i) as APIGroup[];
+});
+
+// same as vitepress' slugify logic
+function slugify(text: string): string {
+ return (
+ text
+ // Replace special characters
+ .replace(/[\s~`!@#$%^&*()\-_+=[\]{}|\\;:"'<>,.?/]+/g, '-')
+ // Remove continuous separators
+ .replace(/\-{2,}/g, '-')
+ // Remove prefixing and trailing separators
+ .replace(/^\-+|\-+$/g, '')
+ // ensure it doesn't start with a number (like #123)
+ .replace(/^(\d)/, '_$1')
+ // // lowercase
+ // .toLowerCase()
+ );
+}
+</script>
+
+<template>
+ <div id="api-index">
+ <div class="header">
+ <h1>API Reference</h1>
+ <div class="api-filter">
+ <label for="api-filter">Filter</label>
+ <input
+ type="search"
+ placeholder="Enter keyword"
+ id="api-filter"
+ v-model="query"
+ />
+ </div>
+ </div>
+
+ <div v-for="section of filtered" :key="section.text" class="api-section">
+ <h2 :id="slugify(section.text)">{{ section.text }}</h2>
+ <div class="api-groups">
+ <div v-for="item of section.items" :key="item.text" class="api-group">
+ <h3>{{ item.text }}</h3>
+ <ul>
+ <li v-for="h of item.headers" :key="h.anchor">
+ <a :href="item.link + '.html#' + slugify(h.anchor)">{{
+ h.anchor
+ }}</a>
+ </li>
+ </ul>
+ </div>
+ </div>
+ </div>
+
+ <div v-if="!filtered.length" class="no-match">
+ No API matching "{{ query }}" found.
+ </div>
+ </div>
+</template>
+
+<style scoped>
+#api-index {
+ max-width: 1024px;
+ margin: 0px auto;
+ padding: 64px 32px;
+}
+
+h1,
+h2,
+h3 {
+ font-weight: 600;
+ line-height: 1;
+}
+
+h1,
+h2 {
+ letter-spacing: -0.02em;
+}
+
+h1 {
+ font-size: 38px;
+}
+
+h2 {
+ font-size: 24px;
+ color: var(--vp-c-text-1);
+ margin: 36px 0;
+ transition: color 0.5s;
+ padding-top: 36px;
+ border-top: 1px solid var(--vp-c-divider-light);
+}
+
+h3 {
+ letter-spacing: -0.01em;
+ color: var(--vp-c-green);
+ font-size: 18px;
+ margin-bottom: 1em;
+ transition: color 0.5s;
+}
+
+.api-section {
+ margin-bottom: 64px;
+}
+
+.api-groups a {
+ font-size: 15px;
+ font-weight: 500;
+ line-height: 2;
+ color: var(--vp-c-text-code);
+ transition: color 0.5s;
+}
+
+.dark .api-groups a {
+ font-weight: 400;
+}
+
+.api-groups a:hover {
+ color: var(--vp-c-green);
+ transition: none;
+}
+
+.api-group {
+ break-inside: avoid;
+ overflow: auto;
+ margin-bottom: 20px;
+ background-color: var(--vp-c-bg-soft);
+ border-radius: 8px;
+ padding: 28px 32px;
+ transition: background-color 0.5s;
+}
+
+.header {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+}
+
+.api-filter {
+ display: flex;
+ align-items: center;
+ justify-content: flex-start;
+ gap: 1rem;
+}
+
+.api-filter input {
+ border: 1px solid var(--vp-c-divider);
+ border-radius: 8px;
+ padding: 6px 12px;
+}
+
+.api-filter:focus {
+ border-color: var(--vp-c-green-light);
+}
+
+.no-match {
+ font-size: 1.2em;
+ color: var(--vp-c-text-3);
+ text-align: center;
+ margin-top: 36px;
+ padding-top: 36px;
+ border-top: 1px solid var(--vp-c-divider-light);
+}
+
+@media (max-width: 768px) {
+ #api-index {
+ padding: 42px 24px;
+ }
+
+ h1 {
+ font-size: 32px;
+ margin-bottom: 24px;
+ }
+
+ h2 {
+ font-size: 22px;
+ margin: 42px 0 32px;
+ padding-top: 32px;
+ }
+
+ .api-groups a {
+ font-size: 14px;
+ }
+
+ .header {
+ display: block;
+ }
+}
+
+@media (min-width: 768px) {
+ .api-groups {
+ columns: 2;
+ }
+}
+
+@media (min-width: 1024px) {
+ .api-groups {
+ columns: 3;
+ }
+}
+</style>
diff --git a/docs/api/api-types.ts b/docs/api/api-types.ts
new file mode 100644
index 00000000..f5dcd659
--- /dev/null
+++ b/docs/api/api-types.ts
@@ -0,0 +1,26 @@
+// These interfaces are copied over from https://github.com/vuejs/docs/blob/main/src/api/api.data.ts
+
+/**
+ * Represents a link to e.g. a Faker-Module method within the API search index page.
+ */
+export interface APIHeader {
+ anchor: string;
+ text: string;
+}
+
+/**
+ * Represents a container for e.g. a Faker-Module within the API search index page.
+ */
+export interface APIItem {
+ text: string;
+ link: string;
+ headers: APIHeader[];
+}
+
+/**
+ * Represents a whole section within the API search index page.
+ */
+export interface APIGroup {
+ text: string;
+ items: APIItem[];
+}
diff --git a/docs/api/index.md b/docs/api/index.md
new file mode 100644
index 00000000..d962f905
--- /dev/null
+++ b/docs/api/index.md
@@ -0,0 +1,12 @@
+---
+layout: page
+title: API Reference
+sidebar: false
+footer: false
+---
+
+<script setup>
+import ApiIndex from './ApiIndex.vue'
+</script>
+
+<ApiIndex />