Skip to content

Commit

Permalink
Merge pull request #4 from gbcdef/main
Browse files Browse the repository at this point in the history
Add support for recursively converting directory
  • Loading branch information
Undertone0809 authored Feb 19, 2023
2 parents be8d16d + 579a7f4 commit a80f4b9
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 11 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ Aliyun:
- 如果你想要保存到本地
```yaml
# 需要转换的markdown文件
# 需要转换的markdown文件或者包含markdown文件的目录
file_path: "test.md"
# 选择本地适配器,img路径将切换为本地路径
adapter: "Local"
Expand All @@ -67,7 +67,7 @@ python main.py

4. 生成转换后的文件

- 运行程序后,转换md图片链接后的文件名为 `yourfilename_converted.md`.
- 运行程序后,转换md图片链接后的文件名为 `yourfilename_converted.md`. 如果转换的是目录,则会以原文件名的方式保存在`<yaml_file_path>_converted_<hashcode>`文件夹下

> 如果你选择保存在本地,那么图片将保存在`images`中,在markdown中以相对路径的方式存在,因此你在移动markdown文件的时候要把对应的`images`文件一起copy走。 没有人想把它作为绝对路径,因此我并没有设置本地绝对路径的功能实现,如果你有这样的需求,欢迎pr。
Expand All @@ -83,7 +83,7 @@ Actually,没有技术什么框架,但还是简单的放一个架构图吧,
## 待办
- [ ] 支持更多类型的图床
- [ ] 完善单元测试
- [ ] 支持批量文件修改
- [x] 支持批量文件修改
- [ ] 支持大图片压缩
- [ ] 支持用yaml自定义文件名、
- [ ] 支持命令行
Expand Down
37 changes: 33 additions & 4 deletions coverter.py → converter.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import os
import re
import logging
import shutil
from typing import Optional
from adapter import Adapter
import image_service

logger = logging.getLogger(__name__)


class Coverter:
class Converter:

def __init__(self, adapter: Optional[Adapter] = None) -> None:
"""
Expand All @@ -20,17 +22,42 @@ def __init__(self, adapter: Optional[Adapter] = None) -> None:
will be coverted to local link.
"""
self.adapter = adapter
self._convert_mode = 'file'
self._converted_path = ''

def covert(self, file_path: str):
def convert(self, file_or_dir_path: str):
self._converted_path = file_or_dir_path

if os.path.isdir(file_or_dir_path):
self._convert_mode = 'dir'
self._convert_dir(file_or_dir_path)
else:
self._convert_mode = 'file'
self._convert_file(file_or_dir_path)

def _convert_file(self, file_path: str):
"""
input a markdown file path, this function will replace img address
attention: markdown image must be a website url ranther than a file path.
"""

ori_data = self._read_md(file_path)
pre_data = self._find_img_and_replace(ori_data)
self._write_data(file_path, pre_data)
logger.info("task end")

def _convert_dir(self, dir_path: str):
"""
input a directory path, this function will recursively convert all markdown files in sub folders.
"""
new_dir_path = dir_path + "_converted_" + str(hash(self))[0:8]
shutil.copytree(dir_path, new_dir_path)

for path, _, file_list in os.walk(new_dir_path):
for file_name in file_list:
to_convert = os.path.join(path, file_name)
self._convert_file(to_convert)

def _read_md(self, file_path: str) -> str:
""" read markdown file and return markdown data """
with open(file_path, "r", encoding="utf-8") as f:
Expand All @@ -40,6 +67,7 @@ def _read_md(self, file_path: str) -> str:

def _find_img_and_replace(self, md_str: str) -> str:
""" input original markdown str and replace images address """
# todo: when _convert_mode is 'dir' mode, images path are still replaced as relative like `.\images\20230218_1733048462.png` which is invalid
images = list(map(lambda item: item[1], re.findall(
r'(?:!\[(.*?)\]\((.*?)\))|<img.*?src=[\'\"](.*?)[\'\"].*?>', md_str)))

Expand All @@ -55,7 +83,8 @@ def _replace_url(self, md_str: str, origin_image_url: str) -> str:
return md_str

def _write_data(self, file_path: str, md_str: str):
new_file_url = file_path.replace(".md", "_converted.md")
new_file_url = file_path.replace(".md", "_converted.md") if self._convert_mode == 'file' else file_path

with open(f"{new_file_url}", "w", encoding="utf-8") as f:
f.write(md_str)
logger.info("write successfully")
logger.info(f"write successfully to {new_file_url}")
6 changes: 3 additions & 3 deletions main.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import logging

from adapter import *
from coverter import Coverter
from converter import Converter

logging.basicConfig(level=logging.INFO,
format='%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s')
Expand Down Expand Up @@ -33,8 +33,8 @@ def __init__(self) -> None:
self.adapter = LocalAdapter()

def run(self):
coverter = Coverter(self.adapter)
coverter.covert(self.file_path)
converter = Converter(self.adapter)
converter.convert(self.file_path)


def main():
Expand Down
8 changes: 7 additions & 1 deletion yaml_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,14 @@
def yaml_check():
""" check some yaml arguments. """
# check file_path
with open(f"{get_file_path()}", 'r') as f:
path = get_file_path()
if os.path.isfile(path):
f = open(path, 'r')
f.close()
elif os.path.isdir(path):
pass
else:
raise ValueError("file_path is not a file nor a directory")
# check adapter
if get_adapter_type() not in adapter.ADAPTER_ENUM:
raise ValueError("Please check your yaml adapter config")
Expand Down

0 comments on commit a80f4b9

Please sign in to comment.