Skip to content

Commit

Permalink
Extract helper for _uri_values and rely on singledispatch to handle t…
Browse files Browse the repository at this point in the history
…he case of 'sheetOrStyle'.
  • Loading branch information
jaraco committed Mar 12, 2021
1 parent c73838b commit fece8b8
Showing 1 changed file with 43 additions and 22 deletions.
65 changes: 43 additions & 22 deletions cssutils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@
import urllib.parse
import xml.dom
import itertools
import functools

from . import errorhandler
from . import css
Expand Down Expand Up @@ -197,10 +198,6 @@ def setSerializer(serializer):

def _style_declarations(base):
"recursive generator to find all CSSStyleDeclarations"
if isinstance(base, css.CSSStyleDeclaration):
# base is a style already
yield base
return
for rule in getattr(base, 'cssRules', ()):
yield from _style_declarations(rule)
if hasattr(base, 'style'):
Expand All @@ -223,41 +220,65 @@ def getUrls(sheet):
other = (
value.uri
for style in _style_declarations(sheet)
for value in _uri_values(style)
)

return itertools.chain(imports, other)


def _uri_values(style):
return (
value
for prop in style.getProperties(all=True)
for value in prop.propertyValue
if value.type == 'URI'
)

return itertools.chain(imports, other)

_flatten = itertools.chain.from_iterable

def replaceUrls(sheetOrStyle, replacer, ignoreImportRules=False):

@functools.singledispatch
def replaceUrls(sheet, replacer, ignoreImportRules=False):
"""Replace all URLs in :class:`cssutils.css.CSSImportRule` or
:class:`cssutils.css.CSSValue` objects of given `sheetOrStyle`.
:class:`cssutils.css.CSSValue` objects of given `sheet`.
:param sheetOrStyle:
a :class:`cssutils.css.CSSStyleSheet` or a
:class:`cssutils.css.CSSStyleDeclaration` which is changed in place
:param sheet:
a :class:`cssutils.css.CSSStyleSheet` to be modified in place.
:param replacer:
a function which is called with a single argument `url` which
is the current value of each url() excluding ``url(``, ``)`` and
surrounding (single or double) quotes.
:param ignoreImportRules:
if ``True`` does not call `replacer` with URLs from @import rules.
"""
if not ignoreImportRules and not isinstance(sheetOrStyle, css.CSSStyleDeclaration):
imports = (rule for rule in sheetOrStyle if rule.type == rule.IMPORT_RULE)
for rule in imports:
rule.href = replacer(rule.href)

values = (
value
for style in _style_declarations(sheetOrStyle)
for prop in style.getProperties(all=True)
for value in prop.propertyValue
if value.type == 'URI'
imports = (
rule
for rule in sheet
if rule.type == rule.IMPORT_RULE and not ignoreImportRules
)
for value in values:
for rule in imports:
rule.href = replacer(rule.href)

for value in _flatten(map(_uri_values, _style_declarations(sheet))):
value.uri = replacer(value.uri)


@replaceUrls.register(css.CSSStyleDeclaration)
def _(style, replacer, ignoreImportRules=False):
"""Replace all URLs in :class:`cssutils.css.CSSImportRule` or
:class:`cssutils.css.CSSValue` objects of given `style`.
:param style:
a :class:`cssutils.css.CSSStyleDeclaration` to be modified in place.
:param replacer:
a function which is called with a single argument `url` which
is the current value of each url() excluding ``url(``, ``)`` and
surrounding (single or double) quotes.
:param ignoreImportRules:
not applicable, ignored.
"""
for value in _uri_values(style):
value.uri = replacer(value.uri)


Expand Down

0 comments on commit fece8b8

Please sign in to comment.