Layer of a Layout¶
Each layer can be specified in layout’s YAML file as a YAML list value for the layers
mapping.
size: { width: 250, height: 250 }
layers: # each layer in this list is denoted with a dash ('-')
- # layer 0
background:
color: orange
- # layer 1
icon:
image: sphinx_logo
- class Layer¶
Each layer can have different attributes. A typical layer has
size
andoffset
attributes with 1 additional attribute detailing abackground
oricon
ortypography
orrectangle
orellipse
. However, these attributes may combined as needed.Each attribute has a priority, so using multiple attributes on a single layer will render consistently. The priority order is as follows (excluding
size
andoffset
):Meaning, any
background
attribute is always rendered before other layer attributes. Additionally, anytypography
attribute is rendered after other attributes but before applying themask
.size: { width: 200, height: 200 } layers: - typography: # the layer's typography attribute content: "S" align: center background: # the layer's background attribute color: '{{ layout.background_color | yaml }}' icon: # the layer's icon attribute image: '{{ layout.logo.image }}' # NOTE that the order of layer attributes does not matter
Error
Each layer can only have 1 of each type of attribute. For example you cannot use 2
background
attributes in a single layer:size: { width: 600, height: 250 } layers: - background: { image: 'images/rainbow.png' } # The `background` attribute is overwritten by next line background: { color: '#ff000037' } # NOTE: The layer's background attribute is composed solely by # the last instance of the background attribute in the layer.
- background : Background | None¶
An optional Layer Background attribute.
- typography : Typography | None¶
An optional Layer Typography Attribute.
- rectangle : Rectangle | None¶
An optional Layer Rectangle attribute.
- ellipse : Ellipse | None¶
An optional Layer Ellipse attribute.
- polygon : Polygon | None¶
An optional Layer Polygon attribute.
- icon : Icon | None¶
An optional Layer Icon Attribute.
- size : Size | None¶
The layer
size
. Defaults to values inherited from thelayout.size
.
- mask : Mask | None¶
An optional Layer Mask attribute.
Using Jinja Syntax within the Layout¶
Seealso
It is advised to read up on how to use Jinja syntax.
Conventionally, Jinja syntax uses characters that have actual meaning in YAML. To help streamline the combination of YAML and Jinja syntaxes, this extension uses a modified jinja syntax:
Conventional |
sphinx-social-cards |
|
---|---|---|
|
|
|
|
|
|
|
|
Escaping Jinja Syntax¶
Use '{{ "'{{" }}'
to escape a Jinja reference.
layers:
- typography:
content: "'{{ "'{{" }}' page.title }}"
# renders as: "{{ page.title }}"
Layouts are Jinja Templates¶
A layout file is basically a Jinja template. So, layers can be generated dynamically using Jinja syntax.
#% set diameter, width, height = (100, 600, 250) %#
size:
width: '{{ width }}'
height: '{{ height }}'
layers:
- background: { color: '#0000007F' }
#% for i in range(3) %#
- ellipse:
color: "#'{{ ('0' * i) + 'F' + ('0' * (2 - i)) }}'"
size:
width: '{{ diameter }}'
height: '{{ diameter }}'
offset:
x: '{{ width / 6 * (i * 2 + 1) - (diameter / 2) }}'
y: '{{ (height - diameter) / 2 }}'
#% endfor %#
Inheriting Layouts¶
Layouts can even inherit from other layouts! The Jinja documentation has an excellent explanation on Template Inheritance. The rest of this section builds upon that useful information, so please read that first.
As a quick example, the default
layout is inherited by default/accent
and default/inverted
layouts. In those layouts, a Jinja block (#% block color_vals %#
) is used to override the
inherited color aliases.
#% block color_vals %#
bg_color: &bg_color '{{ layout.background_color | yaml }}'
fg_color: &fg_color '{{ layout.color | yaml }}'
#% endblock %#
#% extends "default.yml" %#
#% block color_vals %#
bg_color: &bg_color '{{ layout.accent | yaml }}'
fg_color: &fg_color '{{ layout.color | yaml }}'
#% endblock %#
#% extends "default.yml" %#
#% block color_vals %#
bg_color: &bg_color '{{ layout.color | yaml }}'
fg_color: &fg_color '{{ layout.background_color | yaml }}'
#% endblock %#
Note
The Jinja #% extends layout-file %#
statement requires the layout file name to be in
quotes. Additionally, if inheriting from a layout in a sub-directory of layouts, then use the
relative path to the layout.
#% extends "default/variant.yml" %#
Inheritance Tutorial¶
Let’s say you want to change the pre-designed opengraph
layout into a dark themed version.
This can easily be done by inheriting the opengraph
layout in your new custom layout. Upon
inspection, we will find 3 jinja blocks in the opengraph
layout’s source:
The
font_colors
block defines the colors used for fonts:1 2 3 4
#% block font_colors %# project_desc_color: &project_desc_color 'rgb(88, 94, 99)' title_url_color: &title_url_color 'rgb(47, 54, 61)' #% endblock %#
Important
We only need to change the actual color values.
Error
Changing the repeated tag names will break the layout.
The
background
block defines the layer that specifies the background:9 10 11 12 13 14 15 16
#% block background -%# - background: linear_gradient: preset: PremiumWhite start: {} end: { x: 400, y: 210} spread: reflect #%- endblock %#
The
watermark_icon
block defines the layer that specifies the sphinx logo in the bottom corner:81 82 83 84 85 86 87 88 89 90
#% block watermark_icon -%# icon: image: >- #% if page.meta.icon -%# '{{ page.meta.icon }}' #%- else -%# sphinx_logo #%- endif %# color: rgb(132, 146, 175) #%- endblock %#
Note
We could of course change this image via the
cards-icon
. But, notice the color for the icon is hard-coded because the background color is also hard-coded.
What about the other colors and stuff?
The color and image of the logo is already optionally controlled via the
cards_layout_options
[logo
]. Additionally, the color of the bottom stripe can already be
controlled via the cards_layout_options
[accent
]. Any further changes would necessitate a
completely new layout.
Now, we will create our custom layout file in the sphinx project’s source folder (adjacent to the
conf.py file) - typically in a docs
directory. Remember to add the directory path of this new
layout to social_cards
[cards_layout_dir
] and
social_cards
[cards_layout
] in the conf.py file. For this example, the new
layout will be located in docs/social_cards/opengraph-dark.yml
, so we add:
social_cards = {
"site_url": html_base_url,
"description": "a project-wide description",
"cards_layout_dir": "social_cards",
"cards_layout": "opengraph-dark",
}
In the newly created opengraph-dark.yml
file, we inherit the opengraph
layout and make our
customizations:
#% extends "opengraph.yml" %#
#% block font_colors %#
project_desc_color: &project_desc_color 'rgb(239, 240, 241)'
title_url_color: &title_url_color 'rgb(222, 230, 237)'
#% endblock %#
# We need to keep the same indent as the inherited source,
# otherwise the YAML parser may get confused.
#% block background -%#
- background:
linear_gradient:
start: {}
end: { x: 400, y: 210}
spread: reflect
colors:
0.0: rgb(23, 23, 23)
0.35: rgb(18, 18, 18)
1.0: rgb(13, 13, 13)
#%- endblock %#
#% block watermark_icon -%#
icon:
image: sphinx_logo
color: rgb(116, 116, 83)
#%- endblock %#
Referencing Jinja Contexts¶
Items of Jinja contexts can be referenced in the layout as Jinja variables:
layers:
- typography:
content: '{{ page.title }}' # (1)!
color: '{{ undefined }}' # (2)!
A YAML string that begins with a letter does not require extra surrounding quotes. Here, the single quotes are required for Jinja expressions, but they are removed by Jinja before the YAML is parsed.
Any reference to an undefined Jinja context variable is automatically converted to the YAML
null
value. This can be useful for font colors because anull
value will fallback to using the value oflayout.color
.
layers:
- icon:
image: >- # (1)!
#% if page.meta.icon %#
'{{ page.meta.icon }}'
#% else %#
'{{ layout.logo.image }}'
#% endif %#
Here
>
signifies that the following indented block is a single string, but line breaks are replaced with spaces. With-
,>-
instructs the YAML parser to strip a trailing line break from the multi-line string.
The yaml
Jinja filter (for referencing color values)¶
Seealso
Jinja comes with a bunch of documented builtin filters. General usage is briefly described in the Jinja Filters section.
Not all Jinja contexts hold a str
or int
value. For example, a color that was
specified as a gradient will be in the form of a Python dict
. If you want to support color
gradients in the layout, then a custom filter (yaml
) is added to the Jinja environment that
parses the layout before the YAML parser reads the layout.
layers:
- background:
color: '{{ layout.background_color | yaml }}' # (1)!
A
background_color
specified as a gradient like so:social_cards = { "cards_layout_options": { "background_color": { # a linear gradient "start": {"x": 0, "y": 0 }, "end": {"x": 1200, "y": 630}, "preset": 84, # aka "PhoenixStart" }, }, }
will be converted to a proper YAML mapping with the
yaml
filter:color: { start: { x: 0, y: 0 }, end: { x: 1200, y: 630 }, preset: 84 }
Solid colors do not need the yaml
filter
All Jinja Contexts that define a solid color are
automatically translated to use the string form, rgb(<red>, <green>, <blue>)
(or
rgba(<red>, <green>, <blue>, <alpha>)
if an alpha value/transparency was included).
Meaning, layout designers do not have to worry about colors specified with a beginning
#
which would be interpreted as a YAML comment (eg: "#0FF1CE"
is translated
to rgb(15, 241, 206)
).
Warning
Do not use a multi-line YAML string to reference colors from Jinja contexts. Doing so will result in a quoted YAML value:
layers:
- background:
color: >-
#% if layout.logo.color %#
'{{ layout.logo.color | yaml }}'
#% else %#
'{{ layout.background_color | yaml }}'
layers:
- background:
color: #% if layout.logo.color %#'{{ layout.logo.color | yaml }}'#% else %#'{{ layout.background_color | yaml }}'
Jinja Contexts¶
Every generated social card uses a set of Jinja contexts:
- class Config¶
A
dict
whose items expose some configuration options in conf.py. The following items are included in this context:- theme : Dict[str, Any]¶
A
dict
whose items correspond to thehtml_theme_options
. Thisdict
is very dependent on the choice of sphinx theme and what it defines in itstheme.conf
file.
- site_description : str | None¶
The
social_cards.description
value.
- site_url : str¶
The
social_cards.site_url
value. This value has the transport protocol (https://
) automatically removed for convenience.
- JinjaContexts.layout : Cards_Layout_Options¶
A
dict
whose items correspond to thecards_layout_options
.
- class Page¶
A
dict
whose items include the following:- meta : Dict[str, str]¶
A
dict
whose items correspond to the page’s Metadata (or meta element(s) created via the meta directive).