Move most stuff from Site to g.SITE; Site.hostname -> g.SITE.ID; put data for other sites in g.sites.

This commit is contained in:
ccd0 2019-04-09 03:30:58 -07:00
parent 2450d04173
commit 38f63e6aa8
32 changed files with 97 additions and 92 deletions

View File

@ -26,7 +26,7 @@ PostHiding =
return unless Conf['Reply Hiding Buttons'] return unless Conf['Reply Hiding Buttons']
button = PostHiding.makeButton @, 'hide' button = PostHiding.makeButton @, 'hide'
if (sa = Site.selectors.sideArrows) if (sa = g.SITE.selectors.sideArrows)
sideArrows = $ sa, @nodes.root sideArrows = $ sa, @nodes.root
$.replace sideArrows.firstChild, button $.replace sideArrows.firstChild, button
sideArrows.removeAttribute 'class' sideArrows.removeAttribute 'class'

View File

@ -12,7 +12,7 @@ ThreadHiding =
cb: @node cb: @node
catalogSet: (board) -> catalogSet: (board) ->
return unless $.hasStorage and Site.software is 'yotsuba' return unless $.hasStorage and g.SITE.software is 'yotsuba'
hiddenThreads = ThreadHiding.db.get hiddenThreads = ThreadHiding.db.get
boardID: board.ID boardID: board.ID
defaultValue: {} defaultValue: {}
@ -20,7 +20,7 @@ ThreadHiding =
localStorage.setItem "4chan-hide-t-#{board}", JSON.stringify hiddenThreads localStorage.setItem "4chan-hide-t-#{board}", JSON.stringify hiddenThreads
catalogWatch: -> catalogWatch: ->
return unless $.hasStorage and Site.software is 'yotsuba' return unless $.hasStorage and g.SITE.software is 'yotsuba'
@hiddenThreads = JSON.parse(localStorage.getItem "4chan-hide-t-#{g.BOARD}") or {} @hiddenThreads = JSON.parse(localStorage.getItem "4chan-hide-t-#{g.BOARD}") or {}
Main.ready -> Main.ready ->
# 4chan's catalog sets the style to "display: none;" when hiding or unhiding a thread. # 4chan's catalog sets the style to "display: none;" when hiding or unhiding a thread.

View File

@ -54,7 +54,7 @@ BoardConfig =
!data or data.is_archived !data or data.is_archived
noAudio: (boardID) -> noAudio: (boardID) ->
return false unless Site.software is 'yotsuba' return false unless g.SITE.software is 'yotsuba'
boards = @boards or Conf['boardConfig'].boards boards = @boards or Conf['boardConfig'].boards
boards and boards[boardID] and !boards[boardID].webm_audio boards and boards[boardID] and !boards[boardID].webm_audio

View File

@ -42,7 +42,7 @@ Build =
ID: data.no ID: data.no
threadID: data.resto or data.no threadID: data.resto or data.no
boardID: boardID boardID: boardID
siteID: siteID or Site.hostname siteID: siteID or g.SITE.ID
isReply: !!data.resto isReply: !!data.resto
# thread status # thread status
isSticky: !!data.sticky isSticky: !!data.sticky

View File

@ -13,20 +13,20 @@ Get =
{board} = root.dataset {board} = root.dataset
g.threads["#{if board then encodeURIComponent(board) else g.BOARD.ID}.#{root.id.match(/\d*$/)[0]}"] g.threads["#{if board then encodeURIComponent(board) else g.BOARD.ID}.#{root.id.match(/\d*$/)[0]}"]
threadFromNode: (node) -> threadFromNode: (node) ->
Get.threadFromRoot $.x "ancestor-or-self::#{Site.xpath.thread}", node Get.threadFromRoot $.x "ancestor-or-self::#{g.SITE.xpath.thread}", node
postFromRoot: (root) -> postFromRoot: (root) ->
return null unless root? return null unless root?
post = g.posts[root.dataset.fullID] post = g.posts[root.dataset.fullID]
index = root.dataset.clone index = root.dataset.clone
if index then post.clones[index] else post if index then post.clones[index] else post
postFromNode: (root) -> postFromNode: (root) ->
Get.postFromRoot $.x "ancestor-or-self::#{Site.xpath.postContainer}[1]", root Get.postFromRoot $.x "ancestor-or-self::#{g.SITE.xpath.postContainer}[1]", root
postDataFromLink: (link) -> postDataFromLink: (link) ->
if link.dataset.postID # resurrected quote if link.dataset.postID # resurrected quote
{boardID, threadID, postID} = link.dataset {boardID, threadID, postID} = link.dataset
threadID or= 0 threadID or= 0
else else
match = link.href.match Site.regexp.quotelink match = link.href.match g.SITE.regexp.quotelink
[boardID, threadID, postID] = match[1..] [boardID, threadID, postID] = match[1..]
postID or= threadID postID or= threadID
return { return {

View File

@ -92,7 +92,7 @@ Header =
$.add d.body, Header.hover $.add d.body, Header.hover
@setBarPosition Conf['Bottom Header'] @setBarPosition Conf['Bottom Header']
$.onExists doc, "#{Site.selectors.boardList} + *", Header.generateFullBoardList $.onExists doc, "#{g.SITE.selectors.boardList} + *", Header.generateFullBoardList
Main.ready -> Main.ready ->
if not (footer = $.id 'boardNavDesktopFoot') if not (footer = $.id 'boardNavDesktopFoot')
@ -165,7 +165,7 @@ Header =
generateFullBoardList: -> generateFullBoardList: ->
nodes = [] nodes = []
spacer = -> $.el 'span', className: 'spacer' spacer = -> $.el 'span', className: 'spacer'
items = $.X './/a|.//text()[not(ancestor::a)]', $(Site.selectors.boardList) items = $.X './/a|.//text()[not(ancestor::a)]', $(g.SITE.selectors.boardList)
i = 0 i = 0
while node = items.snapshotItem i++ while node = items.snapshotItem i++
switch node.nodeName switch node.nodeName

View File

@ -592,7 +592,7 @@ Index =
return return
Index.req = $.whenModified( Index.req = $.whenModified(
Site.urls.catalogJSON({boardID: g.BOARD.ID}), g.SITE.urls.catalogJSON({boardID: g.BOARD.ID}),
'Index', 'Index',
Index.load Index.load
) )

View File

@ -199,7 +199,7 @@ Settings =
$.on button, 'click', -> $.on button, 'click', ->
@textContent = 'Hidden: 0' @textContent = 'Hidden: 0'
$.get 'hiddenThreads', {}, ({hiddenThreads}) -> $.get 'hiddenThreads', {}, ({hiddenThreads}) ->
if $.hasStorage and Site.software is 'yotsuba' if $.hasStorage and g.SITE.software is 'yotsuba'
for boardID of hiddenThreads.boards for boardID of hiddenThreads.boards
localStorage.removeItem "4chan-hide-t-#{boardID}" localStorage.removeItem "4chan-hide-t-#{boardID}"
($.delete ['hiddenThreads', 'hiddenPosts']) ($.delete ['hiddenThreads', 'hiddenPosts'])

View File

@ -65,7 +65,7 @@ Test =
testOne: (post) -> testOne: (post) ->
Test.postsRemaining++ Test.postsRemaining++
$.cache Site.urls.threadJSON({boardID: post.boardID, threadID: post.threadID}), -> $.cache g.SITE.urls.threadJSON({boardID: post.boardID, threadID: post.threadID}), ->
return unless @response return unless @response
{posts} = @response {posts} = @response
Build.spoilerRange[post.board.ID] = posts[0].custom_spoiler Build.spoilerRange[post.board.ID] = posts[0].custom_spoiler

View File

@ -82,7 +82,7 @@ Gallery =
$.on window, 'resize', Gallery.cb.setHeight $.on window, 'resize', Gallery.cb.setHeight
for postThumb in $$ Site.selectors.file.thumb for postThumb in $$ g.SITE.selectors.file.thumb
continue unless (post = Get.postFromNode postThumb) continue unless (post = Get.postFromNode postThumb)
continue unless post.file?.thumb continue unless post.file?.thumb
Gallery.generateThumb post Gallery.generateThumb post

View File

@ -54,7 +54,7 @@ ImageCommon =
clearTimeout timeoutID if delay? clearTimeout timeoutID if delay?
cb URL cb URL
$.ajax Site.urls.threadJSON({boardID: post.boardID, threadID: post.threadID}), onloadend: -> $.ajax g.SITE.urls.threadJSON({boardID: post.boardID, threadID: post.threadID}), onloadend: ->
post.kill !post.isClone if @status is 404 post.kill !post.isClone if @status is 404
return redirect() if @status isnt 200 return redirect() if @status isnt 200
for postObj in @response.posts for postObj in @response.posts

View File

@ -23,7 +23,7 @@ ImageHover =
return unless doc.contains @ return unless doc.contains @
{file} = post {file} = post
{isVideo} = file {isVideo} = file
return if file.isExpanding or file.isExpanded or Site.isThumbExpanded?(file) return if file.isExpanding or file.isExpanded or g.SITE.isThumbExpanded?(file)
error = ImageHover.error post error = ImageHover.error post
if ImageCommon.cache?.dataset.fullID is post.fullID if ImageCommon.cache?.dataset.fullID is post.fullID
el = ImageCommon.popCache() el = ImageCommon.popCache()

View File

@ -1,6 +1,6 @@
CatalogLinks = CatalogLinks =
init: -> init: ->
if Site.software is 'yotsuba' and (Conf['External Catalog'] or Conf['JSON Index']) and !(Conf['JSON Index'] and g.VIEW is 'index') if g.SITE.software is 'yotsuba' and (Conf['External Catalog'] or Conf['JSON Index']) and !(Conf['JSON Index'] and g.VIEW is 'index')
selector = switch g.VIEW selector = switch g.VIEW
when 'thread', 'archive' then '.navLinks.desktop > a' when 'thread', 'archive' then '.navLinks.desktop > a'
when 'catalog' then '.navLinks > :first-child > a' when 'catalog' then '.navLinks > :first-child > a'
@ -20,7 +20,7 @@ CatalogLinks =
$.after link.parentNode, [$.tn(' '), catalogLink] $.after link.parentNode, [$.tn(' '), catalogLink]
return return
if Site.software is 'yotsuba' and Conf['JSON Index'] and Conf['Use <%= meta.name %> Catalog'] if g.SITE.software is 'yotsuba' and Conf['JSON Index'] and Conf['Use <%= meta.name %> Catalog']
Callbacks.Post.push Callbacks.Post.push
name: 'Catalog Link Rewrite' name: 'Catalog Link Rewrite'
cb: @node cb: @node

View File

@ -23,7 +23,7 @@ ExpandComment =
return return
return if not (a = $ '.abbr > a', post.nodes.comment) return if not (a = $ '.abbr > a', post.nodes.comment)
a.textContent = "Post No.#{post} Loading..." a.textContent = "Post No.#{post} Loading..."
$.cache Site.urls.threadJSON({boardID: post.boardID, threadID: post.threadID}), -> ExpandComment.parse @, a, post $.cache g.SITE.urls.threadJSON({boardID: post.boardID, threadID: post.threadID}), -> ExpandComment.parse @, a, post
contract: (post) -> contract: (post) ->
return unless post.nodes.shortComment return unless post.nodes.shortComment

View File

@ -54,7 +54,7 @@ ExpandThread =
expand: (thread, a) -> expand: (thread, a) ->
ExpandThread.statuses[thread] = status = {} ExpandThread.statuses[thread] = status = {}
a.textContent = Build.summaryText '...', a.textContent.match(/\d+/g)... a.textContent = Build.summaryText '...', a.textContent.match(/\d+/g)...
status.req = $.cache Site.urls.threadJSON({boardID: thread.board.ID, threadID: thread.ID}), -> status.req = $.cache g.SITE.urls.threadJSON({boardID: thread.board.ID, threadID: thread.ID}), ->
return if @ isnt status.req # aborted return if @ isnt status.req # aborted
delete status.req delete status.req
ExpandThread.parse @, thread, a ExpandThread.parse @, thread, a

View File

@ -1,6 +1,6 @@
Fourchan = Fourchan =
init: -> init: ->
return unless Site.software is 'yotsuba' and g.VIEW in ['index', 'thread', 'archive'] return unless g.SITE.software is 'yotsuba' and g.VIEW in ['index', 'thread', 'archive']
BoardConfig.ready @initBoard BoardConfig.ready @initBoard
Main.ready @initReady Main.ready @initReady

View File

@ -1,6 +1,6 @@
Tinyboard = Tinyboard =
init: -> init: ->
return unless Site.software is 'tinyboard' return unless g.SITE.software is 'tinyboard'
if g.VIEW is 'thread' if g.VIEW is 'thread'
Main.ready -> Main.ready ->
$.global -> $.global ->

View File

@ -76,7 +76,7 @@ ThreadStats =
return return
ThreadStats.timeout = setTimeout ThreadStats.fetchPage, 2 * $.MINUTE ThreadStats.timeout = setTimeout ThreadStats.fetchPage, 2 * $.MINUTE
$.whenModified( $.whenModified(
Site.urls.threadsListJSON({boardID: ThreadStats.thread.board}), g.SITE.urls.threadsListJSON({boardID: ThreadStats.thread.board}),
'ThreadStats', 'ThreadStats',
ThreadStats.onThreadsLoad ThreadStats.onThreadsLoad
) )

View File

@ -138,7 +138,7 @@ ThreadUpdater =
ThreadUpdater.setInterval() ThreadUpdater.setInterval()
when 404 when 404
# XXX workaround for 4chan sending false 404s # XXX workaround for 4chan sending false 404s
$.ajax Site.urls.catalogJSON({boardID: ThreadUpdater.thread.board.ID}), onloadend: -> $.ajax g.SITE.urls.catalogJSON({boardID: ThreadUpdater.thread.board.ID}), onloadend: ->
if @status is 200 if @status is 200
confirmed = true confirmed = true
for page in @response for page in @response
@ -234,7 +234,7 @@ ThreadUpdater =
delete ThreadUpdater.req delete ThreadUpdater.req
oldReq.abort() oldReq.abort()
ThreadUpdater.req = $.whenModified( ThreadUpdater.req = $.whenModified(
Site.urls.threadJSON({boardID: ThreadUpdater.thread.board.ID, threadID: ThreadUpdater.thread.ID}), g.SITE.urls.threadJSON({boardID: ThreadUpdater.thread.board.ID, threadID: ThreadUpdater.thread.ID}),
'ThreadUpdater', 'ThreadUpdater',
ThreadUpdater.cb.load, ThreadUpdater.cb.load,
{timeout: $.MINUTE} {timeout: $.MINUTE}

View File

@ -93,7 +93,7 @@ ThreadWatcher =
href: 'javascript:;' href: 'javascript:;'
className: 'watch-thread-link' className: 'watch-thread-link'
$.before $('input', @nodes.info), toggler $.before $('input', @nodes.info), toggler
siteID = Site.hostname siteID = g.SITE.ID
boardID = @board.ID boardID = @board.ID
threadID = @thread.ID threadID = @thread.ID
data = ThreadWatcher.db.get {siteID, boardID, threadID} data = ThreadWatcher.db.get {siteID, boardID, threadID}
@ -148,7 +148,7 @@ ThreadWatcher =
ThreadWatcher.add g.threads[boardID + '.' + threadID] or new Thread(threadID, g.boards[boardID] or new Board(boardID)) ThreadWatcher.add g.threads[boardID + '.' + threadID] or new Thread(threadID, g.boards[boardID] or new Board(boardID))
onIndexUpdate: (e) -> onIndexUpdate: (e) ->
{db} = ThreadWatcher {db} = ThreadWatcher
siteID = Site.hostname siteID = g.SITE.ID
boardID = g.BOARD.ID boardID = g.BOARD.ID
nKilled = 0 nKilled = 0
for threadID, data of db.data[siteID].boards[boardID] when not data?.isDead and "#{boardID}.#{threadID}" not in e.detail.threads for threadID, data of db.data[siteID].boards[boardID] when not data?.isDead and "#{boardID}.#{threadID}" not in e.detail.threads
@ -185,7 +185,7 @@ ThreadWatcher =
else else
ThreadWatcher.status.textContent = "#{Math.round(ThreadWatcher.fetched / ThreadWatcher.requests.length * 100)}%" ThreadWatcher.status.textContent = "#{Math.round(ThreadWatcher.fetched / ThreadWatcher.requests.length * 100)}%"
cb.apply @, args cb.apply @, args
ajax = if siteID is Site.hostname then $.ajax else CrossOrigin.ajax ajax = if siteID is g.SITE.ID then $.ajax else CrossOrigin.ajax
if force if force
delete $.lastModified.ThreadWatcher?[url] delete $.lastModified.ThreadWatcher?[url]
req = $.whenModified( req = $.whenModified(
@ -382,7 +382,7 @@ ThreadWatcher =
all = [] all = []
for siteID, boards of ThreadWatcher.db.data for siteID, boards of ThreadWatcher.db.data
for boardID, threads of boards.boards for boardID, threads of boards.boards
if Conf['Current Board'] and (siteID isnt Site.hostname or boardID isnt g.BOARD.ID) if Conf['Current Board'] and (siteID isnt g.SITE.ID or boardID isnt g.BOARD.ID)
continue continue
if groupByBoard if groupByBoard
all.push (cont = []) all.push (cont = [])
@ -466,7 +466,7 @@ ThreadWatcher =
ThreadWatcher.setPrefixes threads ThreadWatcher.setPrefixes threads
for {siteID, boardID, threadID, data} in threads for {siteID, boardID, threadID, data} in threads
# Add missing excerpt for threads added by Auto Watch # Add missing excerpt for threads added by Auto Watch
if not data.excerpt? and siteID is Site.hostname and (thread = g.threads["#{boardID}.#{threadID}"]) and thread.OP if not data.excerpt? and siteID is g.SITE.ID and (thread = g.threads["#{boardID}.#{threadID}"]) and thread.OP
ThreadWatcher.db.extend {boardID, threadID, val: {excerpt: Get.threadExcerpt thread}} ThreadWatcher.db.extend {boardID, threadID, val: {excerpt: Get.threadExcerpt thread}}
nodes.push ThreadWatcher.makeLine siteID, boardID, threadID, data nodes.push ThreadWatcher.makeLine siteID, boardID, threadID, data
{list} = ThreadWatcher {list} = ThreadWatcher
@ -522,7 +522,7 @@ ThreadWatcher =
ThreadWatcher.db.extend {boardID, threadID, val: {isDead: true, page: undefined, lastPage: undefined, unread: undefined, quotingYou: undefined}}, cb ThreadWatcher.db.extend {boardID, threadID, val: {isDead: true, page: undefined, lastPage: undefined, unread: undefined, quotingYou: undefined}}, cb
toggle: (thread) -> toggle: (thread) ->
siteID = Site.hostname siteID = g.SITE.ID
boardID = thread.board.ID boardID = thread.board.ID
threadID = thread.ID threadID = thread.ID
if ThreadWatcher.db.get {boardID, threadID} if ThreadWatcher.db.get {boardID, threadID}
@ -532,7 +532,7 @@ ThreadWatcher =
add: (thread) -> add: (thread) ->
data = {} data = {}
siteID = Site.hostname siteID = g.SITE.ID
boardID = thread.board.ID boardID = thread.board.ID
threadID = thread.ID threadID = thread.ID
if thread.isDead if thread.isDead
@ -546,7 +546,7 @@ ThreadWatcher =
addRaw: (boardID, threadID, data) -> addRaw: (boardID, threadID, data) ->
ThreadWatcher.db.set {boardID, threadID, val: data} ThreadWatcher.db.set {boardID, threadID, val: data}
ThreadWatcher.refresh() ThreadWatcher.refresh()
thread = {siteID: Site.hostname, boardID, threadID, data, force: true} thread = {siteID: g.SITE.ID, boardID, threadID, data, force: true}
if Conf['Show Page'] and !data.isDead if Conf['Show Page'] and !data.isDead
ThreadWatcher.fetchBoard [thread] ThreadWatcher.fetchBoard [thread]
else if ThreadWatcher.unreadEnabled and Conf['Show Unread Count'] else if ThreadWatcher.unreadEnabled and Conf['Show Unread Count']

View File

@ -34,7 +34,7 @@ Unread =
textContent: 'Test Post Order' textContent: 'Test Post Order'
$.on testLink, 'click', -> $.on testLink, 'click', ->
list1 = (x.ID for x in Unread.order.order()) list1 = (x.ID for x in Unread.order.order())
list2 = (+x.id.match(/\d*$/)[0] for x in $$ (if Site.isOPContainerThread then "#{Site.selectors.thread}, " else '') + Site.selectors.postContainer) list2 = (+x.id.match(/\d*$/)[0] for x in $$ (if g.SITE.isOPContainerThread then "#{g.SITE.selectors.thread}, " else '') + g.SITE.selectors.postContainer)
pass = do -> pass = do ->
return false unless list1.length is list2.length return false unless list1.length is list2.length
for i in [0...list1.length] by 1 for i in [0...list1.length] by 1
@ -223,7 +223,7 @@ Unread =
Unread.saveThreadWatcherCount() Unread.saveThreadWatcherCount()
if Conf['Unread Favicon'] and Site.software is 'yotsuba' if Conf['Unread Favicon'] and g.SITE.software is 'yotsuba'
{isDead} = Unread.thread {isDead} = Unread.thread
Favicon.el.href = Favicon.el.href =
if countQuotingYou if countQuotingYou
@ -238,7 +238,7 @@ Unread =
saveThreadWatcherCount: $.debounce 2 * $.SECOND, -> saveThreadWatcherCount: $.debounce 2 * $.SECOND, ->
$.forceSync 'Remember Last Read Post' $.forceSync 'Remember Last Read Post'
if Conf['Remember Last Read Post'] and (!Unread.thread.isDead or Unread.thread.isArchived) if Conf['Remember Last Read Post'] and (!Unread.thread.isDead or Unread.thread.isArchived)
ThreadWatcher.update Site.hostname, Unread.thread.board.ID, Unread.thread.ID, ThreadWatcher.update g.SITE.ID, Unread.thread.board.ID, Unread.thread.ID,
isDead: Unread.thread.isDead isDead: Unread.thread.isDead
unread: Unread.posts.size unread: Unread.posts.size
quotingYou: !!(if !Conf['Require OP Quote Link'] and QuoteYou.isYou(Unread.thread.OP) then Unread.posts.size else Unread.postsQuotingYou.size) quotingYou: !!(if !Conf['Require OP Quote Link'] and QuoteYou.isYou(Unread.thread.OP) then Unread.posts.size else Unread.postsQuotingYou.size)

View File

@ -64,7 +64,7 @@ UnreadIndex =
firstUnread = post firstUnread = post
hr = UnreadIndex.hr[thread.fullID] hr = UnreadIndex.hr[thread.fullID]
if firstUnread and (repliesRead or (lastReadPost is thread.OP.ID and (!$(Site.selectors.summary, thread.nodes.root) or thread.ID of ExpandThread.statuses))) if firstUnread and (repliesRead or (lastReadPost is thread.OP.ID and (!$(g.SITE.selectors.summary, thread.nodes.root) or thread.ID of ExpandThread.statuses)))
if !hr if !hr
hr = UnreadIndex.hr[thread.fullID] = $.el 'hr', hr = UnreadIndex.hr[thread.fullID] = $.el 'hr',
className: 'unread-line' className: 'unread-line'
@ -87,7 +87,7 @@ UnreadIndex =
href: 'javascript:;' href: 'javascript:;'
textContent: 'Mark Read' textContent: 'Mark Read'
$.on link, 'click', UnreadIndex.markRead $.on link, 'click', UnreadIndex.markRead
if (divider = $ Site.selectors.threadDivider, thread.nodes.root) # divider inside thread as in Tinyboard if (divider = $ g.SITE.selectors.threadDivider, thread.nodes.root) # divider inside thread as in Tinyboard
$.before divider, link $.before divider, link
else else
$.add thread.nodes.root, link $.add thread.nodes.root, link
@ -105,6 +105,6 @@ UnreadIndex =
val: lastPost val: lastPost
$.rm UnreadIndex.hr[thread.fullID] $.rm UnreadIndex.hr[thread.fullID]
thread.nodes.root.classList.remove 'unread-thread' thread.nodes.root.classList.remove 'unread-thread'
ThreadWatcher.update Site.hostname, thread.board.ID, thread.ID, ThreadWatcher.update g.SITE.ID, thread.board.ID, thread.ID,
unread: 0 unread: 0
quotingYou: false quotingYou: false

View File

@ -317,7 +317,7 @@ QR =
$.replace node, $.tn '\n' $.replace node, $.tn '\n'
for node in $$ 'br', frag for node in $$ 'br', frag
$.replace node, $.tn '\n>' unless node is frag.lastChild $.replace node, $.tn '\n>' unless node is frag.lastChild
Site.insertTags?(frag) g.SITE.insertTags?(frag)
for node in $$ '.linkify[data-original]', frag for node in $$ '.linkify[data-original]', frag
$.replace node, $.tn node.dataset.original $.replace node, $.tn node.dataset.original
for node in $$ '.embedder', frag for node in $$ '.embedder', frag

View File

@ -19,7 +19,7 @@ class DataBoard
@data['4chan.org'] = {boards, lastChecked} @data['4chan.org'] = {boards, lastChecked}
delete @data.boards delete @data.boards
delete @data.lastChecked delete @data.lastChecked
@data[Site.hostname] or= boards: {} @data[g.SITE.ID] or= boards: {}
changes: [] changes: []
@ -47,7 +47,7 @@ class DataBoard
cb?() cb?()
delete: ({siteID, boardID, threadID, postID}) -> delete: ({siteID, boardID, threadID, postID}) ->
siteID or= Site.hostname siteID or= g.SITE.ID
return unless @data[siteID] return unless @data[siteID]
@save => @save =>
if postID if postID
@ -76,7 +76,7 @@ class DataBoard
, cb , cb
setUnsafe: ({siteID, boardID, threadID, postID, val}) -> setUnsafe: ({siteID, boardID, threadID, postID, val}) ->
siteID or= Site.hostname siteID or= g.SITE.ID
@data[siteID] or= boards: {} @data[siteID] or= boards: {}
if postID isnt undefined if postID isnt undefined
((@data[siteID].boards[boardID] or= {})[threadID] or= {})[postID] = val ((@data[siteID].boards[boardID] or= {})[threadID] or= {})[postID] = val
@ -101,7 +101,7 @@ class DataBoard
@data[key] = Date.now() @data[key] = Date.now()
get: ({siteID, boardID, threadID, postID, defaultValue}) -> get: ({siteID, boardID, threadID, postID, defaultValue}) ->
siteID or= Site.hostname siteID or= g.SITE.ID
if board = @data[siteID]?.boards[boardID] if board = @data[siteID]?.boards[boardID]
unless threadID? unless threadID?
if postID? if postID?
@ -119,7 +119,7 @@ class DataBoard
val or defaultValue val or defaultValue
clean: -> clean: ->
siteID = Site.hostname siteID = g.SITE.ID
for boardID, val of @data[siteID].boards for boardID, val of @data[siteID].boards
@deleteIfEmpty {siteID, boardID} @deleteIfEmpty {siteID, boardID}
now = Date.now() now = Date.now()
@ -131,12 +131,12 @@ class DataBoard
ajaxClean: (boardID) -> ajaxClean: (boardID) ->
that = @ that = @
siteID = Site.hostname siteID = g.SITE.ID
threadsList = Site.urls.threadsListJSON?({siteID, boardID}) threadsList = g.SITE.urls.threadsListJSON?({siteID, boardID})
return unless threadsList return unless threadsList
$.cache threadsList, -> $.cache threadsList, ->
return unless @status is 200 return unless @status is 200
archiveList = Site.urls.archiveListJSON?({siteID, boardID}) archiveList = g.SITE.urls.archiveListJSON?({siteID, boardID})
return that.ajaxCleanParse(boardID, @response) unless archiveList return that.ajaxCleanParse(boardID, @response) unless archiveList
response1 = @response response1 = @response
$.cache archiveList, -> $.cache archiveList, ->
@ -144,7 +144,7 @@ class DataBoard
that.ajaxCleanParse(boardID, response1, @response) that.ajaxCleanParse(boardID, response1, @response)
ajaxCleanParse: (boardID, response1, response2) -> ajaxCleanParse: (boardID, response1, response2) ->
siteID = Site.hostname siteID = g.SITE.ID
return if not (board = @data[siteID].boards[boardID]) return if not (board = @data[siteID].boards[boardID])
threads = {} threads = {}
if response1 if response1

View File

@ -16,7 +16,7 @@ class Fetcher
@root.textContent = "Loading post No.#{@postID}..." @root.textContent = "Loading post No.#{@postID}..."
if @threadID if @threadID
that = @ that = @
$.cache Site.urls.threadJSON({boardID: @boardID, threadID: @threadID}), ({isCached}) -> $.cache g.SITE.urls.threadJSON({boardID: @boardID, threadID: @threadID}), ({isCached}) ->
that.fetchedPost @, isCached that.fetchedPost @, isCached
else else
@archivedPost() @archivedPost()
@ -81,7 +81,7 @@ class Fetcher
if post.no isnt @postID if post.no isnt @postID
# Cached requests can be stale and must be rechecked. # Cached requests can be stale and must be rechecked.
if isCached if isCached
api = Site.urls.threadJSON({boardID: @boardID, threadID: @threadID}) api = g.SITE.urls.threadJSON({boardID: @boardID, threadID: @threadID})
$.cleanCache (url) -> url is api $.cleanCache (url) -> url is api
that = @ that = @
$.cache api, -> $.cache api, ->

View File

@ -44,7 +44,7 @@ Post.Clone = class extends Post
@file = {} @file = {}
for key, val of @origin.file for key, val of @origin.file
@file[key] = val @file[key] = val
for key, selector of Site.selectors.file for key, selector of g.SITE.selectors.file
@file[key] = $ selector, @nodes.root @file[key] = $ selector, @nodes.root
@file.thumbLink = @file.thumb?.parentNode @file.thumbLink = @file.thumb?.parentNode
@file.fullImage = $ '.full-image', @file.thumbLink if @file.thumbLink @file.fullImage = $ '.full-image', @file.thumbLink if @file.thumbLink

View File

@ -9,7 +9,7 @@ class Post
@ID = +root.id.match(/\d*$/)[0] @ID = +root.id.match(/\d*$/)[0]
@threadID = @thread.ID @threadID = @thread.ID
@boardID = @board.ID @boardID = @board.ID
@siteID = Site.hostname @siteID = g.SITE.ID
@fullID = "#{@board}.#{@ID}" @fullID = "#{@board}.#{@ID}"
@context = @ @context = @
@isReply = (@ID isnt @threadID) @isReply = (@ID isnt @threadID)
@ -21,7 +21,7 @@ class Post
if not @isReply if not @isReply
@thread.OP = @ @thread.OP = @
for key in ['isSticky', 'isClosed', 'isArchived'] for key in ['isSticky', 'isClosed', 'isArchived']
@thread[key] = if (selector = Site.selectors.icons[key]) then !!$(selector, @nodes.info) else false @thread[key] = if (selector = g.SITE.selectors.icons[key]) then !!$(selector, @nodes.info) else false
if @thread.isArchived if @thread.isArchived
@thread.isClosed = true @thread.isClosed = true
@thread.kill() @thread.kill()
@ -67,12 +67,12 @@ class Post
g.posts.push @fullID, @ g.posts.push @fullID, @
parseNodes: (root) -> parseNodes: (root) ->
s = Site.selectors s = g.SITE.selectors
post = $(s.post, root) or root post = $(s.post, root) or root
info = $ s.infoRoot, post info = $ s.infoRoot, post
nodes = nodes =
root: root root: root
bottom: if @isReply or !Site.isOPContainerThread then root else $(s.opBottom, root) bottom: if @isReply or !g.SITE.isOPContainerThread then root else $(s.opBottom, root)
post: post post: post
info: info info: info
comment: $ s.comment, post comment: $ s.comment, post
@ -81,7 +81,7 @@ class Post
embedlinks: [] embedlinks: []
for key, selector of s.info for key, selector of s.info
nodes[key] = $ selector, info nodes[key] = $ selector, info
Site.parseNodes?(@, nodes) g.SITE.parseNodes?(@, nodes)
nodes.uniqueIDRoot or= nodes.uniqueID nodes.uniqueIDRoot or= nodes.uniqueID
# XXX Edge invalidates HTMLCollections when an ancestor node is inserted into another node. # XXX Edge invalidates HTMLCollections when an ancestor node is inserted into another node.
@ -106,7 +106,7 @@ class Post
# 'Comment too long'... # 'Comment too long'...
# EXIF data. (/p/) # EXIF data. (/p/)
@nodes.commentClean = bq = @nodes.comment.cloneNode true @nodes.commentClean = bq = @nodes.comment.cloneNode true
Site.cleanComment?(bq) g.SITE.cleanComment?(bq)
@info.comment = @nodesToText bq @info.comment = @nodesToText bq
commentDisplay: -> commentDisplay: ->
@ -119,13 +119,13 @@ class Post
# Trailing spaces. # Trailing spaces.
bq = @nodes.commentClean.cloneNode true bq = @nodes.commentClean.cloneNode true
@cleanSpoilers bq unless Conf['Remove Spoilers'] or Conf['Reveal Spoilers'] @cleanSpoilers bq unless Conf['Remove Spoilers'] or Conf['Reveal Spoilers']
Site.cleanCommentDisplay?(bq) g.SITE.cleanCommentDisplay?(bq)
@nodesToText(bq).trim().replace(/\s+$/gm, '') @nodesToText(bq).trim().replace(/\s+$/gm, '')
commentOrig: -> commentOrig: ->
# Get the comment's text for reposting purposes. # Get the comment's text for reposting purposes.
bq = @nodes.commentClean.cloneNode true bq = @nodes.commentClean.cloneNode true
Site.insertTags?(bq) g.SITE.insertTags?(bq)
@nodesToText bq @nodesToText bq
nodesToText: (bq) -> nodesToText: (bq) ->
@ -137,14 +137,14 @@ class Post
text text
cleanSpoilers: (bq) -> cleanSpoilers: (bq) ->
spoilers = $$ Site.selectors.spoiler, bq spoilers = $$ g.SITE.selectors.spoiler, bq
for node in spoilers for node in spoilers
$.replace node, $.tn '[spoiler]' $.replace node, $.tn '[spoiler]'
return return
parseQuotes: -> parseQuotes: ->
@quotes = [] @quotes = []
for quotelink in $$ Site.selectors.quotelink, @nodes.comment for quotelink in $$ g.SITE.selectors.quotelink, @nodes.comment
@parseQuote quotelink @parseQuote quotelink
return return
@ -155,7 +155,7 @@ class Post
# - catalog links. (>>>/b/catalog or >>>/b/search) # - catalog links. (>>>/b/catalog or >>>/b/search)
# - rules links. (>>>/a/rules) # - rules links. (>>>/a/rules)
# - text-board quotelinks. (>>>/img/1234) # - text-board quotelinks. (>>>/img/1234)
match = quotelink.href.match Site.regexp.quotelink match = quotelink.href.match g.SITE.regexp.quotelink
return unless match or (@isClone and quotelink.dataset.postID) # normal or resurrected quote return unless match or (@isClone and quotelink.dataset.postID) # normal or resurrected quote
@nodes.quotelinks.push quotelink @nodes.quotelinks.push quotelink
@ -168,12 +168,12 @@ class Post
parseFile: -> parseFile: ->
file = {} file = {}
for key, selector of Site.selectors.file for key, selector of g.SITE.selectors.file
file[key] = $ selector, @nodes.root file[key] = $ selector, @nodes.root
file.thumbLink = file.thumb?.parentNode file.thumbLink = file.thumb?.parentNode
return if not (file.text and file.link) return if not (file.text and file.link)
return if not Site.parseFile @, file return if not g.SITE.parseFile @, file
$.extend file, $.extend file,
url: file.link.href url: file.link.href

View File

@ -13,6 +13,7 @@ docSet = function() {
g = { g = {
VERSION: '<%= readJSON('/version.json').version %>', VERSION: '<%= readJSON('/version.json').version %>',
NAMESPACE: '<%= meta.name %>.', NAMESPACE: '<%= meta.name %>.',
sites: {},
boards: {} boards: {}
}; };

View File

@ -157,7 +157,7 @@ Main =
if ImageHost.test hostname if ImageHost.test hostname
return unless pathname[2] and not /[sm]\.jpg$/.test(pathname[2]) return unless pathname[2] and not /[sm]\.jpg$/.test(pathname[2])
$.asap (-> d.readyState isnt 'loading'), -> $.asap (-> d.readyState isnt 'loading'), ->
if Conf['404 Redirect'] and Site.is404?() if Conf['404 Redirect'] and g.SITE.is404?()
Redirect.navigate 'file', { Redirect.navigate 'file', {
boardID: g.BOARD.ID boardID: g.BOARD.ID
filename: pathname[pathname.length - 1] filename: pathname[pathname.length - 1]
@ -172,7 +172,7 @@ Main =
ImageCommon.addControls video ImageCommon.addControls video
return return
return if Site.isAuxiliaryPage?() return if g.SITE.isAuxiliaryPage?()
if pathname[2] in ['thread', 'res'] if pathname[2] in ['thread', 'res']
g.VIEW = 'thread' g.VIEW = 'thread'
@ -192,7 +192,7 @@ Main =
# c.time 'All initializations' # c.time 'All initializations'
for [name, feature] in Main.features for [name, feature] in Main.features
continue if Site.disabledFeatures and name in Site.disabledFeatures continue if g.SITE.disabledFeatures and name in g.SITE.disabledFeatures
# c.time "#{name} initialization" # c.time "#{name} initialization"
try try
feature.init() feature.init()
@ -213,7 +213,7 @@ Main =
# disable the mobile layout # disable the mobile layout
$('link[href*=mobile]', d.head)?.disabled = true $('link[href*=mobile]', d.head)?.disabled = true
doc.dataset.host = location.host doc.dataset.host = location.host
$.addClass doc, "sw-#{Site.software}" $.addClass doc, "sw-#{g.SITE.software}"
$.addClass doc, if g.VIEW is 'thread' then 'thread-view' else g.VIEW $.addClass doc, if g.VIEW is 'thread' then 'thread-view' else g.VIEW
$.onExists doc, '.ad-cnt, .adg-rects > .desktop', (ad) -> $.onExists ad, 'img, iframe', -> $.addClass doc, 'ads-loaded' $.onExists doc, '.ad-cnt, .adg-rects > .desktop', (ad) -> $.onExists ad, 'img, iframe', -> $.addClass doc, 'ads-loaded'
$.addClass doc, 'autohiding-scrollbar' if Conf['Autohiding Scrollbar'] $.addClass doc, 'autohiding-scrollbar' if Conf['Autohiding Scrollbar']
@ -235,7 +235,7 @@ Main =
setClass: -> setClass: ->
knownStyles = ['yotsuba', 'yotsuba-b', 'futaba', 'burichan', 'photon', 'tomorrow', 'spooky'] knownStyles = ['yotsuba', 'yotsuba-b', 'futaba', 'burichan', 'photon', 'tomorrow', 'spooky']
if Site.software is 'yotsuba' and g.VIEW is 'catalog' if g.SITE.software is 'yotsuba' and g.VIEW is 'catalog'
if (mainStyleSheet = $.id('base-css')) if (mainStyleSheet = $.id('base-css'))
style = mainStyleSheet.href.match(/catalog_(\w+)/)?[1].replace('_new', '').replace(/_+/g, '-') style = mainStyleSheet.href.match(/catalog_(\w+)/)?[1].replace('_new', '').replace(/_+/g, '-')
if style in knownStyles if style in knownStyles
@ -246,7 +246,7 @@ Main =
setStyle = -> setStyle = ->
# Use preconfigured CSS for 4chan's default themes. # Use preconfigured CSS for 4chan's default themes.
if Site.software is 'yotsuba' if g.SITE.software is 'yotsuba'
$.rmClass doc, style $.rmClass doc, style
style = null style = null
for styleSheet in styleSheets for styleSheet in styleSheets
@ -261,7 +261,7 @@ Main =
return return
# Determine proper dialog background color for other themes. # Determine proper dialog background color for other themes.
div = Site.bgColoredEl() div = g.SITE.bgColoredEl()
div.style.position = 'absolute'; div.style.position = 'absolute';
div.style.visibility = 'hidden'; div.style.visibility = 'hidden';
$.add d.body, div $.add d.body, div
@ -282,9 +282,9 @@ Main =
""" """
$.after $.id('fourchanx-css'), Main.bgColorStyle $.after $.id('fourchanx-css'), Main.bgColorStyle
$.onExists d.head, Site.selectors.styleSheet, (el) -> $.onExists d.head, g.SITE.selectors.styleSheet, (el) ->
mainStyleSheet = el mainStyleSheet = el
if Site.software is 'yotsuba' if g.SITE.software is 'yotsuba'
styleSheets = $$ 'link[rel="alternate stylesheet"]', d.head styleSheets = $$ 'link[rel="alternate stylesheet"]', d.head
new MutationObserver(setStyle).observe mainStyleSheet, { new MutationObserver(setStyle).observe mainStyleSheet, {
attributes: true attributes: true
@ -296,7 +296,7 @@ Main =
setStyle() setStyle()
initReady: -> initReady: ->
if Site.is404?() if g.SITE.is404?()
if g.VIEW is 'thread' if g.VIEW is 'thread'
ThreadWatcher.set404 g.BOARD.ID, g.THREADID, -> ThreadWatcher.set404 g.BOARD.ID, g.THREADID, ->
if Conf['404 Redirect'] if Conf['404 Redirect']
@ -308,7 +308,7 @@ Main =
return return
if Site.isIncomplete?() if g.SITE.isIncomplete?()
msg = $.el 'div', msg = $.el 'div',
<%= html('The page didn&#039;t load completely.<br>Some features may not work unless you <a href="javascript:;">reload</a>.') %> <%= html('The page didn&#039;t load completely.<br>Some features may not work unless you <a href="javascript:;">reload</a>.') %>
$.on $('a', msg), 'click', -> location.reload() $.on $('a', msg), 'click', -> location.reload()
@ -322,7 +322,7 @@ Main =
$.event '4chanXInitFinished' $.event '4chanXInitFinished'
initThread: -> initThread: ->
s = Site.selectors s = g.SITE.selectors
if (board = $ s.board) if (board = $ s.board)
threads = [] threads = []
posts = [] posts = []
@ -336,7 +336,7 @@ Main =
Main.handleErrors errors if errors.length Main.handleErrors errors if errors.length
if g.VIEW is 'thread' if g.VIEW is 'thread'
Site.parseThreadMetadata?(threads[0]) g.SITE.parseThreadMetadata?(threads[0])
Main.callbackNodes 'Thread', threads Main.callbackNodes 'Thread', threads
Main.callbackNodesDB 'Post', posts, -> Main.callbackNodesDB 'Post', posts, ->
@ -360,13 +360,13 @@ Main =
thread = new Thread threadID, boardObj thread = new Thread threadID, boardObj
thread.nodes.root = threadRoot thread.nodes.root = threadRoot
threads.push thread threads.push thread
postRoots = $$ Site.selectors.postContainer, threadRoot postRoots = $$ g.SITE.selectors.postContainer, threadRoot
postRoots.unshift threadRoot if Site.isOPContainerThread postRoots.unshift threadRoot if g.SITE.isOPContainerThread
Main.parsePosts postRoots, thread, posts, errors Main.parsePosts postRoots, thread, posts, errors
Main.addPostsObserver.observe threadRoot, {childList: true} Main.addPostsObserver.observe threadRoot, {childList: true}
parsePosts: (postRoots, thread, posts, errors) -> parsePosts: (postRoots, thread, posts, errors) ->
for postRoot in postRoots when !postRoot.dataset.fullID and $(Site.selectors.comment, postRoot) for postRoot in postRoots when !postRoot.dataset.fullID and $(g.SITE.selectors.comment, postRoot)
try try
posts.push new Post postRoot, thread, thread.board posts.push new Post postRoot, thread, thread.board
catch err catch err
@ -379,7 +379,7 @@ Main =
addThreads: (records) -> addThreads: (records) ->
threadRoots = [] threadRoots = []
for record in records for record in records
for node in record.addedNodes when node.nodeType is Node.ELEMENT_NODE and node.matches(Site.selectors.thread) for node in record.addedNodes when node.nodeType is Node.ELEMENT_NODE and node.matches(g.SITE.selectors.thread)
threadRoots.push node threadRoots.push node
return unless threadRoots.length return unless threadRoots.length
threads = [] threads = []
@ -400,7 +400,7 @@ Main =
thread = Get.threadFromRoot record.target thread = Get.threadFromRoot record.target
postRoots = [] postRoots = []
for node in record.addedNodes when node.nodeType is Node.ELEMENT_NODE for node in record.addedNodes when node.nodeType is Node.ELEMENT_NODE
if node.matches(Site.selectors.postContainer) or (node = $(Site.selectors.postContainer, node)) if node.matches(g.SITE.selectors.postContainer) or (node = $(g.SITE.selectors.postContainer, node))
postRoots.push node postRoots.push node
n = posts.length n = posts.length
Main.parsePosts postRoots, thread, posts, errors Main.parsePosts postRoots, thread, posts, errors
@ -512,8 +512,8 @@ Main =
isThisPageLegit: -> isThisPageLegit: ->
# not 404 error page or similar. # not 404 error page or similar.
unless 'thisPageIsLegit' of Main unless 'thisPageIsLegit' of Main
Main.thisPageIsLegit = if Site.isThisPageLegit Main.thisPageIsLegit = if g.SITE.isThisPageLegit
Site.isThisPageLegit() g.SITE.isThisPageLegit()
else else
!/^[45]\d\d\b/.test(document.title) !/^[45]\d\d\b/.test(document.title)
Main.thisPageIsLegit Main.thisPageIsLegit

View File

@ -134,7 +134,7 @@ SW.tinyboard =
parseFile: (post, file) -> parseFile: (post, file) ->
{text, link, thumb} = file {text, link, thumb} = file
return false if $.x("ancestor::#{Site.xpath.postContainer}[1]", text) isnt post.nodes.root # file belongs to a reply return false if $.x("ancestor::#{@xpath.postContainer}[1]", text) isnt post.nodes.root # file belongs to a reply
return false if not (infoNode = if '(' in link.nextSibling?.textContent then link.nextSibling else link.nextElementSibling) return false if not (infoNode = if '(' in link.nextSibling?.textContent then link.nextSibling else link.nextElementSibling)
return false if not (info = infoNode.textContent.match /\((Spoiler Image, )?([\d.]+ [KMG]?B).*\)/) return false if not (info = infoNode.textContent.match /\((Spoiler Image, )?([\d.]+ [KMG]?B).*\)/)
nameNode = $ '.postfilename', text nameNode = $ '.postfilename', text

View File

@ -100,7 +100,7 @@ SW.yotsuba =
if g.BOARD.ID is 'f' and thread.OP.file if g.BOARD.ID is 'f' and thread.OP.file
{file} = thread.OP {file} = thread.OP
$.ajax Site.urls.threadJSON({boardID: 'f', threadID: thread.ID}), $.ajax @urls.threadJSON({boardID: 'f', threadID: thread.ID}),
timeout: $.MINUTE timeout: $.MINUTE
onloadend: -> onloadend: ->
if @response if @response

View File

@ -25,13 +25,17 @@ Site =
changed++ changed++
if changed if changed
$.set 'siteProperties', Conf['siteProperties'] $.set 'siteProperties', Conf['siteProperties']
unless @hostname unless g.SITE
@set hostname @set hostname
cb() cb()
return return
return return
set: (@hostname) -> set: (hostname) ->
@properties = Conf['siteProperties'][@hostname] for ID, properties of Conf['siteProperties']
@software = @properties.software continue if properties.canonical
$.extend @, SW[@software] software = properties.software
continue unless software and SW[software]
g.sites[ID] = site = Object.create SW[software]
$.extend site, {ID, properties, software}
g.SITE = g.sites[hostname]