Merge branch 'ccd0' into v3

Conflicts:
	CHANGELOG.md
	LICENSE
	builds/4chan-X.user.js
	builds/crx.crx
	builds/crx/script.js
	package.json
	src/Archive/archives.json
	src/General/Get.coffee
	src/General/Navigate.coffee
	src/Images/Gallery.coffee
	src/Linkification/Linkify.coffee
	src/Posting/QR.coffee
	src/Posting/QR.post.coffee
This commit is contained in:
Zixaphir 2014-05-11 16:04:14 -07:00
commit 37a3b05e39
17 changed files with 446 additions and 368 deletions

View File

@ -1,7 +1,65 @@
**MayhemYDG**
- Update 4chan namespaces support.
- Better handling of webm playback errors.
- Bugfixes
### v1.7.33
*2014-05-10*
**DamonGant**
- Add Innovandalism Archive.
**ccd0**
- Update archive list.
- Add "disabled" option when Foolz Beta is the only choice.
### v1.7.32
*2014-05-10*
**Zixaphir, ccd0**
- Bug fixes in linkification/embedding.
**ccd0**
- Begin refactoring code to reduce potential for introducing Javascript injection bugs.
### v1.7.31
*2014-05-08*
**Zixaphir**
- Refactoring, bug fixes.
**ccd0**
- Fix some potential Javascript injection issues.
- Bug fixes.
### v1.7.30
*2014-05-05*
**thebladeee**
- Update archives.
### v1.7.29
*2014-05-03*
**ccd0**:
- If the original post form not hidden, it is expanded (except on the catalog page).
- 4chan's horizontal rules are no longer hidden. If you want to hide them as before, add the old code to your custom CSS:
```
body > hr,
#blotter hr,
.desktop > hr,
#delform > hr,
#content > hr {
display: none;
}
:root.index .board > hr:last-of-type,
:root.thread .board > hr {
border: 0px;
margin: 0px;
}
```
### v1.7.28
*2014-05-03*
**ccd0**:
- Copy Mayhem's fix for 4chan post form changes.
### v1.7.27
*2014-05-02*

View File

@ -1,5 +1,5 @@
/*
* 4chan X - Version 1.7.27 - 2014-05-03
* 4chan X - Version 1.7.33 - 2014-05-11
*
* Licensed under the MIT license.
* https://github.com/ccd0/4chan-x/blob/master/LICENSE

View File

@ -1,6 +1,6 @@
// ==UserScript==
// @name 4chan X
// @version 1.7.27
// @version 1.7.33
// @minGMVer 1.14
// @minFFVer 26
// @namespace 4chan-X

File diff suppressed because one or more lines are too long

View File

@ -1,6 +1,6 @@
{
"name": "4chan X",
"version": "1.7.27",
"version": "1.7.33",
"manifest_version": 2,
"description": "Cross-browser userscript for maximum lurking on 4chan.",
"icons": {

File diff suppressed because one or more lines are too long

View File

@ -1,7 +1,7 @@
<?xml version='1.0' encoding='UTF-8'?>
<gupdate xmlns='http://www.google.com/update2/response' protocol='2.0'>
<app appid='lacclbnghgdicfifcamcmcnilckjamag'>
<updatecheck codebase='https://ccd0.github.io/4chan-x/builds/crx.crx' version='1.7.27' />
<updatecheck codebase='https://ccd0.github.io/4chan-x/builds/crx.crx' version='1.7.33' />
</app>
</gupdate>

View File

@ -1,6 +1,6 @@
{
"name": "4chan-X",
"version": "1.7.27",
"version": "1.7.33",
"description": "Cross-browser userscript for maximum lurking on 4chan.",
"meta": {
"name": "4chan X",

View File

@ -7,9 +7,9 @@ Redirect =
archives = {}
for data in Redirect.archives
{name, boards, files, software} = data
{name, boards, files, software, withCredentials} = data
archives[name] = data
for boardID in boards
for boardID in boards when !withCredentials
o.thread[boardID] = data unless boardID of o.thread
o.post[boardID] = data unless boardID of o.post or software isnt 'foolfuuka'
o.file[boardID] = data unless boardID of o.file or boardID not in files

View File

@ -6,7 +6,7 @@
"https": true,
"software": "foolfuuka",
"boards": ["a", "biz", "co", "diy", "gd", "jp", "m", "sci", "sp", "tg", "tv", "vg", "vp", "vr", "wsg"],
"files": ["a", "biz", "gd", "diy", "jp", "m", "sci", "tg", "vg", "vp", "vr", "wsg"]
"files": ["a", "biz", "diy", "gd", "jp", "m", "sci", "tg", "vg", "vp", "vr", "wsg"]
}, {
"uid": 1,
"name": "NSFW Foolz",
@ -55,17 +55,17 @@
}, {
"uid": 5,
"name": "Love is Over",
"domain": "loveisover.me",
"domain": "archive.loveisover.me",
"http": true,
"https": true,
"software": "foolfuuka",
"boards": ["d", "i"],
"files": ["d", "i"]
"boards": ["d", "i", "lgbt"],
"files": ["d", "i", "lgbt"]
}, {
"uid": 8,
"name": "Rebecca Black Tech",
"domain": "rbt.asia",
"http": true,
"http": false,
"https": true,
"software": "fuuka",
"boards": ["cgl", "g", "mu", "w"],
@ -78,7 +78,7 @@
"https": false,
"software": "fuuka",
"boards": ["an", "fit", "k", "mlp", "r9k", "toy"],
"files": ["an", "fit", "k", "r9k", "toy"]
"files": ["an", "fit", "k", "mlp", "r9k", "toy"]
}, {
"uid": 10,
"name": "warosu",
@ -115,6 +115,15 @@
"software": "foolfuuka",
"boards": ["g", "t"],
"files": ["g", "t"]
}, {
"uid": 19,
"name": "Innovandalism Archive",
"domain": "boards.innovandalism.eu",
"http": true,
"https": false,
"software": "foolfuuka",
"boards": ["v"],
"files": []
}, {
"uid": 13,
"name": "Foolz Beta",

View File

@ -47,7 +47,7 @@ Build =
name: data.filename + data.ext
timestamp: "#{data.tim}#{data.ext}"
url: if boardID is 'f'
"//i.4cdn.org/#{boardID}/#{data.filename}#{data.ext}"
"//i.4cdn.org/#{boardID}/#{data.filename}#{data.ext}".replace /'/g, '&apos;'
else
"//i.4cdn.org/#{boardID}/#{data.tim}#{data.ext}"
height: data.h

View File

@ -296,15 +296,21 @@ Settings =
$.on $.id('apply-css'), 'click', Settings.usercss
archBoards = {}
for {name, boards, files, software} in Redirect.archives
for {name, boards, files, software, withCredentials} in Redirect.archives
for boardID in boards
o = archBoards[boardID] or=
thread: []
post: []
file: []
o.thread.push name
o.post.push name if software is 'foolfuuka'
o.file.push name if boardID in files
thread: [[], []]
post: [[], []]
file: [[], []]
i = +!!withCredentials
o.thread[i].push name
o.post[i].push name if software is 'foolfuuka'
o.file[i].push name if boardID in files
for boardID, o of archBoards
for item in ['thread', 'post', 'file']
if o[item][0].length is 0 and o[item][1].length isnt 0
o[item][0].push 'disabled'
o[item] = o[item][0].concat(o[item][1])
rows = []
boardOptions = []

View File

@ -69,24 +69,9 @@ a {
border-radius: 3px;
padding: 0px 2px;
}
body > hr,
#blotter hr,
.desktop > hr,
#delform > hr,
#content > hr {
display: none;
}
:root.index .board > hr:last-of-type,
:root.thread .board > hr {
border: 0px;
margin: 0px;
}
.ad-plea {
display: none;
}
.ad-cnt {
margin: 10px !important;
}
/* 4chan style fixes */
.opContainer, .op {
@ -904,13 +889,16 @@ span.hide-announcement {
/* QR */
:root.hide-original-post-form #postForm,
:root.hide-original-post-form .postingMode,
:root.hide-original-post-form #togglePostForm,
:root.hide-original-post-form #togglePostFormLink,
:root:not(.catalog) #togglePostFormLink,
#qr.autohide:not(.focus):not(:hover):not(:active) > form,
.thread #qr select[data-name=thread],
#file-n-submit:not(.has-file) #qr-filerm {
display: none;
}
:root:not(.hide-original-post-form):not(.catalog) #postForm {
display: table;
}
#qr select,
#dump-button,
#url-button,

View File

@ -24,7 +24,7 @@
"javascript:quote(#{postID})"
else
"/#{boardID}/thread/#{threadID}#q#{postID}"
}' title='Quote this post'>#{postID}</a>
}' title='Reply to this post'>#{postID}</a>
#{pageIcon + sticky + closed + replyLink}
</span>
</div>

View File

@ -10,14 +10,13 @@ Linkify =
if Conf['Embedding'] or Conf['Link Title']
@embedProcess = Function 'link',
"var data = this.services(link);
if (data) {
#{
(if Conf['Embedding'] then 'this.embed(data);\n' else '') +
if Conf['Link Title'] then 'this.title(data);' else ''
}
}
"
"""
var data = this.services(link);
if (data) {#{
(if Conf['Embedding'] then 'this.embed(data); ' else '') +
if Conf['Link Title'] then 'data.push(post); this.title(data);' else ''
}}
"""
Post.callbacks.push
name: 'Linkify'
@ -34,7 +33,7 @@ Linkify =
node: ->
return (if Conf['Embedding'] then Linkify.events @ else null) if @isClone
return unless Linkify.regString.test @info.comment
test = /[^\s'"]+/g
space = /[\s'"]/
snapshot = $.X './/br|.//text()', @nodes.comment
@ -95,7 +94,7 @@ Linkify =
)///i
makeRange: (startNode, endNode, startOffset, endOffset) ->
range = document.createRange();
range = document.createRange()
range.setStart startNode, startOffset
range.setEnd endNode, endOffset
range
@ -156,7 +155,7 @@ Linkify =
return
embed: (data) ->
[key, uid, options, link] = data
[key, uid, options, link, post] = data
href = link.href
embed = $.el 'a',
className: 'embedder'
@ -164,7 +163,6 @@ Linkify =
textContent: '(embed)'
embed.dataset[name] = value for name, value of {key, href, uid, options}
embed.dataset.nodedata = link.innerHTML
$.addClass link, "#{embed.dataset.key}"
@ -173,33 +171,30 @@ Linkify =
Linkify.cb.toggle.call embed if Conf['Auto-embed']
data.push embed
title: (data) ->
[key, uid, options, link, embed] = data
[key, uid, options, link, post] = data
return unless service = Linkify.types[key].title
titles = Conf['CachedTitles']
if title = titles[uid]
# Auto-embed may destroy our links.
if link
link.textContent = title[0]
if Conf['Embedding']
embed.dataset.title = title[0]
link.textContent = title[0]
else
try
$.cache service.api(uid), (-> Linkify.cb.title @, data), responseType: 'json'
catch err
if link
link.innerHTML = "[#{key}] <span class=warning>Title Link Blocked</span> (are you using NoScript?)</a>"
link.innerHTML = '<span class="warning">Title Link Blocked</span> (are you using NoScript?)</a>'
$.prepend link, $.tn "[#{key}] "
return
cb:
toggle: ->
[string, @textContent] = if $.hasClass @, "embedded"
['unembed', '(embed)']
if $.hasClass @, "embedded"
$.rm @previousElementSibling
@previousElementSibling.hidden = false
@textContent = '(embed)'
else
['embed', '(unembed)']
$.replace @previousElementSibling, Linkify.cb[string] @
@previousElementSibling.hidden = true
$.before @, Linkify.cb.embed @
@textContent = '(unembed)'
$.toggleClass @, 'embedded'
embed: (a) ->
@ -214,21 +209,8 @@ Linkify =
return el
unembed: (a) ->
# Recreate the original link.
el = $.el 'a',
rel: 'nofollow noreferrer'
target: 'blank'
className: 'linkify'
href: a.dataset.href
innerHTML: a.dataset.title or a.dataset.nodedata
$.addClass el, a.dataset.key
return el
title: (req, data) ->
[key, uid, options, link, embed] = data
[key, uid, options, link, post] = data
{status} = req
service = Linkify.types[key].title
@ -243,8 +225,11 @@ Linkify =
"#{status}'d"
}"
embed.dataset.title = text if Conf['Embedding'] and status in [200, 304]
link.textContent = text if link
link.textContent = text
for post2 in post.clones
for link2 in $$ 'a', post2.nodes.comment when link2.href is link.href
link2.textContent = text
return
ordered_types: [
key: 'audio'
@ -271,8 +256,10 @@ Linkify =
regExp: /(http|www).*\.(gif|png|jpg|jpeg|bmp)$/
style: 'border: 0; width: auto; height: auto;'
el: (a) ->
$.el 'div',
innerHTML: "<a target=_blank href='#{a.dataset.href}'><img src='#{a.dataset.href}'></a>"
el = $.el 'div'
el.innerHTML = '<a target="_blank"><img></a>'
el.firstChild.href = el.firstChild.firstChild.src = a.dataset.href
el
,
key: 'InstallGentoo'
regExp: /.*(?:paste.installgentoo.com\/view\/)([0-9a-z_]+)/
@ -298,35 +285,36 @@ Linkify =
el
,
key: 'MediaCrush'
regExp: /.*(?:mediacru.sh\/)([0-9a-z_]+)/i
regExp: /.*(?:mediacru.sh\/)([0-9a-z_-]+)/i
style: 'border: 0;'
el: (a) ->
el = $.el 'div'
$.cache "https://mediacru.sh/#{a.dataset.uid}.json", ->
{status} = @
return div.innerHTML = "ERROR #{status}" unless status in [200, 304]
return el.textContent = "ERROR #{status}" unless status in [200, 304]
{files} = @response
for type in ['video/mp4', 'video/ogv', 'image/svg+xml', 'image/png', 'image/gif', 'image/jpeg', 'image/svg', 'audio/mpeg']
for type in ['video/mp4', 'video/webm', 'video/ogv', 'image/svg+xml', 'image/png', 'image/gif', 'image/jpeg', 'audio/mpeg', 'audio/ogg']
for file in files
if file.type is type
embed = file
break
break if embed
return div.innerHTML = "ERROR: Not a valid filetype" unless embed
el.innerHTML = switch embed.type
when 'video/mp4', 'video/ogv' then """
<video autoplay loop>
<source src="https://mediacru.sh/#{a.dataset.uid}.mp4" type="video/mp4;">
<source src="https://mediacru.sh/#{a.dataset.uid}.ogv" type="video/ogg; codecs='theora, vorbis'">
</video>"""
when 'image/png', 'image/gif', 'image/jpeg'
"<a target=_blank href='#{a.dataset.href}'><img src='https://mediacru.sh/#{file.file}'></a>"
when 'image/svg', 'image/svg+xml'
"<embed src='https://mediacru.sh/#{file.file}' type='image/svg+xml' />"
when 'audio/mpeg'
"<audio controls><source src='https://mediacru.sh/#{file.file}'></audio>"
return div.textContent = "ERROR: Not a valid filetype" unless embed
switch embed.type
when 'video/mp4', 'video/webm', 'video/ogv'
el.innerHTML = '<video autoplay loop><source type="video/mp4"><source type="video/webm"><source type="video/ogg"></video>'
for ext, i in ['mp4', 'webm', 'ogv']
el.firstChild.children[i].src = "https://mediacru.sh/#{a.dataset.uid}.#{ext}"
when 'image/svg+xml', 'image/png', 'image/gif', 'image/jpeg'
el.innerHTML = '<a target="_blank"><img></a>'
el.firstChild.href = a.dataset.href
el.firstChild.firstChild.src = "https://mediacru.sh/#{file.file}"
when 'audio/mpeg', 'audio/ogg'
el.innerHTML = '<audio controls><source type="audio/ogg"><source type="audio/mpeg"></audio>'
for ext, i in ['ogg', 'mp3']
el.firstChild.children[i].src = "https://mediacru.sh/#{a.dataset.uid}.#{ext}"
else
"ERROR: No valid filetype."
el.textContent = "ERROR: No valid filetype."
el
,
key: 'pastebin'
@ -343,19 +331,12 @@ Linkify =
,
key: 'SoundCloud'
regExp: /.*(?:soundcloud.com\/|snd.sc\/)([^#\&\?]*).*/
style: 'height: auto; width: 500px; display: inline-block;'
style: 'border: 0; width: 500px; height: 400px;'
el: (a) ->
div = $.el 'div',
className: "soundcloud"
name: "soundcloud"
$.ajax(
"//soundcloud.com/oembed?show_artwork=false&&maxwidth=500px&show_comments=false&format=json&url=https://www.soundcloud.com/#{a.dataset.uid}"
onloadend: ->
div.innerHTML = JSON.parse(@responseText).html
false)
div
$.el 'iframe',
src: "//w.soundcloud.com/player/?visual=true&show_comments=false&url=https%3A%2F%2Fsoundcloud.com%2F#{encodeURIComponent a.dataset.uid}"
title:
api: (uid) -> "//soundcloud.com/oembed?show_artwork=false&&maxwidth=500px&show_comments=false&format=json&url=https://www.soundcloud.com/#{uid}"
api: (uid) -> "//soundcloud.com/oembed?format=json&url=https%3A%2F%2Fsoundcloud.com%2F#{encodeURIComponent uid}"
text: (_) -> _.title
,
key: 'StrawPoll'
@ -369,26 +350,21 @@ Linkify =
regExp: /.*(?:twitch.tv\/)([^#\&\?]*).*/
style: "border: none; width: 640px; height: 360px;"
el: (a) ->
if result = /(\w+)\/(?:[a-z]\/)?(\d+)/i.exec a.dataset.uid
[_, channel, chapter] = result
$.el 'object',
if result = /(\w+)\/([bc])\/(\d+)/i.exec a.dataset.uid
[_, channel, type, id] = result
idparam = {'b': 'archive_id', 'c': 'chapter_id'}
obj = $.el 'object',
data: 'http://www.twitch.tv/widgets/archive_embed_player.swf'
innerHTML: """
<param name='allowFullScreen' value='true' />
<param name='flashvars' value='channel=#{channel}&start_volume=25&auto_play=false#{if chapter then "&chapter_id=" + chapter else ""}' />
"""
obj.innerHTML = '<param name="allowFullScreen" value="true"><param name="flashvars">'
obj.children[1].value = "channel=#{channel}&start_volume=25&auto_play=false&#{idparam[type]}=#{id}"
obj
else
channel = (/(\w+)/.exec a.dataset.uid)[0]
$.el 'object',
obj = $.el 'object',
data: "http://www.twitch.tv/widgets/live_embed_player.swf?channel=#{channel}"
innerHTML: """
<param name="allowFullScreen" value="true" />
<param name="movie" value="http://www.twitch.tv/widgets/live_embed_player.swf" />
<param name="flashvars" value="hostname=www.twitch.tv&channel=#{channel}&auto_play=true&start_volume=25" />
"""
obj.innerHTML = '<param name="allowFullScreen" value="true"><param name="flashvars">'
obj.children[1].value = "hostname=www.twitch.tv&channel=#{channel}&auto_play=true&start_volume=25"
obj
,
key: 'Vocaroo'
regExp: /.*(?:vocaroo.com\/)([^#\&\?]*).*/

View File

@ -51,7 +51,7 @@ QR =
if Conf['QR Shortcut']
$.rmClass $('.qr-shortcut'), 'disabled'
$.before $.id('togglePostForm') or $.id('postForm'), link
$.before $.id('togglePostFormLink'), link
$.on d, 'QRGetSelectedPost', ({detail: cb}) ->
cb QR.selected
@ -435,7 +435,6 @@ QR =
setNode 'addPost', '#add-post'
setNode 'charCount', '#char-count'
setNode 'fileSubmit', '#file-n-submit'
setNode 'filesize', '#qr-filesize'
setNode 'filename', '#qr-filename'
setNode 'fileContainer', '#qr-filename-container'
setNode 'fileRM', '#qr-filerm'

View File

@ -156,7 +156,7 @@ QR.post = class
@save node
return
setFile: (@file) ->
setFile: (@file, el) ->
@filename = file.name
@filesize = $.bytesToString file.size
@nodes.label.hidden = false if QR.spoiler
@ -167,10 +167,8 @@ QR.post = class
@updateFilename()
unless /^(image|video)\//.test file.type
@nodes.el.style.backgroundImage = null
return
@setThumbnail()
setThumbnail: ->
setThumbnail: (el) ->
# Create a redimensioned thumbnail.
isVideo = /^video\//.test @file.type
el = $.el (if isVideo then 'video' else 'img')