deliverance-like implementation that only works on html output(no theme file)
pip install Bumblebee==1.0a2
Introduction ============ Bumblebee is a deliverance-like html transformation framwork implementation that only works on the output an html document. It doesn't use xslt so it isn't as fast as what Diazo is; however, it accomplishes the very simple use-case of moving elements around on html output. Why --- Because I almost never needed the full-fledge deliverance approach for what I wanted to do. In fact, it was usually an annoyance when all I wanted to do was move an element around on a page. How-to Use ========== Configurating your transformations is done with a very xml syntax. Example: HTML:: <html> <head></head> <body> <div id="#header"></div> <div id="content"></div> <div id="footer"></div> </body> </html> Rules XML:: <xml> <block if-content="#content"> <after src="#header" dst="#footer" /> </block> </xml> Running it through:: from bumblebee import transform from repoze.xmliter.utils import getHTMLSerializer from bumblebee.xml import convertRules html = getHTMLSerializer(output) rules = convertRules(rules_xml) result = transform(html, rules) Selectors --------- For xml configuration that selects elements, you can use CSS selectors(default) or XPath. To use XPath, just append '-path' onto the node name:: <after src-xpath="/html/body/div[0]" src-xpath="/html/body/div[2]" /> arbitrary html ~~~~~~~~~~~~~~ Use this to inject html into a page:: <after src-html="" dst="#foo"> <div id="foobar"> <h1>hello, world</h1> </div> </after> Rules ----- Before ~~~~~~ Move an element before another element:: <before src="#foo" dst="#bar" /> Moves "#foo" before "#bar" After ~~~~~ Move an element after another:: <after src="#foo" "#bar" /> Moves "#foo" after "#bar" Drop ~~~~ Remove an element from the dom:: <drop src="#foo" /> Replace ~~~~~~~ Replace an element with another:: <replace src="#foo" dst="#bar" /> Replaces "#dst" with "#src" Class ~~~~~ Add or remove classes from an element:: <class src="#foo" add="three four" remove="one two" /> Remove the classes "one" and "two" from "#foo" and add the classes "three" and "four". Tag ~~~ Change a tag:: <tag src="#foo" tag="p" /> Group ~~~~~ Group rules together with a conditions:: <group if-content="#foo"> <drop src="#bar" /> </group> Performs some rules if "#foo" is in the document. Conditions ---------- if-content ~~~~~~~~~~ Performs actions if the selector is found in the document:: <after src="#foo" dst="#bar" if-content="#foo" /> not conditiion ~~~~~~~~~~~~~~ Any condition can be negated for the opposite affect:: <drop src="#foo" if-not-content="#bar" /> Extending --------- Creating a Rule:: from bumblebee.rules import BaseDouble class Append(BaseDouble): def __call__(self, root): src, dst, skip = self.process_nodes(root) if skip: return None dst = dst[0] for el in dst: dst.append(el) return src from bumblebee.xml import addTag addTag('append', Append) To use the rule, you would:: <append src="#foo" dst="#bar" /> Creating a Condition:: from bumblebee.conditions import BaseIf class IfPath(BaseIf): def __init__(self, path, extras={}): super(IfPath, self).__init__(extras) self.path = path def __call__(self, root): req = self.extras['request'] path = req['PATH_INFO'] if self.path.startswith('/'): return path.startswith(self.path) else: return self.path in path from bumblebee.xml import addCondition addCondition('path', IfPath) To use this condition, you would:: <drop src="#foo" if-path="/foo/bar" /> or:: <drop src="#foo" if-not-path="/foo/bar" />