Skip to content

Add per-file overrides using field lists #50

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 23 commits into from
Feb 21, 2022
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
297ba8e
Use field lists to implement per page overrides
ItayZiv Dec 6, 2021
b56c4c5
Move location where quotes are escaped so that it will work with per …
ItayZiv Dec 6, 2021
82299a0
Add title override
ItayZiv Dec 6, 2021
63655fd
Add documentation for field lists
ItayZiv Dec 6, 2021
3a8e623
Fix empty field lists from crashing
ItayZiv Dec 6, 2021
cbdcc0f
Add tests
ItayZiv Dec 12, 2021
00b05ca
Refractor to use fields.get to get the values
ItayZiv Jan 26, 2022
a72b254
Run black
ItayZiv Jan 26, 2022
fd86b2f
Add arbitrary tags support
ItayZiv Jan 27, 2022
fc6d023
Add tests for arbitrary tags
ItayZiv Jan 27, 2022
13fb48a
Add documentation for arbitrary tags
ItayZiv Jan 27, 2022
0f3e4a8
Prevent creation of multiple tags with the same property
ItayZiv Jan 27, 2022
0f1298a
Revert "Prevent creation of multiple tags with the same property"
ItayZiv Jan 28, 2022
b846603
Rework overrides and arbitrary tags and slightly change syntax
ItayZiv Feb 2, 2022
4ad988f
Update readme.md and adjust image:alt functionality
ItayZiv Feb 2, 2022
d0707a9
Apply suggestions from code review
ItayZiv Feb 2, 2022
c3ab424
Run black
ItayZiv Feb 2, 2022
8ee2ff6
Remove any support for relative paths with field lists and add a note
ItayZiv Feb 2, 2022
6db225b
Revert relative url behaviour
ItayZiv Feb 3, 2022
7ec4e17
Change readme to align with previous commit
ItayZiv Feb 3, 2022
a43d75b
Disable relative file paths with field lists
ItayZiv Feb 3, 2022
18c4aa6
Fix typo in comments
ItayZiv Feb 3, 2022
1ca449d
Update README.md
ItayZiv Feb 3, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 30 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ Users hosting documentation on Read The Docs *do not* need to set any of the fol
* This sets the ogp type attribute, for more information on the types available please take a look at https://ogp.me/#types. By default it is set to `website`, which should be fine for most use cases.
* `ogp_custom_meta_tags`
* This is not required. List of custom html snippets to insert.

## Example Config

### Simple Config
Expand All @@ -60,3 +60,32 @@ ogp_custom_meta_tags = [
]

```

## Per Page Overrides
[Field lists](https://www.sphinx-doc.org/en/master/usage/restructuredtext/field-lists.html) are used to allow you to override certain settings on each page.

Make sure you place the fields at the very start of the document such that Sphinx will pick them up and also won't build them into the html.

### Overrides

* `:ogp-description-length:`
* Configure the amount of characters to grab for the description of the page. If the value isn't a number it will fall back to `ogp_description_length`.
* `:ogp-description:`
* Lets you override the description of the page.
* `:ogp-title:`
* Lets you override the title of the page.
* `:ogp-type:`
* Override the type of the page, for the list of available types take a look at https://ogp.me/#types.
* `:ogp-image:`
* Set the image for the page.
* `:ogp-image-alt:`
* Will be ignored if the image isn't set with the above field, if the image is set, sets the alt text for it.

### Example
Remember that the fields **must** be placed at the very start of the file. You can verify Sphinx has picked up the fields if they aren't shown in the final html file.

```rst
:ogp-description: New description
:ogp-image: http://example.org/image.png
:ogp-image-alt: Example Image
```
43 changes: 35 additions & 8 deletions sphinxext/opengraph/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@


def make_tag(property: str, content: str) -> str:
# Parse quotation, so they won't break html tags if smart quotes are disabled
content = content.replace('"', """)
return f'<meta property="{property}" content="{content}" />\n '


Expand All @@ -38,10 +40,17 @@ def get_tags(
doctree: nodes.document,
config: Dict[str, Any],
) -> str:
# Get field lists for per-poge overrides
fields = context["meta"]
if fields is None:
fields = {}

# Set length of description
try:
desc_len = int(config["ogp_description_length"])
try:
desc_len = int(fields["ogp-description-length"])
except (ValueError, KeyError):
desc_len = int(config["ogp_description_length"])
except ValueError:
desc_len = DEFAULT_DESCRIPTION_LENGTH

Expand All @@ -50,15 +59,24 @@ def get_tags(
title_excluding_html = get_title(context["title"], skip_html_tags=True)

# Parse/walk doctree for metadata (tag/description)
description = get_description(doctree, desc_len, [title, title_excluding_html])
if "ogp-description" in fields:
description = fields["ogp-description"]
else:
description = get_description(doctree, desc_len, [title, title_excluding_html])

tags = "\n "

# title tag
tags += make_tag("og:title", title)
tags += make_tag(
"og:title", title if "ogp-title" not in fields else fields["ogp-title"]
)

# type tag
tags += make_tag("og:type", config["ogp_type"])
tags += make_tag(
"og:type",
config["ogp_type"] if "ogp-type" not in fields else fields["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"])
Expand Down Expand Up @@ -86,7 +104,11 @@ def get_tags(
tags += make_tag("og:url", page_url)

# site name tag
site_name = config["ogp_site_name"]
site_name = (
config["ogp_site_name"]
if "ogp-site-name" not in fields
else fields["ogp-site-name"]
)
if site_name:
tags += make_tag("og:site_name", site_name)

Expand All @@ -96,9 +118,14 @@ def get_tags(

# image tag
# Get basic values from config
image_url = config["ogp_image"]
ogp_use_first_image = config["ogp_use_first_image"]
ogp_image_alt = config["ogp_image_alt"]
if "ogp-image" in fields:
image_url = fields["ogp-image"]
ogp_use_first_image = False
ogp_image_alt = fields["ogp-image-alt"] if "ogp-image-alt" in fields else None
else:
image_url = config["ogp_image"]
ogp_use_first_image = config["ogp_use_first_image"]
ogp_image_alt = config["ogp_image_alt"]

if ogp_use_first_image:
first_image = doctree.next_node(nodes.image)
Expand Down
5 changes: 2 additions & 3 deletions sphinxext/opengraph/descriptionparser.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ def __init__(

# Hack to prevent requirement for the doctree to be passed in.
# It's only used by doctree.walk(...) to print debug messages.
if document == None:
if document is None:

class document_cls:
class reporter:
Expand Down Expand Up @@ -124,5 +124,4 @@ def get_description(

mcv = DescriptionParser(description_length, known_titles, document)
doctree.walkabout(mcv)
# Parse quotation so they won't break html tags if smart quotes are disabled
return mcv.description.replace('"', "&quot;")
return mcv.description
10 changes: 10 additions & 0 deletions tests/roots/test-overrides-complex/conf.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
extensions = ["sphinxext.opengraph"]

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

html_theme = "basic"

ogp_site_name = "Example's Docs!"
ogp_site_url = "http://example.org/"
ogp_image_alt = "Example Alt Text"
6 changes: 6 additions & 0 deletions tests/roots/test-overrides-complex/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
:ogp-description-length: 10
:ogp-image: img/sample.jpg
:ogp-image-alt: Overridden Alt Text
Lorem Ipsum
===========
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse at lorem ornare, fringilla massa nec, venenatis mi. Donec erat sapien, tincidunt nec rhoncus nec, scelerisque id diam. Orci varius natoque penatibus et magnis dis parturient mauris.
11 changes: 11 additions & 0 deletions tests/roots/test-overrides-simple/conf.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
extensions = ["sphinxext.opengraph"]

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

html_theme = "basic"

ogp_site_name = "Example's Docs!"
ogp_site_url = "http://example.org/"
ogp_image = "http://example.org/image.png"
ogp_type = "book"
7 changes: 7 additions & 0 deletions tests/roots/test-overrides-simple/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
:ogp-description: Overridden description
:ogp-title: Overridden Title
:ogp-type: article
:ogp-image: http://example.org/overridden-image.png
Lorem Ipsum
===========
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse at lorem ornare, fringilla massa nec, venenatis mi. Donec erat sapien, tincidunt nec rhoncus nec, scelerisque id diam. Orci varius natoque penatibus et magnis dis parturient mauris.
20 changes: 20 additions & 0 deletions tests/test_options.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,26 @@ def test_quotation_marks(og_meta_tags):
)


@pytest.mark.sphinx("html", testroot="overrides-simple")
def test_overrides_simple(og_meta_tags):
assert get_tag_content(og_meta_tags, "description") == "Overridden description"
assert get_tag_content(og_meta_tags, "title") == "Overridden Title"
assert get_tag_content(og_meta_tags, "type") == "article"
assert (
get_tag_content(og_meta_tags, "image")
== "http://example.org/overridden-image.png"
)
# Make sure alt text still works even when overriding the image
assert get_tag_content(og_meta_tags, "image:alt") == "Example's Docs!"


@pytest.mark.sphinx("html", testroot="overrides-complex")
def test_overrides_complex(og_meta_tags):
assert len(get_tag_content(og_meta_tags, "description")) == 10
assert get_tag_content(og_meta_tags, "image") == "http://example.org/img/sample.jpg"
assert get_tag_content(og_meta_tags, "image:alt") == "Overridden Alt Text"


# use same as simple, as configuration is identical to overriden
@pytest.mark.sphinx("html", testroot="simple")
def test_rtd_override(app: Sphinx, monkeypatch):
Expand Down