# 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文档示例。

`;
// 创建文件
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 =>
``
).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