diff --git a/doc/config.rst b/doc/config.rst index 24334f363..e8bf87177 100644 --- a/doc/config.rst +++ b/doc/config.rst @@ -509,10 +509,11 @@ that use Sphinx' HTMLWriter class. .. confval:: html_static_path - A list of paths that contain custom static files (such as style sheets or - script files). Relative paths are taken as relative to the configuration - directory. They are copied to the output directory after the theme's static - files, so a file named :file:`default.css` will overwrite the theme's + A list of paths that contain custom static files (such as style + sheets or script files). Relative paths are taken as relative to + the configuration directory. They are copied to the output's + :file:`_static` directory after the theme's static files, so a file + named :file:`default.css` will overwrite the theme's :file:`default.css`. .. versionchanged:: 0.4 @@ -521,6 +522,19 @@ that use Sphinx' HTMLWriter class. .. versionchanged:: 1.0 The entries in :confval:`html_static_path` can now be single files. +.. confval:: html_extra_path + + A list of paths that contain extra files not directly related to + the documentation, such as :file:`robots.txt` or :file:`.htaccess`. + Relative paths are taken as relative to the configuration + directory. They are copied to the output directory. They will + overwrite any existing file of the same name. + + As these files are not meant to be built, they are automatically added to + :confval:`exclude_patterns`. + + .. versionadded:: 1.2 + .. confval:: html_last_updated_fmt If this is not the empty string, a 'Last updated on:' timestamp is inserted diff --git a/sphinx/builders/html.py b/sphinx/builders/html.py index ca8a4acdf..cd0200e4b 100644 --- a/sphinx/builders/html.py +++ b/sphinx/builders/html.py @@ -480,6 +480,7 @@ class StandaloneHTMLBuilder(Builder): self.copy_image_files() self.copy_download_files() self.copy_static_files() + self.copy_extra_files() self.write_buildinfo() # dump the search index @@ -607,6 +608,17 @@ class StandaloneHTMLBuilder(Builder): icontarget) self.info('done') + def copy_extra_files(self): + # copy html_extra_path files + self.info(bold('copying extra files... '), nonl=True) + extraentries = [path.join(self.confdir, epath) + for epath in self.config.html_extra_path] + for entry in extraentries: + if not path.exists(entry): + self.warn('html_extra_path entry %r does not exist' % entry) + continue + copy_static_entry(entry, self.outdir, self) + def write_buildinfo(self): # write build info file fp = open(path.join(self.outdir, '.buildinfo'), 'w') diff --git a/sphinx/config.py b/sphinx/config.py index a59012117..051b9eef5 100644 --- a/sphinx/config.py +++ b/sphinx/config.py @@ -86,6 +86,7 @@ class Config(object): html_logo = (None, 'html'), html_favicon = (None, 'html'), html_static_path = ([], 'html'), + html_extra_path = ([], 'html'), # the real default is locale-dependent html_last_updated_fmt = (None, 'html'), html_use_smartypants = (True, 'html'), diff --git a/sphinx/environment.py b/sphinx/environment.py index 35799bea2..3c9c830c1 100644 --- a/sphinx/environment.py +++ b/sphinx/environment.py @@ -335,6 +335,7 @@ class BuildEnvironment: """ matchers = compile_matchers( config.exclude_patterns[:] + + config.html_extra_path + config.exclude_trees + [d + config.source_suffix for d in config.unused_docs] + ['**/' + d for d in config.exclude_dirnames] + diff --git a/sphinx/quickstart.py b/sphinx/quickstart.py index 73926f82e..7124184e6 100644 --- a/sphinx/quickstart.py +++ b/sphinx/quickstart.py @@ -171,6 +171,11 @@ html_theme = 'default' # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['%(dot)sstatic'] +# Add any extra paths that contain custom files (such as robots.txt or +# .htaccess) here, relative to this directory. These files are copied +# directly to the root of the documentation. +#html_extra_path = [] + # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. #html_last_updated_fmt = '%%b %%d, %%Y' diff --git a/tests/root/conf.py b/tests/root/conf.py index 37b9127e7..8025ba33c 100644 --- a/tests/root/conf.py +++ b/tests/root/conf.py @@ -38,6 +38,7 @@ html_sidebars = {'**': 'customsb.html', 'contents': ['contentssb.html', 'localtoc.html'] } html_style = 'default.css' html_static_path = ['_static', 'templated.css_t'] +html_extra_path = ['robots.txt'] html_last_updated_fmt = '%b %d, %Y' html_context = {'hckey': 'hcval', 'hckey_co': 'wrong_hcval_co'} diff --git a/tests/root/robots.txt b/tests/root/robots.txt new file mode 100644 index 000000000..1b425ee0f --- /dev/null +++ b/tests/root/robots.txt @@ -0,0 +1,2 @@ +User-agent: * +Disallow: /cgi-bin/ diff --git a/tests/test_build_html.py b/tests/test_build_html.py index 73a4e3099..2a08ee92d 100644 --- a/tests/test_build_html.py +++ b/tests/test_build_html.py @@ -320,6 +320,9 @@ def check_static_entries(outdir): # a file from _static, but matches exclude_patterns assert not (staticdir / 'excluded.css').exists() +def check_extra_entries(outdir): + assert (outdir / 'robots.txt').isfile() + @gen_with_app(buildername='html', warning=html_warnfile, cleanenv=True, confoverrides={'html_context.hckey_co': 'hcval_co'}, tags=['testtag']) @@ -345,6 +348,7 @@ def test_html(app): yield check_xpath, etree, fname, path, check check_static_entries(app.builder.outdir) + check_extra_entries(app.builder.outdir) @with_app(buildername='html', srcdir='(empty)', confoverrides={'html_sidebars': {'*': ['globaltoc.html']}},