Skip to content

Commit 5cb0ef2

Browse files
committed
feat: implement cross-platform image extraction logic and project configuration management
1 parent 0d5412f commit 5cb0ef2

10 files changed

Lines changed: 265 additions & 141 deletions

bin/converter.py

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -850,7 +850,7 @@ def _is_decorative_image(data, width=None, height=None, is_decorative_flag=False
850850

851851
def _setup_image_output_dir(markdown_output_path):
852852
"""
853-
在 Markdown 输出文件旁创建 images/ 子目录
853+
在 Markdown 输出文件旁创建配置的图片子目录
854854
855855
Args:
856856
markdown_output_path: Markdown 输出文件的绝对路径
@@ -866,17 +866,17 @@ def _setup_image_output_dir(markdown_output_path):
866866

867867
def _save_extracted_image(data, image_save_dir, image_rel_dir, base_name, image_counter):
868868
"""
869-
保存图片到 images/ 目录
869+
保存图片到配置的图片目录
870870
871871
Args:
872872
data: 图片二进制数据
873-
image_save_dir: images/ 目录绝对路径
874-
image_rel_dir: images/ 相对路径(用于 Markdown 引用)
873+
image_save_dir: 图片目录绝对路径
874+
image_rel_dir: 图片目录相对路径(用于 Markdown 引用)
875875
base_name: 文档基础名称(不含扩展名)
876876
image_counter: 图片序号
877877
878878
Returns:
879-
相对路径字符串,如 'images/report_img_001.png',失败返回 None
879+
相对路径字符串,如 'assets/report_img_001.png',失败返回 None
880880
"""
881881
fmt = _detect_image_format(data)
882882
if fmt is None:
@@ -2546,29 +2546,30 @@ def main():
25462546
pass
25472547

25482548
if len(sys.argv) < 2:
2549-
print("Usage: converter.py <file_path> [extract_images] [output_path]")
2549+
print("Usage: converter.py <file_path> [extract_images] [output_path] [image_output_folder]")
25502550
sys.exit(1)
25512551

25522552
file_path = sys.argv[1]
25532553
extract_images = True
25542554
if len(sys.argv) > 2 and sys.argv[2].lower() in ('false', 'no', '0'):
25552555
extract_images = False
25562556
output_path = sys.argv[3] if len(sys.argv) > 3 else None
2557+
image_output_folder = sys.argv[4] if len(sys.argv) > 4 else 'images'
25572558

25582559
# 确定图片输出目录
25592560
image_save_dir = None
25602561
image_rel_dir = None
25612562
file_ext = os.path.splitext(file_path)[1].lower()
25622563
if extract_images and file_ext in ('.docx', '.xlsx', '.pptx'):
25632564
if output_path:
2564-
# 图片放在 output_path 同级的 images/ 目录
2565+
# 图片放在 output_path 同级的配置目录下
25652566
out_dir = os.path.dirname(os.path.abspath(output_path))
2566-
image_save_dir = os.path.join(out_dir, 'images')
2567-
image_rel_dir = 'images'
2567+
image_save_dir = os.path.join(out_dir, image_output_folder)
2568+
image_rel_dir = image_output_folder
25682569
else:
2569-
# fallback:放在输入文件目录的 images/ 下
2570-
image_save_dir = os.path.join(os.path.dirname(os.path.abspath(file_path)), 'images')
2571-
image_rel_dir = 'images'
2570+
# fallback:放在输入文件目录的配置目录下
2571+
image_save_dir = os.path.join(os.path.dirname(os.path.abspath(file_path)), image_output_folder)
2572+
image_rel_dir = image_output_folder
25722573

25732574
# 调用对应转换函数
25742575
try:

bin/darwin/image_extractor.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ def __init__(self, document_path: str, output_dir: str = None, markdown_dir: str
1919
self.document_name = self.document_path.stem
2020
self.document_ext = self.document_path.suffix.lower()
2121

22-
# Set output directory - use DocuGenius/images/{document_name}/ structure
22+
# Set output directory under the configured DocuGenius image folder
2323
if output_dir:
2424
self.output_dir = Path(output_dir) / self.document_name
2525
else:
@@ -134,7 +134,7 @@ def _extract_from_docx(self) -> Dict:
134134
image_info = {
135135
'filename': img_filename,
136136
'path': str(img_path),
137-
'relative_path': f"images/{self.document_name}/{img_filename}",
137+
'relative_path': self._calculate_relative_path(img_path),
138138
'format': img_ext.upper(),
139139
'size_bytes': len(image_data),
140140
'source': 'docx_relationship'
@@ -208,7 +208,7 @@ def _extract_from_pptx(self) -> Dict:
208208
image_info = {
209209
'filename': img_filename,
210210
'path': str(img_path),
211-
'relative_path': f"images/{self.document_name}/{img_filename}",
211+
'relative_path': self._calculate_relative_path(img_path),
212212
'slide': slide_num + 1,
213213
'format': img_ext.upper(),
214214
'size_bytes': len(image_data),
@@ -340,7 +340,7 @@ def _calculate_relative_path(self, image_path: Path) -> str:
340340
return relative_path
341341
except Exception as e:
342342
# Fallback to simple relative path
343-
return f"images/{self.document_name}/{image_path.name}"
343+
return f"{self.output_dir.name}/{self.document_name}/{image_path.name}"
344344

345345
def _calculate_file_hash(self, file_path: Path) -> str:
346346
"""Calculate MD5 hash of a file for duplicate detection"""

bin/win32/image_extractor.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ def __init__(self, document_path: str, output_dir: str = None, markdown_dir: str
2929
self.document_name = self.document_path.stem
3030
self.document_ext = self.document_path.suffix.lower()
3131

32-
# Set output directory - use DocuGenius/images/{document_name}/ structure
32+
# Set output directory under the configured DocuGenius image folder
3333
if output_dir:
3434
self.output_dir = Path(output_dir) / self.document_name
3535
else:
@@ -351,7 +351,7 @@ def _calculate_relative_path(self, image_path: Path) -> str:
351351
return relative_path
352352
except Exception as e:
353353
# Fallback to simple relative path
354-
return f"images/{self.document_name}/{image_path.name}"
354+
return f"{self.output_dir.name}/{self.document_name}/{image_path.name}"
355355

356356
def _calculate_file_hash(self, file_path: Path) -> str:
357357
"""Calculate MD5 hash of a file for duplicate detection"""

package.nls.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,16 @@
77
"config.overwriteExisting.description": "Overwrite existing .md files if source file is newer",
88
"config.extractImages.description": "[BETA] Extract images from Word, Excel, and PowerPoint documents to a separate assets folder (PDF image extraction is not supported)",
99

10-
"config.imageOutputFolder.description": "Folder name for extracted images (relative to document location or markdown subdirectory) (only effective when image extraction is enabled)",
11-
"config.imageMinSize.description": "Minimum image size threshold used when extracting document images",
10+
"config.imageOutputFolder.description": "Folder name for extracted images, used for saved assets and Markdown links (relative to the document location or markdown subdirectory; only effective when image extraction is enabled)",
11+
"config.imageMinSize.description": "Minimum extracted image size in pixels used to skip tiny decorative images",
1212
"config.enableDocumentSplitting.description": "Automatically split large documents into multiple Markdown files for better performance and readability",
1313
"config.documentSplittingThreshold.description": "Character count threshold for document splitting (documents exceeding this limit will be split into multiple files)",
1414

1515
"config.organizeInSubdirectory.description": "Organize converted Markdown files in a subdirectory to separate them from source files",
1616
"config.markdownSubdirectoryName.description": "Name of the subdirectory where converted Markdown files will be stored",
1717
"config.showSuccessNotifications.description": "Show popup notifications when files are successfully converted",
18-
"config.createProjectConfig.description": "Create .docugenius.json project configuration file by default (if disabled, uses global settings only)",
19-
"config.copyTextFiles.description": "Copy plain text files (.txt, .md, .csv, etc.) to the knowledge base folder for unified indexing",
18+
"config.createProjectConfig.description": "When you explicitly enable DocuGenius for a workspace, persist project state in .docugenius.json (if disabled, project state stays in VS Code workspace storage and global settings are used)",
19+
"config.copyTextFiles.description": "Copy plain text files (.txt, .md, .csv, etc.) into the DocuGenius output location without modifying the originals",
2020
"config.batchConversionBehavior.description": "How to handle multiple files detected at once",
2121
"config.batchConversionBehavior.askForEach": "Ask for confirmation for each file individually",
2222
"config.batchConversionBehavior.askOnce": "Ask once for all files in the batch",
@@ -101,7 +101,7 @@
101101
"converter.error.lastError": "Last error: {0}",
102102
"converter.log.copySuccess": "Copied: {0} -> {1}",
103103
"converter.log.deletedOutput": "Deleted: {0} (source file {1} was deleted)",
104-
"converter.log.deletedImages": "Deleted images: images/{0}/",
104+
"converter.log.deletedImages": "Deleted images: {0}",
105105
"converter.log.deletedLegacyAssets": "Deleted legacy assets: {0}_assets/",
106106
"converter.log.cleanupFailed": "Failed to clean up deleted file {0}: {1}",
107107
"converter.status.cleanup": "Cleaned up {0}",

package.nls.zh-cn.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,16 @@
77
"config.overwriteExisting.description": "如果源文件较新,则覆盖现有的 .md 文件",
88
"config.extractImages.description": "[BETA] 将 Word、Excel、PowerPoint 文档中的图片提取到单独的资源文件夹(暂不支持 PDF 图片提取)",
99

10-
"config.imageOutputFolder.description": "提取图片的文件夹名称(相对于文档位置或 markdown 子目录)(仅在启用图片提取时生效)",
11-
"config.imageMinSize.description": "提取文档图片时使用的最小图片尺寸阈值",
10+
"config.imageOutputFolder.description": "提取图片的文件夹名称,用于保存资源文件和生成 Markdown 图片链接(相对于文档位置或 markdown 子目录仅在启用图片提取时生效)",
11+
"config.imageMinSize.description": "提取图片时使用的最小图片尺寸(像素),用于跳过过小的装饰性图片",
1212
"config.enableDocumentSplitting.description": "自动将大型文档切分为多个 Markdown 文件,以提高性能和可读性",
1313
"config.documentSplittingThreshold.description": "文档切分的字符数阈值(超过此限制的文档将被切分为多个文件)",
1414

1515
"config.organizeInSubdirectory.description": "将转换的文件组织在子目录中,以便与源文件分离",
1616
"config.markdownSubdirectoryName.description": "存储转换的文件的子目录名称",
1717
"config.showSuccessNotifications.description": "文件成功转换时显示弹出通知",
18-
"config.createProjectConfig.description": "默认创建 .docugenius.json 项目配置文件(如果禁用,则仅使用全局设置",
19-
"config.copyTextFiles.description": "将纯文本文件(.txt、.md、.csv 等)复制到知识库文件夹以进行统一索引",
18+
"config.createProjectConfig.description": "当你显式为工作区启用 DocuGenius 时,将项目状态写入 .docugenius.json(如果禁用,则项目状态保存在 VS Code 工作区存储中,并使用全局设置",
19+
"config.copyTextFiles.description": "将纯文本文件(.txt、.md、.csv 等)复制到 DocuGenius 输出目录中,不会修改原文件",
2020
"config.batchConversionBehavior.description": "如何处理同时检测到的多个文件",
2121
"config.batchConversionBehavior.askForEach": "为每个文件单独请求确认",
2222
"config.batchConversionBehavior.askOnce": "为批次中的所有文件请求一次确认",
@@ -101,7 +101,7 @@
101101
"converter.error.lastError": "最后错误: {0}",
102102
"converter.log.copySuccess": "已复制: {0} -> {1}",
103103
"converter.log.deletedOutput": "已删除: {0}(源文件 {1} 已被删除)",
104-
"converter.log.deletedImages": "已删除图片目录: images/{0}/",
104+
"converter.log.deletedImages": "已删除图片目录: {0}",
105105
"converter.log.deletedLegacyAssets": "已删除旧版资源目录: {0}_assets/",
106106
"converter.log.cleanupFailed": "清理已删除文件 {0} 失败: {1}",
107107
"converter.status.cleanup": "已清理 {0}",

package.nls.zh.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,16 @@
77
"config.overwriteExisting.description": "如果源文件较新,则覆盖现有的 .md 文件",
88
"config.extractImages.description": "[BETA] 将 Word、Excel、PowerPoint 文档中的图片提取到单独的资源文件夹(暂不支持 PDF 图片提取)",
99

10-
"config.imageOutputFolder.description": "提取图片的文件夹名称(相对于文档位置或 markdown 子目录)(仅在启用图片提取时生效)",
11-
"config.imageMinSize.description": "提取文档图片时使用的最小图片尺寸阈值",
10+
"config.imageOutputFolder.description": "提取图片的文件夹名称,用于保存资源文件和生成 Markdown 图片链接(相对于文档位置或 markdown 子目录仅在启用图片提取时生效)",
11+
"config.imageMinSize.description": "提取图片时使用的最小图片尺寸(像素),用于跳过过小的装饰性图片",
1212
"config.enableDocumentSplitting.description": "自动将大型文档切分为多个 Markdown 文件,以提高性能和可读性",
1313
"config.documentSplittingThreshold.description": "文档切分的字符数阈值(超过此限制的文档将被切分为多个文件)",
1414

1515
"config.organizeInSubdirectory.description": "将转换的文件组织在子目录中,以便与源文件分离",
1616
"config.markdownSubdirectoryName.description": "存储转换的文件的子目录名称",
1717
"config.showSuccessNotifications.description": "文件成功转换时显示弹出通知",
18-
"config.createProjectConfig.description": "默认创建 .docugenius.json 项目配置文件(如果禁用,则仅使用全局设置",
19-
"config.copyTextFiles.description": "将纯文本文件(.txt、.md、.csv 等)复制到知识库文件夹以进行统一索引",
18+
"config.createProjectConfig.description": "当你显式为工作区启用 DocuGenius 时,将项目状态写入 .docugenius.json(如果禁用,则项目状态保存在 VS Code 工作区存储中,并使用全局设置",
19+
"config.copyTextFiles.description": "将纯文本文件(.txt、.md、.csv 等)复制到 DocuGenius 输出目录中,不会修改原文件",
2020
"config.batchConversionBehavior.description": "如何处理同时检测到的多个文件",
2121
"config.batchConversionBehavior.askForEach": "为每个文件单独请求确认",
2222
"config.batchConversionBehavior.askOnce": "为批次中的所有文件请求一次确认",
@@ -101,7 +101,7 @@
101101
"converter.error.lastError": "最后错误: {0}",
102102
"converter.log.copySuccess": "已复制: {0} -> {1}",
103103
"converter.log.deletedOutput": "已删除: {0}(源文件 {1} 已被删除)",
104-
"converter.log.deletedImages": "已删除图片目录: images/{0}/",
104+
"converter.log.deletedImages": "已删除图片目录: {0}",
105105
"converter.log.deletedLegacyAssets": "已删除旧版资源目录: {0}_assets/",
106106
"converter.log.cleanupFailed": "清理已删除文件 {0} 失败: {1}",
107107
"converter.status.cleanup": "已清理 {0}",

0 commit comments

Comments
 (0)