Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-soupsieve for
openSUSE:Factory checked in at 2026-07-07 20:59:53
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-soupsieve (Old)
and /work/SRC/openSUSE:Factory/.python-soupsieve.new.1982 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-soupsieve"
Tue Jul 7 20:59:53 2026 rev:27 rq:1363852 version:2.8.4
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-soupsieve/python-soupsieve.changes
2026-01-28 15:07:15.178266980 +0100
+++
/work/SRC/openSUSE:Factory/.python-soupsieve.new.1982/python-soupsieve.changes
2026-07-07 21:00:11.676091683 +0200
@@ -1,0 +2,9 @@
+Sun Jul 5 10:39:45 UTC 2026 - Dirk Müller <[email protected]>
+
+- update to 2.8.4:
+ * **FIX**: Fix another inefficient attribute pattern
+ (@mauriceng98).
+ * **FIX**: Limit total number of selectors processed in a
+ pattern to prevent massive selector requests (@mauriceng98).
+
+-------------------------------------------------------------------
Old:
----
soupsieve-2.8.3.tar.gz
New:
----
soupsieve-2.8.4.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-soupsieve.spec ++++++
--- /var/tmp/diff_new_pack.jYR3GS/_old 2026-07-07 21:00:14.236178213 +0200
+++ /var/tmp/diff_new_pack.jYR3GS/_new 2026-07-07 21:00:14.248178618 +0200
@@ -26,7 +26,7 @@
%endif
%{?sle15_python_module_pythons}
Name: python-soupsieve%{psuffix}
-Version: 2.8.3
+Version: 2.8.4
Release: 0
Summary: A modern CSS selector implementation for BeautifulSoup
License: MIT
++++++ soupsieve-2.8.3.tar.gz -> soupsieve-2.8.4.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/soupsieve-2.8.3/PKG-INFO new/soupsieve-2.8.4/PKG-INFO
--- old/soupsieve-2.8.3/PKG-INFO 2020-02-02 01:00:00.000000000 +0100
+++ new/soupsieve-2.8.4/PKG-INFO 2020-02-02 01:00:00.000000000 +0100
@@ -1,6 +1,6 @@
Metadata-Version: 2.4
Name: soupsieve
-Version: 2.8.3
+Version: 2.8.4
Summary: A modern CSS selector implementation for Beautiful Soup.
Project-URL: Homepage, https://github.com/facelessuser/soupsieve
Author-email: Isaac Muse <[email protected]>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/soupsieve-2.8.3/docs/src/markdown/about/changelog.md
new/soupsieve-2.8.4/docs/src/markdown/about/changelog.md
--- old/soupsieve-2.8.3/docs/src/markdown/about/changelog.md 2020-02-02
01:00:00.000000000 +0100
+++ new/soupsieve-2.8.4/docs/src/markdown/about/changelog.md 2020-02-02
01:00:00.000000000 +0100
@@ -3,6 +3,11 @@
---
# Changelog
+## 2.8.4
+
+- **FIX**: Fix another inefficient attribute pattern (@mauriceng98).
+- **FIX**: Limit total number of selectors processed in a pattern to prevent
massive selector requests (@mauriceng98).
+
## 2.8.3
- **FIX**: Fix inefficient attribute pattern.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/soupsieve-2.8.3/docs/src/markdown/api.md
new/soupsieve-2.8.4/docs/src/markdown/api.md
--- old/soupsieve-2.8.3/docs/src/markdown/api.md 2020-02-02
01:00:00.000000000 +0100
+++ new/soupsieve-2.8.4/docs/src/markdown/api.md 2020-02-02
01:00:00.000000000 +0100
@@ -26,7 +26,7 @@
> [!tip] Getting Proper Namespaces
> The `html5lib` parser provides proper namespaces for HTML5, but `lxml`'s
HTML parser will not. If you need
> namespace support for HTML5, consider using `html5lib`.
- >
+ >
> For XML, the `lxml-xml` parser (`xml` for short) will provide proper
namespaces. It is generally suggested that
> `lxml-xml` is used to parse XHTML documents to take advantage of
namespaces.
@@ -37,6 +37,12 @@
While Soup Sieve access is exposed through Beautiful Soup's API, Soup Sieve's
API can always be imported and accessed
directly for more controlled tag selection if needed.
+> [!note] Selector Limits
+> Starting in 2.8.4, number of selectors in a given pattern are arbitrarily
capped at ~8192. This limitation was added
+> to prevent cases where impractical, massive selectors.
+>
+> Some selectors are defined as a series of other pre-defined selectors which
also contribute towards the count.
+
## Flags
### `soupseive.DEBUG`
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/soupsieve-2.8.3/docs/src/markdown/selectors/pseudo-classes.md
new/soupsieve-2.8.4/docs/src/markdown/selectors/pseudo-classes.md
--- old/soupsieve-2.8.3/docs/src/markdown/selectors/pseudo-classes.md
2020-02-02 01:00:00.000000000 +0100
+++ new/soupsieve-2.8.4/docs/src/markdown/selectors/pseudo-classes.md
2020-02-02 01:00:00.000000000 +0100
@@ -1707,7 +1707,7 @@
Selects elements that contain the provided text. Text can be found in either
itself, or its descendants.
Originally, there was a pseudo-class called `:contains()` that was originally
included in a [CSS early draft][contains-draft],
-but was dropped from the draft in the end. Soup Sieve implements it how it was
originally proposed accept for two
+but was dropped from the draft in the end. Soup Sieve implements it how it was
originally proposed except for two
differences: it is called `:-soup-contains()` instead of `:contains()`, and it
can accept either a single value, or a
comma separated list of values. An element needs only to match at least one of
the items in the comma separated list to
be considered matching.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/soupsieve-2.8.3/pyproject.toml
new/soupsieve-2.8.4/pyproject.toml
--- old/soupsieve-2.8.3/pyproject.toml 2020-02-02 01:00:00.000000000 +0100
+++ new/soupsieve-2.8.4/pyproject.toml 2020-02-02 01:00:00.000000000 +0100
@@ -1,6 +1,6 @@
[build-system]
requires = [
- "hatchling>=0.21.1",
+ "hatchling>=1.26",
]
build-backend = "hatchling.build"
@@ -54,7 +54,7 @@
"/tests/**/*.py",
"/.pyspelling.yml",
"/.coveragerc",
- "/mkdocs.yml"
+ "/zensical.yml"
]
[tool.mypy]
@@ -128,7 +128,7 @@
deps =
-rrequirements/docs.txt
commands =
- {envbindir}/zensical build -f zensical.yml --clean --strict
+ {envbindir}/zensical build -f zensical.yml --clean
pyspelling -j 8
[testenv:lint]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/soupsieve-2.8.3/soupsieve/__meta__.py
new/soupsieve-2.8.4/soupsieve/__meta__.py
--- old/soupsieve-2.8.3/soupsieve/__meta__.py 2020-02-02 01:00:00.000000000
+0100
+++ new/soupsieve-2.8.4/soupsieve/__meta__.py 2020-02-02 01:00:00.000000000
+0100
@@ -193,5 +193,5 @@
return Version(major, minor, micro, release, pre, post, dev)
-__version_info__ = Version(2, 8, 3, "final")
+__version_info__ = Version(2, 8, 4, "final")
__version__ = __version_info__._get_canonical()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/soupsieve-2.8.3/soupsieve/css_parser.py
new/soupsieve-2.8.4/soupsieve/css_parser.py
--- old/soupsieve-2.8.3/soupsieve/css_parser.py 2020-02-02 01:00:00.000000000
+0100
+++ new/soupsieve-2.8.4/soupsieve/css_parser.py 2020-02-02 01:00:00.000000000
+0100
@@ -11,6 +11,8 @@
UNICODE_REPLACEMENT_CHAR = 0xFFFD
+SELECTOR_LIMIT = 8192
+
# Simple pseudo classes that take no parameters
PSEUDO_SIMPLE = {
":any-link",
@@ -118,7 +120,7 @@
# `nth` content
NTH = fr'(?:[-+])?(?:[0-9]+n?|n)(?:(?<=n){WSC}*(?:[-+]){WSC}*(?:[0-9]+))?'
# Value: quoted string or identifier
-VALUE =
fr'''(?:"(?:\\(?:.|{NEWLINE})|[^\\"\r\n\f]+)*?"|'(?:\\(?:.|{NEWLINE})|[^\\'\r\n\f]+)*?'|{IDENTIFIER})'''
+VALUE =
fr'''(?:"(?:\\(?:.|{NEWLINE})|[^\\"\r\n\f])*?"|'(?:\\(?:.|{NEWLINE})|[^\\'\r\n\f])*?'|{IDENTIFIER})'''
# Attribute value comparison. `!=` is handled special as it is non-standard.
ATTR =
fr'(?:{WSC}*(?P<cmp>[!~^|*$]?=){WSC}*(?P<value>{VALUE})(?:{WSC}*(?P<case>[is]))?)?{WSC}*'
@@ -468,6 +470,13 @@
self.flags = flags
self.debug = self.flags & util.DEBUG
self.custom = {} if custom is None else custom
+ self.count = 0
+
+ def check_count(self) -> None:
+ """Check the current selector count."""
+
+ if self.count > SELECTOR_LIMIT:
+ raise ValueError(f'Selector exceeds pseudo-class nesting limit of
{SELECTOR_LIMIT}')
def parse_attribute_selector(self, sel: _Selector, m: Match[str],
has_selector: bool) -> bool:
"""Create attribute selector from the returned regex match."""
@@ -572,6 +581,9 @@
).process_selectors(flags=FLG_PSEUDO)
self.custom[pseudo] = selector
+ self.count += selector.count
+ self.check_count()
+
sel.selectors.append(selector)
has_selector = True
return has_selector
@@ -603,34 +615,64 @@
elif pseudo == ':empty':
sel.flags |= ct.SEL_EMPTY
elif pseudo in (':link', ':any-link'):
+ self.count += CSS_LINK.count
+ self.check_count()
sel.selectors.append(CSS_LINK)
elif pseudo == ':checked':
+ self.count += CSS_CHECKED.count
+ self.check_count()
sel.selectors.append(CSS_CHECKED)
elif pseudo == ':default':
+ self.count += CSS_DEFAULT.count
+ self.check_count()
sel.selectors.append(CSS_DEFAULT)
elif pseudo == ':indeterminate':
+ self.count += CSS_INDETERMINATE.count
+ self.check_count()
sel.selectors.append(CSS_INDETERMINATE)
elif pseudo == ":disabled":
+ self.count += CSS_DISABLED.count
+ self.check_count()
sel.selectors.append(CSS_DISABLED)
elif pseudo == ":enabled":
+ self.count += CSS_ENABLED.count
+ self.check_count()
sel.selectors.append(CSS_ENABLED)
elif pseudo == ":required":
+ self.count += CSS_REQUIRED.count
+ self.check_count()
sel.selectors.append(CSS_REQUIRED)
elif pseudo == ":muted":
+ self.count += CSS_MUTED.count
+ self.check_count()
sel.selectors.append(CSS_MUTED)
elif pseudo == ":open":
+ self.count += CSS_OPEN.count
+ self.check_count()
sel.selectors.append(CSS_OPEN)
elif pseudo == ":optional":
+ self.count += CSS_OPTIONAL.count
+ self.check_count()
sel.selectors.append(CSS_OPTIONAL)
elif pseudo == ":read-only":
+ self.count += CSS_READ_ONLY.count
+ self.check_count()
sel.selectors.append(CSS_READ_ONLY)
elif pseudo == ":read-write":
+ self.count += CSS_READ_WRITE.count
+ self.check_count()
sel.selectors.append(CSS_READ_WRITE)
elif pseudo == ":in-range":
+ self.count += CSS_IN_RANGE.count
+ self.check_count()
sel.selectors.append(CSS_IN_RANGE)
elif pseudo == ":out-of-range":
+ self.count += CSS_OUT_OF_RANGE.count
+ self.check_count()
sel.selectors.append(CSS_OUT_OF_RANGE)
elif pseudo == ":placeholder-shown":
+ self.count += CSS_PLACEHOLDER_SHOWN.count
+ self.check_count()
sel.selectors.append(CSS_PLACEHOLDER_SHOWN)
elif pseudo == ':first-child':
sel.nth.append(ct.SelectorNth(1, False, 0, False, False,
ct.SelectorList()))
@@ -731,6 +773,8 @@
else:
# Use default `*|*` for `of S`.
nth_sel = CSS_NTH_OF_S_DEFAULT
+ self.count += nth_sel.count
+ self.check_count()
if pseudo_sel == ':nth-child':
sel.nth.append(ct.SelectorNth(s1, var, s2, False, False,
nth_sel))
elif pseudo_sel == ':nth-last-child':
@@ -937,6 +981,7 @@
closed = False
relations = [] # type: list[_Selector]
rel_type = ":" + WS_COMBINATOR
+ count = self.count
# Setup various flags
is_open = bool(flags & FLG_OPEN)
@@ -984,6 +1029,10 @@
while True:
key, m = next(iselector)
+ if key not in ('combine', 'pseudo_close'):
+ self.count += 1
+ self.check_count()
+
# Handle parts
if key == "at_rule":
raise NotImplementedError(f"At-rules found at position
{m.start(0)}")
@@ -1103,7 +1152,7 @@
selectors[-1].flags = ct.SEL_PLACEHOLDER_SHOWN
# Return selector list
- return ct.SelectorList([s.freeze() for s in selectors], is_not,
is_html)
+ return ct.SelectorList([s.freeze() for s in selectors], is_not,
is_html, self.count - count)
def selector_iter(self, pattern: str) -> Iterator[tuple[str, Match[str]]]:
"""Iterate selector tokens."""
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/soupsieve-2.8.3/soupsieve/css_types.py
new/soupsieve-2.8.4/soupsieve/css_types.py
--- old/soupsieve-2.8.3/soupsieve/css_types.py 2020-02-02 01:00:00.000000000
+0100
+++ new/soupsieve-2.8.4/soupsieve/css_types.py 2020-02-02 01:00:00.000000000
+0100
@@ -351,24 +351,27 @@
class SelectorList(Immutable):
"""Selector list."""
- __slots__ = ("selectors", "is_not", "is_html", "_hash")
+ __slots__ = ("selectors", "is_not", "is_html", "count", "_hash")
selectors: tuple[Selector | SelectorNull, ...]
is_not: bool
is_html: bool
+ count: int
def __init__(
self,
selectors: Iterable[Selector | SelectorNull] | None = None,
is_not: bool = False,
- is_html: bool = False
+ is_html: bool = False,
+ count: int = 0,
) -> None:
"""Initialize."""
super().__init__(
selectors=tuple(selectors) if selectors is not None else (),
is_not=is_not,
- is_html=is_html
+ is_html=is_html,
+ count=count
)
def __iter__(self) -> Iterator[Selector | SelectorNull]:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/soupsieve-2.8.3/tests/test_api.py
new/soupsieve-2.8.4/tests/test_api.py
--- old/soupsieve-2.8.3/tests/test_api.py 2020-02-02 01:00:00.000000000
+0100
+++ new/soupsieve-2.8.4/tests/test_api.py 2020-02-02 01:00:00.000000000
+0100
@@ -592,6 +592,38 @@
with self.assertRaises(TypeError):
sv.filter('div', "not a tag", flags=flags)
+ def test_excessive_selectors(self):
+ """Test excessive selectors."""
+
+ # Build a 500 KB selector string: "a,a,a,...,a" (250,000 items)
+ count = 10000
+ selector = ",".join("a" for _ in range(count))
+
+ # Compile the selector
+ with self.assertRaises(ValueError):
+ sv.compile(selector)
+
+ def test_excessive_custom_selectors(self):
+ """Test excessive custom selectors."""
+
+ # Build a 500 KB selector string: "a,a,a,...,a" (250,000 items)
+ count = 10000
+ selector = ",".join("a" for _ in range(count))
+
+ # Compile the selector
+ with self.assertRaises(ValueError):
+ sv.compile('div:--custom', custom={':--custom': selector})
+
+ def test_excessive_custom_and_normal_selectors(self):
+ """Test excessive custom and normal selectors."""
+
+ count = 5000
+ selector = ",".join("a" for _ in range(count))
+
+ # Compile the selector
+ with self.assertRaises(ValueError):
+ sv.compile(f':is({selector}):--custom', custom={':--custom':
selector})
+
class TestSyntaxErrorReporting(util.TestCase):
"""Test reporting of syntax errors."""
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/soupsieve-2.8.3/tests/test_extra/test_attribute.py
new/soupsieve-2.8.4/tests/test_extra/test_attribute.py
--- old/soupsieve-2.8.3/tests/test_extra/test_attribute.py 2020-02-02
01:00:00.000000000 +0100
+++ new/soupsieve-2.8.4/tests/test_extra/test_attribute.py 2020-02-02
01:00:00.000000000 +0100
@@ -62,3 +62,31 @@
self.assertEqual(e.context,
'[\\]!=D4XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n^')
self.assertEqual(e.line, 1)
self.assertEqual(e.col, 1)
+
+ def test_bad_attribute_unclused(self):
+ """Test bad attribute fails for syntax error, not timeout error."""
+
+ import platform
+
+ if platform.system() == 'Windows':
+ with self.assertRaises(sv.SelectorSyntaxError):
+ sv.compile('[a="' + ('x' * 300))
+ else:
+ import signal
+
+ def timeout_handler(signum, frame):
+ raise TimeoutError
+
+ signal.signal(signal.SIGALRM, timeout_handler)
+ signal.alarm(3)
+
+ passed = False
+ try:
+ with self.assertRaises(sv.SelectorSyntaxError):
+ sv.compile('[a="' + ('x' * 300))
+ passed = True
+ except TimeoutError:
+ pass
+ finally:
+ signal.alarm(0)
+ self.assertTrue(passed)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/soupsieve-2.8.3/zensical.yml
new/soupsieve-2.8.4/zensical.yml
--- old/soupsieve-2.8.3/zensical.yml 1970-01-01 01:00:00.000000000 +0100
+++ new/soupsieve-2.8.4/zensical.yml 2020-02-02 01:00:00.000000000 +0100
@@ -0,0 +1,198 @@
+site_name: Soup Sieve
+site_url: https://facelessuser.github.io/soupsieve
+repo_url: https://github.com/facelessuser/soupsieve
+edit_uri: tree/main/docs/src/markdown
+site_description: A modern CSS selector library for Beautiful Soup.
+copyright: |
+ Copyright © 2018 - 2026 <a href="https://github.com/facelessuser"
target="_blank" rel="noopener">Isaac Muse</a>
+
+docs_dir: docs/src/markdown
+theme:
+ name: material
+ custom_dir: docs/theme
+ icon:
+ logo: material/book-open-page-variant
+ palette:
+ # Palette toggle for system
+ - media: "(prefers-color-scheme)"
+ toggle:
+ icon: material/brightness-auto
+ name: Switch to light mode
+
+ # Palette toggle for light mode
+ - media: "(prefers-color-scheme: light)"
+ scheme: default
+ primary: deep purple
+ accent: deep purple
+ toggle:
+ icon: lucide/sun
+ name: Switch to dark mode
+
+ # Palette toggle for dark mode
+ - media: "(prefers-color-scheme: dark)"
+ scheme: slate
+ primary: deep purple
+ accent: deep purple
+ toggle:
+ icon: lucide/moon
+ name: Switch to light mode
+ font:
+ text: Roboto
+ code: Roboto Mono
+ features:
+ - announce.dismiss
+ - navigation.tabs
+ - navigation.top
+ - navigation.instant
+ - navigation.indexes
+ - navigation.path
+ - navigation.footer
+ - toc.follow
+ - content.tabs.link
+ - search.share
+ - search.highlight
+ - search.suggest
+ - content.code.copy
+ - content.tabs.link
+ - content.code.annotations
+
+nav:
+ - Home:
+ - Quick Start: index.md
+ - API: api.md
+ - F.A.Q.: faq.md
+ - Beautiful Soup Differences: differences.md
+ - CSS Selectors:
+ - General Details: selectors/index.md
+ - Basic Selectors: selectors/basic.md
+ - Combinators and Lists: selectors/combinators.md
+ - Pseudo Classes: selectors/pseudo-classes.md
+ - Non-Applicable Pseudo Classes: selectors/unsupported.md
+ - About:
+ - Contributing & Support: about/contributing.md
+ - Development: about/development.md
+ - Security Vulnerabilities: about/security.md
+ - Changelog: about/changelog.md
+ - License: about/license.md
+
+markdown_extensions:
+ - markdown.extensions.toc:
+ slugify: !!python/object/apply:pymdownx.slugs.slugify {kwds: {case:
lower}}
+ permalink: ""
+ - markdown.extensions.smarty:
+ smart_quotes: false
+ - pymdownx.betterem:
+ - markdown.extensions.attr_list:
+ - markdown.extensions.tables:
+ - markdown.extensions.abbr:
+ - markdown.extensions.md_in_html:
+ - pymdownx.superfences:
+ - pymdownx.highlight:
+ line_spans: __codeline
+ line_anchors: __codelineno
+ anchor_linenums: True
+ extend_pygments_lang:
+ - name: pycon3
+ lang: pycon
+ options:
+ python3: true
+ - pymdownx.inlinehilite:
+ - pymdownx.magiclink:
+ repo_url_shortener: true
+ repo_url_shorthand: true
+ social_url_shorthand: true
+ user: facelessuser
+ repo: soupsieve
+ - pymdownx.tilde:
+ - pymdownx.caret:
+ - pymdownx.smartsymbols:
+ - pymdownx.emoji:
+ emoji_index: !!python/name:material.extensions.emoji.twemoji
+ emoji_generator: !!python/name:material.extensions.emoji.to_svg
+ - pymdownx.escapeall:
+ hardbreak: True
+ nbsp: True
+ - pymdownx.tasklist:
+ custom_checkbox: true
+ - pymdownx.progressbar:
+ - pymdownx.mark:
+ - pymdownx.striphtml:
+ - pymdownx.snippets:
+ base_path:
+ - docs/src/markdown/.snippets
+ - LICENSE.md
+ - SECURITY.md
+ auto_append:
+ - refs.md
+ - pymdownx.keys:
+ separator: "\uff0b"
+ - pymdownx.saneheaders:
+ - pymdownx.blocks.admonition:
+ types:
+ - new
+ - settings
+ - note
+ - abstract
+ - info
+ - tip
+ - success
+ - question
+ - warning
+ - failure
+ - danger
+ - bug
+ - example
+ - quote
+ - pymdownx.blocks.details:
+ types:
+ - name: details-new
+ class: new
+ - name: details-settings
+ class: settings
+ - name: details-note
+ class: note
+ - name: details-abstract
+ class: abstract
+ - name: details-info
+ class: info
+ - name: details-tip
+ class: tip
+ - name: details-success
+ class: success
+ - name: details-question
+ class: question
+ - name: details-warning
+ class: warning
+ - name: details-failure
+ class: failure
+ - name: details-danger
+ class: danger
+ - name: details-bug
+ class: bug
+ - name: details-example
+ class: example
+ - name: details-quote
+ class: quote
+ - pymdownx.blocks.html:
+ - pymdownx.blocks.definition:
+ - pymdownx.blocks.tab:
+ alternate_style: True
+ - pymdownx.blocks.caption:
+ - pymdownx.fancylists:
+ inject_style: true
+ - pymdownx.quotes:
+ callouts: true
+
+extra:
+ social:
+ - icon: fontawesome/brands/github
+ link: https://github.com/facelessuser
+
+extra_css:
+ - assets/pymdownx-extras/extra-95634471d6.css
+extra_javascript:
+ - assets/pymdownx-extras/extra-loader-Ccztcqfq.js
+
+plugins:
+ - search:
+ separator: '[:\s\-]+'