Skip to content

Commit

Permalink
add bi_direnctional_links
Browse files Browse the repository at this point in the history
  • Loading branch information
WncFht committed Jan 20, 2025
1 parent 6104ee4 commit 4f3c9eb
Show file tree
Hide file tree
Showing 7 changed files with 216 additions and 1 deletion.
5 changes: 5 additions & 0 deletions build/lib/mkdocs_bi_directional_links/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# 插件入口文件,定义插件的版本和导出内容
__version__ = "0.1.0"
from .plugin import BiDirectionalLinksPlugin

__all__ = ["BiDirectionalLinksPlugin"]
65 changes: 65 additions & 0 deletions build/lib/mkdocs_bi_directional_links/link_processor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import re
import logging
from pathlib import Path

class LinkProcessor:
def __init__(self):
self.includes = [".md", ".png", ".jpg", ".mp4", ".mp3"] # 支持的文件扩展名

def process_markdown(self, markdown, page, config, files, search_integration):
"""
处理 Markdown 中的双向链接语法,生成相应的 HTML 标签。
"""

def replace_bi_directional_link(match):
"""
替换双向链接语法为 HTML 标签。
"""
file_ref = match.group(1).strip() # 获取文件引用
text = match.group(3).strip() if match.group(3) else file_ref # 获取自定义文本

# 如果文件引用没有扩展名,默认添加 .md
if not any(file_ref.endswith(ext) for ext in self.includes):
file_ref += ".md"

# 获取当前文件的路径
from_file = page.file.src_path

# 使用 SearchIntegration 查找文件路径
file_path = search_integration.find_file(from_file, file_ref)
if not file_path:
logging.warning(f"未找到匹配的文件:'{file_ref}'。")
return match.group(0) # 如果未找到文件,返回原始文本
else:
logging.debug(f"找到文件:'{file_ref}' -> '{file_path}'。") # 添加调试日志

# 统一路径分隔符为正斜杠
file_path = file_path.replace("\\", "/")

# 获取 site_url 的第二个路径段
site_url = config.get("site_url", "")
base_path = ""
if site_url:
# 使用正则表达式提取第二个路径段
match = re.match(r"https?://[^/]+/([^/]+)/?", site_url)
if match:
base_path = match.group(1) # 提取第二个路径段
if base_path:
base_path = f"/{base_path}"

# 根据文件类型生成 HTML 标签
if file_path.endswith(".md"):
file_path = file_path[:-3] # 去除 .md 扩展名
return f'<a href="{base_path}/{file_path}/">{text}</a>' # Markdown 文件生成链接
elif any(file_path.endswith(ext) for ext in [".png", ".jpg", ".gif"]):
return f'<img src="{base_path}/{file_path}" alt="{text}">' # 图片文件生成图片标签
elif any(file_path.endswith(ext) for ext in [".mp4", ".webm"]):
return f'<video controls><source src="{base_path}/{file_path}"></video>' # 视频文件生成视频标签
elif any(file_path.endswith(ext) for ext in [".mp3", ".wav"]):
return f'<audio controls><source src="{base_path}/{file_path}"></audio>' # 音频文件生成音频标签
else:
return match.group(0) # 其他文件类型返回原始文本

# 使用正则表达式匹配 [[file]] 和 [[file|text]] 语法
markdown = re.sub(r'!?\[\[([^|\]\n]+)(\|([^\]\n]+))?\]\]', replace_bi_directional_link, markdown)
return markdown
41 changes: 41 additions & 0 deletions build/lib/mkdocs_bi_directional_links/plugin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import logging
from mkdocs.plugins import BasePlugin
from .search_integration import SearchIntegration
from .link_processor import LinkProcessor

class BiDirectionalLinksPlugin(BasePlugin):
def __init__(self):
self.debug = False # 是否启用调试模式
self.search_integration = SearchIntegration() # Search 插件集成模块
self.link_processor = LinkProcessor() # 双向链接处理模块

def on_config(self, config):
"""
在 MkDocs 加载配置时调用,初始化插件配置。
"""
# print("加载配置")
if "bi_directional_links" in config.get("plugins", {}):
plugin_config = config["plugins"]["bi_directional_links"]
if isinstance(plugin_config, dict): # 确保 plugin_config 是字典
self.debug = plugin_config.get("debug", False)
else:
self.debug = False
else:
self.debug = False

# 初始化 SearchIntegration
self.search_integration.load_config(config)
return config

def on_files(self, files, config):
"""
在 MkDocs 加载文件列表时调用,初始化文件缓存。
"""
# print("加载文件列表")
self.search_integration.load_files(files)

def on_page_markdown(self, markdown, page, config, files):
"""
在解析 Markdown 文件时调用,处理双向链接语法。
"""
return self.link_processor.process_markdown(markdown, page, config, files, self.search_integration)
81 changes: 81 additions & 0 deletions build/lib/mkdocs_bi_directional_links/search_integration.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import os
import logging
from typing import List, Optional

class SearchIntegration:
def __init__(self):
self.docs_dir = ""
self.file_cache = {} # 文件名到路径的映射

def load_config(self, config):
"""
加载 MkDocs 配置,初始化 Search 插件。
"""
self.docs_dir = config["docs_dir"]

def load_files(self, files):
"""
加载文件列表,初始化文件缓存。
"""
self._build_file_cache(files)

def _build_file_cache(self, files):
"""
构建文件缓存。
"""
for file in files:
file_path = file.src_path.replace("\\", "/")
file_name = os.path.basename(file_path)

# 缓存文件名到路径的映射
if file_name not in self.file_cache:
self.file_cache[file_name] = [file_path]
else:
self.file_cache[file_name].append(file_path)

# self.print_cache()

def find_file(self, from_file: str, file_ref: str) -> Optional[str]:
"""
查找文件路径。
"""
from_file = from_file.replace("\\", "/")
# print(f"查找文件:from_file={from_file}, file_ref={file_ref}") # 输出当前查找的文件

# 处理绝对路径
# if file_ref.startswith("/"):
# abs_path = os.path.join(self.docs_dir, file_ref[1:])
# abs_path = abs_path.replace("\\", "/")
# print(f"处理绝对路径:abs_path={abs_path}") # 输出绝对路径
# if os.path.isfile(abs_path):
# return abs_path.replace("\\", "/")
# return None

# 处理直接链接(相对路径)
# from_dir = os.path.dirname(from_file)
# abs_path = os.path.join(from_dir, file_ref)
# abs_path = abs_path.replace("\\", "/")
# print(f"处理相对路径:from_dir={from_dir}, abs_path={abs_path}") # 输出相对路径
# if os.path.isfile(abs_path):
# return abs_path.replace("\\", "/")

# 处理 EzLink(需要搜索的链接)
file_name = os.path.basename(file_ref)
# print(f"处理 EzLink:file_name={file_name}") # 输出文件名

# 1. 快速文件缓存查找
if file_name in self.file_cache:
# print(f"快速文件缓存查找:file_name={file_name}, 缓存={self.file_cache[file_name]}") # 输出缓存内容
# 如果有多个匹配项,直接返回第一个
return self.file_cache[file_name][0]

# 2. 如果未找到文件,返回 None
return None

def print_cache(self):
"""
打印缓存内容。
"""
print("文件名到路径的映射:")
for file_name, paths in self.file_cache.items():
print(f"{file_name}: {paths}")
20 changes: 20 additions & 0 deletions build/lib/mkdocs_bi_directional_links/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import os

def resolve_file_path(file_ref, current_file_path, base_dir):
"""
解析文件路径,支持相对路径和绝对路径。
"""
# 解析相对路径
current_dir = os.path.dirname(os.path.join(base_dir, current_file_path))
file_path = os.path.normpath(os.path.join(current_dir, file_ref))

# 检查文件是否存在
if os.path.isfile(file_path):
return file_path

# 回退到基础目录
file_path = os.path.normpath(os.path.join(base_dir, file_ref))
if os.path.isfile(file_path):
return file_path

return None # 如果未找到文件,返回 None
2 changes: 2 additions & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,8 @@ extra_javascript:
- https://cdnjs.cloudflare.com/ajax/libs/mathjax/3.2.0/es5/tex-svg-full.js

plugins:
- bi_directional_links
# - ezlinks
- blogging:
locale: en
dirs:
Expand Down
3 changes: 2 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ mkdocs-blogging-plugin
mkdocs-callouts
mkdocs-changelog-plugin
mkdocs-minify-plugin
mkdocs-video
mkdocs-video
mkdocs-bi-directional-links

0 comments on commit 4f3c9eb

Please sign in to comment.