Created
November 5, 2012 12:37
-
-
Save wichert/4016981 to your computer and use it in GitHub Desktop.
Patternslib syntax converter
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import argparse | |
import os | |
import re | |
import sys | |
from lxml import etree | |
def read(fn): | |
with open(fn, 'r') as input: | |
parser = etree.HTMLParser() | |
return etree.parse(input, parser) | |
SPACE = re.compile('\s+') | |
OLD_SHORTHAND_SYNTAX = re.compile(r'^(\s*\S+\s*;)+') | |
NAMED_ARGUMENT = re.compile(r'^\s*(\w+)\s*:\s*(.*)') | |
def warn(node, msg): | |
print >> sys.stderr, '%d: %s' % (node.sourceline, msg) | |
def update_parser_syntax(node): | |
for (attr, value) in node.attrib.items(): | |
if not attr.startswith('data-pat-'): | |
continue | |
match = OLD_SHORTHAND_SYNTAX.match(value) | |
if match is None: | |
continue | |
parts = value.split(';') | |
new_parts = [] | |
while parts: | |
part = parts.pop(0).strip() | |
if not part: | |
warn(node, | |
'Can not convert shorthand syntax with missing value') | |
return | |
if NAMED_ARGUMENT.match(part) is not None: | |
parts.insert(0, part) | |
break | |
new_parts.append(part) | |
shorthand = ' '.join(new_parts) | |
node.attrib[attr] = '; '.join([shorthand] + parts) | |
def update_depends(node): | |
classes = SPACE.split(node.attrib['class']) | |
new_classes = [] | |
depends = [] | |
action = 'and' | |
for cls in classes: | |
if cls.startswith('dependsType'): | |
action = cls[12:] | |
continue | |
elif not cls.startswith('dependsOn-'): | |
new_classes.append(cls) | |
continue | |
parts = cls[10:].split('-') | |
if len(parts) == 1 or (len(parts) == 2 and parts[1] == 'on'): | |
depends.append(parts[0]) | |
continue | |
elif len(parts) == 2 and parts[1] == 'off': | |
depends.append('not %s' % parts[0]) | |
continue | |
elif len(parts) == 3: | |
if parts[1].lower() == 'equals': | |
depends.append('%s=%s' % (parts[0], parts[2])) | |
continue | |
elif parts[1].lower() == 'notequals': | |
depends.append('%s!=%s' % (parts[0], parts[2])) | |
continue | |
warn(node, 'Do not know how to convert depends class %s' % cls) | |
new_classes.append(cls) | |
node.attrib['data-pat-depends'] = action.join(depends) | |
if 'pat-depends' not in new_classes: | |
new_classes.append('pat-depends') | |
node.attrib['class'] = ' '.join(new_classes) | |
def update_tooltip(node): | |
classes = SPACE.split(node.attrib.get('class', '')) | |
if 'pat-tooltip' not in classes: | |
node.attrib['class'] = ' '.join(classes + ['pat-tooltip']) | |
arguments = node.attrib.pop('data-tooltip').split('!') | |
new = [] | |
for arg in arguments: | |
if arg in ['click', 'ajax']: | |
new.append(arg) | |
elif arg == 'forcePosition': | |
new.append('force') | |
elif arg.startswith('position='): | |
new.insert(0, arg[9:]) | |
else: | |
warn(node, 'Unknown tooltip argument: %s' % arg) | |
return | |
node.attrib['data-pat-tooltip'] = ' '.join(new) | |
def update(root): | |
for node in root.iter(): | |
update_parser_syntax(node) | |
if 'data-tooltip' in node.attrib: | |
update_tooltip(node) | |
cls = node.attrib.get('class', '') | |
if not cls: | |
continue | |
if 'dependsOn-' in cls: | |
update_depends(node) | |
def main(): | |
parser = argparse.ArgumentParser( | |
description='Apply Patternslib syntax changes to HTML documents.') | |
parser.add_argument('-i', '--in-place', default=False, action='store_true', | |
help='Update documents in place') | |
parser.add_argument('html', nargs='+', | |
help='HTML document to update') | |
options = parser.parse_args() | |
for html in options.html: | |
tree = read(html) | |
update(tree) | |
if options.in_place: | |
fn = '%s~' % html | |
with open(fn, 'w') as output: | |
tree.write(output, encoding='utf-8') | |
os.rename(fn, html) | |
else: | |
tree.write(sys.stdout, encoding='utf-8') | |
if __name__ == '__main__': | |
sys.exit(main()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment