Merge Zixaphir X
3
.gitignore
vendored
@ -2,8 +2,7 @@ node_modules/
|
|||||||
*~
|
*~
|
||||||
*.db
|
*.db
|
||||||
tmp-crx/
|
tmp-crx/
|
||||||
tmp-userjs/
|
|
||||||
tmp-userscript/
|
tmp-userscript/
|
||||||
builds/4chan-X-Chrome.zip
|
builds/4chan-X-Chrome.zip
|
||||||
builds/4chan-X-Opera.nex
|
builds/4chan-X-Opera.nex
|
||||||
Gruntfile.js
|
Gruntfile.js
|
||||||
|
|||||||
21
CHANGELOG.md
Normal file → Executable file
@ -1,3 +1,23 @@
|
|||||||
|
**MayhemYDG**:
|
||||||
|
- **New feature**: `Show Dice Roll` (with @carboncopy)
|
||||||
|
- Shows dice that were entered into the email field on /tg/.
|
||||||
|
- Fix impossibility to create new threads when in dead threads.
|
||||||
|
- Fix flag filtering on /sp/ and /int/.
|
||||||
|
- Update archives. (with @woxxy and @proplex)
|
||||||
|
- Minor fixes.
|
||||||
|
- Minor optimizations.
|
||||||
|
|
||||||
|
**Zixaphir**:
|
||||||
|
- Linkifier Rewrite.
|
||||||
|
- Fix Quote Threading toggle.
|
||||||
|
- Added Twitch.tv and Vine embedding (with @ihavenoface)
|
||||||
|
- Keybinds to scroll to posts that quote you.
|
||||||
|
- Minor optimizations.
|
||||||
|
- Minor fixes.
|
||||||
|
|
||||||
|
**aeosynth**:
|
||||||
|
- Update Gruntfile.coffee.
|
||||||
|
|
||||||
### v1.2.25
|
### v1.2.25
|
||||||
*2013-08-04*
|
*2013-08-04*
|
||||||
|
|
||||||
@ -54,7 +74,6 @@
|
|||||||
|
|
||||||
### v1.2.17
|
### v1.2.17
|
||||||
*2013-06-17*
|
*2013-06-17*
|
||||||
|
|
||||||
**seaweedchan**:
|
**seaweedchan**:
|
||||||
- Fix full images being forced onto their own line
|
- Fix full images being forced onto their own line
|
||||||
|
|
||||||
|
|||||||
138
Gruntfile.coffee
Normal file → Executable file
@ -1,18 +1,18 @@
|
|||||||
module.exports = (grunt) ->
|
module.exports = (grunt) ->
|
||||||
|
|
||||||
pkg = grunt.file.readJSON 'package.json'
|
|
||||||
concatOptions =
|
concatOptions =
|
||||||
process:
|
process: Object.create(null, data:
|
||||||
data: pkg
|
get: -> grunt.config 'pkg'
|
||||||
|
enumerable: true
|
||||||
|
)
|
||||||
shellOptions =
|
shellOptions =
|
||||||
stdout: true
|
stdout: true
|
||||||
stderr: true
|
stderr: true
|
||||||
failOnError: true
|
failOnError: true
|
||||||
|
|
||||||
# Project configuration.
|
# Project configuration.
|
||||||
grunt.initConfig
|
grunt.initConfig
|
||||||
pkg: pkg
|
pkg: grunt.file.readJSON 'package.json'
|
||||||
concat:
|
concat:
|
||||||
coffee:
|
coffee:
|
||||||
options: concatOptions
|
options: concatOptions
|
||||||
@ -41,8 +41,8 @@ module.exports = (grunt) ->
|
|||||||
meta:
|
meta:
|
||||||
options: concatOptions
|
options: concatOptions
|
||||||
files:
|
files:
|
||||||
'LICENSE': 'src/General/meta/banner.js',
|
'LICENSE': 'src/General/meta/banner.js',
|
||||||
'latest.js': 'src/General/meta/latest.js'
|
'latest.js': 'src/General/meta/latest.js'
|
||||||
|
|
||||||
crx:
|
crx:
|
||||||
options: concatOptions
|
options: concatOptions
|
||||||
@ -51,19 +51,9 @@ module.exports = (grunt) ->
|
|||||||
'builds/crx/script.js': [
|
'builds/crx/script.js': [
|
||||||
'src/General/meta/botproc.js'
|
'src/General/meta/botproc.js'
|
||||||
'src/General/meta/banner.js'
|
'src/General/meta/banner.js'
|
||||||
|
'src/General/meta/usestrict.js'
|
||||||
'tmp-<%= pkg.type %>/script.js'
|
'tmp-<%= pkg.type %>/script.js'
|
||||||
]
|
]
|
||||||
|
|
||||||
userjs:
|
|
||||||
options: concatOptions
|
|
||||||
src: [
|
|
||||||
'src/General/meta/botproc.js'
|
|
||||||
'src/General/meta/metadata.js'
|
|
||||||
'src/General/meta/banner.js'
|
|
||||||
'tmp-<%= pkg.type %>/script.js'
|
|
||||||
]
|
|
||||||
dest: 'builds/<%= pkg.name %>.js'
|
|
||||||
|
|
||||||
userscript:
|
userscript:
|
||||||
options: concatOptions
|
options: concatOptions
|
||||||
files:
|
files:
|
||||||
@ -72,13 +62,13 @@ module.exports = (grunt) ->
|
|||||||
'src/General/meta/botproc.js'
|
'src/General/meta/botproc.js'
|
||||||
'src/General/meta/metadata.js'
|
'src/General/meta/metadata.js'
|
||||||
'src/General/meta/banner.js'
|
'src/General/meta/banner.js'
|
||||||
|
'src/General/meta/usestrict.js'
|
||||||
'tmp-<%= pkg.type %>/script.js'
|
'tmp-<%= pkg.type %>/script.js'
|
||||||
]
|
]
|
||||||
|
|
||||||
copy:
|
copy:
|
||||||
crx:
|
crx:
|
||||||
src: 'src/General/img/*.png'
|
src: 'src/General/img/*.png'
|
||||||
dest: 'builds/crx/'
|
dest: 'builds/crx/'
|
||||||
expand: true
|
expand: true
|
||||||
flatten: true
|
flatten: true
|
||||||
|
|
||||||
@ -91,24 +81,31 @@ module.exports = (grunt) ->
|
|||||||
build: [
|
build: [
|
||||||
'concat:meta'
|
'concat:meta'
|
||||||
'build-crx'
|
'build-crx'
|
||||||
'build-userjs'
|
|
||||||
'build-userscript'
|
'build-userscript'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
bump:
|
||||||
|
options:
|
||||||
|
updateConfigs: [
|
||||||
|
'pkg'
|
||||||
|
]
|
||||||
|
commit: false
|
||||||
|
createTag: false
|
||||||
|
push: false
|
||||||
|
|
||||||
shell:
|
shell:
|
||||||
commit:
|
commit:
|
||||||
options: shellOptions
|
options: shellOptions
|
||||||
command: [
|
command: [
|
||||||
'git checkout <%= pkg.meta.mainBranch %>',
|
'git checkout <%= pkg.meta.mainBranch %>'
|
||||||
'git commit -am "Release <%= pkg.meta.name %> v<%= pkg.version %>."',
|
'git commit -am "Release <%= pkg.meta.name %> v<%= pkg.version %>."'
|
||||||
'git tag -a <%= pkg.version %> -m "<%= pkg.meta.name %> v<%= pkg.version %>."',
|
'git tag -a <%= pkg.version %> -m "<%= pkg.meta.name %> v<%= pkg.version %>."'
|
||||||
'git tag -af stable -m "<%= pkg.meta.name %> v<%= pkg.version %>."'
|
'git tag -af stable -m "<%= pkg.meta.name %> v<%= pkg.version %>."'
|
||||||
].join(' && ')
|
].join ' && '
|
||||||
stdout: true
|
|
||||||
|
|
||||||
push:
|
push:
|
||||||
options: shellOptions
|
options: shellOptions
|
||||||
command: 'git push origin --tags -f && git push origin --all'
|
command: 'git push origin --tags -f && git push origin --all'
|
||||||
|
|
||||||
watch:
|
watch:
|
||||||
all:
|
all:
|
||||||
@ -124,35 +121,28 @@ module.exports = (grunt) ->
|
|||||||
compress:
|
compress:
|
||||||
crx:
|
crx:
|
||||||
options:
|
options:
|
||||||
archive: 'builds/4chan-X-Chrome.zip'
|
archive: 'builds/<%= pkg.name %>.zip'
|
||||||
level: 9
|
level: 9
|
||||||
pretty: true
|
pretty: true
|
||||||
expand: true
|
expand: true
|
||||||
cwd: 'builds/crx/'
|
flatten: true
|
||||||
src: '**'
|
src: 'builds/crx/*'
|
||||||
|
dest: '/'
|
||||||
clean:
|
clean:
|
||||||
builds: 'builds'
|
builds: 'builds'
|
||||||
tmpcrx: 'tmp-crx'
|
tmpcrx: 'tmp-crx'
|
||||||
tmpuserjs: 'tmp-userjs'
|
|
||||||
tmpuserscript: 'tmp-userscript'
|
tmpuserscript: 'tmp-userscript'
|
||||||
|
|
||||||
grunt.loadNpmTasks 'grunt-bump'
|
require('matchdep').filterDev('grunt-*').forEach grunt.loadNpmTasks
|
||||||
grunt.loadNpmTasks 'grunt-concurrent'
|
|
||||||
grunt.loadNpmTasks 'grunt-contrib-clean'
|
|
||||||
grunt.loadNpmTasks 'grunt-contrib-coffee'
|
|
||||||
grunt.loadNpmTasks 'grunt-contrib-compress'
|
|
||||||
grunt.loadNpmTasks 'grunt-contrib-concat'
|
|
||||||
grunt.loadNpmTasks 'grunt-contrib-copy'
|
|
||||||
grunt.loadNpmTasks 'grunt-contrib-watch'
|
|
||||||
grunt.loadNpmTasks 'grunt-shell'
|
|
||||||
|
|
||||||
grunt.registerTask 'default', [
|
grunt.registerTask 'default', [
|
||||||
'build'
|
'build'
|
||||||
]
|
]
|
||||||
|
|
||||||
grunt.registerTask 'set-build', 'Set the build type variable', (type) ->
|
grunt.registerTask 'set-build', 'Set the build type variable', (type) ->
|
||||||
pkg.type = type;
|
pkg = grunt.config 'pkg'
|
||||||
|
pkg.type = type
|
||||||
|
grunt.config 'pkg', pkg
|
||||||
grunt.log.ok 'pkg.type = %s', type
|
grunt.log.ok 'pkg.type = %s', type
|
||||||
|
|
||||||
grunt.registerTask 'build', [
|
grunt.registerTask 'build', [
|
||||||
@ -168,14 +158,6 @@ module.exports = (grunt) ->
|
|||||||
'clean:tmpcrx'
|
'clean:tmpcrx'
|
||||||
]
|
]
|
||||||
|
|
||||||
grunt.registerTask 'build-userjs', [
|
|
||||||
'set-build:userjs'
|
|
||||||
'concat:coffee'
|
|
||||||
'coffee:script'
|
|
||||||
'concat:userjs'
|
|
||||||
'clean:tmpuserjs'
|
|
||||||
]
|
|
||||||
|
|
||||||
grunt.registerTask 'build-userscript', [
|
grunt.registerTask 'build-userscript', [
|
||||||
'set-build:userscript'
|
'set-build:userscript'
|
||||||
'concat:coffee'
|
'concat:coffee'
|
||||||
@ -185,40 +167,36 @@ module.exports = (grunt) ->
|
|||||||
]
|
]
|
||||||
|
|
||||||
grunt.registerTask 'release', [
|
grunt.registerTask 'release', [
|
||||||
'default'
|
'build'
|
||||||
'compress:crx'
|
|
||||||
'shell:commit'
|
'shell:commit'
|
||||||
'shell:push'
|
'shell:push'
|
||||||
|
'build-crx'
|
||||||
|
'compress:crx'
|
||||||
]
|
]
|
||||||
|
grunt.registerTask 'patch', [
|
||||||
grunt.registerTask 'patch', [
|
'bump'
|
||||||
'bump-only'
|
|
||||||
'reloadPkg'
|
|
||||||
'updcl:3'
|
'updcl:3'
|
||||||
|
'release'
|
||||||
]
|
]
|
||||||
|
|
||||||
grunt.registerTask 'minor', [
|
grunt.registerTask 'minor', [
|
||||||
'bump-only:minor'
|
'bump:minor'
|
||||||
'reloadPkg'
|
|
||||||
'updcl:2'
|
'updcl:2'
|
||||||
|
'release'
|
||||||
]
|
]
|
||||||
|
|
||||||
grunt.registerTask 'major', [
|
grunt.registerTask 'major', [
|
||||||
'bump-only:major'
|
'bump:major'
|
||||||
'reloadPkg'
|
|
||||||
'updcl:1'
|
'updcl:1'
|
||||||
|
'release'
|
||||||
]
|
]
|
||||||
|
|
||||||
grunt.registerTask 'reloadPkg', 'Reload the package', ->
|
grunt.registerTask 'updcl', 'Update the changelog', (headerLevel) ->
|
||||||
# Update the `pkg` object with the new version.
|
headerPrefix = new Array(+headerLevel + 1).join '#'
|
||||||
pkg = grunt.file.readJSON('package.json')
|
{version} = grunt.config 'pkg'
|
||||||
grunt.config.data.pkg = concatOptions.process.data = pkg
|
today = grunt.template.today 'yyyy-mm-dd'
|
||||||
grunt.log.ok('pkg reloaded.')
|
changelog = grunt.file.read 'CHANGELOG.md'
|
||||||
|
|
||||||
|
grunt.file.write 'CHANGELOG.md', "#{headerPrefix} #{version} - *#{today}*\n\n#{changelog}"
|
||||||
|
grunt.log.ok "Changelog updated for v#{version}."
|
||||||
|
|
||||||
grunt.registerTask 'updcl', 'Update the changelog', (i) ->
|
|
||||||
# i is the number of #s for markdown.
|
|
||||||
version = []
|
|
||||||
version.length = +i + 1
|
|
||||||
version = version.join('#') + ' v' + pkg.version + '\n*' + grunt.template.today('yyyy-mm-dd') + '*\n'
|
|
||||||
grunt.file.write 'CHANGELOG.md', version + '\n' + grunt.file.read('CHANGELOG.md')
|
|
||||||
grunt.log.ok 'Changelog updated for v' + pkg.version + '.'
|
|
||||||
2
README.md
Normal file → Executable file
@ -41,4 +41,4 @@ Note: this is only used to release new 4chan X versions, and is **not** needed o
|
|||||||
|
|
||||||
- Edit the CoffeeScript sources.
|
- Edit the CoffeeScript sources.
|
||||||
- If the edits affect regular users, edit the changelog.
|
- If the edits affect regular users, edit the changelog.
|
||||||
- Open a pull request.
|
- Open a pull request.
|
||||||
|
|||||||
0
builds/4chan-X.js
Normal file → Executable file
0
builds/4chan-X.meta.js
Normal file → Executable file
2219
builds/4chan-X.user.js
Normal file → Executable file
0
builds/crx/icon128.png
Normal file → Executable file
|
Before Width: | Height: | Size: 196 B After Width: | Height: | Size: 196 B |
0
builds/crx/icon16.png
Normal file → Executable file
|
Before Width: | Height: | Size: 157 B After Width: | Height: | Size: 157 B |
0
builds/crx/icon48.png
Normal file → Executable file
|
Before Width: | Height: | Size: 204 B After Width: | Height: | Size: 204 B |
3
builds/crx/manifest.json
Normal file → Executable file
@ -15,7 +15,8 @@
|
|||||||
"run_at": "document_start"
|
"run_at": "document_start"
|
||||||
}],
|
}],
|
||||||
"homepage_url": "http://seaweedchan.github.io/4chan-x/",
|
"homepage_url": "http://seaweedchan.github.io/4chan-x/",
|
||||||
"minimum_chrome_version": "26",
|
"minimum_chrome_version": "27",
|
||||||
|
"minimum_opera_version": "15",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
"storage"
|
"storage"
|
||||||
]
|
]
|
||||||
|
|||||||
2183
builds/crx/script.js
Normal file → Executable file
110
json/archives.json
Executable file
@ -0,0 +1,110 @@
|
|||||||
|
[{
|
||||||
|
"uid": 0,
|
||||||
|
"name": "Foolz",
|
||||||
|
"domain": "archive.foolz.us",
|
||||||
|
"http": true,
|
||||||
|
"https": true,
|
||||||
|
"software": "foolfuuka",
|
||||||
|
"boards": ["a", "co", "gd", "jp", "m", "q", "sp", "tg", "tv", "v", "vg", "vp", "vr", "wsg"],
|
||||||
|
"files": ["a", "gd", "jp", "m", "q", "tg", "vg", "vp", "vr", "wsg"]
|
||||||
|
}, {
|
||||||
|
"uid": 1,
|
||||||
|
"name": "NSFW Foolz",
|
||||||
|
"domain": "nsfw.foolz.us",
|
||||||
|
"http": true,
|
||||||
|
"https": true,
|
||||||
|
"software": "foolfuuka",
|
||||||
|
"boards": ["u"],
|
||||||
|
"files": ["u"]
|
||||||
|
}, {
|
||||||
|
"uid": 2,
|
||||||
|
"name": "The Dark Cave",
|
||||||
|
"domain": "archive.thedarkcave.org",
|
||||||
|
"http": true,
|
||||||
|
"https": true,
|
||||||
|
"software": "foolfuuka",
|
||||||
|
"boards": ["c", "int", "out", "po"],
|
||||||
|
"files": ["c", "po"]
|
||||||
|
}, {
|
||||||
|
"uid": 3,
|
||||||
|
"name": "4plebs",
|
||||||
|
"domain": "archive.4plebs.org",
|
||||||
|
"http": true,
|
||||||
|
"https": false,
|
||||||
|
"software": "foolfuuka",
|
||||||
|
"boards": ["hr", "tg", "tv", "x"],
|
||||||
|
"files": ["hr", "tg", "tv", "x"]
|
||||||
|
}, {
|
||||||
|
"uid": 4,
|
||||||
|
"name": "Nyafuu",
|
||||||
|
"domain": "archive.nyafuu.org",
|
||||||
|
"http": true,
|
||||||
|
"https": true,
|
||||||
|
"software": "foolfuuka",
|
||||||
|
"boards": ["c", "w", "wg"],
|
||||||
|
"files": ["c", "w", "wg"]
|
||||||
|
}, {
|
||||||
|
"uid": 11,
|
||||||
|
"name": "Foolz a Shit",
|
||||||
|
"domain": "archive.foolzashit.com",
|
||||||
|
"http": true,
|
||||||
|
"https": true,
|
||||||
|
"software": "foolfuuka",
|
||||||
|
"boards": ["adv", "asp", "cm", "e", "i", "lgbt", "n", "o", "p", "pol", "s", "s4s", "t", "trv", "y"],
|
||||||
|
"files": ["adv", "asp", "cm", "e", "i", "lgbt", "n", "o", "p", "s", "s4s", "t", "trv", "y"]
|
||||||
|
}, {
|
||||||
|
"uid": 12,
|
||||||
|
"name": "fap archive",
|
||||||
|
"domain": "fuuka.worldathleticproject.org",
|
||||||
|
"http": true,
|
||||||
|
"https": false,
|
||||||
|
"software": "foolfuuka",
|
||||||
|
"boards": ["b", "e", "h", "hc", "p", "s", "u"],
|
||||||
|
"files": ["b", "e", "h", "hc", "p", "s", "u"]
|
||||||
|
}, {
|
||||||
|
"uid": 7,
|
||||||
|
"name": "Install Gentoo",
|
||||||
|
"domain": "archive.installgentoo.net",
|
||||||
|
"http": false,
|
||||||
|
"https": true,
|
||||||
|
"software": "fuuka",
|
||||||
|
"boards": ["diy", "g", "sci"],
|
||||||
|
"files": []
|
||||||
|
}, {
|
||||||
|
"uid": 8,
|
||||||
|
"name": "Rebecca Black Tech",
|
||||||
|
"domain": "rbt.asia",
|
||||||
|
"http": true,
|
||||||
|
"https": true,
|
||||||
|
"software": "fuuka",
|
||||||
|
"boards": ["cgl", "g", "mu", "w"],
|
||||||
|
"files": ["cgl", "g", "mu", "w"]
|
||||||
|
}, {
|
||||||
|
"uid": 9,
|
||||||
|
"name": "Heinessen",
|
||||||
|
"domain": "archive.heinessen.com",
|
||||||
|
"http": true,
|
||||||
|
"https": false,
|
||||||
|
"software": "fuuka",
|
||||||
|
"boards": ["an", "fit", "k", "mlp", "r9k", "toy"],
|
||||||
|
"files": ["an", "fit", "k", "r9k", "toy"]
|
||||||
|
}, {
|
||||||
|
"uid": 10,
|
||||||
|
"name": "warosu",
|
||||||
|
"domain": "fuuka.warosu.org",
|
||||||
|
"http": true,
|
||||||
|
"https": true,
|
||||||
|
"software": "fuuka",
|
||||||
|
"boards": ["3", "cgl", "ck", "fa", "ic", "jp", "lit", "q", "tg", "vr"],
|
||||||
|
"files": ["3", "cgl", "ck", "fa", "ic", "jp", "lit", "q", "tg", "vr"]
|
||||||
|
}, {
|
||||||
|
"uid": 13,
|
||||||
|
"name": "Foolz Beta",
|
||||||
|
"domain": "beta.foolz.us",
|
||||||
|
"http": true,
|
||||||
|
"https": true,
|
||||||
|
"withCredentials": true,
|
||||||
|
"software": "foolfuuka",
|
||||||
|
"boards": ["a", "co", "gd", "h", "jp", "m", "mlp", "q", "sp", "tg", "tv", "u", "v", "vg", "vp", "vr", "wsg"],
|
||||||
|
"files": ["a", "gd", "h", "jp", "m", "q", "tg", "u", "vg", "vp", "vr", "wsg"]
|
||||||
|
}]
|
||||||
11
package.json
Normal file → Executable file
@ -22,14 +22,15 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"grunt": "~0.4.1",
|
"grunt": "~0.4.1",
|
||||||
"grunt-bump": "~0.0.11",
|
"grunt-bump": "~0.0.11",
|
||||||
"grunt-concurrent": "~0.2.0",
|
"grunt-concurrent": "~0.3.0",
|
||||||
"grunt-contrib-clean": "~0.4.1",
|
"grunt-contrib-clean": "~0.5.0",
|
||||||
"grunt-contrib-coffee": "~0.7.0",
|
"grunt-contrib-coffee": "~0.7.0",
|
||||||
"grunt-contrib-compress": "~0.5.1",
|
"grunt-contrib-compress": "~0.5.2",
|
||||||
"grunt-contrib-concat": "~0.3.0",
|
"grunt-contrib-concat": "~0.3.0",
|
||||||
"grunt-contrib-copy": "~0.4.1",
|
"grunt-contrib-copy": "~0.4.1",
|
||||||
"grunt-contrib-watch": "~0.4.4",
|
"grunt-contrib-watch": "~0.5.0",
|
||||||
"grunt-shell": "~0.2.2"
|
"grunt-shell": "~0.3.1",
|
||||||
|
"matchdep": "~0.1.2"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|||||||
201
src/Archive/Redirect.coffee
Normal file → Executable file
@ -1,117 +1,124 @@
|
|||||||
Redirect =
|
Redirect =
|
||||||
thread: {}
|
data:
|
||||||
post: {}
|
thread: {}
|
||||||
file: {}
|
post: {}
|
||||||
|
file: {}
|
||||||
|
|
||||||
init: ->
|
init: ->
|
||||||
for boardID, data of Conf['selectedArchives']
|
for boardID, data of Conf['selectedArchives']
|
||||||
for type, id of data
|
for type, id of data
|
||||||
for name, archive of Redirect.archives
|
if archive = Redirect.archives[id]
|
||||||
continue if name isnt id or type is 'post' and archive.software isnt 'foolfuuka'
|
boards = archive[type] or archive['boards']
|
||||||
arr = if type is 'file'
|
continue unless boards.contains boardID
|
||||||
archive.files
|
Redirect.data[type][boardID] = archive
|
||||||
else
|
|
||||||
archive.boards
|
|
||||||
Redirect[type][boardID] = archive if arr.contains boardID
|
|
||||||
for name, archive of Redirect.archives
|
for name, archive of Redirect.archives
|
||||||
for boardID in archive.boards
|
for boardID in archive.boards
|
||||||
unless boardID of Redirect.thread
|
unless boardID of Redirect.data.thread
|
||||||
Redirect.thread[boardID] = archive
|
Redirect.data.thread[boardID] = archive
|
||||||
unless boardID of Redirect.post or archive.software isnt 'foolfuuka'
|
unless boardID of Redirect.data.post or archive.software isnt 'foolfuuka'
|
||||||
Redirect.post[boardID] = archive
|
Redirect.data.post[boardID] = archive
|
||||||
unless boardID of Redirect.file or !archive.files.contains boardID
|
unless boardID of Redirect.data.file or !archive.files.contains boardID
|
||||||
Redirect.file[boardID] = archive
|
Redirect.data.file[boardID] = archive
|
||||||
return
|
return
|
||||||
|
|
||||||
archives:
|
archives:
|
||||||
'Foolz':
|
|
||||||
'domain': 'archive.foolz.us'
|
|
||||||
'http': false
|
|
||||||
'https': true
|
|
||||||
'software': 'foolfuuka'
|
|
||||||
'boards': ['a', 'co', 'gd', 'jp', 'm', 'q', 'sp', 'tg', 'tv', 'v', 'vg', 'vp', 'vr', 'wsg']
|
|
||||||
'files': ['a', 'gd', 'jp', 'm', 'q', 'tg', 'vg', 'vp', 'vr', 'wsg']
|
|
||||||
|
|
||||||
'NSFW Foolz':
|
|
||||||
'domain': 'nsfw.foolz.us'
|
|
||||||
'http': false
|
|
||||||
'https': true
|
|
||||||
'software': 'foolfuuka'
|
|
||||||
'boards': ['u']
|
|
||||||
'files': ['u']
|
|
||||||
|
|
||||||
'The Dark Cave':
|
|
||||||
'domain': 'archive.thedarkcave.org'
|
|
||||||
'http': true
|
|
||||||
'https': true
|
|
||||||
'software': 'foolfuuka'
|
|
||||||
'boards': ['c', 'int', 'out', 'po']
|
|
||||||
'files': ['c', 'po']
|
|
||||||
|
|
||||||
'4plebs':
|
'4plebs':
|
||||||
'domain': 'archive.4plebs.org'
|
domain: 'archive.4plebs.org'
|
||||||
'http': true
|
http: true
|
||||||
'software': 'foolfuuka'
|
software: 'foolfuuka'
|
||||||
'boards': ['hr', 'tg', 'tv', 'x']
|
boards: ['hr', 'tg', 'tv', 'x']
|
||||||
'files': ['hr', 'tg', 'tv', 'x']
|
files: ['hr', 'tg', 'tv', 'x']
|
||||||
|
|
||||||
'Nyafuu':
|
'fap archive':
|
||||||
'domain': 'archive.nyafuu.org'
|
domain: 'fuuka.worldathleticproject.org'
|
||||||
'http': true
|
http: true
|
||||||
'https': true
|
https: false
|
||||||
'software': 'foolfuuka'
|
software: 'foolfuuka'
|
||||||
'boards': ['c', 'w', 'wg']
|
boards: ['b', 'e', 'h', 'hc', 'p', 's', 'u']
|
||||||
'files': ['c', 'w', 'wg']
|
files: ['b', 'e', 'h', 'hc', 'p', 's', 'u']
|
||||||
|
|
||||||
|
'Foolz':
|
||||||
|
domain: 'archive.foolz.us'
|
||||||
|
http: false
|
||||||
|
https: true
|
||||||
|
software: 'foolfuuka'
|
||||||
|
boards: ['a', 'co', 'gd', 'jp', 'm', 'q', 'sp', 'tg', 'tv', 'v', 'vg', 'vp', 'vr', 'wsg']
|
||||||
|
files: ['a', 'gd', 'jp', 'm', 'q', 'tg', 'vg', 'vp', 'vr', 'wsg']
|
||||||
|
|
||||||
'Foolz a Shit':
|
'Foolz a Shit':
|
||||||
'domain': 'archive.foolzashit.com'
|
domain: 'archive.foolzashit.com'
|
||||||
'http': true
|
http: true
|
||||||
'https': true
|
https: true
|
||||||
'software': 'foolfuuka'
|
software: 'foolfuuka'
|
||||||
'boards': ['adv', 'asp', 'cm', 'i', 'lgbt', 'n', 'o', 'p', 's4s', 't', 'trv']
|
boards: ['adv', 'asp', 'cm', 'i', 'lgbt', 'n', 'o', 'p', 's4s', 't', 'trv']
|
||||||
'files': ['adv', 'asp', 'cm', 'i', 'lgbt', 'n', 'o', 'p', 's4s', 't', 'trv']
|
files: ['adv', 'asp', 'cm', 'i', 'lgbt', 'n', 'o', 'p', 's4s', 't', 'trv']
|
||||||
|
|
||||||
'World Athletic Project':
|
'Foolz Beta':
|
||||||
'domain': 'fuuka.worldathleticproject.org'
|
domain: 'beta.foolz.us'
|
||||||
'http': true
|
http: true
|
||||||
'https': false
|
https: true
|
||||||
'software': 'foolfuuka'
|
withCredentials: true
|
||||||
'boards': ['e', 'h', 'hc', 'p', 's', 'u']
|
software: 'foolfuuka'
|
||||||
'files': ['e', 'h', 'hc', 'p', 's', 'u']
|
boards: ['a', 'co', 'gd', 'h', 'jp', 'm', 'mlp', 'q', 'sp', 'tg', 'tv', 'u', 'v', 'vg', 'vp', 'vr', 'wsg'],
|
||||||
|
files: ['a', 'gd', 'h', 'jp', 'm', 'q', 'tg', 'u', 'vg', 'vp', 'vr', 'wsg']
|
||||||
'Install Gentoo':
|
|
||||||
'domain': 'archive.installgentoo.net'
|
|
||||||
'http': false
|
|
||||||
'https': true
|
|
||||||
'software': 'fuuka'
|
|
||||||
'boards': ['diy', 'g', 'sci']
|
|
||||||
'files': []
|
|
||||||
|
|
||||||
'warosu':
|
|
||||||
'domain': 'fuuka.warosu.org'
|
|
||||||
'http': true
|
|
||||||
'https': true
|
|
||||||
'software': 'fuuka'
|
|
||||||
'boards': ['3', 'cgl', 'ck', 'fa', 'ic', 'jp', 'lit', 'q', 'tg', 'vr']
|
|
||||||
'files': ['3', 'cgl', 'ck', 'fa', 'ic', 'jp', 'lit', 'q', 'tg', 'vr']
|
|
||||||
|
|
||||||
'Rebecca Black Tech':
|
|
||||||
'domain': 'rbt.asia'
|
|
||||||
'http': true
|
|
||||||
'https': true
|
|
||||||
'software': 'fuuka'
|
|
||||||
'boards': ['cgl', 'g', 'mu', 'w']
|
|
||||||
'files': ['cgl', 'g', 'mu', 'w']
|
|
||||||
|
|
||||||
'Heinessen':
|
'Heinessen':
|
||||||
'domain': 'archive.heinessen.com'
|
domain: 'archive.heinessen.com'
|
||||||
'http': true
|
http: true
|
||||||
'software': 'fuuka'
|
software: 'fuuka'
|
||||||
'boards': ['an', 'fit', 'k', 'mlp', 'r9k', 'toy']
|
boards: ['an', 'fit', 'k', 'mlp', 'r9k', 'toy']
|
||||||
'files': ['an', 'k', 'toy']
|
files: ['an', 'k', 'toy']
|
||||||
|
|
||||||
|
'Install Gentoo':
|
||||||
|
domain: 'archive.installgentoo.net'
|
||||||
|
http: false
|
||||||
|
https: true
|
||||||
|
software: 'fuuka'
|
||||||
|
boards: ['diy', 'g', 'sci']
|
||||||
|
files: []
|
||||||
|
|
||||||
|
'NSFW Foolz':
|
||||||
|
domain: 'nsfw.foolz.us'
|
||||||
|
http: false
|
||||||
|
https: true
|
||||||
|
software: 'foolfuuka'
|
||||||
|
boards: ['u']
|
||||||
|
files: ['u']
|
||||||
|
|
||||||
|
'Nyafuu':
|
||||||
|
domain: 'archive.nyafuu.org'
|
||||||
|
http: true
|
||||||
|
https: true
|
||||||
|
software: 'foolfuuka'
|
||||||
|
boards: ['c', 'w', 'wg']
|
||||||
|
files: ['c', 'w', 'wg']
|
||||||
|
|
||||||
|
'Rebecca Black Tech':
|
||||||
|
domain: 'rbt.asia'
|
||||||
|
http: true
|
||||||
|
https: true
|
||||||
|
software: 'fuuka'
|
||||||
|
boards: ['cgl', 'g', 'mu', 'w']
|
||||||
|
files: ['cgl', 'g', 'mu', 'w']
|
||||||
|
|
||||||
|
'The Dark Cave':
|
||||||
|
domain: 'archive.thedarkcave.org'
|
||||||
|
http: true
|
||||||
|
https: true
|
||||||
|
software: 'foolfuuka'
|
||||||
|
boards: ['c', 'int', 'out', 'po']
|
||||||
|
files: ['c', 'po']
|
||||||
|
|
||||||
|
'warosu':
|
||||||
|
domain: 'fuuka.warosu.org'
|
||||||
|
http: true
|
||||||
|
https: true
|
||||||
|
software: 'fuuka'
|
||||||
|
boards: ['3', 'cgl', 'ck', 'fa', 'ic', 'jp', 'lit', 'q', 'tg', 'vr']
|
||||||
|
files: ['3', 'cgl', 'ck', 'fa', 'ic', 'jp', 'lit', 'q', 'tg', 'vr']
|
||||||
|
|
||||||
to: (dest, data) ->
|
to: (dest, data) ->
|
||||||
archive = (if dest is 'search' then Redirect.thread else Redirect[dest])[data.boardID]
|
archive = (if dest is 'search' then Redirect.data.thread else Redirect.data[dest])[data.boardID]
|
||||||
return '' unless archive
|
return '' unless archive
|
||||||
Redirect[dest] archive, data
|
Redirect[dest] archive, data
|
||||||
|
|
||||||
@ -144,7 +151,9 @@ Redirect =
|
|||||||
# Remove necessary HTTPS procotol in September 2013.
|
# Remove necessary HTTPS procotol in September 2013.
|
||||||
if ['Foolz', 'NSFW Foolz'].contains archive.name
|
if ['Foolz', 'NSFW Foolz'].contains archive.name
|
||||||
protocol = 'https://'
|
protocol = 'https://'
|
||||||
"#{protocol}#{archive.domain}/_/api/chan/post/?board=#{boardID}&num=#{postID}"
|
URL = new String "#{protocol}#{archive.domain}/_/api/chan/post/?board=#{boardID}&num=#{postID}"
|
||||||
|
URL.archive = archive
|
||||||
|
URL
|
||||||
|
|
||||||
file: (archive, {boardID, filename}) ->
|
file: (archive, {boardID, filename}) ->
|
||||||
"#{Redirect.protocol archive}#{archive.domain}/#{boardID}/full_image/#{filename}"
|
"#{Redirect.protocol archive}#{archive.domain}/#{boardID}/full_image/#{filename}"
|
||||||
|
|||||||
0
src/Filtering/Anonymize.coffee
Normal file → Executable file
2
src/Filtering/Filter.coffee
Normal file → Executable file
@ -209,7 +209,7 @@ Filter =
|
|||||||
el = $.el 'a',
|
el = $.el 'a',
|
||||||
href: 'javascript:;'
|
href: 'javascript:;'
|
||||||
textContent: text
|
textContent: text
|
||||||
el.setAttribute 'data-type', type
|
el.dataset.type = type
|
||||||
$.on el, 'click', Filter.menu.makeFilter
|
$.on el, 'click', Filter.menu.makeFilter
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
25
src/Filtering/PostHiding.coffee
Normal file → Executable file
@ -17,7 +17,7 @@ PostHiding =
|
|||||||
PostHiding.hide @, data.makeStub, data.hideRecursively
|
PostHiding.hide @, data.makeStub, data.hideRecursively
|
||||||
else
|
else
|
||||||
Recursive.apply PostHiding.hide, @, data.makeStub, true
|
Recursive.apply PostHiding.hide, @, data.makeStub, true
|
||||||
Recursive.add PostHiding.hide, @, data.makeStub, true
|
Recursive.add PostHiding.hide, @, data.makeStub, true
|
||||||
return unless Conf['Reply Hiding Buttons']
|
return unless Conf['Reply Hiding Buttons']
|
||||||
$.replace $('.sideArrows', @nodes.root), PostHiding.makeButton @, 'hide'
|
$.replace $('.sideArrows', @nodes.root), PostHiding.makeButton @, 'hide'
|
||||||
|
|
||||||
@ -108,11 +108,12 @@ PostHiding =
|
|||||||
PostHiding.hide post, makeStub, replies
|
PostHiding.hide post, makeStub, replies
|
||||||
else if replies
|
else if replies
|
||||||
Recursive.apply PostHiding.hide, post, makeStub, true
|
Recursive.apply PostHiding.hide, post, makeStub, true
|
||||||
Recursive.add PostHiding.hide, post, makeStub, true
|
Recursive.add PostHiding.hide, post, makeStub, true
|
||||||
else
|
else
|
||||||
return
|
return
|
||||||
PostHiding.saveHiddenState post, true, thisPost, makeStub, replies
|
PostHiding.saveHiddenState post, true, thisPost, makeStub, replies
|
||||||
$.event 'CloseMenu'
|
$.event 'CloseMenu'
|
||||||
|
|
||||||
show: ->
|
show: ->
|
||||||
parent = @parentNode
|
parent = @parentNode
|
||||||
thisPost = $('input[name=thisPost]', parent).checked
|
thisPost = $('input[name=thisPost]', parent).checked
|
||||||
@ -122,7 +123,7 @@ PostHiding =
|
|||||||
PostHiding.show post, replies
|
PostHiding.show post, replies
|
||||||
else if replies
|
else if replies
|
||||||
Recursive.apply PostHiding.show, post, true
|
Recursive.apply PostHiding.show, post, true
|
||||||
Recursive.rm PostHiding.hide, post, true
|
Recursive.rm PostHiding.hide, post, true
|
||||||
else
|
else
|
||||||
return
|
return
|
||||||
if data = PostHiding.db.get {boardID: post.board.ID, threadID: post.thread.ID, postID: post.ID}
|
if data = PostHiding.db.get {boardID: post.board.ID, threadID: post.thread.ID, postID: post.ID}
|
||||||
@ -158,10 +159,7 @@ PostHiding =
|
|||||||
|
|
||||||
toggle: ->
|
toggle: ->
|
||||||
post = Get.postFromNode @
|
post = Get.postFromNode @
|
||||||
if post.isHidden
|
PostHiding[(if post.isHidden then 'show' else 'hide')] post
|
||||||
PostHiding.show post
|
|
||||||
else
|
|
||||||
PostHiding.hide post
|
|
||||||
PostHiding.saveHiddenState post, post.isHidden
|
PostHiding.saveHiddenState post, post.isHidden
|
||||||
|
|
||||||
hide: (post, makeStub=Conf['Stubs'], hideRecursively=Conf['Recursive Hiding']) ->
|
hide: (post, makeStub=Conf['Stubs'], hideRecursively=Conf['Recursive Hiding']) ->
|
||||||
@ -170,7 +168,7 @@ PostHiding =
|
|||||||
|
|
||||||
if hideRecursively
|
if hideRecursively
|
||||||
Recursive.apply PostHiding.hide, post, makeStub, true
|
Recursive.apply PostHiding.hide, post, makeStub, true
|
||||||
Recursive.add PostHiding.hide, post, makeStub, true
|
Recursive.add PostHiding.hide, post, makeStub, true
|
||||||
|
|
||||||
for quotelink in Get.allQuotelinksLinkingTo post
|
for quotelink in Get.allQuotelinksLinkingTo post
|
||||||
$.addClass quotelink, 'filtered'
|
$.addClass quotelink, 'filtered'
|
||||||
@ -184,13 +182,14 @@ PostHiding =
|
|||||||
if Conf['Anonymize']
|
if Conf['Anonymize']
|
||||||
'Anonymous'
|
'Anonymous'
|
||||||
else
|
else
|
||||||
$('.nameBlock', post.nodes.info).textContent
|
post.info.name
|
||||||
$.add a, $.tn " #{postInfo}"
|
$.add a, $.tn " #{postInfo}"
|
||||||
post.nodes.stub = $.el 'div',
|
post.nodes.stub = $.el 'div',
|
||||||
className: 'stub'
|
className: 'stub'
|
||||||
$.add post.nodes.stub, a
|
$.add post.nodes.stub, unless Conf['Menu']
|
||||||
if Conf['Menu']
|
a
|
||||||
$.add post.nodes.stub, [$.tn(' '), Menu.makeButton post]
|
else
|
||||||
|
[a, $.tn(' '), button = Menu.makeButton post]
|
||||||
$.prepend post.nodes.root, post.nodes.stub
|
$.prepend post.nodes.root, post.nodes.stub
|
||||||
|
|
||||||
show: (post, showRecursively=Conf['Recursive Hiding']) ->
|
show: (post, showRecursively=Conf['Recursive Hiding']) ->
|
||||||
@ -202,7 +201,7 @@ PostHiding =
|
|||||||
post.isHidden = false
|
post.isHidden = false
|
||||||
if showRecursively
|
if showRecursively
|
||||||
Recursive.apply PostHiding.show, post, true
|
Recursive.apply PostHiding.show, post, true
|
||||||
Recursive.rm PostHiding.hide, post
|
Recursive.rm PostHiding.hide, post
|
||||||
for quotelink in Get.allQuotelinksLinkingTo post
|
for quotelink in Get.allQuotelinksLinkingTo post
|
||||||
$.rmClass quotelink, 'filtered'
|
$.rmClass quotelink, 'filtered'
|
||||||
return
|
return
|
||||||
0
src/Filtering/Recursive.coffee
Normal file → Executable file
59
src/Filtering/ThreadHiding.coffee
Normal file → Executable file
@ -71,11 +71,6 @@ ThreadHiding =
|
|||||||
makeStub = $.el 'label',
|
makeStub = $.el 'label',
|
||||||
innerHTML: "<input type=checkbox #{if Conf['Stubs'] then 'checked' else ''}> Make stub"
|
innerHTML: "<input type=checkbox #{if Conf['Stubs'] then 'checked' else ''}> Make stub"
|
||||||
|
|
||||||
hideStubLink = $.el 'a',
|
|
||||||
textContent: 'Hide stub'
|
|
||||||
href: 'javascript:;'
|
|
||||||
$.on hideStubLink, 'click', ThreadHiding.menu.hideStub
|
|
||||||
|
|
||||||
$.event 'AddMenuEntry',
|
$.event 'AddMenuEntry',
|
||||||
type: 'post'
|
type: 'post'
|
||||||
el: div
|
el: div
|
||||||
@ -87,6 +82,27 @@ ThreadHiding =
|
|||||||
true
|
true
|
||||||
subEntries: [el: apply; el: makeStub]
|
subEntries: [el: apply; el: makeStub]
|
||||||
|
|
||||||
|
div = $.el 'a',
|
||||||
|
className: 'show-thread-link'
|
||||||
|
textContent: 'Show thread'
|
||||||
|
href: 'javascript:;'
|
||||||
|
$.on div, 'click', ThreadHiding.menu.show
|
||||||
|
|
||||||
|
$.event 'AddMenuEntry',
|
||||||
|
type: 'post'
|
||||||
|
el: div
|
||||||
|
order: 20
|
||||||
|
open: ({thread, isReply}) ->
|
||||||
|
if isReply or !thread.isHidden
|
||||||
|
return false
|
||||||
|
ThreadHiding.menu.thread = thread
|
||||||
|
true
|
||||||
|
|
||||||
|
hideStubLink = $.el 'a',
|
||||||
|
textContent: 'Hide stub'
|
||||||
|
href: 'javascript:;'
|
||||||
|
$.on hideStubLink, 'click', ThreadHiding.menu.hideStub
|
||||||
|
|
||||||
$.event 'AddMenuEntry',
|
$.event 'AddMenuEntry',
|
||||||
type: 'post'
|
type: 'post'
|
||||||
el: hideStubLink
|
el: hideStubLink
|
||||||
@ -102,6 +118,13 @@ ThreadHiding =
|
|||||||
ThreadHiding.hide thread, makeStub
|
ThreadHiding.hide thread, makeStub
|
||||||
ThreadHiding.saveHiddenState thread, makeStub
|
ThreadHiding.saveHiddenState thread, makeStub
|
||||||
$.event 'CloseMenu'
|
$.event 'CloseMenu'
|
||||||
|
|
||||||
|
show: ->
|
||||||
|
{thread} = ThreadHiding.menu
|
||||||
|
ThreadHiding.show thread
|
||||||
|
ThreadHiding.saveHiddenState thread
|
||||||
|
$.event 'CloseMenu'
|
||||||
|
|
||||||
hideStub: ->
|
hideStub: ->
|
||||||
{thread} = ThreadHiding.menu
|
{thread} = ThreadHiding.menu
|
||||||
ThreadHiding.hide thread, false
|
ThreadHiding.hide thread, false
|
||||||
@ -113,7 +136,7 @@ ThreadHiding =
|
|||||||
className: "#{type}-thread-button"
|
className: "#{type}-thread-button"
|
||||||
innerHTML: "<span class=fourchanx-link> #{if type is 'hide' then '-' else '+'} </span>"
|
innerHTML: "<span class=fourchanx-link> #{if type is 'hide' then '-' else '+'} </span>"
|
||||||
href: 'javascript:;'
|
href: 'javascript:;'
|
||||||
a.setAttribute 'data-fullid', thread.fullID
|
a.dataset.fullID = thread.fullID
|
||||||
$.on a, 'click', ThreadHiding.toggle
|
$.on a, 'click', ThreadHiding.toggle
|
||||||
a
|
a
|
||||||
|
|
||||||
@ -134,7 +157,7 @@ ThreadHiding =
|
|||||||
|
|
||||||
toggle: (thread) ->
|
toggle: (thread) ->
|
||||||
unless thread instanceof Thread
|
unless thread instanceof Thread
|
||||||
thread = g.threads[@dataset.fullid]
|
thread = g.threads[@dataset.fullID]
|
||||||
if thread.isHidden
|
if thread.isHidden
|
||||||
ThreadHiding.show thread
|
ThreadHiding.show thread
|
||||||
else
|
else
|
||||||
@ -150,24 +173,28 @@ ThreadHiding =
|
|||||||
threadRoot.hidden = threadRoot.nextElementSibling.hidden = true # <hr>
|
threadRoot.hidden = threadRoot.nextElementSibling.hidden = true # <hr>
|
||||||
return
|
return
|
||||||
|
|
||||||
numReplies = 0
|
numReplies = (
|
||||||
if span = $ '.summary', threadRoot
|
if span = $ '.summary', threadRoot
|
||||||
numReplies = +span.textContent.match /\d+/
|
+span.textContent.match /\d+/
|
||||||
numReplies += $$('.opContainer ~ .replyContainer', threadRoot).length
|
else
|
||||||
numReplies = if numReplies is 1 then '1 reply' else "#{numReplies} replies"
|
0
|
||||||
|
) +
|
||||||
|
$$('.opContainer ~ .replyContainer', threadRoot).length
|
||||||
|
numReplies = if numReplies is 1 then '1 reply' else "#{numReplies or 'No'} replies"
|
||||||
opInfo =
|
opInfo =
|
||||||
if Conf['Anonymize']
|
if Conf['Anonymize']
|
||||||
'Anonymous'
|
'Anonymous'
|
||||||
else
|
else
|
||||||
$('.nameBlock', OP.nodes.info).textContent
|
OP.info.name
|
||||||
|
|
||||||
a = ThreadHiding.makeButton thread, 'show'
|
a = ThreadHiding.makeButton thread, 'show'
|
||||||
$.add a, $.tn " #{opInfo} (#{numReplies})"
|
$.add a, $.tn " #{opInfo} (#{numReplies})"
|
||||||
thread.stub = $.el 'div',
|
thread.stub = $.el 'div',
|
||||||
className: 'stub'
|
className: 'stub'
|
||||||
$.add thread.stub, a
|
$.add thread.stub, unless Conf['Menu']
|
||||||
if Conf['Menu']
|
a
|
||||||
$.add thread.stub, [$.tn(' '), Menu.makeButton OP]
|
else
|
||||||
|
[a, $.tn(' '), button = Menu.makeButton OP]
|
||||||
$.prepend threadRoot, thread.stub
|
$.prepend threadRoot, thread.stub
|
||||||
|
|
||||||
show: (thread) ->
|
show: (thread) ->
|
||||||
|
|||||||
115
src/General/Build.coffee
Normal file → Executable file
@ -27,6 +27,7 @@ Build =
|
|||||||
date: data.now
|
date: data.now
|
||||||
dateUTC: data.time
|
dateUTC: data.time
|
||||||
comment: data.com
|
comment: data.com
|
||||||
|
capReps: data.capcode_replies
|
||||||
# thread status
|
# thread status
|
||||||
isSticky: !!data.sticky
|
isSticky: !!data.sticky
|
||||||
isClosed: !!data.closed
|
isClosed: !!data.closed
|
||||||
@ -58,7 +59,7 @@ Build =
|
|||||||
postID, threadID, boardID
|
postID, threadID, boardID
|
||||||
name, capcode, tripcode, uniqueID, email, subject, flagCode, flagName, date, dateUTC
|
name, capcode, tripcode, uniqueID, email, subject, flagCode, flagName, date, dateUTC
|
||||||
isSticky, isClosed
|
isSticky, isClosed
|
||||||
comment
|
comment, capReps
|
||||||
file
|
file
|
||||||
} = o
|
} = o
|
||||||
isOP = postID is threadID
|
isOP = postID is threadID
|
||||||
@ -108,12 +109,12 @@ Build =
|
|||||||
capcodeStart = ''
|
capcodeStart = ''
|
||||||
capcode = ''
|
capcode = ''
|
||||||
|
|
||||||
flag =
|
flag = unless flagCode
|
||||||
if flagCode
|
''
|
||||||
" <img src='#{staticPath}country/#{if boardID is 'pol' then 'troll/' else ''}" +
|
else if boardID is 'pol'
|
||||||
flagCode.toLowerCase() + ".gif' alt=#{flagCode} title='#{flagName}' class=countryFlag>"
|
" <img src='#{staticPath}country/troll/#{flagCode.toLowerCase()}.gif' alt=#{flagCode} title='#{flagName}' class=countryFlag>"
|
||||||
else
|
else
|
||||||
''
|
" <span title='#{flagName}' class='flag flag-#{flagCode.toLowerCase()}'></span>"
|
||||||
|
|
||||||
if file?.isDeleted
|
if file?.isDeleted
|
||||||
fileHTML = if isOP
|
fileHTML = if isOP
|
||||||
@ -176,78 +177,44 @@ Build =
|
|||||||
else
|
else
|
||||||
fileHTML = ''
|
fileHTML = ''
|
||||||
|
|
||||||
tripcode =
|
tripcode = if tripcode
|
||||||
if tripcode
|
" <span class=postertrip>#{tripcode}</span>"
|
||||||
" <span class=postertrip>#{tripcode}</span>"
|
else
|
||||||
else
|
''
|
||||||
''
|
|
||||||
|
|
||||||
sticky =
|
sticky = if isSticky
|
||||||
if isSticky
|
" <img src=#{staticPath}sticky.gif alt=Sticky title=Sticky class=stickyIcon>"
|
||||||
" <img src=#{staticPath}sticky.gif alt=Sticky title=Sticky class=stickyIcon>"
|
else
|
||||||
else
|
''
|
||||||
''
|
closed = if isClosed
|
||||||
closed =
|
" <img src=#{staticPath}closed.gif alt=Closed title=Closed class=closedIcon>"
|
||||||
if isClosed
|
else
|
||||||
" <img src=#{staticPath}closed.gif alt=Closed title=Closed class=closedIcon>"
|
''
|
||||||
else
|
|
||||||
''
|
capcodeReplies = ''
|
||||||
|
if capReps
|
||||||
|
generateCapcodeReplies = (capcodeType, array) ->
|
||||||
|
"<span class=smaller><span class=bold>#{
|
||||||
|
switch capcodeType
|
||||||
|
when 'admin'
|
||||||
|
'Administrator'
|
||||||
|
when 'mod'
|
||||||
|
'Moderator'
|
||||||
|
when 'developer'
|
||||||
|
'Developer'
|
||||||
|
} Repl#{if array.length > 1 then 'ies' else 'y'}:</span> #{
|
||||||
|
array.map (ID) ->
|
||||||
|
"<a href='/#{boardID}/res/#{threadID}#p#{ID}' class=quotelink>>>#{ID}</a>"
|
||||||
|
.join ' '
|
||||||
|
}</span><br>"
|
||||||
|
for capcodeType, array of capReps
|
||||||
|
capcodeReplies += generateCapcodeReplies capcodeType, array
|
||||||
|
capcodeReplies = "<br><br><span class=capcodeReplies>#{capcodeReplies}</span>"
|
||||||
|
|
||||||
container = $.el 'div',
|
container = $.el 'div',
|
||||||
id: "pc#{postID}"
|
id: "pc#{postID}"
|
||||||
className: "postContainer #{if isOP then 'op' else 'reply'}Container"
|
className: "postContainer #{if isOP then 'op' else 'reply'}Container"
|
||||||
innerHTML: \
|
innerHTML: <%= grunt.file.read('src/General/html/Build/post.html').replace(/>\s+/g, '>').replace(/\s+</g, '<').replace(/\s+/g, ' ').trim() %>
|
||||||
(if isOP then '' else "<div class=sideArrows id=sa#{postID}>>></div>") +
|
|
||||||
"<div id=p#{postID} class='post #{if isOP then 'op' else 'reply'}#{
|
|
||||||
if capcode is 'admin_highlight'
|
|
||||||
' highlightPost'
|
|
||||||
else
|
|
||||||
''
|
|
||||||
}'>" +
|
|
||||||
|
|
||||||
"<div class='postInfoM mobile' id=pim#{postID}>" +
|
|
||||||
"<span class='nameBlock#{capcodeClass}'>" +
|
|
||||||
"<span class=name>#{name or ''}</span>" + tripcode +
|
|
||||||
capcodeStart + capcode + userID + flag + sticky + closed +
|
|
||||||
"<br>#{subject}" +
|
|
||||||
"</span><span class='dateTime postNum' data-utc=#{dateUTC}>#{date}" +
|
|
||||||
"<a href=#{"/#{boardID}/res/#{threadID}#p#{postID}"}>No.</a>" +
|
|
||||||
"<a href='#{
|
|
||||||
if g.VIEW is 'thread' and g.THREADID is +threadID
|
|
||||||
"javascript:quote(#{postID})"
|
|
||||||
else
|
|
||||||
"/#{boardID}/res/#{threadID}#q#{postID}"
|
|
||||||
}'>#{postID}</a>" +
|
|
||||||
'</span>' +
|
|
||||||
'</div>' +
|
|
||||||
|
|
||||||
(if isOP then fileHTML else '') +
|
|
||||||
|
|
||||||
"<div class='postInfo desktop' id=pi#{postID}>" +
|
|
||||||
"<input type=checkbox name=#{postID} value=delete> " +
|
|
||||||
"#{subject} " +
|
|
||||||
"<span class='nameBlock#{capcodeClass}'>" +
|
|
||||||
emailStart +
|
|
||||||
"<span class=name>#{name or ''}</span>" + tripcode +
|
|
||||||
capcodeStart + emailEnd + capcode + userID + flag + sticky + closed +
|
|
||||||
' </span> ' +
|
|
||||||
"<span class=dateTime data-utc=#{dateUTC}>#{date}</span> " +
|
|
||||||
"<span class='postNum desktop'>" +
|
|
||||||
"<a href=#{"/#{boardID}/res/#{threadID}#p#{postID}"} title='Highlight this post'>No.</a>" +
|
|
||||||
"<a href='#{
|
|
||||||
if g.VIEW is 'thread' and g.THREADID is +threadID
|
|
||||||
"javascript:quote(#{postID})"
|
|
||||||
else
|
|
||||||
"/#{boardID}/res/#{threadID}#q#{postID}"
|
|
||||||
}' title='Quote this post'>#{postID}</a>" +
|
|
||||||
'</span>' +
|
|
||||||
'</div>' +
|
|
||||||
|
|
||||||
(if isOP then '' else fileHTML) +
|
|
||||||
|
|
||||||
"<blockquote class=postMessage id=m#{postID}>#{comment or ''}</blockquote> " +
|
|
||||||
|
|
||||||
'</div>'
|
|
||||||
|
|
||||||
for quote in $$ '.quotelink', container
|
for quote in $$ '.quotelink', container
|
||||||
href = quote.getAttribute 'href'
|
href = quote.getAttribute 'href'
|
||||||
|
|||||||
12
src/General/Config.coffee
Normal file → Executable file
@ -53,6 +53,10 @@ Config =
|
|||||||
false
|
false
|
||||||
'Add buttons to navigate to top / bottom of thread.'
|
'Add buttons to navigate to top / bottom of thread.'
|
||||||
]
|
]
|
||||||
|
'Show Dice Roll': [
|
||||||
|
true
|
||||||
|
'Show dice that were entered into the email field.'
|
||||||
|
]
|
||||||
<% if (type !== 'crx') { %>
|
<% if (type !== 'crx') { %>
|
||||||
'Check for Updates': [
|
'Check for Updates': [
|
||||||
true
|
true
|
||||||
@ -641,6 +645,14 @@ q-replace
|
|||||||
'x'
|
'x'
|
||||||
'Hide thread.'
|
'Hide thread.'
|
||||||
]
|
]
|
||||||
|
'Previous Post Quoting You': [
|
||||||
|
'Alt+Up'
|
||||||
|
'Scroll to the previous post that quotes you.'
|
||||||
|
]
|
||||||
|
'Next Post Quoting You': [
|
||||||
|
'Alt+Down'
|
||||||
|
'Scroll to the next post that quotes you.'
|
||||||
|
]
|
||||||
|
|
||||||
updater:
|
updater:
|
||||||
checkbox:
|
checkbox:
|
||||||
|
|||||||
78
src/General/Get.coffee
Normal file → Executable file
@ -18,8 +18,8 @@ Get =
|
|||||||
post = g.posts["#{boardID}.#{postID}"]
|
post = g.posts["#{boardID}.#{postID}"]
|
||||||
if index then post.clones[index] else post
|
if index then post.clones[index] else post
|
||||||
postFromNode: (root) ->
|
postFromNode: (root) ->
|
||||||
Get.postFromRoot $.x 'ancestor::div[contains(@class,"postContainer")][1]', root
|
Get.postFromRoot $.x '(ancestor::div[contains(@class,"postContainer")][1]|following::div[contains(@class,"postContainer")][1])', root
|
||||||
contextFromLink: (quotelink) ->
|
contextFromNode: (quotelink) ->
|
||||||
Get.postFromRoot $.x 'ancestor::div[parent::div[@class="thread"]][1]', quotelink
|
Get.postFromRoot $.x 'ancestor::div[parent::div[@class="thread"]][1]', quotelink
|
||||||
postDataFromLink: (link) ->
|
postDataFromLink: (link) ->
|
||||||
if link.hostname is 'boards.4chan.org'
|
if link.hostname is 'boards.4chan.org'
|
||||||
@ -28,9 +28,8 @@ Get =
|
|||||||
threadID = path[3]
|
threadID = path[3]
|
||||||
postID = link.hash[2..]
|
postID = link.hash[2..]
|
||||||
else # resurrected quote
|
else # resurrected quote
|
||||||
boardID = link.dataset.boardid
|
{boardID, threadID, postID} = link.dataset
|
||||||
threadID = link.dataset.threadid or 0
|
threadID or= 0
|
||||||
postID = link.dataset.postid
|
|
||||||
return {
|
return {
|
||||||
boardID: boardID
|
boardID: boardID
|
||||||
threadID: +threadID
|
threadID: +threadID
|
||||||
@ -72,8 +71,10 @@ Get =
|
|||||||
$.cache "//api.4chan.org/#{boardID}/res/#{threadID}.json", ->
|
$.cache "//api.4chan.org/#{boardID}/res/#{threadID}.json", ->
|
||||||
Get.fetchedPost @, boardID, threadID, postID, root, context
|
Get.fetchedPost @, boardID, threadID, postID, root, context
|
||||||
else if url = Redirect.to 'post', {boardID, postID}
|
else if url = Redirect.to 'post', {boardID, postID}
|
||||||
$.cache url, ->
|
$.cache url,
|
||||||
Get.archivedPost @, boardID, postID, root, context
|
-> Get.archivedPost @, boardID, postID, root, context
|
||||||
|
,
|
||||||
|
withCredentials: url.archive.withCredentials
|
||||||
insert: (post, root, context) ->
|
insert: (post, root, context) ->
|
||||||
# Stop here if the container has been removed while loading.
|
# Stop here if the container has been removed while loading.
|
||||||
return unless root.parentNode
|
return unless root.parentNode
|
||||||
@ -98,8 +99,10 @@ Get =
|
|||||||
unless [200, 304].contains status
|
unless [200, 304].contains status
|
||||||
# The thread can die by the time we check a quote.
|
# The thread can die by the time we check a quote.
|
||||||
if url = Redirect.to 'post', {boardID, postID}
|
if url = Redirect.to 'post', {boardID, postID}
|
||||||
$.cache url, ->
|
$.cache url,
|
||||||
Get.archivedPost @, boardID, postID, root, context
|
-> Get.archivedPost @, boardID, postID, root, context
|
||||||
|
,
|
||||||
|
withCredentials: url.archive.withCredentials
|
||||||
else
|
else
|
||||||
$.addClass root, 'warning'
|
$.addClass root, 'warning'
|
||||||
root.textContent =
|
root.textContent =
|
||||||
@ -116,8 +119,10 @@ Get =
|
|||||||
if post.no > postID
|
if post.no > postID
|
||||||
# The post can be deleted by the time we check a quote.
|
# The post can be deleted by the time we check a quote.
|
||||||
if url = Redirect.to 'post', {boardID, postID}
|
if url = Redirect.to 'post', {boardID, postID}
|
||||||
$.cache url, ->
|
$.cache url,
|
||||||
Get.archivedPost @, boardID, postID, root, context
|
-> Get.archivedPost @, boardID, postID, root, context
|
||||||
|
,
|
||||||
|
withCredentials: url.archive.withCredentials
|
||||||
else
|
else
|
||||||
$.addClass root, 'warning'
|
$.addClass root, 'warning'
|
||||||
root.textContent = "Post No.#{postID} was not found."
|
root.textContent = "Post No.#{postID} was not found."
|
||||||
@ -154,30 +159,7 @@ Get =
|
|||||||
| \[/?code\]
|
| \[/?code\]
|
||||||
| \[/?moot\]
|
| \[/?moot\]
|
||||||
| \[/?banned\]
|
| \[/?banned\]
|
||||||
///g, (text) ->
|
///g, Get.parseMarkup
|
||||||
switch text
|
|
||||||
when '\n'
|
|
||||||
'<br>'
|
|
||||||
when '[b]'
|
|
||||||
'<b>'
|
|
||||||
when '[/b]'
|
|
||||||
'</b>'
|
|
||||||
when '[spoiler]'
|
|
||||||
'<s>'
|
|
||||||
when '[/spoiler]'
|
|
||||||
'</s>'
|
|
||||||
when '[code]'
|
|
||||||
'<pre class=prettyprint>'
|
|
||||||
when '[/code]'
|
|
||||||
'</pre>'
|
|
||||||
when '[moot]'
|
|
||||||
'<div style="padding:5px;margin-left:.5em;border-color:#faa;border:2px dashed rgba(255,0,0,.1);border-radius:2px">'
|
|
||||||
when '[/moot]'
|
|
||||||
'</div>'
|
|
||||||
when '[banned]'
|
|
||||||
'<b style="color: red;">'
|
|
||||||
when '[/banned]'
|
|
||||||
'</b>'
|
|
||||||
|
|
||||||
comment = bq.innerHTML
|
comment = bq.innerHTML
|
||||||
# greentext
|
# greentext
|
||||||
@ -185,7 +167,7 @@ Get =
|
|||||||
# quotes
|
# quotes
|
||||||
.replace /((>){2}(>\/[a-z\d]+\/)?\d+)/g, '<span class=deadlink>$1</span>'
|
.replace /((>){2}(>\/[a-z\d]+\/)?\d+)/g, '<span class=deadlink>$1</span>'
|
||||||
|
|
||||||
threadID = data.thread_num
|
threadID = +data.thread_num
|
||||||
o =
|
o =
|
||||||
# id
|
# id
|
||||||
postID: "#{postID}"
|
postID: "#{postID}"
|
||||||
@ -229,3 +211,27 @@ Get =
|
|||||||
isArchived: true
|
isArchived: true
|
||||||
Main.callbackNodes Post, [post]
|
Main.callbackNodes Post, [post]
|
||||||
Get.insert post, root, context
|
Get.insert post, root, context
|
||||||
|
parseMarkup: (text) ->
|
||||||
|
switch text
|
||||||
|
when '\n'
|
||||||
|
'<br>'
|
||||||
|
when '[b]'
|
||||||
|
'<b>'
|
||||||
|
when '[/b]'
|
||||||
|
'</b>'
|
||||||
|
when '[spoiler]'
|
||||||
|
'<s>'
|
||||||
|
when '[/spoiler]'
|
||||||
|
'</s>'
|
||||||
|
when '[code]'
|
||||||
|
'<pre class=prettyprint>'
|
||||||
|
when '[/code]'
|
||||||
|
'</pre>'
|
||||||
|
when '[moot]'
|
||||||
|
'<div style="padding:5px;margin-left:.5em;border-color:#faa;border:2px dashed rgba(255,0,0,.1);border-radius:2px">'
|
||||||
|
when '[/moot]'
|
||||||
|
'</div>'
|
||||||
|
when '[banned]'
|
||||||
|
'<b style="color: red;">'
|
||||||
|
when '[/banned]'
|
||||||
|
'</b>'
|
||||||
|
|||||||
6
src/General/Globals.coffee
Normal file → Executable file
@ -1,9 +1,3 @@
|
|||||||
<% if (type === 'userjs') { %>
|
|
||||||
# Opera doesn't support the @match metadata key,
|
|
||||||
# return 4chan X here if we're not on 4chan.
|
|
||||||
return unless /^(boards|images|sys)\.4chan\.org$/.test location.hostname
|
|
||||||
<% } %>
|
|
||||||
|
|
||||||
Conf = {}
|
Conf = {}
|
||||||
c = console
|
c = console
|
||||||
d = document
|
d = document
|
||||||
|
|||||||
15
src/General/Header.coffee
Normal file → Executable file
@ -70,7 +70,7 @@ Header =
|
|||||||
return unless Main.isThisPageLegit()
|
return unless Main.isThisPageLegit()
|
||||||
# Wait for #boardNavMobile instead of #boardNavDesktop,
|
# Wait for #boardNavMobile instead of #boardNavDesktop,
|
||||||
# it might be incomplete otherwise.
|
# it might be incomplete otherwise.
|
||||||
$.asap (-> $.id('boardNavMobile') or d.readyState in ['interactive', 'complete']), Header.setBoardList
|
$.asap (-> $.id('boardNavMobile') or d.readyState isnt 'loading'), Header.setBoardList
|
||||||
$.prepend d.body, @bar
|
$.prepend d.body, @bar
|
||||||
$.add d.body, Header.hover
|
$.add d.body, Header.hover
|
||||||
@setBarPosition Conf['Bottom Header']
|
@setBarPosition Conf['Bottom Header']
|
||||||
@ -131,7 +131,7 @@ Header =
|
|||||||
list = $ '#custom-board-list', Header.bar
|
list = $ '#custom-board-list', Header.bar
|
||||||
$.rmAll list
|
$.rmAll list
|
||||||
return unless text
|
return unless text
|
||||||
as = $$('#full-board-list a', Header.bar)
|
as = $$ '#full-board-list a[title]', Header.bar
|
||||||
nodes = text.match(/[\w@]+((-(all|title|replace|full|index|catalog|url:"[^"]+[^"]"|text:"[^"]+")|\,"[^"]+[^"]"))*|[^\w@]+/g).map (t) ->
|
nodes = text.match(/[\w@]+((-(all|title|replace|full|index|catalog|url:"[^"]+[^"]"|text:"[^"]+")|\,"[^"]+[^"]"))*|[^\w@]+/g).map (t) ->
|
||||||
if /^[^\w@]/.test t
|
if /^[^\w@]/.test t
|
||||||
return $.tn t
|
return $.tn t
|
||||||
@ -166,10 +166,13 @@ Header =
|
|||||||
a.textContent
|
a.textContent
|
||||||
|
|
||||||
if m = t.match /-(index|catalog)/
|
if m = t.match /-(index|catalog)/
|
||||||
a.setAttribute 'data-only', m[1]
|
a.dataset.only = m[1]
|
||||||
a.href = "//boards.4chan.org/#{board}/"
|
a.href = "//boards.4chan.org/#{board}/"
|
||||||
if m[1] is 'catalog'
|
if m[1] is 'catalog'
|
||||||
a.href += 'catalog'
|
if Conf['External Catalog']
|
||||||
|
a.href = CatalogLinks.external board
|
||||||
|
else
|
||||||
|
a.href += 'catalog'
|
||||||
$.addClass a, 'catalog'
|
$.addClass a, 'catalog'
|
||||||
|
|
||||||
$.addClass a, 'navSmall' if board is '@'
|
$.addClass a, 'navSmall' if board is '@'
|
||||||
@ -302,8 +305,8 @@ Header =
|
|||||||
{top} = post.getBoundingClientRect()
|
{top} = post.getBoundingClientRect()
|
||||||
if Conf['Fixed Header'] and not Conf['Bottom Header']
|
if Conf['Fixed Header'] and not Conf['Bottom Header']
|
||||||
headRect = Header.bar.getBoundingClientRect()
|
headRect = Header.bar.getBoundingClientRect()
|
||||||
top += - headRect.top - headRect.height
|
top -= headRect.top + headRect.height
|
||||||
<% if (type === 'crx') { %>d.body<% } else { %>doc<% } %>.scrollTop += top
|
window.scrollBy 0, top
|
||||||
|
|
||||||
addShortcut: (el) ->
|
addShortcut: (el) ->
|
||||||
shortcut = $.el 'span',
|
shortcut = $.el 'span',
|
||||||
|
|||||||
143
src/General/Main.coffee
Normal file → Executable file
@ -15,11 +15,12 @@ Main =
|
|||||||
for db in DataBoards
|
for db in DataBoards
|
||||||
Conf[db] = boards: {}
|
Conf[db] = boards: {}
|
||||||
Conf['selectedArchives'] = {}
|
Conf['selectedArchives'] = {}
|
||||||
|
Conf['CachedTitles'] = []
|
||||||
|
|
||||||
$.get Conf, Main.initFeatures
|
$.get Conf, Main.initFeatures
|
||||||
|
|
||||||
$.on d, '4chanMainInit', Main.initStyle
|
$.on d, '4chanMainInit', Main.initStyle
|
||||||
$.asap (-> d.head and $('link[rel="shortcut icon"]', d.head) or d.readyState in ['interactive', 'complete']),
|
$.asap (-> d.head and $('link[rel="shortcut icon"]', d.head) or d.readyState isnt 'loading'),
|
||||||
Main.initStyle
|
Main.initStyle
|
||||||
|
|
||||||
initFeatures: (items) ->
|
initFeatures: (items) ->
|
||||||
@ -47,7 +48,7 @@ Main =
|
|||||||
return
|
return
|
||||||
when 'images.4chan.org'
|
when 'images.4chan.org'
|
||||||
$.ready ->
|
$.ready ->
|
||||||
if Conf['404 Redirect'] and d.title is '4chan - 404 Not Found'
|
if Conf['404 Redirect'] and ['4chan - Temporarily Offline', '4chan - 404 Not Found'].contains d.title
|
||||||
Redirect.init()
|
Redirect.init()
|
||||||
pathname = location.pathname.split '/'
|
pathname = location.pathname.split '/'
|
||||||
URL = Redirect.to 'file',
|
URL = Redirect.to 'file',
|
||||||
@ -72,61 +73,62 @@ Main =
|
|||||||
# c.time 'All initializations'
|
# c.time 'All initializations'
|
||||||
|
|
||||||
init
|
init
|
||||||
'Polyfill': Polyfill
|
'Polyfill': Polyfill
|
||||||
'Redirect': Redirect
|
'Redirect': Redirect
|
||||||
'Header': Header
|
'Header': Header
|
||||||
'Catalog Links': CatalogLinks
|
'Catalog Links': CatalogLinks
|
||||||
'Settings': Settings
|
'Settings': Settings
|
||||||
'Announcement Hiding': PSAHiding
|
'Announcement Hiding': PSAHiding
|
||||||
'Fourchan thingies': Fourchan
|
'Fourchan thingies': Fourchan
|
||||||
'Emoji': Emoji
|
'Emoji': Emoji
|
||||||
'Color User IDs': IDColor
|
'Color User IDs': IDColor
|
||||||
'Remove Spoilers': RemoveSpoilers
|
'Reveal Spoilers': RemoveSpoilers
|
||||||
'Custom CSS': CustomCSS
|
'Custom CSS': CustomCSS
|
||||||
'Linkify': Linkify
|
'Linkify': Linkify
|
||||||
'Resurrect Quotes': Quotify
|
'Resurrect Quotes': Quotify
|
||||||
'Filter': Filter
|
'Filter': Filter
|
||||||
'Thread Hiding Buttons': ThreadHiding
|
'Thread Hiding Buttons': ThreadHiding
|
||||||
'Reply Hiding Buttons': PostHiding
|
'Reply Hiding Buttons': PostHiding
|
||||||
'Recursive': Recursive
|
'Recursive': Recursive
|
||||||
'Strike-through Quotes': QuoteStrikeThrough
|
'Strike-through Quotes': QuoteStrikeThrough
|
||||||
'Quick Reply': QR
|
'Quick Reply': QR
|
||||||
'Menu': Menu
|
'Menu': Menu
|
||||||
'Report Link': ReportLink
|
'Report Link': ReportLink
|
||||||
'Thread Hiding (Menu)': ThreadHiding.menu
|
'Thread Hiding (Menu)': ThreadHiding.menu
|
||||||
'Reply Hiding (Menu)': PostHiding.menu
|
'Reply Hiding (Menu)': PostHiding.menu
|
||||||
'Delete Link': DeleteLink
|
'Delete Link': DeleteLink
|
||||||
'Filter (Menu)': Filter.menu
|
'Filter (Menu)': Filter.menu
|
||||||
'Download Link': DownloadLink
|
'Download Link': DownloadLink
|
||||||
'Archive Link': ArchiveLink
|
'Archive Link': ArchiveLink
|
||||||
'Quote Inlining': QuoteInline
|
'Quote Inlining': QuoteInline
|
||||||
'Quote Previewing': QuotePreview
|
'Quote Previewing': QuotePreview
|
||||||
'Quote Backlinks': QuoteBacklink
|
'Quote Backlinks': QuoteBacklink
|
||||||
'Mark Quotes of You': QuoteYou
|
'Mark Quotes of You': QuoteYou
|
||||||
'Mark OP Quotes': QuoteOP
|
'Mark OP Quotes': QuoteOP
|
||||||
'Mark Cross-thread Quotes': QuoteCT
|
'Mark Cross-thread Quotes': QuoteCT
|
||||||
'Anonymize': Anonymize
|
'Anonymize': Anonymize
|
||||||
'Time Formatting': Time
|
'Time Formatting': Time
|
||||||
'Relative Post Dates': RelativeDates
|
'Relative Post Dates': RelativeDates
|
||||||
'File Info Formatting': FileInfo
|
'File Info Formatting': FileInfo
|
||||||
'Fappe Tyme': FappeTyme
|
'Fappe Tyme': FappeTyme
|
||||||
'Sauce': Sauce
|
'Sauce': Sauce
|
||||||
'Image Expansion': ImageExpand
|
'Image Expansion': ImageExpand
|
||||||
'Image Expansion (Menu)': ImageExpand.menu
|
'Image Expansion (Menu)': ImageExpand.menu
|
||||||
'Reveal Spoilers': RevealSpoilers
|
'Reveal Spoiler Thumbnails': RevealSpoilers
|
||||||
'Image Loading': ImageLoader
|
'Image Loading': ImageLoader
|
||||||
'Image Hover': ImageHover
|
'Image Hover': ImageHover
|
||||||
'Comment Expansion': ExpandComment
|
'Comment Expansion': ExpandComment
|
||||||
'Thread Expansion': ExpandThread
|
'Thread Expansion': ExpandThread
|
||||||
'Thread Excerpt': ThreadExcerpt
|
'Thread Excerpt': ThreadExcerpt
|
||||||
'Favicon': Favicon
|
'Favicon': Favicon
|
||||||
'Unread': Unread
|
'Unread': Unread
|
||||||
'Quote Threading': QuoteThreading
|
'Quote Threading': QuoteThreading
|
||||||
'Thread Stats': ThreadStats
|
'Thread Stats': ThreadStats
|
||||||
'Thread Updater': ThreadUpdater
|
'Thread Updater': ThreadUpdater
|
||||||
'Thread Watcher': ThreadWatcher
|
'Thread Watcher': ThreadWatcher
|
||||||
'Index Navigation': Nav
|
'Index Navigation': Nav
|
||||||
'Keybinds': Keybinds
|
'Keybinds': Keybinds
|
||||||
|
'Show Dice Roll': Dice
|
||||||
|
|
||||||
# c.timeEnd 'All initializations'
|
# c.timeEnd 'All initializations'
|
||||||
|
|
||||||
@ -139,10 +141,7 @@ Main =
|
|||||||
# disable the mobile layout
|
# disable the mobile layout
|
||||||
$('link[href*=mobile]', d.head)?.disabled = true
|
$('link[href*=mobile]', d.head)?.disabled = true
|
||||||
<% if (type === 'crx') { %>
|
<% if (type === 'crx') { %>
|
||||||
$.addClass doc, 'webkit'
|
|
||||||
$.addClass doc, 'blink'
|
$.addClass doc, 'blink'
|
||||||
<% } else if (type === 'userjs') { %>
|
|
||||||
$.addClass doc, 'presto'
|
|
||||||
<% } else { %>
|
<% } else { %>
|
||||||
$.addClass doc, 'gecko'
|
$.addClass doc, 'gecko'
|
||||||
<% } %>
|
<% } %>
|
||||||
@ -166,13 +165,9 @@ Main =
|
|||||||
$.addClass doc, style
|
$.addClass doc, style
|
||||||
setStyle()
|
setStyle()
|
||||||
return unless mainStyleSheet
|
return unless mainStyleSheet
|
||||||
if window.MutationObserver
|
new MutationObserver(setStyle).observe mainStyleSheet,
|
||||||
observer = new MutationObserver setStyle
|
attributes: true
|
||||||
observer.observe mainStyleSheet,
|
attributeFilter: ['href']
|
||||||
attributes: true
|
|
||||||
attributeFilter: ['href']
|
|
||||||
else
|
|
||||||
$.on mainStyleSheet, 'DOMAttrModified', setStyle
|
|
||||||
|
|
||||||
initReady: ->
|
initReady: ->
|
||||||
if d.title is '4chan - 404 Not Found'
|
if d.title is '4chan - 404 Not Found'
|
||||||
@ -192,20 +187,18 @@ Main =
|
|||||||
threads = []
|
threads = []
|
||||||
posts = []
|
posts = []
|
||||||
|
|
||||||
for boardChild in board.children
|
for threadRoot in $$ '.board > .thread', board
|
||||||
continue unless $.hasClass boardChild, 'thread'
|
thread = new Thread +threadRoot.id[1..], g.BOARD
|
||||||
thread = new Thread boardChild.id[1..], g.BOARD
|
|
||||||
threads.push thread
|
threads.push thread
|
||||||
for threadChild in boardChild.children
|
for postRoot in $$ '.thread > .postContainer', threadRoot
|
||||||
continue unless $.hasClass threadChild, 'postContainer'
|
|
||||||
try
|
try
|
||||||
posts.push new Post threadChild, thread, g.BOARD
|
posts.push new Post postRoot, thread, g.BOARD
|
||||||
catch err
|
catch err
|
||||||
# Skip posts that we failed to parse.
|
# Skip posts that we failed to parse.
|
||||||
unless errors
|
unless errors
|
||||||
errors = []
|
errors = []
|
||||||
errors.push
|
errors.push
|
||||||
message: "Parsing of Post No.#{threadChild.id.match(/\d+/)} failed. Post will be skipped."
|
message: "Parsing of Post No.#{postRoot.id.match(/\d+/)} failed. Post will be skipped."
|
||||||
error: err
|
error: err
|
||||||
Main.handleErrors errors if errors
|
Main.handleErrors errors if errors
|
||||||
|
|
||||||
@ -373,7 +366,7 @@ Main =
|
|||||||
unless 'thisPageIsLegit' of Main
|
unless 'thisPageIsLegit' of Main
|
||||||
Main.thisPageIsLegit = location.hostname is 'boards.4chan.org' and
|
Main.thisPageIsLegit = location.hostname is 'boards.4chan.org' and
|
||||||
!$('link[href*="favicon-status.ico"]', d.head) and
|
!$('link[href*="favicon-status.ico"]', d.head) and
|
||||||
d.title not in ['4chan - Temporarily Offline', '4chan - Error']
|
d.title not in ['4chan - Temporarily Offline', '4chan - Error', '504 Gateway Time-out']
|
||||||
Main.thisPageIsLegit
|
Main.thisPageIsLegit
|
||||||
|
|
||||||
css: """
|
css: """
|
||||||
|
|||||||
4
src/General/Settings.coffee
Normal file → Executable file
@ -262,8 +262,7 @@ Settings =
|
|||||||
'%board'
|
'%board'
|
||||||
else
|
else
|
||||||
c
|
c
|
||||||
for key, val of Config.hotkeys
|
for key, val of Config.hotkeys when key of data.Conf
|
||||||
continue unless key of data.Conf
|
|
||||||
data.Conf[key] = data.Conf[key].replace(/ctrl|alt|meta/g, (s) -> "#{s[0].toUpperCase()}#{s[1..]}").replace /(^|.+\+)[A-Z]$/g, (s) ->
|
data.Conf[key] = data.Conf[key].replace(/ctrl|alt|meta/g, (s) -> "#{s[0].toUpperCase()}#{s[1..]}").replace /(^|.+\+)[A-Z]$/g, (s) ->
|
||||||
"Shift+#{s[0...-1]}#{s[-1..].toLowerCase()}"
|
"Shift+#{s[0...-1]}#{s[-1..].toLowerCase()}"
|
||||||
data.Conf.WatchedThreads = data.WatchedThreads
|
data.Conf.WatchedThreads = data.WatchedThreads
|
||||||
@ -467,7 +466,6 @@ Settings =
|
|||||||
$.cb.checked.call @
|
$.cb.checked.call @
|
||||||
usercss: ->
|
usercss: ->
|
||||||
CustomCSS.update()
|
CustomCSS.update()
|
||||||
|
|
||||||
keybinds: (section) ->
|
keybinds: (section) ->
|
||||||
section.innerHTML = """
|
section.innerHTML = """
|
||||||
<%= grunt.file.read('src/General/html/Settings/Keybinds.html').replace(/>\s+</g, '><').trim() %>
|
<%= grunt.file.read('src/General/html/Settings/Keybinds.html').replace(/>\s+</g, '><').trim() %>
|
||||||
|
|||||||
25
src/General/UI.coffee
Normal file → Executable file
@ -70,8 +70,8 @@ UI = do ->
|
|||||||
# Position
|
# Position
|
||||||
mRect = menu.getBoundingClientRect()
|
mRect = menu.getBoundingClientRect()
|
||||||
bRect = button.getBoundingClientRect()
|
bRect = button.getBoundingClientRect()
|
||||||
bTop = doc.scrollTop + d.body.scrollTop + bRect.top
|
bTop = window.scrollY + bRect.top
|
||||||
bLeft = doc.scrollLeft + d.body.scrollLeft + bRect.left
|
bLeft = window.scrollX + bRect.left
|
||||||
cHeight = doc.clientHeight
|
cHeight = doc.clientHeight
|
||||||
cWidth = doc.clientWidth
|
cWidth = doc.clientWidth
|
||||||
[top, bottom] = if bRect.top + bRect.height + mRect.height < cHeight
|
[top, bottom] = if bRect.top + bRect.height + mRect.height < cHeight
|
||||||
@ -306,12 +306,12 @@ UI = do ->
|
|||||||
|
|
||||||
hoverstart = ({root, el, latestEvent, endEvents, asapTest, cb}) ->
|
hoverstart = ({root, el, latestEvent, endEvents, asapTest, cb}) ->
|
||||||
o = {
|
o = {
|
||||||
root: root
|
root
|
||||||
el: el
|
el
|
||||||
style: el.style
|
style: el.style
|
||||||
cb: cb
|
cb
|
||||||
endEvents: endEvents
|
endEvents
|
||||||
latestEvent: latestEvent
|
latestEvent
|
||||||
clientHeight: doc.clientHeight
|
clientHeight: doc.clientHeight
|
||||||
clientWidth: doc.clientWidth
|
clientWidth: doc.clientWidth
|
||||||
}
|
}
|
||||||
@ -327,6 +327,11 @@ UI = do ->
|
|||||||
if $.x 'ancestor::div[contains(@class,"inline")][1]', root
|
if $.x 'ancestor::div[contains(@class,"inline")][1]', root
|
||||||
$.on d, 'keydown', o.hoverend
|
$.on d, 'keydown', o.hoverend
|
||||||
$.on root, 'mousemove', o.hover
|
$.on root, 'mousemove', o.hover
|
||||||
|
<% if (type === 'userscript') { %>
|
||||||
|
# Workaround for https://github.com/MayhemYDG/4chan-x/issues/377
|
||||||
|
o.workaround = (e) -> o.hoverend() unless root.contains e.target
|
||||||
|
$.on doc, 'mousemove', o.workaround
|
||||||
|
<% } %>
|
||||||
|
|
||||||
hover = (e) ->
|
hover = (e) ->
|
||||||
@latestEvent = e
|
@latestEvent = e
|
||||||
@ -357,6 +362,10 @@ UI = do ->
|
|||||||
$.off @root, @endEvents, @hoverend
|
$.off @root, @endEvents, @hoverend
|
||||||
$.off d, 'keydown', @hoverend
|
$.off d, 'keydown', @hoverend
|
||||||
$.off @root, 'mousemove', @hover
|
$.off @root, 'mousemove', @hover
|
||||||
|
<% if (type === 'userscript') { %>
|
||||||
|
# Workaround for https://github.com/MayhemYDG/4chan-x/issues/377
|
||||||
|
$.off doc, 'mousemove', @workaround
|
||||||
|
<% } %>
|
||||||
@cb.call @ if @cb
|
@cb.call @ if @cb
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
0
src/General/audio/beep.wav
Normal file → Executable file
0
src/General/css/burichan.css
Normal file → Executable file
0
src/General/css/futaba.css
Normal file → Executable file
0
src/General/css/photon.css
Normal file → Executable file
34
src/General/css/style.css
Normal file → Executable file
@ -304,10 +304,8 @@ a {
|
|||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
box-shadow: 0 0 15px rgba(0, 0, 0, .15);
|
box-shadow: 0 0 15px rgba(0, 0, 0, .15);
|
||||||
height: 600px;
|
height: 600px;
|
||||||
min-height: 0;
|
|
||||||
max-height: 100%;
|
max-height: 100%;
|
||||||
width: 900px;
|
width: 900px;
|
||||||
min-width: 0;
|
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
padding: 3px;
|
padding: 3px;
|
||||||
@ -315,7 +313,6 @@ a {
|
|||||||
left: 50%;
|
left: 50%;
|
||||||
-moz-transform: translate(-50%, -50%);
|
-moz-transform: translate(-50%, -50%);
|
||||||
-webkit-transform: translate(-50%, -50%);
|
-webkit-transform: translate(-50%, -50%);
|
||||||
-o-transform: translate(-50%, -50%);
|
|
||||||
transform: translate(-50%, -50%);
|
transform: translate(-50%, -50%);
|
||||||
}
|
}
|
||||||
#fourchanx-settings > nav {
|
#fourchanx-settings > nav {
|
||||||
@ -392,14 +389,17 @@ a {
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
}
|
}
|
||||||
.section-advanced .note {
|
.section-advanced .note {
|
||||||
font-size: 0.8em;
|
font-size: 0.8em;
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
}
|
}
|
||||||
.section-advanced .note code {
|
.section-advanced .note code {
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
}
|
}
|
||||||
|
.section-keybinds .field {
|
||||||
|
font-family: monospace;
|
||||||
|
}
|
||||||
#fourchanx-settings fieldset {
|
#fourchanx-settings fieldset {
|
||||||
border: 1px solid;
|
border: 1px solid;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
@ -533,7 +533,8 @@ a.hide-announcement {
|
|||||||
.deadlink {
|
.deadlink {
|
||||||
text-decoration: none !important;
|
text-decoration: none !important;
|
||||||
}
|
}
|
||||||
.backlink.deadlink:not(.forwardlink), .quotelink.deadlink:not(.forwardlink) {
|
.backlink.deadlink:not(.forwardlink),
|
||||||
|
.quotelink.deadlink:not(.forwardlink) {
|
||||||
text-decoration: underline !important;
|
text-decoration: underline !important;
|
||||||
}
|
}
|
||||||
.inlined {
|
.inlined {
|
||||||
@ -576,16 +577,14 @@ a.hide-announcement {
|
|||||||
padding: 2px 2px 5px;
|
padding: 2px 2px 5px;
|
||||||
}
|
}
|
||||||
#qp img {
|
#qp img {
|
||||||
max-height: 300px;
|
|
||||||
max-width: 500px;
|
|
||||||
max-height: 80vh;
|
max-height: 80vh;
|
||||||
max-width: 50vw;
|
max-width: 50vw;
|
||||||
}
|
}
|
||||||
.qphl {
|
.qphl {
|
||||||
outline: 2px solid rgba(216, 94, 49, .7);
|
outline: 2px solid rgba(216, 94, 49, .7);
|
||||||
}
|
}
|
||||||
:root.highlight-own .yourPost>.reply,
|
:root.highlight-own .yourPost > .reply,
|
||||||
:root.highlight-you .quotesYou>.reply {
|
:root.highlight-you .quotesYou > .reply {
|
||||||
border-left: 2px solid rgba(221,0,0,.5);
|
border-left: 2px solid rgba(221,0,0,.5);
|
||||||
}
|
}
|
||||||
/* Quote Threading */
|
/* Quote Threading */
|
||||||
@ -613,8 +612,7 @@ a.hide-announcement {
|
|||||||
:root.fit-width .full-image {
|
:root.fit-width .full-image {
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
:root.gecko.fit-width .full-image,
|
:root.gecko.fit-width .full-image {
|
||||||
:root.presto.fit-width .full-image {
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
#ihover {
|
#ihover {
|
||||||
@ -671,7 +669,10 @@ a.hide-announcement {
|
|||||||
#file-n-submit:not(.has-file) #qr-filerm {
|
#file-n-submit:not(.has-file) #qr-filerm {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
#qr select, #dump-button, .remove, .captcha-img {
|
#qr select,
|
||||||
|
#dump-button,
|
||||||
|
.remove,
|
||||||
|
.captcha-img {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
#qr {
|
#qr {
|
||||||
@ -728,7 +729,8 @@ a.hide-announcement {
|
|||||||
height: 9em;
|
height: 9em;
|
||||||
}
|
}
|
||||||
input.field.tripped:not(:hover):not(:focus) {
|
input.field.tripped:not(:hover):not(:focus) {
|
||||||
color: transparent !important; text-shadow: none !important;
|
color: transparent !important;
|
||||||
|
text-shadow: none !important;
|
||||||
}
|
}
|
||||||
#qr textarea {
|
#qr textarea {
|
||||||
resize: both;
|
resize: both;
|
||||||
@ -910,7 +912,9 @@ a:only-of-type > .remove {
|
|||||||
.qr-preview > label {
|
.qr-preview > label {
|
||||||
background: rgba(0,0,0,.5);
|
background: rgba(0,0,0,.5);
|
||||||
color: #fff;
|
color: #fff;
|
||||||
right: 0; bottom: 0; left: 0;
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|||||||
0
src/General/css/tomorrow.css
Normal file → Executable file
0
src/General/css/yotsuba-b.css
Normal file → Executable file
0
src/General/css/yotsuba.css
Normal file → Executable file
59
src/General/html/Build/post.html
Executable file
@ -0,0 +1,59 @@
|
|||||||
|
"""#{if isOP then '' else "<div class=sideArrows id=sa#{postID}>>></div>"}
|
||||||
|
<div id=p#{postID} class='post #{if isOP then 'op' else 'reply'}#{
|
||||||
|
if capcode is 'admin_highlight' then
|
||||||
|
' highlightPost'
|
||||||
|
else
|
||||||
|
''
|
||||||
|
}'>
|
||||||
|
|
||||||
|
<div class='postInfoM mobile' id=pim#{postID}>
|
||||||
|
<span class='nameBlock#{capcodeClass}'>
|
||||||
|
<span class=name>
|
||||||
|
#{name or ''}
|
||||||
|
</span>
|
||||||
|
#{tripcode + capcodeStart + capcode + userID + flag + sticky + closed}
|
||||||
|
<br>#{subject}
|
||||||
|
</span>
|
||||||
|
<span class='dateTime postNum' data-utc=#{dateUTC}>
|
||||||
|
#{date}
|
||||||
|
<a href=#{"/#{boardID}/res/#{threadID}#p#{postID}"}>
|
||||||
|
No.
|
||||||
|
</a>
|
||||||
|
<a href='#{
|
||||||
|
if g.VIEW is 'thread' and g.THREADID is +threadID then
|
||||||
|
"javascript:quote(#{postID})"
|
||||||
|
else
|
||||||
|
"/#{boardID}/res/#{threadID}#q#{postID}"
|
||||||
|
}'>
|
||||||
|
#{postID}
|
||||||
|
</a>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
#{if isOP then fileHTML else ''}
|
||||||
|
|
||||||
|
<div class='postInfo desktop' id=pi#{postID}>
|
||||||
|
<input type=checkbox name=#{postID} value=delete>
|
||||||
|
#{subject}
|
||||||
|
<span class='nameBlock#{capcodeClass}'>
|
||||||
|
#{emailStart}
|
||||||
|
<span class=name>#{name or ''}</span>
|
||||||
|
#{tripcode + capcodeStart + emailEnd + capcode + userID + flag + sticky + closed}
|
||||||
|
</span>#{" "}
|
||||||
|
<span class=dateTime data-utc=#{dateUTC}>#{date}</span>#{" "}
|
||||||
|
<span class='postNum desktop'>
|
||||||
|
<a href=#{"/#{boardID}/res/#{threadID}#p#{postID}"} title='Highlight this post'>No.</a>
|
||||||
|
<a href='#{
|
||||||
|
if g.VIEW is 'thread' and g.THREADID is +threadID then
|
||||||
|
"javascript:quote(#{postID})"
|
||||||
|
else
|
||||||
|
"/#{boardID}/res/#{threadID}#q#{postID}"
|
||||||
|
}' title='Quote this post'>#{postID}</a>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
#{if isOP then '' else fileHTML}
|
||||||
|
|
||||||
|
<blockquote class=postMessage id=m#{postID}>#{comment or ''}#{capcodeReplies}</blockquote>#{" "}
|
||||||
|
|
||||||
|
</div>"""
|
||||||
0
src/General/html/Features/QuickReply.html
Normal file → Executable file
0
src/General/html/Settings/Advanced.html
Normal file → Executable file
4
src/General/html/Settings/Filter-guide.html
Normal file → Executable file
@ -1,6 +1,6 @@
|
|||||||
<div class=warning #{if Conf['Filter'] then 'hidden' else ''}><code>Filter</code> is disabled.</div>
|
<div class=warning #{if Conf['Filter'] then 'hidden' else ''}><code>Filter</code> is disabled.</div>
|
||||||
<p>
|
<p>
|
||||||
Use <a href=https://developer.mozilla.org/en/JavaScript/Guide/Regular_Expressions>regular expressions</a>, one per line.<br>
|
Use <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions">regular expressions</a>, one per line.<br>
|
||||||
Lines starting with a <code>#</code> will be ignored.<br>
|
Lines starting with a <code>#</code> will be ignored.<br>
|
||||||
For example, <code>/weeaboo/i</code> will filter posts containing the string `<code>weeaboo</code>`, case-insensitive.<br>
|
For example, <code>/weeaboo/i</code> will filter posts containing the string `<code>weeaboo</code>`, case-insensitive.<br>
|
||||||
MD5 filtering uses exact string matching, not regular expressions.
|
MD5 filtering uses exact string matching, not regular expressions.
|
||||||
@ -26,4 +26,4 @@
|
|||||||
Highlighted OPs will have their threads put on top of board pages by default.<br>
|
Highlighted OPs will have their threads put on top of board pages by default.<br>
|
||||||
For example: <code>top:yes;</code> or <code>top:no;</code>.
|
For example: <code>top:yes;</code> or <code>top:no;</code>.
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
0
src/General/html/Settings/Filter-select.html
Normal file → Executable file
0
src/General/html/Settings/Keybinds.html
Normal file → Executable file
0
src/General/html/Settings/Sauce.html
Normal file → Executable file
0
src/General/html/Settings/Settings.html
Normal file → Executable file
0
src/General/img/changelog/1.1.18.png
Normal file → Executable file
|
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 44 KiB |
0
src/General/img/changelog/1.2.0.png
Normal file → Executable file
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
0
src/General/img/emoji/SS-sage.png
Normal file → Executable file
|
Before Width: | Height: | Size: 576 B After Width: | Height: | Size: 576 B |
0
src/General/img/emoji/appchan-sage.png
Normal file → Executable file
|
Before Width: | Height: | Size: 659 B After Width: | Height: | Size: 659 B |
0
src/General/img/emoji/arch.png
Normal file → Executable file
|
Before Width: | Height: | Size: 567 B After Width: | Height: | Size: 567 B |
0
src/General/img/emoji/baka.png
Normal file → Executable file
|
Before Width: | Height: | Size: 987 B After Width: | Height: | Size: 987 B |
0
src/General/img/emoji/centos.png
Normal file → Executable file
|
Before Width: | Height: | Size: 858 B After Width: | Height: | Size: 858 B |
0
src/General/img/emoji/crunchbang.png
Normal file → Executable file
|
Before Width: | Height: | Size: 297 B After Width: | Height: | Size: 297 B |
0
src/General/img/emoji/debian.png
Normal file → Executable file
|
Before Width: | Height: | Size: 559 B After Width: | Height: | Size: 559 B |
0
src/General/img/emoji/fedora.png
Normal file → Executable file
|
Before Width: | Height: | Size: 631 B After Width: | Height: | Size: 631 B |
0
src/General/img/emoji/freebsd.png
Normal file → Executable file
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
0
src/General/img/emoji/gentoo.png
Normal file → Executable file
|
Before Width: | Height: | Size: 882 B After Width: | Height: | Size: 882 B |
0
src/General/img/emoji/gnu.png
Normal file → Executable file
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
0
src/General/img/emoji/madotsuki.png
Normal file → Executable file
|
Before Width: | Height: | Size: 231 B After Width: | Height: | Size: 231 B |
0
src/General/img/emoji/mint.png
Normal file → Executable file
|
Before Width: | Height: | Size: 1006 B After Width: | Height: | Size: 1006 B |
0
src/General/img/emoji/neko.png
Normal file → Executable file
|
Before Width: | Height: | Size: 1012 B After Width: | Height: | Size: 1012 B |
0
src/General/img/emoji/openbsd.png
Normal file → Executable file
|
Before Width: | Height: | Size: 1002 B After Width: | Height: | Size: 1002 B |
0
src/General/img/emoji/osx.png
Normal file → Executable file
|
Before Width: | Height: | Size: 820 B After Width: | Height: | Size: 820 B |
0
src/General/img/emoji/plan9.png
Normal file → Executable file
|
Before Width: | Height: | Size: 668 B After Width: | Height: | Size: 668 B |
0
src/General/img/emoji/ponyo.png
Normal file → Executable file
|
Before Width: | Height: | Size: 884 B After Width: | Height: | Size: 884 B |
0
src/General/img/emoji/rabite.png
Normal file → Executable file
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
0
src/General/img/emoji/rhel.png
Normal file → Executable file
|
Before Width: | Height: | Size: 797 B After Width: | Height: | Size: 797 B |
0
src/General/img/emoji/sabayon.png
Normal file → Executable file
|
Before Width: | Height: | Size: 830 B After Width: | Height: | Size: 830 B |
0
src/General/img/emoji/sakamoto.png
Normal file → Executable file
|
Before Width: | Height: | Size: 934 B After Width: | Height: | Size: 934 B |
0
src/General/img/emoji/sega.png
Normal file → Executable file
|
Before Width: | Height: | Size: 339 B After Width: | Height: | Size: 339 B |
0
src/General/img/emoji/slackware.png
Normal file → Executable file
|
Before Width: | Height: | Size: 912 B After Width: | Height: | Size: 912 B |
0
src/General/img/emoji/trisquel.png
Normal file → Executable file
|
Before Width: | Height: | Size: 820 B After Width: | Height: | Size: 820 B |
0
src/General/img/emoji/ubuntu.png
Normal file → Executable file
|
Before Width: | Height: | Size: 625 B After Width: | Height: | Size: 625 B |
0
src/General/img/emoji/windows.png
Normal file → Executable file
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
0
src/General/img/emoji/yuno.png
Normal file → Executable file
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
0
src/General/img/favicons/Mayhem/unreadDead.png
Normal file → Executable file
|
Before Width: | Height: | Size: 346 B After Width: | Height: | Size: 346 B |
0
src/General/img/favicons/Mayhem/unreadDeadY.png
Normal file → Executable file
|
Before Width: | Height: | Size: 456 B After Width: | Height: | Size: 456 B |
0
src/General/img/favicons/Mayhem/unreadNSFW.png
Normal file → Executable file
|
Before Width: | Height: | Size: 323 B After Width: | Height: | Size: 323 B |
0
src/General/img/favicons/Mayhem/unreadNSFWY.png
Normal file → Executable file
|
Before Width: | Height: | Size: 450 B After Width: | Height: | Size: 450 B |
0
src/General/img/favicons/Mayhem/unreadSFW.png
Normal file → Executable file
|
Before Width: | Height: | Size: 321 B After Width: | Height: | Size: 321 B |
0
src/General/img/favicons/Mayhem/unreadSFWY.png
Normal file → Executable file
|
Before Width: | Height: | Size: 450 B After Width: | Height: | Size: 450 B |
0
src/General/img/favicons/Original/unreadDead.gif
Normal file → Executable file
|
Before Width: | Height: | Size: 110 B After Width: | Height: | Size: 110 B |
0
src/General/img/favicons/Original/unreadDeadY.png
Normal file → Executable file
|
Before Width: | Height: | Size: 232 B After Width: | Height: | Size: 232 B |
0
src/General/img/favicons/Original/unreadNSFW.gif
Normal file → Executable file
|
Before Width: | Height: | Size: 110 B After Width: | Height: | Size: 110 B |
0
src/General/img/favicons/Original/unreadNSFWY.png
Normal file → Executable file
|
Before Width: | Height: | Size: 232 B After Width: | Height: | Size: 232 B |
0
src/General/img/favicons/Original/unreadSFW.gif
Normal file → Executable file
|
Before Width: | Height: | Size: 110 B After Width: | Height: | Size: 110 B |
0
src/General/img/favicons/Original/unreadSFWY.png
Normal file → Executable file
|
Before Width: | Height: | Size: 232 B After Width: | Height: | Size: 232 B |
0
src/General/img/favicons/dead.gif
Normal file → Executable file
|
Before Width: | Height: | Size: 94 B After Width: | Height: | Size: 94 B |
0
src/General/img/favicons/empty.gif
Normal file → Executable file
|
Before Width: | Height: | Size: 94 B After Width: | Height: | Size: 94 B |
0
src/General/img/favicons/exclamation.png
Normal file → Executable file
|
Before Width: | Height: | Size: 114 B After Width: | Height: | Size: 114 B |
0
src/General/img/favicons/ferongr/unreadDead.gif
Normal file → Executable file
|
Before Width: | Height: | Size: 172 B After Width: | Height: | Size: 172 B |
0
src/General/img/favicons/ferongr/unreadDeadY.png
Normal file → Executable file
|
Before Width: | Height: | Size: 274 B After Width: | Height: | Size: 274 B |
0
src/General/img/favicons/ferongr/unreadNSFW.gif
Normal file → Executable file
|
Before Width: | Height: | Size: 172 B After Width: | Height: | Size: 172 B |
0
src/General/img/favicons/ferongr/unreadNSFWY.png
Normal file → Executable file
|
Before Width: | Height: | Size: 274 B After Width: | Height: | Size: 274 B |
0
src/General/img/favicons/ferongr/unreadSFW.gif
Normal file → Executable file
|
Before Width: | Height: | Size: 172 B After Width: | Height: | Size: 172 B |
0
src/General/img/favicons/ferongr/unreadSFWY.png
Normal file → Executable file
|
Before Width: | Height: | Size: 270 B After Width: | Height: | Size: 270 B |
0
src/General/img/favicons/xat-/unreadDead.png
Normal file → Executable file
|
Before Width: | Height: | Size: 273 B After Width: | Height: | Size: 273 B |
0
src/General/img/favicons/xat-/unreadDeadY.png
Normal file → Executable file
|
Before Width: | Height: | Size: 349 B After Width: | Height: | Size: 349 B |
0
src/General/img/favicons/xat-/unreadNSFW.png
Normal file → Executable file
|
Before Width: | Height: | Size: 281 B After Width: | Height: | Size: 281 B |