Skip to content
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion schemas/function.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -150,4 +150,4 @@ $defs:
description: Type of the return value.
name:
type: string
description: Name of the return value.
description: Name of the return value.
19 changes: 19 additions & 0 deletions web/src/components/NoteBox.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
---
<div class="custom-note-box">
<slot />
</div >

<style>
.custom-note-box {
background-color: var(--sl-color-blue-low);
border-left: 4px solid var(--sl-color-blue);
border-radius: 8px;
padding: 1rem 1.25rem;
margin-bottom: 1rem;
color: var(--sl-color-text);
}
html[data-theme="dark"] .custom-note-box {
background-color: var(--sl-color-gray-5);
}
</style>
57 changes: 41 additions & 16 deletions web/src/pages/[func].astro
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ import fs from "fs";
import path from "path";
import { Code } from '@astrojs/starlight/components';

import NoteBox from '@src/components/NoteBox.astro';
import '@src/styles/function-page.css';

export async function getStaticPaths() {
const functions = await getCollection('functions');
return functions.map(func => ({
Expand All @@ -19,24 +22,30 @@ const { func } = Astro.props;

const funcInfo = getFunctionInfo(func.data);
const funcType = funcInfo.type;
const funcTypePretty = funcInfo.typePretty;

const funcPair = funcInfo.pair;
const funcPath = path.dirname(func.filePath ?? "")
let funcExamples = funcInfo.examples
const funcPath = path.dirname(func.filePath ?? "");

if ( funcExamples.length > 0 ){
funcExamples = funcInfo.examples.map((example: any) => {
const { description, notes: funcNotes, examples: rawExamples } = funcInfo;

let processedExamples: any[] = [];
if (Array.isArray(rawExamples) && rawExamples.length > 0) {
processedExamples = rawExamples.map((example: any) => {
try {
const luaCode = fs.readFileSync(path.resolve(`${funcPath}`, example.path), "utf8");
const exampleFilePath = path.resolve(funcPath, example.path);
const luaCode = fs.readFileSync(exampleFilePath, "utf8");
return { ...example, luaCode };
} catch (error) {
console.error(`Error reading ${example.path}:`, error);
return { ...example, luaCode: "Loading example error." };
console.error(`Error reading example file ${example.path} at ${path.resolve(funcPath, example.path)}:`, error);
return { ...example, luaCode: `Error loading example: ${example.path}` };
}
});
}

let notesContent: string[] = [];
if (Array.isArray(funcNotes) && funcNotes.length > 0) {
notesContent = funcNotes;
}

---

<div class={"show-type-badge-" + funcType}>
Expand All @@ -45,18 +54,34 @@ if ( funcExamples.length > 0 ){
title: func.id,
tableOfContents: false,
}}>
<!-- Pair Function Ref -->
{funcPair && (
<p><strong>Pair:</strong> <a href={ funcPair }>{ funcPair }</a></p>
<p><strong>Pair:</strong> <a href={ `/${funcPair}` }>{ funcPair }</a></p>
)}

<!-- Description -->
<Fragment set:html={marked(funcInfo.description)} />
{description && <Fragment set:html={marked(description)} />}

<!-- Notes -->
<div class="notes-section">
{notesContent.map((note) => (
<NoteBox>
<Fragment set:html={marked(note)} />
</NoteBox>
))}
</div>

{funcExamples.length > 0 && funcExamples.map((example: any) => (
<div>
<p set:html={marked(example.description)}></p>
<Code code={example.luaCode} lang="lua" title={path.basename(example.path)} />
<!-- Examples -->
{processedExamples.length > 0 && (
<div class="examples-section">
<h3>Exemplos</h3>
{processedExamples.map((example: any) => (
<div class="function-example">
<Fragment set:html={marked(example.description)} />
<Code code={example.luaCode} lang="lua" title={path.basename(example.path)} />
</div>
))}
</div>
))}
)}
</StarlightPage>
</div>
26 changes: 26 additions & 0 deletions web/src/styles/function-page.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
.function-syntax,
.function-oop,
.notes-section,
.examples-section {
margin-top: 1.5rem;
margin-bottom: 1.5rem;
}

.function-syntax h3,
.function-oop h3,
.examples-section h3 {
margin-bottom: 0.75rem;
font-size: 1.25em;
border-bottom: 1px solid var(--sl-color-gray-5);
padding-bottom: 0.25rem;
}

.function-example {
margin-bottom: 1.5rem;
}
.function-example > :first-child {
margin-bottom: 0.5rem;
}
.examples-section .function-example:last-child {
margin-bottom: 0;
}
61 changes: 49 additions & 12 deletions web/src/utils/functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,46 @@ import type { FunctionType } from './types';

type FunctionItem = Awaited<ReturnType<typeof getCollection>>[number];

type FunctionParameter = {
name: string;
type: string;
description?: string;
};

type FunctionDetails = {
description?: string;
pair?: boolean;
examples?: { code: string; description?: string }[];
notes?: string[];
important_notes?: string[];
parameters?: FunctionParameter[];
};

type FunctionsByCategory = {
[folder: string]: FunctionItem[];
};
type FunctionsByTypeByCategory = {
shared: FunctionsByCategory;
client: FunctionsByCategory;
server: FunctionsByCategory;
[key in FunctionType]: FunctionsByCategory;
};


export type FunctionData = {
shared?: any;
client?: any;
server?: any;
};

export type TypedFunctionData = {
shared?: FunctionDetails;
client?: FunctionDetails;
server?: FunctionDetails;
};

export const functionTypePrettyName = {
'client': 'Client-side',
'server': 'Server-side',
'shared': 'Shared',
};
} as const;

function getFunctionType(data: FunctionData): FunctionType {
if (data.shared) return 'shared';
Expand All @@ -33,16 +53,33 @@ function getFunctionType(data: FunctionData): FunctionType {
}
function getFunctionTypePretty(data: FunctionData): string {
const funcType = getFunctionType(data);
return functionTypePrettyName[funcType] ?? 'Server-side';
return functionTypePrettyName[funcType];
}

export function getFunctionInfo(data: FunctionData): any {
export type FunctionInfo = {
description: string;
type: FunctionType;
typePretty: string;
pair: boolean;
examples: { code: string; description?: string }[];
notes?: string[];
important_notes?: string[];
parameters?: FunctionParameter[];
};

export function getFunctionInfo(data: TypedFunctionData): FunctionInfo {
const type = getFunctionType(data);
const details = data[type] ?? {};

return {
description: data.shared?.description || data.client?.description || data.server?.description || '',
type: getFunctionType(data),
description: details.description || '',
type: type,
typePretty: getFunctionTypePretty(data),
pair: data.shared?.pair || data.client?.pair || data.server?.pair || false,
examples: data.shared?.examples || data.client?.examples || data.server?.examples || [ ],
pair: details.pair || false,
examples: details.examples || [],
notes: details.notes || [],
important_notes: details.important_notes || [],
parameters: details.parameters || [],
};
}

Expand All @@ -55,15 +92,15 @@ let functionsByTypeByCategory: FunctionsByTypeByCategory = {
};

for (let func of functionsCollection) {
const normalizedPath = path.normalize(func.filePath || '');
const normalizedPath = path.normalize(func.id);
const folder = path.basename(path.dirname(normalizedPath));
if (!functionsByCategory[folder]) {
functionsByCategory[folder] = [];
}
functionsByCategory[folder].push(func);

const funcType = getFunctionType(func.data);
if (!functionsByTypeByCategory[funcType][folder]) {
if (!functionsByTypeByCategory[funcType]?.[folder]) {
functionsByTypeByCategory[funcType][folder] = [];
}
functionsByTypeByCategory[funcType][folder].push(func);
Expand Down