mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Ensure user-supplied files are always copied
This commit is contained in:
parent
2f9a79c3b2
commit
0897b5948b
@ -13,6 +13,7 @@ import time
|
||||
import types
|
||||
import warnings
|
||||
from os import path
|
||||
from pathlib import Path
|
||||
from typing import IO, TYPE_CHECKING, Any
|
||||
from urllib.parse import quote
|
||||
|
||||
@ -756,17 +757,20 @@ class StandaloneHTMLBuilder(Builder):
|
||||
def copy_image_files(self) -> None:
|
||||
if self.images:
|
||||
stringify_func = ImageAdapter(self.app.env).get_original_image_uri
|
||||
ensuredir(path.join(self.outdir, self.imagedir))
|
||||
ensuredir(self.outdir / self.imagedir)
|
||||
for src in status_iterator(self.images, __('copying images... '), "brown",
|
||||
len(self.images), self.app.verbosity,
|
||||
stringify_func=stringify_func):
|
||||
dest = self.images[src]
|
||||
try:
|
||||
copyfile(path.join(self.srcdir, src),
|
||||
path.join(self.outdir, self.imagedir, dest))
|
||||
copyfile(
|
||||
self.srcdir / src,
|
||||
self.outdir / self.imagedir / dest,
|
||||
force=True,
|
||||
)
|
||||
except Exception as err:
|
||||
logger.warning(__('cannot copy image file %r: %s'),
|
||||
path.join(self.srcdir, src), err)
|
||||
self.srcdir / src, err)
|
||||
|
||||
def copy_download_files(self) -> None:
|
||||
def to_relpath(f: str) -> str:
|
||||
@ -774,17 +778,17 @@ class StandaloneHTMLBuilder(Builder):
|
||||
|
||||
# copy downloadable files
|
||||
if self.env.dlfiles:
|
||||
ensuredir(path.join(self.outdir, '_downloads'))
|
||||
ensuredir(self.outdir / '_downloads')
|
||||
for src in status_iterator(self.env.dlfiles, __('copying downloadable files... '),
|
||||
"brown", len(self.env.dlfiles), self.app.verbosity,
|
||||
stringify_func=to_relpath):
|
||||
try:
|
||||
dest = path.join(self.outdir, '_downloads', self.env.dlfiles[src][1])
|
||||
ensuredir(path.dirname(dest))
|
||||
copyfile(path.join(self.srcdir, src), dest)
|
||||
dest = self.outdir / '_downloads' / self.env.dlfiles[src][1]
|
||||
ensuredir(dest.parent)
|
||||
copyfile(self.srcdir / src, dest, force=True)
|
||||
except OSError as err:
|
||||
logger.warning(__('cannot copy downloadable file %r: %s'),
|
||||
path.join(self.srcdir, src), err)
|
||||
self.srcdir / src, err)
|
||||
|
||||
def create_pygments_style_file(self) -> None:
|
||||
"""Create a style file for pygments."""
|
||||
@ -801,18 +805,30 @@ class StandaloneHTMLBuilder(Builder):
|
||||
"""Copy a JavaScript file for translations."""
|
||||
jsfile = self._get_translations_js()
|
||||
if jsfile:
|
||||
copyfile(jsfile, path.join(self.outdir, '_static', 'translations.js'))
|
||||
copyfile(
|
||||
jsfile,
|
||||
self.outdir / '_static' / 'translations.js',
|
||||
force=True,
|
||||
)
|
||||
|
||||
def copy_stemmer_js(self) -> None:
|
||||
"""Copy a JavaScript file for stemmer."""
|
||||
if self.indexer is not None:
|
||||
if hasattr(self.indexer, 'get_js_stemmer_rawcodes'):
|
||||
for jsfile in self.indexer.get_js_stemmer_rawcodes():
|
||||
copyfile(jsfile, path.join(self.outdir, '_static', path.basename(jsfile)))
|
||||
js_path = Path(jsfile)
|
||||
copyfile(
|
||||
js_path,
|
||||
self.outdir / '_static' / js_path.name,
|
||||
force=True,
|
||||
)
|
||||
else:
|
||||
if js_stemmer_rawcode := self.indexer.get_js_stemmer_rawcode():
|
||||
copyfile(js_stemmer_rawcode,
|
||||
path.join(self.outdir, '_static', '_stemmer.js'))
|
||||
copyfile(
|
||||
js_stemmer_rawcode,
|
||||
self.outdir / '_static' / '_stemmer.js',
|
||||
force=True,
|
||||
)
|
||||
|
||||
def copy_theme_static_files(self, context: dict[str, Any]) -> None:
|
||||
def onerror(filename: str, error: Exception) -> None:
|
||||
@ -821,10 +837,13 @@ class StandaloneHTMLBuilder(Builder):
|
||||
|
||||
if self.theme:
|
||||
for entry in reversed(self.theme.get_theme_dirs()):
|
||||
copy_asset(path.join(entry, 'static'),
|
||||
path.join(self.outdir, '_static'),
|
||||
excluded=DOTFILES, context=context,
|
||||
renderer=self.templates, onerror=onerror)
|
||||
copy_asset(
|
||||
Path(entry) / 'static',
|
||||
self.outdir / '_static',
|
||||
excluded=DOTFILES, context=context,
|
||||
renderer=self.templates, onerror=onerror,
|
||||
force=True,
|
||||
)
|
||||
|
||||
def copy_html_static_files(self, context: dict[str, Any]) -> None:
|
||||
def onerror(filename: str, error: Exception) -> None:
|
||||
@ -833,24 +852,36 @@ class StandaloneHTMLBuilder(Builder):
|
||||
|
||||
excluded = Matcher([*self.config.exclude_patterns, '**/.*'])
|
||||
for entry in self.config.html_static_path:
|
||||
copy_asset(path.join(self.confdir, entry),
|
||||
path.join(self.outdir, '_static'),
|
||||
excluded, context=context, renderer=self.templates, onerror=onerror)
|
||||
copy_asset(
|
||||
self.confdir / entry,
|
||||
self.outdir / '_static',
|
||||
excluded=excluded, context=context,
|
||||
renderer=self.templates, onerror=onerror,
|
||||
force=True,
|
||||
)
|
||||
|
||||
def copy_html_logo(self) -> None:
|
||||
if self.config.html_logo and not isurl(self.config.html_logo):
|
||||
copy_asset(path.join(self.confdir, self.config.html_logo),
|
||||
path.join(self.outdir, '_static'))
|
||||
source_path = self.confdir / self.config.html_logo
|
||||
copyfile(
|
||||
source_path,
|
||||
self.outdir / '_static' / source_path.name,
|
||||
force=True,
|
||||
)
|
||||
|
||||
def copy_html_favicon(self) -> None:
|
||||
if self.config.html_favicon and not isurl(self.config.html_favicon):
|
||||
copy_asset(path.join(self.confdir, self.config.html_favicon),
|
||||
path.join(self.outdir, '_static'))
|
||||
source_path = self.confdir / self.config.html_favicon
|
||||
copyfile(
|
||||
source_path,
|
||||
self.outdir / '_static' / source_path.name,
|
||||
force=True,
|
||||
)
|
||||
|
||||
def copy_static_files(self) -> None:
|
||||
try:
|
||||
with progress_message(__('copying static files')):
|
||||
ensuredir(path.join(self.outdir, '_static'))
|
||||
ensuredir(self.outdir / '_static')
|
||||
|
||||
# prepare context for templates
|
||||
context = self.globalcontext.copy()
|
||||
@ -873,8 +904,12 @@ class StandaloneHTMLBuilder(Builder):
|
||||
with progress_message(__('copying extra files')):
|
||||
excluded = Matcher(self.config.exclude_patterns)
|
||||
for extra_path in self.config.html_extra_path:
|
||||
entry = path.join(self.confdir, extra_path)
|
||||
copy_asset(entry, self.outdir, excluded)
|
||||
copy_asset(
|
||||
self.confdir / extra_path,
|
||||
self.outdir,
|
||||
excluded=excluded,
|
||||
force=True,
|
||||
)
|
||||
except OSError as err:
|
||||
logger.warning(__('cannot copy extra file %r'), err)
|
||||
|
||||
|
@ -96,6 +96,8 @@ def copy_asset(source: str | os.PathLike[str], destination: str | os.PathLike[st
|
||||
On copying, it expands the template variables if context argument is given and
|
||||
the asset is a template file.
|
||||
|
||||
Use ``copy_asset_file`` instead to copy a single file.
|
||||
|
||||
:param source: The path to source file or directory
|
||||
:param destination: The path to destination directory
|
||||
:param excluded: The matcher to determine the given path should be copied or not
|
||||
|
Loading…
Reference in New Issue
Block a user