├── .gitignore ├── CHANGELOG.md ├── README.md ├── bluebutton.html ├── bluebutton.html.sample ├── build.py ├── contrib ├── __init__.py ├── cssmin.py └── jsmin.py ├── data.xml.sample ├── data.xml.sample2 ├── data.xml.sample3 └── themes └── official ├── config.rb ├── file-hashes.json ├── js ├── 01-modernizr-2.6.2.min.js ├── 02-jquery-1.9.0.min.js ├── 03-swig.min.js ├── 04-bluebutton-0.0.10.js └── 05-bbclear.js ├── sass ├── print.scss └── screen.scss ├── stylesheets ├── normalize.css ├── print.css └── screen.css └── template.html /.gitignore: -------------------------------------------------------------------------------- 1 | *.py[cod] 2 | 3 | # C extensions 4 | *.so 5 | 6 | # Packages 7 | *.egg 8 | *.egg-info 9 | dist 10 | eggs 11 | parts 12 | bin 13 | var 14 | sdist 15 | develop-eggs 16 | .installed.cfg 17 | lib 18 | lib64 19 | .sass-cache/ 20 | 21 | # Installer logs 22 | pip-log.txt 23 | 24 | # Unit test / coverage reports 25 | .coverage 26 | .tox 27 | nosetests.xml 28 | 29 | # Translations 30 | *.mo 31 | 32 | # Mr Developer 33 | .mr.developer.cfg 34 | .project 35 | .pydevproject 36 | 37 | .DS_Store -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # 0.5.3 (May 1, 2013) 2 | 3 | * Reverted the data wrapping mechanism back to a script tag, but using text/plain as the mime type so as not to break in IE. This should be the best of all pragmatic worlds, the only downside being the inaccurate mime type. 4 | 5 | # 0.5.2 (Apr 30, 2013) 6 | 7 | * Updating to bluebutton.js 0.0.10 (thanks to @blacktm) 8 | * Enforce alphabetical order of script injection (thanks to @jmandel) 9 | * Updated README with dependency information. 10 | 11 | # 0.5.1 (Apr 19, 2013) 12 | 13 | * Updating to bluebutton.js 0.0.9 (thanks to @blacktm) 14 | * Improving build script to handle replaced files 15 | 16 | # 0.5.0 (Apr 15, 2013) 17 | 18 | Initial Release 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | bbClear 2 | ========== 3 | 4 | A visualization framework for health records, based on [bluebutton.js](http://github.com/blue-button/bluebutton.js/). 5 | 6 | bbClear creates self-contained HTML documents that can parse and display the contents of common XML-formatted health records, such as those conforming to the CCDA standard. It assembles assets such as stylesheets, Javascripts, and the XML data, and provides an easy-to-use templating framework based on [swig](http://paularmstrong.github.io/swig/) to produce a portable, user-faceable representation of the data. 7 | 8 | ## Getting Started 9 | 10 | bbClear comes with a default theme, aptly named 'clear,' so you're able to get moving right away. If you have an XML data file that conforms to CCDA or one of the other formats supported by bluebutton.js, place it in the main directory of this repository and run: 11 | 12 | python build.py -f -d 13 | 14 | This will build a BlueButton HTML file in the same directory, named `bluebutton.html`. Fire this up in your favorite [modern] web browser, and see what it gives you. 15 | 16 | ## Depdendencies 17 | 18 | bbClear itself is dependent only on [Python](http://python.org). Some themes may have additional dependencies as well. The official theme makes optional use of [Compass](http://compass-style.org/) for CSS authoring. 19 | 20 | ## Browser support 21 | 22 | Currently, bbClear tries to support commonly-used browsers down to IE8. No support is claimed for IE7 or below, or relatively-ancient versions of browsers such as Safari, Firefox, or Chrome. 23 | 24 | ## Documentation 25 | 26 | For more information and documentation, visit http://blue-button.github.io/bbClear/ 27 | 28 | ## Copyright and Licensing 29 | 30 | Copyright (c) 2013 by [M. Jackson Wilkinson](http://mjacksonw.com). Licensed under the [Apache 2.0](http://www.apache.org/licenses/LICENSE-2.0.html) license. 31 | -------------------------------------------------------------------------------- /build.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Blue Button Build Script 5 | Copyright 2013 by M. Jackson Wilkinson 6 | 7 | Running this script polls the theme folder for changes and compiles the template 8 | in the directory that holds this script. 9 | 10 | Requirements: 11 | - Python (2.6 or higher; untested on 3.x) 12 | - Ruby 13 | - Compass: 'gem install compass' 14 | 15 | Notes: 16 | - It minifies javascript files, unless they have '.min.' in the filename. 17 | - It compiles SCSS into CSS and minifies 18 | - It encodes any referenced images as base64 and includes them in the CSS 19 | - It includes files in order of their filename into 'template.html': 20 | - {% insert: js %} (any files in theme/ ending in .js) 21 | - {% insert: css %} (the compiled results of theme/sass, in theme/stylesheets) 22 | - Any 'print.css' file is included with the print media attribute 23 | - Any 'ie.css' file is included within an IE conditional comment. 24 | - {% insert: data %} (any existing data.json, or a placeholder if none) 25 | """ 26 | 27 | import os 28 | import hashlib 29 | import json 30 | import re 31 | import time 32 | import logging 33 | import argparse 34 | import subprocess 35 | import datetime 36 | import codecs 37 | from xml.sax.handler import ContentHandler 38 | from xml.sax import make_parser 39 | 40 | import contrib 41 | from contrib.jsmin import jsmin 42 | from contrib.cssmin import cssmin 43 | 44 | globals()['WORKING'] = False 45 | CONTRIB_DIR = contrib.module_dir() 46 | SCRIPT_DIR = contrib.module_parent() 47 | THEMES_DIR = SCRIPT_DIR + "/themes" 48 | 49 | logger = logging.getLogger('bluebutton') 50 | logger.setLevel(getattr(logging, 'INFO')) 51 | logger_handler = logging.StreamHandler() 52 | logger_handler.setLevel(logging.DEBUG) 53 | logger.addHandler(logger_handler) 54 | 55 | 56 | def build_project(theme="official", watch=False, data_file="data.xml", force=False): 57 | globals()['THEME_DIR'] = "%s/%s" % (THEMES_DIR, theme) 58 | if force: 59 | output = inject_scripts() 60 | output = inject_styles(output) 61 | output = inject_data(input=output, data_file=data_file) 62 | write_output(output) 63 | elif not globals()['WORKING']: 64 | globals()['WORKING'] = True 65 | logger.debug("Checking for changes to project files.") 66 | hashes = build_hashes() 67 | if compare_timestamps(): 68 | if watch: 69 | logger.debug("- No changes to files") 70 | else: 71 | logger.info("- No changes to files") 72 | else: 73 | if compare_hashes(hashes): 74 | if watch: 75 | logger.debug("- No changes to files") 76 | else: 77 | logger.info("- No changes to files") 78 | else: 79 | write_hashes(hashes) 80 | output = inject_scripts() 81 | output = inject_styles(output) 82 | output = inject_data(input=output, data_file=data_file) 83 | write_output(output) 84 | globals()['WORKING'] = False 85 | else: 86 | logger.debug("Currently working, so skipping this build.") 87 | 88 | 89 | def build_hashes(): 90 | logger.debug("Building hashes") 91 | 92 | hashes = [] 93 | 94 | # Find files in the build directory to compare 95 | for dirname, dirnames, filenames in os.walk(globals()['THEME_DIR']): 96 | for filename in filenames: 97 | if filename.split('.')[-1] in ['css', 'js', 'jpg', 'png', 'gif']: 98 | path = os.path.join(dirname, filename) 99 | useful_name = path.partition(globals()['THEME_DIR'])[2].strip("/") 100 | working_file = open(path) 101 | modified = datetime.datetime.fromtimestamp(os.path.getmtime(path)) 102 | md5_hash = md5_for_file(open(path)) 103 | working_file.close() 104 | hashes.append({"filename": useful_name, "hash": md5_hash, "modified": modified}) 105 | 106 | # Check the template file 107 | template_filename = globals()['THEME_DIR'] + "/template.html" 108 | template_file = open(template_filename) 109 | template_modified = datetime.datetime.fromtimestamp(os.path.getmtime(template_filename)) 110 | hashes.append({"filename": 'template.html', "hash": md5_for_file(template_file), 'modified': template_modified}) 111 | template_file.close() 112 | 113 | try: 114 | # Check the data file 115 | data_filename = globals()['THEME_DIR'] + "/data.json" 116 | data_file = open(data_filename) 117 | data_modified = datetime.datetime.fromtimestamp(os.path.getmtime(data_filename)) 118 | hashes.append({"filename": 'data.json', "hash": md5_for_file(data_file), 'modified': data_modified}) 119 | template_file.close() 120 | except IOError: 121 | pass 122 | 123 | return hashes 124 | 125 | 126 | def compare_timestamps(): 127 | """ 128 | Returns True if all known files have consistent timestamps. False if not. 129 | """ 130 | logger.debug("Comparing timestamps") 131 | 132 | try: 133 | file_hashes = open(globals()['THEME_DIR'] + "/file-hashes.json", "r") 134 | except IOError: 135 | return False 136 | 137 | try: 138 | stored_hashes = json.loads(file_hashes.read()) 139 | except ValueError: 140 | return False 141 | 142 | for h in stored_hashes: 143 | filename = globals()['THEME_DIR'] + '/' + h['filename'] 144 | try: 145 | modified = str(datetime.datetime.fromtimestamp(os.path.getmtime(filename))).replace(' ', 'T') 146 | if h['modified'] != modified: 147 | logger.debug('Found a timestamp change. Checking more deeply. %s' % (filename)) 148 | return False 149 | except: 150 | return False 151 | 152 | file_hashes.close() 153 | return True 154 | 155 | 156 | def compare_hashes(hashes): 157 | """ 158 | Returns True if all known files have identical hashes, False if not 159 | """ 160 | logger.debug("Comparing hashes") 161 | 162 | try: 163 | file_hashes = open(globals()['THEME_DIR'] + "/file-hashes.json", "r") 164 | except IOError: 165 | logger.info("No hashes file found (theme/file-hashes.json). Creating one.") 166 | return False 167 | 168 | try: 169 | stored_hashes = json.loads(file_hashes.read()) 170 | except ValueError: 171 | logger.warning("Hashes file is invalid. Rebuilding.") 172 | return False 173 | 174 | # Compare stored hashes against new hashes 175 | for h in hashes: 176 | found = False 177 | for s in stored_hashes: 178 | if s['filename'] == h['filename']: 179 | if s['hash'] != h['hash']: 180 | logger.info("Found a change to %s. Rebuilding." % (h['filename'])) 181 | return False 182 | else: 183 | logger.debug("No change: %s" % (h['filename'])) 184 | found = True 185 | if not found: 186 | logger.info("Found a new file: %s. Rebuilding." % (h['filename'])) 187 | return False 188 | 189 | file_hashes.close() 190 | return True 191 | 192 | 193 | def write_hashes(hashes): 194 | logger.debug("Writing hashes") 195 | 196 | dthandler = lambda obj: obj.isoformat() if isinstance(obj, datetime.datetime) else None 197 | file_hashes = open(globals()['THEME_DIR'] + "/file-hashes.json", "w") 198 | output = json.dumps(hashes, indent=4, separators=(',', ': '), default=dthandler) 199 | file_hashes.write(output) 200 | file_hashes.close() 201 | 202 | return True 203 | 204 | 205 | def inject_scripts(input=None): 206 | logger.info("> Injecting scripts") 207 | scripts_tag = r'([^\S\n]*){%\s?insert\s?scripts\s?%}' 208 | scripts = [] 209 | 210 | for dirname, dirnames, filenames in os.walk(globals()['THEME_DIR'] + "/js"): 211 | filenames.sort() 212 | for filename in filenames: 213 | if filename.split('.')[-1] == 'js': 214 | path = os.path.join(dirname, filename) 215 | scripts.append(path) 216 | 217 | if not input: 218 | logger.debug("- Fetching the template.") 219 | try: 220 | template_file = open(globals()['THEME_DIR'] + "/template.html", "r") 221 | input = template_file.read() 222 | except IOError: 223 | raise TemplateError("Template file could not be opened") 224 | 225 | while re.search(scripts_tag, input, flags=re.IGNORECASE): 226 | tag = re.search(scripts_tag, input, flags=re.IGNORECASE) 227 | begin, end, whitespace = (tag.start(), tag.end(), tag.group(1)) 228 | script_data = "" 229 | 230 | for script in scripts: 231 | logger.debug("- Adding %s to script data" % (script)) 232 | useful_name = script.partition(globals()['THEME_DIR'])[2].strip("/") 233 | data = open(script).read() 234 | if not re.search(r'\.min\.', useful_name, flags=re.IGNORECASE): 235 | data = jsmin(data) 236 | script_data += "%s/* %s */ %s" % (whitespace, useful_name, data) 237 | 238 | script_data = "%s\n%s" % (whitespace, whitespace, script_data, whitespace) 239 | input = input[:begin] + script_data + input[end:] 240 | 241 | return input 242 | 243 | 244 | def inject_styles(input=None): 245 | logger.info("> Injecting styles") 246 | styles_tag = r'([^\S\n]*){%\s?insert\s?styles\s?%}' 247 | stylesheets = [] 248 | 249 | # Run compass to compile any SCSS 250 | os.chdir(globals()['THEME_DIR']) 251 | subprocess.call(['compass', 'compile', '-q']) 252 | os.chdir(SCRIPT_DIR) 253 | 254 | for dirname, dirnames, filenames in os.walk(globals()['THEME_DIR'] + "/stylesheets"): 255 | for filename in filenames: 256 | if filename.split('.')[-1] == 'css' and not re.search(r'(ie|print)\.', filename): 257 | path = os.path.join(dirname, filename) 258 | stylesheets.append(path) 259 | 260 | if not input: 261 | logger.debug("- Fetching the template.") 262 | try: 263 | template_file = open(globals()['THEME_DIR'] + "/template.html", "r") 264 | input = template_file.read() 265 | except IOError: 266 | raise TemplateError("Template file could not be opened") 267 | 268 | while re.search(styles_tag, input, flags=re.IGNORECASE): 269 | tag = re.search(styles_tag, input, flags=re.IGNORECASE) 270 | begin, end, whitespace = (tag.start(), tag.end(), tag.group(1)) 271 | styles_data = "" 272 | 273 | for sheet in stylesheets: 274 | logger.debug("- Adding %s to styles data" % (sheet)) 275 | useful_name = sheet.partition(globals()['THEME_DIR'])[2].strip("/") 276 | data = open(sheet).read() 277 | if not re.search(r'\.min\.', useful_name, flags=re.IGNORECASE): 278 | data = cssmin(data) 279 | styles_data += "%s/* %s */ %s\n" % (whitespace, useful_name, data) 280 | 281 | styles_data = '%s\n%s' % (whitespace, whitespace, styles_data, whitespace) 282 | 283 | try: 284 | data = open(globals()['THEME_DIR'] + "/stylesheets/print.css").read() 285 | data = cssmin(data) 286 | styles_data += '\n%s' % (whitespace, whitespace, data, whitespace) 287 | except IOError: 288 | pass 289 | 290 | input = input[:begin] + styles_data + input[end:] 291 | 292 | return input 293 | 294 | 295 | def inject_data(input=None, placeholder=False, data_file='data.xml'): 296 | logger.info("> Injecting data") 297 | data_tag = r'([^\S\n]*){%\s?insert\s?data\s?%}' 298 | 299 | if not placeholder: 300 | try: 301 | data_filename = SCRIPT_DIR + "/%s" % (data_file) 302 | data = codecs.open(data_filename, encoding="utf-8", mode="r").read() 303 | try: 304 | parser = make_parser() 305 | parser.setContentHandler(ContentHandler()) 306 | parser.parse(data_filename) 307 | except: 308 | pass 309 | # raise DataError("Data file is not proper XML") 310 | except IOError: 311 | logger.info("- No data file found (%s). Using placeholder." % (data_file)) 312 | placeholder = True 313 | 314 | if not input: 315 | logger.debug("- Fetching the template.") 316 | try: 317 | template_file = open(globals()['THEME_DIR'] + "/template.html", "r") 318 | input = template_file.read() 319 | except IOError: 320 | raise TemplateError("Template file could not be opened") 321 | 322 | while re.search(data_tag, input, flags=re.IGNORECASE): 323 | tag = re.search(data_tag, input, flags=re.IGNORECASE) 324 | begin = tag.start() 325 | end = tag.end() 326 | whitespace = tag.group(1) 327 | if not placeholder: 328 | data = '%s\n%s' % (whitespace, whitespace, data) 329 | input = input[:begin] + data + input[end:] 330 | else: 331 | logger.debug("- Writing placeholder.") 332 | placeholder_text = '%s' % (whitespace, whitespace, whitespace) 333 | input = input[:begin] + placeholder_text + input[end:] 334 | 335 | return input 336 | 337 | 338 | def write_output(output): 339 | target_file = codecs.open(SCRIPT_DIR + "/bluebutton.html", encoding="utf-8", mode="w") 340 | target_file.write(output) 341 | target_file.close() 342 | 343 | logger.info("< Written successfully to bluebutton.html") 344 | 345 | 346 | def md5_for_file(f, block_size=1000000): 347 | md5 = hashlib.md5() 348 | while True: 349 | data = f.read(block_size) 350 | if not data: 351 | break 352 | md5.update(data) 353 | return md5.hexdigest() 354 | 355 | 356 | class TemplateError(Exception): 357 | def __init__(self, value): 358 | self.value = value 359 | 360 | def __str__(self): 361 | return repr(self.value) 362 | 363 | 364 | class DataError(Exception): 365 | def __init__(self, value): 366 | self.value = value 367 | 368 | def __str__(self): 369 | return repr(self.value) 370 | 371 | 372 | if __name__ == '__main__': 373 | parser = argparse.ArgumentParser() 374 | parser.add_argument('-v', '--verbose', action='store_true') 375 | parser.add_argument('-w', '--watch', action='store_true') 376 | parser.add_argument('-t', '--theme', default='official') 377 | parser.add_argument('-f', '--force', action='store_true') 378 | parser.add_argument('-d', '--data', default='data.xml') 379 | args = parser.parse_args() 380 | 381 | if args.verbose: 382 | logger.setLevel(getattr(logging, 'DEBUG')) 383 | 384 | if not args.watch or args.force: 385 | if args.watch: 386 | logger.info('You cannot watch and force at the same time. Forcing this time.') 387 | logger.info("Building the project using the '%s' theme..." % (args.theme)) 388 | build_project(theme=args.theme, watch=args.watch, force=args.force, data_file=args.data) 389 | else: 390 | print ">>> Monitoring for changes to project files. Press Ctrl-C to stop." 391 | while True: 392 | build_project(theme=args.theme, watch=True, data_file=args.data) 393 | time.sleep(1) 394 | -------------------------------------------------------------------------------- /contrib/__init__.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | 4 | 5 | def we_are_frozen(): 6 | # All of the modules are built-in to the interpreter, e.g., by py2exe 7 | return hasattr(sys, "frozen") 8 | 9 | 10 | def module_abspath(): 11 | encoding = sys.getfilesystemencoding() 12 | if we_are_frozen(): 13 | return os.path.abspath(unicode(sys.executable, encoding)) 14 | return os.path.abspath(unicode(__file__, encoding)) 15 | 16 | 17 | def module_dir(): 18 | return os.path.dirname(module_abspath()) 19 | 20 | 21 | def module_parent(): 22 | return os.path.dirname(module_dir()) 23 | -------------------------------------------------------------------------------- /contrib/cssmin.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | """ 5 | `cssmin.py` - A Python port of the YUI CSS compressor. 6 | 7 | Copyright (c) 2010 Zachary Voase 8 | 9 | Permission is hereby granted, free of charge, to any person 10 | obtaining a copy of this software and associated documentation 11 | files (the "Software"), to deal in the Software without 12 | restriction, including without limitation the rights to use, 13 | copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the 15 | Software is furnished to do so, subject to the following 16 | conditions: 17 | 18 | The above copyright notice and this permission notice shall be 19 | included in all copies or substantial portions of the Software. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 23 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 25 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 26 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 27 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 28 | OTHER DEALINGS IN THE SOFTWARE. 29 | 30 | ------------------------------------------------------------------------------- 31 | 32 | This software contains portions of the YUI CSS Compressor, notably some regular 33 | expressions for reducing the size of CSS. The YUI Compressor source code can be 34 | found at , and is licensed as follows: 35 | 36 | > YUI Compressor Copyright License Agreement (BSD License) 37 | > 38 | > Copyright (c) 2009, Yahoo! Inc. 39 | > All rights reserved. 40 | > 41 | > Redistribution and use of this software in source and binary forms, 42 | > with or without modification, are permitted provided that the following 43 | > conditions are met: 44 | > 45 | > * Redistributions of source code must retain the above 46 | > copyright notice, this list of conditions and the 47 | > following disclaimer. 48 | > 49 | > * Redistributions in binary form must reproduce the above 50 | > copyright notice, this list of conditions and the 51 | > following disclaimer in the documentation and/or other 52 | > materials provided with the distribution. 53 | > 54 | > * Neither the name of Yahoo! Inc. nor the names of its 55 | > contributors may be used to endorse or promote products 56 | > derived from this software without specific prior 57 | > written permission of Yahoo! Inc. 58 | > 59 | > THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 60 | > AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 61 | > IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 62 | > DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 63 | > FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 64 | > DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 65 | > SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 66 | > CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 67 | > OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 68 | > OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 69 | 70 | """ 71 | 72 | from StringIO import StringIO # The pure-Python StringIO supports unicode. 73 | import re 74 | 75 | 76 | __version__ = '0.1.4' 77 | 78 | 79 | def remove_comments(css): 80 | """Remove all CSS comment blocks.""" 81 | 82 | iemac = False 83 | preserve = False 84 | comment_start = css.find("/*") 85 | while comment_start >= 0: 86 | # Preserve comments that look like `/*!...*/`. 87 | # Slicing is used to make sure we don"t get an IndexError. 88 | preserve = css[comment_start + 2:comment_start + 3] == "!" 89 | 90 | comment_end = css.find("*/", comment_start + 2) 91 | if comment_end < 0: 92 | if not preserve: 93 | css = css[:comment_start] 94 | break 95 | elif comment_end >= (comment_start + 2): 96 | if css[comment_end - 1] == "\\": 97 | # This is an IE Mac-specific comment; leave this one and the 98 | # following one alone. 99 | comment_start = comment_end + 2 100 | iemac = True 101 | elif iemac: 102 | comment_start = comment_end + 2 103 | iemac = False 104 | elif not preserve: 105 | css = css[:comment_start] + css[comment_end + 2:] 106 | else: 107 | comment_start = comment_end + 2 108 | comment_start = css.find("/*", comment_start) 109 | 110 | return css 111 | 112 | 113 | def remove_unnecessary_whitespace(css): 114 | """Remove unnecessary whitespace characters.""" 115 | 116 | def pseudoclasscolon(css): 117 | 118 | """ 119 | Prevents 'p :link' from becoming 'p:link'. 120 | 121 | Translates 'p :link' into 'p ___PSEUDOCLASSCOLON___link'; this is 122 | translated back again later. 123 | """ 124 | 125 | regex = re.compile(r"(^|\})(([^\{\:])+\:)+([^\{]*\{)") 126 | match = regex.search(css) 127 | while match: 128 | css = ''.join([ 129 | css[:match.start()], 130 | match.group().replace(":", "___PSEUDOCLASSCOLON___"), 131 | css[match.end():]]) 132 | match = regex.search(css) 133 | return css 134 | 135 | css = pseudoclasscolon(css) 136 | # Remove spaces from before things. 137 | css = re.sub(r"\s+([!{};:>+\(\)\],])", r"\1", css) 138 | 139 | # If there is a `@charset`, then only allow one, and move to the beginning. 140 | css = re.sub(r"^(.*)(@charset \"[^\"]*\";)", r"\2\1", css) 141 | css = re.sub(r"^(\s*@charset [^;]+;\s*)+", r"\1", css) 142 | 143 | # Put the space back in for a few cases, such as `@media screen` and 144 | # `(-webkit-min-device-pixel-ratio:0)`. 145 | css = re.sub(r"\band\(", "and (", css) 146 | 147 | # Put the colons back. 148 | css = css.replace('___PSEUDOCLASSCOLON___', ':') 149 | 150 | # Remove spaces from after things. 151 | css = re.sub(r"([!{}:;>+\(\[,])\s+", r"\1", css) 152 | 153 | return css 154 | 155 | 156 | def remove_unnecessary_semicolons(css): 157 | """Remove unnecessary semicolons.""" 158 | 159 | return re.sub(r";+\}", "}", css) 160 | 161 | 162 | def remove_empty_rules(css): 163 | """Remove empty rules.""" 164 | 165 | return re.sub(r"[^\}\{]+\{\}", "", css) 166 | 167 | 168 | def normalize_rgb_colors_to_hex(css): 169 | """Convert `rgb(51,102,153)` to `#336699`.""" 170 | 171 | regex = re.compile(r"rgb\s*\(\s*([0-9,\s]+)\s*\)") 172 | match = regex.search(css) 173 | while match: 174 | colors = map(lambda s: s.strip(), match.group(1).split(",")) 175 | hexcolor = '#%.2x%.2x%.2x' % tuple(map(int, colors)) 176 | css = css.replace(match.group(), hexcolor) 177 | match = regex.search(css) 178 | return css 179 | 180 | 181 | def condense_zero_units(css): 182 | """Replace `0(px, em, %, etc)` with `0`.""" 183 | 184 | return re.sub(r"([\s:])(0)(px|em|%|in|cm|mm|pc|pt|ex)", r"\1\2", css) 185 | 186 | 187 | def condense_multidimensional_zeros(css): 188 | """Replace `:0 0 0 0;`, `:0 0 0;` etc. with `:0;`.""" 189 | 190 | css = css.replace(":0 0 0 0;", ":0;") 191 | css = css.replace(":0 0 0;", ":0;") 192 | css = css.replace(":0 0;", ":0;") 193 | 194 | # Revert `background-position:0;` to the valid `background-position:0 0;`. 195 | css = css.replace("background-position:0;", "background-position:0 0;") 196 | 197 | return css 198 | 199 | 200 | def condense_floating_points(css): 201 | """Replace `0.6` with `.6` where possible.""" 202 | 203 | return re.sub(r"(:|\s)0+\.(\d+)", r"\1.\2", css) 204 | 205 | 206 | def condense_hex_colors(css): 207 | """Shorten colors from #AABBCC to #ABC where possible.""" 208 | 209 | regex = re.compile(r"([^\"'=\s])(\s*)#([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])") 210 | match = regex.search(css) 211 | while match: 212 | first = match.group(3) + match.group(5) + match.group(7) 213 | second = match.group(4) + match.group(6) + match.group(8) 214 | if first.lower() == second.lower(): 215 | css = css.replace(match.group(), match.group(1) + match.group(2) + '#' + first) 216 | match = regex.search(css, match.end() - 3) 217 | else: 218 | match = regex.search(css, match.end()) 219 | return css 220 | 221 | 222 | def condense_whitespace(css): 223 | """Condense multiple adjacent whitespace characters into one.""" 224 | 225 | return re.sub(r"\s+", " ", css) 226 | 227 | 228 | def condense_semicolons(css): 229 | """Condense multiple adjacent semicolon characters into one.""" 230 | 231 | return re.sub(r";;+", ";", css) 232 | 233 | 234 | def wrap_css_lines(css, line_length): 235 | """Wrap the lines of the given CSS to an approximate length.""" 236 | 237 | lines = [] 238 | line_start = 0 239 | for i, char in enumerate(css): 240 | # It's safe to break after `}` characters. 241 | if char == '}' and (i - line_start >= line_length): 242 | lines.append(css[line_start:i + 1]) 243 | line_start = i + 1 244 | 245 | if line_start < len(css): 246 | lines.append(css[line_start:]) 247 | return '\n'.join(lines) 248 | 249 | 250 | def cssmin(css, wrap=None): 251 | css = remove_comments(css) 252 | css = condense_whitespace(css) 253 | # A pseudo class for the Box Model Hack 254 | # (see http://tantek.com/CSS/Examples/boxmodelhack.html) 255 | css = css.replace('"\\"}\\""', "___PSEUDOCLASSBMH___") 256 | css = remove_unnecessary_whitespace(css) 257 | css = remove_unnecessary_semicolons(css) 258 | css = condense_zero_units(css) 259 | css = condense_multidimensional_zeros(css) 260 | css = condense_floating_points(css) 261 | css = normalize_rgb_colors_to_hex(css) 262 | css = condense_hex_colors(css) 263 | if wrap is not None: 264 | css = wrap_css_lines(css, wrap) 265 | css = css.replace("___PSEUDOCLASSBMH___", '"\\"}\\""') 266 | css = condense_semicolons(css) 267 | return css.strip() 268 | 269 | 270 | def main(): 271 | import optparse 272 | import sys 273 | 274 | p = optparse.OptionParser( 275 | prog="cssmin", version=__version__, 276 | usage="%prog [--wrap N]", 277 | description="""Reads raw CSS from stdin, and writes compressed CSS to stdout.""") 278 | 279 | p.add_option( 280 | '-w', '--wrap', type='int', default=None, metavar='N', 281 | help="Wrap output to approximately N chars per line.") 282 | 283 | options, args = p.parse_args() 284 | sys.stdout.write(cssmin(sys.stdin.read(), wrap=options.wrap)) 285 | 286 | 287 | if __name__ == '__main__': 288 | main() 289 | -------------------------------------------------------------------------------- /contrib/jsmin.py: -------------------------------------------------------------------------------- 1 | import os, os.path, shutil 2 | 3 | # This code is original from jsmin by Douglas Crockford, it was translated to 4 | # Python by Baruch Even, edited by M. Jackson Wilkinson. The original code had 5 | # the following copyright and license. 6 | # 7 | # /* jsmin.c 8 | # 2007-05-22 9 | # 10 | # Copyright (c) 2002 Douglas Crockford (www.crockford.com) 11 | # 12 | # Permission is hereby granted, free of charge, to any person obtaining a copy of 13 | # this software and associated documentation files (the "Software"), to deal in 14 | # the Software without restriction, including without limitation the rights to 15 | # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 16 | # of the Software, and to permit persons to whom the Software is furnished to do 17 | # so, subject to the following conditions: 18 | # 19 | # The above copyright notice and this permission notice shall be included in all 20 | # copies or substantial portions of the Software. 21 | # 22 | # The Software shall be used for Good, not Evil. 23 | # 24 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 29 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 | # SOFTWARE. 31 | # */ 32 | 33 | from StringIO import StringIO 34 | 35 | 36 | def jsmin(js): 37 | ins = StringIO(js) 38 | outs = StringIO() 39 | JavascriptMinify().minify(ins, outs) 40 | str = outs.getvalue() 41 | if len(str) > 0 and str[0] == '\n': 42 | str = str[1:] 43 | return str 44 | 45 | 46 | def isAlphanum(c): 47 | """return true if the character is a letter, digit, underscore, 48 | dollar sign, or non-ASCII character. 49 | """ 50 | return ((c >= 'a' and c <= 'z') or (c >= '0' and c <= '9') or 51 | (c >= 'A' and c <= 'Z') or c == '_' or c == '$' or c == '\\' or (c is not None and ord(c) > 126)); 52 | 53 | 54 | class UnterminatedComment(Exception): 55 | pass 56 | 57 | 58 | class UnterminatedStringLiteral(Exception): 59 | pass 60 | 61 | 62 | class UnterminatedRegularExpression(Exception): 63 | pass 64 | 65 | 66 | class JavascriptMinify(object): 67 | 68 | def _outA(self): 69 | self.outstream.write(self.theA) 70 | def _outB(self): 71 | self.outstream.write(self.theB) 72 | 73 | def _get(self): 74 | """return the next character from stdin. Watch out for lookahead. If 75 | the character is a control character, translate it to a space or 76 | linefeed. 77 | """ 78 | c = self.theLookahead 79 | self.theLookahead = None 80 | if c == None: 81 | c = self.instream.read(1) 82 | if c >= ' ' or c == '\n': 83 | return c 84 | if c == '': # EOF 85 | return '\000' 86 | if c == '\r': 87 | return '\n' 88 | return ' ' 89 | 90 | def _peek(self): 91 | self.theLookahead = self._get() 92 | return self.theLookahead 93 | 94 | def _next(self): 95 | """get the next character, excluding comments. peek() is used to see 96 | if an unescaped '/' is followed by a '/' or '*'. 97 | """ 98 | c = self._get() 99 | if c == '/' and self.theA != '\\': 100 | p = self._peek() 101 | if p == '/': 102 | c = self._get() 103 | while c > '\n': 104 | c = self._get() 105 | return c 106 | if p == '*': 107 | c = self._get() 108 | while 1: 109 | c = self._get() 110 | if c == '*': 111 | if self._peek() == '/': 112 | self._get() 113 | return ' ' 114 | if c == '\000': 115 | raise UnterminatedComment() 116 | 117 | return c 118 | 119 | def _action(self, action): 120 | """do something! What you do is determined by the argument: 121 | 1 Output A. Copy B to A. Get the next B. 122 | 2 Copy B to A. Get the next B. (Delete A). 123 | 3 Get the next B. (Delete B). 124 | action treats a string as a single character. Wow! 125 | action recognizes a regular expression if it is preceded by ( or , or =. 126 | """ 127 | if action <= 1: 128 | self._outA() 129 | 130 | if action <= 2: 131 | self.theA = self.theB 132 | if self.theA == "'" or self.theA == '"': 133 | while 1: 134 | self._outA() 135 | self.theA = self._get() 136 | if self.theA == self.theB: 137 | break 138 | if self.theA <= '\n': 139 | raise UnterminatedStringLiteral() 140 | if self.theA == '\\': 141 | self._outA() 142 | self.theA = self._get() 143 | 144 | if action <= 3: 145 | self.theB = self._next() 146 | if self.theB == '/' and (self.theA == '(' or self.theA == ',' or 147 | self.theA == '=' or self.theA == ':' or 148 | self.theA == '[' or self.theA == '?' or 149 | self.theA == '!' or self.theA == '&' or 150 | self.theA == '|' or self.theA == ';' or 151 | self.theA == '{' or self.theA == '}' or 152 | self.theA == '\n'): 153 | self._outA() 154 | self._outB() 155 | while 1: 156 | self.theA = self._get() 157 | if self.theA == '/': 158 | break 159 | elif self.theA == '\\': 160 | self._outA() 161 | self.theA = self._get() 162 | elif self.theA <= '\n': 163 | raise UnterminatedRegularExpression() 164 | self._outA() 165 | self.theB = self._next() 166 | 167 | def _jsmin(self): 168 | """Copy the input to the output, deleting the characters which are 169 | insignificant to JavaScript. Comments will be removed. Tabs will be 170 | replaced with spaces. Carriage returns will be replaced with linefeeds. 171 | Most spaces and linefeeds will be removed. 172 | """ 173 | self.theA = '\n' 174 | self._action(3) 175 | 176 | while self.theA != '\000': 177 | if self.theA == ' ': 178 | if isAlphanum(self.theB): 179 | self._action(1) 180 | else: 181 | self._action(2) 182 | elif self.theA == '\n': 183 | if self.theB in ['{', '[', '(', '+', '-']: 184 | self._action(1) 185 | elif self.theB == ' ': 186 | self._action(3) 187 | else: 188 | if isAlphanum(self.theB): 189 | self._action(1) 190 | else: 191 | self._action(2) 192 | else: 193 | if self.theB == ' ': 194 | if isAlphanum(self.theA): 195 | self._action(1) 196 | else: 197 | self._action(3) 198 | elif self.theB == '\n': 199 | if self.theA in ['}', ']', ')', '+', '-', '"', '\'']: 200 | self._action(1) 201 | else: 202 | if isAlphanum(self.theA): 203 | self._action(1) 204 | else: 205 | self._action(3) 206 | else: 207 | self._action(1) 208 | 209 | def minify(self, instream, outstream): 210 | self.instream = instream 211 | self.outstream = outstream 212 | self.theA = '\n' 213 | self.theB = None 214 | self.theLookahead = None 215 | 216 | self._jsmin() 217 | self.instream.close() 218 | 219 | 220 | def compress_files(in_files, out_file, in_type='js', verbose=False, temp_file='.temp'): 221 | temp = open(temp_file, 'w') 222 | for f in in_files: 223 | fh = open(f) 224 | data = fh.read() + '\n' 225 | fh.close() 226 | 227 | temp.write(data) 228 | 229 | print ' + %s' % f 230 | temp.close() 231 | 232 | out = open(out_file, 'w') 233 | 234 | jsm = JavascriptMinify() 235 | jsm.minify(open(temp_file, 'r'), out) 236 | 237 | out.close() 238 | 239 | org_size = os.path.getsize(temp_file) 240 | new_size = os.path.getsize(out_file) 241 | 242 | print '=> %s' % out_file 243 | print 'Original: %.2f kB' % (org_size / 1024.0) 244 | print 'Compressed: %.2f kB' % (new_size / 1024.0) 245 | print 'Reduction: %.1f%%' % (float(org_size - new_size) / org_size * 100) 246 | print '' 247 | 248 | os.remove(temp_file) 249 | 250 | -------------------------------------------------------------------------------- /themes/official/config.rb: -------------------------------------------------------------------------------- 1 | # Require any additional compass plugins here. 2 | 3 | # Set this to the root of your project when deployed: 4 | http_path = "/" 5 | css_dir = "stylesheets" 6 | sass_dir = "sass" 7 | images_dir = "img" 8 | javascripts_dir = "js" 9 | 10 | # You can select your preferred output style here (can be overridden via the command line): 11 | # output_style = :expanded or :nested or :compact or :compressed 12 | 13 | # To enable relative paths to assets via compass helper functions. Uncomment: 14 | # relative_assets = true 15 | 16 | # To disable debugging comments that display the original location of your selectors. Uncomment: 17 | # line_comments = false 18 | 19 | 20 | # If you prefer the indented syntax, you might want to regenerate this 21 | # project again passing --syntax sass, or you can uncomment this: 22 | # preferred_syntax = :sass 23 | # and then run: 24 | # sass-convert -R --from scss --to sass sass scss && rm -rf sass && mv scss sass 25 | -------------------------------------------------------------------------------- /themes/official/file-hashes.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "hash": "f7314be575aff23ee025af9aea5ca8f0", 4 | "modified": "2013-01-22T21:46:56", 5 | "filename": "js/01-modernizr-2.6.2.min.js" 6 | }, 7 | { 8 | "hash": "e5f0f443252cf2905f18e131fd04fc81", 9 | "modified": "2013-01-22T21:50:47", 10 | "filename": "js/02-jquery-1.9.0.min.js" 11 | }, 12 | { 13 | "hash": "a4365e63a1dc1501c9f17dc64bbc93bb", 14 | "modified": "2013-02-19T09:10:15", 15 | "filename": "js/03-swig.min.js" 16 | }, 17 | { 18 | "hash": "294089339b3dab630ece6ebcc6d2b483", 19 | "modified": "2013-04-30T07:41:29", 20 | "filename": "js/04-bluebutton-0.0.10.js" 21 | }, 22 | { 23 | "hash": "07b238cf4cfe33037c6c46d7958964ef", 24 | "modified": "2013-05-01T12:56:25", 25 | "filename": "js/05-bbclear.js" 26 | }, 27 | { 28 | "hash": "3f499e09d570ad694fe54abcb50476be", 29 | "modified": "2013-01-23T10:30:03", 30 | "filename": "stylesheets/normalize.css" 31 | }, 32 | { 33 | "hash": "4583ffae7a2f26754f6b3d0f10655e8b", 34 | "modified": "2013-01-23T10:03:18", 35 | "filename": "stylesheets/print.css" 36 | }, 37 | { 38 | "hash": "d64f5addad4d1a76ac6f1e7a3ab50f78", 39 | "modified": "2013-04-06T21:28:01", 40 | "filename": "stylesheets/screen.css" 41 | }, 42 | { 43 | "hash": "39ebc61734e1e121d10d939d0d930d2a", 44 | "modified": "2013-04-10T23:11:40", 45 | "filename": "template.html" 46 | } 47 | ] -------------------------------------------------------------------------------- /themes/official/js/01-modernizr-2.6.2.min.js: -------------------------------------------------------------------------------- 1 | /* Modernizr 2.6.2 (Custom Build) | MIT & BSD - Build: http://modernizr.com/download/#-fontface-backgroundsize-borderimage-borderradius-boxshadow-flexbox-hsla-multiplebgs-opacity-rgba-textshadow-cssanimations-csscolumns-generatedcontent-cssgradients-cssreflections-csstransforms-csstransforms3d-csstransitions-applicationcache-canvas-canvastext-draganddrop-hashchange-history-audio-video-indexeddb-input-inputtypes-localstorage-postmessage-sessionstorage-websockets-websqldatabase-webworkers-geolocation-inlinesvg-smil-svg-svgclippaths-touch-webgl-shiv-mq-cssclasses-addtest-prefixed-teststyles-testprop-testallprops-hasevent-prefixes-domprefixes-load */;window.Modernizr=function(a,b,c){function D(a){j.cssText=a}function E(a,b){return D(n.join(a+";")+(b||""))}function F(a,b){return typeof a===b}function G(a,b){return!!~(""+a).indexOf(b)}function H(a,b){for(var d in a){var e=a[d];if(!G(e,"-")&&j[e]!==c)return b=="pfx"?e:!0}return!1}function I(a,b,d){for(var e in a){var f=b[a[e]];if(f!==c)return d===!1?a[e]:F(f,"function")?f.bind(d||b):f}return!1}function J(a,b,c){var d=a.charAt(0).toUpperCase()+a.slice(1),e=(a+" "+p.join(d+" ")+d).split(" ");return F(b,"string")||F(b,"undefined")?H(e,b):(e=(a+" "+q.join(d+" ")+d).split(" "),I(e,b,c))}function K(){e.input=function(c){for(var d=0,e=c.length;d',a,""].join(""),l.id=h,(m?l:n).innerHTML+=f,n.appendChild(l),m||(n.style.background="",n.style.overflow="hidden",k=g.style.overflow,g.style.overflow="hidden",g.appendChild(n)),i=c(l,a),m?l.parentNode.removeChild(l):(n.parentNode.removeChild(n),g.style.overflow=k),!!i},z=function(b){var c=a.matchMedia||a.msMatchMedia;if(c)return c(b).matches;var d;return y("@media "+b+" { #"+h+" { position: absolute; } }",function(b){d=(a.getComputedStyle?getComputedStyle(b,null):b.currentStyle)["position"]=="absolute"}),d},A=function(){function d(d,e){e=e||b.createElement(a[d]||"div"),d="on"+d;var f=d in e;return f||(e.setAttribute||(e=b.createElement("div")),e.setAttribute&&e.removeAttribute&&(e.setAttribute(d,""),f=F(e[d],"function"),F(e[d],"undefined")||(e[d]=c),e.removeAttribute(d))),e=null,f}var a={select:"input",change:"input",submit:"form",reset:"form",error:"img",load:"img",abort:"img"};return d}(),B={}.hasOwnProperty,C;!F(B,"undefined")&&!F(B.call,"undefined")?C=function(a,b){return B.call(a,b)}:C=function(a,b){return b in a&&F(a.constructor.prototype[b],"undefined")},Function.prototype.bind||(Function.prototype.bind=function(b){var c=this;if(typeof c!="function")throw new TypeError;var d=w.call(arguments,1),e=function(){if(this instanceof e){var a=function(){};a.prototype=c.prototype;var f=new a,g=c.apply(f,d.concat(w.call(arguments)));return Object(g)===g?g:f}return c.apply(b,d.concat(w.call(arguments)))};return e}),s.flexbox=function(){return J("flexWrap")},s.canvas=function(){var a=b.createElement("canvas");return!!a.getContext&&!!a.getContext("2d")},s.canvastext=function(){return!!e.canvas&&!!F(b.createElement("canvas").getContext("2d").fillText,"function")},s.webgl=function(){return!!a.WebGLRenderingContext},s.touch=function(){var c;return"ontouchstart"in a||a.DocumentTouch&&b instanceof DocumentTouch?c=!0:y(["@media (",n.join("touch-enabled),("),h,")","{#modernizr{top:9px;position:absolute}}"].join(""),function(a){c=a.offsetTop===9}),c},s.geolocation=function(){return"geolocation"in navigator},s.postmessage=function(){return!!a.postMessage},s.websqldatabase=function(){return!!a.openDatabase},s.indexedDB=function(){return!!J("indexedDB",a)},s.hashchange=function(){return A("hashchange",a)&&(b.documentMode===c||b.documentMode>7)},s.history=function(){return!!a.history&&!!history.pushState},s.draganddrop=function(){var a=b.createElement("div");return"draggable"in a||"ondragstart"in a&&"ondrop"in a},s.websockets=function(){return"WebSocket"in a||"MozWebSocket"in a},s.rgba=function(){return D("background-color:rgba(150,255,150,.5)"),G(j.backgroundColor,"rgba")},s.hsla=function(){return D("background-color:hsla(120,40%,100%,.5)"),G(j.backgroundColor,"rgba")||G(j.backgroundColor,"hsla")},s.multiplebgs=function(){return D("background:url(https://),url(https://),red url(https://)"),/(url\s*\(.*?){3}/.test(j.background)},s.backgroundsize=function(){return J("backgroundSize")},s.borderimage=function(){return J("borderImage")},s.borderradius=function(){return J("borderRadius")},s.boxshadow=function(){return J("boxShadow")},s.textshadow=function(){return b.createElement("div").style.textShadow===""},s.opacity=function(){return E("opacity:.55"),/^0.55$/.test(j.opacity)},s.cssanimations=function(){return J("animationName")},s.csscolumns=function(){return J("columnCount")},s.cssgradients=function(){var a="background-image:",b="gradient(linear,left top,right bottom,from(#9f9),to(white));",c="linear-gradient(left top,#9f9, white);";return D((a+"-webkit- ".split(" ").join(b+a)+n.join(c+a)).slice(0,-a.length)),G(j.backgroundImage,"gradient")},s.cssreflections=function(){return J("boxReflect")},s.csstransforms=function(){return!!J("transform")},s.csstransforms3d=function(){var a=!!J("perspective");return a&&"webkitPerspective"in g.style&&y("@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}",function(b,c){a=b.offsetLeft===9&&b.offsetHeight===3}),a},s.csstransitions=function(){return J("transition")},s.fontface=function(){var a;return y('@font-face {font-family:"font";src:url("https://")}',function(c,d){var e=b.getElementById("smodernizr"),f=e.sheet||e.styleSheet,g=f?f.cssRules&&f.cssRules[0]?f.cssRules[0].cssText:f.cssText||"":"";a=/src/i.test(g)&&g.indexOf(d.split(" ")[0])===0}),a},s.generatedcontent=function(){var a;return y(["#",h,"{font:0/0 a}#",h,':after{content:"',l,'";visibility:hidden;font:3px/1 a}'].join(""),function(b){a=b.offsetHeight>=3}),a},s.video=function(){var a=b.createElement("video"),c=!1;try{if(c=!!a.canPlayType)c=new Boolean(c),c.ogg=a.canPlayType('video/ogg; codecs="theora"').replace(/^no$/,""),c.h264=a.canPlayType('video/mp4; codecs="avc1.42E01E"').replace(/^no$/,""),c.webm=a.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/^no$/,"")}catch(d){}return c},s.audio=function(){var a=b.createElement("audio"),c=!1;try{if(c=!!a.canPlayType)c=new Boolean(c),c.ogg=a.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,""),c.mp3=a.canPlayType("audio/mpeg;").replace(/^no$/,""),c.wav=a.canPlayType('audio/wav; codecs="1"').replace(/^no$/,""),c.m4a=(a.canPlayType("audio/x-m4a;")||a.canPlayType("audio/aac;")).replace(/^no$/,"")}catch(d){}return c},s.localstorage=function(){try{return localStorage.setItem(h,h),localStorage.removeItem(h),!0}catch(a){return!1}},s.sessionstorage=function(){try{return sessionStorage.setItem(h,h),sessionStorage.removeItem(h),!0}catch(a){return!1}},s.webworkers=function(){return!!a.Worker},s.applicationcache=function(){return!!a.applicationCache},s.svg=function(){return!!b.createElementNS&&!!b.createElementNS(r.svg,"svg").createSVGRect},s.inlinesvg=function(){var a=b.createElement("div");return a.innerHTML="",(a.firstChild&&a.firstChild.namespaceURI)==r.svg},s.smil=function(){return!!b.createElementNS&&/SVGAnimate/.test(m.call(b.createElementNS(r.svg,"animate")))},s.svgclippaths=function(){return!!b.createElementNS&&/SVGClipPath/.test(m.call(b.createElementNS(r.svg,"clipPath")))};for(var L in s)C(s,L)&&(x=L.toLowerCase(),e[x]=s[L](),v.push((e[x]?"":"no-")+x));return e.input||K(),e.addTest=function(a,b){if(typeof a=="object")for(var d in a)C(a,d)&&e.addTest(d,a[d]);else{a=a.toLowerCase();if(e[a]!==c)return e;b=typeof b=="function"?b():b,typeof f!="undefined"&&f&&(g.className+=" "+(b?"":"no-")+a),e[a]=b}return e},D(""),i=k=null,function(a,b){function k(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x",d.insertBefore(c.lastChild,d.firstChild)}function l(){var a=r.elements;return typeof a=="string"?a.split(" "):a}function m(a){var b=i[a[g]];return b||(b={},h++,a[g]=h,i[h]=b),b}function n(a,c,f){c||(c=b);if(j)return c.createElement(a);f||(f=m(c));var g;return f.cache[a]?g=f.cache[a].cloneNode():e.test(a)?g=(f.cache[a]=f.createElem(a)).cloneNode():g=f.createElem(a),g.canHaveChildren&&!d.test(a)?f.frag.appendChild(g):g}function o(a,c){a||(a=b);if(j)return a.createDocumentFragment();c=c||m(a);var d=c.frag.cloneNode(),e=0,f=l(),g=f.length;for(;e",f="hidden"in a,j=a.childNodes.length==1||function(){b.createElement("a");var a=b.createDocumentFragment();return typeof a.cloneNode=="undefined"||typeof a.createDocumentFragment=="undefined"||typeof a.createElement=="undefined"}()}catch(c){f=!0,j=!0}})();var r={elements:c.elements||"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video",shivCSS:c.shivCSS!==!1,supportsUnknownElements:j,shivMethods:c.shivMethods!==!1,type:"default",shivDocument:q,createElement:n,createDocumentFragment:o};a.html5=r,q(b)}(this,b),e._version=d,e._prefixes=n,e._domPrefixes=q,e._cssomPrefixes=p,e.mq=z,e.hasEvent=A,e.testProp=function(a){return H([a])},e.testAllProps=J,e.testStyles=y,e.prefixed=function(a,b,c){return b?J(a,b,c):J(a,"pfx")},g.className=g.className.replace(/(^|\s)no-js(\s|$)/,"$1$2")+(f?" js "+v.join(" "):""),e}(this,this.document),function(a,b,c){function d(a){return"[object Function]"==o.call(a)}function e(a){return"string"==typeof a}function f(){}function g(a){return!a||"loaded"==a||"complete"==a||"uninitialized"==a}function h(){var a=p.shift();q=1,a?a.t?m(function(){("c"==a.t?B.injectCss:B.injectJs)(a.s,0,a.a,a.x,a.e,1)},0):(a(),h()):q=0}function i(a,c,d,e,f,i,j){function k(b){if(!o&&g(l.readyState)&&(u.r=o=1,!q&&h(),l.onload=l.onreadystatechange=null,b)){"img"!=a&&m(function(){t.removeChild(l)},50);for(var d in y[c])y[c].hasOwnProperty(d)&&y[c][d].onload()}}var j=j||B.errorTimeout,l=b.createElement(a),o=0,r=0,u={t:d,s:c,e:f,a:i,x:j};1===y[c]&&(r=1,y[c]=[]),"object"==a?l.data=c:(l.src=c,l.type=a),l.width=l.height="0",l.onerror=l.onload=l.onreadystatechange=function(){k.call(this,r)},p.splice(e,0,u),"img"!=a&&(r||2===y[c]?(t.insertBefore(l,s?null:n),m(k,j)):y[c].push(l))}function j(a,b,c,d,f){return q=0,b=b||"j",e(a)?i("c"==b?v:u,a,b,this.i++,c,d,f):(p.splice(this.i++,0,a),1==p.length&&h()),this}function k(){var a=B;return a.loader={load:j,i:0},a}var l=b.documentElement,m=a.setTimeout,n=b.getElementsByTagName("script")[0],o={}.toString,p=[],q=0,r="MozAppearance"in l.style,s=r&&!!b.createRange().compareNode,t=s?l:n.parentNode,l=a.opera&&"[object Opera]"==o.call(a.opera),l=!!b.attachEvent&&!l,u=r?"object":l?"script":"img",v=l?"script":u,w=Array.isArray||function(a){return"[object Array]"==o.call(a)},x=[],y={},z={timeout:function(a,b){return b.length&&(a.timeout=b[0]),a}},A,B;B=function(a){function b(a){var a=a.split("!"),b=x.length,c=a.pop(),d=a.length,c={url:c,origUrl:c,prefixes:a},e,f,g;for(f=0;flastLastIndex){output.push(str.slice(lastLastIndex,match.index));if(!splitter._compliantExecNpcg&&match.length>1){match[0].replace(separator2,fixExec)}if(match.length>1&&match.index=limit){break}}if(separator.lastIndex===match.index){separator.lastIndex+=1}match=separator.exec(str)}if(lastLastIndex===str.length){if(lastLength||!separator.test("")){output.push("")}}else{output.push(str.slice(lastLastIndex))}return output.length>limit?output.slice(0,limit):output};splitter._compliantExecNpcg=/()??/.exec("")[1]===undefined;splitter._nativeSplit=String.prototype.split;String.prototype.split=function(separator,limit){return splitter(this,separator,limit)}}})();swig=function(){var swig={},dateformat={},filters={},helpers={},parser={},tags={};(function(){var root=this;var previousUnderscore=root._;var breaker={};var ArrayProto=Array.prototype,ObjProto=Object.prototype,FuncProto=Function.prototype;var push=ArrayProto.push,slice=ArrayProto.slice,concat=ArrayProto.concat,toString=ObjProto.toString,hasOwnProperty=ObjProto.hasOwnProperty;var nativeForEach=ArrayProto.forEach,nativeMap=ArrayProto.map,nativeReduce=ArrayProto.reduce,nativeReduceRight=ArrayProto.reduceRight,nativeFilter=ArrayProto.filter,nativeEvery=ArrayProto.every,nativeSome=ArrayProto.some,nativeIndexOf=ArrayProto.indexOf,nativeLastIndexOf=ArrayProto.lastIndexOf,nativeIsArray=Array.isArray,nativeKeys=Object.keys,nativeBind=FuncProto.bind;var _=function(obj){if(obj instanceof _)return obj;if(!(this instanceof _))return new _(obj);this._wrapped=obj};if(typeof exports!=="undefined"){if(typeof module!=="undefined"&&module.exports){exports=module.exports=_}exports._=_}else{root._=_}_.VERSION="1.4.3";var each=_.each=_.forEach=function(obj,iterator,context){if(obj==null)return;if(nativeForEach&&obj.forEach===nativeForEach){obj.forEach(iterator,context)}else if(obj.length===+obj.length){for(var i=0,l=obj.length;i2;if(obj==null)obj=[];if(nativeReduce&&obj.reduce===nativeReduce){if(context)iterator=_.bind(iterator,context);return initial?obj.reduce(iterator,memo):obj.reduce(iterator)}each(obj,function(value,index,list){if(!initial){memo=value;initial=true}else{memo=iterator.call(context,memo,value,index,list)}});if(!initial)throw new TypeError(reduceError);return memo};_.reduceRight=_.foldr=function(obj,iterator,memo,context){var initial=arguments.length>2;if(obj==null)obj=[];if(nativeReduceRight&&obj.reduceRight===nativeReduceRight){if(context)iterator=_.bind(iterator,context);return initial?obj.reduceRight(iterator,memo):obj.reduceRight(iterator)}var length=obj.length;if(length!==+length){var keys=_.keys(obj);length=keys.length}each(obj,function(value,index,list){index=keys?keys[--length]:--length;if(!initial){memo=obj[index];initial=true}else{memo=iterator.call(context,memo,obj[index],index,list)}});if(!initial)throw new TypeError(reduceError);return memo};_.find=_.detect=function(obj,iterator,context){var result;any(obj,function(value,index,list){if(iterator.call(context,value,index,list)){result=value;return true}});return result};_.filter=_.select=function(obj,iterator,context){var results=[];if(obj==null)return results;if(nativeFilter&&obj.filter===nativeFilter)return obj.filter(iterator,context);each(obj,function(value,index,list){if(iterator.call(context,value,index,list))results[results.length]=value});return results};_.reject=function(obj,iterator,context){return _.filter(obj,function(value,index,list){return!iterator.call(context,value,index,list)},context)};_.every=_.all=function(obj,iterator,context){iterator||(iterator=_.identity);var result=true;if(obj==null)return result;if(nativeEvery&&obj.every===nativeEvery)return obj.every(iterator,context);each(obj,function(value,index,list){if(!(result=result&&iterator.call(context,value,index,list)))return breaker});return!!result};var any=_.some=_.any=function(obj,iterator,context){iterator||(iterator=_.identity);var result=false;if(obj==null)return result;if(nativeSome&&obj.some===nativeSome)return obj.some(iterator,context);each(obj,function(value,index,list){if(result||(result=iterator.call(context,value,index,list)))return breaker});return!!result};_.contains=_.include=function(obj,target){if(obj==null)return false;if(nativeIndexOf&&obj.indexOf===nativeIndexOf)return obj.indexOf(target)!=-1;return any(obj,function(value){return value===target})};_.invoke=function(obj,method){var args=slice.call(arguments,2);return _.map(obj,function(value){return(_.isFunction(method)?method:value[method]).apply(value,args)})};_.pluck=function(obj,key){return _.map(obj,function(value){return value[key]})};_.where=function(obj,attrs){if(_.isEmpty(attrs))return[];return _.filter(obj,function(value){for(var key in attrs){if(attrs[key]!==value[key])return false}return true})};_.max=function(obj,iterator,context){if(!iterator&&_.isArray(obj)&&obj[0]===+obj[0]&&obj.length<65535){return Math.max.apply(Math,obj)}if(!iterator&&_.isEmpty(obj))return-Infinity;var result={computed:-Infinity,value:-Infinity};each(obj,function(value,index,list){var computed=iterator?iterator.call(context,value,index,list):value;computed>=result.computed&&(result={value:value,computed:computed})});return result.value};_.min=function(obj,iterator,context){if(!iterator&&_.isArray(obj)&&obj[0]===+obj[0]&&obj.length<65535){return Math.min.apply(Math,obj)}if(!iterator&&_.isEmpty(obj))return Infinity;var result={computed:Infinity,value:Infinity};each(obj,function(value,index,list){var computed=iterator?iterator.call(context,value,index,list):value;computedb||a===void 0)return 1;if(a>>1;iterator.call(context,array[mid])=0})})};_.difference=function(array){var rest=concat.apply(ArrayProto,slice.call(arguments,1));return _.filter(array,function(value){return!_.contains(rest,value)})};_.zip=function(){var args=slice.call(arguments);var length=_.max(_.pluck(args,"length"));var results=new Array(length);for(var i=0;i=0;i--){args=[funcs[i].apply(this,args)]}return args[0]}};_.after=function(times,func){if(times<=0)return func();return function(){if(--times<1){return func.apply(this,arguments)}}};_.keys=nativeKeys||function(obj){if(obj!==Object(obj))throw new TypeError("Invalid object");var keys=[];for(var key in obj)if(_.has(obj,key))keys[keys.length]=key;return keys};_.values=function(obj){var values=[];for(var key in obj)if(_.has(obj,key))values.push(obj[key]);return values};_.pairs=function(obj){var pairs=[];for(var key in obj)if(_.has(obj,key))pairs.push([key,obj[key]]);return pairs};_.invert=function(obj){var result={};for(var key in obj)if(_.has(obj,key))result[obj[key]]=key;return result};_.functions=_.methods=function(obj){var names=[];for(var key in obj){if(_.isFunction(obj[key]))names.push(key)}return names.sort()};_.extend=function(obj){each(slice.call(arguments,1),function(source){if(source){for(var prop in source){obj[prop]=source[prop]}}});return obj};_.pick=function(obj){var copy={};var keys=concat.apply(ArrayProto,slice.call(arguments,1));each(keys,function(key){if(key in obj)copy[key]=obj[key]});return copy};_.omit=function(obj){var copy={};var keys=concat.apply(ArrayProto,slice.call(arguments,1));for(var key in obj){if(!_.contains(keys,key))copy[key]=obj[key]}return copy};_.defaults=function(obj){each(slice.call(arguments,1),function(source){if(source){for(var prop in source){if(obj[prop]==null)obj[prop]=source[prop]}}});return obj};_.clone=function(obj){if(!_.isObject(obj))return obj;return _.isArray(obj)?obj.slice():_.extend({},obj)};_.tap=function(obj,interceptor){interceptor(obj);return obj};var eq=function(a,b,aStack,bStack){if(a===b)return a!==0||1/a==1/b;if(a==null||b==null)return a===b;if(a instanceof _)a=a._wrapped;if(b instanceof _)b=b._wrapped;var className=toString.call(a);if(className!=toString.call(b))return false;switch(className){case"[object String]":return a==String(b);case"[object Number]":return a!=+a?b!=+b:a==0?1/a==1/b:a==+b;case"[object Date]":case"[object Boolean]":return+a==+b;case"[object RegExp]":return a.source==b.source&&a.global==b.global&&a.multiline==b.multiline&&a.ignoreCase==b.ignoreCase}if(typeof a!="object"||typeof b!="object")return false;var length=aStack.length;while(length--){if(aStack[length]==a)return bStack[length]==b}aStack.push(a);bStack.push(b);var size=0,result=true;if(className=="[object Array]"){size=a.length;result=size==b.length;if(result){while(size--){if(!(result=eq(a[size],b[size],aStack,bStack)))break}}}else{var aCtor=a.constructor,bCtor=b.constructor;if(aCtor!==bCtor&&!(_.isFunction(aCtor)&&aCtor instanceof aCtor&&_.isFunction(bCtor)&&bCtor instanceof bCtor)){return false}for(var key in a){if(_.has(a,key)){size++;if(!(result=_.has(b,key)&&eq(a[key],b[key],aStack,bStack)))break}}if(result){for(key in b){if(_.has(b,key)&&!size--)break}result=!size}}aStack.pop();bStack.pop();return result};_.isEqual=function(a,b){return eq(a,b,[],[])};_.isEmpty=function(obj){if(obj==null)return true;if(_.isArray(obj)||_.isString(obj))return obj.length===0;for(var key in obj)if(_.has(obj,key))return false;return true};_.isElement=function(obj){return!!(obj&&obj.nodeType===1)};_.isArray=nativeIsArray||function(obj){return toString.call(obj)=="[object Array]"};_.isObject=function(obj){return obj===Object(obj)};each(["Arguments","Function","String","Number","Date","RegExp"],function(name){_["is"+name]=function(obj){return toString.call(obj)=="[object "+name+"]"}});if(!_.isArguments(arguments)){_.isArguments=function(obj){return!!(obj&&_.has(obj,"callee"))}}if(typeof/./!=="function"){_.isFunction=function(obj){return typeof obj==="function"}}_.isFinite=function(obj){return isFinite(obj)&&!isNaN(parseFloat(obj))};_.isNaN=function(obj){return _.isNumber(obj)&&obj!=+obj};_.isBoolean=function(obj){return obj===true||obj===false||toString.call(obj)=="[object Boolean]"};_.isNull=function(obj){return obj===null};_.isUndefined=function(obj){return obj===void 0};_.has=function(obj,key){return hasOwnProperty.call(obj,key)};_.noConflict=function(){root._=previousUnderscore;return this};_.identity=function(value){return value};_.times=function(n,iterator,context){var accum=Array(n);for(var i=0;i":">",'"':""","'":"'","/":"/"}};entityMap.unescape=_.invert(entityMap.escape);var entityRegexes={escape:new RegExp("["+_.keys(entityMap.escape).join("")+"]","g"),unescape:new RegExp("("+_.keys(entityMap.unescape).join("|")+")","g")};_.each(["escape","unescape"],function(method){_[method]=function(string){if(string==null)return"";return(""+string).replace(entityRegexes[method],function(match){return entityMap[method][match]})}});_.result=function(object,property){if(object==null)return null;var value=object[property];return _.isFunction(value)?value.call(object):value};_.mixin=function(obj){each(_.functions(obj),function(name){var func=_[name]=obj[name];_.prototype[name]=function(){var args=[this._wrapped];push.apply(args,arguments);return result.call(this,func.apply(_,args))}})};var idCounter=0;_.uniqueId=function(prefix){var id=""+ ++idCounter;return prefix?prefix+id:id};_.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var noMatch=/(.)^/;var escapes={"'":"'","\\":"\\","\r":"r","\n":"n"," ":"t","\u2028":"u2028","\u2029":"u2029"};var escaper=/\\|'|\r|\n|\t|\u2028|\u2029/g;_.template=function(text,data,settings){settings=_.defaults({},settings,_.templateSettings);var matcher=new RegExp([(settings.escape||noMatch).source,(settings.interpolate||noMatch).source,(settings.evaluate||noMatch).source].join("|")+"|$","g");var index=0;var source="__p+='";text.replace(matcher,function(match,escape,interpolate,evaluate,offset){source+=text.slice(index,offset).replace(escaper,function(match){return"\\"+escapes[match]});if(escape){source+="'+\n((__t=("+escape+"))==null?'':_.escape(__t))+\n'"}if(interpolate){source+="'+\n((__t=("+interpolate+"))==null?'':__t)+\n'"}if(evaluate){source+="';\n"+evaluate+"\n__p+='"}index=offset+match.length;return match});source+="';\n";if(!settings.variable)source="with(obj||{}){\n"+source+"}\n";source="var __t,__p='',__j=Array.prototype.join,"+"print=function(){__p+=__j.call(arguments,'');};\n"+source+"return __p;\n";try{var render=new Function(settings.variable||"obj","_",source)}catch(e){e.source=source;throw e}if(data)return render(data,_);var template=function(data){return render.call(this,data,_)};template.source="function("+(settings.variable||"obj")+"){\n"+source+"}";return template};_.chain=function(obj){return _(obj).chain()};var result=function(obj){return this._chain?_(obj).chain():obj};_.mixin(_);each(["pop","push","reverse","shift","sort","splice","unshift"],function(name){var method=ArrayProto[name];_.prototype[name]=function(){var obj=this._wrapped;method.apply(obj,arguments);if((name=="shift"||name=="splice")&&obj.length===0)delete obj[0];return result.call(this,obj)}});each(["concat","join","slice"],function(name){var method=ArrayProto[name];_.prototype[name]=function(){return result.call(this,method.apply(this._wrapped,arguments))}});_.extend(_.prototype,{chain:function(){this._chain=true;return this},value:function(){return this._wrapped}})}).call(this);(function(exports){var config={allowErrors:false,autoescape:true,cache:true,encoding:"utf8",filters:filters,root:"/",tags:tags,extensions:{},tzOffset:0},_config=_.extend({},config),CACHE={};exports.init=function(options){CACHE={};_config=_.extend({},config,options);_config.filters=_.extend(filters,options.filters);_config.tags=_.extend(tags,options.tags);dateformat.defaultTZOffset=_config.tzOffset};function TemplateError(error){return{render:function(){return"
"+error.stack+"
"}}}function createRenderFunc(code){return new Function("_context","_parents","_filters","_","_ext",["_parents = _parents ? _parents.slice() : [];","_context = _context || {};","var j = _parents.length,",' _output = "",'," _this = this;","while (j--) {"," if (_parents[j] === this.id) {",' return "Circular import of template " + this.id + " in " + _parents[_parents.length-1];'," }","}","_parents.push(this.id);",code,"return _output;"].join(""))}function createTemplate(data,id){var template={compileFile:exports.compileFile,blocks:{},type:parser.TEMPLATE,id:id},tokens,code,render;if(_config.allowErrors){tokens=parser.parse.call(template,data,_config.tags,_config.autoescape)}else{try{tokens=parser.parse.call(template,data,_config.tags,_config.autoescape)}catch(e){return new TemplateError(e)}}template.tokens=tokens;code=parser.compile.call(template);if(code!==false){render=createRenderFunc(code)}else{render=function(_context,_parents,_filters,_,_ext){template.tokens=tokens;code=parser.compile.call(template,"",_context);var fn=createRenderFunc(code);return fn.call(this,_context,_parents,_filters,_,_ext)}}template.render=function(context,parents){if(_config.allowErrors){return render.call(this,context,parents,_config.filters,_,_config.extensions)}try{return render.call(this,context,parents,_config.filters,_,_config.extensions)}catch(e){return new TemplateError(e)}};return template}function getTemplate(source,options){var key=options.filename||source;if(_config.cache||options.cache){if(!CACHE.hasOwnProperty(key)){CACHE[key]=createTemplate(source,key)}return CACHE[key]}return createTemplate(source,key)}exports.compileFile=function(filepath,forceAllowErrors){var tpl,get;if(_config.cache&&CACHE.hasOwnProperty(filepath)){return CACHE[filepath]}if(typeof window!=="undefined"){throw new TemplateError({stack:"You must pre-compile all templates in-browser. Use `swig.compile(template);`."})}get=function(){var excp,getSingle,c;getSingle=function(prefix){var file=/^\//.test(filepath)||/^.:/.test(filepath)?filepath:prefix+"/"+filepath,data;try{data=fs.readFileSync(file,config.encoding);tpl=getTemplate(data,{filename:filepath})}catch(e){excp=e}};if(typeof _config.root==="string"){getSingle(_config.root)}if(_config.root instanceof Array){c=0;while(tpl===undefined&&c<_config.root.length){getSingle(_config.root[c]);c=c+1}}if(tpl===undefined){throw excp}};if(_config.allowErrors||forceAllowErrors){get()}else{try{get()}catch(error){tpl=new TemplateError(error)}}return tpl};exports.compile=function(source,options){var tmpl=getTemplate(source,options||{});return function(source,options){return tmpl.render(source,options)}}})(swig);(function(exports){var KEYWORDS=/^(Array|ArrayBuffer|Boolean|Date|Error|eval|EvalError|Function|Infinity|Iterator|JSON|Math|Namespace|NaN|Number|Object|QName|RangeError|ReferenceError|RegExp|StopIteration|String|SyntaxError|TypeError|undefined|uneval|URIError|XML|XMLList|break|case|catch|continue|debugger|default|delete|do|else|finally|for|function|if|in|instanceof|new|return|switch|this|throw|try|typeof|var|void|while|with)(?=(\.|$))/;exports.isStringLiteral=function(string){if(typeof string!=="string"){return false}var first=string.substring(0,1),last=string.charAt(string.length-1,1),teststr;if(first===last&&(first==="'"||first==='"')){teststr=string.substr(1,string.length-2).split("").reverse().join("");if(first==="'"&&/'(?!\\)/.test(teststr)||last==='"'&&/"(?!\\)/.test(teststr)){throw new Error("Invalid string literal. Unescaped quote ("+string[0]+") found.")}return true}return false};exports.isLiteral=function(string){var literal=false;if(/^\d+([.]\d+)?$/.test(string)){literal=true}else if(exports.isStringLiteral(string)){literal=true}return literal};exports.isValidName=function(string){return typeof string==="string"&&string.substr(0,2)!=="__"&&/^([$A-Za-z_]+[$A-Za-z_0-9]*)(\.?([$A-Za-z_]+[$A-Za-z_0-9]*))*$/.test(string)&&!KEYWORDS.test(string)};exports.isValidShortName=function(string){return string.substr(0,2)!=="__"&&/^[$A-Za-z_]+[$A-Za-z_0-9]*$/.test(string)&&!KEYWORDS.test(string)};exports.isValidBlockName=function(string){return/^[A-Za-z]+[A-Za-z_0-9]*$/.test(string)};function stripWhitespace(input){return input.replace(/^\s+|\s+$/g,"")}exports.stripWhitespace=stripWhitespace;function filterVariablePath(props){var filtered=[],literal="",i=0;for(i;i0){_.each(filters,function(filter){switch(filter.name){case"raw":escape=false;return;case"e":case"escape":escape=filter.args||escape;return;default:output=exports.wrapFilter(output,filter,"_filters");break}})}output=output||'""';if(escape){output="_filters.escape.call(this, "+output+", "+escape+")"}return output};exports.setVar=function(varName,argument){var out="",props,output,inArr;if(/\[/.test(argument.name)){props=argument.name.split(/(\[|\])/);output=[];inArr=false;_.each(props,function(prop){if(prop===""){return}if(prop==="["){inArr=true;return}if(prop==="]"){inArr=false;return}if(inArr&&!exports.isStringLiteral(prop)){out+=exports.setVar("___"+prop.replace(/\W/g,"_"),{name:prop,filters:[],escape:true})}})}out+="var "+varName+' = "";\n'+"if ("+check(argument.name,"_context")+") {\n"+" "+varName+" = "+exports.wrapFilters(argument.name,argument.filters,"_context",argument.escape)+";\n"+"} else if ("+check(argument.name)+") {\n"+" "+varName+" = "+exports.wrapFilters(argument.name,argument.filters,null,argument.escape)+";\n"+"}\n";if(argument.filters.length){out+=" else if (true) {\n";out+=" "+varName+" = "+exports.wrapFilters("",argument.filters,null,argument.escape)+";\n";out+="}\n"}return out};exports.parseIfArgs=function(args,parser){var operators=["==","<",">","!=","<=",">=","===","!==","&&","||","in","and","or","mod","%"],errorString="Bad if-syntax in `{% if "+args.join(" ")+" %}...",startParen=/^\(+/,endParen=/\)+$/,tokens=[],prevType,last,closing=0;_.each(args,function(value,index){var endsep=0,startsep=0,operand;if(startParen.test(value)){startsep=value.match(startParen)[0].length;closing+=startsep;value=value.replace(startParen,"");while(startsep){startsep-=1;tokens.push({type:"separator",value:"("})}}if(/^\![^=]/.test(value)||value==="not"){if(value==="not"){value=""}else{value=value.substr(1)}tokens.push({type:"operator",value:"!"})}if(endParen.test(value)&&value.indexOf("(")===-1){if(!closing){throw new Error(errorString)}endsep=value.match(endParen)[0].length;value=value.replace(endParen,"");closing-=endsep}if(value==="in"){last=tokens.pop();prevType="inindex"}else if(_.indexOf(operators,value)!==-1){if(prevType==="operator"){throw new Error(errorString)}value=value.replace("and","&&").replace("or","||").replace("mod","%");tokens.push({value:value});prevType="operator"}else if(value!==""){if(prevType==="value"){throw new Error(errorString)}operand=parser.parseVariable(value);if(prevType==="inindex"){tokens.push({preout:last.preout+exports.setVar("__op"+index,operand),value:"(((_.isArray(__op"+index+") || typeof __op"+index+' === "string") && _.indexOf(__op'+index+", "+last.value+") !== -1) || (typeof __op"+index+' === "object" && '+last.value+" in __op"+index+"))"});last=null}else{tokens.push({preout:exports.setVar("__op"+index,operand),value:"__op"+index})}prevType="value"}while(endsep){endsep-=1;tokens.push({type:"separator",value:")"})}});if(closing>0){throw new Error(errorString)}return tokens}})(helpers);(function(exports){var _months={full:["January","February","March","April","May","June","July","August","September","October","November","December"],abbr:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]},_days={full:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],abbr:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],alt:{"-1":"Yesterday",0:"Today",1:"Tomorrow"}};exports.defaultTZOffset=0;exports.DateZ=function(){var members={"default":["getUTCDate","getUTCDay","getUTCFullYear","getUTCHours","getUTCMilliseconds","getUTCMinutes","getUTCMonth","getUTCSeconds","toISOString","toGMTString","toUTCString","valueOf","getTime"],z:["getDate","getDay","getFullYear","getHours","getMilliseconds","getMinutes","getMonth","getSeconds","getYear","toDateString","toLocaleDateString","toLocaleTimeString"],string:["toLocaleString","toString","toTimeString"],zSet:["setDate","setFullYear","setHours","setMilliseconds","setMinutes","setMonth","setSeconds","setTime","setYear"],set:["setUTCDate","setUTCFullYear","setUTCHours","setUTCMilliseconds","setUTCMinutes","setUTCMonth","setUTCSeconds"],"static":["UTC","parse"]},d=this,i;d.date=d.dateZ=arguments.length>1?new Date(Date.UTC.apply(Date,arguments)+(new Date).getTimezoneOffset()*6e4):arguments.length===1?new Date(new Date(arguments["0"])):new Date;d.timezoneOffset=d.dateZ.getTimezoneOffset();function zeroPad(i){return i<10?"0"+i:i}function _toTZString(){var hours=zeroPad(Math.floor(Math.abs(d.timezoneOffset)/60)),minutes=zeroPad(Math.abs(d.timezoneOffset)-hours*60),prefix=d.timezoneOffset<0?"+":"-",abbr=d.tzAbbreviation===undefined?"":" ("+d.tzAbbreviation+")";return"GMT"+prefix+hours+minutes+abbr}_.each(members.z,function(name){d[name]=function(){return d.dateZ[name]()}});_.each(members.string,function(name){d[name]=function(){return d.dateZ[name].apply(d.dateZ,[]).replace(/GMT[+\-]\\d{4} \\(([a-zA-Z]{3,4})\\)/,_toTZString())}});_.each(members["default"],function(name){d[name]=function(){return d.date[name]()}});_.each(members["static"],function(name){d[name]=function(){return Date[name].apply(Date,arguments)}});_.each(members.zSet,function(name){d[name]=function(){d.dateZ[name].apply(d.dateZ,arguments);d.date=new Date(d.dateZ.getTime()-d.dateZ.getTimezoneOffset()*6e4+d.timezoneOffset*6e4);return d}});_.each(members.set,function(name){d[name]=function(){d.date[name].apply(d.date,arguments);d.dateZ=new Date(d.date.getTime()+d.date.getTimezoneOffset()*6e4-d.timezoneOffset*6e4);return d}});if(exports.defaultTZOffset){this.setTimezoneOffset(exports.defaultTZOffset)}};exports.DateZ.prototype={getTimezoneOffset:function(){return this.timezoneOffset},setTimezoneOffset:function(offset,abbr){this.timezoneOffset=offset;if(abbr){this.tzAbbreviation=abbr}this.dateZ=new Date(this.date.getTime()+this.date.getTimezoneOffset()*6e4-this.timezoneOffset*6e4);return this}};exports.d=function(input){return(input.getDate()<10?"0":"")+input.getDate()};exports.D=function(input){return _days.abbr[input.getDay()]};exports.j=function(input){return input.getDate()};exports.l=function(input){return _days.full[input.getDay()]};exports.N=function(input){var d=input.getDay();return d>=1?d+1:7};exports.S=function(input){var d=input.getDate();return d%10===1&&d!==11?"st":d%10===2&&d!==12?"nd":d%10===3&&d!==13?"rd":"th"};exports.w=function(input){return input.getDay()};exports.z=function(input,offset,abbr){var year=input.getFullYear(),e=new exports.DateZ(year,input.getMonth(),input.getDate(),12,0,0),d=new exports.DateZ(year,0,1,12,0,0);e.setTimezoneOffset(offset,abbr);d.setTimezoneOffset(offset,abbr);return Math.round((e-d)/864e5)};exports.W=function(input){var target=new Date(input.valueOf()),dayNr=(input.getDay()+6)%7,fThurs;target.setDate(target.getDate()-dayNr+3);fThurs=target.valueOf();target.setMonth(0,1);if(target.getDay()!==4){target.setMonth(0,1+(4-target.getDay()+7)%7)}return 1+Math.ceil((fThurs-target)/6048e5)};exports.F=function(input){return _months.full[input.getMonth()]};exports.m=function(input){return(input.getMonth()<9?"0":"")+(input.getMonth()+1)};exports.M=function(input){return _months.abbr[input.getMonth()]};exports.n=function(input){return input.getMonth()+1};exports.t=function(input){return 32-new Date(input.getFullYear(),input.getMonth(),32).getDate()};exports.L=function(input){return new Date(input.getFullYear(),1,29).getDate()===29};exports.o=function(input){var target=new Date(input.valueOf());target.setDate(target.getDate()-(input.getDay()+6)%7+3);return target.getFullYear()};exports.Y=function(input){return input.getFullYear()};exports.y=function(input){return input.getFullYear().toString().substr(2)};exports.a=function(input){return input.getHours()<12?"am":"pm"};exports.A=function(input){return input.getHours()<12?"AM":"PM"};exports.B=function(input){var hours=input.getUTCHours(),beats;hours=hours===23?0:hours+1;beats=Math.abs(((hours*60+input.getUTCMinutes())*60+input.getUTCSeconds())/86.4).toFixed(0);return"000".concat(beats).slice(beats.length)};exports.g=function(input){var h=input.getHours();return h===0?12:h>12?h-12:h};exports.G=function(input){return input.getHours()};exports.h=function(input){var h=input.getHours();return(h<10||12h?"0":"")+(h<12?h:h-12)};exports.H=function(input){var h=input.getHours();return(h<10?"0":"")+h};exports.i=function(input){var m=input.getMinutes();return(m<10?"0":"")+m};exports.s=function(input){var s=input.getSeconds();return(s<10?"0":"")+s};exports.O=function(input){var tz=input.getTimezoneOffset();return(tz<0?"-":"+")+(tz/60<10?"0":"")+Math.abs(tz/60)+"00"};exports.Z=function(input){return input.getTimezoneOffset()*60};exports.c=function(input){return input.toISOString()};exports.r=function(input){return input.toUTCString()};exports.U=function(input){return input.getTime()/1e3}})(dateformat);(function(exports){exports.add=function(input,addend){if(_.isArray(input)&&_.isArray(addend)){return input.concat(addend)}if(typeof input==="object"&&typeof addend==="object"){return _.extend(input,addend)}if(_.isNumber(input)&&_.isNumber(addend)){return input+addend}return input+addend};exports.addslashes=function(input){if(typeof input==="object"){_.each(input,function(value,key){input[key]=exports.addslashes(value)});return input}return input.replace(/\\/g,"\\\\").replace(/\'/g,"\\'").replace(/\"/g,'\\"')};exports.capitalize=function(input){if(typeof input==="object"){_.each(input,function(value,key){input[key]=exports.capitalize(value)});return input}return input.toString().charAt(0).toUpperCase()+input.toString().substr(1).toLowerCase()};exports.date=function(input,format,offset,abbr){var l=format.length,date=new dateformat.DateZ(input),cur,i=0,out="";if(offset){date.setTimezoneOffset(offset,abbr)}for(i;i/g,"\\u003E").replace(/\'/g,"\\u0027").replace(/"/g,"\\u0022").replace(/\=/g,"\\u003D").replace(/-/g,"\\u002D").replace(/;/g,"\\u003B")}return input.replace(/&(?!amp;|lt;|gt;|quot;|#39;)/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'")}return input};exports.first=function(input){if(typeof input==="object"&&!_.isArray(input)){return""}if(typeof input==="string"){return input.substr(0,1)}return _.first(input)};exports.join=function(input,separator){if(_.isArray(input)){return input.join(separator)}if(typeof input==="object"){var out=[];_.each(input,function(value,key){out.push(value)});return out.join(separator)}return input};exports.json_encode=function(input,indent){return JSON.stringify(input,null,indent||0)};exports.last=function(input){if(typeof input==="object"&&!_.isArray(input)){return""}if(typeof input==="string"){return input.charAt(input.length-1)}return _.last(input)};exports.length=function(input){if(typeof input==="object"){return _.keys(input).length}return input.length};exports.lower=function(input){if(typeof input==="object"){_.each(input,function(value,key){input[key]=exports.lower(value)});return input}return input.toString().toLowerCase()};exports.replace=function(input,search,replacement,flags){var r=new RegExp(search,flags);return input.replace(r,replacement)};exports.reverse=function(input){if(_.isArray(input)){return input.reverse()}return input};exports.striptags=function(input){if(typeof input==="object"){_.each(input,function(value,key){input[key]=exports.striptags(value)});return input}return input.toString().replace(/(<([^>]+)>)/gi,"")};exports.title=function(input){if(typeof input==="object"){_.each(input,function(value,key){input[key]=exports.title(value)});return input}return input.toString().replace(/\w\S*/g,function(str){return str.charAt(0).toUpperCase()+str.substr(1).toLowerCase()})};exports.uniq=function(input){return _.uniq(input)};exports.upper=function(input){if(typeof input==="object"){_.each(input,function(value,key){input[key]=exports.upper(value)});return input}return input.toString().toUpperCase()};exports.url_encode=function(input){return encodeURIComponent(input)};exports.url_decode=function(input){return decodeURIComponent(input)}})(filters);(function(exports){var variableRegexp=/^\{\{[^\r]*?\}\}$/,logicRegexp=/^\{%[^\r]*?%\}$/,commentRegexp=/^\{#[^\r]*?#\}$/,TEMPLATE=exports.TEMPLATE=0,LOGIC_TOKEN=1,VAR_TOKEN=2;exports.TOKEN_TYPES={TEMPLATE:TEMPLATE,LOGIC:LOGIC_TOKEN,VAR:VAR_TOKEN};function getMethod(input){return helpers.stripWhitespace(input).match(/^[\w\.]+/)[0]}function doubleEscape(input){return input.replace(/\\/g,"\\\\")}function getArgs(input){return doubleEscape(helpers.stripWhitespace(input).replace(/^[\w\.]+\(|\)$/g,""))}function getContextVar(varName,context){var a=varName.split(".");while(a.length){context=context[a.splice(0,1)[0]]}return context}function getTokenArgs(token,parts){parts=_.map(parts,doubleEscape);var i=0,l=parts.length,arg,ender,out=[];function concat(from,ending){var end=new RegExp("\\"+ending+"$"),i=from,out="";while(!end.test(out)&&i0&&/^end/.test(tagname)){lastToken=_.last(stack[stack.length-2]);if("end"+lastToken.name===tagname){if(lastToken.name==="autoescape"){escape=last_escape}lastToken.strip.end=stripBefore;lastToken.strip.after=stripAfter;stack.pop();index-=1;continue}throw new Error('Expected end tag for "'+lastToken.name+'", but found "'+tagname+'" at line '+lines+".")}if(!tags.hasOwnProperty(tagname)){throw new Error("Unknown logic tag at line "+lines+': "'+tagname+'".')}if(tagname==="autoescape"){last_escape=escape;escape=!parts.length||parts[0]==="true"?parts.length>=2?parts[1]:true:false}token={type:LOGIC_TOKEN,line:curline,name:tagname,compile:tags[tagname],parent:_.uniq(stack[stack.length-2]||[]),strip:{before:stripBefore,after:stripAfter,start:false,end:false}};token.args=getTokenArgs(token,parts);if(tags[tagname].ends){token.strip.after=false;token.strip.start=stripAfter;stack[index].push(token);stack.push(token.tokens=[]);index+=1;continue}}stack[index].push(token)}if(inRaw!==false){throw new Error('Missing expected end tag for "raw" on line '+curline+".")}if(index!==0){lastToken=_.last(stack[stack.length-2]);throw new Error('Missing end tag for "'+lastToken.name+'" that was opened on line '+lastToken.line+".")}return stack[index]};function precompile(indent,context){var filepath,extendsHasVar,preservedTokens=[];if(this.type===TEMPLATE){_.each(this.tokens,function(token,index){if(!extendsHasVar){if(token.name==="extends"){filepath=token.args[0];if(!helpers.isStringLiteral(filepath)){if(!context){extendsHasVar=true;return}filepath='"'+getContextVar(filepath,context)+'"'}if(!helpers.isStringLiteral(filepath)||token.args.length>1){throw new Error("Extends tag on line "+token.line+" accepts exactly one string literal as an argument.")}if(index>0){throw new Error('Extends tag must be the first tag in the template, but "extends" found on line '+token.line+".")}token.template=this.compileFile(filepath.replace(/['"]/g,""),true);this.parent=token.template;this.blocks=_.extend({},this.parent.blocks,this.blocks)}else if(token.name==="block"){var blockname=token.args[0],parentBlockIndex;if(!helpers.isValidBlockName(blockname)||token.args.length!==1){throw new Error('Invalid block tag name "'+blockname+'" on line '+token.line+".")}this.blocks[blockname]=token;findSubBlocks(token,this.blocks);if(this.parent){token.parentBlock=this.parent.blocks[blockname];parentBlockIndex=_.indexOf(this.parent.tokens,this.parent.blocks[blockname]);if(parentBlockIndex>=0){this.parent.tokens[parentBlockIndex]=token}}}else if(token.type===LOGIC_TOKEN){preservedTokens.push(token)}}},this);if(extendsHasVar){return false}if(this.parent&&this.parent.tokens){this.tokens=preservedTokens.concat(this.parent.tokens)}}}exports.compile=function compile(indent,context,template){var code="",wrappedInMethod,blockname,parentBlock;indent=indent||"";if(this.type===TEMPLATE){template=this}if(!this.blocks){this.blocks={}}if(precompile.call(this,indent,context)===false){return false}_.each(this.tokens,function(token,index){var name,key,args,prev,next;if(typeof token==="string"){prev=this.tokens[index-1];next=this.tokens[index+1];if(prev&&prev.strip&&prev.strip.after){token=token.replace(/^\s+/,"")}if(next&&next.strip&&next.strip.before){token=token.replace(/\s+$/,"")}code+='_output += "'+doubleEscape(token).replace(/\n/g,"\\n").replace(/\r/g,"\\r").replace(/"/g,'\\"')+'";\n';return code}if(typeof token!=="object"){return}if(token.type===VAR_TOKEN){name=token.name.replace(/\W/g,"_");key=helpers.isLiteral(name)?'["'+name+'"]':"."+name;args=token.args&&token.args.length?token.args:"";code+='if (typeof _context !== "undefined" && typeof _context'+key+' === "function") {\n';wrappedInMethod=helpers.wrapMethod("",{name:name,args:args},"_context");code+=' _output = (typeof _output === "undefined") ? '+wrappedInMethod+": _output + "+wrappedInMethod+";\n";if(helpers.isValidName(name)){code+="} else if (typeof "+name+' === "function") {\n';wrappedInMethod=helpers.wrapMethod("",{name:name,args:args});code+=' _output = (typeof _output === "undefined") ? '+wrappedInMethod+": _output + "+wrappedInMethod+";\n"}code+="} else {\n";code+=helpers.setVar("__"+name,token);code+=' _output = (typeof _output === "undefined") ? __'+name+": _output + __"+name+";\n";code+="}\n"}if(token.type!==LOGIC_TOKEN){return}if(token.name==="block"){blockname=token.args[0];if(!template.blocks.hasOwnProperty(blockname)){throw new Error('Unrecognized nested block. Block "'+blockname+'" at line '+token.line+' of "'+template.id+'" is not in template block list.')}code+=compile.call(template.blocks[token.args[0]],indent+" ",context,template)}else if(token.name==="parent"){parentBlock=getParentBlock(token);if(!parentBlock){throw new Error("No parent block found for parent tag at line "+token.line+".")}code+=compile.call(parentBlock,indent+" ",context)}else if(token.hasOwnProperty("compile")){if(token.strip.start&&token.tokens.length&&typeof token.tokens[0]==="string"){token.tokens[0]=token.tokens[0].replace(/^\s+/,"")}if(token.strip.end&&token.tokens.length&&typeof _.last(token.tokens)==="string"){token.tokens[token.tokens.length-1]=_.last(token.tokens).replace(/\s+$/,"")}code+=token.compile(indent+" ",exports)}else{code+=compile.call(token,indent+" ",context)}},this);return code}})(parser);tags["autoescape"]=function(){module={};module.exports=function(indent,parser){return parser.compile.apply(this,[indent])};module.exports.ends=true;return module.exports}();tags["block"]=function(){module={};module.exports={ends:true};return module.exports}();tags["else"]=function(){module={};module.exports=function(indent,parser){var last=_.last(this.parent).name,thisArgs=_.clone(this.args),ifarg,args,out;if(last==="for"){if(thisArgs.length){throw new Error('"else" tag cannot accept arguments in the "for" context.')}return"} if (__loopLength === 0) {\n"}if(last!=="if"){throw new Error('Cannot call else tag outside of "if" or "for" context.')}ifarg=thisArgs.shift();args=helpers.parseIfArgs(thisArgs,parser);out="";if(ifarg){out+="} else if (\n";out+=" (function () {\n";_.each(args,function(token){if(token.hasOwnProperty("preout")&&token.preout){out+=token.preout+"\n"}});out+="return (\n";_.each(args,function(token){out+=token.value+" "});out+=");\n";out+=" })()\n";out+=") {\n";return out}return indent+"\n} else {\n"};return module.exports}();tags["extends"]=function(){module={};module.exports={};return module.exports}();tags["filter"]=function(){module={};module.exports=function(indent,parser){var thisArgs=_.clone(this.args),name=thisArgs.shift(),args=thisArgs.length?thisArgs.join(", "):"",value="(function () {\n";value+=' var _output = "";\n';value+=parser.compile.apply(this,[indent+" "])+"\n";value+=" return _output;\n";value+="})()\n";return"_output += "+helpers.wrapFilter(value.replace(/\n/g,""),{name:name,args:args})+";\n"};module.exports.ends=true;return module.exports}();tags["for"]=function(){module={};module.exports=function(indent,parser){var thisArgs=_.clone(this.args),operand1=thisArgs[0],operator=thisArgs[1],operand2=parser.parseVariable(thisArgs[2]),out="",loopShared;indent=indent||"";if(typeof operator!=="undefined"&&operator!=="in"){throw new Error('Invalid syntax in "for" tag')}if(!helpers.isValidShortName(operand1)){throw new Error("Invalid arguments ("+operand1+') passed to "for" tag')}if(!helpers.isValidName(operand2.name)){throw new Error("Invalid arguments ("+operand2.name+') passed to "for" tag')}operand1=helpers.escapeVarName(operand1);loopShared="loop.index = __loopIndex + 1;\n"+"loop.index0 = __loopIndex;\n"+"loop.revindex = __loopLength - loop.index0;\n"+"loop.revindex0 = loop.revindex - 1;\n"+"loop.first = (__loopIndex === 0);\n"+"loop.last = (__loopIndex === __loopLength - 1);\n"+'_context["'+operand1+'"] = __loopIter[loop.key];\n'+parser.compile.apply(this,[indent+" "]);out="(function () {\n"+" var loop = {}, __loopKey, __loopIndex = 0, __loopLength = 0, __keys = [],"+' __ctx_operand = _context["'+operand1+'"],\n'+" loop_cycle = function() {\n"+" var args = _.toArray(arguments), i = loop.index0 % args.length;\n"+" return args[i];\n"+" };\n"+helpers.setVar("__loopIter",operand2)+" else {\n"+" return;\n"+" }\n"+" if (_.isArray(__loopIter)) {\n"+" __loopIndex = 0; __loopLength = __loopIter.length;\n"+" for (; __loopIndex < __loopLength; __loopIndex += 1) {\n"+" loop.key = __loopIndex;\n"+loopShared+" }\n"+' } else if (typeof __loopIter === "object") {\n'+" __keys = _.keys(__loopIter);\n"+" __loopLength = __keys.length;\n"+" __loopIndex = 0;\n"+" for (; __loopIndex < __loopLength; __loopIndex += 1) {\n"+" loop.key = __keys[__loopIndex];\n"+loopShared+" }\n"+" }\n"+' _context["'+operand1+'"] = __ctx_operand;\n'+"})();\n";return out};module.exports.ends=true;return module.exports}();tags["if"]=function(){module={};module.exports=function(indent,parser){var thisArgs=_.clone(this.args),args=helpers.parseIfArgs(thisArgs,parser),out="(function () {\n";_.each(args,function(token){if(token.hasOwnProperty("preout")&&token.preout){out+=token.preout+"\n"}});out+="\nif (\n";_.each(args,function(token){out+=token.value+" "});out+=") {\n";out+=parser.compile.apply(this,[indent+" "]);out+="\n}\n";out+="})();\n";return out};module.exports.ends=true;return module.exports}();tags["import"]=function(){module={};module.exports=function(indent,parser){if(this.args.length!==3){}var thisArgs=_.clone(this.args),file=thisArgs[0],as=thisArgs[1],name=thisArgs[2],out="";if(!helpers.isLiteral(file)&&!helpers.isValidName(file)){throw new Error('Invalid attempt to import "'+file+'".')}if(as!=="as"){throw new Error('Invalid syntax {% import "'+file+'" '+as+" "+name+" %}")}out+="_.extend(_context, (function () {\n";out+='var _context = {}, __ctx = {}, _output = "";\n'+helpers.setVar("__template",parser.parseVariable(file))+"_this.compileFile(__template).render(__ctx, _parents);\n"+"_.each(__ctx, function (item, key) {\n"+' if (typeof item === "function") {\n'+' _context["'+name+'_" + key] = item;\n'+" }\n"+"});\n"+"return _context;\n";out+="})());\n";return out};return module.exports}();tags["include"]=function(){module={};module.exports=function(indent,parser){var args=_.clone(this.args),template=args.shift(),context="_context",ignore=false,out="",ctx;indent=indent||"";if(!helpers.isLiteral(template)&&!helpers.isValidName(template)){throw new Error("Invalid arguments passed to 'include' tag.")}if(args.length){if(_.last(args)==="only"){context="{}";args.pop()}if(args.length>1&&args[0]==="ignore"&args[1]==="missing"){args.shift();args.shift();ignore=true}if(args.length&&args[0]!=="with"){throw new Error("Invalid arguments passed to 'include' tag.")}if(args[0]==="with"){args.shift();if(!args.length){throw new Error("Context for 'include' tag not provided, but expected after 'with' token.")}ctx=args.shift();context='_context["'+ctx+'"] || '+ctx}}out="(function () {\n"+helpers.setVar("__template",parser.parseVariable(template))+"\n"+" var includeContext = "+context+";\n";if(ignore){out+="try {\n"}out+=' if (typeof __template === "string") {\n';out+=" _output += _this.compileFile(__template).render(includeContext, _parents);\n";out+=" }\n";if(ignore){out+="} catch (e) {}\n"}out+="})();\n";return out};return module.exports}();tags["macro"]=function(){module={};module.exports=function(indent,parser){var thisArgs=_.clone(this.args),macro=thisArgs.shift(),args="",out="";if(thisArgs.length){args=JSON.stringify(thisArgs).replace(/^\[|\'|\"|\]$/g,"")}out+="_context."+macro+" = function ("+args+") {\n";out+=' var _output = "";\n';out+=parser.compile.apply(this,[indent+" "]);out+=" return _output;\n";out+="};\n";return out};module.exports.ends=true;return module.exports}();tags["parent"]=function(){module={};module.exports={};return module.exports}();tags["raw"]=function(){module={};module.exports={ends:true};return module.exports}();tags["set"]=function(){module={};module.exports=function(indent,parser){var thisArgs=_.clone(this.args),varname=helpers.escapeVarName(thisArgs.shift(),"_context"),value;if(thisArgs.shift()!=="="){throw new Error('Invalid token "'+thisArgs[1]+'" in {% set '+thisArgs[0]+' %}. Missing "=".')}value=thisArgs[0];if(helpers.isLiteral(value)||/^\{|^\[/.test(value)||value==="true"||value==="false"){return" "+varname+" = "+value+";"}value=parser.parseVariable(value);return" "+varname+" = "+"(function () {\n"+" var _output;\n"+parser.compile.apply({tokens:[value]},[indent])+"\n"+" return _output;\n"+"})();\n"};return module.exports}();return swig}(); 2 | -------------------------------------------------------------------------------- /themes/official/js/05-bbclear.js: -------------------------------------------------------------------------------- 1 | /* Blue Button Reference Implementation 2 | Copyright (c) 2013 by M. Jackson Wilkinson. 3 | License: Apache */ 4 | 5 | function isInt(input){ 6 | return parseInt(input, 10) % 1 === 0; 7 | } 8 | 9 | var filters = { 10 | isolanguage: function(input){ 11 | if(input.length >= 2){ 12 | code = input.substr(0,2); 13 | return isoLangs[code]; 14 | }else{ 15 | return input; 16 | } 17 | }, 18 | 19 | since_days: function(input, days){ 20 | batch = []; 21 | today = new Date(); 22 | target_date = new Date(today.setDate(today.getDate() - days)); 23 | 24 | for (var k in input){ 25 | if (isInt(k)){ 26 | if (input[k].effective_time && input[k].effective_time.low && input[k].effective_time.low > target_date){ 27 | batch.push(input[k]); 28 | }else if(input[k].date && input[k].date > target_date){ 29 | batch.push(input[k]); 30 | } 31 | } 32 | } 33 | 34 | return batch; 35 | }, 36 | 37 | strict_length: function(input){ 38 | return input.length; 39 | }, 40 | 41 | fallback: function(input, output){ 42 | return input ? input : output; 43 | }, 44 | 45 | age: function(date){ 46 | today = new Date(); 47 | ms = today - date; 48 | years = ms / (1000*60*60*24*365); 49 | return Math.floor(years); 50 | }, 51 | 52 | related_by_date: function(input, kind){ 53 | var date, batch; 54 | var list = []; 55 | 56 | if (kind == 'encounters'){ 57 | batch = bb.encounters(); 58 | }else if(kind == 'procedures'){ 59 | batch = bb.procedures(); 60 | }else if(kind == 'problems'){ 61 | batch = bb.problems(); 62 | }else if(kind == 'immunizations'){ 63 | batch = bb.immunizations(); 64 | }else if(kind == 'medications'){ 65 | batch = bb.medications(); 66 | return []; 67 | }else if(kind == 'labs'){ 68 | batch = []; 69 | for (var m in bb.labs()){ 70 | for (var l in bb.labs()[m].results){ 71 | batch.push(bb.labs()[m].results[l]); 72 | } 73 | } 74 | } 75 | 76 | if (input.date){ 77 | if (input.date instanceof Date){ 78 | dates = [input.date.toDateString()]; 79 | }else{ 80 | dates = [input.date_range.start.toDateString(), input.date_range.end.toDateString()]; 81 | } 82 | for (var k in batch){ 83 | if (typeof k == "number"){ 84 | target = batch[k]; 85 | if(target.date instanceof Date){ 86 | target_date = [target.date.toDateString()]; 87 | }else{ 88 | target_dates = [target.date_range.start.toDateString, target.date_range.end.toDateString()]; 89 | } 90 | if(filters.intersects(dates, target_dates).length > 0){ 91 | list.push(target); 92 | } 93 | } 94 | } 95 | } 96 | return list; 97 | }, 98 | intersects: function(input, comparand) { 99 | return input.filter(function(n){ 100 | if($.inArray(n, comparand) == -1){ 101 | return false; 102 | } 103 | return true; 104 | }); 105 | }, 106 | group : function(list, key){ 107 | var keys = key.split("."); 108 | var val, keyList = [], 109 | groupedList = []; 110 | 111 | for (i=0;i" + exp + "/" + unit; 164 | return str; 165 | }else if (input == '1' || input == 1){ 166 | return ""; 167 | }else{ 168 | return input; 169 | } 170 | } 171 | return input; 172 | }, 173 | 174 | full_name: function(input){ 175 | if(typeof input.given == 'undefined'){ 176 | return "John Doe"; 177 | } 178 | if(input.given === null){ 179 | if(input.family === null){ 180 | return "Unknown"; 181 | }else{ 182 | return input.family; 183 | } 184 | } 185 | var name, first_given, other_given, 186 | names = input.given.slice(0); 187 | 188 | if (names instanceof Array){ 189 | first_given = names.splice(0,1); 190 | other_given = names.join(" "); 191 | } else { 192 | first_given = names; 193 | } 194 | 195 | name = first_given; 196 | name = input.call_me ? name + " \"" + input.call_me + "\"" : name; 197 | name = (other_given) ? name + " " + other_given : name; 198 | name = name + " " + input.family; 199 | 200 | return name; 201 | }, 202 | 203 | display_name: function(input){ 204 | if(input.given instanceof Array){ 205 | return input.call_me ? input.call_me : input.given[0]; 206 | }else{ 207 | return input.call_me ? input.call_me : input.given; 208 | } 209 | }, 210 | 211 | gender_pronoun: function(input, possessive, absolute){ 212 | if(input == "female"){ 213 | return possessive ? (absolute ? "hers" : "her") : "she"; 214 | }else{ 215 | return possessive ? "his" : "he"; 216 | } 217 | }, 218 | 219 | max_severity: function(input){ 220 | /* looks through allergies and returns back the highest severity */ 221 | 222 | var i, 223 | mild = 0, 224 | moderate = 0, 225 | severe = 0, 226 | exists = 0; 227 | 228 | if(input.severity){ 229 | if (input.severity.match(/severe/i)){ 230 | severe++; 231 | }else if (input.severity.match(/moderate/i)){ 232 | moderate++; 233 | }else if (input.severity.match(/mild/i)){ 234 | mild++; 235 | }else{ 236 | exists++; 237 | } 238 | } else { 239 | for (i in input){ 240 | if (isInt(i)){ 241 | if(input[i].severity){ 242 | if (input[i].severity.match(/severe/i)){ 243 | severe++; 244 | }else if (input[i].severity.match(/moderate/i)){ 245 | moderate++; 246 | }else if (input[i].severity.match(/mild/i)){ 247 | mild++; 248 | }else{ 249 | exists++; 250 | } 251 | }else{ 252 | exists++; 253 | } 254 | } 255 | } 256 | } 257 | 258 | if(severe){ 259 | return severe > 1 ? "multiple severe" : "severe"; 260 | }else if (moderate){ 261 | return moderate > 1 ? "multiple moderate" : "moderate"; 262 | }else if (mild){ 263 | return mild > 1 ? "multiple mild" : "mild"; 264 | }else{ 265 | return exists === 0 ? "no" : 266 | exists > 1 ? "multiple" : ""; 267 | } 268 | } 269 | }; 270 | 271 | function init_template(){ 272 | swig.init({ 273 | allowErrors: true, 274 | autoescape: true, 275 | cache: true, 276 | encoding: 'utf8', 277 | filters: filters, 278 | tags: {}, 279 | extensions: {}, 280 | tzOffset: 0 281 | }); 282 | 283 | template = swig.compile($(".bb-template").html()); 284 | renderedHtml = template({ 285 | bb: bb, 286 | demographics: bb.demographics(), 287 | allergies: bb.allergies(), 288 | encounters: bb.encounters(), 289 | immunizations: bb.immunizations(), 290 | labs: bb.labs(), 291 | medications: bb.medications(), 292 | problems: bb.problems(), 293 | procedures: bb.procedures(), 294 | vitals: bb.vitals() 295 | }); 296 | 297 | $(".bb-template").html(renderedHtml); 298 | $("#loader").fadeOut(function(){ 299 | $(".bb-template").fadeIn(); 300 | }); 301 | } 302 | 303 | function scrollToElement(element){ 304 | $('html,body').animate({scrollTop: element.offset().top},'slow'); 305 | } 306 | 307 | $(function(){ 308 | $("#loader").fadeIn(function(){ 309 | text = $.text($("script#xmlBBData")); 310 | bb = BlueButton(text); 311 | init_template(); 312 | }); 313 | 314 | $(document).on('click', 'nav a', function(){ 315 | destination = $(this).attr('href'); 316 | scrollToElement($(destination)); 317 | return false; 318 | }); 319 | }); 320 | 321 | isoLangs = { 322 | "ab": "Abkhaz", 323 | "aa": "Afar", 324 | "af": "Afrikaans", 325 | "ak": "Akan", 326 | "sq": "Albanian", 327 | "am": "Amharic", 328 | "ar": "Arabic", 329 | "an": "Aragonese", 330 | "hy": "Armenian", 331 | "as": "Assamese", 332 | "av": "Avaric", 333 | "ae": "Avestan", 334 | "ay": "Aymara", 335 | "az": "Azerbaijani", 336 | "bm": "Bambara", 337 | "ba": "Bashkir", 338 | "eu": "Basque", 339 | "be": "Belarusian", 340 | "bn": "Bengali", 341 | "bh": "Bihari", 342 | "bi": "Bislama", 343 | "bs": "Bosnian", 344 | "br": "Breton", 345 | "bg": "Bulgarian", 346 | "my": "Burmese", 347 | "ca": "Catalan", 348 | "ch": "Chamorro", 349 | "ce": "Chechen", 350 | "ny": "Chichewa", 351 | "zh": "Chinese", 352 | "cv": "Chuvash", 353 | "kw": "Cornish", 354 | "co": "Corsican", 355 | "cr": "Cree", 356 | "hr": "Croatian", 357 | "cs": "Czech", 358 | "da": "Danish", 359 | "dv": "Divehi", 360 | "nl": "Dutch", 361 | "en": "English", 362 | "eo": "Esperanto", 363 | "et": "Estonian", 364 | "ee": "Ewe", 365 | "fo": "Faroese", 366 | "fj": "Fijian", 367 | "fi": "Finnish", 368 | "fr": "French", 369 | "ff": "Fula", 370 | "gl": "Galician", 371 | "ka": "Georgian", 372 | "de": "German", 373 | "el": "Greek, Modern", 374 | "gn": "Guarani", 375 | "gu": "Gujarati", 376 | "ht": "Haitian", 377 | "ha": "Hausa", 378 | "he": "Hebrew (modern)", 379 | "hz": "Herero", 380 | "hi": "Hindi", 381 | "ho": "Hiri Motu", 382 | "hu": "Hungarian", 383 | "ia": "Interlingua", 384 | "id": "Indonesian", 385 | "ie": "Interlingue", 386 | "ga": "Irish", 387 | "ig": "Igbo", 388 | "ik": "Inupiaq", 389 | "io": "Ido", 390 | "is": "Icelandic", 391 | "it": "Italian", 392 | "iu": "Inuktitut", 393 | "ja": "Japanese", 394 | "jv": "Javanese", 395 | "kl": "Greenlandic", 396 | "kn": "Kannada", 397 | "kr": "Kanuri", 398 | "ks": "Kashmiri", 399 | "kk": "Kazakh", 400 | "km": "Khmer", 401 | "ki": "Kikuyu", 402 | "rw": "Kinyarwanda", 403 | "ky": "Kirghiz", 404 | "kv": "Komi", 405 | "kg": "Kongo", 406 | "ko": "Korean", 407 | "ku": "Kurdish", 408 | "kj": "Kwanyama", 409 | "la": "Latin", 410 | "lb": "Luxembourgish", 411 | "lg": "Luganda", 412 | "li": "Limburgish", 413 | "ln": "Lingala", 414 | "lo": "Lao", 415 | "lt": "Lithuanian", 416 | "lu": "Luba-Katanga", 417 | "lv": "Latvian", 418 | "gv": "Manx", 419 | "mk": "Macedonian", 420 | "mg": "Malagasy", 421 | "ms": "Malay", 422 | "ml": "Malayalam", 423 | "mt": "Maltese", 424 | "mi": "Maori", 425 | "mr": "Marathi", 426 | "mh": "Marshallese", 427 | "mn": "Mongolian", 428 | "na": "Nauru", 429 | "nv": "Navajo", 430 | "nb": "Norwegian Bokmal", 431 | "nd": "North Ndebele", 432 | "ne": "Nepali", 433 | "ng": "Ndonga", 434 | "nn": "Norwegian Nynorsk", 435 | "no": "Norwegian", 436 | "ii": "Nuosu", 437 | "nr": "South Ndebele", 438 | "oc": "Occitan", 439 | "oj": "Ojibwe", 440 | "cu": "Old Church Slavonic", 441 | "om": "Oromo", 442 | "or": "Oriya", 443 | "os": "Ossetian", 444 | "pa": "Panjabi", 445 | "pi": "Pali", 446 | "fa": "Persian", 447 | "pl": "Polish", 448 | "ps": "Pashto", 449 | "pt": "Portuguese", 450 | "qu": "Quechua", 451 | "rm": "Romansh", 452 | "rn": "Kirundi", 453 | "ro": "Romanian", 454 | "ru": "Russian", 455 | "sa": "Sanskrit", 456 | "sc": "Sardinian", 457 | "sd": "Sindhi", 458 | "se": "Northern Sami", 459 | "sm": "Samoan", 460 | "sg": "Sango", 461 | "sr": "Serbian", 462 | "gd": "Gaelic", 463 | "sn": "Shona", 464 | "si": "Sinhalese", 465 | "sk": "Slovak", 466 | "sl": "Slovene", 467 | "so": "Somali", 468 | "st": "Southern Sotho", 469 | "es": "Spanish", 470 | "su": "Sundanese", 471 | "sw": "Swahili", 472 | "ss": "Swati", 473 | "sv": "Swedish", 474 | "ta": "Tamil", 475 | "te": "Telugu", 476 | "tg": "Tajik", 477 | "th": "Thai", 478 | "ti": "Tigrinya", 479 | "bo": "Tibetan,", 480 | "tk": "Turkmen", 481 | "tl": "Tagalog", 482 | "tn": "Tswana", 483 | "to": "Tonga", 484 | "tr": "Turkish", 485 | "ts": "Tsonga", 486 | "tt": "Tatar", 487 | "tw": "Twi", 488 | "ty": "Tahitian", 489 | "ug": "Uighur", 490 | "uk": "Ukrainian", 491 | "ur": "Urdu", 492 | "uz": "Uzbek", 493 | "ve": "Venda", 494 | "vi": "Vietnamese", 495 | "vo": "Volapuk", 496 | "wa": "Walloon", 497 | "cy": "Welsh", 498 | "wo": "Wolof", 499 | "fy": "Western Frisian", 500 | "xh": "Xhosa", 501 | "yi": "Yiddish", 502 | "yo": "Yoruba", 503 | "za": "Zhuang" 504 | }; 505 | -------------------------------------------------------------------------------- /themes/official/sass/print.scss: -------------------------------------------------------------------------------- 1 | /* Welcome to Compass. Use this file to define print styles. 2 | * Import this file using the following HTML or equivalent: 3 | * */ 4 | -------------------------------------------------------------------------------- /themes/official/sass/screen.scss: -------------------------------------------------------------------------------- 1 | @import "compass/css3"; 2 | @import "compass/utilities"; 3 | 4 | $severe: #c33; 5 | $warning: #e70; 6 | $light: #ddd; 7 | $very_light: #f8f8f8; 8 | 9 | $dark_text: #333; 10 | $soft_text: #666; 11 | $light_text: #f8f8f8; 12 | 13 | $module_width: 380px; 14 | $module_space: 20px; 15 | 16 | body { 17 | font-family: Helvetica Neue, Arial, Helvetica, sans-serif; 18 | color: $dark_text; 19 | } 20 | 21 | section.bb-template { 22 | width: 800px; 23 | margin: 0 auto; 24 | display: none; 25 | } 26 | 27 | .panel { 28 | padding: 50px 0; 29 | border-bottom: 1px solid $light; 30 | 31 | h1 { 32 | font-size: 30px; 33 | margin-bottom: 30px; 34 | } 35 | } 36 | 37 | a { 38 | color: inherit; 39 | text-decoration: none; 40 | 41 | &:hover{ 42 | text-decoration: underline; 43 | } 44 | } 45 | 46 | ul.pills { 47 | @include clearfix; 48 | margin: 0; padding: 10px 0 0 0; 49 | 50 | li { 51 | float: left; 52 | display: inline-block; 53 | padding: 2px 7px; 54 | margin-right: 5px; 55 | background: $light; 56 | @include border-radius(20px); 57 | font-size: 12px; 58 | border: 1px solid #ccc; 59 | } 60 | } 61 | 62 | .listless { 63 | @include clearfix; 64 | list-style-type: none; 65 | margin: 0; padding: 0; 66 | } 67 | 68 | .module { 69 | float: left; 70 | margin: 0 $module_space $module_space 0; 71 | padding: $module_space; 72 | width: 380px; 73 | background: $very_light; 74 | @include box-sizing(border-box); 75 | 76 | h2, p { 77 | margin-top: 0; 78 | margin-bottom: 2px; 79 | font-size: 18px; 80 | } 81 | 82 | p, header small { 83 | font-weight: 300; 84 | font-size: 18px; 85 | } 86 | } 87 | 88 | .container { 89 | @include clearfix; 90 | width: 800px; 91 | margin: 0 auto; 92 | } 93 | 94 | nav#primaryNav { 95 | position: fixed; 96 | top: 0; 97 | left: 0; 98 | width: 100%; 99 | height: 50px; 100 | @include box-sizing(border-box); 101 | background: #eee; 102 | @include background-image(linear-gradient(top, #eee, #ddd)); 103 | @include box-shadow(0px 0px 15px rgba(0,0,0,0.1)); 104 | z-index: 900; 105 | 106 | h1 { 107 | margin: 12px 0; 108 | padding: 0; 109 | width: 350px; 110 | float: left; 111 | font-size: 20px; 112 | font-weight: normal; 113 | color: #bbb; 114 | } 115 | 116 | ul { 117 | @extend .listless; 118 | float: right; 119 | 120 | li { 121 | padding: 18px 0; 122 | float: left; 123 | margin-right: 15px; 124 | font-size: 11px; 125 | text-transform: uppercase; 126 | color: $soft_text; 127 | 128 | &:hover { 129 | border-bottom: 2px solid #aaa; 130 | } 131 | 132 | a:hover { 133 | text-decoration: none; 134 | } 135 | } 136 | } 137 | } 138 | 139 | div#demographics { 140 | @extend .panel; 141 | font-size: 26px; 142 | font-weight: 300; 143 | 144 | h1 { 145 | font-size: 50px; 146 | } 147 | 148 | strong.severe { 149 | color: $light_text; 150 | background: $severe; 151 | } 152 | 153 | dl { 154 | @include clearfix; 155 | list-style-type: none; 156 | font-size: 18px; 157 | } 158 | 159 | dl li { 160 | width: 25%; 161 | float: left; 162 | } 163 | 164 | dt { 165 | text-transform: lowercase; 166 | color: $soft_text; 167 | } 168 | 169 | dd { 170 | font-weight: bold; 171 | margin-left: 0; 172 | } 173 | } 174 | 175 | div#allergies { 176 | @extend .panel; 177 | 178 | ul { @extend .listless; } 179 | 180 | li { 181 | @extend .module; 182 | 183 | &.allergy-severe { 184 | background: $severe; 185 | color: $light_text; 186 | } 187 | 188 | &.allergy-moderate { 189 | background: $warning; 190 | color: $light_text; 191 | } 192 | } 193 | } 194 | 195 | div#medications{ 196 | @extend .panel; 197 | 198 | ul { @extend .listless; } 199 | 200 | ul>li { 201 | @extend .module; 202 | border: 1px solid #ddd; 203 | 204 | &.odd { 205 | clear: left; 206 | } 207 | 208 | dl { 209 | @include clearfix; 210 | font-size: 13px; 211 | 212 | li { 213 | width: 50%; 214 | float: left; 215 | } 216 | 217 | dt { 218 | font-weight: 300; 219 | color: $soft_text; 220 | } 221 | 222 | dd { 223 | margin: 0; 224 | font-weight: bold; 225 | } 226 | } 227 | } 228 | } 229 | 230 | div#immunizations { 231 | @extend .panel; 232 | 233 | >ul { @extend .listless; } 234 | >ul>li { 235 | @extend .module; 236 | border: 1px solid #ddd; 237 | } 238 | } 239 | 240 | div#history { 241 | @extend .panel; 242 | 243 | >ul { 244 | @extend .listless; 245 | padding-left: 40px; 246 | margin-left: 20px; 247 | border-left: 1px solid $light; 248 | z-index: 1; 249 | 250 | >li:before { 251 | content:"."; 252 | display: block; 253 | position: absolute; 254 | background: #666; 255 | height: 35px; 256 | width: 35px; 257 | text-indent: 100%; 258 | overflow: hidden; 259 | margin-left: -60px; 260 | z-index: 999; 261 | } 262 | >li { 263 | h2 { 264 | font-size: 18px; 265 | font-weight: bold; 266 | margin-top: 0; 267 | padding: 6px 0; 268 | margin-bottom: 20px; 269 | } 270 | 271 | dl>li { 272 | margin-bottom: 30px; 273 | } 274 | 275 | dt { 276 | color: $soft_text; 277 | font-size: 20px; 278 | font-weight: 300; 279 | text-transform: lowercase; 280 | } 281 | 282 | dd { 283 | color: $soft_text; 284 | font-size: 20px; 285 | margin: 0; padding: 0; 286 | font-weight: 300; 287 | 288 | &.head { 289 | font-size: 24px; 290 | color: $dark_text; 291 | font-weight: bold; 292 | 293 | &:before { 294 | content:"."; 295 | display: block; 296 | position: absolute; 297 | background: #666; 298 | height: 15px; 299 | width: 15px; 300 | text-indent: 100%; 301 | overflow: hidden; 302 | margin-left: -48px; 303 | margin-top: 10px; 304 | z-index: 999; 305 | } 306 | } 307 | } 308 | } 309 | } 310 | } 311 | 312 | div#labs { 313 | @extend .panel; 314 | 315 | >ul { @extend .listless; } 316 | 317 | h2 .date { 318 | float: right; 319 | font-weight: 300; 320 | color: $soft_text; 321 | } 322 | 323 | ul.results { 324 | @extend .listless; 325 | display: table; 326 | width: 100%; 327 | border: 1px solid $light; 328 | border-right: none; 329 | @include box-sizing(border-box); 330 | 331 | li { display: table-row; } 332 | li.header span { 333 | background: $light; 334 | font-weight: bold; 335 | } 336 | 337 | span { 338 | display: table-cell; 339 | padding: 20px; 340 | border-right: 1px solid $light; 341 | color: $soft_text; 342 | 343 | &.lab-component { 344 | font-weight: bold; 345 | } 346 | } 347 | } 348 | } 349 | 350 | div#loader { 351 | display: none; 352 | width: 304px; 353 | margin: 100px auto; 354 | text-align: center; 355 | color: #ccc; 356 | 357 | #warningGradientOuterBarG{ 358 | height:38px; 359 | width:304px; 360 | border:2px solid #eee; 361 | overflow:hidden; 362 | background-color:#f8f8f8; 363 | @include background-image(linear-gradient(top, #f8f8f8, #eee)); 364 | } 365 | 366 | .warningGradientBarLineG{ 367 | background-color:#f8f8f8; 368 | float:left; 369 | width:27px; 370 | height:228px; 371 | margin-right:46px; 372 | margin-top:-53px; 373 | @include rotate(45deg); 374 | } 375 | 376 | .warningGradientAnimationG{ 377 | width:448px; 378 | -moz-animation-name:warningGradientAnimationG; 379 | -moz-animation-duration:1.3s; 380 | -moz-animation-iteration-count:infinite; 381 | -moz-animation-timing-function:linear; 382 | -webkit-animation-name:warningGradientAnimationG; 383 | -webkit-animation-duration:1.3s; 384 | -webkit-animation-iteration-count:infinite; 385 | -webkit-animation-timing-function:linear; 386 | -ms-animation-name:warningGradientAnimationG; 387 | -ms-animation-duration:1.3s; 388 | -ms-animation-iteration-count:infinite; 389 | -ms-animation-timing-function:linear; 390 | -o-animation-name:warningGradientAnimationG; 391 | -o-animation-duration:1.3s; 392 | -o-animation-iteration-count:infinite; 393 | -o-animation-timing-function:linear; 394 | animation-name:warningGradientAnimationG; 395 | animation-duration:1.3s; 396 | animation-iteration-count:infinite; 397 | animation-timing-function:linear; 398 | } 399 | 400 | } 401 | 402 | @-moz-keyframes warningGradientAnimationG { 403 | 0% { margin-left:-72px; } 404 | 100% { margin-left:0px; } 405 | } 406 | 407 | @-webkit-keyframes warningGradientAnimationG{ 408 | 0% { margin-left:-72px; } 409 | 100% { margin-left:0px; } 410 | } 411 | 412 | @-ms-keyframes warningGradientAnimationG{ 413 | 0% { margin-left:-72px; } 414 | 100% { margin-left:0px; } 415 | } 416 | 417 | @-o-keyframes warningGradientAnimationG{ 418 | 0% { margin-left:-72px; } 419 | 100% { margin-left:0px; } 420 | } 421 | 422 | @keyframes warningGradientAnimationG{ 423 | 0% { margin-left:-72px; } 424 | 100% { margin-left:0px; } 425 | } 426 | -------------------------------------------------------------------------------- /themes/official/stylesheets/normalize.css: -------------------------------------------------------------------------------- 1 | /*! normalize.css v1.0.1 | MIT License | git.io/normalize */ 2 | article,aside,details,figcaption,figure,footer,header,hgroup,nav,section,summary{display:block} 3 | audio,canvas,video{display:inline-block;*display:inline;*zoom:1} 4 | audio:not([controls]){display:none;height:0} 5 | [hidden]{display:none} 6 | html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%} 7 | html,button,input,select,textarea{font-family:sans-serif} 8 | body{margin:0} 9 | a:focus{outline:thin dotted} 10 | a:active,a:hover{outline:0} 11 | h1{font-size:2em;margin:.67em 0} 12 | h2{font-size:1.5em;margin:.83em 0} 13 | h3{font-size:1.17em;margin:1em 0} 14 | h4{font-size:1em;margin:1.33em 0} 15 | h5{font-size:.83em;margin:1.67em 0} 16 | h6{font-size:.75em;margin:2.33em 0} 17 | abbr[title]{border-bottom:1px dotted} 18 | b,strong{font-weight:bold} 19 | blockquote{margin:1em 40px} 20 | dfn{font-style:italic} 21 | mark{background:#ff0;color:#000} 22 | p,pre{margin:1em 0} 23 | code,kbd,pre,samp{font-family:monospace,serif;_font-family:'courier new',monospace;font-size:1em} 24 | pre{white-space:pre;white-space:pre-wrap;word-wrap:break-word} 25 | q{quotes:none} 26 | q:before,q:after{content:'';content:none} 27 | small{font-size:80%} 28 | sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline} 29 | sup{top:-0.5em} 30 | sub{bottom:-0.25em} 31 | dl,menu,ol,ul{margin:1em 0} 32 | dd{margin:0 0 0 40px} 33 | menu,ol,ul{padding:0 0 0 40px} 34 | nav ul,nav ol{list-style:none;list-style-image:none} 35 | img{border:0;-ms-interpolation-mode:bicubic} 36 | svg:not(:root){overflow:hidden} 37 | figure{margin:0} 38 | form{margin:0} 39 | fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:.35em .625em .75em} 40 | legend{border:0;padding:0;white-space:normal;*margin-left:-7px} 41 | button,input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle} 42 | button,input{line-height:normal} 43 | button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer;*overflow:visible} 44 | button[disabled],input[disabled]{cursor:default} 45 | input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0;*height:13px;*width:13px} 46 | input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box} 47 | input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none} 48 | button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0} 49 | textarea{overflow:auto;vertical-align:top} 50 | table{border-collapse:collapse;border-spacing:0} 51 | -------------------------------------------------------------------------------- /themes/official/stylesheets/print.css: -------------------------------------------------------------------------------- 1 | /* Welcome to Compass. Use this file to define print styles. 2 | * Import this file using the following HTML or equivalent: 3 | * */ 4 | -------------------------------------------------------------------------------- /themes/official/stylesheets/screen.css: -------------------------------------------------------------------------------- 1 | /* line 16, ../sass/screen.scss */ 2 | body { 3 | font-family: Helvetica Neue, Arial, Helvetica, sans-serif; 4 | color: #333333; 5 | } 6 | 7 | /* line 21, ../sass/screen.scss */ 8 | section.bb-template { 9 | width: 800px; 10 | margin: 0 auto; 11 | display: none; 12 | } 13 | 14 | /* line 27, ../sass/screen.scss */ 15 | .panel, div#demographics, div#allergies, div#medications, div#immunizations, div#history, div#labs { 16 | padding: 50px 0; 17 | border-bottom: 1px solid #dddddd; 18 | } 19 | /* line 31, ../sass/screen.scss */ 20 | .panel h1, div#demographics h1, div#allergies h1, div#medications h1, div#immunizations h1, div#history h1, div#labs h1 { 21 | font-size: 30px; 22 | margin-bottom: 30px; 23 | } 24 | 25 | /* line 37, ../sass/screen.scss */ 26 | a { 27 | color: inherit; 28 | text-decoration: none; 29 | } 30 | /* line 41, ../sass/screen.scss */ 31 | a:hover { 32 | text-decoration: underline; 33 | } 34 | 35 | /* line 46, ../sass/screen.scss */ 36 | ul.pills { 37 | overflow: hidden; 38 | *zoom: 1; 39 | margin: 0; 40 | padding: 10px 0 0 0; 41 | } 42 | /* line 50, ../sass/screen.scss */ 43 | ul.pills li { 44 | float: left; 45 | display: inline-block; 46 | padding: 2px 7px; 47 | margin-right: 5px; 48 | background: #dddddd; 49 | -webkit-border-radius: 20px; 50 | -moz-border-radius: 20px; 51 | -ms-border-radius: 20px; 52 | -o-border-radius: 20px; 53 | border-radius: 20px; 54 | font-size: 12px; 55 | border: 1px solid #ccc; 56 | } 57 | 58 | /* line 62, ../sass/screen.scss */ 59 | .listless, nav#primaryNav ul, div#allergies ul, div#medications ul, div#immunizations > ul, div#history > ul, div#labs > ul, div#labs ul.results { 60 | overflow: hidden; 61 | *zoom: 1; 62 | list-style-type: none; 63 | margin: 0; 64 | padding: 0; 65 | } 66 | 67 | /* line 68, ../sass/screen.scss */ 68 | .module, div#allergies li, div#medications ul > li, div#immunizations > ul > li { 69 | float: left; 70 | margin: 0 20px 20px 0; 71 | padding: 20px; 72 | width: 380px; 73 | background: #f8f8f8; 74 | -webkit-box-sizing: border-box; 75 | -moz-box-sizing: border-box; 76 | box-sizing: border-box; 77 | } 78 | /* line 76, ../sass/screen.scss */ 79 | .module h2, div#allergies li h2, div#medications ul > li h2, div#immunizations > ul > li h2, .module p, div#allergies li p, div#medications ul > li p, div#immunizations > ul > li p { 80 | margin-top: 0; 81 | margin-bottom: 2px; 82 | font-size: 18px; 83 | } 84 | /* line 82, ../sass/screen.scss */ 85 | .module p, div#allergies li p, div#medications ul > li p, div#immunizations > ul > li p, .module header small, div#allergies li header small, div#medications ul > li header small, div#immunizations > ul > li header small { 86 | font-weight: 300; 87 | font-size: 18px; 88 | } 89 | 90 | /* line 88, ../sass/screen.scss */ 91 | .container { 92 | overflow: hidden; 93 | *zoom: 1; 94 | width: 800px; 95 | margin: 0 auto; 96 | } 97 | 98 | /* line 94, ../sass/screen.scss */ 99 | nav#primaryNav { 100 | position: fixed; 101 | top: 0; 102 | left: 0; 103 | width: 100%; 104 | height: 50px; 105 | -webkit-box-sizing: border-box; 106 | -moz-box-sizing: border-box; 107 | box-sizing: border-box; 108 | background: #eee; 109 | background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #eeeeee), color-stop(100%, #dddddd)); 110 | background-image: -webkit-linear-gradient(top, #eeeeee, #dddddd); 111 | background-image: -moz-linear-gradient(top, #eeeeee, #dddddd); 112 | background-image: -o-linear-gradient(top, #eeeeee, #dddddd); 113 | background-image: linear-gradient(top, #eeeeee, #dddddd); 114 | -webkit-box-shadow: 0px 0px 15px rgba(0, 0, 0, 0.1); 115 | -moz-box-shadow: 0px 0px 15px rgba(0, 0, 0, 0.1); 116 | box-shadow: 0px 0px 15px rgba(0, 0, 0, 0.1); 117 | z-index: 900; 118 | } 119 | /* line 106, ../sass/screen.scss */ 120 | nav#primaryNav h1 { 121 | margin: 12px 0; 122 | padding: 0; 123 | width: 350px; 124 | float: left; 125 | font-size: 20px; 126 | font-weight: normal; 127 | color: #bbb; 128 | } 129 | /* line 116, ../sass/screen.scss */ 130 | nav#primaryNav ul { 131 | float: right; 132 | } 133 | /* line 120, ../sass/screen.scss */ 134 | nav#primaryNav ul li { 135 | padding: 18px 0; 136 | float: left; 137 | margin-right: 15px; 138 | font-size: 11px; 139 | text-transform: uppercase; 140 | color: #666666; 141 | } 142 | /* line 128, ../sass/screen.scss */ 143 | nav#primaryNav ul li:hover { 144 | border-bottom: 2px solid #aaa; 145 | } 146 | /* line 132, ../sass/screen.scss */ 147 | nav#primaryNav ul li a:hover { 148 | text-decoration: none; 149 | } 150 | 151 | /* line 139, ../sass/screen.scss */ 152 | div#demographics { 153 | font-size: 26px; 154 | font-weight: 300; 155 | } 156 | /* line 144, ../sass/screen.scss */ 157 | div#demographics h1 { 158 | font-size: 50px; 159 | } 160 | /* line 148, ../sass/screen.scss */ 161 | div#demographics strong.severe { 162 | color: #f8f8f8; 163 | background: #cc3333; 164 | } 165 | /* line 153, ../sass/screen.scss */ 166 | div#demographics dl { 167 | overflow: hidden; 168 | *zoom: 1; 169 | list-style-type: none; 170 | font-size: 18px; 171 | } 172 | /* line 159, ../sass/screen.scss */ 173 | div#demographics dl li { 174 | width: 25%; 175 | float: left; 176 | } 177 | /* line 164, ../sass/screen.scss */ 178 | div#demographics dt { 179 | text-transform: lowercase; 180 | color: #666666; 181 | } 182 | /* line 169, ../sass/screen.scss */ 183 | div#demographics dd { 184 | font-weight: bold; 185 | margin-left: 0; 186 | } 187 | 188 | /* line 183, ../sass/screen.scss */ 189 | div#allergies li.allergy-severe { 190 | background: #cc3333; 191 | color: #f8f8f8; 192 | } 193 | /* line 188, ../sass/screen.scss */ 194 | div#allergies li.allergy-moderate { 195 | background: #ee7700; 196 | color: #f8f8f8; 197 | } 198 | 199 | /* line 200, ../sass/screen.scss */ 200 | div#medications ul > li { 201 | border: 1px solid #ddd; 202 | } 203 | /* line 204, ../sass/screen.scss */ 204 | div#medications ul > li.odd { 205 | clear: left; 206 | } 207 | /* line 208, ../sass/screen.scss */ 208 | div#medications ul > li dl { 209 | overflow: hidden; 210 | *zoom: 1; 211 | font-size: 13px; 212 | } 213 | /* line 212, ../sass/screen.scss */ 214 | div#medications ul > li dl li { 215 | width: 50%; 216 | float: left; 217 | } 218 | /* line 217, ../sass/screen.scss */ 219 | div#medications ul > li dl dt { 220 | font-weight: 300; 221 | color: #666666; 222 | } 223 | /* line 222, ../sass/screen.scss */ 224 | div#medications ul > li dl dd { 225 | margin: 0; 226 | font-weight: bold; 227 | } 228 | 229 | /* line 234, ../sass/screen.scss */ 230 | div#immunizations > ul > li { 231 | border: 1px solid #ddd; 232 | } 233 | 234 | /* line 243, ../sass/screen.scss */ 235 | div#history > ul { 236 | padding-left: 40px; 237 | margin-left: 20px; 238 | border-left: 1px solid #dddddd; 239 | z-index: 1; 240 | } 241 | /* line 250, ../sass/screen.scss */ 242 | div#history > ul > li:before { 243 | content: "."; 244 | display: block; 245 | position: absolute; 246 | background: #666; 247 | height: 35px; 248 | width: 35px; 249 | text-indent: 100%; 250 | overflow: hidden; 251 | margin-left: -60px; 252 | z-index: 999; 253 | } 254 | /* line 263, ../sass/screen.scss */ 255 | div#history > ul > li h2 { 256 | font-size: 18px; 257 | font-weight: bold; 258 | margin-top: 0; 259 | padding: 6px 0; 260 | margin-bottom: 20px; 261 | } 262 | /* line 271, ../sass/screen.scss */ 263 | div#history > ul > li dl > li { 264 | margin-bottom: 30px; 265 | } 266 | /* line 275, ../sass/screen.scss */ 267 | div#history > ul > li dt { 268 | color: #666666; 269 | font-size: 20px; 270 | font-weight: 300; 271 | text-transform: lowercase; 272 | } 273 | /* line 282, ../sass/screen.scss */ 274 | div#history > ul > li dd { 275 | color: #666666; 276 | font-size: 20px; 277 | margin: 0; 278 | padding: 0; 279 | font-weight: 300; 280 | } 281 | /* line 288, ../sass/screen.scss */ 282 | div#history > ul > li dd.head { 283 | font-size: 24px; 284 | color: #333333; 285 | font-weight: bold; 286 | } 287 | /* line 293, ../sass/screen.scss */ 288 | div#history > ul > li dd.head:before { 289 | content: "."; 290 | display: block; 291 | position: absolute; 292 | background: #666; 293 | height: 15px; 294 | width: 15px; 295 | text-indent: 100%; 296 | overflow: hidden; 297 | margin-left: -48px; 298 | margin-top: 10px; 299 | z-index: 999; 300 | } 301 | 302 | /* line 317, ../sass/screen.scss */ 303 | div#labs h2 .date { 304 | float: right; 305 | font-weight: 300; 306 | color: #666666; 307 | } 308 | /* line 323, ../sass/screen.scss */ 309 | div#labs ul.results { 310 | display: table; 311 | width: 100%; 312 | border: 1px solid #dddddd; 313 | border-right: none; 314 | -webkit-box-sizing: border-box; 315 | -moz-box-sizing: border-box; 316 | box-sizing: border-box; 317 | } 318 | /* line 331, ../sass/screen.scss */ 319 | div#labs ul.results li { 320 | display: table-row; 321 | } 322 | /* line 332, ../sass/screen.scss */ 323 | div#labs ul.results li.header span { 324 | background: #dddddd; 325 | font-weight: bold; 326 | } 327 | /* line 337, ../sass/screen.scss */ 328 | div#labs ul.results span { 329 | display: table-cell; 330 | padding: 20px; 331 | border-right: 1px solid #dddddd; 332 | color: #666666; 333 | } 334 | /* line 343, ../sass/screen.scss */ 335 | div#labs ul.results span.lab-component { 336 | font-weight: bold; 337 | } 338 | 339 | /* line 350, ../sass/screen.scss */ 340 | div#loader { 341 | display: none; 342 | width: 304px; 343 | margin: 100px auto; 344 | text-align: center; 345 | color: #ccc; 346 | } 347 | /* line 357, ../sass/screen.scss */ 348 | div#loader #warningGradientOuterBarG { 349 | height: 38px; 350 | width: 304px; 351 | border: 2px solid #eee; 352 | overflow: hidden; 353 | background-color: #f8f8f8; 354 | background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #f8f8f8), color-stop(100%, #eeeeee)); 355 | background-image: -webkit-linear-gradient(top, #f8f8f8, #eeeeee); 356 | background-image: -moz-linear-gradient(top, #f8f8f8, #eeeeee); 357 | background-image: -o-linear-gradient(top, #f8f8f8, #eeeeee); 358 | background-image: linear-gradient(top, #f8f8f8, #eeeeee); 359 | } 360 | /* line 366, ../sass/screen.scss */ 361 | div#loader .warningGradientBarLineG { 362 | background-color: #f8f8f8; 363 | float: left; 364 | width: 27px; 365 | height: 228px; 366 | margin-right: 46px; 367 | margin-top: -53px; 368 | -webkit-transform: rotate(45deg); 369 | -moz-transform: rotate(45deg); 370 | -ms-transform: rotate(45deg); 371 | -o-transform: rotate(45deg); 372 | transform: rotate(45deg); 373 | } 374 | /* line 376, ../sass/screen.scss */ 375 | div#loader .warningGradientAnimationG { 376 | width: 448px; 377 | -moz-animation-name: warningGradientAnimationG; 378 | -moz-animation-duration: 1.3s; 379 | -moz-animation-iteration-count: infinite; 380 | -moz-animation-timing-function: linear; 381 | -webkit-animation-name: warningGradientAnimationG; 382 | -webkit-animation-duration: 1.3s; 383 | -webkit-animation-iteration-count: infinite; 384 | -webkit-animation-timing-function: linear; 385 | -ms-animation-name: warningGradientAnimationG; 386 | -ms-animation-duration: 1.3s; 387 | -ms-animation-iteration-count: infinite; 388 | -ms-animation-timing-function: linear; 389 | -o-animation-name: warningGradientAnimationG; 390 | -o-animation-duration: 1.3s; 391 | -o-animation-iteration-count: infinite; 392 | -o-animation-timing-function: linear; 393 | animation-name: warningGradientAnimationG; 394 | animation-duration: 1.3s; 395 | animation-iteration-count: infinite; 396 | animation-timing-function: linear; 397 | } 398 | 399 | @-moz-keyframes warningGradientAnimationG { 400 | /* line 403, ../sass/screen.scss */ 401 | 0% { 402 | margin-left: -72px; 403 | } 404 | 405 | /* line 404, ../sass/screen.scss */ 406 | 100% { 407 | margin-left: 0px; 408 | } 409 | } 410 | 411 | @-webkit-keyframes warningGradientAnimationG { 412 | /* line 408, ../sass/screen.scss */ 413 | 0% { 414 | margin-left: -72px; 415 | } 416 | 417 | /* line 409, ../sass/screen.scss */ 418 | 100% { 419 | margin-left: 0px; 420 | } 421 | } 422 | 423 | @-ms-keyframes warningGradientAnimationG { 424 | /* line 413, ../sass/screen.scss */ 425 | 0% { 426 | margin-left: -72px; 427 | } 428 | 429 | /* line 414, ../sass/screen.scss */ 430 | 100% { 431 | margin-left: 0px; 432 | } 433 | } 434 | 435 | @-o-keyframes warningGradientAnimationG { 436 | /* line 418, ../sass/screen.scss */ 437 | 0% { 438 | margin-left: -72px; 439 | } 440 | 441 | /* line 419, ../sass/screen.scss */ 442 | 100% { 443 | margin-left: 0px; 444 | } 445 | } 446 | 447 | @keyframes warningGradientAnimationG { 448 | /* line 423, ../sass/screen.scss */ 449 | 0% { 450 | margin-left: -72px; 451 | } 452 | 453 | /* line 424, ../sass/screen.scss */ 454 | 100% { 455 | margin-left: 0px; 456 | } 457 | } 458 | -------------------------------------------------------------------------------- /themes/official/template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Blue Button Health Record 10 | 11 | 12 | 13 | {% insert styles %} 14 | {% insert scripts %} 15 | 16 | 17 |
18 | 31 |
32 |

{{demographics.name|full_name}}

33 |

34 | 35 | {{demographics.name|display_name}} is a {% if demographics.dob %}{{demographics.dob|age}} year old{% endif %} 36 | {% if demographics.race %}{{demographics.race}} {% endif %}{% if demographics.marital_status %}{{demographics.marital_status|lower}} {% endif %}{{demographics.gender|lower}} 37 | {% if demographics.religion or demographics.language %}who {% if demographics.religion %}is {{demographics.religion}}{% if demographics.language %} and {% endif %}{% endif %}{% if demographics.language %}speaks {{demographics.language|isolanguage|title}}{% endif %}{% endif %}. 38 | 39 | 40 | {{demographics.gender|gender_pronoun|title}} has {{allergies|max_severity}} allergies. 41 | 42 | 43 | In the past year, {{demographics.gender|gender_pronoun}} 44 | 45 | {% if encounters|since_days(365)|strict_length == 0 %} 46 | did not have medical encounters 47 | {% else %} 48 | had medical encounters 49 | {% endif %} 50 | and has 51 | {% if medications|since_days(365)|strict_length == 0 %} 52 | not had any medications prescribed. 53 | {% else %} 54 | been prescribed medications. 55 | {% endif %} 56 | 57 | 58 |

59 |
60 |
  • 61 |
    Birthday
    62 |
    {{demographics.dob|date("F j, Y")}}
    63 |
  • 64 |
  • 65 |
    Address
    66 | {% if demographics.address.street|length == 2 %} 67 | {% for line in demographics.address.street %} 68 |
    {{line}}
    69 | {% endfor %} 70 | {% else %} 71 |
    {{demographics.address.street}}
    72 | {% endif %} 73 |
    {{demographics.address.city}}, {{demographics.address.state}} {{demographics.address.zip}}
    74 |
  • 75 |
  • 76 |
    Telephone
    77 | {% for number in demographics.phone %} 78 | {% if number %}
    {{loop.key|slice(0,1)}}: {{number|format_phone}}
    {% endif %} 79 | {% else %} 80 |
    No known number
    81 | {% endfor %} 82 |
  • 83 | {% if demographics.guardian and demographics.guardian.name.family %}
  • 84 |
    {{demographics.guardian.relationship|fallback("Guardian")}}
    85 |
    {{demographics.guardian.name|full_name}}
    86 | {% for number in demographics.guardian.phone %} 87 | {% if number %}
    {{loop.key|slice(0,1)}}: {{number|format_phone}}
    {% endif %} 88 | {% else %} 89 |
    No known number
    90 | {% endfor %} 91 |
  • {% endif %} 92 |
    93 |
    94 |
    95 |

    Allergies

    96 | {% for allergy in allergies %} 97 | {% if loop.first %}
      {% endif %} 98 |
    • 99 |

      {{allergy.allergen.name}}

      100 | {% if allergy.severity %}

      {{allergy.severity}}

      {% endif %} 101 | {% if allergy.reaction.name %}

      Causes {{allergy.reaction.name|lower}}

      {% endif %} 102 |
    • 103 | {% if loop.last %}
    {% endif %} 104 | {% else %} 105 |

    No known allergies

    106 | {% endfor %} 107 |
    108 |
    109 |

    Medication History

    110 | {% for med in medications %} 111 | {% if loop.first %}
      {% endif %} 112 |
    • 113 |
      114 |

      {{med.product.name}}

      115 | {% if med.administration.name %}{{med.administration.name|title}}{% endif %} 116 | {% if med.reason.name %}for {{med.reason.name}}{% endif %} 117 |
      118 | 119 | 133 |
    • 134 | {% if loop.last %}
    {% endif %} 135 | {% else %} 136 |

    No known medications

    137 | {% endfor %} 138 |
    139 |
    140 |

    Immunizations

    141 | {% for group in immunizations|group('product.name') %} 142 | {% if loop.first %}
      {% endif %} 143 |
    • 144 |

      {{group.grouper}}

      145 | {% for item in group.list %} 146 | {% if loop.first %}
        {% endif %} 147 |
      • {{item.date|date('M j, Y')}}
      • 148 | {% if loop.last %}
      {% endif %} 149 | {% endfor %} 150 |
    • 151 | {% if loop.last %}
    {% endif %} 152 | {% else %} 153 |

    No known immunizations

    154 | {% endfor %} 155 |
    156 |
    157 |

    Medical History

    158 | {% for encounter in encounters %} 159 | {% if loop.first %}
      {% endif %} 160 |
    • 161 |

      {{encounter.date|date('M j, Y')}}

      162 |
      163 |
    • 164 |
      Encounter
      165 |
      {{encounter.name|fallback("Unknown Visit")|title}}
      166 | {% if encounter.finding.name %}
      Finding: {{encounter.finding.name}}
      {% endif %} 167 |
    • 168 | {% for problem in encounter|related_by_date('problems') %} 169 |
    • 170 |
      Problem
      171 |
      {{problem.name}}
      172 |
    • 173 | {% endfor %} 174 | {% for procedure in encounter|related_by_date('procedures') %} 175 |
    • 176 |
      Procedure
      177 |
      {{procedure.name}}
      178 |
    • 179 | {% endfor %} 180 | {% for medication in encounter|related_by_date('medications') %} 181 |
    • 182 |
      Medication
      183 |
      {{medication.product.name}}
      184 |
    • 185 | {% endfor %} 186 | {% for immunization in encounter|related_by_date('immunizations') %} 187 |
    • 188 |
      Immunization
      189 |
      {{immunization.product.name}}
      190 |
    • 191 | {% endfor %} 192 |
      193 |
    • 194 | {% if loop.last %}
    {% endif %} 195 | {% else %} 196 |

    No known past encounters

    197 | {% endfor %} 198 |
    199 |
    200 |

    Lab Results

    201 | {% for panel in labs %} 202 | {% if loop.first %}
      {% endif %} 203 |
    • 204 |

      205 | {{panel.results[0].date|date('M j, Y')}} 206 | {{panel.name|fallback("Laboratory Panel")}} 207 |

      208 |
        209 |
      • 210 | Component 211 | Value 212 | Low 213 | High 214 |
      • 215 | {% for result in panel.results %} 216 |
      • 217 | {{result.name}} 218 | {{result.value|fallback("Unknown")}}{% if result.unit %} {{result.unit|format_unit|raw}}{% endif %} 219 | {% if result.reference.low %}{{result.reference.low}}{% endif %} 220 | {% if result.reference.high %}{{result.reference.high}}{% endif %} 221 |
      • 222 | {% endfor %} 223 |
      224 |
    • 225 | {% if loop.last %}
    {% endif %} 226 | {% endfor %} 227 |
    228 |
    229 |
    230 |
    231 |
    232 |
    233 |
    234 |
    235 |
    236 |
    237 |
    238 |
    239 |
    240 |

    Reticulating splines...

    241 |
    242 | 243 | 244 | {% insert data %} 245 | --------------------------------------------------------------------------------