Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 45 additions & 38 deletions cssify/cssify.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,25 @@
from optparse import OptionParser

sub_regexes = {
"tag": "([a-zA-Z][a-zA-Z0-9]{0,10}|\*)",
"attribute": "[.a-zA-Z_:][-\w:.]*(\(\))?)",
"value": "\s*[\w/:][-/\w\s,:;.]*"
"tag": r"([a-zA-Z][a-zA-Z0-9]{0,10}|\*)",
"attribute": r"[.a-zA-Z_:][-\w:.]*(\(\))?)",
"value": r"\s*[\w/:][-/\w\s,:;.]*"
}

validation_re = (
"(?P<node>"
"("
"^id\([\"\']?(?P<idvalue>%(value)s)[\"\']?\)" # special case! id(idValue)
"|"
"(?P<nav>//?)(?P<tag>%(tag)s)" # //div
"(\[("
"(?P<matched>(?P<mattr>@?%(attribute)s=[\"\'](?P<mvalue>%(value)s))[\"\']" # [@id="bleh"] and [text()="meh"]
"|"
"(?P<contained>contains\((?P<cattr>@?%(attribute)s,\s*[\"\'](?P<cvalue>%(value)s)[\"\']\))" # [contains(text(), "bleh")] or [contains(@id, "bleh")]
")\])?"
"(\[(?P<nth>\d)\])?"
")"
")" % sub_regexes
)
r"(?P<node>"
r"("
r"^id\([\"\']?(?P<idvalue>{value})[\"\']?\)" # special case! id(idValue)
r"|"
r"(?P<nav>//?)(?P<tag>{tag})" # //div
r"(\[("
r"(?P<matched>(?P<mattr>@?{attribute}=[\"\'](?P<mvalue>{value}))[\"\']" # [@id="bleh"] and [text()="meh"]
r"|"
r"(?P<contained>contains\((?P<cattr>@?{attribute},\s*[\"\'](?P<cvalue>{value})[\"\']\))" # [contains(text(), "bleh")] or [contains(@id, "bleh")]
r")\])?"
r"(\[(?P<nth>\d)\])?"
r")"
r")").format(**sub_regexes)

prog = re.compile(validation_re)

Expand All @@ -45,10 +44,11 @@ def cssify(xpath):
while position < len(xpath):
node = prog.match(xpath[position:])
if node is None:
raise XpathException("Invalid or unsupported Xpath: %s" % xpath)
log("node found: %s" % node)
raise XpathException(
"Invalid or unsupported Xpath: {}".format(xpath))
log("node found: {}".format(node))
match = node.groupdict()
log("broke node down to: %s" % match)
log("broke node down to: {}".format(match))

if position != 0:
nav = " " if match['nav'] == "//" else " > "
Expand All @@ -58,66 +58,73 @@ def cssify(xpath):
tag = "" if match['tag'] == "*" else match['tag'] or ""

if match['idvalue']:
attr = "#%s" % match['idvalue'].replace(" ", "#")
attr = "#{}".format(match['idvalue'].replace(" ", "#"))
elif match['matched']:
if match['mattr'] == "@id":
attr = "#%s" % match['mvalue'].replace(" ", "#")
attr = "#{}".format(match['mvalue'].replace(" ", "#"))
elif match['mattr'] == "@class":
attr = ".%s" % match['mvalue'].replace(" ", ".")
attr = ".{}".format(match['mvalue'].replace(" ", "."))
elif match['mattr'] in ["text()", "."]:
attr = ":contains(^%s$)" % match['mvalue']
attr = ":contains(^{}$)".format(match['mvalue'])
elif match['mattr']:
if match["mvalue"].find(" ") != -1:
match["mvalue"] = "\"%s\"" % match["mvalue"]
attr = "[%s=%s]" % (match['mattr'].replace("@", ""),
match['mvalue'])
match["mvalue"] = "\"{}\"".format(match["mvalue"])
attr = "[{}={}]".format(match['mattr'].replace("@", ""),
match['mvalue'])
elif match['contained']:
if match['cattr'].startswith("@"):
attr = "[%s*=%s]" % (match['cattr'].replace("@", ""),
match['cvalue'])
attr = "[{}*={}]".format(match['cattr'].replace("@", ""),
match['cvalue'])
elif match['cattr'] == "text()":
attr = ":contains(%s)" % match['cvalue']
attr = ":contains({})".format(match['cvalue'])
else:
attr = ""

if match['nth']:
nth = ":nth-of-type(%s)" % match['nth']
nth = ":nth-of-type({})".format(match['nth'])
else:
nth = ""

node_css = nav + tag + attr + nth

log("final node css: %s" % node_css)
log("final node css: {}".format(node_css))

css += node_css
position += node.end()
else:
css = css.strip()
return css


if __name__ == "__main__":
usage = "usage: %prog [options] XPATH"
parser = OptionParser(usage)
parser.add_option("-v", "--verbose",
action="store_true", dest="verbose", default=False,
parser.add_option("-v",
"--verbose",
action="store_true",
dest="verbose",
default=False,
help="print status messages to stdout")

(options, args) = parser.parse_args()

if options.verbose:

def log(msg):
print "> %s" % msg
print("> {}".format(msg))
else:

def log(msg):
pass

if len(args) != 1:
parser.error("incorrect number of arguments")
try:
print cssify(args[0])
except XpathException, e:
print e
print(cssify(args[0]))
except XpathException as e:
print(e)
sys.exit(1)
else:

def log(msg):
pass