Skip to content

Instantly share code, notes, and snippets.

@benknight
Last active August 29, 2015 13:56
Show Gist options
  • Save benknight/9011428 to your computer and use it in GitHub Desktop.
Save benknight/9011428 to your computer and use it in GitHub Desktop.
ReviewBoard CSS rewrites
// ==UserScript==
// @name Better ReviewBoard styles
// @version 1.1
// @description Rewrites some ReviewBoard styles
// @match https://reviewboard.yelpcorp.com/*
// @copyright 2014 Benjamin Knight <[email protected]>
// ==/UserScript==
(function () {
var cssRewrites = 'button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}html{position:relative;min-height:100%}#container{margin-bottom:120px}body{height:100%;padding:10px;font-family:Helvetica Neue, Lucida Grande, Verdana, sans-serif;font-size:13px;background-attachment:scroll;background-size:100px;background-position:20px calc(100% - 20px)}pre,textarea{font-family:Menlo, monospace;font-size:14px}table.sidebyside{color:rgba(0,0,0,0.8)}table.sidebyside .insert td,table.sidebyside .delete td,table.sidebyside .replace td{outline:1px solid rgba(0,0,0,0.05);outline-offset:-1px}table.sidebyside pre{font-size:13px}#headerbar{height:30px}#headerbar #logo{display:none}#headerbar #title{font-size:20px}#headerbar #title .version{font-size:16px}#headerbar #accountnav{float:right;padding:13px}#headerbar #rbinfo{float:left;padding:0.8em}#headerbar br{display:none}.box-container,#navbar-outer,#accountnav{border:none}#navbar,.box,#dashboard-main{border:1px rgba(0,0,0,0.33) solid}#dashboard-navbar{width:200px}#dashboard-main{border-width:0 0 0 1px;margin-left:200px}.review-request .box-inner{background:#FFFADB !important}#details{background:rgba(0,0,0,0.03)}.marquee-container{position:absolute;bottom:0px;width:100px;height:100px;left:15px}.random-source-code{pointer-events:none;opacity:0;position:fixed;bottom:0;left:140px;height:1000px;color:green;-moz-transition:opacity 0.3s ease;-o-transition:opacity 0.3s ease;-webkit-transition:opacity 0.3s ease;transition:opacity 0.3s ease}.marquee-container:hover .random-source-code{opacity:0.5}';
var randomSourceCode = "from __future__ import absolute_import\nfrom __future__ import print_function\n\nfrom functools import partial\nimport logging\nimport operator\nimport re\n\nimport six\n\nimport scss.config as config\nfrom scss.cssdefs import COLOR_NAMES, is_builtin_css_function, _expr_glob_re, _interpolate_re\nfrom scss.errors import SassError, SassEvaluationError, SassParseError\nfrom scss.rule import Namespace\nfrom scss.types import Boolean, Color, List, Map, Null, Number, String, Undefined, Value\nfrom scss.util import dequote, normalize_var\n\n################################################################################\n# Load C acceleration modules\nScanner = None\ntry:\n from scss._speedups import Scanner\nexcept ImportError:\n from scss._native import Scanner\n\nlog = logging.getLogger(__name__)\n\n\nclass Calculator(object):\n \"\"\"Expression evaluator.\"\"\"\n\n ast_cache = {}\n\n def __init__(self, namespace=None):\n if namespace is None:\n self.namespace = Namespace()\n else:\n self.namespace = namespace\n\n def _pound_substitute(self, result):\n expr = result.group(1)\n value = self.evaluate_expression(expr)\n\n if value is None:\n return self.apply_vars(expr)\n elif value.is_null:\n return \"\"\n else:\n return dequote(value.render())\n\n def do_glob_math(self, cont):\n \"\"\"Performs #{}-interpolation. The result is always treated as a fixed\n syntactic unit and will not be re-evaluated.\n \"\"\"\n # TODO that's a lie! this should be in the parser for most cases.\n cont = str(cont)\n if '#{' not in cont:\n return cont\n cont = _expr_glob_re.sub(self._pound_substitute, cont)\n return cont\n\n def apply_vars(self, cont):\n # TODO this is very complicated. it should go away once everything\n # valid is actually parseable.\n if isinstance(cont, six.string_types) and '$' in cont:\n try:\n # Optimization: the full cont is a variable in the context,\n cont = self.namespace.variable(cont)\n except KeyError:\n # Interpolate variables:\n def _av(m):\n v = None\n n = m.group(2)\n try:\n v = self.namespace.variable(n)\n except KeyError:\n if config.FATAL_UNDEFINED:\n raise SyntaxError(\"Undefined variable: '%s'.\" % n)\n else:\n if config.VERBOSITY > 1:\n log.error(\"Undefined variable '%s'\", n, extra={'stack': True})\n return n\n else:\n if v:\n if not isinstance(v, six.string_types):\n v = v.render()\n # TODO this used to test for _dequote\n if m.group(1):\n v = dequote(v)\n else:\n v = m.group(0)\n return v\n\n cont = _interpolate_re.sub(_av, cont)\n # TODO this is surprising and shouldn't be here\n cont = self.do_glob_math(cont)\n return cont\n\n def calculate(self, _base_str, divide=False):\n better_expr_str = _base_str\n\n better_expr_str = self.do_glob_math(better_expr_str)\n\n better_expr_str = self.evaluate_expression(better_expr_str, divide=divide)\n\n if better_expr_str is None:\n better_expr_str = String.unquoted(self.apply_vars(_base_str))\n\n return better_expr_str\n\n # TODO only used by magic-import...?\n def interpolate(self, var):\n value = self.namespace.variable(var)\n if var != value and isinstance(value, six.string_types):\n _vi = self.evaluate_expression(value)\n if _vi is not None:\n value = _vi\n return value\n\n def evaluate_expression(self, expr, divide=False):\n try:\n ast = self.parse_expression(expr)\n except SassError:\n if config.DEBUG:\n raise\n else:\n return None\n\n try:\n return ast.evaluate(self, divide=divide)\n except Exception as e:\n raise SassEvaluationError(e, expression=expr)\n\n def parse_expression(self, expr, target='goal'):\n if not isinstance(expr, six.string_types):\n raise TypeError(\"Expected string, got %r\" % (expr,))\n\n key = (target, expr)\n if key in self.ast_cache:\n return self.ast_cache[key]\n\n try:\n parser = SassExpression(SassExpressionScanner(expr))\n ast = getattr(parser, target)()\n except SyntaxError as e:\n raise SassParseError(e, expression=expr, expression_pos=parser._char_pos)\n\n self.ast_cache[key] = ast\n return ast\n\n\n# ------------------------------------------------------------------------------\n# Expression classes -- the AST resulting from a parse\n\nclass Expression(object):\n def __repr__(self):\n return '<%s()>' % (self.__class__.__name__)\n\n def evaluate(self, calculator, divide=False):\n \"\"\"Evaluate this AST node, and return a Sass value.\n\n `divide` indicates whether a descendant node representing a division\n should be forcibly treated as a division. See the commentary in\n `BinaryOp`.\n \"\"\"\n raise NotImplementedError\n\n\nclass Parentheses(Expression):\n \"\"\"An expression of the form `(foo)`.\n\n Only exists to force a slash to be interpreted as division when contained\n within parentheses.\n \"\"\"\n def __repr__(self):\n return '<%s(%s)>' % (self.__class__.__name__, repr(self.contents))\n\n def __init__(self, contents):\n self.contents = contents\n\n def evaluate(self, calculator, divide=False):\n return self.contents.evaluate(calculator, divide=True)\n\n\nclass UnaryOp(Expression):\n def __repr__(self):\n return '<%s(%s, %s)>' % (self.__class__.__name__, repr(self.op), repr(self.operand))\n\n def __init__(self, op, operand):\n self.op = op\n self.operand = operand\n\n def evaluate(self, calculator, divide=False):\n return self.op(self.operand.evaluate(calculator, divide=True))\n\n\nclass BinaryOp(Expression):\n def __repr__(self):\n return '<%s(%s, %s, %s)>' % (self.__class__.__name__, repr(self.op), repr(self.left), repr(self.right))\n\n def __init__(self, op, left, right):\n self.op = op\n self.left = left\n self.right = right\n\n def evaluate(self, calculator, divide=False):\n left = self.left.evaluate(calculator, divide=True)\n right = self.right.evaluate(calculator, divide=True)\n\n # Special handling of division: treat it as a literal slash if both\n # operands are literals, there are parentheses, or this is part of a\n # bigger expression.\n # The first condition is covered by the type check. The other two are\n # covered by the `divide` argument: other nodes that perform arithmetic\n # will pass in True, indicating that this should always be a division.\n if (\n self.op is operator.truediv\n and not divide\n and isinstance(self.left, Literal)\n and isinstance(self.right, Literal)\n ):\n return String(left.render() + ' / ' + right.render(), quotes=None)\n\n return self.op(left, right)\n\n\nclass AnyOp(Expression):\n def __repr__(self):\n return '<%s(*%s)>' % (self.__class__.__name__, repr(self.op), repr(self.operands))\n\n def __init__(self, *operands):\n self.operands = operands\n\n def evaluate(self, calculator, divide=False):\n for operand in self.operands:\n value = operand.evaluate(calculator, divide=True)\n if value:\n return value\n return value\n\n\nclass AllOp(Expression):\n def __repr__(self):\n return '<%s(*%s)>' % (self.__class__.__name__, repr(self.operands))\n\n def __init__(self, *operands):\n self.operands = operands\n\n def evaluate(self, calculator, divide=False):\n for operand in self.operands:\n value = operand.evaluate(calculator, divide=True)\n if not value:\n return value\n return value\n\n\nclass NotOp(Expression):\n def __repr__(self):\n return '<%s(%s)>' % (self.__class__.__name__, repr(self.operand))\n\n def __init__(self, operand):\n self.operand = operand\n\n def evaluate(self, calculator, divide=False):\n operand = self.operand.evaluate(calculator, divide=True)\n return Boolean(not(operand))\n\n\nclass CallOp(Expression):\n def __repr__(self):\n return '<%s(%s, %s)>' % (self.__class__.__name__, repr(self.func_name), repr(self.argspec))\n\n def __init__(self, func_name, argspec):\n self.func_name = func_name\n self.argspec = argspec\n\n def evaluate(self, calculator, divide=False):\n # TODO bake this into the context and options \"dicts\", plus library\n func_name = normalize_var(self.func_name)\n\n argspec_node = self.argspec\n\n # Turn the pairs of arg tuples into *args and **kwargs\n # TODO unclear whether this is correct -- how does arg, kwarg, arg\n # work?\n args, kwargs = argspec_node.evaluate_call_args(calculator)\n argspec_len = len(args) + len(kwargs)\n\n # Translate variable names to Python identifiers\n # TODO what about duplicate kw names? should this happen in argspec?\n # how does that affect mixins?\n kwargs = dict(\n (key.lstrip('$').replace('-', '_'), value)\n for key, value in kwargs.items())\n\n # TODO merge this with the library\n funct = None\n try:\n funct = calculator.namespace.function(func_name, argspec_len)\n # @functions take a ns as first arg. TODO: Python functions possibly\n # should too\n if getattr(funct, '__name__', None) == '__call':\n funct = partial(funct, calculator.namespace)\n except KeyError:\n try:\n # DEVIATION: Fall back to single parameter\n funct = calculator.namespace.function(func_name, 1)\n args = [List(args, use_comma=True)]\n except KeyError:\n if not is_builtin_css_function(func_name):\n log.error(\"Function not found: %s:%s\", func_name, argspec_len, extra={'stack': True})\n\n if funct:\n ret = funct(*args, **kwargs)\n if not isinstance(ret, Value):\n raise TypeError(\"Expected Sass type as return value, got %r\" % (ret,))\n return ret\n\n # No matching function found, so render the computed values as a CSS\n # function call. Slurpy arguments are expanded and named arguments are\n # unsupported.\n if kwargs:\n raise TypeError(\"The CSS function %s doesn't support keyword arguments.\" % (func_name,))\n\n # TODO another candidate for a \"function call\" sass type\n rendered_args = [arg.render() for arg in args]\n\n return String(\n u\"%s(%s)\" % (func_name, u\", \".join(rendered_args)),\n quotes=None)\n\n\nclass Literal(Expression):\n def __repr__(self):\n return '<%s(%s)>' % (self.__class__.__name__, repr(self.value))\n\n def __init__(self, value):\n if isinstance(value, Undefined) and config.FATAL_UNDEFINED:\n raise SyntaxError(\"Undefined literal.\")\n else:\n self.value = value\n\n def evaluate(self, calculator, divide=False):\n return self.value\n\n\nclass Variable(Expression):\n def __repr__(self):\n return '<%s(%s)>' % (self.__class__.__name__, repr(self.name))\n\n def __init__(self, name):\n self.name = name\n\n def evaluate(self, calculator, divide=False):\n try:\n value = calculator.namespace.variable(self.name)\n except KeyError:\n if config.FATAL_UNDEFINED:\n raise SyntaxError(\"Undefined variable: '%s'.\" % self.name)\n else:\n if config.VERBOSITY > 1:\n log.error(\"Undefined variable '%s'\", self.name, extra={'stack': True})\n return Undefined()\n else:\n if isinstance(value, six.string_types):\n evald = calculator.evaluate_expression(value)\n if evald is not None:\n return evald\n return value\n\n\nclass ListLiteral(Expression):\n def __repr__(self):\n return '<%s(%s, comma=%s)>' % (self.__class__.__name__, repr(self.items), repr(self.comma))\n\n def __init__(self, items, comma=True):\n self.items = items\n self.comma = comma\n\n def evaluate(self, calculator, divide=False):\n items = [item.evaluate(calculator, divide=divide) for item in self.items]\n\n # Whether this is a \"plain\" literal matters for null removal: nulls are\n # left alone if this is a completely vanilla CSS property\n is_literal = True\n if divide:\n # TODO sort of overloading \"divide\" here... rename i think\n is_literal = False\n elif not all(isinstance(item, Literal) for item in self.items):\n is_literal = False\n\n return List(items, use_comma=self.comma, is_literal=is_literal)\n\n\nclass MapLiteral(Expression):\n def __repr__(self):\n return '<%s(%s)>' % (self.__class__.__name__, repr(self.pairs))\n\n def __init__(self, pairs):\n self.pairs = tuple((var, value) for var, value in pairs if value is not None)\n\n def evaluate(self, calculator, divide=False):\n scss_pairs = []\n for key, value in self.pairs:\n scss_pairs.append((\n key.evaluate(calculator),\n value.evaluate(calculator),\n ))\n\n return Map(scss_pairs)\n\n\nclass ArgspecLiteral(Expression):\n \"\"\"Contains pairs of argument names and values, as parsed from a function\n definition or function call.\n\n Note that the semantics are somewhat ambiguous. Consider parsing:\n\n $foo, $bar: 3\n\n If this appeared in a function call, $foo would refer to a value; if it\n appeared in a function definition, $foo would refer to an existing\n variable. This it's up to the caller to use the right iteration function.\n \"\"\"\n def __repr__(self):\n return '<%s(%s)>' % (self.__class__.__name__, repr(self.argpairs))\n\n def __init__(self, argpairs, slurp=None):\n # argpairs is a list of 2-tuples, parsed as though this were a function\n # call, so (variable name as string or None, default value as AST\n # node).\n # slurp is the name of a variable to receive slurpy arguments.\n self.argpairs = tuple(argpairs)\n if slurp is all:\n # DEVIATION: special syntax to allow injecting arbitrary arguments\n # from the caller to the callee\n self.inject = True\n self.slurp = None\n elif slurp:\n self.inject = False\n self.slurp = Variable(slurp)\n else:\n self.inject = False\n self.slurp = None\n\n def iter_list_argspec(self):\n yield None, ListLiteral(zip(*self.argpairs)[1])\n\n def iter_def_argspec(self):\n \"\"\"Interpreting this literal as a function definition, yields pairs of\n (variable name as a string, default value as an AST node or None).\n \"\"\"\n started_kwargs = False\n seen_vars = set()\n\n for var, value in self.argpairs:\n if var is None:\n # value is actually the name\n var = value\n value = None\n\n if started_kwargs:\n raise SyntaxError(\n \"Required argument %r must precede optional arguments\"\n % (var.name,))\n\n else:\n started_kwargs = True\n\n if not isinstance(var, Variable):\n raise SyntaxError(\"Expected variable name, got %r\" % (var,))\n\n if var.name in seen_vars:\n raise SyntaxError(\"Duplicate argument %r\" % (var.name,))\n seen_vars.add(var.name)\n\n yield var.name, value\n\n def evaluate_call_args(self, calculator):\n \"\"\"Interpreting this literal as a function call, return a 2-tuple of\n ``(args, kwargs)``.\n \"\"\"\n args = []\n kwargs = {}\n for var_node, value_node in self.argpairs:\n value = value_node.evaluate(calculator, divide=True)\n if var_node is None:\n # Positional\n args.append(value)\n else:\n # Named\n if not isinstance(var_node, Variable):\n raise SyntaxError(\"Expected variable name, got %r\" % (var_node,))\n kwargs[var_node.name] = value\n\n # Slurpy arguments go on the end of the args\n if self.slurp:\n args.extend(self.slurp.evaluate(calculator, divide=True))\n\n return args, kwargs\n\n\ndef parse_bareword(word):\n if word in COLOR_NAMES:\n return Color.from_name(word)\n elif word == 'null':\n return Null()\n elif word == 'undefined':\n return Undefined()\n elif word == 'true':\n return Boolean(True)\n elif word == 'false':\n return Boolean(False)\n else:\n return String(word, quotes=None)\n\n\nclass Parser(object):\n def __init__(self, scanner):\n self._scanner = scanner\n self._pos = 0\n self._char_pos = 0\n\n def reset(self, input):\n self._scanner.reset(input)\n self._pos = 0\n self._char_pos = 0\n\n def _peek(self, types):\n \"\"\"\n Returns the token type for lookahead; if there are any args\n then the list of args is the set of token types to allow\n \"\"\"\n try:\n tok = self._scanner.token(self._pos, types)\n return tok[2]\n except SyntaxError:\n return None\n\n def _scan(self, type):\n \"\"\"\n Returns the matched text, and moves to the next token\n \"\"\"\n tok = self._scanner.token(self._pos, set([type]))\n self._char_pos = tok[0]\n if tok[2] != type:\n raise SyntaxError(\"SyntaxError[@ char %s: %s]\" % (repr(tok[0]), \"Trying to find \" + type))\n self._pos += 1\n return tok[3]\n\n\n################################################################################\n## Grammar compiled using Yapps:\n\nclass SassExpressionScanner(Scanner):\n patterns = None\n _patterns = [\n ('\":\"', ':'),\n ('\",\"', ','),\n ('[ \r\t\n]+', '[ \r\t\n]+'),\n ('LPAR', '\\(|\\['),\n ('RPAR', '\\)|\\]'),\n ('END', '$'),\n ('MUL', '[*]'),\n ('DIV', '/'),\n ('ADD', '[+]'),\n ('SUB', '-\\s'),\n ('SIGN', '-(?![a-zA-Z_])'),\n ('AND', '(?<![-\\w])and(?![-\\w])'),\n ('OR', '(?<![-\\w])or(?![-\\w])'),\n ('NOT', '(?<![-\\w])not(?![-\\w])'),\n ('NE', '!='),\n ('INV', '!'),\n ('EQ', '=='),\n ('LE', '<='),\n ('GE', '>='),\n ('LT', '<'),\n ('GT', '>'),\n ('DOTDOTDOT', '[.]{3}'),\n ('KWSTR', \"'[^']*'(?=\\s*:)\"),\n ('STR', \"'[^']*'\"),\n ('KWQSTR', '\"[^\"]*\"(?=\\s*:)'),\n ('QSTR', '\"[^\"]*\"'),\n ('UNITS', '(?<!\\s)(?:[a-zA-Z]+|%)(?![-\\w])'),\n ('KWNUM', '(?:\\d+(?:\\.\\d*)?|\\.\\d+)(?=\\s*:)'),\n ('NUM', '(?:\\d+(?:\\.\\d*)?|\\.\\d+)'),\n ('KWCOLOR', '#(?:[a-fA-F0-9]{6}|[a-fA-F0-9]{3})(?![a-fA-F0-9])(?=\\s*:)'),\n ('COLOR', '#(?:[a-fA-F0-9]{6}|[a-fA-F0-9]{3})(?![a-fA-F0-9])'),\n ('KWVAR', '\\$[-a-zA-Z0-9_]+(?=\\s*:)'),\n ('SLURPYVAR', '\\$[-a-zA-Z0-9_]+(?=[.][.][.])'),\n ('VAR', '\\$[-a-zA-Z0-9_]+'),\n ('FNCT', '[-a-zA-Z_][-a-zA-Z0-9_]*(?=\\()'),\n ('KWID', '[-a-zA-Z_][-a-zA-Z0-9_]*(?=\\s*:)'),\n ('ID', '[-a-zA-Z_][-a-zA-Z0-9_]*'),\n ('BANG_IMPORTANT', '!important'),\n ]\n\n def __init__(self, input=None):\n if hasattr(self, 'setup_patterns'):\n self.setup_patterns(self._patterns)\n elif self.patterns is None:\n self.__class__.patterns = []\n for t, p in self._patterns:\n self.patterns.append((t, re.compile(p)))\n super(SassExpressionScanner, self).__init__(None, ['[ \r\t\n]+'], input)\n\n\nclass SassExpression(Parser):\n def goal(self):\n expr_lst = self.expr_lst()\n END = self._scan('END')\n return expr_lst\n\n def goal_argspec(self):\n argspec = self.argspec()\n END = self._scan('END')\n return argspec\n\n def argspec(self):\n _token_ = self._peek(self.argspec_rsts)\n if _token_ not in self.argspec_chks:\n if self._peek(self.argspec_rsts_) not in self.argspec_chks_:\n argspec_items = self.argspec_items()\n args, slurpy = argspec_items\n return ArgspecLiteral(args, slurp=slurpy)\n return ArgspecLiteral([])\n elif _token_ == 'SLURPYVAR':\n SLURPYVAR = self._scan('SLURPYVAR')\n DOTDOTDOT = self._scan('DOTDOTDOT')\n return ArgspecLiteral([], slurp=SLURPYVAR)\n else: # == 'DOTDOTDOT'\n DOTDOTDOT = self._scan('DOTDOTDOT')\n return ArgspecLiteral([], slurp=all)\n\n def argspec_items(self):\n slurpy = None\n argspec_item = self.argspec_item()\n args = [argspec_item]\n if self._peek(self.argspec_items_rsts) == '\",\"':\n self._scan('\",\"')\n if self._peek(self.argspec_items_rsts_) not in self.argspec_chks_:\n _token_ = self._peek(self.argspec_items_rsts__)\n if _token_ == 'SLURPYVAR':\n SLURPYVAR = self._scan('SLURPYVAR')\n DOTDOTDOT = self._scan('DOTDOTDOT')\n slurpy = SLURPYVAR\n elif _token_ == 'DOTDOTDOT':\n DOTDOTDOT = self._scan('DOTDOTDOT')\n slurpy = all\n else: # in self.argspec_items_chks\n argspec_items = self.argspec_items()\n more_args, slurpy = argspec_items\n args.extend(more_args)\n return args, slurpy\n\n def argspec_item(self):\n _token_ = self._peek(self.argspec_items_chks)\n if _token_ == 'KWVAR':\n KWVAR = self._scan('KWVAR')\n self._scan('\":\"')\n expr_slst = self.expr_slst()\n return (Variable(KWVAR), expr_slst)\n else: # in self.argspec_item_chks\n expr_slst = self.expr_slst()\n return (None, expr_slst)\n\n def expr_map(self):\n map_item = self.map_item()\n pairs = [map_item]\n while self._peek(self.expr_map_rsts) == '\",\"':\n self._scan('\",\"')\n map_item = (None, None)\n if self._peek(self.expr_map_rsts_) not in self.expr_map_rsts:\n map_item = self.map_item()\n pairs.append(map_item)\n return MapLiteral(pairs)\n\n def map_item(self):\n kwatom = self.kwatom()\n self._scan('\":\"')\n expr_slst = self.expr_slst()\n return (kwatom, expr_slst)\n\n def expr_lst(self):\n expr_slst = self.expr_slst()\n v = [expr_slst]\n while self._peek(self.argspec_items_rsts) == '\",\"':\n self._scan('\",\"')\n expr_slst = self.expr_slst()\n v.append(expr_slst)\n return ListLiteral(v) if len(v) > 1 else v[0]\n\n def expr_slst(self):\n or_expr = self.or_expr()\n v = [or_expr]\n while self._peek(self.expr_slst_rsts) not in self.argspec_items_rsts:\n or_expr = self.or_expr()\n v.append(or_expr)\n return ListLiteral(v, comma=False) if len(v) > 1 else v[0]\n\n def or_expr(self):\n and_expr = self.and_expr()\n v = and_expr\n while self._peek(self.or_expr_rsts) == 'OR':\n OR = self._scan('OR')\n and_expr = self.and_expr()\n v = AnyOp(v, and_expr)\n return v\n\n def and_expr(self):\n not_expr = self.not_expr()\n v = not_expr\n while self._peek(self.and_expr_rsts) == 'AND':\n AND = self._scan('AND')\n not_expr = self.not_expr()\n v = AllOp(v, not_expr)\n return v\n\n def not_expr(self):\n _token_ = self._peek(self.argspec_item_chks)\n if _token_ != 'NOT':\n comparison = self.comparison()\n return comparison\n else: # == 'NOT'\n NOT = self._scan('NOT')\n not_expr = self.not_expr()\n return NotOp(not_expr)\n\n def comparison(self):\n a_expr = self.a_expr()\n v = a_expr\n while self._peek(self.comparison_rsts) in self.comparison_chks:\n _token_ = self._peek(self.comparison_chks)\n if _token_ == 'LT':\n LT = self._scan('LT')\n a_expr = self.a_expr()\n v = BinaryOp(operator.lt, v, a_expr)\n elif _token_ == 'GT':\n GT = self._scan('GT')\n a_expr = self.a_expr()\n v = BinaryOp(operator.gt, v, a_expr)\n elif _token_ == 'LE':\n LE = self._scan('LE')\n a_expr = self.a_expr()\n v = BinaryOp(operator.le, v, a_expr)\n elif _token_ == 'GE':\n GE = self._scan('GE')\n a_expr = self.a_expr()\n v = BinaryOp(operator.ge, v, a_expr)\n elif _token_ == 'EQ':\n EQ = self._scan('EQ')\n a_expr = self.a_expr()\n v = BinaryOp(operator.eq, v, a_expr)\n else: # == 'NE'\n NE = self._scan('NE')\n a_expr = self.a_expr()\n v = BinaryOp(operator.ne, v, a_expr)\n return v\n\n def a_expr(self):\n m_expr = self.m_expr()\n v = m_expr\n while self._peek(self.a_expr_rsts) in self.a_expr_chks:\n _token_ = self._peek(self.a_expr_chks)\n if _token_ == 'ADD':\n ADD = self._scan('ADD')\n m_expr = self.m_expr()\n v = BinaryOp(operator.add, v, m_expr)\n else: # == 'SUB'\n SUB = self._scan('SUB')\n m_expr = self.m_expr()\n v = BinaryOp(operator.sub, v, m_expr)\n return v\n\n def m_expr(self):\n u_expr = self.u_expr()\n v = u_expr\n while self._peek(self.m_expr_rsts) in self.m_expr_chks:\n _token_ = self._peek(self.m_expr_chks)\n if _token_ == 'MUL':\n MUL = self._scan('MUL')\n u_expr = self.u_expr()\n v = BinaryOp(operator.mul, v, u_expr)\n else: # == 'DIV'\n DIV = self._scan('DIV')\n u_expr = self.u_expr()\n v = BinaryOp(operator.truediv, v, u_expr)\n return v\n\n def u_expr(self):\n _token_ = self._peek(self.u_expr_rsts)\n if _token_ == 'SIGN':\n SIGN = self._scan('SIGN')\n u_expr = self.u_expr()\n return UnaryOp(operator.neg, u_expr)\n elif _token_ == 'ADD':\n ADD = self._scan('ADD')\n u_expr = self.u_expr()\n return UnaryOp(operator.pos, u_expr)\n else: # in self.u_expr_chks\n atom = self.atom()\n return atom\n\n def atom(self):\n _token_ = self._peek(self.u_expr_chks)\n if _token_ == 'LPAR':\n LPAR = self._scan('LPAR')\n _token_ = self._peek(self.atom_rsts)\n if _token_ not in self.argspec_item_chks:\n expr_map = self.expr_map()\n v = expr_map\n else: # in self.argspec_item_chks\n expr_lst = self.expr_lst()\n v = expr_lst\n RPAR = self._scan('RPAR')\n return Parentheses(v)\n elif _token_ == 'FNCT':\n FNCT = self._scan('FNCT')\n LPAR = self._scan('LPAR')\n argspec = self.argspec()\n RPAR = self._scan('RPAR')\n return CallOp(FNCT, argspec)\n elif _token_ == 'BANG_IMPORTANT':\n BANG_IMPORTANT = self._scan('BANG_IMPORTANT')\n return Literal(String(BANG_IMPORTANT, quotes=None))\n elif _token_ == 'ID':\n ID = self._scan('ID')\n return Literal(parse_bareword(ID))\n elif _token_ == 'NUM':\n NUM = self._scan('NUM')\n UNITS = None\n if self._peek(self.atom_rsts_) == 'UNITS':\n UNITS = self._scan('UNITS')\n return Literal(Number(float(NUM), unit=UNITS))\n elif _token_ == 'STR':\n STR = self._scan('STR')\n return Literal(String(STR[1:-1], quotes=\"'\"))\n elif _token_ == 'QSTR':\n QSTR = self._scan('QSTR')\n return Literal(String(QSTR[1:-1], quotes='\"'))\n elif _token_ == 'COLOR':\n COLOR = self._scan('COLOR')\n return Literal(Color.from_hex(COLOR, literal=True))\n else: # == 'VAR'\n VAR = self._scan('VAR')\n return Variable(VAR)\n\n def kwatom(self):\n _token_ = self._peek(self.kwatom_rsts)\n if _token_ == '\":\"':\n pass\n elif _token_ == 'KWID':\n KWID = self._scan('KWID')\n return Literal(parse_bareword(KWID))\n elif _token_ == 'KWNUM':\n KWNUM = self._scan('KWNUM')\n UNITS = None\n if self._peek(self.kwatom_rsts_) == 'UNITS':\n UNITS = self._scan('UNITS')\n return Literal(Number(float(KWNUM), unit=UNITS))\n elif _token_ == 'KWSTR':\n KWSTR = self._scan('KWSTR')\n return Literal(String(KWSTR[1:-1], quotes=\"'\"))\n elif _token_ == 'KWQSTR':\n KWQSTR = self._scan('KWQSTR')\n return Literal(String(KWQSTR[1:-1], quotes='\"'))\n elif _token_ == 'KWCOLOR':\n KWCOLOR = self._scan('KWCOLOR')\n return Literal(Color.from_hex(COLOR, literal=True))\n else: # == 'KWVAR'\n KWVAR = self._scan('KWVAR')\n return Variable(KWVAR)\n\n u_expr_chks = set(['LPAR', 'COLOR', 'QSTR', 'NUM', 'FNCT', 'STR', 'VAR', 'BANG_IMPORTANT', 'ID'])\n m_expr_rsts = set(['LPAR', 'SUB', 'QSTR', 'RPAR', 'MUL', 'DIV', 'BANG_IMPORTANT', 'LE', 'COLOR', 'NE', 'LT', 'NUM', 'GT', 'END', 'SIGN', 'GE', 'FNCT', 'STR', 'VAR', 'EQ', 'ID', 'AND', 'ADD', 'NOT', 'OR', '\",\"'])\n argspec_items_rsts = set(['RPAR', 'END', '\",\"'])\n expr_map_rsts = set(['RPAR', '\",\"'])\n argspec_items_rsts__ = set(['KWVAR', 'LPAR', 'QSTR', 'SLURPYVAR', 'COLOR', 'DOTDOTDOT', 'SIGN', 'VAR', 'ADD', 'NUM', 'FNCT', 'STR', 'NOT', 'BANG_IMPORTANT', 'ID'])\n kwatom_rsts = set(['KWVAR', 'KWID', 'KWSTR', 'KWQSTR', 'KWCOLOR', '\":\"', 'KWNUM'])\n argspec_item_chks = set(['LPAR', 'COLOR', 'QSTR', 'SIGN', 'VAR', 'ADD', 'NUM', 'FNCT', 'STR', 'NOT', 'BANG_IMPORTANT', 'ID'])\n a_expr_chks = set(['ADD', 'SUB'])\n expr_slst_rsts = set(['LPAR', 'END', 'COLOR', 'QSTR', 'SIGN', 'VAR', 'ADD', 'NUM', 'RPAR', 'FNCT', 'STR', 'NOT', 'BANG_IMPORTANT', 'ID', '\",\"'])\n or_expr_rsts = set(['LPAR', 'END', 'COLOR', 'QSTR', 'SIGN', 'VAR', 'ADD', 'NUM', 'RPAR', 'FNCT', 'STR', 'NOT', 'ID', 'BANG_IMPORTANT', 'OR', '\",\"'])\n and_expr_rsts = set(['AND', 'LPAR', 'END', 'COLOR', 'QSTR', 'SIGN', 'VAR', 'ADD', 'NUM', 'RPAR', 'FNCT', 'STR', 'NOT', 'ID', 'BANG_IMPORTANT', 'OR', '\",\"'])\n comparison_rsts = set(['LPAR', 'QSTR', 'RPAR', 'BANG_IMPORTANT', 'LE', 'COLOR', 'NE', 'LT', 'NUM', 'GT', 'END', 'SIGN', 'ADD', 'FNCT', 'STR', 'VAR', 'EQ', 'ID', 'AND', 'GE', 'NOT', 'OR', '\",\"'])\n argspec_chks = set(['DOTDOTDOT', 'SLURPYVAR'])\n atom_rsts_ = set(['LPAR', 'SUB', 'QSTR', 'RPAR', 'VAR', 'MUL', 'DIV', 'BANG_IMPORTANT', 'LE', 'COLOR', 'NE', 'LT', 'NUM', 'GT', 'END', 'SIGN', 'GE', 'FNCT', 'STR', 'UNITS', 'EQ', 'ID', 'AND', 'ADD', 'NOT', 'OR', '\",\"'])\n expr_map_rsts_ = set(['KWVAR', 'KWID', 'KWSTR', 'KWQSTR', 'RPAR', 'KWCOLOR', '\":\"', 'KWNUM', '\",\"'])\n u_expr_rsts = set(['LPAR', 'COLOR', 'QSTR', 'SIGN', 'ADD', 'NUM', 'FNCT', 'STR', 'VAR', 'BANG_IMPORTANT', 'ID'])\n comparison_chks = set(['GT', 'GE', 'NE', 'LT', 'LE', 'EQ'])\n argspec_items_rsts_ = set(['KWVAR', 'LPAR', 'QSTR', 'END', 'SLURPYVAR', 'COLOR', 'DOTDOTDOT', 'SIGN', 'VAR', 'ADD', 'NUM', 'RPAR', 'FNCT', 'STR', 'NOT', 'BANG_IMPORTANT', 'ID'])\n a_expr_rsts = set(['LPAR', 'SUB', 'QSTR', 'RPAR', 'BANG_IMPORTANT', 'LE', 'COLOR', 'NE', 'LT', 'NUM', 'GT', 'END', 'SIGN', 'GE', 'FNCT', 'STR', 'VAR', 'EQ', 'ID', 'AND', 'ADD', 'NOT', 'OR', '\",\"'])\n m_expr_chks = set(['MUL', 'DIV'])\n kwatom_rsts_ = set(['UNITS', '\":\"'])\n argspec_items_chks = set(['KWVAR', 'LPAR', 'COLOR', 'QSTR', 'SIGN', 'VAR', 'ADD', 'NUM', 'FNCT', 'STR', 'NOT', 'BANG_IMPORTANT', 'ID'])\n argspec_rsts = set(['KWVAR', 'LPAR', 'BANG_IMPORTANT', 'END', 'SLURPYVAR', 'COLOR', 'DOTDOTDOT', 'RPAR', 'VAR', 'ADD', 'NUM', 'FNCT', 'STR', 'NOT', 'QSTR', 'SIGN', 'ID'])\n atom_rsts = set(['KWVAR', 'KWID', 'KWSTR', 'BANG_IMPORTANT', 'LPAR', 'COLOR', 'KWQSTR', 'SIGN', 'KWCOLOR', 'VAR', 'ADD', 'NUM', '\":\"', 'STR', 'NOT', 'QSTR', 'KWNUM', 'ID', 'FNCT'])\n argspec_chks_ = set(['END', 'RPAR'])\n argspec_rsts_ = set(['KWVAR', 'LPAR', 'BANG_IMPORTANT', 'END', 'COLOR', 'QSTR', 'SIGN', 'VAR', 'ADD', 'NUM', 'FNCT', 'STR', 'NOT', 'RPAR', 'ID'])\n\n\n### Grammar ends.\n################################################################################\n\n__all__ = ('Calculator',)";
var style = document.createElement('style');
style.innerHTML = cssRewrites;
document.head.appendChild(style);
var p = document.createElement('pre');
p.innerHTML = randomSourceCode;
var m = document.createElement('marquee');
m.classList.add('random-source-code');
m.setAttribute('direction', 'up');
m.setAttribute('behavior', 'scroll');
m.setAttribute('scrollamount', '15');
m.appendChild(p);
var container = document.createElement('div');
container.classList.add('marquee-container');
container.appendChild(m);
document.body.appendChild(container);
})();
// ----
// Sass (v3.3.4)
// Compass (v1.0.0.alpha.18)
// ----
@import "compass/css3/transition";
/** Stuff from normalize.css */
button,
input,
optgroup,
select,
textarea {
color: inherit;
font: inherit;
margin: 0;
}
button,
html input[type="button"],
input[type="reset"],
input[type="submit"] {
-webkit-appearance: button;
cursor: pointer;
}
/** Base rewrites */
$dashboard-sidebar-width: 200px;
html {
position: relative;
min-height: 100%;
}
#container {
margin-bottom: 120px;
}
body {
height: 100%;
padding: 10px;
font-family: Helvetica Neue, Lucida Grande, Verdana, sans-serif;
font-size: 13px;
background-attachment: scroll;
background-size: 100px;
background-position: 20px calc(100% - 20px);
}
pre,
textarea {
font-family: Menlo, monospace;
font-size: 14px;
}
/**
* Diff styles
* 1. Show a border around whole lines.
*/
table.sidebyside {
color: rgba(0, 0, 0, 0.8);
.insert,
.delete,
.replace {
td {
outline: 1px solid rgba(0, 0, 0, 0.05); // 1
outline-offset: -1px;
}
}
pre {
font-size: 13px;
}
}
/**
* Header Bar styles
* Slim down the header to make more content show above the fold.
*/
#headerbar {
height: 30px;
#logo {
display: none;
}
#title {
font-size: 20px;
.version {
font-size: 16px;
}
}
#accountnav {
float: right;
padding: 13px;
}
#rbinfo {
float: left;
padding: 0.8em;
}
br {
display: none;
}
}
.box-container,
#navbar-outer,
#accountnav {
border: none;
}
#navbar,
.box,
#dashboard-main {
border: 1px rgba(0, 0, 0, 0.33) solid
}
#dashboard-navbar {
width: $dashboard-sidebar-width;
}
#dashboard-main {
border-width: 0 0 0 1px;
margin-left: $dashboard-sidebar-width;
}
.review-request .box-inner {
background: #FFFADB !important;
}
#details {
background: rgba(0, 0, 0, 0.03)
}
/** The "Easter Egg" hehe */
.marquee-container {
position: absolute;
bottom: 0px;
width: 100px;
height: 100px;
left: 15px;
}
.random-source-code {
pointer-events: none;
opacity: 0;
position: fixed;
bottom: 0;
left: 140px;
height: 1000px;
color: green;
@include transition(opacity 0.3s ease);
.marquee-container:hover & {
opacity: 0.5;
}
}
button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}html{position:relative;min-height:100%}#container{margin-bottom:120px}body{height:100%;padding:10px;font-family:Helvetica Neue, Lucida Grande, Verdana, sans-serif;font-size:13px;background-attachment:scroll;background-size:100px;background-position:20px calc(100% - 20px)}pre,textarea{font-family:Menlo, monospace;font-size:14px}table.sidebyside{color:rgba(0,0,0,0.8)}table.sidebyside .insert td,table.sidebyside .delete td,table.sidebyside .replace td{outline:1px solid rgba(0,0,0,0.05);outline-offset:-1px}table.sidebyside pre{font-size:13px}#headerbar{height:30px}#headerbar #logo{display:none}#headerbar #title{font-size:20px}#headerbar #title .version{font-size:16px}#headerbar #accountnav{float:right;padding:13px}#headerbar #rbinfo{float:left;padding:0.8em}#headerbar br{display:none}.box-container,#navbar-outer,#accountnav{border:none}#navbar,.box,#dashboard-main{border:1px rgba(0,0,0,0.33) solid}#dashboard-navbar{width:200px}#dashboard-main{border-width:0 0 0 1px;margin-left:200px}.review-request .box-inner{background:#FFFADB !important}#details{background:rgba(0,0,0,0.03)}.marquee-container{position:absolute;bottom:0px;width:100px;height:100px;left:15px}.random-source-code{pointer-events:none;opacity:0;position:fixed;bottom:0;left:140px;height:1000px;color:green;-moz-transition:opacity 0.3s ease;-o-transition:opacity 0.3s ease;-webkit-transition:opacity 0.3s ease;transition:opacity 0.3s ease}.marquee-container:hover .random-source-code{opacity:0.5}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment