
项目特性: - 完整的Markdown编辑器,支持实时预览 - 文件管理功能,支持保存/加载/删除文件 - 正则表达式工具,支持批量文本替换 - 前后端分离架构 - 响应式设计 技术栈: - 前端:React + TypeScript + Vite - 后端:Python Flask - Markdown解析:Python-Markdown 包含组件: - WorkingMarkdownEditor: 基础功能版本 - FullMarkdownEditor: 完整功能版本 - SimpleMarkdownEditor: 简化版本
111 lines
2.7 KiB
TypeScript
111 lines
2.7 KiB
TypeScript
/**
|
|
* Markdown工具模块
|
|
* 提供Markdown相关的辅助函数
|
|
*/
|
|
|
|
/**
|
|
* 提取Markdown中的标题用于目录
|
|
*/
|
|
export function extractHeadings(content: string): Array<{
|
|
level: number;
|
|
text: string;
|
|
id: string;
|
|
}> {
|
|
const headingRegex = /^(#{1,6})\s+(.+)$/gm;
|
|
const headings: Array<{ level: number; text: string; id: string }> = [];
|
|
let match;
|
|
|
|
while ((match = headingRegex.exec(content)) !== null) {
|
|
const level = match[1].length;
|
|
const text = match[2].trim();
|
|
const id = text.toLowerCase().replace(/[^\w\u4e00-\u9fa5]+/g, '-');
|
|
|
|
headings.push({ level, text, id });
|
|
}
|
|
|
|
return headings;
|
|
}
|
|
|
|
/**
|
|
* 计算阅读时间
|
|
*/
|
|
export function calculateReadingTime(content: string): number {
|
|
const chineseChars = content.match(/[\u4e00-\u9fa5]/g) || [];
|
|
const englishWords = content.match(/\b\w+\b/g) || [];
|
|
|
|
const chineseTime = chineseChars.length / 500;
|
|
const englishTime = englishWords.length / 200;
|
|
|
|
return Math.max(1, Math.ceil(chineseTime + englishTime));
|
|
}
|
|
|
|
/**
|
|
* 计算字数统计
|
|
*/
|
|
export function calculateWordCount(content: string): {
|
|
characters: number;
|
|
words: number;
|
|
lines: number;
|
|
} {
|
|
const chineseChars = content.match(/[\u4e00-\u9fa5]/g) || [];
|
|
const englishWords = content.match(/\b\w+\b/g) || [];
|
|
const lines = content.split('\n').length;
|
|
|
|
return {
|
|
characters: chineseChars.length,
|
|
words: englishWords.length,
|
|
lines,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* 自动保存到本地存储
|
|
*/
|
|
export function saveToLocalStorage(key: string, content: string): void {
|
|
try {
|
|
localStorage.setItem(`markdown-editor-${key}`, content);
|
|
} catch (error) {
|
|
console.warn('Failed to save to localStorage:', error);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 从本地存储加载内容
|
|
*/
|
|
export function loadFromLocalStorage(key: string): string | null {
|
|
try {
|
|
return localStorage.getItem(`markdown-editor-${key}`);
|
|
} catch (error) {
|
|
console.warn('Failed to load from localStorage:', error);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 格式化文件大小
|
|
*/
|
|
export function formatFileSize(bytes: number): string {
|
|
if (bytes === 0) return '0 B';
|
|
|
|
const k = 1024;
|
|
const sizes = ['B', 'KB', 'MB', 'GB'];
|
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
|
|
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`;
|
|
}
|
|
|
|
/**
|
|
* 格式化时间戳
|
|
*/
|
|
export function formatDate(timestamp: number): string {
|
|
const date = new Date(timestamp);
|
|
const now = new Date();
|
|
const diff = now.getTime() - date.getTime();
|
|
|
|
if (diff < 60000) return '刚刚';
|
|
if (diff < 3600000) return `${Math.floor(diff / 60000)}分钟前`;
|
|
if (diff < 86400000) return `${Math.floor(diff / 3600000)}小时前`;
|
|
if (diff < 604800000) return `${Math.floor(diff / 86400000)}天前`;
|
|
|
|
return date.toLocaleDateString('zh-CN');
|
|
} |