Signed-off-by: wang.yuqi <yuqi.wang@daocloud.io> Signed-off-by: wang.yuqi <noooop@126.com> Signed-off-by: Harry Mellor <19981378+hmellor@users.noreply.github.com> Co-authored-by: Cyrus Leung <cyrus.tl.leung@gmail.com> Co-authored-by: Harry Mellor <19981378+hmellor@users.noreply.github.com>
142 lines
5.1 KiB
Python
142 lines
5.1 KiB
Python
# SPDX-License-Identifier: Apache-2.0
|
|
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
|
|
"""
|
|
MkDocs hook + markdown extension to enable the following links to render correctly,
|
|
including inside content included via pymdownx.snippets:
|
|
|
|
- Relative file links outside of the `docs/` directory, e.g.:
|
|
- [Text](../some_file.py)
|
|
- [Directory](../../some_directory/)
|
|
- GitHub URLs for issues, pull requests, and projects, e.g.:
|
|
- Adds GitHub icon before links
|
|
- Replaces raw links with descriptive text,
|
|
e.g. <...pull/123> -> [Pull Request #123](.../pull/123)
|
|
- Works for external repos too by including the `owner/repo` in the link title
|
|
|
|
The link replacement runs as a markdown preprocessor (priority 25) so that it executes
|
|
after pymdownx.snippets (priority 32) has expanded all included content.
|
|
The on_page_markdown hook passes the current page context to the preprocessor before
|
|
each page is converted.
|
|
"""
|
|
|
|
from pathlib import Path
|
|
|
|
import regex as re
|
|
from markdown import Extension
|
|
from markdown.preprocessors import Preprocessor
|
|
from mkdocs.config.defaults import MkDocsConfig
|
|
from mkdocs.structure.files import Files
|
|
from mkdocs.structure.pages import Page
|
|
|
|
ROOT_DIR = Path(__file__).parent.parent.parent.parent.resolve()
|
|
DOC_DIR = ROOT_DIR / "docs"
|
|
|
|
gh_icon = ":octicons-mark-github-16:"
|
|
|
|
# Regex pieces
|
|
TITLE = r"(?P<title>[^\[\]<>]+?)"
|
|
REPO = r"(?P<repo>.+?/.+?)"
|
|
TYPE = r"(?P<type>issues|pull|projects)"
|
|
NUMBER = r"(?P<number>\d+)"
|
|
PATH = r"(?P<path>[^\s]+?)"
|
|
FRAGMENT = r"(?P<fragment>#[^\s]+)?"
|
|
URL = f"https://github.com/{REPO}/{TYPE}/{NUMBER}{FRAGMENT}"
|
|
RELATIVE = rf"(?!(https?|ftp)://|#){PATH}{FRAGMENT}"
|
|
|
|
# Common titles to use for GitHub links when none is provided in the link.
|
|
TITLES = {"issues": "Issue ", "pull": "Pull Request ", "projects": "Project "}
|
|
|
|
# Regex to match GitHub issue, PR, and project links with optional titles.
|
|
github_link = re.compile(rf"(\[{TITLE}\]\(|<){URL}(\)|>)")
|
|
# Regex to match relative file links with optional titles.
|
|
relative_link = re.compile(rf"\[{TITLE}\]\({RELATIVE}\)")
|
|
|
|
|
|
class UrlSchemesPreprocessor(Preprocessor):
|
|
"""Preprocessor that runs after pymdownx.snippets to process all links."""
|
|
|
|
def __init__(self, md, ext):
|
|
super().__init__(md)
|
|
self.ext = ext
|
|
|
|
def run(self, lines):
|
|
page = self.ext.page
|
|
if page is None or getattr(page.file, "abs_src_path", None) is None:
|
|
return lines
|
|
|
|
def replace_relative_link(match: re.Match) -> str:
|
|
"""
|
|
Replace relative file links with URLs if they point outside the docs dir.
|
|
"""
|
|
title = match.group("title")
|
|
path = match.group("path")
|
|
path = (Path(page.file.abs_src_path).parent / path).resolve()
|
|
fragment = match.group("fragment") or ""
|
|
|
|
# Check if the path exists and is outside the docs dir
|
|
if not path.exists() or path.is_relative_to(DOC_DIR):
|
|
return match.group(0)
|
|
|
|
# Files and directories have different URL schemes on GitHub
|
|
slug = "tree/main" if path.is_dir() else "blob/main"
|
|
|
|
path = path.relative_to(ROOT_DIR)
|
|
url = f"https://github.com/vllm-project/vllm/{slug}/{path}{fragment}"
|
|
return f"[{gh_icon} {title}]({url})"
|
|
|
|
def replace_github_link(match: re.Match) -> str:
|
|
"""
|
|
Replace GitHub issue, PR, and project links with enhanced Markdown links.
|
|
"""
|
|
repo = match.group("repo")
|
|
type = match.group("type")
|
|
number = match.group("number")
|
|
# Title and fragment could be None
|
|
title = match.group("title") or ""
|
|
fragment = match.group("fragment") or ""
|
|
|
|
# Use default titles for raw links
|
|
if not title:
|
|
title = TITLES[type]
|
|
if "vllm-project" not in repo:
|
|
title += repo
|
|
title += f"#{number}"
|
|
|
|
url = f"https://github.com/{repo}/{type}/{number}{fragment}"
|
|
return f"[{gh_icon} {title}]({url})"
|
|
|
|
markdown = "\n".join(lines)
|
|
markdown = relative_link.sub(replace_relative_link, markdown)
|
|
markdown = github_link.sub(replace_github_link, markdown)
|
|
return markdown.split("\n")
|
|
|
|
|
|
class UrlSchemesExtension(Extension):
|
|
"""Markdown extension that registers the URL schemes preprocessor."""
|
|
|
|
def __init__(self, **kwargs):
|
|
self.page = None
|
|
super().__init__(**kwargs)
|
|
|
|
def extendMarkdown(self, md):
|
|
# Priority 25 runs after pymdownx.snippets (priority 32)
|
|
md.preprocessors.register(UrlSchemesPreprocessor(md, self), "url_schemes", 25)
|
|
|
|
|
|
# Singleton extension instance shared between the hook and the preprocessor.
|
|
_ext = UrlSchemesExtension()
|
|
|
|
|
|
def on_config(config: MkDocsConfig) -> MkDocsConfig:
|
|
"""Register the URL schemes markdown extension."""
|
|
config["markdown_extensions"].append(_ext)
|
|
return config
|
|
|
|
|
|
def on_page_markdown(
|
|
markdown: str, *, page: Page, config: MkDocsConfig, files: Files
|
|
) -> str:
|
|
"""Pass the current page context to the preprocessor."""
|
|
_ext.page = page
|
|
return markdown
|