Style = init: -> @agent = { 'gecko': '-moz-' 'webkit': '-webkit-' 'presto': '-o-' }[$.engine] @sizing = "#{if $.engine is 'gecko' then @agent else ''}box-sizing" $.ready -> return unless $.id 'navtopright' Style.padding.nav = $ "#boardNavDesktop", d.body Style.padding.pages = $(".pagelist", d.body) Style.padding() $.on window, "resize", Style.padding # Give ExLinks and 4sight a little time to append their dialog links setTimeout (-> Style.iconPositions() if exLink = $ "#navtopright .exlinksOptionsLink", d.body $.on exLink, "click", -> setTimeout Style.rice, 100 ), 500 @setup() setup: -> @addStyleReady() if d.head @remStyle() unless Style.headCount return @cleanup() @observe() observe: -> if MutationObserver Style.observer = new MutationObserver onMutationObserver = @wrapper Style.observer.observe d, childList: true subtree: true else $.on d, 'DOMNodeInserted', @wrapper wrapper: -> if d.head Style.remStyle() if not Style.headCount or d.readyState is 'complete' if Style.observer Style.observer.disconnect() else $.off d, 'DOMNodeInserted', Style.wrapper Style.cleanup() cleanup: -> delete Style.observe delete Style.wrapper delete Style.remStyle delete Style.headCount delete Style.cleanup addStyle: (theme) -> _conf = Conf unless theme theme = Themes[_conf['theme']] MascotTools.init _conf["mascot"] Style.layoutCSS.textContent = Style.layout() Style.themeCSS.textContent = Style.theme(theme) Style.iconPositions() headCount: 12 addStyleReady: -> theme = Themes[Conf['theme']] $.extend Style, layoutCSS: $.addStyle Style.layout(), 'layout' themeCSS: $.addStyle Style.theme(theme), 'theme' icons: $.addStyle "", 'icons' paddingSheet: $.addStyle "", 'padding' mascot: $.addStyle "", 'mascotSheet' # Non-customizable $.addStyle JSColor.css(), 'jsColor' delete Style.addStyleReady remStyle: -> nodes = d.head.children i = nodes.length while i-- break unless Style.headCount node = nodes[i] if (node.nodeName is 'STYLE' and !node.id) or ("#{node.rel}".contains('stylesheet') and node.href[..3] isnt 'data') Style.headCount-- $.rm node continue return filter: (text, background) -> matrix = (fg, bg) -> " #{bg.r} #{-fg.r} 0 0 #{fg.r} #{bg.g} #{-fg.g} 0 0 #{fg.g} #{bg.b} #{-fg.b} 0 0 #{fg.b} " fgHex = Style.colorToHex text bgHex = Style.colorToHex background string = matrix { r: parseInt(fgHex.substr(0, 2), 16) / 255 g: parseInt(fgHex.substr(2, 2), 16) / 255 b: parseInt(fgHex.substr(4, 2), 16) / 255 }, { r: parseInt(bgHex.substr(0, 2), 16) / 255 g: parseInt(bgHex.substr(2, 2), 16) / 255 b: parseInt(bgHex.substr(4, 2), 16) / 255 } return "filter: url(\"data:image/svg+xml,#filters\");" layout: -> _conf = Conf agent = Style.agent xOffset = if _conf["Sidebar Location"] is "left" then '' else '-' # Position of submenus in relation to the post menu. position = { right: { hide: if parseInt(_conf['Right Thread Padding'], 10) < 100 "right" else "left" minimal: "right" }[_conf["Sidebar"]] or "left" left: if parseInt(_conf['Right Thread Padding'], 10) < 100 "right" else "left" }[_conf["Sidebar Location"]] # Offsets various UI of the sidebar depending on the sidebar's width. # Only really used for the board banner or right sidebar. Style['sidebarOffset'] = if _conf["Sidebar"] is "large" { W: 51 H: 17 } else { W: 0 H: 0 } Style.logoOffset = if _conf["4chan Banner"] is "at sidebar top" 83 + Style.sidebarOffset.H else 0 width = 248 + Style.sidebarOffset.W Style.sidebarLocation = if _conf["Sidebar Location"] is "left" ["left", "right"] else ["right", "left" ] if _conf['editMode'] is "theme" editSpace = {} editSpace[Style.sidebarLocation[1]] = 300 editSpace[Style.sidebarLocation[0]] = 0 else editSpace = left: 0 right: 0 Style.sidebar = { minimal: 20 hide: 2 }[_conf.Sidebar] or (252 + Style.sidebarOffset.W) Style.replyMargin = _conf["Post Spacing"] css = """<%= grunt.file.read('css/layout.css') %>""" theme: (theme) -> _conf = Conf agent = Style.agent bgColor = new Style.color Style.colorToHex backgroundC = theme["Background Color"] Style.lightTheme = bgColor.isLight() icons = Icons.header.png + Icons.themes[_conf["Icons"]] css = """<%= grunt.file.read('css/theme.css') %>""" iconPositions: -> css = """<%= grunt.file.read('css/icons.base.css') %>""" i = 0 align = Style.sidebarLocation[0] _conf = Conf notCatalog = !g.CATALOG notEither = notCatalog and g.BOARD isnt 'f' aligner = (first, checks) -> # Create a position to hold values position = [first] # Check which elements we actually have. Some are easy, because the script creates them so we'd know they're here # Some are hard, like 4sight, which we have no way of knowing if available without looking for it. for enabled in checks position[position.length] = if enabled first += 19 else first position if _conf["Icon Orientation"] is "horizontal" position = aligner( 2 [ notCatalog _conf['Slideout Navigation'] isnt 'hide' _conf['Announcements'] is 'slideout' and $ '#globalMessage', d.body notCatalog and _conf['Slideout Watcher'] and _conf['Thread Watcher'] $ '#navtopright .exlinksOptionsLink', d.body notCatalog and $ 'body > a[style="cursor: pointer; float: right;"]', d.body notEither and _conf['Image Expansion'] notEither g.REPLY notEither and _conf['Fappe Tyme'] navlinks = ((!g.REPLY and _conf['Index Navigation']) or (g.REPLY and _conf['Reply Navigation'])) and notCatalog navlinks ] ) iconOffset = position[position.length - 1] - (if _conf['4chan SS Navigation'] 0 else Style.sidebar + parseInt(_conf["Right Thread Padding"], 10)) if iconOffset < 0 then iconOffset = 0 css += """<%= grunt.file.read('css/icons.horz.css') %>""" if _conf["Updater Position"] isnt 'moveable' css += """<%= grunt.file.read('css/icons.horz.tu.css') %>""" else position = aligner( 2 + (if _conf["4chan Banner"] is "at sidebar top" then (Style.logoOffset + 19) else 0) [ notEither and _conf['Image Expansion'] notCatalog _conf['Slideout Navigation'] isnt 'hide' _conf['Announcements'] is 'slideout' and $ '#globalMessage', d.body notCatalog and _conf['Slideout Watcher'] and _conf['Thread Watcher'] notCatalog and $ 'body > a[style="cursor: pointer; float: right;"]', d.body $ '#navtopright .exlinksOptionsLink', d.body notEither g.REPLY notEither and _conf['Fappe Tyme'] navlinks = ((!g.REPLY and _conf['Index Navigation']) or (g.REPLY and _conf['Reply Navigation'])) and notCatalog navlinks ] ) iconOffset = ( if g.REPLY and _conf['Prefetch'] 250 + Style.sidebarOffset.W else 20 + ( if g.REPLY and _conf['Updater Position'] is 'top' 100 else 0 ) ) - ( if _conf['4chan SS Navigation'] 0 else Style.sidebar + parseInt _conf[align.capitalize() + " Thread Padding"], 10 ) css += """<%= grunt.file.read('css/icons.vert.css') %>""" if _conf["Updater Position"] isnt 'moveable' css += """<%= grunt.file.read('css/icons.vert.tu.css') %>""" Style.icons.textContent = css padding: -> return unless sheet = Style.paddingSheet _conf = Conf Style.padding.nav.property = _conf["Boards Navigation"].split(" ") Style.padding.nav.property = Style.padding.nav.property[Style.padding.nav.property.length - 1] if Style.padding.pages Style.padding.pages.property = _conf["Pagination"].split(" ") Style.padding.pages.property = Style.padding.pages.property[Style.padding.pages.property.length - 1] css = "body::before {\n" if _conf["4chan SS Emulation"] if Style.padding.pages and (_conf["Pagination"] is "sticky top" or _conf["Pagination"] is "sticky bottom") css += " #{Style.padding.pages.property}: #{Style.padding.pages.offsetHeight}px !important;\n" if _conf["Boards Navigation"] is "sticky top" or _conf["Boards Navigation"] is "sticky bottom" css += " #{Style.padding.nav.property}: #{Style.padding.nav.offsetHeight}px !important;\n" css += """ } body { padding-bottom: 0;\n """ if Style.padding.pages? and (_conf["Pagination"] is "sticky top" or _conf["Pagination"] is "sticky bottom" or _conf["Pagination"] is "top") css += " padding-#{Style.padding.pages.property}: #{Style.padding.pages.offsetHeight}px;\n" unless _conf["Boards Navigation"] is "hide" css += " padding-#{Style.padding.nav.property}: #{Style.padding.nav.offsetHeight}px;\n" css += "}" sheet.textContent = css color: (hex) -> @hex = "#" + hex @calc_rgb = (hex) -> hex = parseInt hex, 16 [ # 0xRRGGBB to [R, G, B] (hex >> 16) & 0xFF (hex >> 8) & 0xFF hex & 0xFF ] @private_rgb = @calc_rgb(hex) @rgb = @private_rgb.join "," @isLight = -> rgb = @private_rgb return (rgb[0] + rgb[1] + rgb[2]) >= 400 @shiftRGB = (shift, smart) -> minmax = (base) -> Math.min Math.max(base, 0), 255 rgb = @private_rgb.slice 0 shift = if smart ( if @isLight rgb -1 else 1 ) * Math.abs shift else shift return [ minmax rgb[0] + shift minmax rgb[1] + shift minmax rgb[2] + shift ].join "," @hover = @shiftRGB 16, true colorToHex: (color) -> if color.substr(0, 1) is '#' return color.slice 1, color.length if digits = color.match /(.*?)rgba?\((\d+), ?(\d+), ?(\d+)(.*?)\)/ # [R, G, B] to 0xRRGGBB hex = ( (parseInt(digits[2], 10) << 16) | (parseInt(digits[3], 10) << 8) | (parseInt(digits[4], 10)) ).toString 16 while hex.length < 6 hex = "0#{hex}" hex else false Emoji = init: -> Emoji.icons.not.push ['PlanNine', Emoji.icons.not[0][1]] css: (position) -> _conf = Conf css = [] margin = "margin-#{if position is "before" then "right" else "left"}: #{parseInt _conf['Emoji Spacing']}px;" for key, category of Emoji.icons if (_conf['Emoji'] isnt "disable ponies" and key is "pony") or (_conf['Emoji'] isnt "only ponies" and key is "not") for icon in category name = icon[0] css[css.length] = """ a.useremail[href*='#{name}']:last-of-type::#{position}, a.useremail[href*='#{name.toLowerCase()}']:last-of-type::#{position}, a.useremail[href*='#{name.toUpperCase()}']:last-of-type::#{position} { content: url('#{Icons.header.png + icon[1]}'); vertical-align: top; #{margin} }\n """ css.join "" icons: pony: [ ['Pinkie', 'BAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAA3dJREFUGBlNwUtoXFUcB+Df/zzuY553pp2MmUwSk5TGpnamiokWRdNCSkCrUChKCnVZQUEUdy5sQZC6cyd2VWgoutCFXWTjIyp1UdqmEDBRsSZNmkmaZF6Zx32ccyzowu8j/M883pH5A9kBYfNkFOpu0OiulyqXmnhkDmdYHYJexzX1Ef51EQDhP9fxpjU0PDCd7IldYIxGVag3/KZ/ZX1p8/P0k/0U47qs291M2NS3f6ncuLeFeQ3A8KuYoNPoY/3e2Ej6scSnqUJ8gksmhC2y3OJHpSUHU0/3HU+WCuddyV6VSpVyYv/aUuPefWAP4iDG8AhJWyYYo972tg8DQ1wyWHGZSfcmZmQ+YeKTw1bQ70H8uJw3xtDp6NzG15VLf/DLWMBZHGPkwuWGyq7njLoZyzAiCtqRIddioifBxYBHIpeE0oaw0yoG7WA755dvi8Xih66BOSZj4rwds45bSQkuOeOCQYWG2PjjcEq94JwjQgQ+kCW+tBl3H7Ym4jnbE/nDmamwqz9mnEaYoBgiZaJIGW5zEIHEPheykMD2w12ztPIXCrZHec+GdOVAUI8ygjvifeHQESiNoKtMlIoRxSV0owMjAeY5+P3BKrbTDq3n02B/7yDTDkBANSXiewKgjFbahEwQe34IiVIfRNqCv1qDanQR9Di4+tU16N409o2WMXnyJeNWb9PO4s6WroZawOiSiozCoR7lPFUQezICCzXF+pPGYRna6/rotNqY/eJLUzh4mM5dP4Va0YXV45x0O9F9FhkN5auq4eznaq3WmP1pDkuibW5uraNaqyNh23ihPA6v7wAVS+PwXAGkbYiUnU3kYm8JzvgGpJGdG6vzm15+ce6H79/9bnnBhCxG702dwnTaw4nyM/jsiTHsHx+DEyjKWnGEUpBOyjTTgbpsNHyLojPe7PK3qci58NvNu0Gl0YA8NIxWp4MkdzCdK2Ci6iNYXIV6UEfUDBC2Q/A3WqVbUUfVucWftYhP9fLiFf7yRPGVmZmhE88dJVmpGRMqRH4E3emSbnQR3lkzaqNB3br/J39tb1ibJglGfJDZbMReb37Td/bFhcnB/iNppXNUbZEKFGBJ6FBT+9cVo5c3yd/trDV3OxdFDDHFOV8IffVJtNNOC+J3xtYqATWw0Mm6RIJ9YAy9rdtt07q1ZtjdVXCYFRBG4Bv8A+lliGhzN164AAAAAElFTkSuQmCC'] ['Applejack', 'A4AAAAQCAYAAAAmlE46AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAv9JREFUOE9dkmtIU2EYx88Roi9FfahkfQmS6kNGEBRlZWSY5tylTKepqR8MHYGl2R1POm2u5bCVlzbog2Ze591pzZPZxUskDZLMMLSWzcIca3MXt7N/55woqhf+PC8Pz+99n+fPQxAEQf6vhINb1nG5/ISdobWXo+9eSd4tyM7OJimKImmaJhsaGjjmX/DGqfDQmkvRg1x+9YrlZPd18fdupXiu6mxkOAcqlUqyuLiYB/+cayfD1rKFH0w3pYEHV4/omhTCyieVcYEB7TEYSyX21Mita/6u/91qUBMV00JrjmKwMg4zI2fgnlfD90PLx+nhMyinIrb91SFBFqaHBevPHb7G/fS06jhs0wXwO8rBOLXws2Kct/k4//HKRE+jZD0Pl2buD2FnmOlVSUFrpJg15/JFgcWKP0Bg8Q6fs1sVs+11wmAebKaEuiG1CC81Yozci+cL4KoC3JUIuCp4+R23+Ee4Dr5bisZmJi7fJzpLRJZPOin8vSlwdSXDO54Hz+vT8LzLh3uuCIuzBfDa1DzMPcrJMVfkIHpVEu94uYgH/aaTvOxdJzDZkI76smhY2mVwDmfg8zM5RukcvH8pbx96mLiPMBTG0nSpGK7mePg6k+DsSUZbSQwem02oba3DRsFKzNQfx9sHSdi1dzve5Ow4xM+ozorY1K2U2MY0IrhbEuB7lIqB6gxY7B9R3XoHAoEAivN74O5LAaXNwvNLe9PlcjlJACANRaIRztFh1iRvfRyYx5kIOCwY+GCE9GIUOjrzwZjS4H16FV80UT1WqzWIWFhYIBsLhDf7y46Ck1UvATNKgXlxHgHbJDyub2DGVPC2s+bVyGDTx74ym80kwe2fKvNASN8NySK3NeayWNagNPj7WaP62Uhn8HdPkwyWW3IoEjdv0Ol0JGE0GvmV0+dFpj9SS5kOKuahr01Wwbb2lXV6aakjkfF1p8DXlwHnaB5yTm1bbzAYfs34e/+0pyNic+N2ruIWmQWXcdE1dUEGd9UYq6kle1mXqVW6imWIn290AGVZutJTAAAAAElFTkSuQmCC'] ['Fluttershy', 'BAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAA2xJREFUOE9dU91PWmcYP2uybDfrxdIlu9vN/oglverWNN3Fmu1iN7vY2q4utnE2Nu26ukyrUUGwExGpn3xY+TyACjrskFrcEYoWnCAM4YAgcJjROkFA1q789nJczNaTPHnfk+f5/d7n4/dQ1Cvf3Ut3Xp//Qnze36gYCt56kIgJpyqRFvrvcIvxMNxhSa9eV993XJK/+yqO/zdf7j7tbRz1RdstLzOKReRoLxJSOzb7HyKtdCEumgErmEbwO03U2aR8738kzq8ln8e6bXlWYMWmZA6Z8SUk5U5ytyPeY0Oy1w5O50FO+wQ5jbtG4lK19L5BGehzb9sE19+JtFt2c8ZlJPvmwAqtSA06EWs3g+2aQnacwdbwAmLknuiZxaZ4FiTD6tLFvi+pBeenb/3mvvo4Yu3D5v1ZsP1axHpUiAo0iPyg41/dGiNgiQI5PXmdXkai92dkVItYbZ6YpVZWLrrKFSOynBip9W6U/7LwViqZ8SykRWpcR8BqJNlmJCZp1LLMkIxSAw6s39WHqUCo/mDnWTdKhwRUMaNMzvLh5NFZsaBIbD+rJ34jgsxtcLQH3IQbKakDoVZDmnpk+irA/fEjCkXlv+AawX+MEJQJcaFEY8bWAJdMgYxyESn5PILNumUqJNVVA4EG7OXlx8Bf3T2QyRuh0X2P5ad9pCQTcjtqDI3UwTMuReIeaaKagb9u6B6VVi9Wg1YRUhkhH1g6NKFf3gD/2gAYz08YVd5AdltDfDS2d2QIrH6DcNcwUjLHc+aC8AMqLrW/4EwesBoligUTCgc05h52IH9gwu6+ERwBb+9pkc0IwLJNWHPXIyrUIdysW2POd52gopIZjtOSpgzOI2NToVAmwD0D9osmvvZSxcCXtr5wA08627Ah0yHZ74D3ysBNXokR8XQ8q2SQM3gQbZtAPm1AiZRyNIUawZGFl5qIRqbBdk4Sndjy1iviIymzIquXldirWRXDzzdOZr63q8J66OqOf+2yL8be+nMr3fry91A9NlRjvKT9tx88Pt6Djdaps0RZxQRZmCzpbHrMBV9b5/YM/dn7tSCT/cNTvpauFdasR5xkkCaS9n07Kj0mIKm+GbujP5OQ/vI8Ofyomhx0sOmxhU9W6wYp5uOO12qB3guik2TuI2QPXmwpXLGnjSMf3RRdO1Hz/QNneMt7Iqmg5QAAAABJRU5ErkJggg=='] ['Twilight', 'BIAAAAQCAYAAAAbBi9cAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAA6lJREFUOE+VlF9Mk1cYxj+Kc3+yXWimFxuk2zTIn4bQFkppF0hDNmBpBtgKixhhQZAhbSkFBp1uZWg3ZLRMxFKE0qKtrMy2E2ztn2+1tLQgbuJiorvQ7c5pgplZNjfmePZ9nwtZMm52kufqvOeX5zznfQ9B/M9l/8CXPP2R/6ajy+u0amZeoI8D2PpfTLqMlZQpT9vE2fPOc9l73302q7rs6Sz5K6zM3ZuJzD2EVf1VytejC4hNXoWj2/vlF71+FgVKIsZVHrbnEzLoPkYOqqtPNm7j1l1J4R9Y4wgVkOR3Qcvrg+uNXmTnt9zfmdcUFRd1XqQhC+eWMXP8MiwKdyUDOqMLEG49qYtYlhA+vQi7zocGmQHFYi2UnM9wq/RzNEsOQyDWMBIWtjNurjivw2ucg+toyM+A6LWZU72vvsqwFjwVZwrmrEvoq7DBLDDiltQAobidgeRRUipMTA0t32AU3hNzD7zGSANBZMi2UFe5nyZohrREB9dxEnMTS+jgnUBYMghv2afrbhhHb3aAnFxkQMHhOALDid8p0EHiKU6VklvQil0UiJakqBsf77dCmTmASPEAhoqPIEN4CGmCJvAkauzKfw/5pRr4J+JUTtfo693zGSM7iBdzan10sE9gh5AragNXoEKtvB+93ZMY0TthGraB92oJVlYewDTgQJ96DKTtiStXb8jvNoafIV7i19+lndC2X+bXPyqXffj4kmV+PYexY1aQMwnkv1YGWUUljryvQ0/dqfV9+Vs9zVTYLILKZ5UGsXMbb2/llJaWCN8OnzNMrxda9JNYjt+ENL0RrQol0nekQVtlRHA8gsWpZQhEmrviws5yIpXfcG87t+52UpY8NZXN3lIjPRiOReZxfugCA7s4EsCN727ArHChQiKDYGchRrumELbFEbQmkFvQ+ofg9TYX8Xx2zfnkLDmHbgM2m00M1tortQf06FC2Y2HqGgMjvSR+WfkVplYPzCoX3EOziDmuwjMSRk6BajVP1PYT/fzb/j0nZ7tmN+n3mUlpUTmCo1EGFHJE8NvDR/g+egd0fj5LDN6xKHo6bOAL1D/niTTRDUd2rMW13VBj/zFu/5YZBaYBp69j0blMPfs8zhj9KCjspPNZ+6fjd28IGld4MgIn5x/HJr9ByJRYDz5oS2B6KIT9Nf3IEaj+pCBrXFELOTERZm0Ichy+lHy2czZlpv+y80JfmILFVwPDsTvmo26SJ1I9zBU1/UVBfqAk35ujpb+RpL8BJjxIUjyXvSgAAAAASUVORK5CYII='] ['Rainbow', 'A8AAAAQCAYAAADJViUEAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAA3tJREFUGBk9wV9MG3UAB/Dv7+531971aKGMlr+OwjoGBUZwRDrRBJwj0bHEmeiS6Xwyxn8x8UVNzHAPPvliFhMzsy0m8uDD5h/QZWoUNxYMBoZbZCBjZTBoKRwtLde7cv9+bg/6+ZDnzk6C44lw6f6whdOnETpzla+0803RMD3ZGSH95V62lzGQtMH9M7MhfpPUyIX5HE1uvNXDaCQgtykB70cR/4unrn3aqzYkZt7v18ZfezyTkfy0HlJ7FMWKEBJFpYMSVq7bngMlGvvc/OTiLzRYLp8K1waObaS16MDIRfupG9c6SuwCsSt2kJ+/B+3HMdC6MBofa0N1a2sVJTWj02mh4BFCCpV84jN4oHyX3KYEJAi2BWYR2CkPmMlBiOgwE0mYiymo1Qu0Mx4/8VLVnrtnF4VxfuCN9z5mDBA9FJt7mzDe3oXkjou69CqoxkA4gC9xQAggankMa7uTm3m32SLKD+Sz6XXGGCDJAv6j7di4MzqBo199Adk2EIqkQGQHDy3Ij2Q+bHr9g3UxyFHLdFyvJHAg+J/ipYgdjuMyzwELCfRsTWG/NQEwhqCVC0YLy/qKGJzmD77w9pHSoFyjbWWxtjAH5jIIHi8EKkCpq8JteCD2H0F2u4BwZhE+x8BEWbt6i6df8kr/s0+H/HKMc1yo02MYaG9APjGLxJ+T2NxYRV7fxu66GqjwYyrn2AG7YFGw4FygeYiXjva/KoipxoaKGPY1N+PJfRHEauvQaIj47vsLSN67i87ew6hOLGFeTS38FO45XhR8lQlffS0tmGViwbmCdKEb3tJSGLYLieMwMfQr1tZSqOzqheCVkDWIk7i/vvJ7WdVVxd96XWBU4kzb55qOiZvqJazmCxhLGzBFiqbnuzD71xyij8bxEN/XzXccf7PyxJ6+lkxuwknnftP4vorBd9O1mXBAnsbfaQW6VQadcWC7gmiIH0JlrBWuw+DYgFyiSGqu+O2NjZllPMBJRUevuH4Ipu1DyOefrS6RzmQN211iFGUtzSAcD8dh2Ll8cyStai8vra/8MQhgEADvjx/bX78c6rgT1ddl722/btSelEz69eaWoZqms1kwrGVt27xV1I1zgdWfRw6Ww8lmswQAo6QR2dnM6JC6HT3PEfvctjSsnx+3J1uob6qt6gAtSgEu4BbdV2KO80T3O0QQBFiWRQRBwL/txI3OlzkSKwAAAABJRU5ErkJggg=='] ['Rarity', 'BMAAAAQCAYAAAD0xERiAAAEEElEQVR4Xm2SW2xURRyHfzPnsmcvlO4ulN1uF2sLrIpdJNS0KUZFUq1t0AiKkpASbyQSjRKENEGrPuCTiUoTjSENKAnFYKokbZOmIBaoTRXB1AjbWmrabmVpt3SvZ899PFnTxAe+ZF7+D998mf/gbmwt30131B58YM+WTw7vbTnW/+oTHZda6490723uPP1KY0fna40dh/Y0fFz/4pq3XRFEsATB/2i71EauvDcplHN173p8of2gnI8KPHLxm/AEqwgIARUEeywyS1dVPZ+9kJ6OHdB/uzF2BmcYXRIdHxkhO/0vR/e9+c4p7+pIO+92+wlHaGE+QV1lYWpLCe90kdKVTvJo80rqDTic4nJfk7c62kM3rltfgQpSLGOM4ZfR0apQIPQTpSR04uhVqhUYSkoItLyMVFaEIjNENpTg8ZbVyGYK6PpyHIYGBhCmLiYHZ2NDzxZlpwYHaX3V2mMet3sPpZSbjc/B5y+Fw8GDgWEukcbURBLR2jB0TcPpz4cwO5aBBQJuWSnsbC09eeN50tnZSYy0s6p5V+MwIVghSQ4iFwqQHBIIIcVjGEaxXtd1XO2P4dr3N6EqCvJyFoqmgvqDlqZqp+jxD4/z8etKGxjxm6ZJxmIxnB8YwNDQEGITE5iemQHHcRAEATYIVPvB8ZQRQu05D45QGPNx2PYNNFxWV21y/h0AiCiKkGUZcwsZnDjTg7cOtuOr098hYxLYQJIklK8ps5hoaAyM2ZeAFwRQEJi5FEclT/BpxZBKFhdkQimFx+NBTbQG+1pfQFZ34tZtFd29PTAtC+N2dU9vH/t18sKCwPP4r46DQ3QySzcGKBGERzRFpYl4CkubPdd3Fj1nu5GduAxvdQNIPgNV1zBw/hy6+y+D510xUZQYzwlM5CXT5iID+5RailLNDINN/ZUCoQTLlnkQj8dx8uRJW2DA7V2F6H0RGJoGt8vFgqF7c2vD0T4wMANgd0yjP2Mqb+Ty2RkqMrhhmbh+JYnk7TSWl/pwuP0DrIvWoX73EWx/LIIV3lKIgoitT21Dy7aWPzU125/JpbOLukrA8U1ly8uGwxWVz1CXwOvE0qHIGq4NJ4qPHApVoKurC4defw6bKigCwfLiRkMBPzavL39w5/tPChk5vV+ZvzVHUknm4DhB13RKeZ5LlthlzDAQG00jkykU/5VTYKgJiTANE6LkhKIqTNW0nKqpvYauj89PzX5jcqxG0/WmeGK6bj6V+IHPy7nfV/hWbS5kM0gnC5iMLWBjXfhnAA0FRQGz0XVtzmJsZEHOH52a+uPirubtOmw2BfYmg9cSP2YsJ7uIbxlpfaitdk3l/Q/rlv7FnVzucmXdPS+1HtjyD8dzWCIvy76/Z6bY5MTs4tfjn7HBjwZxN/4Fq6rr1ZuF0oUAAAAASUVORK5CYII='] ['Spike', 'A4AAAAQCAYAAAAmlE46AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAsFJREFUOE+Fk1tM0nEUx/9QPtCD7z30nE9sbbVeXJJR6j8DkVsIhg6HTqSXnBHSMMEbEy+AgPwVQpcgNy+kKLc/lCgF09Wquaab67kHX1pulif+mHRdne3sd3Z2Pt/fOee3H4J8N/ow2lrj4H64OljRfEXBIZ/k/3lWquXIrQl2ROAVA98jOro2XKUtvV9Dpj/iFV/ppwvLVfzThEBZGRWh0S4hmFx+rId2ysmMSU6WAAUeMfDcdYe0gUrGdUOl7rZXBDRdRQtRp1PeIRlVctIzk+lHR6itJnwC1nkbgOXgZlhO3h6RY9rZKYT7W9NUKpUklUqRKjPDQADEjYTz3SLgzQjzMWua/5E5xLpQrqOX/jEzamTc4LqEX/KQRwRMBwfEDgnUOyXAdgk+1zr5e0w7J/vA15OfN28PW5SnZlRuVT3WeMia5oHW1AthawSS40mIjcWhW98HfF89Ifa6qb+hqAA6FA5xzIp/dVncYDc/hkQOiI/jBcctCegwdRJgsERWcszpZTrKU/3S7s+Ff4vn9UG4aWbGyofoaB60d05dDJuiR/8DcXMCpLY24GPsrlRWcxZxKmaqF0aCsDy8ArgtAVFL/Jc2C4LWBEwFNLCUbt9PZrpEiEk2VjbmMYIdm4TQ6Cq4RmYB02CwZAlB2ByBkHEVYhYcEmEreNZl4F+/C8F0+0vE2x1IL3qDsDgZhKg5Bt7ULAgHa+HVzlt4v7MHMQyHpM8LrlQzuNdaIfJCub+R0Z5DfNrAxsJAEHJbhXhue5nQJmS3t2D73S6suVK5XBKiYQMs4B3xSEbZ83xTc3ljq5eMmNts5/3d82/8jicQDc0Cbo8BjiVyQsez4rYkeNRzfqfadUYgEJBRFCVRKBQS0tTUSM7BxaauUelyenwunnZ+SnhXDkKG0EGgb+5g4p5dpa5TFEkk1bmfQSu8/TfTXs+Z8UbptgAAAABJRU5ErkJggg=='] ] not: [ ['Plan9', 'AwAAAAPCAYAAAGn5h7fAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3AoYAzE15J1s7QAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAACAElEQVQoz3WSz4sSARTHvzMjygpqYg3+KIhkE83DKtKlf0C9SrTRuZNEx0VowU6CuSeJNlwwpEO2kJ6SQBiIUAzFjRDF4wrjKosnGx3HmdehFDfpe/2+z/s++D5gU7IsEwRByICIiAEAIiIAYAFAXsjYVr/fLxMRNVvN+prJ5/OA3+/XERFNf02JyeVyDx0OxyvLNQsnimLKfcf9KRQKXQAAnE6nlf5qMpnQycnbP/kAoKoqsSwLAJhOp+AAwOv1otvtpqxWq73dbt/r9XqvEQ6HUalUEvF4XLd5IpvNZqlerzd5nlf6/f6tTCZjBACk0+nb+XxeW4UrikLJZPImAGA0Gq0NIqJyuSyyANDr9Q5Wu1utFvR6/SULAI1G4+vK8Pv90DTtGwsAJpPpaGUYDAZ0Op3PHAAEg8H3tVqtbrtu21sqyxuRSOQJk0ql9IvF4r7b7f7pcrlejkaj57IsH58Pzp8dvjhc/lsBk0gkbLFYrFqtVvd27+4qOk733ePxPDCbzVBVFfP5fCiK4rvhxfDN/qP9wSasGwwGMv1HiqJQsVg8ZlfTHMepkiR1t05gGJBGmM/nMBqNj9nN9kql0lNN064ARISzH2cQBAGz2ewLu2na7XYLwzBbvxYIBBCNRrFj3BmsAZ/PZ+J5/kOhUIAkSVeA8XiMZqt5efrx9OA3GfcgvyVno9cAAAAASUVORK5CYII='] ['Neko', 'BMAAAARCAMAAAAIRmf1AAACoFBMVEUAAABnUFZoUVddU1T6+PvFwLzn4eFXVlT/+vZpZGCgm5dKU1Cfnpz//flbWljr5uLp5OCalpNZWFb//f3r6+n28ff9+PRaVVH59Pr//vr38vj57/Dp7eyjn5zq8O5aVVJbYV9nVFhjUFRiWFlZVlFgZGOboJzm5uZhamfz9/bt8fDw6+drb26bl5j/8/lkX1z06uldWFS5r61UT0tfWlbDwr3Ew76moqNRTU7Mx8P75OpeY19pWl1XW1qzr6x5eHaLiojv7+1UT0xIU0uzqadVS0nV0MxkZGT5+PPk497///ra29Xq5eFtY2H28e2hnJignJlUUE1dXV2vrqxkY2FkYF/m3d5vZmfDuruhl5aZlJHx8O75+PZWVVP29vT/9fTj3trv6ubh5eRdXFqTkpBOTUtqZmX88/RMQ0T78vPEvr7HwcHDwsDq6ef///3Gx8H++fXEv7tZWVedmZZXXVudnJp0c3FZU1f79fnb1dlXUVVjXWFrZmy8t7359/qLj455e3q4s69vamZjX1zy4+avpaReWFz/+f1NR0vu6Ozp4+f48/lnYmi8ur3Iw7/69fHz7+xbV1SZmJZVUk1ZV1zq5ez++f/c196uqbDn4uj9+P7z7vRVVVXt6ORiXl/OycXHw8CPi4ihoJ5aWF3/+v/k3+axrLOsp67LzMZYU1m2sq9dWF5WUU1WUk/Au7eYlJGqpqObmphYVV749f7p5Or38fPu6OpiXFz38fH79vLz7urv6+hhYF5cWWKal6D//f/Z09Xg29exraqbl5RqaW6kpKTq5uPv7Of/+PDj29D//vP18Ozs5+OloJymoZ1ZVVJZWVlkYF2hnpmblIyspJmVjYKQi4enop5STUlRTUpcWUhqY1BgWT9ZUjhcV1NiXVkkhke3AAAABHRSTlMA5vjapJ+a9wAAAP9JREFUGBk9wA1EAwEAhuHv3dTQAkLiUlJFJWF0QDLFYDRXIMkomBgxNIYxhOk4wwCqQhQjxgxSGIsALFA5BiYbMZHajz1oJlx51sBJpf6Gd3zONcrqm/r1W8ByK0r+XV1LXyOLLnjW6hMGpu0u1IzPSdO17DgrGC6AadrVodGcDQYbhguP6wAvAaC0BRZQalkUQ8UQDz5tAof0XbejOFcV5xiUoCfjj3O/nf0ZbqAMPYmzU18KSDaRQ08qnfw+B2JNdAEQt2O5vctUGjhoIBU4ygPsj2Vh5zYopDK73hsirdkPTwGCbSHpiYFwYVVC/17pCFSBeUmoqwYQuZtWxx+BVEz0LeVKIQAAAABJRU5ErkJggg=='] ['Madotsuki', 'BQAAAAPCAMAAADTRh9nAAAALVBMVEUAAAC3iopWLTtWPkHnvqUcBxx5GCZyAAARERGbdXJrRUyGRUyYbY23coZFGDRFGEYfAAAAAXRSTlMAQObYZgAAAGhJREFUeF5Vy1kOQyEMQ1Fshzd12P9y61AixLX4yJFo1cvVUfT23GaflF0HPLln6bhnZVKCcrIWGqpCUcKYSP3JSIRySKTtULPNwMaD8/NC8tsyqsd1hR+6qeqIDHc3LD0B3KdtV1f2A+LJBBIHSgcEAAAAAElFTkSuQmCC'] ['Sega', 'CwAAAALBAMAAAD2A3K8AAAAMFBMVEUAAACMjpOChImytLmdnqMrKzDIyM55dnkODQ94foQ7PkXm5Olsb3VUUVVhZmw8Sl6klHLxAAAAAXRSTlMAQObYZgAAANFJREFUGJVjYIACRiUlJUUGDHBk4syTkxQwhO3/rQ/4ZYsuymi3YEFUqAhC4LCJZJGIi1uimKKjk3KysbOxsaMnAwNLyqoopaXhttf2it1anrJqke1pr1DlBAZhicLnM5YXZ4RWlIYoezx0zrjYqG6czCDsYRzxIko6Q/qFaKy0690Ij0MxN8K2MIhJXF+hsfxJxuwdpYGVaUU3Mm5bqgKFOZOFit3Vp23J3pgsqLxFUXpLtlD5bgcGBs45794dn6mkOVFQUOjNmXPPz8ysOcAAANw6SHLtrqolAAAAAElFTkSuQmCC'] ['Sakamoto', 'BEAAAAQCAYAAADwMZRfAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAxVJREFUOE+Nk19IU1EYwK+GQQTVQ39egh6ibKlzw91z7rn3bvfOmddNszl1bjKXc5rJJGmBUr7Yg9qTD0IalFgRBEYg6EDQQB+GovQyQgiaUZsoLcgHMcr069w7MgcGXfi453zn+37fv3MYZt/n99e76tzVj4JN/hP79fvXnV3hnNabwUBjoOHcgTYOu/JQspgTzsqKgn9BfD4vkWTzur287PqLVy+zM+yePB7KsRXLywTjnSpnZctBkPCdW8ccDuU55vBO8RXbkC/oP5ph19V5+7LIky0OY1BKbZEbLcFSt7u6pN7jLmltCVrr3DV5jY3+KovFEsccB1KJNVpefe10BqS2tqqO4/AuphBB4L/LkrRqNgtJs1lMypLls1kU38mytMLz/E8VIlutqVqX6/weZG52OttRXjbE0cP/FYLRlpVjDXuQ/r77x2XZPKkCHA4HBAIBkCQpAygIAvh8Pu2MZgO0Lz+QSa/sQfwN9RfpVN66XC6Ynp6GhYUFGBwczAC1t7fD0tISxONx6O7upgHILmsqvLcHodOggfiV/v5+SCaT4HQ6IRaLgdfr1bIRRREmJyfBZrNBNBqF+fl5sNsdgE2GiAbp6bmbdbXC7qWQbxMTE7C2tgY6nQ5SqRSEw2ENopaoZpCXlwdTU1NaoECgCbgiU6y8QH+ECYWaTymK7TWdys7MzIwGaWtrg42NDejo6AB1WjU1NZo+FArB2NgYrK6uQrAlCASxn2z6wkuMp87VIAhkE2MEAwMDkEgkYHx8HBYXF0HtkQpRy1BLiEQisLy8rPVNKSsFjEzrXH4+z1hlS4xDhKadNu7t7YPR0VHweDzAEVWfHru6HxkZgeHhYVAURYNjkylVWKArZjjMzqmdVi+QCsLUkQiEjvDvncEkvU7/qQ0Vgukeo48Go87IiCJnZNmipxiz7wXEbVDnbUxQOgM12h9n6qTq6NvapRdtkwaP0XK8RmPuYSbxYfaQ/sJJhjfknuFRURUi7AMOozcCwl94hLZp5F+EioDQVwqYI6jomZU1NFtM+rOSxZjVazcyvwHr/p/Kws1jegAAAABJRU5ErkJggg=='] ['Baka', 'BAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAA0pJREFUOE91k3tI01EUx39JOpA0H4jNx0pbD3XTalISWf8YFlEgldqDsBLLyqjEKBCiLLWiggh6/KEV1WZ7OaelLZvDdDafNW1JFraWe/32+01FrUZ9uy4ylLpw4Z5z7/nc77n3HIqaMRIjZJyEcNX+uFCFeGmI/GZciEIsCFJUTvoAzDz+1y7K76MSwhX5hXl6z+WSbrzU2KB8YEGDwgrTaxZ3b7xHcaHhR3xw7Z5/UviB1ReP5XSg3+TAqYJOxMzWISFIC0GQDomhTVA9skCnsaAwp/vnMq66dBokNuBR9uFd7T9Z1zCunjci0qcRJUVdoJ3DYOhRnC/qBZ+jQbfeCc+37yjY2UEg0iwvJE0k9l8Z+8xqHmTgot0QLdQgTaQFQ2AsOzlHvOu1S5pwOLsHHo8HjHMCq2MazNvTlByKHyrJLDvdR25jMWRxYx5HjeMH2r1BDOOeguRua4OI14jx8a8YH5tA+al3EHKlW6mYOapb2oZBOOwMbEMseAE12L+jjUh3w+VipyAZ65oxn1NP/GMYGR6Ftn4Qsf7qa9S82Y/l/X122G0uL2TbxmZEz1WhXW8mUol8moXu+SCi/OoQ6VsDh3UUwyQ1k9GOaI5MTkX4yWTGHutvgI1F28sviAlRgxeoRm62HvsyW8En9pZ1TYgi6TntoyQtFm86rVgUoJZRvDnKMmXVAGxWmkAYOBwudBqGcHCvHulrGpGT2Uy+z4yT+QYsCXtCUpp8GxbKhx8gDK0ro+KjJGvzdjfDZnN6VdisLD5/JjArQ2zW66PJOj2lEZtStaBphkwah7K6kMJ/GEulp1bMWhAmMbTozOQRaWRtfoZVgjo4iRra4SYgGi26TwjxVeDKhR7Y7U606ixICq9tr7hd7+OthRWL7yUnJ1WPmXotqLhpRICPHCePtuFV6xdUPTAhcWEtRHEqfHpPyto4hPXLXnzflSEJnFaN3OCKDcsFsrEntR9RUmxARLAUgT5iBPuJsXWDBj0dZjRU9yNV+PTbpjTp9OA/pOSk24nRkXf1J462oPxcJ65f6ULlHSMulepRerYDgvj7A0cKpNz/tyTZqbzXO4t0ZZGQJ34RH11lFHIlA8LIqreCCMUZRY3cd2bwL/5/RmjNSXqtAAAAAElFTkSuQmCC'] ['Ponyo', 'BAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAuNJREFUOE+Nk3tI01EUx39BTytConQTt1am07m5abi5KT5S8z2dj1yOEMUC7aUgIoimlmUEWX9kBZGWaamEmE6U1BI1XNPNGTrnHs33IwuSXrL4NgcJ0mNdOHDh3PPhnPP9XoKwcroJYvMQiRSicHCQKCgUyZC9/T5rNet5KUFs0zCZbZMsFmZ9fTEjEEBDp4/KSSSb/4JoGIyWaTYbiykpWEhOxhSHAzWD0aqkUGhWAcVkW58xlvuPhfh4zItEmOHxYDR3MhcdDaNAsKJydAz5IySKRNjEUmy88vjOVaU8F0iPCqCNjEBHkC/UYaGYFwqxmJoKLYOhkxPElg0QsbNtTlmox9yjRD9UCbnoOR+J/lwRWtOCcdXfDc2BPpg0d7CQlIQZPh9KKlVkAQjJ2x2zmOSsQu7hpzUJfBhLjsNQmADjxcT10Bcl4rE4EHc5LjBEhEPn7f1WTqXSLQB/s1Tp7vslsoIkyPPiMJAbi86McBguiaHKjoEqR4jJy2K0nAxApzMN5iUGrclrKVaz2fUvuF4tRbxDKA90w5VjTFyLZKHpTBSq4/1QnxGB2qxoVIZx0JopRCPHFSNOThfWZzfrXDcZEowH4iA05ATg68hDtBaL0HAuCm3lJ9Bfcx2fFNUoi/DCjRgfNHHd1wCZA2TyXjNkE6F0cBDpPFiojeNi8EkJdFoN3vXch0nbBJOhDd907dANv8JITxNqziag3ZsJbUDAwLin50Q9QWwl1qSYoNOVvUcOoqOqAAa9Fu9H2/F9+B5WZLcwOyxFX18flLI+VASyMGVeoJHD+Tzq5BS1PoaKRrNT8127P74swsq4FCa9FKvqBqwaOiz3hdEuLKueYSyECT2LNW0eIfo3E/WmEbvnG1MUJnWdpWhDGDvxQXZHo+RR0uW2tnv+auPX+TvtJm7zKpaen/4y2yjBUlcxlvtvmvT16ZWDpQeoVv3/60F/NrHjTf4ugazIXtJ8ivjnz/sJ+yGQRjcqUdIAAAAASUVORK5CYII='] ['Rabite', 'BIAAAAQCAYAAAAbBi9cAAAD/0lEQVR4Xl2MXUxbdQDFz/9+9Lb3tkBLCxTKhzgoOOZAsokbJmZxDFHnd+LL4hKVzBgfNCY++ODbjDEaZowvErOM6HRu6hKZY2rIAOkCY4OSDTpFaAsrlJa2t5+39+NvjT7tnJzknIfzI98Nf/C6TuXdguWBd1q9rcb8/CwsZiu2Ywm4nDVo3VWLZCKDaDwJq9mCg31PgjAMKKUwmcyYvTbek9iJRDm6M/XswEDjwNz6plWW6wdZhjUAintFCEEhn0N04zYskljaDLaj8ar49oUrsYR6mrFJNj322w46H8y+mitM/ZJKZmyE4XAvjJSsazpyuSzslVZIkgWKOvvRgQ6Xrdlhqmds7o7bFZoLkctreKxf7GtuCE7IyUQjBQcQ8j/lvxCGQJZz0IoCVpamTtzfIh9nwiaIrCQyjNg8mq11oDLUhNXRJfT1Ozr3tS/PqpnQ80qRgjAmKIqBfK4ItbSLKoOZqR/6neLkENlSUAIhlktvEf+sD2rkm8nWTHtvZCGMVON1ePuaoBER31/MXGly1wSqq9Uug6FluYyWXJiPqFXmjd4Dh9oF9ZKKimYXRtYCx8lmMIDIxlIPGz591av0mtanF7FcCEN6iMXeox2wOJ0QJAmUAoRQaIqCnWAQY1/ewKNGNeQuYXkm0d2NC2e+wvmRr/Hx+6+8PHayrbDyyQBNDb9As3PHKDWG6MTM23RoeJAWsqeoWvyUUv0UHf7pBB0fe4OeeXe3/vmHbx3+8dwIGJ4IsFpMMFe0fbtAn+nwZePr1u4MBK8XIALG/Rt479wYrs2vgeNNAMNgMbiNzybuoKVvn+Gs9kbr6qpBfJfGYHFIkJUCoGwfqcoMX/b27EGhwgOjoCADDlP+CA51ugFFRzoB8FYNaQ1oqKD44+eNL+wNj7zJGQSIhe8+jgQ9thk+27v/KRY6L4FSCkVOwtlQj6P73Qgt/o1ERoKt4iUkE7+jrZMHyzIoK9cOBFfT4LbWAk+0a7ZLnvqHcTNdACgFScfAcjxEdy00VQclHGo7dqGeYxHbvIo6hwhSghCehb3G5p6eW7VxXC5/xGWToMgrKKoaCnIalI9CIARasQAqloMI/x4BWrLLYwE1AEPTwCGHaGjz7pw/leZUNV8wNm9BLy6CxsvxZ1kMbaY4TKIIXlNBsynoVjvAC4CuAoYOVi+CMfLYCUfg95tPHuzZB0YtKzsb58RMucWE/fZmhCbdOP9rNnLnxko6GVoB8lFwyVVw8b/AyeulHoJyN4Rb19dTFyeqBlu6njvfsWcvOJvLs7DMmw/7bvpeE4pU2OIcgcqmp4fGAgt2Txwvqr7lTp5V7LquZxXC6+BqEvGcY5pyjaM1tffJbk89NE3FP5VQ6y7a+paZAAAAAElFTkSuQmCC'] ['Arch', 'BAAAAAQCAMAAAAoLQ9TAAABCFBMVEUAAAAA//8rqtVAqtUQj88tpdIYks46otwVldUbktEaldMjldM2qNcXk9IWktQZkdIYlc8mnNUXlNEZktEZlNIYktIWlNMXktE7o9klmdMXktFHqdkXk9EWk9EYk9IlmtQXlNEXktAWk9AWlNEYlNFDptkZldMYk9E4otg/p9kXktEXk9AXlNA4otclmdQXk9IYktEXlNEwn9YXk9IXk9FFp9o3otgXk9FPrdwXk9E2otdCptkXk9E/ptkcldIXk9Edl9IXk9EjmdUXk9EXk9EXk9EbldIcldIjmdMmmtQsndUvntYyn9YyoNYzoNc0odc1odc2odc6pNg7pNg9pdlDp9pJqttOrdzlYlFbAAAARXRSTlMAAQYMEBEVFhgcHR0mLS8zNTY3PT4/RU1kdXp6e3+Cg4WIiYqMjZGXl5mbnqSnrbS3zMzV3OPk7Ozv8fT29vf4+fz8/f7SyXIjAAAAmUlEQVR4XlXI1WLCUBQF0YM3SHB3a1B3l7Bx1///E6ANkDtva0jKbCW2XIH1z2hiZEZ4uUgxo7JedTQye/KN/Sb5tbJ+7V9OXd1n+O+38257TL+tah3mADAwSMM7wzQWF4Hff6ubQIZIAIb6vxEF4CZyATXhZa4HwEnEA+2QgoiyQDnIEWkjVSBBZBqXbCRlKYo8+Rwkyx54AOYfFe7HhFa7AAAAAElFTkSuQmCC'] ['CentOS', 'BAAAAAQCAMAAAAoLQ9TAAAB5lBMVEUAAADy8tng4Ovs9tnk5O3c7bX44LLduNO1tdDh7r/eutj43q2kocX23az07N+qqsvUqcmXl7331ZXJj7r40o/Pn8T42qP63KjNw9n21p3Y387Ml7732JzR55z05MSxtMLGn8TC4Hx8eqt8e62Af6/B4HnG4oPC4HzH44fBf7LCgbOkoMTcsrmtn8PWqcfFtKrj4Jvs2ZOz2FnMqLXT3KfY5p60Z6NUU5XRuqHzwWSywqDn3JaiiLWahrWhkry5zJjRmqm1Z6P1wmb1y319fK632mK5cKi5nH+73Gu73Gy73W283W+9eK17e6y1yZS3aqRZWJdcW5ldXJplXZppaKBwb6VwcKV5eKswL306OYNPTpGkfK+m0kGpUJWq1EnEqIuXK3+Xh7ahP4qhkryMfK6BgK+CdpGMaKKMa6O9ea2+eq6+oYW/eq+NbqWVlL2Wlr7AjanA4HnA4HrBkqbBlafB33rCgbLCmKjCxIzC1mSs1UytV5mtxIWt1lCuz2evWpuvXJywxYzHjrvH4oXIjrrN2HXO5pTO5pXUlYnUlYvVl5Hb0G7e0XTg03rhr5fpzHPpzXTp0Hvtz3/wrDHytknyt0zyuE3yuVHzvVr0wGP1x3T1yHf1yXe0ZaL2zYP30o730pD31ZeRIcF5AAAAQ3RSTlMAFBkbHEhJS0xMTk5UWWBsd4SEiIiPkJCVlZaam6CjpK29wMPDxMTFxcnK193e3+Dg4uTn5+fo6e/v8/P4+fn7/P7+J4XBAAAAAOBJREFUeF5Vj1OvAwEYBb/yGlu717atLW0b17Zt2/6nze42TTpvMw8nOZCAmwUpiIY6c5IiLi9tPX64GairqszHQ4X2VB64v1Cs6PxMPJSdHM777s6/jyaMRGiRLyyrb88OpjZ3CzAXrm1sqzSNNeN7kVBPNgB7cG51abE5l9cXDces7emQ1uadHhutFUg6gpPKkSIqQGavwz7r7O/+/3t/rSdjI9XDM3qz4fr3B/3iA0aJTG9x71+9oR/PLDwUe2wm19bly+fTIxHyEETatbPewGEw6Mk/tKZCEqSQQUlIHB/QNBEjjVN1AAAAAElFTkSuQmCC'] ['Debian', 'A0AAAAQCAYAAADNo/U5AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAZ5JREFUOE+Nkk0oBHEYxv8fu5GQj3JwcaDkIAc5IpR87M7MKnIVJVKclaIQ5Sy5OLkgR7n5OigcSNpmd2c2Vyfl4KT8/muWiVU79TTv+7zv837NCBF6PG1X+NpZyEYSD9mIc+tHnBPe23B9xKrCuTmbQA/JKfABrhBswa1hH4A38IwfOxPdX1qcjiCQxO5NyrjKV70TnSbeRPwJvGN3i4yyqnEucPY8ZZX9GSEgGK+RvFfyjk2VKZxzBNG8wJWWgh/xtDOeUXZ7Slr6TrSLYL9N4SMgYTTcwdc2ArvJcElhSVcM6mCNSV8n9hA59yTU5UWMG6HIbLhIWlglgWiC2L4Z79qTdo40D6ISuOWwKCWHyk9Fv8ldpUHOuGTuynwSBUynddPdlbEosVpP9Eu4FnOsRzUYNTsdmZN/d5LDiqM0w+2CMdAFFsFGWgfXxZnheqe/z+0puwEM0HHYV3Z9Sgz8TEz7GkQvpuJ/36ggj2AaHLrSlkULWV5x+h2E8xkZL16YVjGNaAUscfZ/f6c/k9ywLKI2MMcRWl0RLy007idmRbQJ7RIfDAAAAABJRU5ErkJggg=='] ['Fedora', 'BAAAAAQCAMAAAAoLQ9TAAABPlBMVEUAAAApQXIpQXIpQXIqQ3UpQXIpQXIpQXIpQXIpQXIpQXIpQXIpQXIpQXIpQXIpQXIpQXIpQXIpQXIpQXIpQXIpQXIqQ3QpQXIpQXIqRHYpQXIpQXIqQ3QqRHYpQXI8brT///8uTYMpQnM5Zqg5ZqnS1+I4ZaY4ZactSn8uRnYrQ3MrRXgsRHUsR3s8bbM8brMtSX4wUosxVI01XZw2X50vUIguToQvR3c6X5o6aKs6aq08Un8qQnM9VIFDWINJXohKcKlXapEqQ3UvUIc2X55bhcBdcJVgcpdhfapmd5tuk8dxgqJ1hKR5jbB6iah/m8Shudq3v9C4wNG/x9bFy9nFzNnFzNrIz9zK0NzK0t/O2+3P1eA2YaDU2eTb3+jb4Oje4urj6fHm6e/s7/Tz9fj3+fz7/P38/f3+/v83YaEa/NNxAAAAHnRSTlMABAoVGyY1SVlpeIuQsLfDzdHW4+3y8/b39/n6+vr4+ns8AAAAyklEQVR4XiWN5XrDMAxF75KOknYdZJS0klNmHjMzMzO9/wvMcH7I37mSJShsJ+5NjMT6umDoHyXDcI/2qJadh++P3cle1de+9yPe3/bTY92wzfzr7wGtP3JrAI72BZGVtcAdQlwHy+JS1pDbBE9qamZF3BYrjQxPEXwKc6dC8bXFm0QIpmt8kn0Rn093q82UCtK8oXZckwFJzuulV8bHkajPyXdbnJnARfDHs0trz+JQ+5AFvzp/L0+cL2qPAINUPrq5OC6p/64F/AMnrST+Dq/r7QAAAABJRU5ErkJggg=='] ['FreeBSD', 'BAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAABIAAAASABGyWs+AAAABmJLR0QA/wD/AP+gvaeTAAADXklEQVQYGQXBS2wUZQDA8f83j33M9rF9d7u4loaWklaDpkSo9KDGaIKUaGxshD2YSPRiuDVeTDyhBxosJCoa40ktpAkPDcUqAYVIpUSUPrAulEdD2bbb7e7ObGcfM/P5+4kwKDvq6yJ1FYYcvb+YAkqAHo/HQ7FYrFIoCiurq9ZXJ06YSOkA+kBzfX06bys3zHxS9EL0tXDVyZfefacqV+X/ZSJx5+qLbx98LhaL9RiGEZWlEsWC/Thd9q6Pf3vs2u6Orc83rFsvTwwfLf5obgywT1Vjh2Hh+rbNsnTssJdNLedK5aIrpSuldKVXKsnH4+Pyn6FDXn5tMef9O+3NvdkvP1V4+EYw2AoQ+KSx8dRYS6NXXnwovaItXduSrrkinWxGOmZWJi9OyOK9m1LmsjIz9IH8QUMOd3WfAQwNKCy2tJwbHB5+XasPaxIHmc4g7WWEZ1MquBiRFlJTf1E7+Tl/H/8asavPzTY1nWd2ZkMDRPeBeHPz5ojwsilEQCBvTSKunCF3M8FSNkBGVTHDYYrLj8jVNhDZ2SMa2zo3MTamaIC/u6Ojr3DtrOrvP0BpdATnyBeIhTxpR5ABUlKSUlXS1dWstbVxdz6hPL0l1quGqkLaKwNvVcjEXNRd/4mit4Z19DjefBEPyCKxgQJQcF28dBrHNDGTSZSezsjeff0hraa2Vs2vrvit81O4vj9xLJcC4ADrQA7YAGqBGsAql/EtLdFQE/L7dF1XZmdnSrbPMJfXoLDmolQK8gJyQBowgQhQDRQBD+hsraVhd4e5MH+/oExfvWLJ9q3/3S7qMpNH2hsS40kFS4EUUAMA2IANRIBXv4uzuO67c2PykqkA5YmZ6bN18YPi0Yoknxc4AsJPCMLVAk2BLKDosCWqs/PZaulkuxk9fekcUBAAQGDks5FT0W++3NuYuC0DVUL4DIEdlIQDAj0IRkigaMjArkFx0tf523sffrQHyKsAgHPhwoXLL+yP9/kePNhk5ExUTyKFkJVAUAiCFZrQup4Rv9ftuLV/6ONBYBVABQAArMvJ5MXW7duD6P62sD8UrPAFRU1TpeCpCnGvPZr7WW///v0jpw+VC9ZdAAABAAAAAMLo7drWrmQyPWG/r8tnaGIjaM05ujr16x/ZBFh5AACA/wGZnIuw4Z4A3AAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAxMi0wNy0wNFQxMDowOTo0OS0wNDowMOPVpFwAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMTItMDctMDRUMTA6MDk6NDktMDQ6MDCSiBzgAAAAAElFTkSuQmCC'] ['Gentoo', 'BAAAAAQCAMAAAAoLQ9TAAAB9VBMVEUAAAD///+AgICqqv+AgIC/v9+Ojqqii9GAgKptYZKQkOmPj/ddUYBgW4eVjeCTgfiWjO5wbJaZkvPBvepkXomYkNldV4Bzbpl6dJ+Uj7ynoO6Vi+1qZI63se2mnudjXYjOy+GCfaqZjvWlm/Pc2e+Oh7NeWIOWjfeXjeW1sd+gl+diXIfp5/KHgKnn5/F2cZx6c6ZgWoXc2e6dltrAvNu0scrX1eTOyujCvup4c5qpovVpY43///+6uPPJyPXq6fvm5vrz8/z8/P7+/v/d3PixqvmxrPSyrfe0sPO0sfS3tMve2/3r6vy6ufPz8/3d3fi3tM63tPO4tsu5tsu5tvO6tfe6t/Vva5KRjKy7tvW7t/W9vPO/vM+/vvPCwfPEw/TFwvTFxOfGxfTGxvTHxvTIx/TJx/aTiOrNzPXNzfXQzfnRzuHS0fbS0vbT0uHU0e/U0uTU0/bW0+zW1ffX1vfY1/jZ2Pjb2/jc2uSTiemVkLSlnvbe3PTe3vng3fzg3f3g4Pnh4Pnh4fri4enj4/nk5Prl5Prm4/ymn/bn5vro5/rp6O/p6funoPWsqs3t7Pvt7fXv7vzv7v3w7/nx7/3y8f3y8v3z8vytqPWuqPX09P319P319P719f339v739/34+P35+f37+/+uqev9/f6vqvSwrPQAR0dcAAAAPHRSTlMAAQIDBAgJCwwVFyAsNUFHSVBneH+Bh4mVmZmanKCxsrK2tr3ExtDW19rb4ODl5u3t7u/w8/T6+/z9/f4MkNJ1AAAA8ElEQVR4XjXNw5aDURSE0YrRtm3b54+dtm3btm3bz9k3Wek9+2pSYFwT8ibzE93hwAtdJqK3nZo4J9hFXbP+vFHOthV6gnGzstZq94wdCs4UCCDymQ2v7X0LdYoSQ0MIENRYzJbRlPTTHu73ZNAL8vivmVui98PpzuqffX0mIPHJGtOQenukteJ+aS3b9htNpDnT9TeZH1bHAwBRMhGpd6e6uNrLoRgxBKmsX47nBlp678ojpEA40fejcmW4e/No0V8IIPfj6eKgbEJ3ZUnzgE1OqWp9Q3VeWRAsg51f1dZ8c31RmAsc+N5JGbG+zvj3BzDCPrzMDC9SAAAAAElFTkSuQmCC'] ['Mint', 'BAAAAAQCAMAAAAoLQ9TAAACVVBMVEUAAADh4eEAAAAAAAAAAAAAAAAAAAAsLCyXl5dgYGCnp6eTk5N3d3fBwcGqqqq8vLzNzc3Ozs7Ozs7Pz8/Pz9DQ0NHR0dLS0tLS0tPT09Pf3t/Pz8/i4eLb29vZ2drZ2tna2dra2trf3t/u7O/u7e/u7O/r6+vt7O/w7/Lw8PDy8fTz8fXz8fbx8fHz8/P19fb49/j49/n6+vuPxlmWyGOx437h9NDr9eD6/fj////+/v75/vTA5Jv6/fb7/fnL5bDL5q+AxjeDxUCEzTyGxUaGzjyHxkiHzz6J0D+Kxk6K0kCLyE2M00WNy06P00mSz1OUyF+W2FGX1FiY0F6Z02CZ21ac0Wiez2yfz2+f2mOh4GCi4GOi4WKi4mOk12+k3Wul32um1Hin0nun4G6n5Gin5Wmo23Op2Huq1n+q43Cr526s4Hit23+v6XSw34Cw34Gw6nWx4IKy4IOy44Cy63ez146z34az4IWz4YW03Y217nu38H2625e645G74pK83pu98Iq984W+4ZjA4px0tzDA5ZrB8ZDC5p7D55/E947F6KHF+JHH4qvH6qTI46/K5LLL5LN1tzLL5bN1uTDL57DM5bPM6qzM66/N5rTP6LbP6bTR6rfS573T67vT7LrV7r3X68XX7MHX773Y77/Y9rvZ8cHa7cjd88bi88/j8tTk8djk9tHm8trn89vo89zo9N3p9N3p9d7p9tvq9d/s+93s/dzy+erz+O73+vT4/PX5/fT5/fX5/vN1uzB3vTD6/ff6/fh5uTj8/fv9/vr9/vx8wjV/xDmrMRH0AAAAOXRSTlMAAAECAwQJDzk/RUlNU3F0kpSVlpeYmpucnaKjpKWqqqqtu8LExMTEzdTU1NXY4evy8vP+/v7+/v6LaR1mAAABD0lEQVR4XiXI03bEABAA0KltW9kaW3eSZW3btm3btm3b/q4mp/fxgqKOtpamhrqaqoqykrQYABh+PVMU9fjE5Xp8o54kgPHN0EBHU2N5YXZykiua0HHd2759VF2Sk5IYE5GGsmCEWLV1kVWwt5O+3x/qpgsy8k4ja+cJl2/v5C22tlgCAHtw9TQSa4s+AzfPSm0BRNl9SydhWJzLC567KrNhgrNwHIJ5qTz/2f9w7Jw/DNqIjVr04exW0AEOXcN3Ab7enr9eDW2VTJgehONyc2Z8XP5YdD0Tcuhcc4/r45OjGX51TEjYPbh8THRPvbz+CHusgSZlT7rP8PkCwfQKaQUi9Igr6JsRBMFiWZgb/AHKElRzKopZJQAAAABJRU5ErkJggg=='] ['Osx', 'BAAAAAQCAMAAAAoLQ9TAAABrVBMVEUAAAD///////+qqqr///+ZmZn///+qqqqAgID///////+tra339/eAgICoqKjx8fGMjIzm5ubh4eGPj4/g4ODIyMiAgICSkpKLi4vS1tbPz8+Xl5eMjIypqanIyMjW1tZ2dnbR0dGamprFxcV3d3d+fn60tbV3d3dcXFx3d3epqal7fHxxcXF+foCnp6hYWFhyc3Ojo6SMjI5fX196enp+fn6Li4xERERqamqgoKFpaWmFhoeen6A/Pz9QUFCWlpeSk5SUlZWUlZaOjo+Tk5RHR0cuLi5YWFgwMDAeHh40NDQ3Nzc6OjpcXF1rbG0XFxdSU1NVVVVXV1dZWVlbW1tnZ2lwcHABAQEEBAQXFxchISI+P0BISUpaW1xHR0kNDg4qKyszNDU1NTY9Pj8NDQ1cXF4XFxhSU1QSEhIDAwMrKywtLS4uLi4wMDFHSElISEggISE0NDVJSktNTU1FRUVWVlhGRkYEBAVBQUE0NTZQUVJQUVMFBQUqKitWV1lXV1daWlpaWlw+Pj8bGxtcXV9dXV1fX19fYGFgYGBkZGRlZmhpaWlsbGxwcHB2dna844Y9AAAAV3RSTlMAAQIDAwUFBggMDhkeICMkKCgqMDIzPj9ERFBib4CCg4iMjZCcnp+jqamrw83W1tvb3ePl6Ojp6+vs7u7v8PHy9PT09PT3+vr7/f39/f39/v7+/v7+/v50ou7NAAAA30lEQVR4XkXIY3vDYABG4SepMdq2bRSz/capzdm2fvOuDO397Rw0Ly4tz2QAQPbcxuZ2E/STJwfxPhWgG355fRrVAIVb1zeP9UDLfiSwkAcADe8fn7tFxWuEXFRDoer/OgoMTRBCumj8yJwPBo8Zhpk14U856/HI8n0ZUtpZ1udrSzfVneA4roNKjdrwpcMRilb8d8G60+lKnrpWcn9bO+B23w2O8Tzfq4aiNSZJqzn5O4Kw16h06fPZ+VUlUHfo97+VAEb7rSh2UgDd4/U+TBlQY7FMj5gBIGvcarVVfQPVPTG94D0j9QAAAABJRU5ErkJggg=='] ['Rhel', 'BAAAAAQCAMAAAAoLQ9TAAABj1BMVEUAAAD///////8AAAD///////8AAAD///8AAAD///////8AAAD///8AAAD+/v4AAAAAAAAAAAArKysAAAD///////8AAAAAAAAAAAAAAAD///8AAAAAAAAAAAD///8AAAD///8AAAAAAAAAAAAAAAB5eXn+/v5JSUnKysrS0tJ5eXmqqqqxsrL+/v4ZCgknJyeHh4eIiIjo6OgZCAdOTk7t7e3///8GCwwPAAArKyv19fX29vb9/f0EAAD////+/v4AAAAGBgYHAAAJAAAMAAANAQAPAQAVAQFyCQV9fX2pIRzmEQjn5+cBAAAFAAAAAADnEQjvEgn////uEQjyEgnsEQjzEgnxEgljBwPaEAj9EwnwEglHBQJHBQNNBQIBAAB3CQR5CQSHCgWLCgWRCgWTCwadDAWmDAapDAa/DgfKDwjWEAgGAADh4eHiEQjmEQjmEQkKAADoEQgLAQDtEQgMAQDuEQnvEQjvEQkPAQAfAgEuAwEvAwE8BAL1Egn3Egn4Egn6Egk+BAL+/v5CBQJrB0muAAAAT3RSTlMAAAMEBAkYGhsbMTRLUmpvcHeIjLe6vcHCxM3P0NbW3Ojp6u/w9ff5+fn6+vr6+/v7+/v8/Pz9/f39/f39/f7+/v7+/v7+/v7+/v7+/v7+Q8UoNAAAAO5JREFUeF4tiwVPA0EYRL9SXIsWl+LuxfcOd2Z3764quLu788NZNrxkksmbDP2R7vH6GioLs+iffEzNXd4+TqPErUUpVqMOvwgdzMPn1rv5vPsVeufBTaBK/bH2FPvkEUuIG5jIIc+sHYn/HJ3dC/Hxuo4y8s44dzwBbFkisHN8bVIdXs6jb+H97aCwbHEIqgcml64CD7YllNkAVQC940MLYe5YzvIeQAXNrd19Roc5MdzfdQLUUKaUYyuG9I8y1g4gj6hIak4X5cBIT2MquZJrJdOqpY11ZpAiqVwbY/C7KY1cRCrZxX4pWXVuiuq/hs49kg4OyP4AAAAASUVORK5CYII='] ['Sabayon', 'BAAAAAQCAMAAAAoLQ9TAAABvFBMVEUAAAAcUaYdVKwAAAAAAAUABAwWRY4YSZYhZtIhaNYHDx0KCgoFDBcKCgoRMmYSNm0fXL0fXb8AAAAYS5gaTp8fXLwgXsEGBgYFBQUZSpgZTZ4JFSgODg4IEiIOJkwOKVIkW7EnXbQLGzUTExMKGC8LHjwMIkITExMiIiIPEBEPJ00QEhMXOXAaPncOJEgoXbApXbEcHBwwMDAEAgAfHRgQDgo3NC8AAAAHBwcKCgoLCwsJCQkaGhofHx8lJSUwMDA0NDQ4ODiRkZEICQocHBweHh4GBgYHCg8mJiYnJycpKSkrKystLS0uLi4ICAgODg43NzcRERF1dXUUFBSjo6O1tbUbGxsEBAMLGS8MDA0iIiIjIyMkJCQNDQ0NHTYKCQkoKCgPDw8QEBArMDkKCgkRERIREhMxMTEyMjISIz00Njk1NTU2NjYCAgIVFRU5OTo5P0c8PD0+Pj4/QURAQEBHR0dKSkpMTExSUlJiYmJlZWVnZ2cWFhZ2dnZ4eHh8fHx9fX2FhYUXFxeVlZWXl5eYmJiZmZmcnJwZGRmlpaWrq6usrKyvr68KFiq/v7/FxcXY2Nji4uLn5+ft7e0yif9uAAAAN3RSTlMAAAApKSkqKioqg4OEhISEhoa1tra3t7y9vr7S09PT09TU+Pj5+fn5+/v7+/v7+/v7/v7+/v7+70RY/wAAAPpJREFUeF4dyWNjw2AUBeC7dfYyorM6rx1exKltzLZt2/rDa/J8OgBVVlFDX39jcTZoUqCse251a2dvu6ccUtWlanLQ4Vpel+ThlWq1l3wEz58tx4dOt1dMlAJk9A5gMjG75LHwo46hzkwosGOMbejumoRvubC9EOrMviT0E0Us9fvN9dA6zxJCNv6+ECGsb6oNWsgmpZT9/UTUZo3Em6AW34guTL4jiAudiCM1kLcw8/SmHERfT1/eueBiDqR1GK1n9w+K8nglxYxd6QAML4ztXoQuj8YFgWcgqdJp8qzty26vaboCNIxBCshyQDKov0aXr29v1ufq1PwPx5Q7bCoh6eoAAAAASUVORK5CYII='] ['Slackware', 'BAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3AcEDi0qZWWDgAAAAx1JREFUOMt9kktoXHUchb/ffc1M7rySSdJMOknFPMRitLgoNKKI8ZHGKkgrjU8SitidimSh2UkXoQmoO1dGQSxJjdvOtqSaqlR0USEGSjVJGxuSmWR6M3fu4/93YX0g4rc9HA6cc4Q7DI+fpzz7PA8++2mxvZAeBZ4xhHtFcJRmXWsWvb36/OLcyxf5B/KHeYHy7DmGx1+YSDjmWTdlobTGMAStQGkNoLXS4tXDq7u7tUcWz49tA8jR8QUuzB5n5NTCV13F9JEo1JJwTLKuzU61QiOMcd0UDb+BncwQK3Rl15eNja3ui/Njq8aF2eMcO/XlBz0H8oO2ZUkum6A13WB99TtyzXlaCi24SaFa+ZFCzsG2DNnfkdbFjsI1APPhk+d6ujqznycdCxFozadYWvyMpx47wa+bPkGksKwUNnsk3TaCGASRXDZh5LpHXPPg4Rcni+3uYBxrtBbQghlscOVKmYHeEm0ZIZ9xyLffw41ND6VAa43SmjiMByzHYtjzwr9arfshxf5jOKlvKZfn8es77N2uks24PPfSFD/9Uvt7AtPKWmEU9d645eHYJo5tcKi/FX/zG+zmQxQH+rANk862DOW5N/hhaY64cJSa5xNFCgDDILZACMKYWAmh73HmzFsMlBQJ06LeiMinE1S3KzRCm5rXIIoUIoKIYCVM36urZFbEoiBLNMIhAE6/NsSB7h6SKZdL8xsUOnpx9j1KbTdARACIowArYe1ergfNT2i0mIbJys0GI6PT3N1/hJvrPxOFdRJNBQIy/FapI4Bpgohgcjuw+jq8jy8tV55MNBWI4ohS802CpizKv8q+FgALZAfYgSyAZtNro1oLaU1VvxCA029Oraxs7u/tKnXiNjn8HyKwur6lI++6vPK4V7IA7u+1Dyu1tr183ddNbkHuXP8/zEIYeFqiLRl6YO/p0bHJdflT/PD9qZa1W+ry99fcvlAlcZwUpuUAglIRYVgnDEIOlna4q0M/NPnuO1/PzMwg/045O/XeibUt5/Xangx6viSVFpK2jtMpvdyWCz+5ryf10clX3/amp6eZmJjgd441URWWJY8BAAAAAElFTkSuQmCC'] ['Trisquel', 'BAAAAAQCAMAAAAoLQ9TAAABjFBMVEX///8AAAAAAAAAAAAAADMAAGYAAAAAHFUAGWYAF10AImYAIGAAHloAHGMAKGsAGmYAJmYAJGEAKnUAJ1gAMXYAJnEAJGQAI2EAK28AK3cAGTEAMHgALXEALXgALG0AFUAAI2oAK3EAMngANoYALXMANIAAM4IANIIAL3gANIcANokANoQANYQAOY0ANIYANooAN4kAN40AOY0APZMANIUAOY0AO5AAPZUAPJAAP5MAPpQAQJUAOYsAPpYANoUAPpoAPpUAM4AAQJkAPZIAPJEAQpgAN4cAPpQAPZUAPJEAO4oAOosAOo8AQJoAOYsAO44AQpsAO48AQp0AP5UAQpoARJwAQ58ARaAAQZgAQ54AQ50AQpgARaIARqMARaMARaIAR6QARaIARaEASakARKEAR6MASqsARKEASKcAR6MARqYAR6UATbEATa8ARqUARKAAR6oARqMASKgATK8AR6QATbIATbAASq0AR6cASKgASqwAR6UASKcATa8ASqoASqwAS6wASKoAS60ATbHn4CTpAAAAhHRSTlMAAQIFBQUGCQoLDxAREhMUFBUYGhobHB0eHh8gIiIjJCQkJCYoLC0xMTE0NDo6Oz1BQUNHSUxOVFVVVldaWl5iY2RkZWZoamtsb3FycnR1ent9f4KDhIiJioyNkJGYm5+foqOkpqamqKmqrKytsLKzs7e4uLy8v8TFxcXGx8rO0NXY2eZc4XYcAAAA00lEQVR4XkWN1VoCUQAG/3NWtwh7CTsQJOyk7BaDxuxA6bbrxf32gt25m7kZqDRYxziooDV7+1AalMUavQh2AsEZoWvzigLun+T17/c8QiJZ7qu2QKiNmyZthdcR1/as353jIeU1GxMHo5XHdqPFeX8IaDMdHPYN6dRN7LR4qQewdTa35HWkyh+fbxERAMjwlAWJv3CPSKDQ+H7XvHdkV4Pua3Gtm4sPKIF/WV8dop4VKBw/NU33B3x1JbTt+XwhkJQoqRfWvHOy28uqH8JIdomR/R+s9yR3Cso77AAAAABJRU5ErkJggg=='] ['Ubuntu', 'BAAAAAQCAMAAAAoLQ9TAAABKVBMVEX////ojFzplGf1zbnqnHLvs5P10b3yuZv1xKrytZXvtJXys5LysI32waT0n3HxiVHwg0jxhk31kFn0h0zxf0P0hUrveTv2iU3yfkD1hEfyejv5eDLybSX0aR7zZxvyayH6ZxnxZBj4YhH7XAb5WALlUQLeTwHgUAHeTgHfTwD65NzdTQDdTQHdTgD31MfcTgLcTADcTQD////xt5/31Mf54dfmfE/dUAbeVQ/jcUDcTgHeWBnnflHohFvpjGbqkGztnX342Mz53dLgXiP65d399PHdUgrtoYLyu6Xzvaf76eLfXB/rkm/fWhvupojwrpTeVhTgYSfgYynzwa30xbL1ybnngFT31snngljhZS3539XhZzDiajbibDn77OX88Ovrl3X99vTjbz1fisGCAAAAMHRSTlMABgYGBwcHJiorMDA1NXGHjY2Nl5mZmZyfn6O5u8XHzc3X193j9fj4+vr6/f39/f08OUojAAAAx0lEQVR4Xi3HZVbDYBhGwQctWqzFPXiQ+36pu+LubvtfBKcN82/UEhld2vWXxyL6F92gbTPabse8hU/uHMx1SZoyyJWPTwq1Rs7GpYE9+Cg+OJcs1MHvU9y4fnrN31yUm18vMCIPjtw3QMndw4rs8ieVzAAcBlewpe1KM3uaBuD3Dda1BhWXAsi6AFY1a2SqifxZ+rnxWYcJDRkUS3fO1R5vwe+XZgw4D4L3RAJiknoXCVX3WeiUpJ5pIxTvVmg45pl5k4Ot/AGV2iqZBWgJJAAAAABJRU5ErkJggg=='] ['Windows', 'BIAAAAQCAYAAAAbBi9cAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAA+pJREFUOE+F0n84FHYcB3CWSsL9ojo/6ik64c6PnTjmSS0limmrpBm2G002y++xzXRz6zE0R4nbw+RnTj/WD4sbanLkkAe55ccYlyNme4SrO9u9d13PI3/saZ+/vs/3831ez+f9eb5aWsuqy2mjRYeNUa7YmtjfTico7jNJ8z0eG24NB9vvnDrvufzpq89Npnr8VjMddNmuRh9rDfp36mFg91oM7qPIc5JdbDJq3An/JfCu7Hl53W2lpS220pP2OuniN299jAYbYizSENIoAgbCTdrTKtxOJVdvGo8psUwKy7Vxe4ez1YEVudGP8YEZzyveInFJ6mZRHHqYazDspw/pJwTIuERM5JIwmUdGdyo9K7/BszGzzg6fXzZHGJ8KvzQqXKOpoIeZLjofWR++BPWyCEnPY4xFGEKWQcLjMjKmr1MwfcMYwmz/Y4KOgNki0V5k1dkjUWCK93Kp2PMFFawos8cm1gZ2GqjLXktL4mbQPHLQ4B9ZDFE5+S356fQlyuJMqzH++HnTo6ui2OO1ko9Ul+4fxfd3d4F7k4YTReqpuFS88bGZUE2QNNDobuIq8Q5CduHb7lFJaTnvnym9ergjMWD/FG8zf+aKS3G9JO5C01Asah6wUXrvALKEDoitMMHhDKrKJdg8RU2s0EB2EWWur8dd7PDPFv6dUC0Gv3kAN36VPRGP/5k5NS6lljWxG0TDiSr1VKhoPwhevRMSqkwRxDObc/DavGtpP6zoi8XOyZfhnyNEvKANBU0P8VPfI/wyNCGXSn7wlEmyA9KrgmOKGth3eDVvPfyywq2dnUEv2R9qG2rLsH7xJXziKnWcI8tlTvEC7Mu8hROlImTU9aKqcwQ1vWOihWFu+sJknmph5CvxQh87c7bNh/NXo03hrMCosyvLmMNgMF7TQL6J1dsZIUVwjKqEO+cajp5vxPN439U/gKBt8PTcYHzL/BgHCyOf4unAISj6mFC2bYC82kB5Ls460NHRUVsDeYSXpGw7UgC7sAtwShDgzdM38W7BbURXtqpqhfmB8sEQuXwoCM/6faGQuGCxyxyKWhIm+PrSD495WL3cT0hhi8Whc3NbAs9KaOyCTvrJ8qkdX19XBeTUDU00+55USFzVU2yHstcaix0mUAjJkJeuRU868Ucmk0lcguiBnMAVxjbbdHV1yeq8+u4Hgo22huSG+iQXp83ftaxW3lsPZcs6KG5T8OwaAfJiPcxlrVRVRhvF02i0F/t5VbHZ7JWDfErKTLnhE3mFPuRFepg/uxqz6TqLv6euGj3ut87t/4ylvre3t3ZehOWWO1zjSFEqMVP4GfGb/DBykJcjmaZOoLsc+hcVY/LaAgcTQAAAAABJRU5ErkJggg=='] ['OpenBSD', 'BAAAAAQCAYAAAFo9M/3AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3AoYAykIPu64pQAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAADTklEQVQ4y32RXUxTdxjGn3N6eujoKT3SUkuk3VoBGfVjgFXAsZ7WkipyYXQbuu3CzUXZmGRbssnFEseFkWzgcGzGXky9MWL8TsC4IeFgtK4oAqOnG5vMVl1pCMVWQD7b/y5M6jLdflfvxfPked/nBQA0NDSChqnGVrLuGkES742NhJAdhAKAuk9yyUs5Gry7RQMZAARCWgivpQiPe71P5DUfH0xaqTL7m/iiLkJmphawa+e4SM2PvUyC4yUIBu8CnAQKAK53rCA5OUtQtStVpJ4Gw/FOBddZVKhCfq4MP4n6+at+DUsJm/e0G9JZzYEvI2tHwlEYjDxomkZ+3nG8WroRtHihZVOhVlorDQzh0okhcByDP4ZGcf+X9XAsvY5/RsBa7Kq5H/CqLctKyl/g08S2i6fq8W/MS3P34T9wNDVYSeDX1eTD9xhiLXbtB/Akwmmv6Kr+ICFkLpGhtNSM3qsSstS3oX8lSsmsxS6ZVn3j6PvVVqhUcvC8AtPxVPxwygVKvngN89WOjgVprggGA4eenjB4nsXsTASpC63I0wVTZYPR11FoKRB8Ax54PCFk6BhMTk5CPR3GSbHouGzknr/bYFq9EAvfc9Tu1sLjHcXNKxLuTOTgzOlOe7IHBc/beAXWpWmXlz8a84nhcLQ+ecVzsAEQrMWuMX+f9HZF2YPZ28FVSNfoPWqOzMUmqYMAJm7+/OOzXQFwHGpyEV+vi+yvtxBC9pDmpgJC4tvI3mo9GTitIxvW24nT7ug67HY/3eDs2bbyrVsrY2day70rV6kRfDAHk5lDLJqAmmeRiD9GJDKHvwb74R8G0mkTPjrQTTG122xkTTbwaV2b1H4u16JQKXGr7yG2b8/H1MQ09IsTSEmRwzf4CCwzD+dmE1re8CI7wwi5XNlFf9vaTXX4dWJg4LLl7h05fpNGwNAMWpp9CIVYNO/tRCzGwpDFQaVMQTS2CKY0BWr3GVGWNSXKACDDaA4Mh976pq9f5Sy09GgKlmeAMIBKzUKpU+BFoxJecRhUfAbMxDi4eADfHVmE79v7q575gvvYeVvjZ58LD5mwsKUyX0hnf0feslnQCWD4zxnc6reKisxsfH2oscqcmTmK/+Ow252cna7K52r+Bky6PqmoT5HBAAAAAElFTkSuQmCC'] ['Gnu', 'BAAAAAQCAYAAAFo9M/3AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3AoYAywUV5gQrwAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAADcElEQVQ4y43Tb0jjBRzH8c9v+7nNMebcUW21Cc78g/wcuhByIScoMRwoTBmFlZCmIJ14axqkgoYIkXIqKIVBEuJNUBEUPRlpqDC3Q2Ex0nTezun2YOaPLXNIv7Vvj7zgiOj1+PPk/eADjuNEuHN6ekqMw+H4IzMz8xChUCjV1NT0JbO7uxtfXFy8NZvNr21tbd0AAEQikY6I0m1tbQbx2NjYZiqV+vn29jY+PDw8xhYWFj45PDzcb25uhlQqfSTief6X0dFRpqKigvF4PPPipaWlY7lcXhCLxXJnZmY+ZTY2NnzX19ePGxsbHw0MDLivrq5mc3Jy2pPJZLVWq/2cdbvdDSzLholoNJ1OMy6Xq0Ymk5HNZktOTU29qMgA8HYqlaKDgwNKp9M0PT09BgAM/iGuqqoimUx2yPP8U5/P9wEAMB0dHRUKheJHiUTyeGhoqAUAnE7nR0qlsjcQCLwjlsvlz+bm5mQWi0VSWlr6bXV1tU6hUMj6+/vfN5lMN0xxcfG1zWZ7SETTSqWSGhoamPHxcajV6s+8Xu9Xou7u7t9VKtW00+mkSCTC6PV6aDQa8Dw/Wl9fP8UAQCgUosvLSyovL2eWl5dRUFBw7Ha7v9vc3By5K3g1EAg8FQSBiIguLi4IgBwA2LtEjuPuJxKJ62AwKFpdXf0eQBIvYVmW/cLlchEAWK1WAADT09NzX6PR/OTz+eKVlZUzKpVqTyqVvsnzfLCkpGSrtrb2t97eXnFeXl5ZKpWyZ2RkPPP7/UUnJyefGI3GU+zt7aU4jotOTk7mAUBfX1+b1Wq9kcvlBIAcDgctLCyQxWKhoqIi6uzs/BoAVlZW3qqpqbllZmdnf1hfX//Q4/HEzWbzX+3t7fcMBgMFg0EYjUYmEolAEAREo1Hk5+fT+fk5Mzg4GD86OpJ0dXXJGQBoaWl5Ra/XP6yrq3tQVlam2N7ehslkAsuySCaTUKvVSCQS2NnZSXAcJxYEQTEyMvKeIAhLDADY7fZ7BoPhm6ysLFpbWzuan5//WKvVvsHzPEWjUSYSiSA3N5d0Oh0TjUaf+/1+S2Nj46/4FwYAr7e2tnbF4/E/iYjC4TCFw+F0LBaj/f19mpiYeID/IAagAyABYLXb7cLZ2Rml02nyer3POY6rwv8hEr34u0IkEk1mZ2cTgGMA7768/RtL5JKsGzrLIgAAAABJRU5ErkJggg=='] ['CrunchBang', 'BYAAAAQCAQAAAC45EetAAAA8ElEQVR4XnWOsUpCYQBGz1TIHYu2Qix6g0DEtSeQu/UIISJtUS8gJq61F1wcdMohcBDxKUR8hsz1xA/y44/cs3znbB+RJ0Skl3pSkeFQbUs79VAPzrwPFRmN1Ja0Ug/16I93+1oi4lKte+zMXv32WuoAm43lXMrqzbFncgWw21lORf4+/PREKpAhYqZuPXZ+T/3yXbZEajV1JavUQ104sRcq0myqc5mnHurWqc/7yhExVwuPncl+C4Bu13L60ueAwcByOtLhgAIRCzU38fRGTmSxUBvSSD3Ui1NvQkXWa7Uq1dRD9R17HiqyRUSy1NP6B7e1Yu2GtlUKAAAAAElFTkSuQmCC'] ['Yuno', 'BgAAAAPCAYAAAD+pA/bAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAABDtJREFUOE+FlHtMm1UYxrtsi8aEgCb+oTFmZur+WNS5RaPERU10C2qGaBgb6hgwLwMmHTIKlIKlQIHSQrmU24BSSmnpBVooUmihtEC5yKWDjVu5uOkcEca4lG5E93j6EQmELX7Jky/fOed9fu973vMdGu0xT3Cgz57yXMZLDdXcy821PFWLKmuA6HqLMqtLX5POl4iYb2ukWW8IOOFe/qfe3/M4n0eOjwyZD8//bldODOk37N1yDJgl+LVdjEGLFKO9KkzZm8hbje7mIrTXZ7sMtTydrJh15H8hHW11XvN/jGS7VudcD5w34ZZzeQYb67fwYO03LN4exo1+LWzNxbA05O5QuzbHqRYn+++CHDx4YK9WLfaedfQzV5em54g5Zbi8OIml+VFMDLWQ7GXoaSmFWZsDZVGCO2u0EbkhHTrhFqi9PmelSsQ8tAtSVch60dpUeGe4kxgZxegzVkBzlQ2NKBG2+iJIMqMok9r8OLRIMqApToSqmAWTmk9B2+o2YW79oshU7ABcuvAFrVGWXkVKpBYoSaBSxIS2mINpiwbjZiUMZRloVfJQyaXDKObBpimBScpHFe8KmmXpaKhK3arGrBVuVBclHN2CiPNin1OVs1tVJYlQlyZBxA6DviQVo6ZaOKd7sTplw53BVugruBBzfsRslw7rZPxaczWutSpQV/gzJPxo1JexyfaxKBBpuiEx+tw+CpKdEvGWTprGlhcwqbIzL5/DYKMYndpK3L1hxf3ZfkrzwybUZjPhnOqmvlcmutFF1jis9QSShOrcWNSXJ1MA0ou/NZWc8Ddfe4VGO3bk0JON1dyMMlK+gmxNrZCFhZF2Kng7YNO0awt4b7wLNp2EqtAsF6ImP56SG0B6siovTYpIjg15gapCVhAfJRUyIBFEo6k8AyuTtkcC/qvG/XbDexulWJvqgYH0o0nKhVHFJ40XwFQnWM5OCX+XMg86c3KvVMSMapCmPpSTIygTxGKZZOcOXhrr3Mp4uzkFuG6B3ajE3TELDDU8qEmsmvRATxquKkxAnSTFjwKEfv3JU9JC5unG6rQ1bTkbQ4Yq/DVgxOqwBWt2K9Yne3ZCZvrgHO2k5paHzOhSiVCZSkdNTgzy40JRlPgDhDHBCxUZdCs91G8fLeK87zOl6XSOICZYXMGNhDqX9fDP/mbK2DXVi/szm03eLpejl5pzOfqwOt4JBT8OeYwQt/4R/BR0OzXiLCM5LOCji/4nXt46rpywgG+zor5RxgSdupBzJdglSY+5ZZbl3XNY6mbn7W0Lcx06zBg1WBjtcC6OmG+OmRTrFrnIUZESZeVeCpwh8TpiPsQ47/tloM97T+/6m8mg55mT3tStyL54mhlwwtszNvjzD8/6HH8i7PvvPPRioZdRWuDBZUR6pEWG7I8P9Xs1Jsj36MfvvO5J/+rTw58dP7afJPfBgeef3XGz/gskFVpJc4HwGwAAAABJRU5ErkJggg=='] ] Banner = init: -> $.asap (-> doc), -> $.asap (-> $ '.abovePostForm'), Banner.ready ready: -> banner = $ ".boardBanner" title = $.el "div", id: "boardTitle" children = banner.children i = children.length nodes = [] while i-- child = children[i] if child.tagName.toLowerCase() is "img" child.id = "Banner" continue if Conf['Custom Board Titles'] cachedTest = child.innerHTML if not Conf['Persistent Custom Board Titles'] or cachedTest is $.get "#{g.BOARD}.#{child.className}.orig", cachedTest child.innerHTML = $.get "#{g.BOARD}.#{child.className}", cachedTest else $.set "#{g.BOARD}.#{child.className}.orig", cachedTest $.set "#{g.BOARD}.#{child.className}", cachedTest $.on child, 'click', (e) -> if e.shiftKey @contentEditable = true $.on child, 'keydown', (e) -> e.stopPropagation() $.on child, 'focus', -> @textContent = @innerHTML $.on child, 'blur', -> $.set "#{g.BOARD}.#{@className}", @textContent @innerHTML = @textContent @contentEditable = false nodes.push child $.add title, nodes.reverse() $.after banner, title return GlobalMessage = init: -> $.asap (-> doc), -> $.asap (-> $.id 'delform'), GlobalMessage.ready ready: -> if el = $ "#globalMessage", d.body for child in el.children child.cssText = "" return Rice = init: -> $.ready -> Rice.nodes d.body Post::callbacks.push name: 'Rice Checkboxes' cb: @node checkclick: -> @check.click() selectclick: -> e.stopPropagation() if Rice.ul return Rice.remSelect() rect = @getBoundingClientRect() {clientHeight} = d.documentElement ul = Rice.ul = $.el 'ul', id: "selectrice" {style} = ul style.width = "#{rect.width}px" if clientHeight - rect.bottom < 200 style.bottom = "#{clientHeight - rect.top}px" else style.top = "#{rect.bottom}px" style.left = "#{rect.left}px" input = @previousSibling for option in input.options li = $.el 'li', textContent: option.textContent li.setAttribute 'data-value', option.value $.on li, 'click', (e) -> e.stopPropagation() container = @parentElement.parentElement input = container.previousSibling container.firstChild.textContent = @textContent input.value = @getAttribute 'data-value' ev = document.createEvent 'HTMLEvents' ev.initEvent "change", true, true $.event input, ev Rice.remSelect() $.add ul, li $.on ul, 'click scroll blur', (e) -> e.stopPropagation() $.on d, 'click scroll blur resize', Rice.remSelect $.add @, ul remSelect: -> $.off d, 'click scroll blur resize', Rice.remSelect $.rm Rice.ul delete Rice.ul nodes: (source) -> checkboxes = $$('[type=checkbox]:not(.riced)', source) checkrice = Rice.checkbox for input in checkboxes checkrice input selects = $$('select:not(.riced)', source) selectrice = Rice.select for input in selects selectrice input return node: -> Rice.checkbox $ '.postInfo input', @nodes.post checkbox: (input) -> return if $.hasClass input, 'riced' $.addClass input, 'riced' div = $.el 'div', className: 'rice' div.check = input $.after input, div if div.parentElement.tagName.toLowerCase() != 'label' $.on div, 'click', Rice.checkclick select: (input) -> $.addClass input, 'riced' div = $.el 'div', className: 'selectrice' innerHTML: "
#{input.options[input.selectedIndex].textContent or null}
" $.on div, "click", (e) -> Rice.selectclick $.after input, div ### JSColor http://github.com/hotchpotch/jscolor/tree/master JSColor is color library for JavaScript. JSColor code is porting from AS3 Color library ColorSB < http://sketchbook.libspark.org/trac/wiki/ColorSB >. ### JSColor = css: -> agent = Style.agent """<%= grunt.file.read('css/jscolor.css') %>""" bind: (el) -> el.color = new JSColor.color(el) if not el.color fetchElement: (mixed) -> if typeof mixed is "string" then $.id mixed else mixed fireEvent: (el, evnt) -> return unless el ev = document.createEvent 'HTMLEvents' ev.initEvent evnt, true, true el.dispatchEvent ev getRelMousePos: (e = window.event) -> x = 0 y = 0 if typeof e.offsetX is 'number' x = e.offsetX y = e.offsetY else if typeof e.layerX is 'number' x = e.layerX y = e.layerY x: x y: y color: (target) -> # Read Only @hsv = [0, 0, 1] # 0-6, 0-1, 0-1 @rgb = [1, 1, 1] # 0-1, 0-1, 0-1 # Writable. # Value holder / Where to reflect current color @valueElement = @styleElement = target # Blur / Drag trackers abortBlur = holdPad = holdSld = false @hidePicker = -> if isPickerOwner() then removePicker() @showPicker = -> unless isPickerOwner() then drawPicker() @importColor = -> unless valueElement @exportColor() else unless @fromString valueElement.value, leaveValue styleElement.style.backgroundColor = styleElement.jscStyle.backgroundColor @exportColor leaveValue | leaveStyle @exportColor = (flags) -> if !(flags & leaveValue) and valueElement value = '#' + @toString() valueElement.value = value valueElement.previousSibling.value = value editTheme[valueElement.previousSibling.name] = value setTimeout -> Style.themeCSS.textContent = Style.theme editTheme if not (flags & leaveStyle) and styleElement styleElement.style.backgroundColor = '#' + @toString() if not (flags & leavePad) and isPickerOwner() redrawPad() if not (flags & leaveSld) and isPickerOwner() redrawSld() @fromHSV = (h, s, v, flags) -> # null = don't change @hsv = [ h = if h $.minmax h, 0.0, 6.0 else @hsv[0] s = if s $.minmax s, 0.0, 1.0 else @hsv[1] v = if v $.minmax v, 0.0, 1.0 else @hsv[2] ] @rgb = HSV_RGB(h, s, v) @exportColor flags @fromRGB = (r, g, b, flags) -> # null = don't change r = if r? $.minmax r, 0.0, 1.0 else @rgb[0] g = if g? $.minmax g, 0.0, 1.0 else @rgb[1] b = if b? $.minmax b, 0.0, 1.0 else @rgb[2] hsv = RGB_HSV(r, g, b) if hsv[0]? @hsv[0] = $.minmax hsv[0], 0.0, 6.0 if hsv[2] isnt 0 @hsv[1] = unless hsv[1]? null else $.minmax hsv[1], 0.0, 1.0 @hsv[2] = unless hsv[2]? null else $.minmax hsv[2], 0.0, 1.0 # update RGB according to final HSV, as some values might be trimmed @rgb = HSV_RGB @hsv[0], @hsv[1], @hsv[2] @exportColor flags @fromString = (number, flags) -> m = number.match /^\W*([0-9A-F]{3}([0-9A-F]{3})?)\W*$/i unless m return false else if m[1].length is 6 # 6-char notation @fromRGB( parseInt(m[1].substr(0, 2), 16) / 255 parseInt(m[1].substr(2, 2), 16) / 255 parseInt(m[1].substr(4, 2), 16) / 255 flags ) else # 3-char notation @fromRGB( # Double-up each character to fake 6-char notation. parseInt((val = m[1].charAt 0) + val, 16) / 255 parseInt((val = m[1].charAt 1) + val, 16) / 255 parseInt((val = m[1].charAt 2) + val, 16) / 255 flags ) true @toString = -> (0x100 | Math.round(255 * @rgb[0])).toString(16).substr(1) + (0x100 | Math.round(255 * @rgb[1])).toString(16).substr(1) + (0x100 | Math.round(255 * @rgb[2])).toString(16).substr(1) RGB_HSV = (r, g, b) -> n = if (n = if r < g then r else g) < b then n else b v = if (v = if r > g then r else g) > b then v else b m = v - n return [ null, 0, v ] if m is 0 h = if r is n 3 + (b - g) / m else if g is n 5 + (r - b) / m else 1 + (g - r) / m [ if h is 6 then 0 else h m / v v ] HSV_RGB = (h, s, v) -> return [ v, v, v ] unless h? i = Math.floor(h) f = if i % 2 h - i else 1 - (h - i) m = v * (1 - s) n = v * (1 - s * f) switch i when 6, 0 [v,n,m] when 1 [n,v,m] when 2 [m,v,n] when 3 [m,n,v] when 4 [n,m,v] when 5 [v,m,n] removePicker = -> delete JSColor.picker.owner $.rm JSColor.picker.boxB drawPicker = (x, y) -> unless p = JSColor.picker elements = ['box', 'boxB', 'pad', 'padB', 'padM', 'sld', 'sldB', 'sldM', 'btn'] p = {} for item in elements p[item] = $.el 'div', {className: "jsc#{item.capitalize()}"} p.btnS = $.el 'span', {className: 'jscBtnS'} p.btnT = $.tn 'Close' JSColor.picker = p $.add p.box, [p.sldB, p.sldM, p.padB, p.padM, p.btn] $.add p.sldB, p.sld $.add p.padB, p.pad $.add p.btnS, p.btnT $.add p.btn, p.btnS $.add p.boxB, p.box # controls interaction {box, boxB, btn, btnS, pad, padB, padM, sld, sldB, sldM} = p box.onmouseup = box.onmouseout = -> target.focus() box.onmousedown = -> abortBlur=true box.onmousemove = (e) -> if holdPad or holdSld holdPad and setPad e holdSld and setSld e if d.selection d.selection.empty() else if window.getSelection window.getSelection().removeAllRanges() padM.onmouseup = padM.onmouseout = -> if holdPad holdPad = false JSColor.fireEvent valueElement, 'change' padM.onmousedown = (e) -> # If the slider is at the bottom, move it up if THIS.hsv[2] is 0 THIS.fromHSV null, null, 1.0 holdPad = true setPad e sldM.onmouseup = sldM.onmouseout = -> if holdSld holdSld = false JSColor.fireEvent valueElement, 'change' sldM.onmousedown = (e) -> holdSld = true setSld e btn.onmousedown = -> THIS.hidePicker() # place pointers redrawPad() redrawSld() JSColor.picker.owner = THIS $.add ThemeTools.dialog, p.boxB # redraw the pad pointer redrawPad = -> # The X and Y positions of the picker crosshair, based on the hsv Hue and Saturation values as percentages and the picker's dimensions. JSColor.picker.padM.style.backgroundPosition = "#{4 + Math.round (THIS.hsv[0] / 6) * 180}px #{4 + Math.round (1 - THIS.hsv[1]) * 100}px" rgb = HSV_RGB(THIS.hsv[0], THIS.hsv[1], 1) JSColor.picker.sld.style.backgroundColor = "rgb(#{rgb[0] * 100}%, #{rgb[1] * 100}%, #{rgb[2] * 100}%)" return redrawSld = -> # redraw the slider pointer. X will always be 0, Y will always be a percentage of the HSV 'Value' value. JSColor.picker.sldM.style.backgroundPosition = "0 #{6 + Math.round (1 - THIS.hsv[2]) * 100}px" isPickerOwner = -> return JSColor.picker and JSColor.picker.owner is THIS blurTarget = -> if valueElement is target THIS.importColor() blurValue = -> if valueElement isnt target THIS.importColor() setPad = (e) -> mpos = JSColor.getRelMousePos e x = mpos.x - 11 y = mpos.y - 11 THIS.fromHSV( x * (1 / 30) 1 - y / 100 null leaveSld ) setSld = (e) -> mpos = JSColor.getRelMousePos e y = mpos.y - 9 THIS.fromHSV( null null 1 - y / 100 leavePad ) THIS = @ valueElement = JSColor.fetchElement @valueElement styleElement = JSColor.fetchElement @styleElement leaveValue = 1 << 0 leaveStyle = 1 << 1 leavePad = 1 << 2 leaveSld = 1 << 3 # target $.on target, 'focus', -> THIS.showPicker() $.on target, 'blur', -> unless abortBlur window.setTimeout(-> abortBlur or blurTarget() abortBlur = false ) else abortBlur = false # valueElement if valueElement $.on valueElement, 'keyup input', -> THIS.fromString valueElement.value, leaveValue $.on valueElement, 'blur', blurValue valueElement.setAttribute 'autocomplete', 'off' # styleElement if styleElement styleElement.jscStyle = backgroundColor: styleElement.style.backgroundColor @importColor() MascotTools = init: (mascot = Conf[g.MASCOTSTRING][Math.floor(Math.random() * Conf[g.MASCOTSTRING].length)]) -> Conf['mascot'] = mascot @el = el = $('#mascot img', d.body) if !Conf['Mascots'] or (g.CATALOG and Conf['Hide Mascots on Catalog']) return if el then el.src = "" else null position = "#{if Conf['Mascot Position'] is 'bottom' or !(Conf['Mascot Position'] is "default" and Conf['Post Form Style'] is "fixed") 0 + (if (!g.REPLY or Conf['Boards Navigation'] is 'sticky bottom') and Conf['4chan SS Navigation'] then 1.6 else 0) else 20.3 + (if !g.REPLY or !!$ '#postForm input[name=spoiler]' then 1.4 else 0) + (if Conf['Show Post Form Header'] then 1.5 else 0) + (if Conf['Post Form Decorations'] then 0.2 else 0) }em" # If we're editting anything, let's not change mascots any time we change a value. if Conf['editMode'] unless mascot = editMascot or mascot = Mascots[Conf["mascot"]] return else unless Conf["mascot"] return if el then el.src = "" else null unless mascot = Mascots[Conf["mascot"]] Conf[g.MASCOTSTRING].remove Conf["mascot"] return @init() @addMascot mascot if Conf["Sidebar Location"] is 'left' if Conf["Mascot Location"] is "sidebar" location = 'left' else location = 'right' else if Conf["Mascot Location"] is "sidebar" location = 'right' else location = 'left' filters = [] if Conf["Grayscale Mascots"] filters.push '' Style.mascot.textContent = """ #mascot img { position: fixed; z-index: #{ if Conf['Mascots Overlap Posts'] '3' else '-1' }; #{if Style.sidebarLocation[0] is "left" then "#{Style.agent}transform: scaleX(-1);" else ""} bottom: #{ if mascot.position is 'top' 'auto' else if (mascot.position is 'bottom' and Conf['Mascot Position'] is 'default') or !$.id 'postForm' '0' else position }; #{location}: #{ (mascot.hOffset or 0) + ( if Conf['Sidebar'] is 'large' and mascot.center 25 else 0 ) }px; top: #{ if mascot.position is 'top' '0' else 'auto' }; height: #{ if mascot.height and isNaN parseFloat mascot.height mascot.height else if mascot.height parseInt(mascot.height, 10) + 'px' else 'auto' }; width: #{ if mascot.width and isNaN parseFloat mascot.width mascot.width else if mascot.width parseInt(mascot.width, 10) + 'px' else 'auto' }; margin-#{location}: #{mascot.hOffset or 0}px; margin-bottom: #{mascot.vOffset or 0}px; opacity: #{Conf['Mascot Opacity']}; pointer-events: none; #{if filters.length > 0 then "filter: url('data:image/svg+xml," + filters.join("") + "#filters');" else ""} } """ categories: [ 'Anime' 'Ponies' 'Questionable' 'Silhouette' 'Western' ] dialog: (key) -> Conf['editMode'] = 'mascot' if Mascots[key] editMascot = JSON.parse(JSON.stringify(Mascots[key])) else editMascot = {} editMascot.name = key or '' MascotTools.addMascot editMascot Style.addStyle() layout = name: [ "Mascot Name" "" "text" ] image: [ "Image" "" "text" ] category: [ "Category" MascotTools.categories[0] "select" MascotTools.categories ] position: [ "Position" "default" "select" ["default", "top", "bottom"] ] height: [ "Height" "auto" "text" ] width: [ "Width" "auto" "text" ] vOffset: [ "Vertical Offset" "0" "number" ] hOffset: [ "Horizontal Offset" "0" "number" ] center: [ "Center Mascot" false "checkbox" ] dialog = $.el "div", id: "mascotConf" className: "reply dialog" innerHTML: "

Save Mascot
Close
" for name, item of layout switch item[2] when "text" div = @input item, name input = $ 'input', div if name is 'image' $.on input, 'blur', -> editMascot[@name] = @value MascotTools.addMascot editMascot Style.addStyle() fileInput = $.el 'input', type: "file" accept: "image/*" title: "imagefile" hidden: "hidden" $.on input, 'click', (evt) -> if evt.shiftKey @.nextSibling.click() $.on fileInput, 'change', (evt) -> MascotTools.uploadImage evt, @ $.after input, fileInput if name is 'name' $.on input, 'blur', -> @value = @value.replace /[^a-z-_0-9]/ig, "_" unless /^[a-z]/i.test @value return alert "Mascot names must start with a letter." editMascot[@name] = @value MascotTools.addMascot editMascot Style.addStyle() else $.on input, 'blur', -> editMascot[@name] = @value MascotTools.addMascot editMascot Style.addStyle() when "number" div = @input item, name $.on $('input', div), 'blur', -> editMascot[@name] = parseInt @value MascotTools.addMascot editMascot Style.addStyle() when "select" value = editMascot[name] or item[1] optionHTML = "
#{item[0]}
" div = $.el 'div', className: "mascotvar" innerHTML: optionHTML setting = $ "select", div setting.value = value $.on $('select', div), 'change', -> editMascot[@name] = @value MascotTools.addMascot editMascot Style.addStyle() when "checkbox" value = editMascot[name] or item[1] div = $.el "div", className: "mascotvar" innerHTML: "" $.on $('input', div), 'click', -> editMascot[@name] = if @checked then true else false MascotTools.addMascot editMascot Style.addStyle() $.add $("#mascotcontent", dialog), div $.on $('#save > a', dialog), 'click', -> MascotTools.save editMascot $.on $('#close > a', dialog), 'click', MascotTools.close Style.rice(dialog) $.add d.body, dialog input: (item, name) -> if Array.isArray(editMascot[name]) if Style.lightTheme value = editMascot[name][1] else value = editMascot[name][0] else value = editMascot[name] or item[1] editMascot[name] = value div = $.el "div", className: "mascotvar" innerHTML: "
#{item[0]}
" return div uploadImage: (evt, el) -> file = evt.target.files[0] reader = new FileReader() reader.onload = (evt) -> val = evt.target.result el.previousSibling.value = val editMascot.image = val Style.addStyle() reader.readAsDataURL file addMascot: (mascot) -> if el = @el el.src = if Array.isArray(mascot.image) then (if Style.lightTheme then mascot.image[1] else mascot.image[0]) else mascot.image else @el = el = $.el 'div', id: "mascot" innerHTML: "" $.add d.body, el save: (mascot) -> {name, image} = mascot if !name? or name is "" alert "Please name your mascot." return if !image? or image is "" alert "Your mascot must contain an image." return unless mascot.category mascot.category = MascotTools.categories[0] if Mascots[name] if Conf["Deleted Mascots"].contains name Conf["Deleted Mascots"].remove name $.set "Deleted Mascots", Conf["Deleted Mascots"] else if confirm "A mascot named \"#{name}\" already exists. Would you like to over-write?" delete Mascots[name] else return alert "Creation of \"#{name}\" aborted." for type in ["Enabled Mascots", "Enabled Mascots sfw", "Enabled Mascots nsfw"] unless Conf[type].contains name Conf[type].push name $.set type, Conf[type] Mascots[name] = JSON.parse(JSON.stringify(mascot)) Conf["mascot"] = name delete Mascots[name].name userMascots = $.get "userMascots", {} userMascots[name] = Mascots[name] $.set 'userMascots', userMascots alert "Mascot \"#{name}\" saved." close: -> Conf['editMode'] = false editMascot = {} $.rm $("#mascotConf", d.body) Style.addStyle() Options.dialog("mascot") importMascot: (evt) -> file = evt.target.files[0] reader = new FileReader() reader.onload = (e) -> try imported = JSON.parse e.target.result catch err alert err return unless (imported["Mascot"]) alert "Mascot file is invalid." name = imported["Mascot"] delete imported["Mascot"] if Mascots[name] and not Conf["Deleted Mascots"].remove name unless confirm "A mascot with this name already exists. Would you like to over-write?" return Mascots[name] = imported userMascots = $.get "userMascots", {} userMascots[name] = Mascots[name] $.set 'userMascots', userMascots alert "Mascot \"#{name}\" imported!" $.rm $("#mascotContainer", d.body) Options.mascotTab.dialog() reader.readAsText(file) ### Style.color adapted from 4chan Style Script ### ThemeTools = init: (key) -> Conf['editMode'] = "theme" if Themes[key] editTheme = JSON.parse(JSON.stringify(Themes[key])) if ($.get "userThemes", {})[key] editTheme["Theme"] = key else editTheme["Theme"] = key += " [custom]" else editTheme = JSON.parse(JSON.stringify(Themes['Yotsuba B'])) editTheme["Theme"] = "Untitled" editTheme["Author"] = "Author" editTheme["Author Tripcode"] = "Unknown" # Objects are not guaranteed to have any type of arrangement, so we use a presorted # array to generate the layout of of the theme editor. # (Themes aren't even guaranteed to have any of these values, actually) layout = [ "Background Image" "Background Attachment" "Background Position" "Background Repeat" "Background Color" "Thread Wrapper Background" "Thread Wrapper Border" "Dialog Background" "Dialog Border" "Reply Background" "Reply Border" "Highlighted Reply Background" "Highlighted Reply Border" "Backlinked Reply Outline" "Input Background" "Input Border" "Hovered Input Background" "Hovered Input Border" "Focused Input Background" "Focused Input Border" "Checkbox Background" "Checkbox Border" "Checkbox Checked Background" "Buttons Background" "Buttons Border" "Navigation Background" "Navigation Border" "Links" "Hovered Links" "Quotelinks" "Backlinks" "Navigation Links" "Hovered Navigation Links" "Names" "Tripcodes" "Emails" "Subjects" "Text" "Inputs" "Post Numbers" "Greentext" "Sage" "Board Title" "Timestamps" "Warnings" "Shadow Color" ] ThemeTools.dialog = $.el "div", id: "themeConf" className: "reply dialog" innerHTML: "

" header = $.el "div", innerHTML: " by " #Setup inputs that are not generated from the layout variable. for input in $$("input", header) $.on input, 'blur', -> editTheme[@name] = @value $.add $("#themebar", ThemeTools.dialog), header themecontent = $("#themecontent", ThemeTools.dialog) for item in layout unless editTheme[item] editTheme[item] = '' div = $.el "div", className: "themevar" innerHTML: "
#{item}
" input = $('input', div) input.value = editTheme[item] switch item when "Background Image" input.className = 'field' fileInput = $.el 'input', type: 'file' accept: "image/*" title: "BG Image" hidden: "hidden" $.on input, 'click', (evt) -> if evt.shiftKey @nextSibling.click() $.on fileInput, 'change', (evt) -> ThemeTools.uploadImage evt, @ $.after input, fileInput when "Background Attachment" ,"Background Position", "Background Repeat" input.className = 'field' else input.className = "colorfield" colorInput = $.el 'input', className: 'color' value: "##{Style.colorToHex input.value}" JSColor.bind colorInput $.after input, colorInput $.on input, 'blur', -> depth = 0 unless @value.length > 1000 for i in [0..@value.length - 1] switch @value[i] when '(' then depth++ when ')' then depth-- when '"' then toggle1 = not toggle1 when "'" then toggle2 = not toggle2 if depth != 0 or toggle1 or toggle2 return alert "Syntax error on #{@name}." if @className == "colorfield" @nextSibling.value = "##{Style.colorToHex @value}" @nextSibling.color.importColor() editTheme[@name] = @value Style.addStyle(editTheme) $.add themecontent, div $.add themecontent, div unless editTheme["Custom CSS"] editTheme["Custom CSS"] = "" div = $.el "div", className: "themevar" innerHTML: "
Custom CSS
" $.on $('textarea', div), 'blur', -> editTheme["Custom CSS"] = @value Style.themeCSS.textContent = Style.theme editTheme $.add themecontent, div $.on $('#save > a', ThemeTools.dialog), 'click', -> ThemeTools.save editTheme $.on $('#close > a', ThemeTools.dialog), 'click', ThemeTools.close $.add d.body, ThemeTools.dialog Style.themeCSS.textContent = Style.theme editTheme uploadImage: (evt, el) -> file = evt.target.files[0] reader = new FileReader() reader.onload = (evt) -> val = 'url("' + evt.target.result + '")' el.previousSibling.value = val editTheme["Background Image"] = val Style.themeCSS.textContent = Style.theme editTheme reader.readAsDataURL file importtheme: (origin, evt) -> file = evt.target.files[0] reader = new FileReader() reader.onload = (e) -> try imported = JSON.parse e.target.result catch err alert err return unless (origin != 'appchan' and imported.mainColor) or (origin == 'appchan' and imported["Author Tripcode"]) alert "Theme file is invalid." return name = imported.name or imported["Theme"] delete imported.name if Themes[name] and not Themes[name]["Deleted"] if confirm "A theme with this name already exists. Would you like to over-write?" delete Themes[name] else return if origin == "oneechan" or origin == "SS" bgColor = new Style.color(imported.bgColor); mainColor = new Style.color(imported.mainColor); brderColor = new Style.color(imported.brderColor); inputColor = new Style.color(imported.inputColor); inputbColor = new Style.color(imported.inputbColor); blinkColor = new Style.color(imported.blinkColor); jlinkColor = new Style.color(imported.jlinkColor); linkColor = new Style.color(imported.linkColor); linkHColor = new Style.color(imported.linkHColor); nameColor = new Style.color(imported.nameColor); quoteColor = new Style.color(imported.quoteColor); sageColor = new Style.color(imported.sageColor); textColor = new Style.color(imported.textColor); titleColor = new Style.color(imported.titleColor); tripColor = new Style.color(imported.tripColor); timeColor = new Style.color(imported.timeColor || imported.textColor); if imported.bgRPA bgRPA = imported.bgRPA.split(' ') else bgRPA = ['no-repeat', 'bottom', 'left', 'fixed'] if origin == "oneechan" Themes[name] = { 'Author' : "Anonymous" 'Author Tripcode' : "!POMF.9waa" 'Background Image' : 'url("' + (imported.bgImg or '') + '")' 'Background Attachment' : bgRPA[3] or '' 'Background Position' : ((bgRPA[1] + " ") or '') + (bgRPA[2] or '') 'Background Repeat' : bgRPA[0] or '' 'Background Color' : 'rgb(' + bgColor.rgb + ')' 'Dialog Background' : 'rgba(' + mainColor.rgb + ',.98)' 'Dialog Border' : 'rgb(' + brderColor.rgb + ')' 'Thread Wrapper Background' : 'rgba(0,0,0,0)' 'Thread Wrapper Border' : 'rgba(0,0,0,0)' 'Reply Background' : 'rgba(' + mainColor.rgb + ',' + imported.replyOp + ')' 'Reply Border' : 'rgb(' + brderColor.rgb + ')' 'Highlighted Reply Background': 'rgba(' + mainColor.shiftRGB(4, true) + ',' + imported.replyOp + ')' 'Highlighted Reply Border' : 'rgb(' + linkColor.rgb + ')' 'Backlinked Reply Outline' : 'rgb(' + linkColor.rgb + ')' 'Checkbox Background' : 'rgba(' + inputColor.rgb + ',' + imported.replyOp + ')' 'Checkbox Border' : 'rgb(' + inputbColor.rgb + ')' 'Checkbox Checked Background' : 'rgb(' + inputColor.rgb + ')' 'Input Background' : 'rgba(' + inputColor.rgb + ',' + imported.replyOp + ')' 'Input Border' : 'rgb(' + inputbColor.rgb + ')' 'Hovered Input Background' : 'rgba(' + inputColor.hover + ',' + imported.replyOp + ')' 'Hovered Input Border' : 'rgb(' + inputbColor.rgb + ')' 'Focused Input Background' : 'rgba(' + inputColor.hover + ',' + imported.replyOp + ')' 'Focused Input Border' : 'rgb(' + inputbColor.rgb + ')' 'Buttons Background' : 'rgba(' + inputColor.rgb + ',' + imported.replyOp + ')' 'Buttons Border' : 'rgb(' + inputbColor.rgb + ')' 'Navigation Background' : 'rgba(' + bgColor.rgb + ',0.8)' 'Navigation Border' : 'rgb(' + mainColor.rgb + ')' 'Quotelinks' : 'rgb(' + linkColor.rgb + ')' 'Links' : 'rgb(' + linkColor.rgb + ')' 'Hovered Links' : 'rgb(' + linkHColor.rgb + ')' 'Navigation Links' : 'rgb(' + textColor.rgb + ')' 'Hovered Navigation Links' : 'rgb(' + linkHColor.rgb + ')' 'Subjects' : 'rgb(' + titleColor.rgb + ')' 'Names' : 'rgb(' + nameColor.rgb + ')' 'Sage' : 'rgb(' + sageColor.rgb + ')' 'Tripcodes' : 'rgb(' + tripColor.rgb + ')' 'Emails' : 'rgb(' + linkColor.rgb + ')' 'Post Numbers' : 'rgb(' + linkColor.rgb + ')' 'Text' : 'rgb(' + textColor.rgb + ')' 'Backlinks' : 'rgb(' + linkColor.rgb + ')' 'Greentext' : 'rgb(' + quoteColor.rgb + ')' 'Board Title' : 'rgb(' + textColor.rgb + ')' 'Timestamps' : 'rgb(' + timeColor.rgb + ')' 'Inputs' : 'rgb(' + textColor.rgb + ')' 'Warnings' : 'rgb(' + sageColor.rgb + ')' 'Shadow Color' : 'rgba(0,0,0,0.1)' 'Custom CSS' : """<%= grunt.file.read('css/theme.oneechan.css') %>""" + (imported.customCSS or '') } else if origin == "SS" Themes[name] = { 'Author' : "Anonymous" 'Author Tripcode' : "!.pC/AHOKAg" 'Background Image' : 'url("' + (imported.bgImg or '') + '")' 'Background Attachment' : bgRPA[3] or '' 'Background Position' : ((bgRPA[1] + " ") or '') + (bgRPA[2] or '') 'Background Repeat' : bgRPA[0] or '' 'Background Color' : 'rgb(' + bgColor.rgb + ')' 'Dialog Background' : 'rgba(' + mainColor.rgb + ',.98)' 'Dialog Border' : 'rgb(' + brderColor.rgb + ')' 'Thread Wrapper Background' : 'rgba(' + mainColor.rgb + ',.5)' 'Thread Wrapper Border' : 'rgba(' + brderColor.rgb + ',.9)' 'Reply Background' : 'rgba(' + mainColor.rgb + ',.9)' 'Reply Border' : 'rgb(' + brderColor.rgb + ')' 'Highlighted Reply Background': 'rgba(' + mainColor.shiftRGB(4, true) + ',.9)' 'Highlighted Reply Border' : 'rgb(' + linkColor.rgb + ')' 'Backlinked Reply Outline' : 'rgb(' + linkColor.rgb + ')' 'Checkbox Background' : 'rgba(' + inputColor.rgb + ',.9)' 'Checkbox Border' : 'rgb(' + inputbColor.rgb + ')' 'Checkbox Checked Background' : 'rgb(' + inputColor.rgb + ')' 'Input Background' : 'rgba(' + inputColor.rgb + ',.9)' 'Input Border' : 'rgb(' + inputbColor.rgb + ')' 'Hovered Input Background' : 'rgba(' + inputColor.hover + ',.9)' 'Hovered Input Border' : 'rgb(' + inputbColor.rgb + ')' 'Focused Input Background' : 'rgba(' + inputColor.hover + ',.9)' 'Focused Input Border' : 'rgb(' + inputbColor.rgb + ')' 'Buttons Background' : 'rgba(' + inputColor.rgb + ',.9)' 'Buttons Border' : 'rgb(' + inputbColor.rgb + ')' 'Navigation Background' : 'rgba(' + bgColor.rgb + ',0.8)' 'Navigation Border' : 'rgb(' + mainColor.rgb + ')' 'Quotelinks' : 'rgb(' + linkColor.rgb + ')' 'Links' : 'rgb(' + linkColor.rgb + ')' 'Hovered Links' : 'rgb(' + linkHColor.rgb + ')' 'Navigation Links' : 'rgb(' + textColor.rgb + ')' 'Hovered Navigation Links' : 'rgb(' + linkHColor.rgb + ')' 'Subjects' : 'rgb(' + titleColor.rgb + ')' 'Names' : 'rgb(' + nameColor.rgb + ')' 'Sage' : 'rgb(' + sageColor.rgb + ')' 'Tripcodes' : 'rgb(' + tripColor.rgb + ')' 'Emails' : 'rgb(' + linkColor.rgb + ')' 'Post Numbers' : 'rgb(' + linkColor.rgb + ')' 'Text' : 'rgb(' + textColor.rgb + ')' 'Backlinks' : 'rgb(' + linkColor.rgb + ')' 'Greentext' : 'rgb(' + quoteColor.rgb + ')' 'Board Title' : 'rgb(' + textColor.rgb + ')' 'Timestamps' : 'rgb(' + timeColor.rgb + ')' 'Inputs' : 'rgb(' + textColor.rgb + ')' 'Warnings' : 'rgb(' + sageColor.rgb + ')' 'Shadow Color' : 'rgba(0,0,0,0.1)' 'Custom CSS' : """<%= grunt.file.read('css/theme.4chanss.css') %>""" + (imported.customCSS or '') } else if origin == 'appchan' Themes[name] = imported userThemes = $.get "userThemes", {} userThemes[name] = Themes[name] $.set 'userThemes', userThemes alert "Theme \"#{name}\" imported!" $.rm $("#themes", d.body) Options.themeTab() reader.readAsText(file) save: (theme) -> name = theme["Theme"] if Themes[name] and not Themes[name]["Deleted"] if confirm "A theme with this name already exists. Would you like to over-write?" delete Themes[name] else return Themes[name] = JSON.parse(JSON.stringify(theme)) delete Themes[name]["Theme"] userThemes = $.get "userThemes", {} userThemes[name] = Themes[name] $.set 'userThemes', userThemes $.set "theme", Conf['theme'] = name alert "Theme \"#{name}\" saved." close: -> Conf['editMode'] = false $.rm $("#themeConf", d.body) Style.addStyle() Options.dialog("theme")