pax_global_header00006660000000000000000000000064144002275460014516gustar00rootroot0000000000000052 comment=e7380e08d4898136408b9f175b7cd62781a4cb5b sphinx-favicon-1.0.1/000077500000000000000000000000001440022754600144515ustar00rootroot00000000000000sphinx-favicon-1.0.1/.github/000077500000000000000000000000001440022754600160115ustar00rootroot00000000000000sphinx-favicon-1.0.1/.github/workflows/000077500000000000000000000000001440022754600200465ustar00rootroot00000000000000sphinx-favicon-1.0.1/.github/workflows/basic-ci.yml000066400000000000000000000021531440022754600222440ustar00rootroot00000000000000name: Python lint and test on: push: branches: [ main ] pull_request: branches: [ main ] jobs: format: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: actions/setup-python@v4 with: python-version: '3.8' - uses: pre-commit/action@v3.0.0 test: runs-on: ${{ matrix.os }} strategy: matrix: os: [ubuntu-latest] python-version: ['3.7', '3.8', '3.9', '3.10'] include: - os: macos-latest python-version: '3.9' - os: windows-latest python-version: '3.9' steps: - uses: actions/checkout@v3 - name: Setup Python uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} - name: Install dependencies run: pip install .[test] - name: MyPy checks run: | pip install mypy mypy --ignore-missing-imports --install-types --non-interactive sphinx_favicon - name: Run Tests for ${{ matrix.python-version }} run: pytest --color=yes --cov --cov-report=xml tests sphinx-favicon-1.0.1/.gitignore000066400000000000000000000034321440022754600164430ustar00rootroot00000000000000# Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] *$py.class # C extensions *.so # Distribution / packaging .Python build/ develop-eggs/ dist/ downloads/ eggs/ .eggs/ lib/ lib64/ parts/ sdist/ var/ wheels/ pip-wheel-metadata/ share/python-wheels/ *.egg-info/ .installed.cfg *.egg MANIFEST # PyInstaller # Usually these files are written by a python script from a template # before PyInstaller builds the exe, so as to inject date/other infos into it. *.manifest *.spec # Installer logs pip-log.txt pip-delete-this-directory.txt # Unit test / coverage reports htmlcov/ .tox/ .nox/ .coverage .coverage.* .cache nosetests.xml coverage.xml *.cover *.py,cover .hypothesis/ .pytest_cache/ # Translations *.mo *.pot # Django stuff: *.log local_settings.py db.sqlite3 db.sqlite3-journal # Flask stuff: instance/ .webassets-cache # Scrapy stuff: .scrapy # Sphinx documentation docs/_build/ # PyBuilder target/ # Jupyter Notebook .ipynb_checkpoints # IPython profile_default/ ipython_config.py # pyenv .python-version # pipenv # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. # However, in case of collaboration, if having platform-specific dependencies or dependencies # having no cross-platform support, pipenv may install dependencies that don't work, or not # install all needed dependencies. #Pipfile.lock # PEP 582; used by e.g. github.com/David-OConnor/pyflow __pypackages__/ # Celery stuff celerybeat-schedule celerybeat.pid # SageMath parsed files *.sage.py # Environments .env .venv env/ venv/ ENV/ env.bak/ venv.bak/ # Spyder project settings .spyderproject .spyproject # Rope project settings .ropeproject # mkdocs documentation /site # mypy .mypy_cache/ .dmypy.json dmypy.json # Pyre type checker .pyre/ # VSCode .vscode/ sphinx-favicon-1.0.1/.pre-commit-config.yaml000066400000000000000000000004331440022754600207320ustar00rootroot00000000000000repos: - repo: "https://github.com/psf/black" rev: 22.3.0 hooks: - id: black stages: [commit] - repo: https://github.com/charliermarsh/ruff-pre-commit rev: "v0.0.217" hooks: - id: ruff stages: [commit] args: ["--force-exclude"]sphinx-favicon-1.0.1/.readthedocs.yml000066400000000000000000000007661440022754600175500ustar00rootroot00000000000000# .readthedocs.yaml # Read the Docs configuration file # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details # Required version: 2 # Set the version of Python and other tools you might need build: os: ubuntu-22.04 tools: python: "3.10" # Build documentation in the docs/ directory with Sphinx sphinx: configuration: docs/source/conf.py # Optionally declare the Python requirements required to build your docs python: install: - method: pip path: .[doc] sphinx-favicon-1.0.1/CHANGELOG000066400000000000000000000075401440022754600156710ustar00rootroot00000000000000# 2023-03-02, Release 1.0.1 This is a bugfix for Release 1.0 and contains only one change. ## What's Changed * fix: don't use relative path to _static output folder by @12rambau in https://github.com/tcmetzger/sphinx-favicon/pull/46 **Full Changelog**: https://github.com/tcmetzger/sphinx-favicon/compare/v1.0...v1.1 # 2023-03-01, Release 1.0 1.0 is the first major release of Sphinx Favicon. It 1.0 brings one **breaking change**: To better conform with Python standards, the extension module name was changed from `sphinx-favicon` to `sphinx_favicon`. If you have used previous version of this extension, you need to update your `conf.py` file to use `sphinx_favicon` (instead of the old name, `sphinx-favicon`) Otherwise, your existing configuration should work without any changes. The 1.0 release contains lots of updates and new features, including [automatic detection of favicon pixel dimensions] (https://sphinx-favicon.readthedocs.io/en/latest/configuration.html#sizes-the-image-size), [basic support for additional favicon formats](https://sphinx-favicon.readthedocs.io/en/latest/configuration.html#name-specific-to-msapp-icons), and a new, [Sphinx-based documentation site at https://sphinx-favicon.readthedocs.io](https://sphinx-favicon.readthedocs.io). ## What's Changed * change folder name by @12rambau in https://github.com/tcmetzger/sphinx-favicon/pull/13 * Use pre-commit to enforce linting by @12rambau in https://github.com/tcmetzger/sphinx-favicon/pull/14 * Update ci by @tcmetzger in https://github.com/tcmetzger/sphinx-favicon/pull/17 * Add sphinx docs by @tcmetzger in https://github.com/tcmetzger/sphinx-favicon/pull/18 * Update docs config by @tcmetzger in https://github.com/tcmetzger/sphinx-favicon/pull/19 * Mypy by @12rambau in https://github.com/tcmetzger/sphinx-favicon/pull/20 * authorize any parameter in the favicon dict by @12rambau in https://github.com/tcmetzger/sphinx-favicon/pull/24 * Delete .gitattributes by @12rambau in https://github.com/tcmetzger/sphinx-favicon/pull/29 * update documentation by @12rambau in https://github.com/tcmetzger/sphinx-favicon/pull/27 * refactor: Simplify favicon parsing by @12rambau in https://github.com/tcmetzger/sphinx-favicon/pull/30 * edit announcement link by @12rambau in https://github.com/tcmetzger/sphinx-favicon/pull/31 * Meta by @12rambau in https://github.com/tcmetzger/sphinx-favicon/pull/25 * compute size automatically if not set by @12rambau in https://github.com/tcmetzger/sphinx-favicon/pull/26 * resize mstile to 150x150 by @tcmetzger in https://github.com/tcmetzger/sphinx-favicon/pull/33 * use only pyproject.toml for build by @12rambau in https://github.com/tcmetzger/sphinx-favicon/pull/34 * refactor documentation by @12rambau in https://github.com/tcmetzger/sphinx-favicon/pull/35 * Fix typo by @tcmetzger in https://github.com/tcmetzger/sphinx-favicon/pull/36 * Update tests by @tcmetzger in https://github.com/tcmetzger/sphinx-favicon/pull/37 * fixed `documentation` and `contribution` broken links by @adityakode in https://github.com/tcmetzger/sphinx-favicon/pull/40 * Docs updates by @tcmetzger in https://github.com/tcmetzger/sphinx-favicon/pull/41 * fix: remove download url by @12rambau in https://github.com/tcmetzger/sphinx-favicon/pull/42 * Update docs for release by @tcmetzger in https://github.com/tcmetzger/sphinx-favicon/pull/43 ## New Contributors * @12rambau made their first contribution in https://github.com/tcmetzger/sphinx-favicon/pull/13 * @adityakode made their first contribution in https://github.com/tcmetzger/sphinx-favicon/pull/40 **Full Changelog**: https://github.com/tcmetzger/sphinx-favicon/compare/v0.2...v1.0 # 2021-11-15, Release 0.2 - Add support for relative files (#2) - Add basic tests (#3) - Test on multiple os (#5) ## New Contributors * @abravalheri made their first contribution in https://github.com/tcmetzger/sphinx-favicon/pull/2 # 2021-10-03, Release 0.1 Initial release sphinx-favicon-1.0.1/LICENSE000066400000000000000000000020671440022754600154630ustar00rootroot00000000000000MIT License Copyright (c) 2021 Timo Cornelius Metzger Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. sphinx-favicon-1.0.1/README.md000066400000000000000000000066231440022754600157370ustar00rootroot00000000000000# Sphinx Favicon [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Black badge](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black) [![PyPI](https://img.shields.io/pypi/v/sphinx-favicon?logo=python&logoColor=white)](https://pypi.org/project/sphinx-favicon/) ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/sphinx-favicon?color=orange&logo=python&logoColor=white) ![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/tcmetzger/sphinx-favicon/basic-ci.yml?logo=github&logoColor=white) ![Read the Docs (version)](https://img.shields.io/readthedocs/sphinx-favicon/latest?logo=readthedocs&logoColor=white) > **Note: Updating from Version 0.2 to Version 1.0** > > Between v0.2 and v1.0, the module name of the extension changed to better conform with Python standards. Please update the name used in the extension list of your `conf.py` from `sphinx-favicon` to `sphinx_favicon`! **A Sphinx extension to add custom favicons** With Sphinx Favicon, you can add custom favicons to your Sphinx html documentation quickly and easily. You can define favicons directly in your `conf.py`, with different `rel` attributes such as [`"icon"`](https://html.spec.whatwg.org/multipage/links.html#rel-icon) or [`"apple-touch-icon"`](https://developer.apple.com/library/archive/documentation/AppleApplications/Reference/SafariWebContent/ConfiguringWebApplications/ConfiguringWebApplications.html) and any favicon size. The Sphinx Favicon extension gives you more flexibility than the [standard `favicon.ico` supported by Sphinx](https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-html_favicon). It provides a quick and easy way to add the most important favicon formats for different browsers and devices. ## Installation Use ``pip`` to install Sphinx Favicon in your environment: ```sh pip install sphinx-favicon ``` ## Usage After installing **sphinx-favicon**, add it to your `conf.py` extension list: ```python extensions = ["sphinx_favicon"] ``` Then configure the favicon links using the `favicons` parameter (`html_static_path` is mandatory if you use relative path): ```python html_static_path = ["_static"] favicons = [ {"href": "icon.svg"}, # => use `_static/icon.svg` {"href": "https://secure.example.com/favicon/favicon-16x16.png"}, {"href": "https://secure.example.com/favicon/favicon-32x32.png"}, { "rel": "apple-touch-icon", "href": "https://secure.example.com/favicon/apple-touch-icon-180x180.png", }, ] ``` Based on this configuration, Sphinx will include the following favicon information in the HTML `` element: ```html ``` For more details and more advanced usage, please see the [documentation](https://sphinx-favicon.readthedocs.io). ## Contribution Contributions of any kind are welcome. Please see the [contribution](https://sphinx-favicon.readthedocs.io/en/latest/contribute.html) section of our documentation for more information. sphinx-favicon-1.0.1/docs/000077500000000000000000000000001440022754600154015ustar00rootroot00000000000000sphinx-favicon-1.0.1/docs/source/000077500000000000000000000000001440022754600167015ustar00rootroot00000000000000sphinx-favicon-1.0.1/docs/source/_static/000077500000000000000000000000001440022754600203275ustar00rootroot00000000000000sphinx-favicon-1.0.1/docs/source/_static/android-chrome-192x192.png000066400000000000000000000143331440022754600246710ustar00rootroot00000000000000PNG  IHDRդgAMA a cHRMz&u0`:pQ<bKGD̿tIME o/IDATxit\u_c!vpp'(hR(,Vƞё,;938:yb,(3[*MSwjp1MZ4k|*zթ=[ejtp'FtqAjQ&5y曡L,6t^14p1;錓NhlW*l+08d&S;&[^G"|ҟl뀝vܰ:_h*ͷLY8DipSg,J0+ S}ЫWl snZdY4t!M=z4:n렞ϴxˊW:KXR5,nW42comw8l>uZlf _MF;as,r]?Jn{pn뭶R :p&g;\tJa:YU[*7`<޺+t)`APC%* VZJX(2w;Ce̓SXF/bEz ƐVӥ>RgVdfS :fFm8n^op֢.ca(N׽jWpnlSi92\ҭE sJQ=ag ;錋Ce3vv{9VmQ!mT,o0fe4;l^uq^3إ44, :kzףA&49hdZ@{pagS-n"LV<x~`"G'IXh0,%JTok6;q9o/FI"٪Vv=z7L ոZ+T(/wLhC=:>Ԉn d4Ws璿Z\J-bZ;NQ1d˒eU6Xeϱ >߀Vx.ZգM3dirddnۧ[Gf]!$Oy[fiG{Ib&h(ٲ2\7 JM#gk@~;ҮOߐf&zV)]gY,Wrn~} h^f*W9eVEQ@BTmrd$Gu}Zy35r%6n.L/Ux.ۭ"jH春PY.].9N5gaxB*=~+b-+(88$QFۆD.5%j(E~ƳvhM({\S 5=*Qƈ\M3A9)j~ $֡;4[1N;}2xy&M w)9ZW4"'M2qGtnGV)?(r眸P@&n]^a>;k b kkYO{2>uNv:y}Z%ŽH_y6sLKY7^OjiOi܍^J"'M2\}?ۥ#t]vu4ݜELVo̵aޠG|؂PbX4!CGs3AevSi86[>_l16f[fHa ~=tBN8K*o]^Ugc1U~GdZٮ6lDt^MLyjԸQjXӪA q?OZc;mH9Nl\$K,qmFGMYH1aunrRrLy51v-kjީ!Sgӣ꫚}81?+ōYmf fzv9D3Vy,da.8![{BCҨ:~+g#RiV[iAJ,EyV{0Z5]oy:;JpZipPhmlOxS&뭲ܤC8ǞD*nƥdpR˭Qn-:zslӔg*EץY +9 2߬OZ dt )2EzҦ^mkۓZ-v喛g:ZUӣGNpZvvRH)fr*R nfg5$sAj`Pk t5`@nk}x1 ģ7|d dj3@VvNKɟ@Eֺz)]Ҝ8g,)f"[|귬Wl҄>itx̣cr,"63ݭA vHYr4.(-Wri5l8$!!Ը͝(P=4/4Hƃ-YcBqv_{8EK&VXvJGCLDبb,F`&-d c ^GN6dfyjע9E.c. k BJLWiy(WX>w=(V:җ㊿3DNW1bNnqcG[M|L^o #8+>[l 87rDEw[(q q6DH 8+F'%)~(iT3qknOqv:iGKZaۓ5V%cx>POD&C8GD4q/MF>ݘ|B5|ޡ [W~sWnD\ @:5~G=С[@&cYn޸e7unAOu@>eF{1n]s2-}@{;_ kFX[x4OX-\KZ˘f9!nF}9cRH\WIX2=?,UրG$F{ O}Y =R'-1LďFmkM&"9ު6Jr7;̀,t\J@h== +Dz_hovP+yz&ns 6=G5YrE  _NfOx(12(aGx:ʸ!6d'UT#XcDIo1TkEG碌j{DfcCIrkvyϨ|;dR|$J6pGsa4Ԏ0bٝjqՇ]rwf"Z;q߳"!Gb,~F>.5/Ɲ᧽hnѣ:l%=|#r KPNm銈-PƅG#[GfŸӭ6]E.] Y$gbc1˜O$ZS2@|,LJƄQ{&IcxU1﵏ڜD vV=?u14aKLcbSNU;Q+KMv\c8]|Ο`hpWjC6NO4پe4uvk3, <m# ?CI8.Xes u(+ɐemN(> ӇNn~VO Bz qjЫIu\Gwxwnu12]a8P,^+ޫr2`xEDSk1}^) Tw Ŕ+YѸtTRJwnx',LBy/yB"¶7EgWx$nZܐ^{yUdj`-sh=<4Zs*HP< GRM9o_a[1@˟iPo;˛*)Z[mMU`R5,Ǐ=j]]/# /3br8\%fX_>Zth֭ǹ'GB+'G WXW=b魑Wd΁K-!6=a3,hn=`NnG$6) ϧ-NSZl nytn9?b)  + LH2׀;}6wcUIKwʋ0?N hpwHOhlFGS@fwȶC^t"y{Cf8\->O ;`:p,61ՠ-8j-yma|`T>ʠ4j֠VxJ{Wdci}I͵RU+V,˿J%t x~^:u5fīYG2mXV;]:Ji)W)ԫDH5:YS~LL?N#G&ڡ}_X}I%/nfޡwZ H/ H54^3%tEXtdate:create2023-01-14T08:32:02+00:00V%tEXtdate:modify2023-01-14T08:32:02+00:00GWzTXtRaw profile type iptcx qV((OIR# .c #K D4d#T ˀHJ.tB5IENDB`sphinx-favicon-1.0.1/docs/source/_static/apple-touch-icon.png000066400000000000000000000113531440022754600242070ustar00rootroot00000000000000PNG  IHDRYgAMA a cHRMz&u0`:pQ<bKGD̿tIME IDATxwpי.:AAU,ʒ%[VH-9,߸]|J<3v.Ğ8%]lE,XDJ콃 u ,ot }{?|a1BYB!:t:$A AC@B!:t:$z< l}C{ViκXX"%9V*FH }-hj b2Q15h[wo|O7n Җ2!9+#>E+Z-]C&(.1]U}w5uOY) 6(0[/_4ty9+nؚ*r m._k3:<4 eYU;2]yb63҉7S+v]h850Pn^-4eUyif hsKs%/O!;l]]]V|ne `|8B$J$J땡 f4/q9K݌q2~"9q~zs甛@h{ p [4gրR8Ci6fH1і1;Wfo*O$,2=_]eBLr?9<22kg{LF }vByO(۶H!/W߆K [_h?q܈gDž=A6'yR9MS8 :Vq#p184Ҋl9]mt}: )w?0V{)f>S -K HM p'[{wV;u͜ % wܕgo\d?xqga_d`N|2h%}uUܓ72דۗ˳4KM EXD@']/ŷ _]0MW//E3E˛Vp Ęc9X36~>rGIRBxCbzn}\` NN,ْ2_vQrޛ~=!礋ğ^+e0J\?ACB4]h'I`8Rxzz40K3K6o4ߛ%{do_7;7ۆo};4~uiCmmw,08OH.(ޘn}k.TS •iCrhwz m7ݾo2{!L %&EtmŔ> 6k׷LNeP=`P ֚&)k .--?O)HeTyevcۘщd;h2\lmuݓU؄x4L$ֵNengxtXƒϕ+2'`Kg0 rT$\Tatyju r-%{g*DmЉ=ik>$%=4۬sjN0 | }cZj"Y G'R~ʺ&Kq=buwx`zގG(@ΖޞN6SԳORmuc}]M͒ـTou jusnFm'Wّ zks w yBLV1VBᜎP(uώ v8\Amq@$OQrtP<-@6ݔoQxC8.^iݣz%ٯ B>E~DY:~r_ b*qK Ž{!QE~buç91SC 5S]M)mB WbFB!1œroxQ}Cv-:GWmIwQw;ٟ[H_ +BxIgSf=, Y+̦^uͤ I>ܥO.Yuf{΢3{HZפ dyZ&ZW)CŗoUw"} X0R)U1+gR5adu0 珪 jV>eY" ro)g!A3@CKy:ύ?M9,zsa&E-9N+T"+<VTuh T$2{d-1tg ͻ"m|H;UBᖳɣ6fcNc6|77m˻K Y>\@I5 53V  NS]mAIۨJf?8􈞼 \9|+&~r:);@#ݣ3[RJȆ/0THҥ>l ٹL JQ`L v [Mܥ s m=ozgv|uol"('wVP,}®_xKnmjn 6g + HP-%}bk?´,mR*^$yX zgULI΢&4 ^$y K@nb?/VVoXBȶ#JX[z!W^Z;m9a[zK$^b.W'o& AC@B!:t:$A AC@B!:bAN%tEXtdate:create2023-01-14T08:32:01+00:00%tEXtdate:modify2023-01-14T08:32:01+00:00wWzTXtRaw profile type iptcx qV((OIR# .c #K D4d#T ˀHJ.tB5IENDB`sphinx-favicon-1.0.1/docs/source/_static/custom.css000066400000000000000000000011101440022754600223440ustar00rootroot00000000000000/* add dollar sign in console code-block */ div.highlight-console pre span.go::before { /*-webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; -o-user-select: none; user-select: none;*/ content: "$"; margin-right: 10px; margin-left: 5px; } /* make the footer inline */ .footer-item { display: inline-block; } .footer-item:not(:last-child) { border-right: 1px solid var(--pst-color-text-base); margin-right: 0.5em; padding-right: 0.5em; } .card-header-gray { background-color: #c2c2c2 !important; font-weight: bold; } sphinx-favicon-1.0.1/docs/source/_static/favicon-16x16.png000066400000000000000000000011401440022754600232410ustar00rootroot00000000000000PNG  IHDR7gAMA a cHRMz&u0`:pQ<bKGD̿tIME IDAT(ϥO+o[ 9h+%Rr 7J8pAMInN"Mk1)}o<SUݲtʩKwFHiY^Ef eDgЫQeCZݸWP !׈u Nl[rjXVro>H)ytk̄69k4"+#)*%݅9Α8tfޮc-" 1sfm:@&<(IIIܸ6{ X!$g_S6~UwmTQ|AIUc%tEXtdate:create2023-01-14T08:32:01+00:00%tEXtdate:modify2023-01-14T08:32:01+00:00wWzTXtRaw profile type iptcx qV((OIR# .c #K D4d#T ˀHJ.tB5IENDB`sphinx-favicon-1.0.1/docs/source/_static/favicon-32x32.png000066400000000000000000000020051440022754600232360ustar00rootroot00000000000000PNG  IHDR sgAMA a cHRMz&u0`:pQ<bKGD̿tIME IDATHKletҖJBiVHE֍ Prc$i,47>F#AƍB1JJXl mǒ>Ls1ӆ*ntn=w;Ut{5lU\ˆ%jnmV7{%NysjglTyWݔ+BDpN8:ZȘpրQ)UHtM:۴+FE>v(ʴ1)6`ղE tJTv bf:X瀔yڢŒi)}(Q o .kQ-A\W~ %H˔ Quۭ4Wь N XYC9f0[, xSFkD:aI4}iSР3K{Pf3sڤ1WYPj\= Ȭ1q/k²1-#[7^.TnmҤݢ=V^6ӏsuFFnZHAWD N|kuA{Od$K`Ю|&t{}o? #:ra.ٸe -TW3nO^.O:)]sN_^6 ڵza_o`HJS2-i^0C˳xO֥Cy>-jH:WdYG̻ "bhɋ; &%tEXtdate:create2023-01-14T08:32:01+00:00%tEXtdate:modify2023-01-14T08:32:01+00:00wWzTXtRaw profile type iptcx qV((OIR# .c #K D4d#T ˀHJ.tB5IENDB`sphinx-favicon-1.0.1/docs/source/_static/favicon.ico000066400000000000000000000353561440022754600224640ustar00rootroot0000000000000000 %6  % h6(0` $Q DkzT( %b}CqW+hG:6<WX +E% L&?N:( ew  - 0l1#NiI! n#4]OZ#,"kEK(3{D+@Sclk_A *W C (W4 &RgG<MM3*;Z#x}E(I ,jAe* >A-W%`KXs: Im0D58Q~meLIZihB8PO9VXe?CmlB>hu}I4AcgC5I|2&TxxO6)('(3Lu3cQ%!;#>|A ,]]+  $B`{fG& ???~??Cxx( @ * 0q~C dkr~G2.=kH< BGY%> c&"'y35; <l6:6cn `` (Jj7S8l3P*g0 )\@*8\Ns9@Y`wrjy{mon*{nsvmhwmi !Du{SSl1Of- /Wh=?|<??<~<??(    0YNxt--W5A,'Xd gTx M_?/+b 0BpH~+DiJ<F +bO oCasphinx-favicon-1.0.1/docs/source/_static/mstile-150x150.png000066400000000000000000000075711440022754600232650ustar00rootroot00000000000000PNG  IHDR<qiCCPICC profile(}=HPOS";t:Yq*Bi+`IC(Y:8*? .N.R}IE{ Sͮq@,#xa`Qz2g}S7]gyYJdO$eaOoZ:}+K 9A$~ qX,ulSE(_ȹpVjuO`A[pV ,"DȨaXѮb"MqOK&9Q ٚ 7)_l# vfݶmy+6Om-r lmM.w']2$GE) }Z8}4-Qǻ{;oOk~?p$rSbKGDN pHYs B(xtIMEbP* uIDATxyU?f!悊( B"Fb4&Vbie$JHĭ\eHiY01(H+0b8eɌ}}8_U׳df^w90 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0`].a\v h>k3a## *czX EY ,UAJcj`EFe`1xf&〱*a@@BhKt3a* *A{bi]RZd LF ,ԲXp&>XЄU_5҉Z,y>܄C[Locn$v9c!w` KLmpi )I])ªFULcy)-ˁ17J `U(ؑkF-{M䌚ݴjj9pvkYe ͧ@Vp!'V@Z^+KI'bG|u:kǍHw:?onS}2*ql8^V%wlL`P_|^u9u塲1 vD[63}t09b쩥1v;)1Xn6lN. xB>5 x%PB]/0T7GkSOUu͕MՈ=;A6}Q)p~ouE:tpGmxx A}8MLT8':i_ 5^نX/~>\lEܼpB*\v;Ltn"[ e3p?T"_ۧwRI59 Tau#B2_E<2Zw%\#7a55{[KXHQF:盆7#N.MFNQ…Oe9R>0W.SJN|؅Gg]`0Iҫm4y5,o7$!&sD\+Ϻ]♤Be\Mtm:7יʌօ k3k[7o]?4}xmc*b}q\auVowrIϭIIz[̗+u@x_aw(ŠJo1Q>mݖi5&듵 ddEuxt|Z-Ŭ\rA}i?"z؋ ֧Kg69I!SԴ[<*I[I֓>?C"B?%x.)Q DOWz~6Iָx@;7sש?Q"rI:9~ H7y!:կD\}?mJ$4*I[FMMkP@`z$-!mU*n_E5XmLiHR19A_dNiq%ed9p T .T s,h)=OVՖK)$hpm;jC\Է8/VZE\Sh#\=0óʐ;b෺IPպHQ }S1ī#q=lVU]i2$54@.jY X on7Ļ-]>^Dr;;!ywq9Y^#4V4RlVCxHLN oPQEIW!ЫS#^?r\ $}W:$>cԛT N} qP?7CLnt 뢥~Cs W ٯ$MaBYIs(;Gw{ɕjWrTF]b~-FZH fCg$j32/p` r DM&9ʙ̚6J9Boxd8f,^8 twO6$K "2/ ǨV]qM;/ζ-!*x]r"T'n]gڥMI4ZHO݋W눱W*vhzQʈvՈ^Q(5tX!tSB,[%>"vPco%.~/dʁxmNegќR<kzUp'Qu=,vZ?]L6["=\=Q60}ڥ+ UݔjÊӟ'AK{aQ҅˔/sNuJ gTT .8]U`>HxšAQ2q_#m|IXΘNG,.m[ _3|%aZğG|Q4%al|߾wd7b'-1ުS2b^%!ݑDs#6ǭ~@ǎH-{#"\-y:M8eFD[L[9tƥp}`ZBnDOmw8b-pn7~= s#W\O$\_e}pc*bLE rޕ- l2 m,8ԅH/UT!ު>JF$73\ɨy.DgVb |CTy~.. !YVi \]yTT3g1.<@ip,Ƞr?k~AqA79 kC=^bǟaC3خ2WsLQ$PKG23a3֦j$]d!(=;,  'ʷ՝ E<+ޙ\3vIᴑ O< EwqGMu&?G:h P 'T|/sW&M#xӊ ?E$OgJs`%U}~֗3p<]I|w B8F}G =_&!! %Nbr&U&$Lj%rr_Cz _  ŷG$"~KV2YQb/%}ܽw%ѣf$ށąnC(;D!,X_RLѩ+kڦ (\.)`>Bղ Hu׀sE6fbbbj@<\"K}UI;h&d[c5bK4YW$1Ra5=}0I?UHt$$ ا ZnB=D`۲ֈbM,֒ Ɂ:OA=C9^ ح%v|7pMFbo52L]N0|0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ʣ/eIENDB`sphinx-favicon-1.0.1/docs/source/_static/safari-pinned-tab.svg000066400000000000000000000036761440022754600243500ustar00rootroot00000000000000 Created by potrace 1.14, written by Peter Selinger 2001-2017 sphinx-favicon-1.0.1/docs/source/conf.py000066400000000000000000000056631440022754600202120ustar00rootroot00000000000000"""Sphinx configuration file for sphinx-favicon documentation.""" # -- imports and read config --------------------------------------------------- import datetime as dt import pkg_resources version = pkg_resources.require("sphinx-favicon")[0].version year = dt.datetime.now().year # -- Project information ------------------------------------------------------- project = "Sphinx Favicon" copyright = f"{year}, Timo Metzger" author = "Timo Metzger" release = version # -- General configuration ----------------------------------------------------- extensions = [ "sphinx.ext.autosectionlabel", "sphinx_favicon", "sphinx_copybutton", "sphinx_design", ] source_suffix = [".rst", ".md"] templates_path = ["_templates"] exclude_patterns = ["Thumbs.db", ".DS_Store", "**.ipynb_checkpoints"] # -- Options for HTML output --------------------------------------------------- html_theme = "pydata_sphinx_theme" html_static_path = ["_static"] html_css_files = ["custom.css"] html_context = { "display_github": True, "github_user": "tcmetzger", "github_repo": "sphinx-favicon", "github_version": "main/docs/source/", } # -- Options for the html theme ------------------------------------------------ html_theme_options = { "icon_links": [ { "name": "GitHub", "url": "https://github.com/tcmetzger/sphinx-favicon", "icon": "fa-brands fa-github", }, { "name": "PyPi", "url": "https://pypi.org/project/sphinx-favicon/", "icon": "fa-brands fa-python", }, ], "logo": {"text": project}, "use_edit_page_button": True, "announcement": ( "

Between v0.2 and v1.0, the module name of the extension changed to better " "conform with Python standards. Please update the name used in the extension " 'list of your ' 'conf.py from ' 'sphinx-favicon to ' '' "sphinx_favicon!

" ), } # -- Option for favicons ------------------------------------------------------- favicons = [ # generic icons compatible with most browsers {"href": "favicon-32x32.png"}, "favicon-16x16.png", {"rel": "shortcut icon", "sizes": "any", "href": "favicon.ico"}, # chrome specific "android-chrome-192x192.png", # apple icons {"rel": "mask-icon", "color": "#2d89ef", "href": "safari-pinned-tab.svg"}, {"rel": "apple-touch-icon", "href": "apple-touch-icon.png"}, # msapplications {"name": "msapplication-TileColor", "content": "#2d89ef"}, {"name": "theme-color", "content": "#ffffff"}, "https://raw.githubusercontent.com/tcmetzger/sphinx-favicon/main/docs/source/_static/mstile-150x150.png" # to show it works as well with absolute urls ] sphinx-favicon-1.0.1/docs/source/configuration.rst000066400000000000000000000136421440022754600223100ustar00rootroot00000000000000Configuration ============= In the quickstart guide, you have used a simple list of favicons and **Sphinx Favicon** has automatically generated the corresponding HTML tags. This section will explain how to customize the configuration and use specific tags and attributes such as ``apple-touch-icon``. Defining favicons ^^^^^^^^^^^^^^^^^ Every favicon in **Sphinx Favicon** is defined as a dictionary of HTML attributes. For a single favicon, you can provide a single dictionary: .. code-block:: python favicons = {"rel": "icon", "href": "icon.svg", "type": "image/svg+xml"} This will generate the following HTML tag: .. code-block:: html For multiple favicons, provide a list of dictionaries: .. code-block:: python favicons = [ {"rel": "icon", "href": "icon.svg", "type": "image/svg+xml"}, {"rel": "icon", "sizes": "16x16", "href": "favicon-16x16.png", "type": "image/png"}, {"rel": "icon", "sizes": "32x32", "href": "favicon-32x32.png", "type": "image/png"}, {"rel": "apple-touch-icon", "sizes": "180x180", "href": "apple-touch-icon-180x180.png" "type": "image/png"} ] This will generate the following HTML tags: .. code-block:: html For any attributes that you don't explicitly set, **Sphinx Favicon** will infer the values from your provided input. For example: if you don't provide a ``type`` attribute, **Sphinx Favicon** will infer the type from the file extension. If you don't provide a ``sizes`` attribute, **Sphinx Favicon** will attempt to read the pixel dimensions of the provided image. .. note:: If you provide a simple list (like in the quickstart guide), **Sphinx Favicon** will automatically generate the dict behind the scenes. Your list of favicons can also be a mixture of strings and dicts: .. code-block:: python favicons = [ "icon.svg", "favicon-32x32.png", {"rel": "apple-touch-icon", "href": "apple-touch-icon.png"}, ] This will generate the following HTML tags: .. code-block:: html Customization ^^^^^^^^^^^^^ You can use any parameters to define your favicon as long as they are interpreted by browsers. The following attributes are the most commonly used ones: ``href``: the image location ############################ You can define favicon images with the ``href`` attribute in two ways: Use an **absolute URL** for a favicon file. For example: .. code-block:: python "href": "https://www.sphinx-doc.org/en/master/_static/favicon.svg" Use a **local static file** as a favicon. Make sure you place your local static favicon file(s) inside a directory listed in the Sphinx `"html_static_path" `__. For example: .. code-block:: python "href": "favicon.svg" .. note:: We continue to support the legacy ``static_file`` from v0.2 for local files. ``sizes``: the image size ######################### Use the ``sizes`` attribute as defined `here `__. For example: .. code-block:: python "sizes": "16x16" **Sphinx Favicon** automatically computes a favicon's size if you don't provide a value for the ``sizes`` attribute (for BMP, GIF, JPEG, JPG and PNG files). ``rel``: the favicon relation ############################# Use the ``rel`` attribute to define the favicon relation. This can either be the standard `"icon" and "shortcut icon" `__, or a custom relation like `"apple-touch-icon" `__. For example: .. code-block:: python "rel": "apple-touch-icon" If you don't provide a value for the ``rel`` attribute, **Sphinx Favicon** will automatically set ``rel="icon"``. ``type``: the image MIME type ############################# Use the ``type`` to define a favicon's MIME type as defined `here `__. For example: .. code-block:: python "type": "image/svg+xml" If you don't provide a value for the ``rel`` attribute, **Sphinx Favicon** will automatically extract the MIME type from the provided image file (for BMP, GIF, ICO, JPEG, JPG, PNG, and SVG files). ``name``: specific to msapp icons ################################# You also have the option to specify a ``name`` attribute. This is useful for ``msapplication``-style favicons. If you use the ``name`` attribute, **Sphinx Favicon** will automatically set the ``rel`` attribute to ``"meta"``. For example: .. code-block:: python favicons = [ "mstile-150x150.png", {"name": "msapplication-TileColor", "content": "#2d89ef"}, {"name": "theme-color", "content": "#ffffff"}, ] This will generate the following HTML tags: .. code-block:: html .. tip:: See the ``conf.py`` file for this documentation in the project's GitHub repository, at https://github.com/tcmetzger/sphinx-favicon/blob/main/docs/source/conf.py sphinx-favicon-1.0.1/docs/source/contribute.rst000066400000000000000000000066541440022754600216240ustar00rootroot00000000000000Contribute ========== Thank you for your help improving **Sphinx Favicon**! Workflow for contributing changes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ We follow a typical GitHub workflow of: - Create a personal fork of this repo - Create a branch - Open a pull request - Review results of tests and linting, update code as needed - Update your PR based on feedback from code review on GitHub See the following sections for more details. Clone the repository ^^^^^^^^^^^^^^^^^^^^ First off, you'll need your own copy of the **Sphinx Favicon** codebase. You can clone it for local development like so: Fork the repository so you have your own copy on GitHub. See the `GitHub forking guide for more information `__. Then, clone the repository locally so that you have a local copy to work on: .. code-block:: console git clone https://github.com/{{ YOUR USERNAME }}/sphinx-favicon cd sphinx-favicon Then install the development version of the extension: .. code-block:: console pip install -e .[dev] This will install the Sphinx Favicon library, together with two additional tools: - `pre-commit `__ to automatically check code standards and code quality before commits. - `nox `__ to automate common development tasks. Lastly, activate the pre-commit hooks by running: .. code-block:: console pre-commit install This will install the necessary dependencies to run pre-commit every time you make a commit with Git. Use ``nox`` to manage development environments ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ **Sphinx Favicon** uses `nox `__ to automate several development-related tasks. Currently, the project uses four automation processes (called sessions) in ``noxfile.py``: - ``mypy``: to perform a mypy check on the codebase - ``test``: to run the test suite (using pytest and codecov) - ``docs``: to build the documentation in the ``build`` folder - ``lint``: to run the pre-commits in an isolated environment Every nox session is run in its own virtual environment, and the dependencies are installed automatically. This means you won't have to worry about installing dependencies manually or managing environments with tools like ``venv``. To run a specific nox automation process, use the following command: .. code-block:: console nox -s {{session name}} For example: ``nox -s test`` or ``nox -s docs``. Contribute to the codebase ^^^^^^^^^^^^^^^^^^^^^^^^^^ Any larger updates to the codebase should include tests and documentation. The tests are located in the ``tests`` folder. To run the tests locally, use the following command: .. code-block:: console nox -s test See :ref:`below ` for more information on how to update the documentation. .. _contributing-docs: Contribute to the docs ^^^^^^^^^^^^^^^^^^^^^^ The documentation is built using `Sphinx `__ and deployed to `Read the Docs `__. The documentation sources are located in the ``docs`` folder. To build the documentation locally, use the following command: .. code-block:: console nox -s docs For each pull request, the documentation is built and deployed to make it easier to review the changes in the PR. To access the docs build from a PR, click on the "Read the Docs" preview in the CI/CD jobs. sphinx-favicon-1.0.1/docs/source/index.rst000066400000000000000000000032101440022754600205360ustar00rootroot00000000000000Sphinx Favicon ============== **A Sphinx extension to add custom favicons** With **Sphinx Favicon**, you can add custom favicons to your Sphinx HTML documentation. You can define favicons directly in your ``conf.py``, using attributes such as ``rel``, ``sizes``, ``href``, or ``name``. **Sphinx Favicon** creates the respective ```` or ```` tags in your HTML output. The **Sphinx Favicon** extension gives you more flexibility than the `standard "favicon.ico" supported by Sphinx `_. **Sphinx Favicon** provides a quick and easy way to add the most important favicon formats for different browsers and devices. For example, you can add support for general as well as vendor-specific favicons, including ``apple-touch-icon`` and ``mask-icon``. See our :ref:`quickstart guide ` to get started! Documentation contents ---------------------- This documentation contains three sections: .. grid:: 1 1 3 3 .. grid-item-card:: :link: quickstart :link-type: ref :class-header: card-header-gray Quickstart ^^^ ➡ Installation and basic usage .. grid-item-card:: :link: configuration :link-type: ref :class-header: card-header-gray Configuration ^^^ ➡ Detailed information about all configuration options and examples .. grid-item-card:: :link: contribute :link-type: ref :class-header: card-header-gray Contribute ^^^ ➡ Help improve Sphinx Favicon .. toctree:: :hidden: :maxdepth: 2 quickstart configuration contribute sphinx-favicon-1.0.1/docs/source/quickstart.rst000066400000000000000000000051101440022754600216220ustar00rootroot00000000000000Quickstart ========== This section contains basic information about **Sphinx Favicon** to get you started. Installation ------------ Use ``pip`` to install **Sphinx Favicon** in your environment: .. code-block:: console pip install sphinx-favicon Extension setup --------------- Enable the extension ^^^^^^^^^^^^^^^^^^^^ After installing **Sphinx Favicon**, add ``sphinx_favicon`` to the list of extensions in your ``conf.py`` file: .. code-block:: python extensions = [ #[...] "sphinx_favicon", ] Check static directory configuration ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ In case you want to use favicons from files in your static directory, make sure that the `html_static_path `_ in your ``conf.py`` is configured correctly. For example: .. code-block:: python html_static_path = ["_static"] Favicon configuration --------------------- Add basic favicons ^^^^^^^^^^^^^^^^^^ After adding ``sphinx_favicon`` to your list of extensions, you can now use the ``favicons`` variable in ``conf.py`` to define favicons. There are many ways to define favicons, with varying degrees of complexity. The simplest way to add favicons is to define a list of favicon file names or URLs. For example: .. code-block:: python favicons = [ "favicon-16x16.png", "favicon-32x32.png", "icon.svg", ] **Sphinx Favicon** automatically determines the relevant attributes for each favicon and adjusts paths for static files where necessary. Based on this configuration, **Sphinx Favicon** adds the following ```` tags in the HTML ```` for each page in your Sphinx-generated HTML documentation: .. code-block:: html You can mix file names (relative to your ``html_static_path``) and URLs in this list. For example: .. code-block:: python favicons = [ "https://picsum.photos/16/16", "https://picsum.photos/32/32", ] This will add the following ```` tags: .. code-block:: html Advanced usage -------------- This chapter only covers basic setup. For more advanced usage, see the :ref:`following chapter `! sphinx-favicon-1.0.1/noxfile.py000066400000000000000000000021171440022754600164700ustar00rootroot00000000000000"""Test process to run in isolated environments.""" import nox @nox.session(reuse_venv=True) def test(session): """Apply the tests on the lib.""" session.install(".[test]") test_files = session.posargs or ["tests"] session.run("pytest", "--color=yes", "--cov", "--cov-report=html", *test_files) @nox.session(name="mypy", reuse_venv=True) def mypy(session): """Run the mypy evaluation of the lib.""" session.install(".") session.install("mypy") test_files = session.posargs or ["sphinx_favicon"] session.run( "mypy", "--ignore-missing-imports", "--install-types", "--non-interactive", *test_files, ) @nox.session(name="docs", reuse_venv=True) def docs(session): """Build the docs.""" session.install(".[doc]") session.run( "sphinx-build", "-b=html", *session.posargs, "docs/source", "docs/build/html" ) @nox.session(reuse_venv=True) def lint(session): """Run pre-commit linting checks.""" session.install(".[test]") session.run("pre-commit", "run", "--all-files", external=True) sphinx-favicon-1.0.1/pyproject.toml000066400000000000000000000036171440022754600173740ustar00rootroot00000000000000[build-system] requires = ["setuptools >= 40.9.0","wheel"] build-backend = "setuptools.build_meta" [project] name = "sphinx-favicon" version = "1.0" description = "Sphinx Extension adding support for custom favicons" keywords = ["sphinx", "extension", "favicon", "meta html"] classifiers = [ "Development Status :: 5 - Production/Stable", "Environment :: Plugins", "Environment :: Web Environment", "Framework :: Sphinx :: Extension", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Natural Language :: English", "Operating System :: OS Independent", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python", "Topic :: Utilities", "Topic :: Documentation", "Topic :: Documentation :: Sphinx", "Topic :: Software Development :: Documentation", "Topic :: Text Processing", ] requires-python = ">=3.7" dependencies = ["sphinx>=3.4"] [[project.authors]] name = "Timo Cornelius Metzger" email = "coding@tcmetzger.net" [project.license] text = "MIT" [project.readme] file = "README.md" content-type = "text/markdown" [project.urls] Homepage = "https://github.com/tcmetzger/sphinx-favicon" [project.optional-dependencies] dev = ["pre-commit", "nox"] test = ["pytest", "beautifulsoup4", "pytest-cov"] doc = ["sphinx<6", "pydata-sphinx-theme", "sphinx-copybutton", "sphinx-design"] [tool.setuptools] license-files = ["LICENSE"] packages = ["sphinx_favicon"] [tool.ruff] fix = true select = ["E", "F", "W", "I", "D", "RUF"] ignore = ["E501"] # line too long | Black take care of it exclude = ["setup.py", "tests/roots/*", "tests/__init__.py"] [tool.ruff.flake8-quotes] docstring-quotes = "double" [tool.ruff.pydocstyle] convention = "google" [tool.coverage.run] source = ["sphinx_favicon"] sphinx-favicon-1.0.1/setup.py000066400000000000000000000000461440022754600161630ustar00rootroot00000000000000import setuptools setuptools.setup() sphinx-favicon-1.0.1/sphinx_favicon/000077500000000000000000000000001440022754600174675ustar00rootroot00000000000000sphinx-favicon-1.0.1/sphinx_favicon/__init__.py000066400000000000000000000216511440022754600216050ustar00rootroot00000000000000"""Sphinx extension to add custom favicons. With sphinx-favicon, you can add custom favicons to your Sphinx html documentation quickly and easily. You can define favicons directly in your conf.py, with different rel attributes such as "icon" or "apple-touch-icon" and any favicon size. The sphinx-favicon extension gives you more flexibility than the standard favicon.ico supported by Sphinx. It provides a quick and easy way to add the most important favicon formats for different browsers and devices. """ from io import BytesIO from pathlib import Path from typing import Any, Callable, Dict, List, Optional, Union from urllib.parse import urlparse import docutils.nodes as nodes import imagesize import requests from requests.exceptions import RequestException from sphinx.application import Sphinx from sphinx.util import logging logger = logging.getLogger(__name__) FaviconsDef = Union[Dict[str, str], List[Dict[str, str]]] OUTPUT_STATIC_DIR: str = "_static" "output folder for static items in the html builder" FILE_FIELD: str = "static-file" "field in the ``FaviconsDef`` pointing to file in the ``html_static_path``" SUPPORTED_MIME_TYPES: Dict[str, str] = { "bmp": "image/x-ms-bmp", "gif": "image/gif", "ico": "image/x-icon", "jpeg": "image/jpeg", "jpg": "image/jpeg", "png": "image/png", "svg": "image/svg+xml", } "supported mime types of the link tag" SUPPORTED_SIZE_TYPES: List[str] = ["bmp", "gif", "jpeg", "jpg", "png"] "list of file type that can be used to compute size" def generate_meta(favicon: Dict[str, str]) -> str: """Generate metatag based on favicon data. Default behavior: - If favicon data contains no ``rel`` attribute, sets ``rel="icon"`` - If no ``sizes`` attribute is provided, ``sizes`` will be computed from the file - 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) Args: favicon: Favicon data Returns: Favicon link or meta tag """ # get the tag of the output tag = "meta" if "name" in favicon else "link" # default to "icon" for link elements if tag == "link": favicon.setdefault("rel", "icon") favicon["href"] # to raise an error if not set extension = favicon["href"].split(".")[-1] # set the type for link elements. # if type is not set, try to guess it from the file extension type_ = favicon.get("type") if not type_ and tag == "link" and extension in SUPPORTED_MIME_TYPES: type_ = SUPPORTED_MIME_TYPES[extension] favicon["type"] = type_ # build the html element parameters = [f'{k}="{v}"' for k, v in favicon.items() if v is not None] html_element = f" <{tag} {' '.join(parameters)}>" return html_element def _sizes( favicon: Dict[str, str], static_path: List[str], confdir: str ) -> Dict[str, str]: """Compute the size of the favicon if its size is not explicitly defined. If the file is a SUPPORTED_MIME_TYPES, then the size is computed on the fly and added to the favicon attributes. Don't do anything if the favicon is not a link tag. Args: favicon: The favicon description as set in the conf.py file static_path: The static_path registered in the application confdir: The source directory of the documentation Returns: The favicon with a fully qualified size """ # exit if the favicon tag has no href (like meta) if not (FILE_FIELD in favicon or "href" in favicon): return favicon # init the parameters link: Optional[str] = favicon.get("href") or favicon.get(FILE_FIELD) extension: Optional[str] = link.split(".")[-1] if link else None sizes: Optional[str] = favicon.get("sizes") # get the size automatically if not supplied if link and sizes is None and extension in SUPPORTED_SIZE_TYPES: file: Optional[Union[BytesIO, Path]] = None if bool(urlparse(link).netloc): try: response = requests.get(link) except RequestException: response = requests.Response() response.status_code = -1 if response.status_code == 200: file = BytesIO(response.content) else: logger.warning( f"The provided link ({link}) cannot be read. " "Size will not be computed." ) else: for folder in static_path: path = Path(confdir) / folder / link if path.is_file(): file = path break if file is None: logger.warning( f"The provided path ({link}) is not part of any of the static path. " "Size will not be computed." ) # compute the image size if image file is found if file is not None: w, h = imagesize.get(file) size = f"{int(w)}x{int(h)}" favicon["sizes"] = size return favicon def _static_to_href(pathto: Callable, init_favicon: Dict[str, str]) -> Dict[str, str]: """Replace static ref to fully qualified href. if the ``href`` is a relative path then it's replaced with the correct ``href``. We keep checking for ``static-file`` for legacy reasons. If both ``static-file`` and ``href`` are provided, ``href`` will be ignored. If the favicon has no ``href`` nor ``static-file`` then do nothing. Args: pathto: Sphinx helper_ function to handle relative URLs init_favicon: The favicon description as set in the conf.py file Returns: The favicon with a fully qualified href """ # work on a copy of the favicon (mutable issue) favicon = init_favicon.copy() # exit if the favicon tag has no href (like meta) if not (FILE_FIELD in favicon or "href" in favicon): return favicon # legacy check for "static-file" if FILE_FIELD in favicon: favicon["href"] = favicon.pop(FILE_FIELD) # check if link is absolute link = favicon["href"] is_absolute = bool(urlparse(link).netloc) or link.startswith("/") # if the link is absolute do nothing, else replace it with a full one if not is_absolute: favicon["href"] = pathto(f"{OUTPUT_STATIC_DIR}/{link}", resource=True) return favicon def create_favicons_meta( pathto: Callable, favicons: FaviconsDef, static_path: List[str], confdir: str ) -> Optional[str]: """Create ```` elements for favicons defined in configuration. Args: pathto: Sphinx helper_ function to handle relative URLs favicons: Favicon data from configuration. Can be a single dict or a list of dicts. static_path: the static_path registered in the application confdir: the source directory of the documentation Returns: ```` elements for all favicons. See Also: https://www.sphinx-doc.org/en/master/templating.html#path """ # force cast the favicon config as a list if isinstance(favicons, dict): favicons = [favicons] # read this list and create the links for each item meta_favicons = [] for favicon in favicons: if isinstance(favicon, str): favicon = {"href": favicon} if not isinstance(favicon, dict): logger.warning( f"Invalid config value for favicon extension: {favicon}." "Custom favicons will not be included in build." ) continue favicon = _sizes(favicon, static_path, confdir) tag = generate_meta(_static_to_href(pathto, favicon)) meta_favicons.append(tag) return "\n".join(meta_favicons) def html_page_context( app: Sphinx, pagename: str, templatename: str, context: Dict[str, Any], doctree: nodes.document, ) -> None: """Update the html page context by adding the favicons. Args: app: The sphinx application pagename: the name of the page as string templatename: the name of the template as string context: the html context dictionary doctree: the docutils document tree """ # extract parameters from app favicons: Optional[Dict[str, str]] = app.config["favicons"] pathto: Callable = context["pathto"] static_path: List[str] = app.config["html_static_path"] confdir: str = app.confdir if not (doctree and favicons): return favicons_meta = create_favicons_meta(pathto, favicons, static_path, confdir) context["metatags"] += favicons_meta def setup(app: Sphinx) -> Dict[str, Any]: """Add custom configuration to sphinx app. Args: app: the Sphinx application Returns: the 2 parralel parameters set to ``True`` """ app.add_config_value("favicons", None, "html") app.connect("html-page-context", html_page_context) return { "parallel_read_safe": True, "parallel_write_safe": True, } sphinx-favicon-1.0.1/tests/000077500000000000000000000000001440022754600156135ustar00rootroot00000000000000sphinx-favicon-1.0.1/tests/__init__.py000066400000000000000000000000001440022754600177120ustar00rootroot00000000000000sphinx-favicon-1.0.1/tests/conftest.py000066400000000000000000000031521440022754600200130ustar00rootroot00000000000000"""Configuration fixtures of the tests.""" import pytest from bs4 import BeautifulSoup from sphinx.testing.path import path pytest_plugins = "sphinx.testing.fixtures" @pytest.fixture(scope="session") def rootdir(): """The root directory.""" return path(__file__).parent.abspath() / "roots" @pytest.fixture() def content(app): """The app build content.""" app.build() yield app def _link_tags(content, page): """Link tags in a page content.""" c = (content.outdir / page).read_text() return BeautifulSoup(c, "html.parser").find_all("link") def _favicon_tags(content, page="index.html"): """Favicon tags in the index.html page.""" return [ tag for tag in _link_tags(content, page) if tag.get("type", "").startswith("image") ] def _meta_tags(content, page): """Link tags in a page content.""" c = (content.outdir / page).read_text() return BeautifulSoup(c, "html.parser").find_all("meta") @pytest.fixture() def link_tags(content): """Link tags in index.html page.""" return _link_tags(content, "index.html") @pytest.fixture() def meta_tags(content): """Meta tags in index.html page.""" return _meta_tags(content, "index.html") @pytest.fixture() def favicon_tags(content): """Favicon tags in index.html page.""" return _favicon_tags(content) @pytest.fixture() def favicon_tags_for_nested(content): """Favicon tags in nested/page.html page.""" return _favicon_tags(content, "nested/page.html") def pytest_configure(config): """Add markers config to pytest.""" config.addinivalue_line("markers", "sphinx") sphinx-favicon-1.0.1/tests/roots/000077500000000000000000000000001440022754600167615ustar00rootroot00000000000000sphinx-favicon-1.0.1/tests/roots/test-href_and_static/000077500000000000000000000000001440022754600230535ustar00rootroot00000000000000sphinx-favicon-1.0.1/tests/roots/test-href_and_static/conf.py000066400000000000000000000010551440022754600243530ustar00rootroot00000000000000extensions = ["sphinx_favicon"] master_doc = "index" exclude_patterns = ["_build"] html_theme = "basic" html_static_path = ["gfx"] favicons = [ { "sizes": "32x32", "static-file": "square.svg", "href": "https://raw.githubusercontent.com/tcmetzger/sphinx-favicon/main/docs/source/_static/favicon-32x32.png", }, { "sizes": "128x128", "static-file": "nested/triangle.svg", "href": "https://raw.githubusercontent.com/tcmetzger/sphinx-favicon/main/docs/source/_static/apple-touch-icon.png", }, ] sphinx-favicon-1.0.1/tests/roots/test-href_and_static/gfx/000077500000000000000000000000001440022754600236375ustar00rootroot00000000000000sphinx-favicon-1.0.1/tests/roots/test-href_and_static/gfx/nested/000077500000000000000000000000001440022754600251215ustar00rootroot00000000000000sphinx-favicon-1.0.1/tests/roots/test-href_and_static/gfx/nested/triangle.svg000066400000000000000000000003301440022754600274430ustar00rootroot00000000000000 sphinx-favicon-1.0.1/tests/roots/test-href_and_static/gfx/square.svg000066400000000000000000000002331440022754600256560ustar00rootroot00000000000000 sphinx-favicon-1.0.1/tests/roots/test-href_and_static/index.rst000066400000000000000000000000601440022754600247100ustar00rootroot00000000000000Contents -------- .. toctree:: nested/page sphinx-favicon-1.0.1/tests/roots/test-href_and_static/nested/000077500000000000000000000000001440022754600243355ustar00rootroot00000000000000sphinx-favicon-1.0.1/tests/roots/test-href_and_static/nested/page.rst000066400000000000000000000000741440022754600260040ustar00rootroot00000000000000=========== Nested Page =========== Nothing to see here... sphinx-favicon-1.0.1/tests/roots/test-list_of_three_dicts/000077500000000000000000000000001440022754600237525ustar00rootroot00000000000000sphinx-favicon-1.0.1/tests/roots/test-list_of_three_dicts/conf.py000066400000000000000000000014071440022754600252530ustar00rootroot00000000000000extensions = ["sphinx_favicon"] master_doc = "index" exclude_patterns = ["_build"] html_theme = "basic" favicons = [ { "rel": "icon", "sizes": "16x16", "href": "https://raw.githubusercontent.com/tcmetzger/sphinx-favicon/main/docs/source/_static/favicon-16x16.png", "type": "image/png", }, { "rel": "icon", "sizes": "32x32", "href": "https://raw.githubusercontent.com/tcmetzger/sphinx-favicon/main/docs/source/_static/favicon-32x32.png", "type": "image/png", }, { "rel": "apple-touch-icon", "sizes": "180x180", "href": "https://raw.githubusercontent.com/tcmetzger/sphinx-favicon/main/docs/source/_static/apple-touch-icon.png", "type": "image/png", }, ] sphinx-favicon-1.0.1/tests/roots/test-list_of_three_dicts/index.rst000066400000000000000000000000001440022754600256010ustar00rootroot00000000000000sphinx-favicon-1.0.1/tests/roots/test-list_of_three_icons_automated_values/000077500000000000000000000000001440022754600274015ustar00rootroot00000000000000sphinx-favicon-1.0.1/tests/roots/test-list_of_three_icons_automated_values/conf.py000066400000000000000000000010651440022754600307020ustar00rootroot00000000000000extensions = ["sphinx_favicon"] master_doc = "index" exclude_patterns = ["_build"] html_theme = "basic" favicons = [ "https://raw.githubusercontent.com/tcmetzger/sphinx-favicon/main/docs/source/_static/favicon-16x16.png", { "href": "https://raw.githubusercontent.com/tcmetzger/sphinx-favicon/main/docs/source/_static/favicon-32x32.png", }, { "rel": "apple-touch-icon", "sizes": "180x180", "href": "https://raw.githubusercontent.com/tcmetzger/sphinx-favicon/main/docs/source/_static/apple-touch-icon.png", }, ] sphinx-favicon-1.0.1/tests/roots/test-list_of_three_icons_automated_values/index.rst000066400000000000000000000000001440022754600312300ustar00rootroot00000000000000sphinx-favicon-1.0.1/tests/roots/test-list_of_urls/000077500000000000000000000000001440022754600224425ustar00rootroot00000000000000sphinx-favicon-1.0.1/tests/roots/test-list_of_urls/conf.py000066400000000000000000000006231440022754600237420ustar00rootroot00000000000000extensions = ["sphinx_favicon"] master_doc = "index" exclude_patterns = ["_build"] html_theme = "basic" favicons = [ "https://secure.example.com/favicon/favicon-16x16.gif", "https://raw.githubusercontent.com/tcmetzger/sphinx-favicon/main/docs/source/_static/favicon-32x32.png", "https://raw.githubusercontent.com/tcmetzger/sphinx-favicon/main/docs/source/_static/apple-touch-icon.png", ] sphinx-favicon-1.0.1/tests/roots/test-list_of_urls/index.rst000066400000000000000000000000001440022754600242710ustar00rootroot00000000000000sphinx-favicon-1.0.1/tests/roots/test-msapp_meta/000077500000000000000000000000001440022754600220645ustar00rootroot00000000000000sphinx-favicon-1.0.1/tests/roots/test-msapp_meta/conf.py000066400000000000000000000004411440022754600233620ustar00rootroot00000000000000extensions = ["sphinx_favicon"] master_doc = "index" exclude_patterns = ["_build"] html_theme = "basic" html_static_path = ["gfx"] favicons = [ "mstile-150x150.png", {"name": "msapplication-TileColor", "content": "#2d89ef"}, {"name": "theme-color", "content": "#ffffff"}, ] sphinx-favicon-1.0.1/tests/roots/test-msapp_meta/gfx/000077500000000000000000000000001440022754600226505ustar00rootroot00000000000000sphinx-favicon-1.0.1/tests/roots/test-msapp_meta/gfx/mstile-150x150.png000066400000000000000000000075711440022754600256060ustar00rootroot00000000000000PNG  IHDR<qiCCPICC profile(}=HPOS";t:Yq*Bi+`IC(Y:8*? .N.R}IE{ Sͮq@,#xa`Qz2g}S7]gyYJdO$eaOoZ:}+K 9A$~ qX,ulSE(_ȹpVjuO`A[pV ,"DȨaXѮb"MqOK&9Q ٚ 7)_l# vfݶmy+6Om-r lmM.w']2$GE) }Z8}4-Qǻ{;oOk~?p$rSbKGDN pHYs B(xtIMEbP* uIDATxyU?f!悊( B"Fb4&Vbie$JHĭ\eHiY01(H+0b8eɌ}}8_U׳df^w90 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0`].a\v h>k3a## *czX EY ,UAJcj`EFe`1xf&〱*a@@BhKt3a* *A{bi]RZd LF ,ԲXp&>XЄU_5҉Z,y>܄C[Locn$v9c!w` KLmpi )I])ªFULcy)-ˁ17J `U(ؑkF-{M䌚ݴjj9pvkYe ͧ@Vp!'V@Z^+KI'bG|u:kǍHw:?onS}2*ql8^V%wlL`P_|^u9u塲1 vD[63}t09b쩥1v;)1Xn6lN. xB>5 x%PB]/0T7GkSOUu͕MՈ=;A6}Q)p~ouE:tpGmxx A}8MLT8':i_ 5^نX/~>\lEܼpB*\v;Ltn"[ e3p?T"_ۧwRI59 Tau#B2_E<2Zw%\#7a55{[KXHQF:盆7#N.MFNQ…Oe9R>0W.SJN|؅Gg]`0Iҫm4y5,o7$!&sD\+Ϻ]♤Be\Mtm:7יʌօ k3k[7o]?4}xmc*b}q\auVowrIϭIIz[̗+u@x_aw(ŠJo1Q>mݖi5&듵 ddEuxt|Z-Ŭ\rA}i?"z؋ ֧Kg69I!SԴ[<*I[I֓>?C"B?%x.)Q DOWz~6Iָx@;7sש?Q"rI:9~ H7y!:կD\}?mJ$4*I[FMMkP@`z$-!mU*n_E5XmLiHR19A_dNiq%ed9p T .T s,h)=OVՖK)$hpm;jC\Է8/VZE\Sh#\=0óʐ;b෺IPպHQ }S1ī#q=lVU]i2$54@.jY X on7Ļ-]>^Dr;;!ywq9Y^#4V4RlVCxHLN oPQEIW!ЫS#^?r\ $}W:$>cԛT N} qP?7CLnt 뢥~Cs W ٯ$MaBYIs(;Gw{ɕjWrTF]b~-FZH fCg$j32/p` r DM&9ʙ̚6J9Boxd8f,^8 twO6$K "2/ ǨV]qM;/ζ-!*x]r"T'n]gڥMI4ZHO݋W눱W*vhzQʈvՈ^Q(5tX!tSB,[%>"vPco%.~/dʁxmNegќR<kzUp'Qu=,vZ?]L6["=\=Q60}ڥ+ UݔjÊӟ'AK{aQ҅˔/sNuJ gTT .8]U`>HxšAQ2q_#m|IXΘNG,.m[ _3|%aZğG|Q4%al|߾wd7b'-1ުS2b^%!ݑDs#6ǭ~@ǎH-{#"\-y:M8eFD[L[9tƥp}`ZBnDOmw8b-pn7~= s#W\O$\_e}pc*bLE rޕ- l2 m,8ԅH/UT!ު>JF$73\ɨy.DgVb |CTy~.. !YVi \]yTT3g1.<@ip,Ƞr?k~AqA79 kC=^bǟaC3خ2WsLQ$PKG23a3֦j$]d!(=;,  'ʷ՝ E<+ޙ\3vIᴑ O< EwqGMu&?G:h P 'T|/sW&M#xӊ ?E$OgJs`%U}~֗3p<]I|w B8F}G =_&!! %Nbr&U&$Lj%rr_Cz _  ŷG$"~KV2YQb/%}ܽw%ѣf$ށąnC(;D!,X_RLѩ+kڦ (\.)`>Bղ Hu׀sE6fbbbj@<\"K}UI;h&d[c5bK4YW$1Ra5=}0I?UHt$$ ا ZnB=D`۲ֈbM,֒ Ɂ:OA=C9^ ح%v|7pMFbo52L]N0|0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ʣ/eIENDB`sphinx-favicon-1.0.1/tests/roots/test-msapp_meta/index.rst000066400000000000000000000000011440022754600237140ustar00rootroot00000000000000 sphinx-favicon-1.0.1/tests/roots/test-single_dict/000077500000000000000000000000001440022754600222225ustar00rootroot00000000000000sphinx-favicon-1.0.1/tests/roots/test-single_dict/conf.py000066400000000000000000000004511440022754600235210ustar00rootroot00000000000000extensions = ["sphinx_favicon"] master_doc = "index" exclude_patterns = ["_build"] html_theme = "basic" favicons = { "rel": "apple-touch-icon", "sizes": "180x180", "href": "https://raw.githubusercontent.com/tcmetzger/sphinx-favicon/main/docs/source/_static/apple-touch-icon.png", } sphinx-favicon-1.0.1/tests/roots/test-single_dict/index.rst000066400000000000000000000000001440022754600240510ustar00rootroot00000000000000sphinx-favicon-1.0.1/tests/roots/test-static_files/000077500000000000000000000000001440022754600224075ustar00rootroot00000000000000sphinx-favicon-1.0.1/tests/roots/test-static_files/conf.py000066400000000000000000000006071440022754600237110ustar00rootroot00000000000000extensions = ["sphinx_favicon"] master_doc = "index" exclude_patterns = ["_build"] html_theme = "basic" html_static_path = ["gfx"] favicons = [ { "sizes": "32x32", "href": "square.svg", # use href }, { "sizes": "128x128", "static-file": "nested/triangle.svg", # use outdated static-file }, "circle.svg", # use nothing but filename ] sphinx-favicon-1.0.1/tests/roots/test-static_files/gfx/000077500000000000000000000000001440022754600231735ustar00rootroot00000000000000sphinx-favicon-1.0.1/tests/roots/test-static_files/gfx/circle.svg000066400000000000000000000032641440022754600251620ustar00rootroot00000000000000 image/svg+xml sphinx-favicon-1.0.1/tests/roots/test-static_files/gfx/nested/000077500000000000000000000000001440022754600244555ustar00rootroot00000000000000sphinx-favicon-1.0.1/tests/roots/test-static_files/gfx/nested/triangle.svg000066400000000000000000000003301440022754600267770ustar00rootroot00000000000000 sphinx-favicon-1.0.1/tests/roots/test-static_files/gfx/square.svg000066400000000000000000000002331440022754600252120ustar00rootroot00000000000000 sphinx-favicon-1.0.1/tests/roots/test-static_files/index.rst000066400000000000000000000000601440022754600242440ustar00rootroot00000000000000Contents -------- .. toctree:: nested/page sphinx-favicon-1.0.1/tests/roots/test-static_files/nested/000077500000000000000000000000001440022754600236715ustar00rootroot00000000000000sphinx-favicon-1.0.1/tests/roots/test-static_files/nested/page.rst000066400000000000000000000000741440022754600253400ustar00rootroot00000000000000=========== Nested Page =========== Nothing to see here... sphinx-favicon-1.0.1/tests/test_options.py000066400000000000000000000143141440022754600207220ustar00rootroot00000000000000"""Test suite for the sphinx-favicon extension.""" from itertools import chain from pathlib import Path import pytest @pytest.mark.sphinx("html", testroot="list_of_three_dicts") def test_list_of_three_dicts(favicon_tags): """Run tests on a list of 3 dicts. Args: favicon_tags: Favicon tags in index.html page. """ # this test should have 3 favicons assert len(favicon_tags) == 3 # all favicons should have rel, href, type, and sizes attributes for favicon_tag in favicon_tags: assert favicon_tag["rel"] assert favicon_tag["href"] assert favicon_tag["type"] assert favicon_tag["sizes"] # check first favicon in more detail assert favicon_tags[0]["rel"] == ["icon"] assert ( favicon_tags[0]["href"] == "https://raw.githubusercontent.com/tcmetzger/sphinx-favicon/main/docs/source/_static/favicon-16x16.png" ) assert favicon_tags[0]["type"] == "image/png" assert favicon_tags[0]["sizes"] == "16x16" @pytest.mark.sphinx("html", testroot="list_of_three_icons_automated_values") def test_list_of_three_icons_automated_values(favicon_tags): """Run tests on a list of 3 dicts with automated values. Args: favicon_tags: Favicon tags in index.html page. """ # this test should have 3 favicons assert len(favicon_tags) == 3 # all favicons should have rel, href, type, and sizes attributes for favicon_tag in favicon_tags: assert favicon_tag["rel"] assert favicon_tag["href"] assert favicon_tag["type"] assert favicon_tag["sizes"] # check first favicon in more detail assert favicon_tags[0]["rel"] == ["icon"] assert ( favicon_tags[0]["href"] == "https://raw.githubusercontent.com/tcmetzger/sphinx-favicon/main/docs/source/_static/favicon-16x16.png" ) assert favicon_tags[0]["type"] == "image/png" assert favicon_tags[0]["sizes"] == "16x16" @pytest.mark.sphinx("html", testroot="single_dict") def test_single_dict(favicon_tags): """Run tests on a single dict. Args: favicon_tags: Favicon tags in index.html page. """ # this test should have 1 favicon assert len(favicon_tags) == 1 # check favicon assert favicon_tags[0]["rel"] == ["apple-touch-icon"] assert ( favicon_tags[0]["href"] == "https://raw.githubusercontent.com/tcmetzger/sphinx-favicon/main/docs/source/_static/apple-touch-icon.png" ) assert favicon_tags[0]["type"] == "image/png" assert favicon_tags[0]["sizes"] == "180x180" @pytest.mark.sphinx("html", testroot="list_of_urls") def test_list_of_urls(favicon_tags): """Run tests on a list of urls. Args: favicon_tags: Favicon tags in index.html page. """ # this test should have 3 favicons assert len(favicon_tags) == 3 # all favicons should have rel, href, and type attributes for favicon_tag in favicon_tags: assert favicon_tag["rel"] assert favicon_tag["href"] assert favicon_tag["type"] # check first favicon in more detail assert favicon_tags[0]["rel"] == ["icon"] assert ( favicon_tags[0]["href"] == "https://secure.example.com/favicon/favicon-16x16.gif" ) assert favicon_tags[0]["type"] == "image/gif" @pytest.mark.sphinx("html", testroot="static_files") def test_static_files(app, favicon_tags, favicon_tags_for_nested): """Run tests using static files. Args: app: the Sphinx application favicon_tags: Favicon tags in index.html page. favicon_tags_for_nested: Favicon tags in nested/page.html page. """ # this test should have 2 favicons assert len(favicon_tags) == 3 # all favicons should have rel, href, and type 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 "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() assert (static / "circle.svg").exists() @pytest.mark.sphinx("html", testroot="href_and_static") def test_href_and_static(app, favicon_tags, favicon_tags_for_nested): """Run tests on a mix of static files and complete urls. Args: app: the Sphinx application favicon_tags: Favicon tags in index.html page. favicon_tags_for_nested: Favicon tags in nested/page.html page. """ # this test should have 3 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") # 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() @pytest.mark.sphinx("html", testroot="msapp_meta") def test_msapp_meta(favicon_tags, meta_tags): """Run tests on a favicon configuration with meta. Args: favicon_tags: Favicon tags in index.html page. meta_tags: Meta tags in index.html page. """ # this test should have 1 link tag assert len(favicon_tags) == 1 # get all values from meta tags and check for expected values tag_values = [] for tag in meta_tags: tag_values.extend(list(tag.attrs.values())) assert "msapplication-TileColor" in tag_values assert "#2d89ef" in tag_values assert "theme-color" in tag_values assert "#ffffff" in tag_values