Style = sheets: {} init: -> Style.svgs = { <% if (type === 'crx') { %> el: $.el 'div', id: 'svg_filters' <% } %> } theme = Themes[Conf[g.THEMESTRING]] or Themes['Yotsuba B'] items = [ ['layout', Style.layout] ['theme', Style.theme theme] ['emoji', Emoji.css()] ['dynamic', Style.dynamic()] ['padding', ""] ['mascots', ""] ] i = 0 while item = items[i++] Style.sheets[item[0]] = $.addStyle item[1], item[0] # Non-customizable $.addStyle JSColor.css(), 'jsColor' $.asap (-> d.head), Style.observe $.asap (-> d.body), @asapInit $.asap (-> Header.bar.parentElement), Style.padding $.on window, "resize", Style.padding $.ready @readyInit asapInit: -> <% if (type === 'crx') { %> $.addClass doc, 'blink' <% } else { %> $.addClass doc, 'gecko' <% } %> $.addClass doc, 'fourchan-x' $.addClass doc, 'appchan-x' $.addClass doc, g.VIEW <% if (type === 'crx') { %> $.add d.body, Style.svgs.el <% } %> for title, cat of Config.style for name, setting of cat continue if !Conf[name] or setting[2] is 'text' or name in ['NSFW/SFW Themes', 'NSFW/SFW Mascots'] hyphenated = "#{name}#{if setting[2] then " #{Conf[name]}" else ""}".toLowerCase().replace(/^4/, 'four').replace /\s+/g, '-' $.addClass doc, hyphenated return readyInit: -> Style.iconPositions() if exLink = $ "#navtopright .exlinksOptionsLink", d.body $.on exLink, "click", -> setTimeout Rice.nodes, 100 observe: -> Style.observer = new MutationObserver onMutationObserver = Style.wrapper Style.observer.observe d.head, childList: true subtree: true wrapper: -> first = {addedNodes: d.head.children} Style.remStyle first if d.readyState is 'complete' Style.observer.disconnect() remStyle: ({addedNodes}) -> i = addedNodes.length while i-- {nodeName, rel, id, href, textContent} = node = addedNodes[i] if nodeName is 'STYLE' continue if id or /\.typeset/.test textContent else if nodeName is 'LINK' continue if rel and (!/stylesheet/.test(rel) or /flags.*\.css$/.test(href) or href[..3] is 'data') else continue $.rm node return generateFilter: (id, values) -> """<%= grunt.file.read('src/General/html/Features/Filters.svg').replace(/>\s+<') %>""" matrix: -> colors = [] rgb = ['r', 'g', 'b'] for arg in arguments hex = (new Color arg).raw color = {} i = 0 while val = rgb[i] color[val] = parseInt(hex.substr((2 * i++), 2), 16) / 255 colors.push color colors filter: ([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}" silhouette: ([fg]) -> "0 0 0 0 #{fg.r} 0 0 0 0 #{fg.g} 0 0 0 0 #{fg.b}" layout: """<%= grunt.file.read('src/General/css/layout.css').replace(/\s+/g, ' ').trim() + ' ' + grunt.file.read('src/General/css/font-awesome.css').replace(/\s+/g, ' ').replace(/\\/g, '\\\\').trim() %>""" dynamic: -> sidebarLocation = if Conf["Sidebar Location"] is "left" ["left", "right"] else ["right", "left" ] if Conf['editMode'] is "theme" editSpace = {} editSpace[sidebarLocation[1]] = 300 editSpace[sidebarLocation[0]] = 0 else editSpace = left: 0 right: 0 """<%= grunt.file.read('src/General/css/dynamic.css').replace(/\s+/g, ' ').trim() %>""" setTheme: (theme) -> Style.sheets.theme.textContent = Style.theme theme theme: (theme) -> bgColor = new Color backgroundC = theme["Background Color"] replybg = new Color theme["Reply Background"] replyRGB = "rgb(#{replybg.shiftRGB parseInt(Conf['Silhouette Contrast'], 10), true})" Style.lightTheme = bgColor.isLight() svgs = [ ['captcha-filter', "values='#{Style.filter Style.matrix theme["Text"], theme["Input Background"]} 0 0 0 1 0'"] ['mascot-filter', "values='#{Style.silhouette Style.matrix replyRGB} 0 0 0 1 0'"] ['grayscale', 'id="color" type="saturate" values="0"'] ['icons-filter', "values='-.6 0 0 0 1 0 -.6 0 0 1 0 0 -.6 0 1 0 0 0 1 0'"] ] for svg, i in svgs <% if (type === 'crx') { %> svgs[i] <% } else { %> Style.svgs[svg[0].replace /\-/, ""] <% } %> = Style.generateFilter svg[0], svg[1] <% if (type === 'crx') { %> Style.svgs.el.innerHTML = svgs.join '' <% } %> """<%= grunt.file.read('src/General/css/theme.css').replace(/\s+/g, ' ').trim() %>""" + <%= grunt.file.read('src/General/css/themeoptions.css').replace(/\s+/g, ' ').trim() %> iconPositions: -> # Slideout Navigation slideNav = $.el 'span', id: 'so-nav' innerHTML: '' exec = -> if g.VIEW is 'catalog' then $ '#threads .thread' else true $.asap exec, -> $.add slideNav, $.id('boardNavDesktopFoot') Header.addShortcut slideNav, true # Announcements if Conf['Announcements'] is 'slideout' if (psa = $.id 'globalMessage') and !psa.hidden psaIcon = $.el 'i', id: 'so-psa' innerHTML: '' $.add psaIcon, psa Header.addShortcut psaIcon, true if g.VIEW is 'thread' el = $('body > div.navLinks > a') el.textContent = '' el.id = 'returnIcon' el.className = 'a-icon' Header.addShortcut el, true padding: -> navHeight = Header.bar.offsetHeight pageHeight = ($ '.pagelist', d.body)?.offsetHeight or 15 Style.sheets.padding.textContent = """<%= grunt.file.read('src/General/css/padding.nav.css').replace(/\s+/g, ' ').trim() %> """ + if pageHeight """<%= grunt.file.read('src/General/css/padding.pages.css').replace(/\s+/g, ' ').trim() %>""" else ''