mirror of
https://github.com/squidfunk/mkdocs-material.git
synced 2024-06-14 11:52:32 +03:00
Merge branch 'master' of github.com:squidfunk/mkdocs-material
This commit is contained in:
commit
7e27f4d00b
@ -1,37 +0,0 @@
|
|||||||
# Custom .gitignore-like file
|
|
||||||
#
|
|
||||||
# The difference is that those are regex patterns, which will be compared
|
|
||||||
# against directory and file names case-sensitively. The plugin uses the
|
|
||||||
# external https://pypi.org/project/regex/ module.
|
|
||||||
#
|
|
||||||
# Additional remarks for pattern creation:
|
|
||||||
# - The compared paths will be always in POSIX format.
|
|
||||||
# - Each directory path will have a / at the end to allow to distinguish them
|
|
||||||
# from files.
|
|
||||||
# - Patterns for dynamic or custom paths like Virtual Environments (venv) or
|
|
||||||
# build site directories are created during plugin runtime.
|
|
||||||
|
|
||||||
# Byte-compiled / optimized / DLL files
|
|
||||||
# Python cache directory
|
|
||||||
.*__pycache__/
|
|
||||||
|
|
||||||
# macOS
|
|
||||||
|
|
||||||
.*\.DS_Store
|
|
||||||
|
|
||||||
# .dotfiles in the root directory
|
|
||||||
|
|
||||||
^/\.[^/]+$
|
|
||||||
|
|
||||||
# Generated files and folders
|
|
||||||
|
|
||||||
^/.*\.zip
|
|
||||||
|
|
||||||
# Allow .github or .devcontainer directories
|
|
||||||
# Exclude .cache files and folders
|
|
||||||
# Exclude known IDE directories
|
|
||||||
|
|
||||||
.*\.cache/?
|
|
||||||
^/\.vscode/
|
|
||||||
^/\.vs/
|
|
||||||
^/\.idea/
|
|
27
material/plugins/info/patterns.py
Normal file
27
material/plugins/info/patterns.py
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
def get_exclusion_patterns():
|
||||||
|
"""
|
||||||
|
Regex patterns, which will be compared against directory and file names
|
||||||
|
case-sensitively. https://docs.python.org/3/library/re.html#re.search is the
|
||||||
|
matching function and scans the whole string to find any pattern match. Used
|
||||||
|
with the https://pypi.org/project/regex/ module.
|
||||||
|
|
||||||
|
Additional remarks for pattern creation:
|
||||||
|
- The compared paths will be always in POSIX format.
|
||||||
|
- Each directory path will have a / at the end to allow to distinguish them
|
||||||
|
from files.
|
||||||
|
- Patterns for dynamic or custom paths like Virtual Environments (venv) or
|
||||||
|
build site directories are created during plugin runtime.
|
||||||
|
"""
|
||||||
|
return [
|
||||||
|
r"/__pycache__/", # Python cache directory
|
||||||
|
|
||||||
|
r"/\.DS_Store$", # macOS
|
||||||
|
|
||||||
|
r"/[^/]+\.zip$", # Generated files and folders
|
||||||
|
|
||||||
|
r"/[^/]*\.cache($|/)", # .cache files and folders
|
||||||
|
|
||||||
|
r"/\.vscode/", # Common autogenerated IDE directories
|
||||||
|
r"/\.vs/",
|
||||||
|
r"/\.idea/",
|
||||||
|
]
|
@ -39,6 +39,7 @@ from mkdocs.utils import get_yaml_loader
|
|||||||
from zipfile import ZipFile, ZIP_DEFLATED
|
from zipfile import ZipFile, ZIP_DEFLATED
|
||||||
|
|
||||||
from .config import InfoConfig
|
from .config import InfoConfig
|
||||||
|
from .patterns import get_exclusion_patterns
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
# Classes
|
# Classes
|
||||||
@ -56,6 +57,7 @@ class InfoPlugin(BasePlugin[InfoConfig]):
|
|||||||
|
|
||||||
# Initialize empty members
|
# Initialize empty members
|
||||||
self.exclusion_patterns = []
|
self.exclusion_patterns = []
|
||||||
|
self.excluded_entries = []
|
||||||
|
|
||||||
# Determine whether we're serving the site
|
# Determine whether we're serving the site
|
||||||
def on_startup(self, *, command, dirty):
|
def on_startup(self, *, command, dirty):
|
||||||
@ -183,15 +185,18 @@ class InfoPlugin(BasePlugin[InfoConfig]):
|
|||||||
example, _ = os.path.splitext(example)
|
example, _ = os.path.splitext(example)
|
||||||
example = "-".join([present, slugify(example, "-")])
|
example = "-".join([present, slugify(example, "-")])
|
||||||
|
|
||||||
# Load exclusion patterns
|
# Get local copy of the exclusion patterns
|
||||||
self.exclusion_patterns = _load_exclusion_patterns()
|
self.exclusion_patterns = get_exclusion_patterns()
|
||||||
|
self.excluded_entries = []
|
||||||
|
|
||||||
# Exclude the site_dir at project root
|
# Exclude the site_dir at project root
|
||||||
if config.site_dir.startswith(os.getcwd()):
|
if config.site_dir.startswith(os.getcwd()):
|
||||||
self.exclusion_patterns.append(_resolve_pattern(config.site_dir))
|
self.exclusion_patterns.append(_resolve_pattern(config.site_dir))
|
||||||
|
|
||||||
# Exclude the site-packages directory
|
# Exclude the Virtual Environment directory. site.getsitepackages() has
|
||||||
for path in site.getsitepackages():
|
# inconsistent results across operating systems, and relies on the
|
||||||
|
# PREFIXES that will contain the absolute path to the activated venv.
|
||||||
|
for path in site.PREFIXES:
|
||||||
if path.startswith(os.getcwd()):
|
if path.startswith(os.getcwd()):
|
||||||
self.exclusion_patterns.append(_resolve_pattern(path))
|
self.exclusion_patterns.append(_resolve_pattern(path))
|
||||||
|
|
||||||
@ -211,24 +216,17 @@ class InfoPlugin(BasePlugin[InfoConfig]):
|
|||||||
files: list[str] = []
|
files: list[str] = []
|
||||||
with ZipFile(archive, "a", ZIP_DEFLATED, False) as f:
|
with ZipFile(archive, "a", ZIP_DEFLATED, False) as f:
|
||||||
for abs_root, dirnames, filenames in os.walk(os.getcwd()):
|
for abs_root, dirnames, filenames in os.walk(os.getcwd()):
|
||||||
|
# Set and print progress indicator
|
||||||
|
indicator = f"Processing: {abs_root}"
|
||||||
|
print(indicator, end="\r", flush=True)
|
||||||
|
|
||||||
# Prune the folders in-place to prevent their processing
|
# Prune the folders in-place to prevent their processing
|
||||||
for name in list(dirnames):
|
for name in list(dirnames):
|
||||||
# Resolve the absolute directory path
|
# Resolve the absolute directory path
|
||||||
path = os.path.join(abs_root, name)
|
path = os.path.join(abs_root, name)
|
||||||
|
|
||||||
# Exclude the directory and all subdirectories
|
# Exclude the directory and all subdirectories
|
||||||
if self._is_excluded(_resolve_pattern(path)):
|
if self._is_excluded(path):
|
||||||
dirnames.remove(name)
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Projects, which don't use the projects plugin for
|
|
||||||
# multi-language support could have separate build folders
|
|
||||||
# for each config file or language. Therefore, we exclude
|
|
||||||
# them with the assumption a site_dir contains the sitemap
|
|
||||||
# file. Example of such a setup: https://t.ly/DLQcy
|
|
||||||
sitemap_gz = os.path.join(path, "sitemap.xml.gz")
|
|
||||||
if os.path.exists(sitemap_gz):
|
|
||||||
log.debug(f"Excluded site_dir: {path}")
|
|
||||||
dirnames.remove(name)
|
dirnames.remove(name)
|
||||||
|
|
||||||
# Write files to the in-memory archive
|
# Write files to the in-memory archive
|
||||||
@ -237,13 +235,16 @@ class InfoPlugin(BasePlugin[InfoConfig]):
|
|||||||
path = os.path.join(abs_root, name)
|
path = os.path.join(abs_root, name)
|
||||||
|
|
||||||
# Exclude the file
|
# Exclude the file
|
||||||
if self._is_excluded(_resolve_pattern(path)):
|
if self._is_excluded(path):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Resolve the relative path to create a matching structure
|
# Resolve the relative path to create a matching structure
|
||||||
path = os.path.relpath(path, os.path.curdir)
|
path = os.path.relpath(path, os.path.curdir)
|
||||||
f.write(path, os.path.join(example, path))
|
f.write(path, os.path.join(example, path))
|
||||||
|
|
||||||
|
# Clear the line for the next indicator
|
||||||
|
print(" " * len(indicator), end="\r", flush=True)
|
||||||
|
|
||||||
# Add information on installed packages
|
# Add information on installed packages
|
||||||
f.writestr(
|
f.writestr(
|
||||||
os.path.join(example, "requirements.lock.txt"),
|
os.path.join(example, "requirements.lock.txt"),
|
||||||
@ -261,11 +262,14 @@ class InfoPlugin(BasePlugin[InfoConfig]):
|
|||||||
"system": platform.platform(),
|
"system": platform.platform(),
|
||||||
"architecture": platform.architecture(),
|
"architecture": platform.architecture(),
|
||||||
"python": platform.python_version(),
|
"python": platform.python_version(),
|
||||||
|
"cwd": os.getcwd(),
|
||||||
"command": " ".join([
|
"command": " ".join([
|
||||||
sys.argv[0].rsplit(os.sep, 1)[-1],
|
sys.argv[0].rsplit(os.sep, 1)[-1],
|
||||||
*sys.argv[1:]
|
*sys.argv[1:]
|
||||||
]),
|
]),
|
||||||
"sys.path": sys.path
|
"env:$PYTHONPATH": os.getenv("PYTHONPATH", ""),
|
||||||
|
"sys.path": sys.path,
|
||||||
|
"excluded_entries": self.excluded_entries
|
||||||
},
|
},
|
||||||
default = str,
|
default = str,
|
||||||
indent = 2
|
indent = 2
|
||||||
@ -363,10 +367,10 @@ class InfoPlugin(BasePlugin[InfoConfig]):
|
|||||||
print(Style.NORMAL)
|
print(Style.NORMAL)
|
||||||
for path in outside_root:
|
for path in outside_root:
|
||||||
print(f" {path}")
|
print(f" {path}")
|
||||||
print(" \nTo assure that all project files are found please adjust")
|
print("\n To assure that all project files are found please adjust")
|
||||||
print(" your config or file structure and put everything within the")
|
print(" your config or file structure and put everything within the")
|
||||||
print(" root directory of the project.\n")
|
print(" root directory of the project.")
|
||||||
print(" Please also make sure `mkdocs build` is run in the actual")
|
print("\n Please also make sure `mkdocs build` is run in the actual")
|
||||||
print(" root directory of the project.")
|
print(" root directory of the project.")
|
||||||
print(Style.RESET_ALL)
|
print(Style.RESET_ALL)
|
||||||
|
|
||||||
@ -374,13 +378,34 @@ class InfoPlugin(BasePlugin[InfoConfig]):
|
|||||||
if self.config.archive_stop_on_violation:
|
if self.config.archive_stop_on_violation:
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
# Exclude files which we don't want in our zip file
|
# Check if path is excluded and should be omitted from the zip. Use pattern
|
||||||
def _is_excluded(self, posix_path: str) -> bool:
|
# matching for files and folders, and lookahead specific files in folders to
|
||||||
|
# skip them. Side effect: Save excluded paths to save them in the zip file.
|
||||||
|
def _is_excluded(self, abspath: str) -> bool:
|
||||||
|
|
||||||
|
# Resolve the path into POSIX format to match the patterns
|
||||||
|
pattern_path = _resolve_pattern(abspath, return_path = True)
|
||||||
|
|
||||||
for pattern in self.exclusion_patterns:
|
for pattern in self.exclusion_patterns:
|
||||||
if regex.match(pattern, posix_path):
|
if regex.search(pattern, pattern_path):
|
||||||
log.debug(f"Excluded pattern '{pattern}': {posix_path}")
|
log.debug(f"Excluded pattern '{pattern}': {abspath}")
|
||||||
|
self.excluded_entries.append(f"{pattern} - {pattern_path}")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
# File exclusion should be limited to pattern matching
|
||||||
|
if os.path.isfile(abspath):
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Projects, which don't use the projects plugin for multi-language
|
||||||
|
# support could have separate build folders for each config file or
|
||||||
|
# language. Therefore, we exclude them with the assumption a site_dir
|
||||||
|
# contains the sitemap file. Example of such a setup: https://t.ly/DLQcy
|
||||||
|
sitemap_gz = os.path.join(abspath, "sitemap.xml.gz")
|
||||||
|
if os.path.exists(sitemap_gz):
|
||||||
|
log.debug(f"Excluded site_dir: {abspath}")
|
||||||
|
self.excluded_entries.append(f"sitemap.xml.gz - {pattern_path}")
|
||||||
|
return True
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
@ -435,31 +460,22 @@ def _load_yaml(abs_src_path: str):
|
|||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
# Load info.gitignore, ignore any empty lines or # comments
|
|
||||||
def _load_exclusion_patterns(path: str = None):
|
|
||||||
if path is None:
|
|
||||||
path = os.path.dirname(os.path.abspath(__file__))
|
|
||||||
path = os.path.join(path, "info.gitignore")
|
|
||||||
|
|
||||||
with open(path, encoding = "utf-8") as file:
|
|
||||||
lines = map(str.strip, file.readlines())
|
|
||||||
|
|
||||||
return [line for line in lines if line and not line.startswith("#")]
|
|
||||||
|
|
||||||
# Get a normalized POSIX path for the pattern matching with removed current
|
# Get a normalized POSIX path for the pattern matching with removed current
|
||||||
# working directory prefix. Directory paths end with a '/' to allow more control
|
# working directory prefix. Directory paths end with a '/' to allow more control
|
||||||
# in the pattern creation for files and directories.
|
# in the pattern creation for files and directories. The patterns are matched
|
||||||
def _resolve_pattern(abspath: str):
|
# using the search function, so they are prefixed with ^ for specificity.
|
||||||
path = abspath.replace(os.getcwd(), "", 1).replace(os.sep, "/")
|
def _resolve_pattern(abspath: str, return_path: bool = False):
|
||||||
|
path = abspath.replace(os.getcwd(), "", 1)
|
||||||
|
path = path.replace(os.sep, "/").rstrip("/")
|
||||||
|
|
||||||
if not path:
|
if not path:
|
||||||
return "/"
|
return "/"
|
||||||
|
|
||||||
# Check abspath, as the file needs to exist
|
# Check abspath, as the file needs to exist
|
||||||
if not os.path.isfile(abspath):
|
if not os.path.isfile(abspath):
|
||||||
return path.rstrip("/") + "/"
|
path = path + "/"
|
||||||
|
|
||||||
return path
|
return path if return_path else f"^{path}"
|
||||||
|
|
||||||
# Get project configuration with resolved absolute paths for validation
|
# Get project configuration with resolved absolute paths for validation
|
||||||
def _get_project_config(project_config_file: str):
|
def _get_project_config(project_config_file: str):
|
||||||
|
@ -1,37 +0,0 @@
|
|||||||
# Custom .gitignore-like file
|
|
||||||
#
|
|
||||||
# The difference is that those are regex patterns, which will be compared
|
|
||||||
# against directory and file names case-sensitively. The plugin uses the
|
|
||||||
# external https://pypi.org/project/regex/ module.
|
|
||||||
#
|
|
||||||
# Additional remarks for pattern creation:
|
|
||||||
# - The compared paths will be always in POSIX format.
|
|
||||||
# - Each directory path will have a / at the end to allow to distinguish them
|
|
||||||
# from files.
|
|
||||||
# - Patterns for dynamic or custom paths like Virtual Environments (venv) or
|
|
||||||
# build site directories are created during plugin runtime.
|
|
||||||
|
|
||||||
# Byte-compiled / optimized / DLL files
|
|
||||||
# Python cache directory
|
|
||||||
.*__pycache__/
|
|
||||||
|
|
||||||
# macOS
|
|
||||||
|
|
||||||
.*\.DS_Store
|
|
||||||
|
|
||||||
# .dotfiles in the root directory
|
|
||||||
|
|
||||||
^/\.[^/]+$
|
|
||||||
|
|
||||||
# Generated files and folders
|
|
||||||
|
|
||||||
^/.*\.zip
|
|
||||||
|
|
||||||
# Allow .github or .devcontainer directories
|
|
||||||
# Exclude .cache files and folders
|
|
||||||
# Exclude known IDE directories
|
|
||||||
|
|
||||||
.*\.cache/?
|
|
||||||
^/\.vscode/
|
|
||||||
^/\.vs/
|
|
||||||
^/\.idea/
|
|
27
src/plugins/info/patterns.py
Normal file
27
src/plugins/info/patterns.py
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
def get_exclusion_patterns():
|
||||||
|
"""
|
||||||
|
Regex patterns, which will be compared against directory and file names
|
||||||
|
case-sensitively. https://docs.python.org/3/library/re.html#re.search is the
|
||||||
|
matching function and scans the whole string to find any pattern match. Used
|
||||||
|
with the https://pypi.org/project/regex/ module.
|
||||||
|
|
||||||
|
Additional remarks for pattern creation:
|
||||||
|
- The compared paths will be always in POSIX format.
|
||||||
|
- Each directory path will have a / at the end to allow to distinguish them
|
||||||
|
from files.
|
||||||
|
- Patterns for dynamic or custom paths like Virtual Environments (venv) or
|
||||||
|
build site directories are created during plugin runtime.
|
||||||
|
"""
|
||||||
|
return [
|
||||||
|
r"/__pycache__/", # Python cache directory
|
||||||
|
|
||||||
|
r"/\.DS_Store$", # macOS
|
||||||
|
|
||||||
|
r"/[^/]+\.zip$", # Generated files and folders
|
||||||
|
|
||||||
|
r"/[^/]*\.cache($|/)", # .cache files and folders
|
||||||
|
|
||||||
|
r"/\.vscode/", # Common autogenerated IDE directories
|
||||||
|
r"/\.vs/",
|
||||||
|
r"/\.idea/",
|
||||||
|
]
|
@ -39,6 +39,7 @@ from mkdocs.utils import get_yaml_loader
|
|||||||
from zipfile import ZipFile, ZIP_DEFLATED
|
from zipfile import ZipFile, ZIP_DEFLATED
|
||||||
|
|
||||||
from .config import InfoConfig
|
from .config import InfoConfig
|
||||||
|
from .patterns import get_exclusion_patterns
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
# Classes
|
# Classes
|
||||||
@ -56,6 +57,7 @@ class InfoPlugin(BasePlugin[InfoConfig]):
|
|||||||
|
|
||||||
# Initialize empty members
|
# Initialize empty members
|
||||||
self.exclusion_patterns = []
|
self.exclusion_patterns = []
|
||||||
|
self.excluded_entries = []
|
||||||
|
|
||||||
# Determine whether we're serving the site
|
# Determine whether we're serving the site
|
||||||
def on_startup(self, *, command, dirty):
|
def on_startup(self, *, command, dirty):
|
||||||
@ -183,15 +185,18 @@ class InfoPlugin(BasePlugin[InfoConfig]):
|
|||||||
example, _ = os.path.splitext(example)
|
example, _ = os.path.splitext(example)
|
||||||
example = "-".join([present, slugify(example, "-")])
|
example = "-".join([present, slugify(example, "-")])
|
||||||
|
|
||||||
# Load exclusion patterns
|
# Get local copy of the exclusion patterns
|
||||||
self.exclusion_patterns = _load_exclusion_patterns()
|
self.exclusion_patterns = get_exclusion_patterns()
|
||||||
|
self.excluded_entries = []
|
||||||
|
|
||||||
# Exclude the site_dir at project root
|
# Exclude the site_dir at project root
|
||||||
if config.site_dir.startswith(os.getcwd()):
|
if config.site_dir.startswith(os.getcwd()):
|
||||||
self.exclusion_patterns.append(_resolve_pattern(config.site_dir))
|
self.exclusion_patterns.append(_resolve_pattern(config.site_dir))
|
||||||
|
|
||||||
# Exclude the site-packages directory
|
# Exclude the Virtual Environment directory. site.getsitepackages() has
|
||||||
for path in site.getsitepackages():
|
# inconsistent results across operating systems, and relies on the
|
||||||
|
# PREFIXES that will contain the absolute path to the activated venv.
|
||||||
|
for path in site.PREFIXES:
|
||||||
if path.startswith(os.getcwd()):
|
if path.startswith(os.getcwd()):
|
||||||
self.exclusion_patterns.append(_resolve_pattern(path))
|
self.exclusion_patterns.append(_resolve_pattern(path))
|
||||||
|
|
||||||
@ -211,24 +216,17 @@ class InfoPlugin(BasePlugin[InfoConfig]):
|
|||||||
files: list[str] = []
|
files: list[str] = []
|
||||||
with ZipFile(archive, "a", ZIP_DEFLATED, False) as f:
|
with ZipFile(archive, "a", ZIP_DEFLATED, False) as f:
|
||||||
for abs_root, dirnames, filenames in os.walk(os.getcwd()):
|
for abs_root, dirnames, filenames in os.walk(os.getcwd()):
|
||||||
|
# Set and print progress indicator
|
||||||
|
indicator = f"Processing: {abs_root}"
|
||||||
|
print(indicator, end="\r", flush=True)
|
||||||
|
|
||||||
# Prune the folders in-place to prevent their processing
|
# Prune the folders in-place to prevent their processing
|
||||||
for name in list(dirnames):
|
for name in list(dirnames):
|
||||||
# Resolve the absolute directory path
|
# Resolve the absolute directory path
|
||||||
path = os.path.join(abs_root, name)
|
path = os.path.join(abs_root, name)
|
||||||
|
|
||||||
# Exclude the directory and all subdirectories
|
# Exclude the directory and all subdirectories
|
||||||
if self._is_excluded(_resolve_pattern(path)):
|
if self._is_excluded(path):
|
||||||
dirnames.remove(name)
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Projects, which don't use the projects plugin for
|
|
||||||
# multi-language support could have separate build folders
|
|
||||||
# for each config file or language. Therefore, we exclude
|
|
||||||
# them with the assumption a site_dir contains the sitemap
|
|
||||||
# file. Example of such a setup: https://t.ly/DLQcy
|
|
||||||
sitemap_gz = os.path.join(path, "sitemap.xml.gz")
|
|
||||||
if os.path.exists(sitemap_gz):
|
|
||||||
log.debug(f"Excluded site_dir: {path}")
|
|
||||||
dirnames.remove(name)
|
dirnames.remove(name)
|
||||||
|
|
||||||
# Write files to the in-memory archive
|
# Write files to the in-memory archive
|
||||||
@ -237,13 +235,16 @@ class InfoPlugin(BasePlugin[InfoConfig]):
|
|||||||
path = os.path.join(abs_root, name)
|
path = os.path.join(abs_root, name)
|
||||||
|
|
||||||
# Exclude the file
|
# Exclude the file
|
||||||
if self._is_excluded(_resolve_pattern(path)):
|
if self._is_excluded(path):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Resolve the relative path to create a matching structure
|
# Resolve the relative path to create a matching structure
|
||||||
path = os.path.relpath(path, os.path.curdir)
|
path = os.path.relpath(path, os.path.curdir)
|
||||||
f.write(path, os.path.join(example, path))
|
f.write(path, os.path.join(example, path))
|
||||||
|
|
||||||
|
# Clear the line for the next indicator
|
||||||
|
print(" " * len(indicator), end="\r", flush=True)
|
||||||
|
|
||||||
# Add information on installed packages
|
# Add information on installed packages
|
||||||
f.writestr(
|
f.writestr(
|
||||||
os.path.join(example, "requirements.lock.txt"),
|
os.path.join(example, "requirements.lock.txt"),
|
||||||
@ -261,11 +262,14 @@ class InfoPlugin(BasePlugin[InfoConfig]):
|
|||||||
"system": platform.platform(),
|
"system": platform.platform(),
|
||||||
"architecture": platform.architecture(),
|
"architecture": platform.architecture(),
|
||||||
"python": platform.python_version(),
|
"python": platform.python_version(),
|
||||||
|
"cwd": os.getcwd(),
|
||||||
"command": " ".join([
|
"command": " ".join([
|
||||||
sys.argv[0].rsplit(os.sep, 1)[-1],
|
sys.argv[0].rsplit(os.sep, 1)[-1],
|
||||||
*sys.argv[1:]
|
*sys.argv[1:]
|
||||||
]),
|
]),
|
||||||
"sys.path": sys.path
|
"env:$PYTHONPATH": os.getenv("PYTHONPATH", ""),
|
||||||
|
"sys.path": sys.path,
|
||||||
|
"excluded_entries": self.excluded_entries
|
||||||
},
|
},
|
||||||
default = str,
|
default = str,
|
||||||
indent = 2
|
indent = 2
|
||||||
@ -363,10 +367,10 @@ class InfoPlugin(BasePlugin[InfoConfig]):
|
|||||||
print(Style.NORMAL)
|
print(Style.NORMAL)
|
||||||
for path in outside_root:
|
for path in outside_root:
|
||||||
print(f" {path}")
|
print(f" {path}")
|
||||||
print(" \nTo assure that all project files are found please adjust")
|
print("\n To assure that all project files are found please adjust")
|
||||||
print(" your config or file structure and put everything within the")
|
print(" your config or file structure and put everything within the")
|
||||||
print(" root directory of the project.\n")
|
print(" root directory of the project.")
|
||||||
print(" Please also make sure `mkdocs build` is run in the actual")
|
print("\n Please also make sure `mkdocs build` is run in the actual")
|
||||||
print(" root directory of the project.")
|
print(" root directory of the project.")
|
||||||
print(Style.RESET_ALL)
|
print(Style.RESET_ALL)
|
||||||
|
|
||||||
@ -374,13 +378,34 @@ class InfoPlugin(BasePlugin[InfoConfig]):
|
|||||||
if self.config.archive_stop_on_violation:
|
if self.config.archive_stop_on_violation:
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
# Exclude files which we don't want in our zip file
|
# Check if path is excluded and should be omitted from the zip. Use pattern
|
||||||
def _is_excluded(self, posix_path: str) -> bool:
|
# matching for files and folders, and lookahead specific files in folders to
|
||||||
|
# skip them. Side effect: Save excluded paths to save them in the zip file.
|
||||||
|
def _is_excluded(self, abspath: str) -> bool:
|
||||||
|
|
||||||
|
# Resolve the path into POSIX format to match the patterns
|
||||||
|
pattern_path = _resolve_pattern(abspath, return_path = True)
|
||||||
|
|
||||||
for pattern in self.exclusion_patterns:
|
for pattern in self.exclusion_patterns:
|
||||||
if regex.match(pattern, posix_path):
|
if regex.search(pattern, pattern_path):
|
||||||
log.debug(f"Excluded pattern '{pattern}': {posix_path}")
|
log.debug(f"Excluded pattern '{pattern}': {abspath}")
|
||||||
|
self.excluded_entries.append(f"{pattern} - {pattern_path}")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
# File exclusion should be limited to pattern matching
|
||||||
|
if os.path.isfile(abspath):
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Projects, which don't use the projects plugin for multi-language
|
||||||
|
# support could have separate build folders for each config file or
|
||||||
|
# language. Therefore, we exclude them with the assumption a site_dir
|
||||||
|
# contains the sitemap file. Example of such a setup: https://t.ly/DLQcy
|
||||||
|
sitemap_gz = os.path.join(abspath, "sitemap.xml.gz")
|
||||||
|
if os.path.exists(sitemap_gz):
|
||||||
|
log.debug(f"Excluded site_dir: {abspath}")
|
||||||
|
self.excluded_entries.append(f"sitemap.xml.gz - {pattern_path}")
|
||||||
|
return True
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
@ -435,31 +460,22 @@ def _load_yaml(abs_src_path: str):
|
|||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
# Load info.gitignore, ignore any empty lines or # comments
|
|
||||||
def _load_exclusion_patterns(path: str = None):
|
|
||||||
if path is None:
|
|
||||||
path = os.path.dirname(os.path.abspath(__file__))
|
|
||||||
path = os.path.join(path, "info.gitignore")
|
|
||||||
|
|
||||||
with open(path, encoding = "utf-8") as file:
|
|
||||||
lines = map(str.strip, file.readlines())
|
|
||||||
|
|
||||||
return [line for line in lines if line and not line.startswith("#")]
|
|
||||||
|
|
||||||
# Get a normalized POSIX path for the pattern matching with removed current
|
# Get a normalized POSIX path for the pattern matching with removed current
|
||||||
# working directory prefix. Directory paths end with a '/' to allow more control
|
# working directory prefix. Directory paths end with a '/' to allow more control
|
||||||
# in the pattern creation for files and directories.
|
# in the pattern creation for files and directories. The patterns are matched
|
||||||
def _resolve_pattern(abspath: str):
|
# using the search function, so they are prefixed with ^ for specificity.
|
||||||
path = abspath.replace(os.getcwd(), "", 1).replace(os.sep, "/")
|
def _resolve_pattern(abspath: str, return_path: bool = False):
|
||||||
|
path = abspath.replace(os.getcwd(), "", 1)
|
||||||
|
path = path.replace(os.sep, "/").rstrip("/")
|
||||||
|
|
||||||
if not path:
|
if not path:
|
||||||
return "/"
|
return "/"
|
||||||
|
|
||||||
# Check abspath, as the file needs to exist
|
# Check abspath, as the file needs to exist
|
||||||
if not os.path.isfile(abspath):
|
if not os.path.isfile(abspath):
|
||||||
return path.rstrip("/") + "/"
|
path = path + "/"
|
||||||
|
|
||||||
return path
|
return path if return_path else f"^{path}"
|
||||||
|
|
||||||
# Get project configuration with resolved absolute paths for validation
|
# Get project configuration with resolved absolute paths for validation
|
||||||
def _get_project_config(project_config_file: str):
|
def _get_project_config(project_config_file: str):
|
||||||
|
@ -149,7 +149,7 @@ const assets$ = concat(
|
|||||||
})),
|
})),
|
||||||
|
|
||||||
/* Copy images and configurations */
|
/* Copy images and configurations */
|
||||||
...["**/*.{jpg,png,svg,yml,gitignore}"]
|
...["**/*.{jpg,png,svg,yml}"]
|
||||||
.map(pattern => copyAll(pattern, {
|
.map(pattern => copyAll(pattern, {
|
||||||
from: "src",
|
from: "src",
|
||||||
to: base
|
to: base
|
||||||
|
Loading…
Reference in New Issue
Block a user