# markdownzip **Repository Path**: jl15988/markdownzip ## Basic Information - **Project Name**: markdownzip - **Description**: 一个专为Markdown文档设计的打包格式,它能将Markdown文件及其相关资源(图片、视频、附件等)封装为单一的自包含文件,实现文档的便捷分享与存储。MDZ格式支持密码保护、完整性校验等高级特性。 - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-04-02 - **Last Updated**: 2025-04-03 ## Categories & Tags **Categories**: Uncategorized **Tags**: Markdown, md, zip, mdz ## README

MarkdownZip (MDZ)

MarkdownZip (MDZ) 是一个专为Markdown文档设计的打包格式,它能将Markdown文件及其相关资源(图片、视频、附件等)封装为单一的自包含文件,实现文档的便捷分享与存储。MDZ格式支持密码保护、完整性校验等高级特性。

---- ## 特性 - 将Markdown内容和所有资源文件封装到单一文件中 - 支持密码加密保护敏感内容 - 文件完整性校验,防止文件损坏 - 安全的文件操作,防止路径遍历攻击 - 支持丰富的元数据(标题、作者、创建和修改时间等) - 简单易用的TypeScript API - 支持命令行操作 ## 安装 ### NPM包安装 ```bash npm install markdownzip ``` ### 全局安装CLI工具 ```bash npm install -g markdownzip ``` ## CLI使用说明 MDZ提供了命令行工具,方便快速创建、查看和管理MDZ文件。 ### 基本命令 ```bash # 创建MDZ文件 mdz create [选项] # 提取MDZ文件内容 mdz extract [选项] # 显示MDZ文件信息 mdz info [选项] # 添加资源到MDZ文件 mdz add <资源文件> [选项] # 列出MDZ文件中的资源 mdz list [选项] # 更新MDZ文件的元数据 mdz metadata [选项] # 设置或更改MDZ文件的密码 mdz password [选项] # 验证MDZ文件的完整性 mdz verify [选项] # 提取MDZ文件中的特定资源 mdz extract-asset <资源ID> <输出路径> [选项] # 显示版本信息 mdz version # 显示帮助信息 mdz help mdz --help ``` ### 常用选项 全局选项: - `--password=<密码>` 或 `-p <密码>` - 设置或提供密码 - `--verbose` 或 `-v` - 显示详细信息 - `--quiet` 或 `-q` - 减少输出信息 - `--force` 或 `-f` - 强制操作,忽略警告 `create` 命令特有选项: - `--title=<标题>` 或 `-t <标题>` - 设置文档标题 - `--author=<作者>` 或 `-a <作者>` - 设置文档作者 `extract` 命令特有选项: - `--overwrite` - 覆盖已存在的文件 `add` 命令特有选项: - `--relative-path=<路径>` 或 `-r <路径>` - 设置资源在MDZ中的相对路径 `list` 命令特有选项: - `--json` - 以JSON格式输出资源列表 `metadata` 命令特有选项: - `--title=<标题>` 或 `-t <标题>` - 更新文档标题 - `--author=<作者>` 或 `-a <作者>` - 更新文档作者 - `--json=` - 以JSON格式提供完整的元数据更新 `password` 命令特有选项: - `--new-password=<密码>` - 设置新密码 - `--remove` - 移除密码保护 ### 命令详解 #### create - 创建MDZ文件 从Markdown文件创建新的MDZ文件。 ```bash mdz create example.mdz README.md --title="示例文档" --author="作者" --password=123456 ``` 此命令会从README.md创建一个新的MDZ文件,设置标题为"示例文档",作者为"作者",并添加密码保护。输出文件为example.mdz。 #### extract - 提取MDZ文件内容 将MDZ文件的主要内容提取到Markdown文件中。 ```bash mdz extract example.mdz extracted.md --password=123456 ``` 此命令会从example.mdz提取主要内容到extracted.md文件中。如果文件有密码保护,需要提供密码。 #### info - 显示MDZ文件信息 显示MDZ文件的元数据和资源列表。 ```bash mdz info example.mdz --password=123456 ``` 输出包括文件标题、作者、版本、创建和更新时间、是否加密以及资源列表等信息。 #### add - 添加资源到MDZ文件 向MDZ文件添加一个资源文件。 ```bash mdz add example.mdz image.png --password=123456 ``` 此命令会向example.mdz文件添加image.png资源,并返回资源ID。 #### list - 列出MDZ文件中的资源 列出MDZ文件中所有资源的详细信息。 ```bash mdz list example.mdz --password=123456 mdz list example.mdz --json # 以JSON格式输出 ``` #### metadata - 更新MDZ文件的元数据 更新MDZ文件的元数据信息,如标题、作者等。 ```bash mdz metadata example.mdz --title="新标题" --author="新作者" --password=123456 mdz metadata example.mdz --json='{"title":"JSON格式标题","author":"JSON格式作者"}' ``` #### password - 设置或更改MDZ文件的密码 设置新密码、更改现有密码或移除密码保护。 ```bash # 设置新密码或更改现有密码 mdz password example.mdz --password=123456 --new-password=654321 # 移除密码保护 mdz password example.mdz --password=123456 --remove ``` #### verify - 验证MDZ文件的完整性 验证MDZ文件中所有资源的校验和,检查文件是否被篡改或损坏。 ```bash mdz verify example.mdz --password=123456 ``` #### extract-asset - 提取MDZ文件中的特定资源 根据资源ID提取MDZ文件中的特定资源到指定路径。 ```bash mdz extract-asset example.mdz 5f2d8da6-e716-4c0e-8b0c-ec92d0b44dbd ./output.png --password=123456 ``` ### 示例场景 #### 基本工作流程 ```bash # 1. 创建MDZ文件 mdz create document.mdz README.md --title="项目文档" --author="团队" # 2. 查看MDZ文件信息 mdz info document.mdz # 3. 添加资源 mdz add document.mdz logo.png mdz add document.mdz screenshot.jpg # 4. 列出所有资源 mdz list document.mdz # 5. 提取内容到新文件 mdz extract document.mdz extracted.md ``` #### 使用密码保护 ```bash # 创建带密码的MDZ文件 mdz create secure.mdz confidential.md --password=123456 --title="机密文档" # 提取受保护的MDZ文件 mdz extract secure.mdz extracted.md --password=123456 # 查看受保护的MDZ文件信息 mdz info secure.mdz --password=123456 # 验证文件完整性 mdz verify secure.mdz --password=123456 # 更改密码 mdz password secure.mdz --password=123456 --new-password=newpass ``` #### 元数据管理 ```bash # 创建MDZ文件 mdz create document.mdz README.md # 更新元数据 mdz metadata document.mdz --title="更新的标题" --author="新作者" # 使用JSON格式更新更多元数据字段 mdz metadata document.mdz --json='{"title":"JSON标题","author":"JSON作者","keywords":["markdown","mdz","文档"]}' ``` #### 批量处理 ```bash # 创建一个批处理脚本示例(bash) #!/bin/bash # 批量创建MDZ文件 for mdfile in *.md; do mdz create "${mdfile%.md}.mdz" "$mdfile" --title="$(basename "${mdfile%.md}")" --author="自动化脚本" done # 批量验证MDZ文件 for mdzfile in *.mdz; do mdz verify "$mdzfile" done ``` ## API使用示例 ### 创建一个新的MDZ文件 ```typescript import { MDZFile } from 'markdownzip'; async function createMDZ() { // 创建一个新的MDZ文件 const mdz = new MDZFile('example.mdz'); // 准备Markdown内容 const content = `# Hello MDZ 这是一个MDZ文档示例。 ![示例图片](./assets/image.png) `; // 创建文件 await mdz.create(content, { title: '示例文档', author: '张三', password: '可选密码' // 可选 }); // 添加资源文件 await mdz.addAsset('/path/to/image.png'); // 保存文件 await mdz.save(); // 关闭文件 await mdz.close(); } ``` ### 打开并读取MDZ文件 ```typescript import { MDZFile } from 'markdownzip'; async function openMDZ() { // 创建MDZ实例 const mdz = new MDZFile('example.mdz'); // 打开文件(如果有密码保护,则提供密码) await mdz.open('可选密码'); // 读取主要内容 const content = await mdz.getMainContent(); console.log(content); // 获取元数据 const metadata = mdz.getMetadata(); console.log(`标题: ${metadata.title}`); console.log(`作者: ${metadata.author}`); // 获取资源列表 const assets = mdz.getAssets(); console.log(`资源数量: ${assets.length}`); // 导出资源 if (assets.length > 0) { await mdz.extractAsset(assets[0].id, '/path/to/output.png'); } // 关闭文件 await mdz.close(); } ``` ### 编辑MDZ文件 ```typescript import { MDZFile } from 'markdownzip'; async function editMDZ() { // 打开现有文件 const mdz = new MDZFile('example.mdz'); await mdz.open('可选密码'); // 获取当前内容并修改 let content = await mdz.getMainContent(); content += '\n\n## 新章节\n\n这是一个新添加的章节。\n'; // 更新内容 await mdz.setMainContent(content); // 更新元数据 mdz.updateMetadata({ title: '更新后的文档标题' }); // 添加新资源 await mdz.addAsset('/path/to/another-image.jpg'); // 保存更改 await mdz.save(); // 关闭文件 await mdz.close(); } ``` ## MDZ文件格式 MDZ文件本质上是一个ZIP文件,具有以下内部结构: - `manifest.json` - 包含元数据和资源列表的清单文件 - `content/` - 包含主Markdown文件及其他内容文件的目录 - `main.md` - 主Markdown文件 - `assets/` - 包含所有资源文件的目录 - `signature` - 用于验证MDZ文件格式有效性的签名文件 ## API参考 ### 核心类 #### MDZFile 主要的类,用于创建、读取和修改MDZ文件。 **构造函数:** ```typescript constructor(filePath?: string, options?: MDZOptions) ``` **方法:** | 方法 | 说明 | 参数 | 返回值 | |------|------|------|--------| | `create` | 创建新的MDZ文件 | mainContent: string, options?: MDZOptions | Promise<void> | | `open` | 打开现有MDZ文件 | password?: string | Promise<void> | | `save` | 保存MDZ文件 | targetPath?: string | Promise<void> | | `close` | 关闭文件并清理临时资源 | - | Promise<void> | | `getMainContent` | 获取主Markdown内容 | - | Promise<string> | | `setMainContent` | 设置主Markdown内容 | content: string | Promise<void> | | `addAsset` | 添加资源 | sourcePath: string, relativePath?: string | Promise<string> | | `removeAsset` | 移除资源 | assetId: string | Promise<void> | | `getAssetContent` | 获取资源内容 | assetId: string | Promise<Buffer> | | `extractAsset` | 导出资源 | assetId: string, targetPath: string | Promise<void> | | `getAssets` | 获取所有资源信息 | - | MDZAsset[] | | `getMetadata` | 获取元数据 | - | MDZMetadata | | `updateMetadata` | 更新元数据 | metadata: Partial<MDZMetadata> | void | | `setPassword` | 设置或移除密码保护 | newPassword: string \| null, currentPassword?: string | Promise<void> | | `isModified` | 检查文件是否已修改 | - | boolean | ### 类型定义 #### MDZMetadata MDZ文件的元数据接口。 | 属性 | 类型 | 必填 | 说明 | |------|------|------|------| | `version` | string | 是 | MDZ格式版本 | | `title` | string | 否 | 文档标题 | | `author` | string | 否 | 作者 | | `createdAt` | string | 是 | 创建时间,ISO格式 | | `updatedAt` | string | 是 | 更新时间,ISO格式 | | `encrypted` | boolean | 是 | 是否加密 | | `checksum` | string | 是 | 校验和 | #### MDZAsset MDZ文件的资源项目接口。 | 属性 | 类型 | 必填 | 说明 | |------|------|------|------| | `id` | string | 是 | 资源唯一标识符 | | `path` | string | 是 | 资源在zip中的路径 | | `originalName` | string | 是 | 原始文件名 | | `mimeType` | string | 是 | MIME类型 | | `size` | number | 是 | 文件大小(字节) | | `checksum` | string | 是 | 文件校验和 | #### MDZManifest MDZ文件的清单接口。 | 属性 | 类型 | 必填 | 说明 | |------|------|------|------| | `metadata` | MDZMetadata | 是 | 元数据 | | `mainDocument` | string | 是 | 主Markdown文件路径 | | `assets` | MDZAsset[] | 是 | 资源列表 | #### MDZOptions 创建或修改MDZ文件时的选项。 | 属性 | 类型 | 必填 | 说明 | |------|------|------|------| | `title` | string | 否 | 文档标题 | | `author` | string | 否 | 作者 | | `password` | string | 否 | 加密密码 | | `tempDir` | string | 否 | 临时目录路径 | | `mainFileName` | string | 否 | 主文件名(默认为main.md) | #### MDZErrorType MDZ操作错误类型枚举。 | 枚举值 | 说明 | |------|------| | `FILE_NOT_FOUND` | 文件未找到或无法访问 | | `INVALID_FORMAT` | 无效的MDZ格式或结构 | | `ENCRYPTION_ERROR` | 加密或解密错误 | | `CHECKSUM_MISMATCH` | 校验和验证失败 | | `IO_ERROR` | 输入/输出操作错误 | | `UNKNOWN_ERROR` | 未知或未指定的错误 | | `PERMISSION_DENIED` | 权限被拒绝 | | `VALIDATION_ERROR` | 内容验证错误 | | `TIMEOUT` | 操作超时 | ## 高级用法 ### 处理错误 MDZ库使用自定义错误类型处理错误情况: ```typescript import { MDZFile, MDZError, MDZErrorType } from 'markdownzip'; async function handleMDZErrors() { try { const mdz = new MDZFile('example.mdz'); await mdz.open('错误密码'); } catch (error) { if (error instanceof MDZError) { switch (error.type) { case MDZErrorType.ENCRYPTION_ERROR: console.error('密码错误或加密问题:', error.message); break; case MDZErrorType.FILE_NOT_FOUND: console.error('文件不存在:', error.message); break; case MDZErrorType.INVALID_FORMAT: console.error('无效的MDZ格式:', error.message); break; default: console.error('MDZ错误:', error.message); } } else { console.error('未知错误:', error); } } } ``` ### 批量资源处理 处理大量资源文件的示例: ```typescript import { MDZFile } from 'markdownzip'; import * as fs from 'fs'; import * as path from 'path'; async function batchAssetProcessing() { const mdz = new MDZFile('document.mdz'); await mdz.create('# 多资源文档'); // 读取目录中的所有图像文件 const imageDir = '/path/to/images'; const files = fs.readdirSync(imageDir) .filter(file => ['.jpg', '.png', '.gif'].includes(path.extname(file).toLowerCase())); // 添加所有图像 for (const file of files) { const filePath = path.join(imageDir, file); const assetId = await mdz.addAsset(filePath); console.log(`添加资源: ${file}, ID: ${assetId}`); } // 更新内容,包含所有图像的引用 const imageReferences = files.map(file => `![${path.basename(file, path.extname(file))}](./assets/${file})` ).join('\n\n'); await mdz.setMainContent(`# 多资源文档\n\n${imageReferences}`); await mdz.save(); await mdz.close(); } ``` ### 导出与转换 将MDZ文件导出为其他格式: ```typescript import { MDZFile } from 'markdownzip'; import * as fs from 'fs'; import * as path from 'path'; async function exportMDZ() { const mdz = new MDZFile('example.mdz'); await mdz.open(); // 创建导出目录 const exportDir = './export'; if (!fs.existsSync(exportDir)) { fs.mkdirSync(exportDir, { recursive: true }); } // 导出主内容 const content = await mdz.getMainContent(); fs.writeFileSync(path.join(exportDir, 'content.md'), content); // 导出所有资源 const assets = mdz.getAssets(); const assetsDir = path.join(exportDir, 'assets'); if (!fs.existsSync(assetsDir)) { fs.mkdirSync(assetsDir, { recursive: true }); } for (const asset of assets) { await mdz.extractAsset(asset.id, path.join(assetsDir, asset.originalName)); } // 导出元数据 const metadata = mdz.getMetadata(); fs.writeFileSync( path.join(exportDir, 'metadata.json'), JSON.stringify(metadata, null, 2) ); await mdz.close(); console.log(`已导出到 ${exportDir}`); } ``` ## 安全特性 MDZ格式具有多项安全特性: 1. **密码保护** - 使用AES-256-CBC加密算法保护敏感内容 2. **数据完整性** - 使用SHA-256校验和验证文件未被篡改 3. **安全的路径处理** - 防止目录遍历攻击 4. **签名验证** - 验证MDZ文件格式的有效性 ### 加密详情 MDZ使用以下加密实现: - 使用PBKDF2进行密钥派生,增强密码强度 - 使用随机盐和初始化向量(IV)确保加密安全性 - 加密结果包含算法信息、盐值和IV,便于未来格式升级 ## 兼容性与性能 - 支持Node.js 14及以上版本 - 支持处理大型文件(>1GB)和大量资源 - 所有文件操作均支持异步处理,避免阻塞主线程 ## 贡献 欢迎贡献代码、提交问题或改进建议。提交PR前请确保: 1. 代码遵循项目的代码风格 2. 添加适当的测试用例 3. 更新相关文档 ## 开发与示例 本项目提供了一些示例和测试脚本,帮助开发者更好地理解MDZ的用法。这些文件在发布的npm包中不可用,但可以在源代码仓库中找到。 ### 示例 在`examples`目录下提供了以下示例: - `example.ts` - 展示MDZ文件的基本操作,包括创建、读取和修改 - `test-encryption.ts` - 展示加密和解密功能的使用方法 ### 运行示例 ```bash # 克隆仓库 git clone https://github.com/yourusername/markdownzip.git cd markdownzip # 安装依赖 npm install # 构建项目 npm run build # 运行基本示例 npm run example # 运行加密测试 npm run test-encryption # 运行所有示例 npm run examples ``` ### 开发工作流 1. 克隆仓库并安装依赖 2. 修改代码 3. 运行`npm run build`构建项目 4. 运行`npm test`确保基本功能正常 5. 运行示例检验特定功能 开发过程中,可以使用`npm run dev`命令启动TypeScript的监视模式,自动编译修改的文件。 ## 文件图标设置 MDZ工具支持为.mdz文件设置自定义图标,使其在文件管理器中更加易于识别。要设置文件图标: 1. 确保`src/MDZ.png`文件存在 2. 运行命令: ```bash npm run install-icon ``` 详细说明请参考[图标设置文档](./icon-tools/icon-README.md)。 ## 许可证 MIT