diff --git a/README.md b/README.md index 679ed66..1ab7535 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,8 @@ extensions = [ ## Options These values are placed in the conf.py of your sphinx project. +Users hosting documentation on Read The Docs *do not* need to set any of the following unless custom configuration is wanted. The extension will automatically retrieve your site url. + * `ogp_site_url` * This config option is very important, set it to the URL the site is being hosted on. * `ogp_description_length` diff --git a/docs/source/conf.py b/docs/source/conf.py index 46f901f..ee638f3 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -12,17 +12,18 @@ # import os import sys -sys.path.insert(0, os.path.abspath('../..')) + +sys.path.insert(0, os.path.abspath("../..")) # -- Project information ----------------------------------------------------- -project = 'sphinxext-opengraph' -copyright = '2020, FIRST' -author = 'WPILib' +project = "sphinxext-opengraph" +copyright = "2020, FIRST" +author = "WPILib" # The full version, including alpha/beta/rc tags -release = '1.0' +release = "1.0" # -- General configuration --------------------------------------------------- @@ -36,7 +37,7 @@ ] # Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] +templates_path = ["_templates"] # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. @@ -49,4 +50,4 @@ # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # -html_theme = 'furo' +html_theme = "furo" diff --git a/output.txt b/output.txt new file mode 100644 index 0000000..9fe0e6e Binary files /dev/null and b/output.txt differ diff --git a/sphinxext/opengraph/__init__.py b/sphinxext/opengraph/__init__.py index 03c57a8..74cb70c 100644 --- a/sphinxext/opengraph/__init__.py +++ b/sphinxext/opengraph/__init__.py @@ -1,13 +1,17 @@ from typing import Any, Dict -from urllib.parse import urljoin -from pathlib import Path +from urllib.parse import urljoin, urlparse, urlunparse +from pathlib import Path, PosixPath import docutils.nodes as nodes from sphinx.application import Sphinx +from sphinx.util import logger from .descriptionparser import get_description from .titleparser import get_title +import os + + DEFAULT_DESCRIPTION_LENGTH = 200 # A selection from https://www.iana.org/assignments/media-types/media-types.xhtml#image @@ -30,7 +34,10 @@ def make_tag(property: str, content: str) -> str: def get_tags( - context: Dict[str, Any], doctree: nodes.document, config: Dict[str, Any] + app: Sphinx, + context: Dict[str, Any], + doctree: nodes.document, + config: Dict[str, Any], ) -> str: # Set length of description @@ -53,6 +60,24 @@ def get_tags( # type tag tags += make_tag("og:type", config["ogp_type"]) + if os.getenv("READTHEDOCS") and config["ogp_site_url"] is None: + # readthedocs uses html_baseurl for sphinx > 1.8 + parse_result = urlparse(config["html_baseurl"]) + + if config["html_baseurl"] is None: + raise EnvironmentError("ReadTheDocs did not provide a valid canonical URL!") + + # Grab root url from canonical url + config["ogp_site_url"] = urlunparse( + ( + parse_result.scheme, + parse_result.netloc, + parse_result.path, + "", + "", + "", + ) + ) # url tag # Get the URL of the specific page @@ -109,7 +134,7 @@ def html_page_context( doctree: nodes.document, ) -> None: if doctree: - context["metatags"] += get_tags(context, doctree, app.config) + context["metatags"] += get_tags(app, context, doctree, app.config) def setup(app: Sphinx) -> Dict[str, Any]: diff --git a/tests/conftest.py b/tests/conftest.py index e0d15b3..913e5bc 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -2,6 +2,9 @@ from bs4 import BeautifulSoup from sphinx.testing.path import path +from sphinx.application import Sphinx + + pytest_plugins = "sphinx.testing.fixtures" @@ -21,6 +24,12 @@ def _meta_tags(content): return BeautifulSoup(c, "html.parser").find_all("meta") +def _og_meta_tags(content): + return [ + tag for tag in _meta_tags(content) if tag.get("property", "").startswith("og:") + ] + + @pytest.fixture() def meta_tags(content): return _meta_tags(content) diff --git a/tests/roots/test-rtd-default/conf.py b/tests/roots/test-rtd-default/conf.py new file mode 100644 index 0000000..7f99bb3 --- /dev/null +++ b/tests/roots/test-rtd-default/conf.py @@ -0,0 +1,6 @@ +extensions = ["sphinxext.opengraph"] + +master_doc = "index" +exclude_patterns = ["_build"] + +html_theme = "basic" diff --git a/tests/roots/test-rtd-default/index.rst b/tests/roots/test-rtd-default/index.rst new file mode 100644 index 0000000..634fe79 --- /dev/null +++ b/tests/roots/test-rtd-default/index.rst @@ -0,0 +1,8 @@ +* Item 1 +* Item 2 + + * Nested Item 1 + * Nested Item 2 + +* Item 3 +* Item 4 \ No newline at end of file diff --git a/tests/roots/test-rtd-invalid/conf.py b/tests/roots/test-rtd-invalid/conf.py new file mode 100644 index 0000000..7f99bb3 --- /dev/null +++ b/tests/roots/test-rtd-invalid/conf.py @@ -0,0 +1,6 @@ +extensions = ["sphinxext.opengraph"] + +master_doc = "index" +exclude_patterns = ["_build"] + +html_theme = "basic" diff --git a/tests/roots/test-rtd-invalid/index.rst b/tests/roots/test-rtd-invalid/index.rst new file mode 100644 index 0000000..634fe79 --- /dev/null +++ b/tests/roots/test-rtd-invalid/index.rst @@ -0,0 +1,8 @@ +* Item 1 +* Item 2 + + * Nested Item 1 + * Nested Item 2 + +* Item 3 +* Item 4 \ No newline at end of file diff --git a/tests/test_options.py b/tests/test_options.py index 81b0995..f6439ae 100644 --- a/tests/test_options.py +++ b/tests/test_options.py @@ -1,4 +1,7 @@ import pytest +from sphinx.application import Sphinx +import conftest +import os def get_tag(tags, tag_type): @@ -122,3 +125,36 @@ def test_skip_raw(og_meta_tags): description == "This text should be included. This text should also be included." ) + + +# use same as simple, as configuration is identical to overriden +@pytest.mark.sphinx("html", testroot="simple") +def test_rtd_override(app: Sphinx, monkeypatch): + monkeypatch.setenv("READTHEDOCS", "True") + app.config.html_baseurl = "https://failure.com" + + app.build() + tags = conftest._og_meta_tags(app) + + assert get_tag_content(tags, "url") == "http://example.org/index.html" + + +@pytest.mark.sphinx("html", testroot="rtd-default") +def test_rtd_valid(app: Sphinx, monkeypatch): + monkeypatch.setenv("READTHEDOCS", "True") + app.config.html_baseurl = "https://failure.com" + + app.build() + tags = conftest._og_meta_tags(app) + + assert get_tag_content(tags, "url") == "https://failure.com/index.html" + + +# use rtd-default, as we are not changing configuration, but RTD variables +@pytest.mark.sphinx("html", testroot="rtd-invalid") +def test_rtd_invalid(app: Sphinx, monkeypatch): + monkeypatch.setenv("READTHEDOCS", "True") + app.config.html_baseurl = None + + with pytest.raises(Exception): + app.build()