Skip to content

Commit

Permalink
V0.2 housekeeping (#8)
Browse files Browse the repository at this point in the history
* Add changelog

* Bump version number

* Update readme

* Update docstrings

* Add test for `href` and `static-file`

* Update readme
  • Loading branch information
tcmetzger authored Nov 16, 2021
1 parent 188f20c commit e8613e0
Show file tree
Hide file tree
Showing 11 changed files with 116 additions and 29 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
2021-11-15 0.2:
------------------
* enhancements:
- Add support for relative files (#2)
- Add basic tests (#3)
- Test on multiple os (#5)

2021-10-03 0.1:
------------------
Initial release
52 changes: 31 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,20 @@ pip install sphinx-favicon
## Usage

After installing sphinx-favicon, you can configure the extension directly in
`conf.py`.
`conf.py` (see [Configuration](https://www.sphinx-doc.org/en/master/usage/configuration.html)
in the Sphinx documentation for more information about this file).

There are two ways to include favicon files in your configuration:

If you are using **local static files**, make sure you place them inside a
directory listed in [Sphinx' `html_static_path`](https://www.sphinx-doc.org/en/master/usage/configuration.html?highlight=static#confval-html_static_path).
Alternatively you can also use **absolute URLs**.
* Either use an **absolute URL** for a favicon file (beginning with `http://` or
`https://`). If you use an absolute URL, use the `"href"` parameter. See below
for examples.
* Or use a **local static file** as a favicon. Make sure you place your local
static favicon file(s) inside a directory listed in [Sphinx' `html_static_path`](https://www.sphinx-doc.org/en/master/usage/configuration.html?highlight=static#confval-html_static_path). If you use a relative path, use the `"static-file"` parameter. See below for
examples.

First, add `"sphinx-favicon"` to the list of extensions:
To configure sphinx-favicon, first add `"sphinx-favicon"` to the list of
extensions:

```python
extensions = [
Expand All @@ -52,19 +59,20 @@ or a custom extension like [`"apple-touch-icon"`](https://developer.apple.com/li
* ``sizes``: a value for the [favicon's ``sizes`` attribute](https://html.spec.whatwg.org/multipage/semantics.html#attr-link-sizes)
* ``href``: the **absolute URL** to the favicon's image file (not required if you use the ``static-file`` parameter, see below)
* ``type``: a value specifying the [favicon's MIME type](https://html.spec.whatwg.org/multipage/semantics.html#attr-link-type)
* ``static-file``: **local static file** corresponding to your icon's image.
* ``static-file``: the **local static file** corresponding to your icon's image.
Please notice this path should be relative to a directory listed in
[Sphinx' `html_static_path`](https://www.sphinx-doc.org/en/master/usage/configuration.html?highlight=static#confval-html_static_path).
[Sphinx' `html_static_path`](https://www.sphinx-doc.org/en/master/usage/configuration.html?highlight=static#confval-html_static_path) (usually `_static`). If you define both
``static-file`` and ``href``, the value for ``href`` will be ignored.

For example:

```python
html_static_path = ["assets"]
html_static_path = ["_static"] # html_static_path is required if you use the "static-file" parameter

favicons = [
{
"rel": "icon",
"static-file": "icon.svg", # => `assets/icon.svg` exists
"static-file": "icon.svg", # => use `_static/icon.svg`
"type": "image/svg+xml",
},
{
Expand All @@ -89,7 +97,7 @@ favicons = [
```

Based on this configuration, Sphinx will include the following favicon
information in the `<head>` of every HTML file:
information in the HTML `<head>` element:

```html
<link rel="icon" href="_static/icon.svg" type="image/svg+xml">
Expand All @@ -98,8 +106,11 @@ information in the `<head>` of every HTML file:
<link rel="apple-touch-icon" href="https://secure.example.com/favicon/apple-touch-icon-180x180.png" sizes="180x180" type="image/png">
```

To make things easier for you, sphinx-favicon can also add some metadata to each
favicon's `<link>` element automatically:
Note that the relative path to the favicon's image file in the static directory
will be adjusted according to each html file's location.

To make things easier for you, sphinx-favicon can also add *some* metadata to
each favicon's `<link>` element automatically:

* If you don't provide the `"rel"` argument, sphinx-favicon automatically adds
`rel="icon"`.
Expand All @@ -114,10 +125,10 @@ Therefore, the following simplified configuration generates the exact same
HTML result as above:

```python
html_static_path = ["assets"]
html_static_path = ["_static"]

favicons = [
{"static-file": "icon.svg"}, # => `assets/icon.svg` exists
{"static-file": "icon.svg"}, # => use `_static/icon.svg`
{
"sizes": "16x16",
"href": "https://secure.example.com/favicon/favicon-16x16.png",
Expand Down Expand Up @@ -160,17 +171,17 @@ The quickest way to add favicons is just adding a list of favicon URLs to
`conf.py`.

```python
html_static_path = ["assets"]
html_static_path = ["_static"]
favicons = [
"icon.svg", # => `assets/icon.svg`
"icon.svg", # => `_static_/icon.svg`
"https://secure.example.com/favicon/favicon-16x16.gif",
"https://secure.example.com/favicon/favicon-32x32.png",
"https://secure.example.com/favicon/apple-touch-icon-180x180.png",
]
```

Based on this configuration, Sphinx will include the following favicon
information in the `<head>` of every HTML file:
information in the HTML `<head>` element:

```html
<link rel="icon" href="_static/icon.svg" type="image/svg+xml">
Expand All @@ -179,7 +190,7 @@ information in the `<head>` of every HTML file:
<link rel="icon" href="https://secure.example.com/favicon/apple-touch-icon-180x180.png" type="image/png">
```

Please notice that if your URLs don't start with `https://`, `http://` or `/`,
Please note that if your URLs don't start with `https://`, `http://` or `/`,
they will be considered a static file inside a directory listed in
[Sphinx' `html_static_path`](https://www.sphinx-doc.org/en/master/usage/configuration.html?highlight=static#confval-html_static_path).

Expand All @@ -189,6 +200,5 @@ To contribute to this extension, please open an issue or make a pull request to
the repository on GitHub.

Additional dependencies for development are listed in the file
`dev-requirements.txt` in the repository.
Tests can be run with ``pytest -vv``.
All Python code should be formatted with [Black](https://github.com/psf/black).
`dev-requirements.txt` in the repository. Use ``pytest -vv`` to run tests. All
Python code should be formatted with [Black](https://github.com/psf/black).
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[metadata]
name = sphinx-favicon
version = 0.1
version = 0.2
description = Sphinx Extension adding support for custom favicons
long_description = file: README.md
long_description_content_type = text/markdown; charset=UTF-8
Expand Down
12 changes: 8 additions & 4 deletions sphinx-favicon/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def generate_meta(favicon: Dict[str, str]) -> str:
- If no ``size`` attribute is provided, ``size`` will be omitted
- If no favicon MIME type is provided, the value for ``type`` will be
based on the favicon's file name extension (for BMP, GIF, ICO, JPG, JPEG,
SVG, or PNG files).
SVG, or PNG files)
Args:
favicon (Dict[str, str]): Favicon data
Expand Down Expand Up @@ -66,12 +66,16 @@ def generate_meta(favicon: Dict[str, str]) -> str:


def _static_to_href(pathto: Callable, favicon: Dict[str, str]) -> Dict[str, str]:
"""Return a modified version of the icon attributes replacing ``static-file``
with the correct ``href``.
"""If a ``static-file`` is provided, returns a modified version of the icon
attributes replacing ``static-file`` with the correct ``href``.
If both ``static-file`` and ``href`` are provided, ``href`` will be ignored.
"""
if FILE_FIELD in favicon:
attrs = favicon.copy()
attrs["href"] = pathto(f"_static/{attrs.pop(FILE_FIELD)}", resource=True)
attrs["href"] = pathto(
f"{OUTPUT_STATIC_DIR}/{attrs.pop(FILE_FIELD)}", resource=True
)
return attrs
return favicon

Expand Down
3 changes: 0 additions & 3 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,6 @@ def link_tags(content):
@pytest.fixture()
def favicon_tags(content):
return _favicon_tags(content)
# return [
# tag for tag in _link_tags(content) if tag.get("type", "").startswith("image")
# ]


@pytest.fixture()
Expand Down
20 changes: 20 additions & 0 deletions tests/roots/test-href_and_static/conf.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
extensions = ["sphinx-favicon"]

master_doc = "index"
exclude_patterns = ["_build"]

html_theme = "basic"
html_static_path = ["gfx"]

favicons = [
{
"sizes": "32x32",
"static-file": "square.svg",
"href": "https://secure.example.com/favicon/favicon-32x32.png",
},
{
"sizes": "128x128",
"static-file": "nested/triangle.svg",
"href": "https://secure.example.com/favicon/apple-touch-icon-180x180.png",
},
]
5 changes: 5 additions & 0 deletions tests/roots/test-href_and_static/gfx/nested/triangle.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions tests/roots/test-href_and_static/gfx/square.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions tests/roots/test-href_and_static/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Contents
--------

.. toctree::

nested/page
5 changes: 5 additions & 0 deletions tests/roots/test-href_and_static/nested/page.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
===========
Nested Page
===========

Nothing to see here...
26 changes: 26 additions & 0 deletions tests/test_options.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,31 @@ def test_list_of_urls(favicon_tags):
@pytest.mark.sphinx("html", testroot="static_files")
def test_static_files(app, favicon_tags, favicon_tags_for_nested):

# this test should have 2 favicons
assert len(favicon_tags) == 2

# all favicons should have rel, href, type, and sizes attributes
for favicon_tag in chain(favicon_tags, favicon_tags_for_nested):
assert favicon_tag["rel"] == ["icon"]
assert "_static" in favicon_tag["href"]
assert favicon_tag["type"] == "image/svg+xml"
assert favicon_tag["sizes"]
assert "static-file" not in favicon_tag

for favicon_tag in favicon_tags:
assert favicon_tag["href"].startswith("_static")

for favicon_tag in favicon_tags_for_nested:
assert favicon_tag["href"].startswith("../_static")

static = Path(app.outdir, "_static")
assert (static / "square.svg").exists()
assert (static / "nested/triangle.svg").exists()


@pytest.mark.sphinx("html", testroot="href_and_static")
def test_href_and_static(app, favicon_tags, favicon_tags_for_nested):

# this test should have 3 favicons
assert len(favicon_tags) == 2

Expand All @@ -108,6 +133,7 @@ def test_static_files(app, favicon_tags, favicon_tags_for_nested):
for favicon_tag in favicon_tags_for_nested:
assert favicon_tag["href"].startswith("../_static")

# favicons should use relative paths, ignoring paths provided with `href`
static = Path(app.outdir, "_static")
assert (static / "square.svg").exists()
assert (static / "nested/triangle.svg").exists()

0 comments on commit e8613e0

Please sign in to comment.