Skip to content

Commit

Permalink
Updated docs to add stability filters
Browse files Browse the repository at this point in the history
  • Loading branch information
tristanpoland committed Oct 20, 2024
1 parent 9e8ef37 commit 372d84e
Show file tree
Hide file tree
Showing 7 changed files with 121 additions and 69 deletions.
123 changes: 105 additions & 18 deletions app/components/DocsCards.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,28 +13,89 @@ interface DocFile {
excerpt: string;
content: string;
firstImage?: string;
tags?: string[];
stability?: 'stable' | 'in-dev' | 'experimental';
}

function parseFileContent(content: string): DocFile {
const [, frontMatter, markdownContent] = content.split('---');
const metadata = Object.fromEntries(
frontMatter.trim().split('\n').map(line => line.split(': '))
);
// function parseFileContent(content: string): { parsedDoc: DocFile; rawMetadata: any } {
// const [, frontMatter, markdownContent] = content.split('---');
// const metadata = Object.fromEntries(
// frontMatter.trim().split('\n').map(line => {
// const [key, ...value] = line.split(': ');
// return [key, value.join(': ').trim()];
// })
// );
//
// console.log('Raw parsed metadata:', metadata);
//
// const parsedDoc: DocFile = {
// slug: '', // You'll need to set this elsewhere
// title: metadata.title || '',
// excerpt: metadata.excerpt || '',
// content: markdownContent.trim(),
// firstImage: metadata.image || undefined,
// tags: metadata.tags ? JSON.parse(metadata.tags.replace(/'/g, '"')) : undefined,
// stability: metadata.stability as 'stable' | 'in-dev' | 'experimental' | undefined
// };
//
// console.log('Parsed document:', parsedDoc);
//
// return { parsedDoc, rawMetadata: metadata };
// }

const firstParagraph = markdownContent.trim().split('\n\n')[0];
const stabilityEmoji: { [key: string]: string } = {
stable: '✅ Stable - ',
'in-dev': '🚧 InDev - ',
experimental: '🧪 Experimental - '
};

return {
slug: '', // You'll need to set this elsewhere
title: metadata.title || '',
excerpt: metadata.excerpt || '',
content: markdownContent.trim(),
firstImage: metadata.image || undefined
};
interface TagsProps {
tags: string[];
selectedTags: string[];
setSelectedTags: React.Dispatch<React.SetStateAction<string[]>>;
}

const Tags: React.FC<TagsProps> = ({ tags, selectedTags, setSelectedTags }) => (
<div className="flex flex-wrap gap-2">
{tags.map(tag => (
<button
key={tag}
onClick={() => setSelectedTags(prev =>
prev.includes(tag) ? prev.filter(t => t !== tag) : [...prev, tag]
)}
className={`px-2 py-1 rounded-full text-sm ${
selectedTags.includes(tag) ? 'bg-blue-500 text-white' : 'bg-gray-200 text-black'
}`}
>
{tag}
</button>
))}
</div>
);

interface StabilityFilterProps {
selectedStability: string;
setSelectedStability: React.Dispatch<React.SetStateAction<string>>;
}

const StabilityFilter: React.FC<StabilityFilterProps> = ({ selectedStability, setSelectedStability }) => (
<select
value={selectedStability}
onChange={(e) => setSelectedStability(e.target.value)}
className="p-2 border border-gray-300 text-black rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
>
<option value="all">All Stability</option>
<option value="stable">Stable</option>
<option value="in-dev">In Development</option>
<option value="experimental">Experimental</option>
</select>
);

export function DocsCards({ docs }: { docs: DocFile[] }) {
const [active, setActive] = useState<DocFile | null>(null);
const [searchTerm, setSearchTerm] = useState("");
const [selectedTags, setSelectedTags] = useState<string[]>([]);
const [selectedStability, setSelectedStability] = useState<string>('all');
const ref = useRef<HTMLDivElement>(null);
const id = useId();

Expand All @@ -58,25 +119,49 @@ export function DocsCards({ docs }: { docs: DocFile[] }) {
useOutsideClick(ref, () => setActive(null));

const filteredDocs = docs.filter((doc) =>
doc.title.toLowerCase().includes(searchTerm.toLowerCase()) ||
doc.excerpt.toLowerCase().includes(searchTerm.toLowerCase())
(doc.title.toLowerCase().includes(searchTerm.toLowerCase()) ||
doc.excerpt.toLowerCase().includes(searchTerm.toLowerCase())) &&
(selectedTags.length === 0 || (doc.tags && selectedTags.every(tag => doc.tags.includes(tag)))) &&
(selectedStability === 'all' || (doc.stability && doc.stability === selectedStability))
);

const allTags = Array.from(new Set(docs.flatMap(doc => doc.tags || [])));

const renderExcerpt = (content: string) => {
const firstParagraph = content.split('\n\n')[0];
return marked(firstParagraph);
};

const renderTags = (tags: string[] | undefined) => {
if (!tags || tags.length === 0) return null;
return (
<div className="mt-2 flex flex-wrap gap-2">
{tags.map(tag => (
<span key={tag} className="px-2 py-1 bg-gray-200 text-black rounded-full text-xs">
{tag}
</span>
))}
</div>
);
};

const renderStabilityEmoji = (stability: string | undefined) => {
if (!stability || !stabilityEmoji[stability]) return null;
return <span className="mr-2">{stabilityEmoji[stability]}</span>;
};

return (
<>
<div className="mb-6 overflow-x-hidden">
<div className="mb-6 space-y-4">
<input
type="text"
placeholder="Search documentation..."
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
className="w-full p-2 border border-gray-300 text-black rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
/>
<Tags tags={allTags} selectedTags={selectedTags} setSelectedTags={setSelectedTags} />
<StabilityFilter selectedStability={selectedStability} setSelectedStability={setSelectedStability} />
</div>
<AnimatePresence>
{active && (
Expand Down Expand Up @@ -122,7 +207,7 @@ export function DocsCards({ docs }: { docs: DocFile[] }) {
layoutId={`title-${active.slug}-${id}`}
className="text-2xl font-bold text-neutral-800 dark:text-neutral-100 mb-4"
>
{active.title}
{renderStabilityEmoji(active.stability)}{active.title}
</motion.h2>
<motion.div
layout
Expand All @@ -132,6 +217,7 @@ export function DocsCards({ docs }: { docs: DocFile[] }) {
className="prose dark:prose-invert max-w-none"
dangerouslySetInnerHTML={{ __html: renderExcerpt(active.content) }}
/>
{renderTags(active.tags)}
<div className="mt-4 flex justify-between items-center">
<a href="https://discord.gg/NM4awJWGWu" target="_blank" rel="noopener noreferrer" className="px-4 py-2 bg-blue-500 text-white rounded-full hover:bg-blue-600">
Join Discord
Expand Down Expand Up @@ -162,14 +248,15 @@ export function DocsCards({ docs }: { docs: DocFile[] }) {
layoutId={`title-${doc.slug}-${id}`}
className="font-medium text-lg text-neutral-800 dark:text-neutral-200 text-left"
>
{doc.title}
{renderStabilityEmoji(doc.stability)}{doc.title}
</motion.h3>
<motion.p
layoutId={`excerpt-${doc.slug}-${id}`}
className="text-neutral-600 dark:text-neutral-400 text-left"
>
{doc.excerpt}
</motion.p>
{renderTags(doc.tags)}
</div>
<Link
href={`/docs/${doc.slug}`}
Expand Down
42 changes: 0 additions & 42 deletions app/docs/DocsList.tsx

This file was deleted.

2 changes: 1 addition & 1 deletion app/docs/[slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ async function getDocContent(slug: string) {
export default async function DocPage({ params }: { params: { slug: string } }) {
const { content } = await getDocContent(params.slug);
return (
<div className="container mx-auto px-4 py-8 pt-32 max-w-[60%] content-center">
<div className="container mx-auto px-4 py-8 pt-32 max-w-[800px] content-center">
<div className="w-full">
<div
className={styles.markdownContent}
Expand Down
13 changes: 7 additions & 6 deletions app/docs/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,41 +11,42 @@ interface DocFile {
content: string;
firstImage?: string;
htmlContent: string;
tags?: string[];
stability?: 'stable' | 'in-dev' | 'experimental';
}

async function parseFileContent(fileContents: string, slug: string): Promise<DocFile | null> {
const { data, content } = matter(fileContents);

if (!data.title) {
console.warn(`Document ${slug} does not have a valid title and will be skipped.`);
return null;
}

const excerpt = data.excerpt || content.slice(0, 150) + '...';
const htmlContent = await marked(content);

return {
slug,
title: data.title,
excerpt,
content,
firstImage: data.image || undefined,
htmlContent
htmlContent,
tags: data.tags || [],
stability: data.stability as 'stable' | 'in-dev' | 'experimental' | undefined
};
}

async function getDocs(): Promise<DocFile[]> {
const docsDirectory = path.join(process.cwd(), 'docs');
const filenames = fs.readdirSync(docsDirectory);

const docsPromises = filenames.map(async (filename) => {
const filePath = path.join(docsDirectory, filename);
const fileContents = fs.readFileSync(filePath, 'utf8');
const slug = filename.replace('.md', '');

return await parseFileContent(fileContents, slug);
});

const docs = await Promise.all(docsPromises);
return docs.filter((doc): doc is DocFile => doc !== null);
}
Expand Down
2 changes: 2 additions & 0 deletions docs/about-horizon.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
---
title: About Horizon
image:
tags: []
stability: stable
excerpt: A brief introduction to Horizon
---

Expand Down
4 changes: 3 additions & 1 deletion docs/api-experimental.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
---
title: 🧪 Experimental Plugin API
title: Plugin API
image:
tags: []
stability: experimental
excerpt: The Plugin API is an experimental feature of Horizon and is not recommended for use in production environments yet.
---

Expand Down
4 changes: 3 additions & 1 deletion docs/development.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
---
title: Development - Getting started
title: Getting started with Development
image:
excerpt: A starting point to learn about developing for Horizon
tags: []
stability: stable
---

# Developer Documentation - Overview
Expand Down

0 comments on commit 372d84e

Please sign in to comment.