mirror of
https://github.com/Crosstalk-Solutions/project-nomad.git
synced 2026-03-28 03:29:25 +01:00
fix(Docs): documentation renderer fixes
This commit is contained in:
parent
6ac9d147cf
commit
0c8527921c
6
admin/app/exceptions/internal_server_error_exception.ts
Normal file
6
admin/app/exceptions/internal_server_error_exception.ts
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
import { Exception } from '@adonisjs/core/exceptions'
|
||||
|
||||
export default class InternalServerErrorException extends Exception {
|
||||
static status = 500
|
||||
static code = 'E_INTERNAL_SERVER_ERROR'
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@ import Markdoc from '@markdoc/markdoc'
|
|||
import { streamToString } from '../../util/docs.js'
|
||||
import { getFile, getFileStatsIfExists, listDirectoryContentsRecursive } from '../utils/fs.js'
|
||||
import path from 'path'
|
||||
import InternalServerErrorException from '#exceptions/internal_server_error_exception'
|
||||
|
||||
export class DocsService {
|
||||
private docsPath = path.join(process.cwd(), 'docs')
|
||||
|
|
@ -23,18 +24,27 @@ export class DocsService {
|
|||
}
|
||||
|
||||
parse(content: string) {
|
||||
try {
|
||||
const ast = Markdoc.parse(content)
|
||||
const config = this.getConfig()
|
||||
const errors = Markdoc.validate(ast, config)
|
||||
|
||||
if (errors.length > 0) {
|
||||
throw new Error(`Markdoc validation errors: ${errors.map((e) => e.error).join(', ')}`)
|
||||
// Filter out attribute-undefined errors which may be caused by emojis and special characters
|
||||
const criticalErrors = errors.filter((e) => e.error.id !== 'attribute-undefined')
|
||||
if (criticalErrors.length > 0) {
|
||||
console.error('Markdoc validation errors:', errors.map((e) => JSON.stringify(e.error)).join(', '))
|
||||
throw new Error('Markdoc validation failed')
|
||||
}
|
||||
|
||||
return Markdoc.transform(ast, config)
|
||||
} catch (error) {
|
||||
console.log('Error parsing Markdoc content:', error)
|
||||
throw new InternalServerErrorException(`Error parsing content: ${(error as Error).message}`)
|
||||
}
|
||||
}
|
||||
|
||||
async parseFile(_filename: string) {
|
||||
try {
|
||||
if (!_filename) {
|
||||
throw new Error('Filename is required')
|
||||
}
|
||||
|
|
@ -52,6 +62,9 @@ export class DocsService {
|
|||
}
|
||||
const content = await streamToString(fileStream)
|
||||
return this.parse(content)
|
||||
} catch (error) {
|
||||
throw new InternalServerErrorException(`Error parsing file: ${(error as Error).message}`)
|
||||
}
|
||||
}
|
||||
|
||||
private prettify(filename: string) {
|
||||
|
|
@ -87,6 +100,21 @@ export class DocsService {
|
|||
id: { type: String },
|
||||
},
|
||||
},
|
||||
list: {
|
||||
render: 'List',
|
||||
attributes: {
|
||||
ordered: { type: Boolean },
|
||||
start: { type: Number },
|
||||
},
|
||||
},
|
||||
list_item: {
|
||||
render: 'ListItem',
|
||||
attributes: {
|
||||
marker: { type: String },
|
||||
className: { type: String },
|
||||
class: { type: String }
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
|||
5
admin/docs/about.md
Normal file
5
admin/docs/about.md
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
# About Project N.O.M.A.D.
|
||||
|
||||
Project N.O.M.A.D. (Node for Offline Media, Archives, and Data; "Nomad" for short) is a project started in 2025 by Chris Sherwood of [Crosstalk Solutions, LLC.](https://crosstalksolutions.com). The goal of the project is not to create just another utility for storing offline resources, but rather to allow users to run their own ultime "survival computer".
|
||||
|
||||
While many similar offline survival computers are designed to be run on bare-minimum, lightweight hardware, Project N.O.M.A.D. is quite the opposite. To install and run the available AI tools, we highly encourage the use of a beefy, GPU-backed device to make the most of your install.
|
||||
|
|
@ -1,6 +1,148 @@
|
|||
# Release Notes
|
||||
|
||||
## Version 1.1.0 - July 20, 2025
|
||||
## Version 1.10.1 - December 5, 2025
|
||||
|
||||
### ✨ Improvements
|
||||
1. This is a test
|
||||
- **Kiwix**: ZIM storage path
|
||||
|
||||
---
|
||||
|
||||
## Version 1.10.0 - December 5, 2025
|
||||
|
||||
### 🚀 Features
|
||||
|
||||
- Disk info monitoring
|
||||
|
||||
### ✨ Improvements
|
||||
|
||||
- **Install**: Add Redis env variables to compose file
|
||||
- **Kiwix**: initial download and setup
|
||||
|
||||
---
|
||||
|
||||
## Version 1.9.0 - December 5, 2025
|
||||
|
||||
### 🚀 Features
|
||||
|
||||
- Background job management with BullMQ
|
||||
|
||||
### ✨ Improvements
|
||||
|
||||
- **Install**: Character escaping in env variables
|
||||
- **Install**: Host env variable
|
||||
|
||||
---
|
||||
|
||||
## Version 1.8.0 - December 5, 2025
|
||||
|
||||
### 🚀 Features
|
||||
|
||||
- Alert and button styles redesign
|
||||
- System info page redesign
|
||||
- **Collections**: Curated ZIM Collections
|
||||
- **Collections**: add Preppers Library
|
||||
- **Collections**: add slug, icon, and language
|
||||
- **Collections**: store additional data with resources list
|
||||
- Custom map and ZIM file downloads (WIP)
|
||||
- New maps system (WIP)
|
||||
|
||||
### ✨ Improvements
|
||||
|
||||
- **DockerService**: cleanup old OSM stuff
|
||||
- **Install**: standardize compose file names
|
||||
- Hide query devtools in prod
|
||||
|
||||
---
|
||||
|
||||
## Version 1.7.0 - December 5, 2025
|
||||
|
||||
### 🚀 Features
|
||||
|
||||
- Alert and button styles redesign
|
||||
- System info page redesign
|
||||
- **Collections**: Curated ZIM Collections
|
||||
- **Collections**: add Preppers Library
|
||||
- **Collections**: add slug, icon, and language
|
||||
- **Collections**: store additional data with resources list
|
||||
- Custom map and ZIM file downloads (WIP)
|
||||
- New maps system (WIP)
|
||||
|
||||
### ✨ Improvements
|
||||
|
||||
- **DockerService**: cleanup old OSM stuff
|
||||
- **Install**: standardize compose file names
|
||||
- Hide query devtools in prod
|
||||
|
||||
---
|
||||
|
||||
## Version 1.6.0 - November 18, 2025
|
||||
|
||||
### 🚀 Features
|
||||
|
||||
- Added Kolibri to standard app library
|
||||
|
||||
### ✨ Improvements
|
||||
|
||||
- Standardize container names in management-compose
|
||||
|
||||
---
|
||||
|
||||
## Version 1.5.0 - November 18, 2025
|
||||
|
||||
### 🚀 Features
|
||||
|
||||
- Version footer and fix CI version handling
|
||||
|
||||
---
|
||||
|
||||
## Version 1.4.0 - November 18, 2025
|
||||
|
||||
### 🚀 Features
|
||||
|
||||
- **Services**: Friendly names and descriptions
|
||||
|
||||
### ✨ Improvements
|
||||
|
||||
- **Scripts**: logs directory creation improvements
|
||||
- **Scripts**: fix type in management-compose file path
|
||||
|
||||
---
|
||||
|
||||
## Version 1.3.0 - October 9, 2025
|
||||
|
||||
### 🚀 New Features
|
||||
|
||||
- Uninstall script now removes non-management Nomad app containers
|
||||
|
||||
### ✨ Improvements
|
||||
|
||||
- **OpenStreetMap**: Apply dir permission fixes more robustly
|
||||
|
||||
---
|
||||
|
||||
## Version 1.2.0 - October 7, 2025
|
||||
|
||||
### 🚀 New Features
|
||||
|
||||
- Added CyberChef to standard app library
|
||||
- Added Dozzle to core containers for enhanced logs and metrics
|
||||
- Added FlatNotes to standard app library
|
||||
- Uninstall helper script available
|
||||
|
||||
### ✨ Improvements
|
||||
|
||||
- **OpenStreetMap**:
|
||||
- Fixed directory paths and access issues
|
||||
- Improved error handling
|
||||
- Fixed renderer file permissions
|
||||
- Fixed absolute host path issue
|
||||
- **ZIM Manager**:
|
||||
- Initial ZIM download now hosted in Project Nomad GitHub repo for better availability
|
||||
|
||||
---
|
||||
|
||||
## Version 1.1.0 - August 20, 2025
|
||||
|
||||
### 🚀 New Features
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
import React, { JSX } from 'react'
|
||||
import React from 'react'
|
||||
import Markdoc from '@markdoc/markdoc'
|
||||
import { Heading } from './markdoc/Heading'
|
||||
import { List } from './markdoc/List'
|
||||
import { ListItem } from './markdoc/ListItem'
|
||||
|
||||
// Custom components for Markdoc tags
|
||||
const Callout = ({
|
||||
|
|
@ -27,37 +30,12 @@ const Callout = ({
|
|||
)
|
||||
}
|
||||
|
||||
const Heading = ({
|
||||
level,
|
||||
id,
|
||||
children,
|
||||
}: {
|
||||
level: number
|
||||
id: string
|
||||
children: React.ReactNode
|
||||
}) => {
|
||||
const Tag = `h${level}` as keyof JSX.IntrinsicElements
|
||||
const sizes = {
|
||||
1: 'text-3xl font-bold',
|
||||
2: 'text-2xl font-semibold',
|
||||
3: 'text-xl font-semibold',
|
||||
4: 'text-lg font-semibold',
|
||||
5: 'text-base font-semibold',
|
||||
6: 'text-sm font-semibold',
|
||||
}
|
||||
|
||||
return (
|
||||
// @ts-ignore
|
||||
<Tag id={id} className={`${sizes[level]} mb-4 mt-6`}>
|
||||
{children}
|
||||
</Tag>
|
||||
)
|
||||
}
|
||||
|
||||
// Component mapping for Markdoc
|
||||
const components = {
|
||||
Callout,
|
||||
Heading,
|
||||
List,
|
||||
ListItem,
|
||||
}
|
||||
|
||||
interface MarkdocRendererProps {
|
||||
|
|
@ -65,11 +43,9 @@ interface MarkdocRendererProps {
|
|||
}
|
||||
|
||||
const MarkdocRenderer: React.FC<MarkdocRendererProps> = ({ content }) => {
|
||||
return (
|
||||
<div className="prose prose-lg max-w-none">
|
||||
{Markdoc.renderers.react(content, React, { components })}
|
||||
</div>
|
||||
)
|
||||
console.log('Markdoc content:', content)
|
||||
|
||||
return <div className="tracking-wide">{Markdoc.renderers.react(content, React, { components })}</div>
|
||||
}
|
||||
|
||||
export default MarkdocRenderer
|
||||
|
|
|
|||
28
admin/inertia/components/markdoc/Heading.tsx
Normal file
28
admin/inertia/components/markdoc/Heading.tsx
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
import React, { JSX } from 'react'
|
||||
|
||||
export function Heading({
|
||||
level,
|
||||
id,
|
||||
children,
|
||||
}: {
|
||||
level: number
|
||||
id: string
|
||||
children: React.ReactNode
|
||||
}) {
|
||||
const Component = `h${level}` as keyof JSX.IntrinsicElements
|
||||
const sizes = {
|
||||
1: 'text-3xl font-bold',
|
||||
2: 'text-2xl font-semibold',
|
||||
3: 'text-xl font-semibold',
|
||||
4: 'text-lg font-semibold',
|
||||
5: 'text-base font-semibold',
|
||||
6: 'text-sm font-semibold',
|
||||
}
|
||||
|
||||
return (
|
||||
// @ts-ignore
|
||||
<Component id={id} className={`${sizes[level]} mb-2 mt-6`}>
|
||||
{children}
|
||||
</Component>
|
||||
)
|
||||
}
|
||||
20
admin/inertia/components/markdoc/List.tsx
Normal file
20
admin/inertia/components/markdoc/List.tsx
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
export function List({
|
||||
ordered = false,
|
||||
start,
|
||||
children,
|
||||
}: {
|
||||
ordered?: boolean
|
||||
start?: number
|
||||
children: React.ReactNode
|
||||
}) {
|
||||
const className = ordered
|
||||
? 'list-decimal list-outside !ml-12 mb-4 space-y-1'
|
||||
: 'list-disc list-outside !ml-12 mb-4 space-y-1'
|
||||
const Tag = ordered ? 'ol' : 'ul'
|
||||
return (
|
||||
// @ts-ignore
|
||||
<Tag start={ordered ? start : undefined} className={className}>
|
||||
{children}
|
||||
</Tag>
|
||||
)
|
||||
}
|
||||
4
admin/inertia/components/markdoc/ListItem.tsx
Normal file
4
admin/inertia/components/markdoc/ListItem.tsx
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
|
||||
export function ListItem({ children }: { children: React.ReactNode }) {
|
||||
return <li className="ml-0 !pl-4">{children}</li>
|
||||
}
|
||||
|
|
@ -8,5 +8,5 @@
|
|||
"~/*": ["./*"],
|
||||
},
|
||||
},
|
||||
"include": ["./**/*.ts", "./**/*.tsx"],
|
||||
"include": ["./**/*.ts", "./**/*.tsx", "components/markdoc/nodes/heading.markdoc.js"],
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user