mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-15 19:39:40 +02:00
## New Features ### Network Graph Visualization (Contacts, Calendar, Todo) - D3.js force simulation for physics-based layout - Zoom & pan with mouse/touchpad - Keyboard shortcuts: +/- zoom, 0 reset, Esc deselect, / search, F focus - Filtering by tags, company/location/project, connection strength - Shared components in @manacore/shared-ui ### Central Tags API (mana-core-auth) - CRUD endpoints for tags - Schema: tags table with userId, name, color, app - Shared tag components in @manacore/shared-ui ### Custom Themes System - Theme editor with live preview and color picker - Community theme gallery - Theme sharing (public, unlisted, private) - Backend API in mana-core-auth ### Todo App Extensions - Glass-pill design for task input and items - Settings page with 20+ preferences - Task edit modal with inline editing - Statistics page with visualizations - PWA support with offline capabilities - Multiple kanban boards ### Contacts App Features - Duplicate detection - Photo upload - Batch operations - Enhanced favorites page with multiple view modes - Alphabet view improvements - Search modal ### Help System - @manacore/shared-help-content - @manacore/shared-help-ui - @manacore/shared-help-types ### Other Features - Themes page for all apps - Referral system frontend - CommandBar (global search) - Skeleton loaders - Settings page improvements ## Bug Fixes - Network graph simulation initialization - Database schema TEXT for user_id columns (Better Auth compatibility) - Various styling fixes ## Documentation - Daily report for 2025-12-10 - CI/CD deployment guide 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
86 lines
1.8 KiB
TypeScript
86 lines
1.8 KiB
TypeScript
/**
|
|
* Markdown + Frontmatter Parser
|
|
* Parses Markdown files with YAML frontmatter
|
|
*/
|
|
|
|
import matter from 'gray-matter';
|
|
import { marked } from 'marked';
|
|
import type { ZodSchema } from 'zod';
|
|
|
|
export interface ParsedContent<T> {
|
|
frontmatter: T;
|
|
content: string;
|
|
html: string;
|
|
}
|
|
|
|
export interface ParseOptions {
|
|
/** Convert Markdown to HTML */
|
|
renderHtml?: boolean;
|
|
}
|
|
|
|
/**
|
|
* Parse a Markdown file with frontmatter
|
|
*/
|
|
export function parseMarkdown<T>(
|
|
rawContent: string,
|
|
schema?: ZodSchema<T>,
|
|
options: ParseOptions = { renderHtml: true }
|
|
): ParsedContent<T> {
|
|
const { data, content } = matter(rawContent);
|
|
|
|
// Validate frontmatter if schema provided
|
|
let frontmatter: T;
|
|
if (schema) {
|
|
const result = schema.safeParse(data);
|
|
if (!result.success) {
|
|
throw new Error(`Invalid frontmatter: ${result.error.message}`);
|
|
}
|
|
frontmatter = result.data;
|
|
} else {
|
|
frontmatter = data as T;
|
|
}
|
|
|
|
// Render HTML if requested
|
|
const html = options.renderHtml ? (marked.parse(content) as string) : '';
|
|
|
|
return {
|
|
frontmatter,
|
|
content: content.trim(),
|
|
html,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Parse multiple Markdown files
|
|
*/
|
|
export function parseMarkdownFiles<T>(
|
|
files: { filename: string; content: string }[],
|
|
schema?: ZodSchema<T>,
|
|
options?: ParseOptions
|
|
): Array<ParsedContent<T> & { filename: string }> {
|
|
return files.map(({ filename, content }) => ({
|
|
filename,
|
|
...parseMarkdown<T>(content, schema, options),
|
|
}));
|
|
}
|
|
|
|
/**
|
|
* Extract text content from HTML (for search indexing)
|
|
*/
|
|
export function stripHtml(html: string): string {
|
|
return html
|
|
.replace(/<[^>]*>/g, ' ')
|
|
.replace(/\s+/g, ' ')
|
|
.trim();
|
|
}
|
|
|
|
/**
|
|
* Generate excerpt from content
|
|
*/
|
|
export function generateExcerpt(content: string, maxLength = 150): string {
|
|
const text = stripHtml(content);
|
|
if (text.length <= maxLength) {
|
|
return text;
|
|
}
|
|
return text.substring(0, maxLength).trim() + '...';
|
|
}
|