Enhance documentation structure and content across multiple guides
- Added frontmatter to various markdown files for better metadata handling. - Updated site URLs in configuration files for consistency. - Improved content organization and clarity in getting started, server extension, and client addon guides.
This commit is contained in:
parent
9ab4ff9fd9
commit
a4d5c2fd4d
@ -29,7 +29,7 @@ request and response chunks through the extension transport module.
|
||||
### Client Addons
|
||||
|
||||
Client addons live under `arma/client/addons`. They own local player UX,
|
||||
keybinds, browser UI dialogs, and UI-to-SQF event handling. When a client needs`
|
||||
keybinds, browser UI dialogs, and UI-to-SQF event handling. When a client needs
|
||||
durable or authoritative state, it routes work to the matching server addon
|
||||
instead of touching persistence directly.
|
||||
|
||||
|
||||
@ -4,7 +4,7 @@ const repoUrl =
|
||||
const repoBranch = process.env.DOCS_REPO_BRANCH || 'master';
|
||||
const siteUrl =
|
||||
process.env.DOCS_SITE_URL ||
|
||||
'https://innovativedevsolutions.github.io';
|
||||
'https://innovativedevsolutions.github.io/forge';
|
||||
|
||||
export default defineAppConfig({
|
||||
site: {
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
# Getting Started
|
||||
|
||||
Use this section as the main entry point for the Forge framework.
|
||||
---
|
||||
title: Getting Started
|
||||
description: Use this section as the main entry point for the Forge framework.
|
||||
---
|
||||
|
||||
Forge combines:
|
||||
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
# Framework Architecture
|
||||
|
||||
Forge is organized around domain modules. A domain usually has SQF addon
|
||||
entry points, Rust models, repository traits, service logic, extension command
|
||||
handlers, and optional browser UI.
|
||||
---
|
||||
title: "Framework Architecture"
|
||||
description: "Forge is organized around domain modules. A domain usually has SQF addon entry points, Rust models, repository traits, service logic, extension command handlers, and optional browser UI."
|
||||
---
|
||||
|
||||
## Runtime Flow
|
||||
|
||||
@ -29,7 +28,7 @@ request and response chunks through the extension transport module.
|
||||
### Client Addons
|
||||
|
||||
Client addons live under `arma/client/addons`. They own local player UX,
|
||||
keybinds, browser UI dialogs, and UI-to-SQF event handling. When a client needs`
|
||||
keybinds, browser UI dialogs, and UI-to-SQF event handling. When a client needs
|
||||
durable or authoritative state, it routes work to the matching server addon
|
||||
instead of touching persistence directly.
|
||||
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
# Module Reference
|
||||
|
||||
This reference lists the main Forge modules and where each layer lives.
|
||||
---
|
||||
title: "Module Reference"
|
||||
description: "This reference lists the main Forge modules and where each layer lives."
|
||||
---
|
||||
|
||||
## Directory Map
|
||||
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
# Development Guide
|
||||
|
||||
This guide covers the usual path for adding or changing a Forge module.
|
||||
---
|
||||
title: "Development Guide"
|
||||
description: "This guide covers the usual path for adding or changing a Forge module."
|
||||
---
|
||||
|
||||
## Local Checks
|
||||
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
# SurrealDB Setup
|
||||
|
||||
Forge uses SurrealDB for durable storage. The Rust server extension connects to
|
||||
SurrealDB on startup and applies Forge schema modules automatically, so setup
|
||||
comes down to running a reachable database and matching the Forge config.
|
||||
---
|
||||
title: "SurrealDB Setup"
|
||||
description: "Forge uses SurrealDB for durable storage. The Rust server extension connects to SurrealDB on startup and applies Forge schema modules automatically, so setup comes down to running a reachable database and matching the Forge config."
|
||||
---
|
||||
|
||||
## Choose the Right Path
|
||||
|
||||
@ -94,9 +93,9 @@ or live server and you are not changing Forge source code.
|
||||
|
||||
Official SurrealDB resources:
|
||||
|
||||
- [Surrealist installation](https://surrealdb.com/docs/explore/surrealist/installation)
|
||||
- [Surrealist installation](https://surrealdb.com/docs/surrealist/installation)
|
||||
- [Surrealist web app](https://app.surrealdb.com)
|
||||
- [Surrealist local database serving](https://surrealdb.com/docs/explore/surrealist/concepts/local-database-serving)
|
||||
- [Surrealist local database serving](https://surrealdb.com/docs/surrealist/concepts/local-database-serving)
|
||||
|
||||
Recommended approach:
|
||||
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
# Forge Server Extension
|
||||
|
||||
Forge Server is an arma-rs extension for Arma 3 server-side persistence and
|
||||
domain services. It exposes game-facing commands and stores durable state in
|
||||
SurrealDB.
|
||||
---
|
||||
title: "Forge Server Extension"
|
||||
description: "Forge Server is an arma-rs extension for Arma 3 server-side persistence and domain services. It exposes game-facing commands and stores durable state in SurrealDB."
|
||||
---
|
||||
|
||||
## Architecture
|
||||
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
# Forge Server API Reference
|
||||
|
||||
The Forge server extension exposes domain-oriented commands through
|
||||
`callExtension`. Persistent data is stored through the configured SurrealDB
|
||||
connection and schema modules.
|
||||
---
|
||||
title: "Forge Server API Reference"
|
||||
description: "The Forge server extension exposes domain-oriented commands through `callExtension`. Persistent data is stored through the configured SurrealDB connection and schema modules."
|
||||
---
|
||||
|
||||
## Core Commands
|
||||
|
||||
@ -39,6 +38,7 @@ needed by `forge_server_addons_extension_fnc_extCall`.
|
||||
- [Actor](/server-modules/actor)
|
||||
- [Bank](/server-modules/bank)
|
||||
- [CAD](/server-modules/cad)
|
||||
- [Economy](/server-modules/economy)
|
||||
- [Garage](/server-modules/garage)
|
||||
- [Locker](/server-modules/locker)
|
||||
- [Organization](/server-modules/organization)
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
# Forge Server Usage Examples
|
||||
|
||||
These examples use the domain command surface exposed by the extension.
|
||||
Persistence is handled by the server through SurrealDB.
|
||||
---
|
||||
title: "Forge Server Usage Examples"
|
||||
description: "These examples use the domain command surface exposed by the extension. Persistence is handled by the server through SurrealDB."
|
||||
---
|
||||
|
||||
## Status Check
|
||||
|
||||
|
||||
@ -1,9 +1,7 @@
|
||||
# Forge Server Common
|
||||
|
||||
## Overview
|
||||
The common addon provides shared SQF utilities used by server-side Forge
|
||||
addons. It contains lightweight helpers only; gameplay domain state belongs in
|
||||
the specific domain addons or the Rust extension.
|
||||
---
|
||||
title: "Forge Server Common"
|
||||
description: "The common addon provides shared SQF utilities used by server-side Forge addons. It contains lightweight helpers only; gameplay domain state belongs in the specific domain addons or the Rust extension."
|
||||
---
|
||||
|
||||
## Dependencies
|
||||
- `forge_server_main`
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
# Server Module Guides
|
||||
|
||||
These pages document the authoritative server-side workflows in Forge.
|
||||
---
|
||||
title: Server Module Guides
|
||||
description: These pages document the authoritative server-side workflows in Forge.
|
||||
---
|
||||
|
||||
Most modules follow the same shape:
|
||||
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
# Actor Usage Guide
|
||||
|
||||
The actor module stores persistent player character data: identity, loadout,
|
||||
position, direction, stance, contact fields, state, holster status, rank, and
|
||||
organization.
|
||||
---
|
||||
title: "Actor Usage Guide"
|
||||
description: "The actor module stores persistent player character data: identity, loadout, position, direction, stance, contact fields, state, holster status, rank, and organization."
|
||||
---
|
||||
|
||||
## Storage Model
|
||||
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
# Store Usage Guide
|
||||
|
||||
The store module processes checkout requests. It charges a payment source and
|
||||
grants purchased items to the player locker, virtual arsenal locker, and
|
||||
virtual garage unlocks.
|
||||
---
|
||||
title: "Store Usage Guide"
|
||||
description: "The store module processes checkout requests. It charges a payment source and grants purchased items to the player locker, virtual arsenal locker, and virtual garage unlocks."
|
||||
---
|
||||
|
||||
## Server SQF Module
|
||||
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
# Task Usage Guide
|
||||
|
||||
The task module stores transient mission task metadata for active server or
|
||||
mission lifecycle workflows. SQF still owns Arma-only runtime state such as
|
||||
objects and participants.
|
||||
---
|
||||
title: "Task Usage Guide"
|
||||
description: "The task module stores transient mission task metadata for active server or mission lifecycle workflows. SQF still owns Arma-only runtime state such as objects and participants."
|
||||
---
|
||||
|
||||
The server addon at `arma/server/addons/task` also owns task execution:
|
||||
creating BIS tasks, registering task entities, tracking participants, binding
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
# Bank Usage Guide
|
||||
|
||||
The bank module stores player account balances, earnings, PINs, and transaction
|
||||
strings. The hot-state API also owns the active banking workflows used by the
|
||||
UI: deposit, withdraw, transfer, checkout charge, and PIN validation.
|
||||
---
|
||||
title: "Bank Usage Guide"
|
||||
description: "The bank module stores player account balances, earnings, PINs, and transaction strings. The hot-state API also owns the active banking workflows used by the UI: deposit, withdraw, transfer, checkout charge, and PIN validation."
|
||||
---
|
||||
|
||||
## Storage Model
|
||||
|
||||
|
||||
@ -1,9 +1,7 @@
|
||||
# CAD Usage Guide
|
||||
|
||||
The CAD module stores transient operational state for dispatch activity,
|
||||
assignments, dispatch orders, support requests, group profiles, grouped views,
|
||||
and hydrated UI payloads. CAD state is in-memory and follows the active server
|
||||
or mission lifecycle.
|
||||
---
|
||||
title: "CAD Usage Guide"
|
||||
description: "The CAD module stores transient operational state for dispatch activity, assignments, dispatch orders, support requests, group profiles, grouped views, and hydrated UI payloads. CAD state is in-memory and follows the active server or mission lifecycle."
|
||||
---
|
||||
|
||||
## Data Model
|
||||
|
||||
|
||||
@ -1,9 +1,7 @@
|
||||
# Economy Usage Guide
|
||||
|
||||
The economy server addon owns Arma-world service behavior for fuel, medical,
|
||||
and repair interactions. It does not own money state. Money mutations go
|
||||
through extension-backed bank and organization hot state before the world
|
||||
effect is applied.
|
||||
---
|
||||
title: "Economy Usage Guide"
|
||||
description: "The economy server addon owns Arma-world service behavior for fuel, medical, and repair interactions. It does not own money state. Money mutations go through extension-backed bank and organization hot state before the world effect is applied."
|
||||
---
|
||||
|
||||
## Dependencies
|
||||
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
# Garage Usage Guide
|
||||
|
||||
The garage module stores physical player vehicles. Each record keeps the
|
||||
vehicle classname, generated plate UUID, fuel, overall damage, and detailed hit
|
||||
point damage.
|
||||
---
|
||||
title: "Garage Usage Guide"
|
||||
description: "The garage module stores physical player vehicles. Each record keeps the vehicle classname, generated plate UUID, fuel, overall damage, and detailed hit point damage."
|
||||
---
|
||||
|
||||
## Storage Model
|
||||
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
# Locker Usage Guide
|
||||
|
||||
The locker module stores physical player inventory items by classname. It is
|
||||
separate from the virtual arsenal unlock module documented in
|
||||
[Owned Storage Usage Guide](/server-modules/owned-storage).
|
||||
---
|
||||
title: "Locker Usage Guide"
|
||||
description: "The locker module stores physical player inventory items by classname. It is separate from the virtual arsenal unlock module documented in [Owned Storage Usage Guide](/server-modules/owned-storage)."
|
||||
---
|
||||
|
||||
## Storage Model
|
||||
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
# Organization Usage Guide
|
||||
|
||||
The organization module stores organization records, members, assets, fleet
|
||||
entries, and credit lines. Durable commands manage persisted records directly.
|
||||
Hot-state commands support the active organization UI workflows.
|
||||
---
|
||||
title: "Organization Usage Guide"
|
||||
description: "The organization module stores organization records, members, assets, fleet entries, and credit lines. Durable commands manage persisted records directly. Hot-state commands support the active organization UI workflows."
|
||||
---
|
||||
|
||||
## Storage Model
|
||||
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
# Owned Storage Usage Guide
|
||||
|
||||
Owned storage covers the `owned:locker` and `owned:garage` extension command
|
||||
groups. These modules store unlock lists rather than physical item or vehicle
|
||||
instances.
|
||||
---
|
||||
title: "Owned Storage Usage Guide"
|
||||
description: "Owned storage covers the `owned:locker` and `owned:garage` extension command groups. These modules store unlock lists rather than physical item or vehicle instances."
|
||||
---
|
||||
|
||||
Use these modules for virtual arsenal and virtual garage unlocks. Use
|
||||
[Locker Usage Guide](/server-modules/locker) and
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
# Phone Usage Guide
|
||||
|
||||
The phone module stores contacts, messages, and emails for each UID. It is a
|
||||
server-extension state module backed by SurrealDB.
|
||||
---
|
||||
title: "Phone Usage Guide"
|
||||
description: "The phone module stores contacts, messages, and emails for each UID. It is a server-extension state module backed by SurrealDB."
|
||||
---
|
||||
|
||||
## Storage Model
|
||||
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
# Client Usage Guide
|
||||
|
||||
Forge Client contains the Arma client-side addons that open player interfaces,
|
||||
handle browser events, cache client-visible state, and forward authoritative
|
||||
requests to the server addons.
|
||||
---
|
||||
title: "Client Usage Guide"
|
||||
description: "Forge Client contains the Arma client-side addons that open player interfaces, handle browser events, cache client-visible state, and forward authoritative requests to the server addons."
|
||||
---
|
||||
|
||||
Use this guide as the entry point for client-side integration. Domain data,
|
||||
validation, persistence, rewards, ownership, and checkout behavior remain
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
# Client Main Usage Guide
|
||||
|
||||
The client `main` addon provides the shared mod identity, version metadata,
|
||||
CBA settings, and macro foundation used by the Forge client addons.
|
||||
---
|
||||
title: "Client Main Usage Guide"
|
||||
description: "The client `main` addon provides the shared mod identity, version metadata, CBA settings, and macro foundation used by the Forge client addons."
|
||||
---
|
||||
|
||||
## Purpose
|
||||
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
# Client Phone Usage Guide
|
||||
|
||||
The client phone addon provides the in-game phone UI for contacts, SMS
|
||||
messages, email, and local utility apps such as notes, calendar events, world
|
||||
clocks, and alarms.
|
||||
---
|
||||
title: "Client Phone Usage Guide"
|
||||
description: "The client phone addon provides the in-game phone UI for contacts, SMS messages, email, and local utility apps such as notes, calendar events, world clocks, and alarms."
|
||||
---
|
||||
|
||||
## Open Phone UI
|
||||
|
||||
@ -26,11 +25,12 @@ Local utility app state is stored in `profileNamespace`:
|
||||
- alarms
|
||||
- theme/preferences
|
||||
|
||||
## Phone Class
|
||||
## Phone Repository
|
||||
|
||||
`forge_client_phone_fnc_initClass` creates `GVAR(PhoneClass)`.
|
||||
`forge_client_phone_fnc_initRepository` creates `GVAR(PhoneRepository)`.
|
||||
|
||||
The phone class currently owns local notes, events, and settings helpers.
|
||||
The phone repository owns local notes, events, clocks, alarms, and settings
|
||||
helpers.
|
||||
Contacts, messages, and emails continue to use server-backed request/response
|
||||
events.
|
||||
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
# Client Store Usage Guide
|
||||
|
||||
The client store addon provides the storefront browser UI for catalog browsing,
|
||||
category hydration, payment source display, cart handling, and checkout
|
||||
requests.
|
||||
---
|
||||
title: "Client Store Usage Guide"
|
||||
description: "The client store addon provides the storefront browser UI for catalog browsing, category hydration, payment source display, cart handling, and checkout requests."
|
||||
---
|
||||
|
||||
## Open Store UI
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
# Client Common Usage Guide
|
||||
|
||||
The client `common` addon contains shared browser UI bridge declarations and
|
||||
common client-side browser integration patterns.
|
||||
---
|
||||
title: "Client Common Usage Guide"
|
||||
description: "The client `common` addon contains shared browser UI bridge declarations and common client-side browser integration patterns."
|
||||
---
|
||||
|
||||
## Purpose
|
||||
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
# Client Actor Usage Guide
|
||||
|
||||
The client actor addon owns the player interaction menu and client-side actor
|
||||
repository. It is the main launcher for nearby player actions and other Forge
|
||||
client UIs.
|
||||
---
|
||||
title: "Client Actor Usage Guide"
|
||||
description: "The client actor addon owns the player interaction menu and client-side actor repository. It is the main launcher for nearby player actions and other Forge client UIs."
|
||||
---
|
||||
|
||||
## Open the Actor Menu
|
||||
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
# Client Bank Usage Guide
|
||||
|
||||
The client bank addon opens the bank and ATM browser UI, forwards banking
|
||||
requests to the server bank addon, and pushes account updates back into the
|
||||
browser.
|
||||
---
|
||||
title: "Client Bank Usage Guide"
|
||||
description: "The client bank addon opens the bank and ATM browser UI, forwards banking requests to the server bank addon, and pushes account updates back into the browser."
|
||||
---
|
||||
|
||||
## Open Bank UI
|
||||
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
# Client CAD Usage Guide
|
||||
|
||||
The client CAD addon provides the map and dispatch UI for groups, active
|
||||
tasks, task assignment, dispatch orders, support requests, and task
|
||||
acknowledge/decline workflows.
|
||||
---
|
||||
title: "Client CAD Usage Guide"
|
||||
description: "The client CAD addon provides the map and dispatch UI for groups, active tasks, task assignment, dispatch orders, support requests, and task acknowledge/decline workflows."
|
||||
---
|
||||
|
||||
## Open CAD UI
|
||||
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
# Client Garage Usage Guide
|
||||
|
||||
The client garage addon provides player vehicle storage UI, vehicle
|
||||
store/retrieve actions, selected nearby vehicle service requests, vehicle
|
||||
context building, and the virtual garage view.
|
||||
---
|
||||
title: "Client Garage Usage Guide"
|
||||
description: "The client garage addon provides player vehicle storage UI, vehicle store/retrieve actions, selected nearby vehicle service requests, vehicle context building, and the virtual garage view."
|
||||
---
|
||||
|
||||
## Open Garage UI
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
# Client Locker Usage Guide
|
||||
|
||||
The client locker addon manages personal locker display state, local locker
|
||||
container behavior, and virtual arsenal unlock state.
|
||||
---
|
||||
title: "Client Locker Usage Guide"
|
||||
description: "The client locker addon manages personal locker display state, local locker container behavior, and virtual arsenal unlock state."
|
||||
---
|
||||
|
||||
## Repositories
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
# Client Notifications Usage Guide
|
||||
|
||||
The client notifications addon owns the notification HUD, notification sound,
|
||||
and local notification service used by Forge client and server modules.
|
||||
---
|
||||
title: "Client Notifications Usage Guide"
|
||||
description: "The client notifications addon owns the notification HUD, notification sound, and local notification service used by Forge client and server modules."
|
||||
---
|
||||
|
||||
## Runtime Behavior
|
||||
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
# Client Organization Usage Guide
|
||||
|
||||
The client organization addon provides the organization portal UI and browser
|
||||
bridge for login, registration, membership, invites, credit lines, leave and
|
||||
disband flows, assets, fleet, and treasury display.
|
||||
---
|
||||
title: "Client Organization Usage Guide"
|
||||
description: "The client organization addon provides the organization portal UI and browser bridge for login, registration, membership, invites, credit lines, leave and disband flows, assets, fleet, and treasury display."
|
||||
---
|
||||
|
||||
## Open Organization UI
|
||||
|
||||
@ -24,6 +23,7 @@ through `forge_client_org_fnc_handleUIEvents`.
|
||||
- create/login response routing
|
||||
- leave and disband requests
|
||||
- credit-line assignment requests
|
||||
- payroll and treasury transfer requests
|
||||
- invite, accept invite, and decline invite requests
|
||||
- targeted browser response events
|
||||
|
||||
@ -37,6 +37,8 @@ through `forge_client_org_fnc_handleUIEvents`.
|
||||
| `org::disband::request` | Request disband on server. |
|
||||
| `org::leave::request` | Request leave on server. |
|
||||
| `org::credit::request` | Request credit-line assignment. |
|
||||
| `org::payroll::request` | Request payroll payout from the organization treasury. |
|
||||
| `org::transfer::request` | Request treasury transfer to a member. |
|
||||
| `org::invite::request` | Request member invite. |
|
||||
| `org::invite::accept` | Accept invite by org ID. |
|
||||
| `org::invite::decline` | Decline invite by org ID. |
|
||||
@ -83,6 +85,24 @@ Credit-line request payload:
|
||||
}
|
||||
```
|
||||
|
||||
Payroll request payload:
|
||||
|
||||
```json
|
||||
{
|
||||
"amount": 1000
|
||||
}
|
||||
```
|
||||
|
||||
Treasury transfer request payload:
|
||||
|
||||
```json
|
||||
{
|
||||
"memberUid": "76561198000000000",
|
||||
"memberName": "Player Name",
|
||||
"amount": 1000
|
||||
}
|
||||
```
|
||||
|
||||
Invite request payload:
|
||||
|
||||
```json
|
||||
|
||||
@ -3,7 +3,10 @@ const baseURL =
|
||||
(process.env.NODE_ENV === 'production' ? '/forge/' : '/');
|
||||
const siteUrl =
|
||||
process.env.DOCS_SITE_URL ||
|
||||
'https://innovativedevsolutions.github.io';
|
||||
'https://innovativedevsolutions.github.io/forge';
|
||||
|
||||
process.env.NUXT_SITE_URL ||= siteUrl;
|
||||
process.env.NUXT_PUBLIC_SITE_URL ||= siteUrl;
|
||||
|
||||
export default defineNuxtConfig({
|
||||
extends: ['docus'],
|
||||
|
||||
@ -35,6 +35,10 @@ const generatedPages = [
|
||||
source: 'arma/server/docs/usage-examples.md',
|
||||
target: '2.server-extension/2.usage-examples.md'
|
||||
},
|
||||
{
|
||||
source: 'arma/server/addons/common/README.md',
|
||||
target: '2.server-extension/3.common.md'
|
||||
},
|
||||
{
|
||||
source: 'docs/ACTOR_USAGE_GUIDE.md',
|
||||
target: '3.server-modules/1.actor.md'
|
||||
@ -323,9 +327,10 @@ icon: i-lucide-rocket
|
||||
},
|
||||
{
|
||||
target: '1.getting-started/0.index.md',
|
||||
content: `# Getting Started
|
||||
|
||||
Use this section as the main entry point for the Forge framework.
|
||||
content: `---
|
||||
title: Getting Started
|
||||
description: Use this section as the main entry point for the Forge framework.
|
||||
---
|
||||
|
||||
Forge combines:
|
||||
|
||||
@ -421,9 +426,10 @@ icon: i-lucide-layers-3
|
||||
},
|
||||
{
|
||||
target: '3.server-modules/0.index.md',
|
||||
content: `# Server Module Guides
|
||||
|
||||
These pages document the authoritative server-side workflows in Forge.
|
||||
content: `---
|
||||
title: Server Module Guides
|
||||
description: These pages document the authoritative server-side workflows in Forge.
|
||||
---
|
||||
|
||||
Most modules follow the same shape:
|
||||
|
||||
@ -555,7 +561,7 @@ for (const page of generatedPages) {
|
||||
const sourceRel = toPosix(page.source);
|
||||
const sourcePath = path.join(repoRoot, page.source);
|
||||
const rawContent = await fs.readFile(sourcePath, 'utf8');
|
||||
const content = rewriteMarkdownLinks(rawContent, sourceRel);
|
||||
const content = prepareGeneratedPageContent(rewriteMarkdownLinks(rawContent, sourceRel));
|
||||
await writeContentFile(page.target, content);
|
||||
}
|
||||
|
||||
@ -591,6 +597,151 @@ function rewriteMarkdownLinks(content, sourceRel) {
|
||||
});
|
||||
}
|
||||
|
||||
function prepareGeneratedPageContent(content) {
|
||||
const title = extractFirstH1(content);
|
||||
const description = extractLeadParagraph(content);
|
||||
const body = stripMatchingLeadParagraph(stripFirstH1(content), description).trimStart();
|
||||
const frontmatter = [
|
||||
'---',
|
||||
title ? `title: ${yamlString(title)}` : undefined,
|
||||
description ? `description: ${yamlString(description)}` : undefined,
|
||||
'---'
|
||||
].filter(Boolean).join('\n');
|
||||
|
||||
return `${frontmatter}\n\n${body}`;
|
||||
}
|
||||
|
||||
function extractFirstH1(content) {
|
||||
const match = content.match(/^#\s+(.+?)\s*#*\s*$/m);
|
||||
return match ? match[1].trim() : '';
|
||||
}
|
||||
|
||||
function extractLeadParagraph(content) {
|
||||
const lines = stripFirstH1(content).split(/\r?\n/);
|
||||
|
||||
for (let index = 0; index < lines.length; index += 1) {
|
||||
const line = lines[index].trim();
|
||||
if (!line) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isParagraphStart(line)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const paragraph = [];
|
||||
for (let paragraphIndex = index; paragraphIndex < lines.length; paragraphIndex += 1) {
|
||||
const paragraphLine = lines[paragraphIndex].trim();
|
||||
if (!paragraphLine) {
|
||||
break;
|
||||
}
|
||||
|
||||
paragraph.push(paragraphLine);
|
||||
}
|
||||
|
||||
return normalizeParagraph(paragraph.join(' '));
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
function stripFirstH1(content) {
|
||||
const lines = content.split(/\r?\n/);
|
||||
const headingIndex = lines.findIndex((line) => /^#\s+.+/.test(line.trim()));
|
||||
if (headingIndex === -1) {
|
||||
return content;
|
||||
}
|
||||
|
||||
lines.splice(headingIndex, 1);
|
||||
while (headingIndex < lines.length && !lines[headingIndex].trim()) {
|
||||
lines.splice(headingIndex, 1);
|
||||
}
|
||||
|
||||
return lines.join('\n');
|
||||
}
|
||||
|
||||
function stripMatchingLeadParagraph(content, description) {
|
||||
if (!description) {
|
||||
return content;
|
||||
}
|
||||
|
||||
const lines = content.split(/\r?\n/);
|
||||
let startIndex = 0;
|
||||
while (startIndex < lines.length && !lines[startIndex].trim()) {
|
||||
startIndex += 1;
|
||||
}
|
||||
|
||||
if (startIndex < lines.length && /^##\s+overview\s*$/i.test(lines[startIndex].trim())) {
|
||||
const sectionStart = startIndex;
|
||||
startIndex += 1;
|
||||
while (startIndex < lines.length && !lines[startIndex].trim()) {
|
||||
startIndex += 1;
|
||||
}
|
||||
|
||||
let sectionEnd = startIndex;
|
||||
const sectionLines = [];
|
||||
while (sectionEnd < lines.length && !/^#{2,}\s+/.test(lines[sectionEnd].trim())) {
|
||||
if (lines[sectionEnd].trim()) {
|
||||
sectionLines.push(lines[sectionEnd].trim());
|
||||
}
|
||||
|
||||
sectionEnd += 1;
|
||||
}
|
||||
|
||||
if (normalizeParagraph(sectionLines.join(' ')) === description) {
|
||||
while (sectionEnd < lines.length && !lines[sectionEnd].trim()) {
|
||||
sectionEnd += 1;
|
||||
}
|
||||
|
||||
return [...lines.slice(0, sectionStart), ...lines.slice(sectionEnd)].join('\n');
|
||||
}
|
||||
|
||||
startIndex = sectionStart;
|
||||
}
|
||||
|
||||
if (startIndex >= lines.length || !isParagraphStart(lines[startIndex].trim())) {
|
||||
return content;
|
||||
}
|
||||
|
||||
let endIndex = startIndex;
|
||||
const paragraph = [];
|
||||
while (endIndex < lines.length && lines[endIndex].trim()) {
|
||||
paragraph.push(lines[endIndex].trim());
|
||||
endIndex += 1;
|
||||
}
|
||||
|
||||
if (normalizeParagraph(paragraph.join(' ')) !== description) {
|
||||
return content;
|
||||
}
|
||||
|
||||
while (endIndex < lines.length && !lines[endIndex].trim()) {
|
||||
endIndex += 1;
|
||||
}
|
||||
|
||||
return [...lines.slice(0, startIndex), ...lines.slice(endIndex)].join('\n');
|
||||
}
|
||||
|
||||
function isParagraphStart(line) {
|
||||
return !(
|
||||
line.startsWith('#') ||
|
||||
line.startsWith('![') ||
|
||||
line.startsWith('```') ||
|
||||
line.startsWith(':::') ||
|
||||
line.startsWith('::') ||
|
||||
line.startsWith('|') ||
|
||||
/^[-*+]\s+/.test(line) ||
|
||||
/^\d+\.\s+/.test(line)
|
||||
);
|
||||
}
|
||||
|
||||
function normalizeParagraph(value) {
|
||||
return value.replace(/\s+/g, ' ').trim();
|
||||
}
|
||||
|
||||
function yamlString(value) {
|
||||
return JSON.stringify(value);
|
||||
}
|
||||
|
||||
function toRoute(target) {
|
||||
const withoutExt = toPosix(target).replace(/\.md$/i, '');
|
||||
const parts = withoutExt.split('/');
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user