def get_selectors(document, selectors): view = {} for selector in selectors: val = selectors.get(selector) cssselector = CSSSelector(selector) matching = cssselector.evaluate(document) # print(selector, info) for element in matching: info = val if callable(val): info = val(selector, element) if element not in view: view[element] = {} if info: view[element].update(info) else: # head = view[element].get('start', '') # tail = view[element].get('end', '') if info: view[element].update(info) return view
def getView(document, css, media='all', name=None, styleCallback=lambda element: None): """ document a DOM document, currently an lxml HTML document css a CSS StyleSheet string media: optional TODO: view for which media it should be name: optional TODO: names of sheets only styleCallback: optional should return css.CSSStyleDeclaration of inline styles, for html a style declaration for ``element@style``. Gets one parameter ``element`` which is the relevant DOMElement returns style view a dict of {DOMElement: css.CSSStyleDeclaration} for html """ sheet = cssutils.parseString(css) view = {} specificities = {} # needed temporarily # TODO: filter rules simpler?, add @media rules = (rule for rule in sheet if rule.type == rule.STYLE_RULE) for rule in rules: for selector in rule.selectorList: log(0, 'SELECTOR', selector.selectorText) # TODO: make this a callback to be able to use other stuff than lxml cssselector = CSSSelector(selector.selectorText) matching = cssselector.evaluate(document) for element in matching: #if element.tag in ('div',): # add styles for all matching DOM elements log(1, 'ELEMENT', id(element), element.text) if element not in view: # add initial empty style declatation view[element] = cssutils.css.CSSStyleDeclaration() specificities[element] = {} # and add inline @style if present inlinestyle = styleCallback(element) if inlinestyle: for p in inlinestyle: # set inline style specificity view[element].setProperty(p) specificities[element][p.name] = (1, 0, 0, 0) for p in rule.style: # update style declaration if p not in view[element]: # setProperty needs a new Property object and # MUST NOT reuse the existing Property # which would be the same for all elements! # see Issue #23 view[element].setProperty(p.name, p.value, p.priority) specificities[element][p.name] = selector.specificity log(2, view[element].getProperty('color')) else: log(2, view[element].getProperty('color')) sameprio = ( p.priority == view[element].getPropertyPriority( p.name)) if not sameprio and bool(p.priority) or ( sameprio and selector.specificity >= specificities[element][p.name]): # later, more specific or higher prio view[element].setProperty(p.name, p.value, p.priority) #pprint(view) return view
document = etree.HTML(html) e = etree.Element('pre', {'class': 'cssutils'}) e.text = css document.find('body').append(e) sheet = cssutils.parseString(css) view = {} specificities = {} # temporarily needed # TODO: filter rules simpler?, add @media rules = (rule for rule in sheet.cssRules if rule.type == rule.STYLE_RULE) for rule in rules: for selector in rule.selectorList: cssselector = CSSSelector(selector.selectorText) elements = cssselector.evaluate(document) for element in elements: # add styles for all matching DOM elements if element not in view: # add initial view[element] = cssutils.css.CSSStyleDeclaration() specificities[element] = {} for p in rule.style: # update styles if p not in view[element]: view[element].setProperty(p) specificities[element][p.name] = selector.specificity else: sameprio = ( p.priority == view[element].getPropertyPriority(
def getView(document, css): """ document a DOM document, currently an lxml HTML document css a CSS StyleSheet string returns style view a dict of {DOMElement: css.CSSStyleDeclaration} for html """ from lxml.cssselect import CSSSelector sheet = cssutils.parseString(css) view = {} specificities = {} # needed temporarily # TODO: filter rules simpler?, add @media rules = (rule for rule in sheet if rule.type == rule.STYLE_RULE) for rule in rules: for selector in rule.selectorList: #log(0, 'SELECTOR', selector.selectorText) # TODO: make this a callback to be able to use other stuff than lxml try: cssselector = CSSSelector(selector.selectorText) except: continue matching = cssselector.evaluate(document) for element in matching: #if element.tag in ('div',): # add styles for all matching DOM elements #log(1, 'ELEMENT', id(element), element.text) if element not in view: # add initial empty style declatation view[element] = cssutils.css.CSSStyleDeclaration( ) # @UndefinedVariable specificities[element] = {} for p in rule.style: # update style declaration if p not in view[element]: # setProperty needs a new Property object and # MUST NOT reuse the existing Property # which would be the same for all elements! # see Issue #23 view[element].setProperty(p.name, p.value, p.priority) specificities[element][p.name] = selector.specificity #log(2, view[element].getProperty('color')) else: #log(2, view[element].getProperty('color')) sameprio = ( p.priority == view[element].getPropertyPriority( p.name)) if not sameprio and bool(p.priority) or ( sameprio and selector.specificity >= specificities[element][p.name]): # later, more specific or higher prio view[element].setProperty(p.name, p.value, p.priority) return view
def get_view(document, sheet, name=None, style_callback=lambda element: None): """ document a DOM document, currently an lxml HTML document sheet a CSS StyleSheet name: optional TODO: names of sheets only style_callback: optional should return css.CSSStyleDeclaration of inline styles, for html a style declaration for ``element@style``. Gets one parameter ``element`` which is the relevant DOMElement returns style view a dict of {DOMElement: css.CSSStyleDeclaration} for html """ view = {} specificities = {} # needed temporarily # TODO: filter rules simpler?, add @media rules = (rule for rule in sheet if rule.type == rule.STYLE_RULE) for rule in rules: for selector in rule.selectorList: # TODO: make this a callback to be able to use other stuff than lxml try: cssselector = CSSSelector(selector.selectorText) except ExpressionError: continue matching = cssselector.evaluate(document) for element in matching: # if element.tag in ('div',): # add styles for all matching DOM elements if element not in view: # add initial empty style declatation view[element] = cssutils.css.CSSStyleDeclaration() specificities[element] = {} for p in rule.style: # update style declaration if p not in view[element]: # setProperty needs a new Property object and # MUST NOT reuse the existing Property # which would be the same for all elements! # see Issue #23 view[element].setProperty(p.name, p.value, p.priority) specificities[element][p.name] = selector.specificity else: sameprio = ( p.priority == view[element].getPropertyPriority( p.name)) if not sameprio and bool(p.priority) or ( sameprio and selector.specificity >= specificities[element][p.name]): # later, more specific or higher prio view[element].setProperty(p.name, p.value, p.priority) return view
def getView(self, document, sheet, media='all', name=None, styleCallback=None): """ document a DOM document, currently an lxml HTML document sheet a CSS StyleSheet object, currently cssutils sheet media: optional TODO: view for which media it should be name: optional TODO: names of sheets only styleCallback: optional should return css.CSSStyleDeclaration of inline styles, for html a style declaration for ``element@style``. Gets one parameter ``element`` which is the relevant DOMElement returns style view a dict of {DOMElement: css.CSSStyleDeclaration} for html """ styleCallback = styleCallback or self.styleattribute _unmergable_rules = CSSStyleSheet() view = {} specificities = {} # needed temporarily # TODO: filter rules simpler?, add @media rules = (rule for rule in sheet if rule.type == rule.STYLE_RULE) for rule in rules: for selector in rule.selectorList: self.log(0, 'SELECTOR', selector.selectorText) # TODO: make this a callback to be able to use other stuff than lxml try: cssselector = CSSSelector(selector.selectorText) except (ExpressionError, NotImplementedError) as e: _unmergable_rules.add(CSSStyleRule(selectorText=selector.selectorText, style=rule.style)) continue matching = cssselector.evaluate(document) for element in matching: if element.tag in self.NONVISUAL_TAGS: continue # add styles for all matching DOM elements self.log(1, 'ELEMENT', id(element), element.text) if element not in view: # add initial empty style declatation view[element] = CSSStyleDeclaration() specificities[element] = {} # and add inline @style if present inlinestyle = styleCallback(element) if inlinestyle: for p in inlinestyle: # set inline style specificity view[element].setProperty(p) specificities[element][p.name] = (1, 0, 0, 0) for p in rule.style: # update style declaration if p not in view[element]: # setProperty needs a new Property object and # MUST NOT reuse the existing Property # which would be the same for all elements! # see Issue #23 view[element].setProperty(p.name, p.value, p.priority) specificities[element][p.name] = selector.specificity self.log(2, view[element].getProperty('color')) else: self.log(2, view[element].getProperty('color')) sameprio = (p.priority == view[element].getPropertyPriority(p.name)) if not sameprio and bool(p.priority) or ( sameprio and selector.specificity >= specificities[element][p.name]): # later, more specific or higher prio view[element].setProperty(p.name, p.value, p.priority) _unmergable_css = _unmergable_rules.cssText if _unmergable_css: e = etree.Element('style') # print __name__, _unmergable_css.__repr__() e.text = to_unicode(_unmergable_css, 'utf-8') body = document.find('body') or document body.insert(0, e) # add <style> right into body return view
document = etree.HTML(html) e = etree.Element('pre', {'class': 'cssutils'}) e.text = css document.find('body').append(e) sheet = cssutils.parseString(css) view = {} specificities = {} # temporarily needed # TODO: filter rules simpler?, add @media rules = (rule for rule in sheet.cssRules if rule.type == rule.STYLE_RULE) for rule in rules: for selector in rule.selectorList: cssselector = CSSSelector(selector.selectorText) elements = cssselector.evaluate(document) for element in elements: # add styles for all matching DOM elements if element not in view: # add initial view[element] = cssutils.css.CSSStyleDeclaration() specificities[element] = {} for p in rule.style: # update styles if p not in view[element]: view[element].setProperty(p) specificities[element][p.name] = selector.specificity else: sameprio = (p.priority == view[element].getPropertyPriority(p.name))
def getView(document, css): """ document a DOM document, currently an lxml HTML document css a CSS StyleSheet string returns style view a dict of {DOMElement: css.CSSStyleDeclaration} for html """ from lxml.cssselect import CSSSelector sheet = cssutils.parseString(css) view = {} specificities = {} # needed temporarily # TODO: filter rules simpler?, add @media rules = (rule for rule in sheet if rule.type == rule.STYLE_RULE) for rule in rules: for selector in rule.selectorList: #log(0, 'SELECTOR', selector.selectorText) # TODO: make this a callback to be able to use other stuff than lxml try: cssselector = CSSSelector(selector.selectorText) except: continue matching = cssselector.evaluate(document) for element in matching: #if element.tag in ('div',): # add styles for all matching DOM elements #log(1, 'ELEMENT', id(element), element.text) if element not in view: # add initial empty style declatation view[element] = cssutils.css.CSSStyleDeclaration() # @UndefinedVariable specificities[element] = {} for p in rule.style: # update style declaration if p not in view[element]: # setProperty needs a new Property object and # MUST NOT reuse the existing Property # which would be the same for all elements! # see Issue #23 view[element].setProperty(p.name, p.value, p.priority) specificities[element][p.name] = selector.specificity #log(2, view[element].getProperty('color')) else: #log(2, view[element].getProperty('color')) sameprio = (p.priority == view[element].getPropertyPriority(p.name)) if not sameprio and bool(p.priority) or ( sameprio and selector.specificity >= specificities[element][p.name]): # later, more specific or higher prio view[element].setProperty(p.name, p.value, p.priority) return view
def getView(document, css, media='all', name=None, styleCallback=lambda element: None): """ document a DOM document, currently an lxml HTML document css a CSS StyleSheet string media: optional TODO: view for which media it should be name: optional TODO: names of sheets only styleCallback: optional should return css.CSSStyleDeclaration of inline styles, for html a style declaration for ``element@style``. Gets one parameter ``element`` which is the relevant DOMElement returns style view a dict of {DOMElement: css.CSSStyleDeclaration} for html """ sheet = cssutils.parseString(css) view = {} specificities = {} # needed temporarily # TODO: filter rules simpler?, add @media rules = (rule for rule in sheet if rule.type == rule.STYLE_RULE) for rule in rules: for selector in rule.selectorList: log(0, 'SELECTOR', selector.selectorText) # TODO: make this a callback to be able to use other stuff than lxml cssselector = CSSSelector(selector.selectorText) matching = cssselector.evaluate(document) for element in matching: #if element.tag in ('div',): # add styles for all matching DOM elements log(1, 'ELEMENT', id(element), element.text) if element not in view: # add initial empty style declatation view[element] = cssutils.css.CSSStyleDeclaration() specificities[element] = {} # and add inline @style if present inlinestyle = styleCallback(element) if inlinestyle: for p in inlinestyle: # set inline style specificity view[element].setProperty(p) specificities[element][p.name] = (1,0,0,0) for p in rule.style: # update style declaration if p not in view[element]: # setProperty needs a new Property object and # MUST NOT reuse the existing Property # which would be the same for all elements! # see Issue #23 view[element].setProperty(p.name, p.value, p.priority) specificities[element][p.name] = selector.specificity log(2, view[element].getProperty('color')) else: log(2, view[element].getProperty('color')) sameprio = (p.priority == view[element].getPropertyPriority(p.name)) if not sameprio and bool(p.priority) or ( sameprio and selector.specificity >= specificities[element][p.name]): # later, more specific or higher prio view[element].setProperty(p.name, p.value, p.priority) #pprint(view) return view