Filter = filters: {} init: -> return if g.VIEW is 'catalog' or !Conf['Filter'] unless Conf['Filtered Backlinks'] $.addClass doc, 'hide-backlinks' for key of Config.filter @filters[key] = [] for filter in Conf[key].split '\n' continue if filter[0] is '#' unless regexp = filter.match /\/(.+)\/(\w*)/ continue # Don't mix up filter flags with the regular expression. filter = filter.replace regexp[0], '' # Do not add this filter to the list if it's not a global one # and it's not specifically applicable to the current board. # Defaults to global. boards = filter.match(/boards:([^;]+)/)?[1].toLowerCase() or 'global' if boards isnt 'global' and g.BOARD.ID not in boards.split ',' continue if key in ['uniqueID', 'MD5'] # MD5 filter will use strings instead of regular expressions. regexp = regexp[1] else try # Please, don't write silly regular expressions. regexp = RegExp regexp[1], regexp[2] catch err # I warned you, bro. new Notice 'warning', err.message, 60 continue # Filter OPs along with their threads, replies only, or both. # Defaults to both. op = filter.match(/[^t]op:(yes|no|only)/)?[1] or 'yes' # Overrule the `Show Stubs` setting. # Defaults to stub showing. stub = switch filter.match(/stub:(yes|no)/)?[1] when 'yes' true when 'no' false else Conf['Stubs'] # Highlight the post, or hide it. # If not specified, the highlight class will be filter-highlight. # Defaults to post hiding. if hl = /highlight/.test filter hl = filter.match(/highlight:(\w+)/)?[1] or 'filter-highlight' # Put highlighted OP's thread on top of the board page or not. # Defaults to on top. top = filter.match(/top:(yes|no)/)?[1] or 'yes' top = top is 'yes' # Turn it into a boolean @filters[key].push @createFilter regexp, op, stub, hl, top # Only execute filter types that contain valid filters. unless @filters[key].length delete @filters[key] return unless Object.keys(@filters).length Post.callbacks.push name: 'Filter' cb: @node createFilter: (regexp, op, stub, hl, top) -> test = if typeof regexp is 'string' # MD5 checking (value) -> regexp is value else (value) -> regexp.test value settings = hide: !hl stub: stub class: hl top: top (value, isReply) -> if isReply and op is 'only' or !isReply and op is 'no' return false unless test value return false settings node: -> return if @isClone or @isFetchedQuote for key of Filter.filters value = Filter[key] @ # Continue if there's nothing to filter (no tripcode for example). continue if value is false for filter in Filter.filters[key] unless result = filter value, @isReply continue # Hide if result.hide if @isReply PostHiding.hide @, result.stub else if g.VIEW is 'index' ThreadHiding.hide @thread, result.stub else continue return # Highlight $.addClass @nodes.root, result.class if !@isReply and result.top @thread.isOnTop = true name: (post) -> if 'name' of post.info return post.info.name false uniqueID: (post) -> if 'uniqueID' of post.info return post.info.uniqueID false tripcode: (post) -> if 'tripcode' of post.info return post.info.tripcode false capcode: (post) -> if 'capcode' of post.info return post.info.capcode false email: (post) -> if 'email' of post.info return post.info.email false subject: (post) -> if 'subject' of post.info return post.info.subject or false false comment: (post) -> if 'comment' of post.info return post.info.comment false flag: (post) -> if 'flag' of post.info return post.info.flag false filename: (post) -> if post.file return post.file.name false dimensions: (post) -> if post.file and post.file.isImage return post.file.dimensions false filesize: (post) -> if post.file return post.file.size false MD5: (post) -> if post.file return post.file.MD5 false menu: init: -> return if g.VIEW is 'catalog' or !Conf['Menu'] or !Conf['Filter'] div = $.el 'div', textContent: 'Filter' entry = el: div order: 50 open: (post) -> Filter.menu.post = post true subEntries: [] for type in [ ['Name', 'name'] ['Unique ID', 'uniqueID'] ['Tripcode', 'tripcode'] ['Capcode', 'capcode'] ['E-mail', 'email'] ['Subject', 'subject'] ['Comment', 'comment'] ['Flag', 'flag'] ['Filename', 'filename'] ['Image dimensions', 'dimensions'] ['Filesize', 'filesize'] ['Image MD5', 'MD5'] ] # Add a sub entry for each filter type. entry.subEntries.push Filter.menu.createSubEntry type[0], type[1] Menu.menu.addEntry entry createSubEntry: (text, type) -> el = $.el 'a', href: 'javascript:;' textContent: text el.dataset.type = type $.on el, 'click', Filter.menu.makeFilter return { el: el open: (post) -> value = Filter[type] post value isnt false } makeFilter: -> {type} = @dataset # Convert value -> regexp, unless type is MD5 value = Filter[type] Filter.menu.post re = if type in ['uniqueID', 'MD5'] then value else value.replace /// / | \\ | \^ | \$ | \n | \. | \( | \) | \{ | \} | \[ | \] | \? | \* | \+ | \| ///g, (c) -> if c is '\n' '\\n' else if c is '\\' '\\\\' else "\\#{c}" re = if type in ['uniqueID', 'MD5'] "/#{re}/" else "/^#{re}$/" # Add a new line before the regexp unless the text is empty. $.get type, Conf[type], (item) -> save = item[type] save = if save "#{save}\n#{re}" else re $.set type, save # Open the settings and display & focus the relevant filter textarea. Settings.open 'Filter' section = $ '.section-container' select = $ 'select[name=filter]', section select.value = type Settings.selectFilter.call select ta = $ 'textarea', section tl = ta.textLength ta.setSelectionRange tl, tl ta.focus()