diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 42fa67ad2..66cdd1973 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -3,10 +3,10 @@ 1. Make sure both your **browser** and **4chan X** are up to date. 2. Disable your other extensions & scripts to identify conflicts. 3. If your issue persists, open a [new issue](https://github.com/MayhemYDG/4chan-x/issues) with the following information: - 1. Report precise steps to reproduce the problem. - 2. Report console errors, if any. - 3. Report browser version. - 4. Include your exported settings. + 1. Precise steps to reproduce the problem. + 2. Console errors, if any. + 3. Browser version. + 4. Your exported settings. Open your console with: - `Ctrl + Shift + J` on Chrome. diff --git a/Gruntfile.coffee b/Gruntfile.coffee index cc031785f..a21e7644e 100644 --- a/Gruntfile.coffee +++ b/Gruntfile.coffee @@ -23,31 +23,18 @@ module.exports = (grunt) -> ] dest: 'tmp/script.coffee' - manifest: - options: - process: - data: pkg - src: 'src/manifest.json', - dest: 'builds/crx/manifest.json' - - metadata: - options: - process: - data: pkg - src: 'src/metadata.js', - dest: '<%= pkg.name %>.meta.js' - crx: options: process: data: pkg - src: [ - 'src/banner.js' - 'tmp/script.js' - ] - dest: 'builds/crx/script.js' + files: + 'builds/crx/manifest.json': 'src/manifest.json' + 'builds/crx/script.js': [ + 'src/banner.js' + 'tmp/script.js' + ] - userscript: + userjs: options: process: data: pkg @@ -56,13 +43,27 @@ module.exports = (grunt) -> 'src/banner.js' 'tmp/script.js' ] - dest: '<%= pkg.name %>.user.js' - - userjs: - # Lazily copy the userscript - src: '<%= pkg.name %>.user.js' dest: 'builds/<%= pkg.name %>.js' + userscript: + options: + process: + data: pkg + files: + 'builds/<%= pkg.name %>.meta.js': 'src/metadata.js' + 'builds/<%= pkg.name %>.user.js': [ + 'src/metadata.js' + 'src/banner.js' + 'tmp/script.js' + ] + + copy: + crx: + src: 'img/*.png' + dest: 'builds/crx/' + expand: true + flatten: true + coffee: script: src: 'tmp/script.coffee' @@ -89,35 +90,73 @@ module.exports = (grunt) -> options: interrupt: true files: [ - 'Gruntfile.js' + 'Gruntfile.coffee' 'package.json' - 'lib/**/*.coffee' - 'src/**/*.coffee' - 'src/**/*.js' - 'css/**/*.css' - 'img/*' + 'lib/**/*' + 'src/**/*' + 'css/**/*' + 'img/**/*' ] - tasks: 'default' + tasks: 'build' + + compress: + crx: + options: + archive: 'builds/4chan-X.zip' + level: 9 + pretty: true + expand: true + cwd: 'builds/crx/' + src: '**' clean: - tmp: 'tmp' + builds: 'builds' + tmp: 'tmp' grunt.loadNpmTasks 'grunt-bump' 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-exec' - grunt.registerTask 'default', [ - 'concat:coffee', - 'coffee:script', - 'concat:manifest', - 'concat:crx', - 'concat:userscript', - 'concat:userjs', - 'concat:metadata', - 'clean' + grunt.registerTask 'default', ['build'] + + grunt.registerTask 'set-build', 'Set the build type variable', (type) -> + pkg.type = type; + grunt.log.ok 'pkg.type = %s', type + + grunt.registerTask 'build', [ + 'build-crx' + 'build-userjs' + 'build-userscript' + ] + + grunt.registerTask 'build-crx', [ + 'set-build:crx' + 'concat:coffee' + 'coffee:script' + 'concat:crx' + 'copy:crx' + 'clean:tmp' + ] + + grunt.registerTask 'build-userjs', [ + 'set-build:userjs' + 'concat:coffee' + 'coffee:script' + 'concat:userjs' + 'clean:tmp' + ] + + grunt.registerTask 'build-userscript', [ + 'set-build:userscript' + 'concat:coffee' + 'coffee:script' + 'concat:userscript' + 'clean:tmp' ] grunt.registerTask 'release', [ @@ -140,6 +179,7 @@ module.exports = (grunt) -> 'bump:major' 'updcl:1' ] + grunt.registerTask 'updcl', 'Update the changelog', (i) -> # Update the `pkg` object with the new version. pkg = grunt.file.readJSON('package.json'); diff --git a/README.md b/README.md index d377b6372..c8c176c3d 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ # 4chan X -Get it [here](http://mayhemydg.github.com/4chan-x/). +Get it [here](https://4chan-x.just-believe.in/). *** -### [MIT License](/4chan-x/blob/master/LICENSE) -### [Contribute](/4chan-x/blob/master/CONTRIBUTING.md) +### [MIT License](/LICENSE) +### [Contribute](/CONTRIBUTING.md) diff --git a/changelog b/changelog-old similarity index 100% rename from changelog rename to changelog-old diff --git a/css/style.css b/css/style.css index 3f21f4327..ae66b6610 100644 --- a/css/style.css +++ b/css/style.css @@ -60,7 +60,7 @@ a[href="javascript:;"] { #qp, #ihover, #updater, #thread-stats, #navlinks, #header, -#qr, #watcher { +#qr { position: fixed; } #overlay { @@ -81,12 +81,15 @@ a[href="javascript:;"] { #qr { z-index: 30; } -#watcher { +#watcher:hover { z-index: 20; } #header { z-index: 10; } +#watcher { + z-index: 5; +} /* Header */ .fourchan-x body { @@ -104,8 +107,8 @@ a[href="javascript:;"] { display: flex; padding: 3px 4px 4px; position: relative; - -webkit-transition: all .1s ease-in-out; - transition: all .1s ease-in-out; + -webkit-transition: all .1s .05s ease-in-out; + transition: all .1s .05s ease-in-out; } #board-list { -webkit-flex: 1; @@ -252,6 +255,9 @@ a[href="javascript:;"] { -webkit-flex: 1; flex: 1; } +.tab-selected { + font-weight: 700; +} .section-container { -webkit-flex: 1; flex: 1; @@ -421,7 +427,7 @@ a[href="javascript:;"] { max-height: 300px; max-width: 500px; } -.qphl { +.qphl > .post { outline: 2px solid rgba(216, 94, 49, .7); } @@ -435,6 +441,9 @@ a[href="javascript:;"] { .expanding { opacity: .5; } +.expanded-image { + clear: both; +} .expanded-image > .op > .file::after { content: ''; clear: both; @@ -736,6 +745,11 @@ a[href="javascript:;"] { #file-n-submit > #qr-file-spoiler { margin: 0 2px; } +#file-n-submit input[type='submit'] { + min-width: 40px; + -webkit-order: 1; + order: 1; +} #qr input[type='file'] { position: absolute; visibility: hidden; diff --git a/img/favicons/Mayhem/unreadNSFWY.png b/img/favicons/Mayhem/unreadNSFWY.png index a4b95550d..16180b91c 100644 Binary files a/img/favicons/Mayhem/unreadNSFWY.png and b/img/favicons/Mayhem/unreadNSFWY.png differ diff --git a/img/favicons/Mayhem/unreadSFWY.png b/img/favicons/Mayhem/unreadSFWY.png index 7b5b0ee60..3f48cf5c2 100644 Binary files a/img/favicons/Mayhem/unreadSFWY.png and b/img/favicons/Mayhem/unreadSFWY.png differ diff --git a/img/favicons/Original/unreadDeadY.png b/img/favicons/Original/unreadDeadY.png index f0a1bdab4..f5f41b903 100644 Binary files a/img/favicons/Original/unreadDeadY.png and b/img/favicons/Original/unreadDeadY.png differ diff --git a/img/favicons/Original/unreadNSFWY.png b/img/favicons/Original/unreadNSFWY.png index f005e187c..fb562d564 100644 Binary files a/img/favicons/Original/unreadNSFWY.png and b/img/favicons/Original/unreadNSFWY.png differ diff --git a/img/favicons/Original/unreadSFWY.png b/img/favicons/Original/unreadSFWY.png index 881821f9f..eaf49a8e3 100644 Binary files a/img/favicons/Original/unreadSFWY.png and b/img/favicons/Original/unreadSFWY.png differ diff --git a/img/favicons/ferongr/unreadDeadY.png b/img/favicons/ferongr/unreadDeadY.png index 39c27dcec..e8008c9c6 100644 Binary files a/img/favicons/ferongr/unreadDeadY.png and b/img/favicons/ferongr/unreadDeadY.png differ diff --git a/img/favicons/ferongr/unreadNSFWY.png b/img/favicons/ferongr/unreadNSFWY.png index 4f4fa0979..35c59ddc2 100644 Binary files a/img/favicons/ferongr/unreadNSFWY.png and b/img/favicons/ferongr/unreadNSFWY.png differ diff --git a/img/favicons/ferongr/unreadSFWY.png b/img/favicons/ferongr/unreadSFWY.png index f4397364b..4ab87b0c4 100644 Binary files a/img/favicons/ferongr/unreadSFWY.png and b/img/favicons/ferongr/unreadSFWY.png differ diff --git a/img/favicons/xat-/unreadDeadY.png b/img/favicons/xat-/unreadDeadY.png index dab4041c2..b18f8140c 100644 Binary files a/img/favicons/xat-/unreadDeadY.png and b/img/favicons/xat-/unreadDeadY.png differ diff --git a/img/favicons/xat-/unreadNSFWY.png b/img/favicons/xat-/unreadNSFWY.png index 6e5802597..4ee06355c 100644 Binary files a/img/favicons/xat-/unreadNSFWY.png and b/img/favicons/xat-/unreadNSFWY.png differ diff --git a/img/favicons/xat-/unreadSFWY.png b/img/favicons/xat-/unreadSFWY.png index aa0b53c66..4e6c1b4be 100644 Binary files a/img/favicons/xat-/unreadSFWY.png and b/img/favicons/xat-/unreadSFWY.png differ diff --git a/img/icon128.png b/img/icon128.png new file mode 100644 index 000000000..e75a8f86b Binary files /dev/null and b/img/icon128.png differ diff --git a/img/icon16.png b/img/icon16.png new file mode 100644 index 000000000..a1d2a71e8 Binary files /dev/null and b/img/icon16.png differ diff --git a/img/icon48.png b/img/icon48.png new file mode 100644 index 000000000..227f681ed Binary files /dev/null and b/img/icon48.png differ diff --git a/lib/$.coffee b/lib/$.coffee index 447bb1c3d..d23fa6a8e 100644 --- a/lib/$.coffee +++ b/lib/$.coffee @@ -51,7 +51,7 @@ $.extend String::, $.DAY = 24 * ($.HOUR = 60 * ($.MINUTE = 60 * ($.SECOND = 1000))) $.extend $, - engine: /WebKit|Presto|Gecko/.exec(navigator.userAgent)[0].toLowerCase() + engine: '<% if (type === 'crx') { %>webkit<% } else if (type === 'userjs') { %>presto<% } else { %>gecko<% } %>' id: (id) -> d.getElementById id ready: (fc) -> @@ -226,19 +226,8 @@ $.extend $, globalEval: (code) -> script = $.el 'script', textContent: code - $.add d.head, script + $.add (d.head or doc), script $.rm script - # http://mths.be/unsafewindow - unsafeWindow: - if window.opera # Opera - window - else if unsafeWindow? # Firefox - unsafeWindow - else # Chrome - do -> - p = d.createElement 'p' - p.setAttribute 'onclick', 'return window' - p.onclick() bytesToString: (size) -> unit = 0 # Bytes while size >= 1024 @@ -255,11 +244,30 @@ $.extend $, Math.round size "#{size} #{['B', 'KB', 'MB', 'GB'][unit]}" -if GM_deleteValue? +<% if (type === 'crx') { %> + delete: (name) -> + localStorage.removeItem g.NAMESPACE + name + get: (name, defaultValue) -> + if value = localStorage.getItem g.NAMESPACE + name + JSON.parse value + else + defaultValue + set: (name, value) -> + localStorage.setItem g.NAMESPACE + name, JSON.stringify value +<% } else if (type === 'userjs') { %> +do -> + # http://www.opera.com/docs/userjs/specs/#scriptstorage + # http://www.opera.com/docs/userjs/using/#securepages + # The scriptStorage object is available only during + # the main User JavaScript thread, being therefore + # accessible only in the main body of the user script. + # To access the storage object later, keep a reference + # to the object. + {scriptStorage} = opera $.delete = (name) -> - GM_deleteValue g.NAMESPACE + name + delete scriptStorage[g.NAMESPACE + name] $.get = (name, defaultValue) -> - if value = GM_getValue g.NAMESPACE + name + if value = scriptStorage[g.NAMESPACE + name] JSON.parse value else defaultValue @@ -268,37 +276,19 @@ if GM_deleteValue? value = JSON.stringify value # for `storage` events localStorage.setItem name, value - GM_setValue name, value -else if window.opera - do -> - # http://www.opera.com/docs/userjs/specs/#scriptstorage - # http://www.opera.com/docs/userjs/using/#securepages - # >The scriptStorage object is available only during - # the main User JavaScript thread, being therefore - # accessible only in the main body of the user script. - # To access the storage object later, keep a reference - # to the object. - {scriptStorage} = opera - $.delete = (name) -> - delete scriptStorage[g.NAMESPACE + name] - $.get = (name, defaultValue) -> - if value = scriptStorage[g.NAMESPACE + name] - JSON.parse value - else - defaultValue - $.set = (name, value) -> - name = g.NAMESPACE + name - value = JSON.stringify value - # for `storage` events - localStorage.setItem name, value - scriptStorage[name] = value -else - $.delete = (name) -> - localStorage.removeItem g.NAMESPACE + name - $.get = (name, defaultValue) -> - if value = localStorage.getItem g.NAMESPACE + name + scriptStorage[name] = value +<% } else { %> + delete: (name) -> + GM_deleteValue g.NAMESPACE + name + get: (name, defaultValue) -> + if value = GM_getValue g.NAMESPACE + name JSON.parse value else defaultValue - $.set = (name, value) -> - localStorage.setItem g.NAMESPACE + name, JSON.stringify value + set: (name, value) -> + name = g.NAMESPACE + name + value = JSON.stringify value + # for `storage` events + localStorage.setItem name, value + GM_setValue name, value +<% } %> diff --git a/package.json b/package.json index a099124d4..32095fc07 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "meta": { "name": "4chan X Beta", "repo": "https://github.com/MayhemYDG/4chan-x/", - "page": "http://mayhemydg.github.com/4chan-x/", + "page": "https://4chan-x.just-believe.in/", "mainBranch": "v3", "matches": [ "*://api.4chan.org/*", @@ -15,12 +15,14 @@ ] }, "devDependencies": { - "grunt": "~0.4.0", + "grunt": "~0.4.1", "grunt-bump": "~0.0.0", "grunt-contrib-clean": "~0.4.0", - "grunt-contrib-coffee": "~0.6.2", - "grunt-contrib-concat": "~0.1.0", - "grunt-contrib-watch": "~0.3.0", + "grunt-contrib-coffee": "~0.6.4", + "grunt-contrib-compress": "~0.4.5", + "grunt-contrib-concat": "~0.1.3", + "grunt-contrib-copy": "~0.4.0", + "grunt-contrib-watch": "~0.3.1", "grunt-exec": "~0.4.0" }, "repository": { diff --git a/src/config.coffee b/src/config.coffee index 31eb11526..bee11d02a 100644 --- a/src/config.coffee +++ b/src/config.coffee @@ -15,7 +15,7 @@ Config = ] 'Custom Board Navigation': [ true - 'Disable this to always display the full board list.' + 'Show custom links instead of the full board list.' ] '404 Redirect': [ true @@ -27,7 +27,7 @@ Config = ] 'Time Formatting': [ true - 'Localize and format timestamps arbitrarily.' + 'Localize and format timestamps.' ] 'Relative Post Dates': [ false @@ -39,19 +39,15 @@ Config = ] 'Comment Expansion': [ true - 'Can expand too long comments.' + 'Add buttons to expand long comments.' ] 'Thread Expansion': [ true - 'Can expand threads to view all replies.' + 'Add buttons to expand threads.' ] 'Index Navigation': [ false - 'Navigate to previous / next thread.' - ] - 'Custom CSS': [ - false - 'Apply custom CSS to 4chan.' + 'Add buttons to navigate between threads.' ] 'Check for Updates': [ true @@ -75,7 +71,7 @@ Config = 'Filtering': 'Anonymize': [ false - 'Turn everyone Anonymous.' + 'Make everyone Anonymous.' ] 'Filter': [ true @@ -87,19 +83,19 @@ Config = ] 'Thread Hiding': [ true - 'Hide entire threads.' + 'Add buttons to hide entire threads.' ] 'Reply Hiding': [ true - 'Hide single replies.' + 'Add buttons to hide single replies.' ] 'Hiding Buttons': [ true - 'Make buttons to hide threads / replies, in addition to menu links.' + 'Add buttons to hide threads / replies, in addition to menu links.' ] 'Stubs': [ true - 'Make stubs of hidden threads / replies.' + 'Show stubs of hidden threads / replies.' ] 'Images': @@ -135,8 +131,16 @@ Config = 'Menu': 'Menu': [ true - 'Add a drop-down menu in posts.' + 'Add a drop-down menu to posts.' ] + 'Thread Hiding Link': [ + true + 'Add a link to hide entire threads.' + ] + 'Reply Hiding Link': [ + true + 'Add a link to hide single replies.' + ] 'Report Link': [ true 'Add a report link to the menu.' @@ -222,7 +226,7 @@ Config = 'Hide the normal post form.' ] - 'Quote links': + 'Quote Links': 'Quote Backlinks': [ true 'Add quote backlinks.' @@ -331,21 +335,23 @@ Config = MD5: '' sauces: """ -http://iqdb.org/?url=%turl -http://www.google.com/searchbyimage?image_url=%turl -#http://tineye.com/search?url=%turl -#http://saucenao.com/search.php?db=999&url=%turl -#http://3d.iqdb.org/?url=%turl -#http://regex.info/exif.cgi?imgurl=%url +http://iqdb.org/?url=%TURL +https://www.google.com/searchbyimage?image_url=%TURL +#//tineye.com/search?url=%TURL +#http://saucenao.com/search.php?url=%TURL +#http://3d.iqdb.org/?url=%TURL +#http://regex.info/exif.cgi?imgurl=%URL # uploaders: -#http://imgur.com/upload?url=%url;text:Upload to imgur -#http://omploader.org/upload?url1=%url;text:Upload to omploader +#http://imgur.com/upload?url=%URL;text:Upload to imgur +#http://ompldr.org/upload?url1=%URL;text:Upload to ompldr # "View Same" in archives: #//archive.foolz.us/_/search/image/%MD5/;text:View same on foolz #//archive.foolz.us/%board/search/image/%MD5/;text:View same on foolz /%board/ #//archive.installgentoo.net/%board/image/%MD5;text:View same on installgentoo /%board/ """ + 'Custom CSS': false + 'Header auto-hide': false 'Header catalog links': false diff --git a/src/features.coffee b/src/features.coffee index 665e07294..a448820a2 100644 --- a/src/features.coffee +++ b/src/features.coffee @@ -31,7 +31,7 @@ Header = className: 'hide-board-list-button brackets-wrap' innerHTML: ' - ' $.on btn, 'click', Header.toggleBoardList - $.prepend fullBoardList, btn + $.add fullBoardList, btn else $.rm $ '#custom-board-list', nav fullBoardList.hidden = false @@ -40,8 +40,8 @@ Header = list = $ '#custom-board-list', Header.nav list.innerHTML = null return unless text - as = $$('#full-board-list a', Header.nav) - nodes = text.match(/[\w@]+(-(all|title|full|text:"[^"]+"))?|[^\w@]+/g).map (t) -> + as = $$('#full-board-list a', Header.nav)[0...-2] # ignore the Settings and Home links + nodes = text.match(/[\w@]+(-(all|title|full|index|catalog|text:"[^"]+"))*|[^\w@]+/g).map (t) -> if /^[^\w@]/.test t return $.tn t if t is 'toggle-all' @@ -58,12 +58,17 @@ Header = for a in as if a.textContent is board a = a.cloneNode true - if /-title$/.test t + if /-title/.test t a.textContent = a.title - else if /-full$/.test t + else if /-full/.test t a.textContent = "/#{board}/ - #{a.title}" - else if m = t.match /-text:"(.+)"$/ - a.textContent = m[1] + else if /-(index|catalog|text)/.test t + if m = t.match /-(index|catalog)/ + a.setAttribute 'data-only', m[1] + a.href = "//boards.4chan.org/#{board}/" + a.href += 'catalog' if m[1] is 'catalog' + if m = t.match /-text:"(.+)"/ + a.textContent = m[1] else if board is '@' $.addClass a, 'navSmall' return a @@ -224,17 +229,15 @@ Settings = links = [] for section in Settings.sections link = $.el 'a', + className: "tab-#{section.hyphenatedTitle}" textContent: section.title href: 'javascript:;' $.on link, 'click', Settings.openSection.bind section links.push link, $.tn ' | ' sectionToOpen = link if section.title is openSection links.pop() - if sectionToOpen - sectionToOpen.click() - else - links[0].click() $.add $('.sections-list', overlay), links + (if sectionToOpen then sectionToOpen else links[0]).click() $.on $('.close', overlay), 'click', Settings.close $.on overlay, 'click', Settings.close @@ -254,11 +257,15 @@ Settings = addSection: (title, open) -> if typeof title isnt 'string' {title, open} = title.detail - Settings.sections.push {title, open} + hyphenatedTitle = title.toLowerCase().replace /\s+/g, '-' + Settings.sections.push {title, hyphenatedTitle, open} openSection: -> + if selected = $ '.tab-selected', Settings.dialog + $.rmClass selected, 'tab-selected' + $.addClass $(".tab-#{@hyphenatedTitle}", Settings.dialog), 'tab-selected' section = $ 'section', Settings.dialog section.innerHTML = null - section.className = "section-#{@title.toLowerCase().replace /\s+/g, '-'}" + section.className = "section-#{@hyphenatedTitle}" @open section, g section.scrollTop = 0 @@ -283,7 +290,7 @@ Settings = description = arr[1] div = $.el 'div', innerHTML: ": #{description}" - $.on $('input', div), 'click', $.cb.checked + $.on $('input', div), 'change', $.cb.checked $.add fs, div $.add section, fs @@ -311,7 +318,7 @@ Settings = className: 'warning' textContent: 'Save me!' download: "<%= meta.name %> v#{g.VERSION}-#{now}.json" - href: "data:application/json;base64,#{btoa unescape encodeURIComponent JSON.stringify data}" + href: "data:application/json;base64,#{btoa unescape encodeURIComponent JSON.stringify data, null, 2}" target: '_blank' if $.engine isnt 'gecko' a.click() @@ -451,7 +458,7 @@ Settings = $.add div, ta return div.innerHTML = """ -
Filter is disabled.Filter is disabled.
Use regular expressions, one per line.
Lines starting with a # will be ignored.
@@ -509,6 +516,9 @@ Settings =
board-titleboard-fullboard-text:"VIP Board"board-indexboard-catalogboard-index-text:"VIP Index"toggle-all