Merge tag '1.9.15.4' into noscript
4chan X v1.9.15.4. Conflicts: src/Posting/QR.captcha.coffee
This commit is contained in:
commit
77f3639772
51
CHANGELOG.md
51
CHANGELOG.md
@ -2,7 +2,58 @@ The attributions below are for work that has been incorporated into the script a
|
|||||||
|
|
||||||
The links to individual versions below are to copies of the script with the update URL removed. If you want automatic updates, install the script from the links on the [main page](https://github.com/ccd0/4chan-x).
|
The links to individual versions below are to copies of the script with the update URL removed. If you want automatic updates, install the script from the links on the [main page](https://github.com/ccd0/4chan-x).
|
||||||
|
|
||||||
|
<!-- v1.9.15.x -->
|
||||||
|
### v1.9.15.4
|
||||||
|
*2014-12-08* - [[Firefox](https://raw.githubusercontent.com/ccd0/4chan-x/1.9.15.4/builds/4chan-X-noupdate.user.js "Firefox version")] [[Chromium](https://raw.githubusercontent.com/ccd0/4chan-x/1.9.15.4/builds/4chan-X-noupdate.crx "Chromium version")]
|
||||||
|
|
||||||
|
**ccd0**
|
||||||
|
- Make `Catalog Links`, `Relative Post Dates`, and `Pin Watched Threads` off by default.
|
||||||
|
|
||||||
|
### v1.9.15.3
|
||||||
|
*2014-12-08* - [[Firefox](https://raw.githubusercontent.com/ccd0/4chan-x/1.9.15.3/builds/4chan-X-noupdate.user.js "Firefox version")] [[Chromium](https://raw.githubusercontent.com/ccd0/4chan-x/1.9.15.3/builds/4chan-X-noupdate.crx "Chromium version")]
|
||||||
|
|
||||||
|
**ccd0**
|
||||||
|
- Fix sounds sometimes playing for a short time before `Disable Autoplaying Sounds` halts them (as in 1.9.14.4).
|
||||||
|
|
||||||
|
### v1.9.15.2
|
||||||
|
*2014-12-08* - [[Firefox](https://raw.githubusercontent.com/ccd0/4chan-x/1.9.15.2/builds/4chan-X-noupdate.user.js "Firefox version")] [[Chromium](https://raw.githubusercontent.com/ccd0/4chan-x/1.9.15.2/builds/4chan-X-noupdate.crx "Chromium version")]
|
||||||
|
|
||||||
|
**ccd0**
|
||||||
|
- Add `Pin Watched Threads` setting to `Index Navigation` header submenu (default: checked), moving watched threads to the beginning of 4chan X's index/catalog.
|
||||||
|
- `Alt+Click` in the 4chan X catalog watches/unwatches a thread.
|
||||||
|
- Add a `Watch Thread`/`Unwatch Thread` item to the menu in the 4chan X catalog.
|
||||||
|
|
||||||
|
### v1.9.15.1
|
||||||
|
*2014-12-07* - [[Firefox](https://raw.githubusercontent.com/ccd0/4chan-x/1.9.15.1/builds/4chan-X-noupdate.user.js "Firefox version")] [[Chromium](https://raw.githubusercontent.com/ccd0/4chan-x/1.9.15.1/builds/4chan-X-noupdate.crx "Chromium version")]
|
||||||
|
|
||||||
|
**ccd0**
|
||||||
|
- Center the controls added to formerly autoplaying audio by `Disable Autoplaying Sounds` (as in v1.9.14.3).
|
||||||
|
|
||||||
|
### v1.9.15.0
|
||||||
|
*2014-12-07* - [[Firefox](https://raw.githubusercontent.com/ccd0/4chan-x/1.9.15.0/builds/4chan-X-noupdate.user.js "Firefox version")] [[Chromium](https://raw.githubusercontent.com/ccd0/4chan-x/1.9.15.0/builds/4chan-X-noupdate.crx "Chromium version")]
|
||||||
|
|
||||||
|
Based on v1.9.14.2.
|
||||||
|
|
||||||
|
**MayhemYDG, Matěj Grabovský**
|
||||||
|
- Quoting now also includes the spoiler and code tags.
|
||||||
|
|
||||||
|
**ccd0**
|
||||||
|
- Quote the original URL of links rather than the title, and don't quote `(embed)`.
|
||||||
|
- Bug fixes.
|
||||||
|
|
||||||
<!-- v1.9.14.x -->
|
<!-- v1.9.14.x -->
|
||||||
|
### v1.9.14.4
|
||||||
|
*2014-12-08* - [[Firefox](https://raw.githubusercontent.com/ccd0/4chan-x/1.9.14.4/builds/4chan-X-noupdate.user.js "Firefox version")] [[Chromium](https://raw.githubusercontent.com/ccd0/4chan-x/1.9.14.4/builds/4chan-X-noupdate.crx "Chromium version")]
|
||||||
|
|
||||||
|
**ccd0**
|
||||||
|
- Fix sounds sometimes playing for a short time before `Disable Autoplaying Sounds` halts them.
|
||||||
|
|
||||||
|
### v1.9.14.3
|
||||||
|
*2014-12-07* - [[Firefox](https://raw.githubusercontent.com/ccd0/4chan-x/1.9.14.3/builds/4chan-X-noupdate.user.js "Firefox version")] [[Chromium](https://raw.githubusercontent.com/ccd0/4chan-x/1.9.14.3/builds/4chan-X-noupdate.crx "Chromium version")]
|
||||||
|
|
||||||
|
**ccd0**
|
||||||
|
- Center the controls added to formerly autoplaying audio by `Disable Autoplaying Sounds`.
|
||||||
|
|
||||||
### v1.9.14.2
|
### v1.9.14.2
|
||||||
*2014-12-04* - [[Firefox](https://raw.githubusercontent.com/ccd0/4chan-x/1.9.14.2/builds/4chan-X-noupdate.user.js "Firefox version")] [[Chromium](https://raw.githubusercontent.com/ccd0/4chan-x/1.9.14.2/builds/4chan-X-noupdate.crx "Chromium version")]
|
*2014-12-04* - [[Firefox](https://raw.githubusercontent.com/ccd0/4chan-x/1.9.14.2/builds/4chan-X-noupdate.user.js "Firefox version")] [[Chromium](https://raw.githubusercontent.com/ccd0/4chan-x/1.9.14.2/builds/4chan-X-noupdate.crx "Chromium version")]
|
||||||
|
|
||||||
|
|||||||
@ -25,6 +25,10 @@ module.exports = (grunt) ->
|
|||||||
output = if parts2.length is 0 then '""' else parts2.join ' + '
|
output = if parts2.length is 0 then '""' else parts2.join ' + '
|
||||||
"(innerHTML: #{output})"
|
"(innerHTML: #{output})"
|
||||||
|
|
||||||
|
assert = (statement, objs...) ->
|
||||||
|
return '' unless grunt.config('pkg').tests_enabled
|
||||||
|
"throw new Error 'Assertion failed: ' + `#{JSON.stringify statement}` unless #{statement}"
|
||||||
|
|
||||||
# Project configuration.
|
# Project configuration.
|
||||||
grunt.initConfig
|
grunt.initConfig
|
||||||
pkg: grunt.file.readJSON 'package.json'
|
pkg: grunt.file.readJSON 'package.json'
|
||||||
@ -35,6 +39,7 @@ module.exports = (grunt) ->
|
|||||||
pkg = grunt.config 'pkg'
|
pkg = grunt.config 'pkg'
|
||||||
pkg.importHTML = importHTML
|
pkg.importHTML = importHTML
|
||||||
pkg.html = html
|
pkg.html = html
|
||||||
|
pkg.assert = assert
|
||||||
pkg.tests_enabled or= false
|
pkg.tests_enabled or= false
|
||||||
pkg
|
pkg
|
||||||
enumerable: true
|
enumerable: true
|
||||||
|
|||||||
2
LICENSE
2
LICENSE
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* 4chan X - Version 1.9.14.2
|
* 4chan X - Version 1.9.15.4
|
||||||
*
|
*
|
||||||
* Licensed under the MIT license.
|
* Licensed under the MIT license.
|
||||||
* https://github.com/ccd0/4chan-x/blob/master/LICENSE
|
* https://github.com/ccd0/4chan-x/blob/master/LICENSE
|
||||||
|
|||||||
@ -39,6 +39,9 @@ If you want to install the current beta version but get updates from the stable
|
|||||||
## Security note
|
## Security note
|
||||||
4chan X currently shares your settings and post history between the HTTP and HTTPS versions of 4chan. If you are concerned about protecting your privacy against a man-in-the-middle attack, you should disable 4chan X on the HTTP version of 4chan and/or install [HTTPS Everywhere](https://www.eff.org/https-everywhere).
|
4chan X currently shares your settings and post history between the HTTP and HTTPS versions of 4chan. If you are concerned about protecting your privacy against a man-in-the-middle attack, you should disable 4chan X on the HTTP version of 4chan and/or install [HTTPS Everywhere](https://www.eff.org/https-everywhere).
|
||||||
|
|
||||||
|
## Uninstalling
|
||||||
|
4chan X disables the native extension, so if you uninstall 4chan X, you'll need to re-enable it. To do this, click the `[Settings]` link in the top right corner and uncheck "`Disable the native extension`" in the panel that appears.
|
||||||
|
|
||||||
## More information
|
## More information
|
||||||
- [Source Code](https://github.com/ccd0/4chan-x)
|
- [Source Code](https://github.com/ccd0/4chan-x)
|
||||||
- [Changelog](https://github.com/ccd0/4chan-x/blob/master/CHANGELOG.md)
|
- [Changelog](https://github.com/ccd0/4chan-x/blob/master/CHANGELOG.md)
|
||||||
|
|||||||
Binary file not shown.
@ -1,6 +1,6 @@
|
|||||||
// ==UserScript==
|
// ==UserScript==
|
||||||
// @name 4chan X beta
|
// @name 4chan X beta
|
||||||
// @version 1.9.14.2
|
// @version 1.9.15.4
|
||||||
// @minGMVer 1.14
|
// @minGMVer 1.14
|
||||||
// @minFFVer 26
|
// @minFFVer 26
|
||||||
// @namespace 4chan-X
|
// @namespace 4chan-X
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
@ -1,6 +1,6 @@
|
|||||||
// ==UserScript==
|
// ==UserScript==
|
||||||
// @name 4chan X
|
// @name 4chan X
|
||||||
// @version 1.9.14.2
|
// @version 1.9.15.4
|
||||||
// @minGMVer 1.14
|
// @minGMVer 1.14
|
||||||
// @minFFVer 26
|
// @minFFVer 26
|
||||||
// @namespace 4chan-X
|
// @namespace 4chan-X
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Binary file not shown.
@ -1,7 +1,7 @@
|
|||||||
<?xml version='1.0' encoding='UTF-8'?>
|
<?xml version='1.0' encoding='UTF-8'?>
|
||||||
<gupdate xmlns='http://www.google.com/update2/response' protocol='2.0'>
|
<gupdate xmlns='http://www.google.com/update2/response' protocol='2.0'>
|
||||||
<app appid='lacclbnghgdicfifcamcmcnilckjamag'>
|
<app appid='lacclbnghgdicfifcamcmcnilckjamag'>
|
||||||
<updatecheck codebase='https://ccd0.github.io/4chan-x/builds/4chan-X-beta.crx' version='1.9.14.2' />
|
<updatecheck codebase='https://ccd0.github.io/4chan-x/builds/4chan-X-beta.crx' version='1.9.15.4' />
|
||||||
</app>
|
</app>
|
||||||
</gupdate>
|
</gupdate>
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
<?xml version='1.0' encoding='UTF-8'?>
|
<?xml version='1.0' encoding='UTF-8'?>
|
||||||
<gupdate xmlns='http://www.google.com/update2/response' protocol='2.0'>
|
<gupdate xmlns='http://www.google.com/update2/response' protocol='2.0'>
|
||||||
<app appid='lacclbnghgdicfifcamcmcnilckjamag'>
|
<app appid='lacclbnghgdicfifcamcmcnilckjamag'>
|
||||||
<updatecheck codebase='https://ccd0.github.io/4chan-x/builds/4chan-X.crx' version='1.9.14.2' />
|
<updatecheck codebase='https://ccd0.github.io/4chan-x/builds/4chan-X.crx' version='1.9.15.4' />
|
||||||
</app>
|
</app>
|
||||||
</gupdate>
|
</gupdate>
|
||||||
|
|
||||||
|
|||||||
@ -47,6 +47,8 @@ Only the latest stable version of 4chan X is available.</p>
|
|||||||
<p>If you want to install the current beta version but get updates from the stable channel after that, install it from <a href="https://github.com/ccd0/4chan-x/raw/beta/builds/4chan-X.user.js">here</a> for Firefox or <a href="https://github.com/ccd0/4chan-x/raw/beta/builds/4chan-X.crx">here</a> for Chromium.</p>
|
<p>If you want to install the current beta version but get updates from the stable channel after that, install it from <a href="https://github.com/ccd0/4chan-x/raw/beta/builds/4chan-X.user.js">here</a> for Firefox or <a href="https://github.com/ccd0/4chan-x/raw/beta/builds/4chan-X.crx">here</a> for Chromium.</p>
|
||||||
<h2 id="security-note">Security note</h2>
|
<h2 id="security-note">Security note</h2>
|
||||||
<p>4chan X currently shares your settings and post history between the HTTP and HTTPS versions of 4chan. If you are concerned about protecting your privacy against a man-in-the-middle attack, you should disable 4chan X on the HTTP version of 4chan and/or install <a href="https://www.eff.org/https-everywhere">HTTPS Everywhere</a>.</p>
|
<p>4chan X currently shares your settings and post history between the HTTP and HTTPS versions of 4chan. If you are concerned about protecting your privacy against a man-in-the-middle attack, you should disable 4chan X on the HTTP version of 4chan and/or install <a href="https://www.eff.org/https-everywhere">HTTPS Everywhere</a>.</p>
|
||||||
|
<h2 id="uninstalling">Uninstalling</h2>
|
||||||
|
<p>4chan X disables the native extension, so if you uninstall 4chan X, you'll need to re-enable it. To do this, click the <code>[Settings]</code> link in the top right corner and uncheck "<code>Disable the native extension</code>" in the panel that appears.</p>
|
||||||
<h2 id="more-information">More information</h2>
|
<h2 id="more-information">More information</h2>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="https://github.com/ccd0/4chan-x">Source Code</a></li>
|
<li><a href="https://github.com/ccd0/4chan-x">Source Code</a></li>
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
"description": "Cross-browser userscript for maximum lurking on 4chan.",
|
"description": "Cross-browser userscript for maximum lurking on 4chan.",
|
||||||
"meta": {
|
"meta": {
|
||||||
"name": "4chan X",
|
"name": "4chan X",
|
||||||
"version": "1.9.14.2",
|
"version": "1.9.15.4",
|
||||||
"repo": "https://github.com/ccd0/4chan-x/",
|
"repo": "https://github.com/ccd0/4chan-x/",
|
||||||
"page": "https://github.com/ccd0/4chan-x",
|
"page": "https://github.com/ccd0/4chan-x",
|
||||||
"downloads": "https://ccd0.github.io/4chan-x/builds/",
|
"downloads": "https://ccd0.github.io/4chan-x/builds/",
|
||||||
|
|||||||
@ -14,7 +14,7 @@ Config =
|
|||||||
'Link to 4chan X\'s catalog instead of the native 4chan one.'
|
'Link to 4chan X\'s catalog instead of the native 4chan one.'
|
||||||
]
|
]
|
||||||
'Catalog Links': [
|
'Catalog Links': [
|
||||||
true
|
false
|
||||||
'Add toggle link in header menu to turn Navigation links into links to each board\'s catalog.'
|
'Add toggle link in header menu to turn Navigation links into links to each board\'s catalog.'
|
||||||
]
|
]
|
||||||
'QR Shortcut': [
|
'QR Shortcut': [
|
||||||
@ -46,7 +46,7 @@ Config =
|
|||||||
'Localize and format timestamps.'
|
'Localize and format timestamps.'
|
||||||
]
|
]
|
||||||
'Relative Post Dates': [
|
'Relative Post Dates': [
|
||||||
true
|
false
|
||||||
'Display dates like "3 minutes ago". Tooltip shows the timestamp.'
|
'Display dates like "3 minutes ago". Tooltip shows the timestamp.'
|
||||||
]
|
]
|
||||||
'Comment Expansion': [
|
'Comment Expansion': [
|
||||||
@ -589,6 +589,7 @@ http://iqdb.org/?url=%TURL
|
|||||||
'Index Sort': 'bump'
|
'Index Sort': 'bump'
|
||||||
'Index Size': 'small'
|
'Index Size': 'small'
|
||||||
'Show Replies': true
|
'Show Replies': true
|
||||||
|
'Pin Watched Threads': false
|
||||||
'Anchor Hidden Threads': true
|
'Anchor Hidden Threads': true
|
||||||
'Refreshed Navigation': false
|
'Refreshed Navigation': false
|
||||||
|
|
||||||
|
|||||||
@ -24,25 +24,27 @@ Index =
|
|||||||
Header.addShortcut @button, 1
|
Header.addShortcut @button, 1
|
||||||
|
|
||||||
repliesEntry = el: UI.checkbox 'Show Replies', ' Show replies'
|
repliesEntry = el: UI.checkbox 'Show Replies', ' Show replies'
|
||||||
|
pinEntry = el: UI.checkbox 'Pin Watched Threads', ' Pin watched threads'
|
||||||
anchorEntry = el: UI.checkbox 'Anchor Hidden Threads', ' Anchor hidden threads'
|
anchorEntry = el: UI.checkbox 'Anchor Hidden Threads', ' Anchor hidden threads'
|
||||||
refNavEntry = el: UI.checkbox 'Refreshed Navigation', ' Refreshed navigation'
|
refNavEntry = el: UI.checkbox 'Refreshed Navigation', ' Refreshed navigation'
|
||||||
anchorEntry.el.title = 'Move hidden threads at the end of the index.'
|
pinEntry.el.title = 'Move watched threads to the start of the index.'
|
||||||
|
anchorEntry.el.title = 'Move hidden threads to the end of the index.'
|
||||||
refNavEntry.el.title = 'Refresh index when navigating through pages.'
|
refNavEntry.el.title = 'Refresh index when navigating through pages.'
|
||||||
for label in [repliesEntry, anchorEntry, refNavEntry]
|
for label in [repliesEntry, pinEntry, anchorEntry, refNavEntry]
|
||||||
input = label.el.firstChild
|
input = label.el.firstChild
|
||||||
{name} = input
|
{name} = input
|
||||||
$.on input, 'change', $.cb.checked
|
$.on input, 'change', $.cb.checked
|
||||||
switch name
|
switch name
|
||||||
when 'Show Replies'
|
when 'Show Replies'
|
||||||
$.on input, 'change', @cb.replies
|
$.on input, 'change', @cb.replies
|
||||||
when 'Anchor Hidden Threads'
|
when 'Pin Watched Threads', 'Anchor Hidden Threads'
|
||||||
$.on input, 'change', @cb.sort
|
$.on input, 'change', @cb.sort
|
||||||
|
|
||||||
Header.menu.addEntry
|
Header.menu.addEntry
|
||||||
el: $.el 'span',
|
el: $.el 'span',
|
||||||
textContent: 'Index Navigation'
|
textContent: 'Index Navigation'
|
||||||
order: 98
|
order: 98
|
||||||
subEntries: [repliesEntry, anchorEntry, refNavEntry]
|
subEntries: [repliesEntry, pinEntry, anchorEntry, refNavEntry]
|
||||||
|
|
||||||
$.addClass doc, 'index-loading', "#{Conf['Index Mode'].replace /\ /g, '-'}-mode"
|
$.addClass doc, 'index-loading', "#{Conf['Index Mode'].replace /\ /g, '-'}-mode"
|
||||||
@root = $.el 'div', className: 'board'
|
@root = $.el 'div', className: 'board'
|
||||||
@ -252,9 +254,9 @@ Index =
|
|||||||
1
|
1
|
||||||
else
|
else
|
||||||
+window.location.pathname.split('/')[2] or 1
|
+window.location.pathname.split('/')[2] or 1
|
||||||
userPageNav: (page) ->
|
userPageNav: (page, noRefresh) ->
|
||||||
state = Index.pushState {page}
|
state = Index.pushState {page}
|
||||||
if Conf['Refreshed Navigation']
|
if Conf['Refreshed Navigation'] and !noRefresh
|
||||||
Index.update state
|
Index.update state
|
||||||
else
|
else
|
||||||
Index.pageLoad state if state.page
|
Index.pageLoad state if state.page
|
||||||
@ -542,7 +544,7 @@ Index =
|
|||||||
# Sticky threads
|
# Sticky threads
|
||||||
Index.sortOnTop (thread) -> thread.isSticky
|
Index.sortOnTop (thread) -> thread.isSticky
|
||||||
# Highlighted threads
|
# Highlighted threads
|
||||||
Index.sortOnTop (thread) -> thread.isOnTop
|
Index.sortOnTop (thread) -> thread.isOnTop or Conf['Pin Watched Threads'] and ThreadWatcher.isWatched thread
|
||||||
# Non-hidden threads
|
# Non-hidden threads
|
||||||
Index.sortOnTop((thread) -> !thread.isHidden) if Conf['Anchor Hidden Threads']
|
Index.sortOnTop((thread) -> !thread.isHidden) if Conf['Anchor Hidden Threads']
|
||||||
|
|
||||||
@ -561,6 +563,11 @@ Index =
|
|||||||
nodes = Index.buildCatalogViews()
|
nodes = Index.buildCatalogViews()
|
||||||
Index.sizeCatalogViews nodes
|
Index.sizeCatalogViews nodes
|
||||||
else
|
else
|
||||||
|
if Index.followedThreadID?
|
||||||
|
i = 0
|
||||||
|
i++ while Index.followedThreadID isnt Get.threadFromRoot(Index.sortedNodes[i]).ID
|
||||||
|
page = i // Index.threadsNumPerPage + 1
|
||||||
|
Index.pushState {page} if page isnt Index.getCurrentPage()
|
||||||
nodes = Index.buildSinglePage Index.getCurrentPage()
|
nodes = Index.buildSinglePage Index.getCurrentPage()
|
||||||
$.rmAll Index.root
|
$.rmAll Index.root
|
||||||
$.rmAll Header.hover
|
$.rmAll Header.hover
|
||||||
@ -569,6 +576,8 @@ Index =
|
|||||||
else
|
else
|
||||||
Index.buildReplies nodes if Conf['Show Replies']
|
Index.buildReplies nodes if Conf['Show Replies']
|
||||||
Index.buildStructure nodes
|
Index.buildStructure nodes
|
||||||
|
if Index.followedThreadID? and (post = g.posts["#{g.BOARD}.#{Index.followedThreadID}"])
|
||||||
|
Header.scrollTo post.nodes.root
|
||||||
|
|
||||||
buildSinglePage: (pageNum) ->
|
buildSinglePage: (pageNum) ->
|
||||||
nodesPerPage = Index.threadsNumPerPage
|
nodesPerPage = Index.threadsNumPerPage
|
||||||
|
|||||||
@ -103,7 +103,9 @@ hr + div.center:not(.ad-cnt):not(.topad):not(.middlead):not(.bottomad) {
|
|||||||
/* party hats */
|
/* party hats */
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
.center > audio {
|
|
||||||
|
/* Anti-autoplay */
|
||||||
|
audio.controls-added {
|
||||||
display: block;
|
display: block;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
}
|
}
|
||||||
@ -888,6 +890,7 @@ span.hide-announcement {
|
|||||||
-webkit-align-self: stretch;
|
-webkit-align-self: stretch;
|
||||||
align-self: stretch;
|
align-self: stretch;
|
||||||
}
|
}
|
||||||
|
.catalog-thread.watched .werkTyme-filename,
|
||||||
.filter-highlight .werkTyme-filename {
|
.filter-highlight .werkTyme-filename {
|
||||||
border: 2px solid rgba(255, 0, 0, .5);
|
border: 2px solid rgba(255, 0, 0, .5);
|
||||||
}
|
}
|
||||||
@ -909,6 +912,7 @@ span.hide-announcement {
|
|||||||
.filter-highlight > .reply {
|
.filter-highlight > .reply {
|
||||||
box-shadow: -5px 0 rgba(255, 0, 0, .5);
|
box-shadow: -5px 0 rgba(255, 0, 0, .5);
|
||||||
}
|
}
|
||||||
|
.catalog-thread.watched .catalog-thumb,
|
||||||
.filter-highlight .catalog-thumb {
|
.filter-highlight .catalog-thumb {
|
||||||
border: 2px solid rgba(255, 0, 0, .5);
|
border: 2px solid rgba(255, 0, 0, .5);
|
||||||
}
|
}
|
||||||
@ -918,6 +922,12 @@ span.hide-announcement {
|
|||||||
:root.reveal-spoilers s > a {
|
:root.reveal-spoilers s > a {
|
||||||
color: white !important;
|
color: white !important;
|
||||||
}
|
}
|
||||||
|
:root.reveal-spoilers .removed-spoiler::before {
|
||||||
|
content: "[spoiler]";
|
||||||
|
}
|
||||||
|
:root.reveal-spoilers .removed-spoiler::after {
|
||||||
|
content: "[/spoiler]";
|
||||||
|
}
|
||||||
|
|
||||||
/* Thread & Reply Hiding */
|
/* Thread & Reply Hiding */
|
||||||
.hide-thread-button,
|
.hide-thread-button,
|
||||||
|
|||||||
@ -10,20 +10,20 @@
|
|||||||
</div>
|
</div>
|
||||||
<form>
|
<form>
|
||||||
<div class=persona>
|
<div class=persona>
|
||||||
<input name=name data-name=name list="list-name" placeholder=Name class=field size=1 tabindex=10>
|
<input name=name data-name=name list="list-name" placeholder=Name class=field size=1>
|
||||||
<input name=email data-name=email list="list-email" placeholder=Options class=field size=1 tabindex=20>
|
<input name=email data-name=email list="list-email" placeholder=Options class=field size=1>
|
||||||
<input name=sub data-name=sub list="list-sub" placeholder=Subject class=field size=1 tabindex=30>
|
<input name=sub data-name=sub list="list-sub" placeholder=Subject class=field size=1>
|
||||||
</div>
|
</div>
|
||||||
<div class=textarea>
|
<div class=textarea>
|
||||||
<textarea data-name=com placeholder=Comment class=field tabindex=40></textarea>
|
<textarea data-name=com placeholder=Comment class=field></textarea>
|
||||||
<span id=char-count></span>
|
<span id=char-count></span>
|
||||||
</div>
|
</div>
|
||||||
<div id=dump-list-container>
|
<div id=dump-list-container>
|
||||||
<div id=dump-list></div>
|
<div id=dump-list></div>
|
||||||
<a id=add-post href=javascript:; title="Add a post" tabindex=50>+</a>
|
<a id=add-post href=javascript:; title="Add a post">+</a>
|
||||||
</div>
|
</div>
|
||||||
<div id=file-n-submit>
|
<div id=file-n-submit>
|
||||||
<span id=qr-filename-container class=field tabindex=60>
|
<span id=qr-filename-container class=field tabindex=0>
|
||||||
<span id=qr-no-file>No selected file</span>
|
<span id=qr-no-file>No selected file</span>
|
||||||
<input id="qr-filename" data-name="filename" spellcheck="false">
|
<input id="qr-filename" data-name="filename" spellcheck="false">
|
||||||
<span id=qr-extras-container>
|
<span id=qr-extras-container>
|
||||||
@ -33,9 +33,9 @@
|
|||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
<label id=qr-spoiler-label>
|
<label id=qr-spoiler-label>
|
||||||
<input type=checkbox id=qr-file-spoiler title='Spoiler image' tabindex=70>
|
<input type=checkbox id=qr-file-spoiler title='Spoiler image'>
|
||||||
</label>
|
</label>
|
||||||
<input type=submit tabindex=80>
|
<input type=submit>
|
||||||
</div>
|
</div>
|
||||||
<input type=file multiple>
|
<input type=file multiple>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@ -52,16 +52,20 @@ Linkify =
|
|||||||
|
|
||||||
endNode = saved
|
endNode = saved
|
||||||
{data} = saved
|
{data} = saved
|
||||||
word += data
|
|
||||||
{length} = data
|
|
||||||
|
|
||||||
if end = space.exec data
|
if end = space.exec data
|
||||||
# Set our snapshot and regex to start on this node at this position when the loop resumes
|
# Set our snapshot and regex to start on this node at this position when the loop resumes
|
||||||
|
word += data[...end.index]
|
||||||
test.lastIndex = length = end.index
|
test.lastIndex = length = end.index
|
||||||
i--
|
i--
|
||||||
break
|
break
|
||||||
|
else
|
||||||
|
{length} = data
|
||||||
|
word += data
|
||||||
|
|
||||||
links.push Linkify.makeRange node, endNode, index, length if Linkify.regString.exec word
|
if Linkify.regString.test word
|
||||||
|
links.push Linkify.makeRange node, endNode, index, length
|
||||||
|
<%= assert('word is links[links.length-1].toString()') %>
|
||||||
|
|
||||||
break unless test.lastIndex and node is endNode
|
break unless test.lastIndex and node is endNode
|
||||||
|
|
||||||
@ -84,9 +88,9 @@ Linkify =
|
|||||||
[a-z\d%/]
|
[a-z\d%/]
|
||||||
)
|
)
|
||||||
| # This should account for virtually all links posted without http:
|
| # This should account for virtually all links posted without http:
|
||||||
[-a-z\d]+[.](
|
([-a-z\d]+[.])+(
|
||||||
aero|asia|biz|cat|com|coop|info|int|jobs|mobi|moe|museum|name|net|org|post|pro|tel|travel|xxx|edu|gov|mil|[a-z]{2}
|
aero|asia|biz|cat|com|coop|info|int|jobs|mobi|moe|museum|name|net|org|post|pro|tel|travel|xxx|edu|gov|mil|[a-z]{2}
|
||||||
)([:/]|(?!.))
|
)([:/]|(?![^\s'"]))
|
||||||
| # IPv4 Addresses
|
| # IPv4 Addresses
|
||||||
[\d]{1,3}\.[\d]{1,3}\.[\d]{1,3}\.[\d]{1,3}
|
[\d]{1,3}\.[\d]{1,3}\.[\d]{1,3}\.[\d]{1,3}
|
||||||
| # E-mails
|
| # E-mails
|
||||||
@ -103,10 +107,9 @@ Linkify =
|
|||||||
text = range.toString()
|
text = range.toString()
|
||||||
|
|
||||||
# Clean start of range
|
# Clean start of range
|
||||||
i = 0
|
i = text.search Linkify.regString
|
||||||
i++ while /[(\[{<>]/.test text.charAt i
|
|
||||||
|
|
||||||
if i
|
if i > 0
|
||||||
text = text.slice i
|
text = text.slice i
|
||||||
i-- while range.startOffset + i >= range.startContainer.data.length
|
i-- while range.startOffset + i >= range.startContainer.data.length
|
||||||
|
|
||||||
@ -237,9 +240,11 @@ Linkify =
|
|||||||
"#{status}'d"
|
"#{status}'d"
|
||||||
}"
|
}"
|
||||||
|
|
||||||
|
link.dataset.original = link.textContent
|
||||||
link.textContent = text
|
link.textContent = text
|
||||||
for post2 in post.clones
|
for post2 in post.clones
|
||||||
for link2 in $$ 'a.linkify', post2.nodes.comment when link2.href is link.href
|
for link2 in $$ 'a.linkify', post2.nodes.comment when link2.href is link.href
|
||||||
|
link2.dataset.original = link2.textContent
|
||||||
link2.textContent = text
|
link2.textContent = text
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|||||||
@ -1,10 +1,13 @@
|
|||||||
AntiAutoplay =
|
AntiAutoplay =
|
||||||
init: ->
|
init: ->
|
||||||
return if !Conf['Disable Autoplaying Sounds']
|
return if !Conf['Disable Autoplaying Sounds']
|
||||||
$.ready @ready
|
@stop audio for audio in $$ 'audio[autoplay]', doc
|
||||||
|
window.addEventListener 'loadstart', ((e) => @stop e.target), true
|
||||||
|
|
||||||
ready: ->
|
stop: (audio) ->
|
||||||
for audio in $$ 'audio[autoplay]'
|
return unless audio.autoplay
|
||||||
audio.pause()
|
audio.pause()
|
||||||
audio.autoplay = false
|
audio.autoplay = false
|
||||||
audio.controls = true
|
return if audio.controls
|
||||||
|
audio.controls = true
|
||||||
|
$.addClass audio, 'controls-added'
|
||||||
|
|||||||
@ -1,14 +1,10 @@
|
|||||||
RemoveSpoilers =
|
RemoveSpoilers =
|
||||||
init: ->
|
init: ->
|
||||||
if Conf['Reveal Spoilers'] and !Conf['Remove Spoilers']
|
if Conf['Reveal Spoilers']
|
||||||
$.addClass doc, 'reveal-spoilers'
|
$.addClass doc, 'reveal-spoilers'
|
||||||
|
|
||||||
return unless Conf['Remove Spoilers']
|
return unless Conf['Remove Spoilers']
|
||||||
|
|
||||||
if Conf['Reveal Spoilers']
|
|
||||||
@wrapper = (text) ->
|
|
||||||
"[spoiler]#{text}[/spoiler]"
|
|
||||||
|
|
||||||
Post.callbacks.push
|
Post.callbacks.push
|
||||||
name: 'Reveal Spoilers'
|
name: 'Reveal Spoilers'
|
||||||
cb: @node
|
cb: @node
|
||||||
@ -16,11 +12,10 @@ RemoveSpoilers =
|
|||||||
name: 'Reveal Spoilers'
|
name: 'Reveal Spoilers'
|
||||||
cb: @node
|
cb: @node
|
||||||
|
|
||||||
wrapper: (text) ->
|
|
||||||
text
|
|
||||||
|
|
||||||
node: (post) ->
|
node: (post) ->
|
||||||
spoilers = $$ 's', @nodes.comment
|
spoilers = $$ 's', @nodes.comment
|
||||||
for spoiler in spoilers
|
for spoiler in spoilers
|
||||||
$.replace spoiler, $.tn RemoveSpoilers.wrapper spoiler.textContent
|
span = $.el 'span', className: 'removed-spoiler'
|
||||||
|
$.replace spoiler, span
|
||||||
|
$.add span, [spoiler.childNodes...]
|
||||||
return
|
return
|
||||||
|
|||||||
@ -42,6 +42,29 @@ ThreadWatcher =
|
|||||||
Thread.callbacks.push
|
Thread.callbacks.push
|
||||||
name: 'Thread Watcher'
|
name: 'Thread Watcher'
|
||||||
cb: @node
|
cb: @node
|
||||||
|
CatalogThread.callbacks.push
|
||||||
|
name: 'Thread Watcher'
|
||||||
|
cb: @catalogNode
|
||||||
|
|
||||||
|
if g.VIEW is 'index' and Conf['JSON Navigation'] and Conf['Menu'] and g.BOARD.ID isnt 'f'
|
||||||
|
Menu.menu.addEntry
|
||||||
|
el: $.el 'a', href: 'javascript:;'
|
||||||
|
order: 6
|
||||||
|
open: ({thread}) ->
|
||||||
|
return false if Conf['Index Mode'] isnt 'catalog'
|
||||||
|
@el.textContent = if ThreadWatcher.isWatched thread
|
||||||
|
'Unwatch thread'
|
||||||
|
else
|
||||||
|
'Watch thread'
|
||||||
|
$.off @el, 'click', @cb if @cb
|
||||||
|
@cb = ->
|
||||||
|
$.event 'CloseMenu'
|
||||||
|
ThreadWatcher.toggle thread
|
||||||
|
$.on @el, 'click', @cb
|
||||||
|
true
|
||||||
|
|
||||||
|
isWatched: (thread) ->
|
||||||
|
ThreadWatcher.db?.get {boardID: thread.board.ID, threadID: thread.ID}
|
||||||
|
|
||||||
node: ->
|
node: ->
|
||||||
toggler = $.el 'img',
|
toggler = $.el 'img',
|
||||||
@ -49,6 +72,13 @@ ThreadWatcher =
|
|||||||
$.on toggler, 'click', ThreadWatcher.cb.toggle
|
$.on toggler, 'click', ThreadWatcher.cb.toggle
|
||||||
$.before $('input', @OP.nodes.post), toggler
|
$.before $('input', @OP.nodes.post), toggler
|
||||||
|
|
||||||
|
catalogNode: ->
|
||||||
|
$.addClass @nodes.root, 'watched' if ThreadWatcher.isWatched @thread
|
||||||
|
$.on @nodes.thumb.parentNode, 'click', (e) =>
|
||||||
|
return unless e.button is 0 and e.altKey
|
||||||
|
ThreadWatcher.toggle @thread
|
||||||
|
e.preventDefault()
|
||||||
|
|
||||||
ready: ->
|
ready: ->
|
||||||
$.off d, '4chanXInitFinished', ThreadWatcher.ready
|
$.off d, '4chanXInitFinished', ThreadWatcher.ready
|
||||||
return unless Main.isThisPageLegit()
|
return unless Main.isThisPageLegit()
|
||||||
@ -83,7 +113,10 @@ ThreadWatcher =
|
|||||||
ThreadWatcher.refresh()
|
ThreadWatcher.refresh()
|
||||||
$.event 'CloseMenu'
|
$.event 'CloseMenu'
|
||||||
toggle: ->
|
toggle: ->
|
||||||
ThreadWatcher.toggle Get.postFromNode(@).thread
|
{thread} = Get.postFromNode @
|
||||||
|
Index.followedThreadID = thread.ID
|
||||||
|
ThreadWatcher.toggle thread
|
||||||
|
delete Index.followedThreadID
|
||||||
rm: ->
|
rm: ->
|
||||||
[boardID, threadID] = @parentNode.dataset.fullID.split '.'
|
[boardID, threadID] = @parentNode.dataset.fullID.split '.'
|
||||||
ThreadWatcher.rm boardID, +threadID
|
ThreadWatcher.rm boardID, +threadID
|
||||||
@ -240,14 +273,17 @@ ThreadWatcher =
|
|||||||
for threadID in threads.keys
|
for threadID in threads.keys
|
||||||
thread = threads[threadID]
|
thread = threads[threadID]
|
||||||
toggler = $ '.watch-thread-link', thread.OP.nodes.post
|
toggler = $ '.watch-thread-link', thread.OP.nodes.post
|
||||||
watched = ThreadWatcher.db.get {boardID: thread.board.ID, threadID}
|
helper = if ThreadWatcher.isWatched thread then ['addClass', 'Unwatch'] else ['rmClass', 'Watch']
|
||||||
helper = if watched then ['addClass', 'Unwatch'] else ['rmClass', 'Watch']
|
|
||||||
$[helper[0]] toggler, 'watched'
|
$[helper[0]] toggler, 'watched'
|
||||||
|
$[helper[0]] thread.catalogView.nodes.root, 'watched' if thread.catalogView
|
||||||
toggler.title = "#{helper[1]} Thread"
|
toggler.title = "#{helper[1]} Thread"
|
||||||
|
|
||||||
for refresher in ThreadWatcher.menu.refreshers
|
for refresher in ThreadWatcher.menu.refreshers
|
||||||
refresher()
|
refresher()
|
||||||
return
|
|
||||||
|
if Index.nodes and Conf['Pin Watched Threads']
|
||||||
|
Index.sort()
|
||||||
|
Index.buildIndex()
|
||||||
|
|
||||||
toggle: (thread) ->
|
toggle: (thread) ->
|
||||||
boardID = thread.board.ID
|
boardID = thread.board.ID
|
||||||
|
|||||||
@ -14,7 +14,6 @@ QR.captcha =
|
|||||||
title: 'Verification'
|
title: 'Verification'
|
||||||
autocomplete: 'off'
|
autocomplete: 'off'
|
||||||
spellcheck: false
|
spellcheck: false
|
||||||
tabIndex: 45
|
|
||||||
@nodes = {container, input}
|
@nodes = {container, input}
|
||||||
|
|
||||||
$.on input, 'blur', QR.focusout
|
$.on input, 'blur', QR.focusout
|
||||||
|
|||||||
@ -213,12 +213,34 @@ QR =
|
|||||||
e?.preventDefault()
|
e?.preventDefault()
|
||||||
return unless QR.postingIsEnabled
|
return unless QR.postingIsEnabled
|
||||||
|
|
||||||
sel = d.getSelection()
|
sel = d.getSelection()
|
||||||
post = Get.postFromNode @
|
post = Get.postFromNode @
|
||||||
text = ">>#{post}\n"
|
text = ">>#{post}\n"
|
||||||
if (s = sel.toString().trim()) and post is Get.postFromNode sel.anchorNode
|
if sel.toString().trim() and post is Get.postFromNode sel.anchorNode
|
||||||
s = s.replace /\n/g, '\n>'
|
range = sel.getRangeAt 0
|
||||||
text += ">#{s}\n"
|
frag = range.cloneContents()
|
||||||
|
ancestor = range.commonAncestorContainer
|
||||||
|
# Quoting the insides of a spoiler/code tag.
|
||||||
|
if $.x 'ancestor-or-self::*[self::s or contains(@class,"removed-spoiler")]', ancestor
|
||||||
|
$.prepend frag, $.tn '[spoiler]'
|
||||||
|
$.add frag, $.tn '[/spoiler]'
|
||||||
|
if insideCode = $.x 'ancestor-or-self::pre[contains(@class,"prettyprint")]', ancestor
|
||||||
|
$.prepend frag, $.tn '[code]'
|
||||||
|
$.add frag, $.tn '[/code]'
|
||||||
|
for node in $$ (if insideCode then 'br' else '.prettyprint br'), frag
|
||||||
|
$.replace node, $.tn '\n'
|
||||||
|
for node in $$ 'br', frag
|
||||||
|
$.replace node, $.tn '\n>' unless node is frag.lastChild
|
||||||
|
for node in $$ 's, .removed-spoiler', frag
|
||||||
|
$.replace node, [$.tn('[spoiler]'), node.childNodes..., $.tn '[/spoiler]']
|
||||||
|
for node in $$ '.prettyprint', frag
|
||||||
|
$.replace node, [$.tn('[code]'), node.childNodes..., $.tn '[/code]']
|
||||||
|
for node in $$ '.linkify[data-original]', frag
|
||||||
|
$.replace node, $.tn node.dataset.original
|
||||||
|
for node in $$ '.embedder', frag
|
||||||
|
$.rm node.previousSibling if node.previousSibling?.nodeValue is ' '
|
||||||
|
$.rm node
|
||||||
|
text += ">#{frag.textContent.trim()}\n"
|
||||||
|
|
||||||
QR.open()
|
QR.open()
|
||||||
if QR.selected.isLocked
|
if QR.selected.isLocked
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user