├── .gitignore ├── Gruntfile.js ├── LICENSE.md ├── README.md ├── dist ├── README.md └── iZhihu for Chrome.pem ├── docs ├── .gitCfg.bat ├── assets │ ├── Bootstrap.bmml │ ├── comment.png │ └── favorites.png ├── icons │ ├── 128128无空白.JPG │ ├── 128128无空白.png │ ├── 16边缘空白.png │ └── 源文件.psd ├── prototype │ ├── assets │ │ ├── Bootstrap.bmml │ │ ├── comment.png │ │ └── favorites.png │ ├── comment.bmml │ ├── comment.png │ ├── favorites.bmml │ └── favorites.png └── screenshots │ ├── 「我要回答」快速跳转链接.png │ ├── 于回答右侧展开评论列表.png │ ├── 功能开关选项.png │ ├── 功能开关选项_s.png │ ├── 原有评论框底部添加「收起」按钮.png │ ├── 回答目录&预览.png │ ├── 快速屏蔽.png │ ├── 快速黑名单.png │ ├── 搜索框增强.png │ ├── 收藏夹地址清单.png │ ├── 消息通知下拉列表.png │ ├── 用户回答地址清单.png │ ├── 首页动态过滤选项.png │ └── 首页调整预览.png ├── grunt ├── README.md └── config.js ├── import ├── blue.css ├── blue.png ├── blue@2x.png ├── icheck.min.js ├── jquery-1.8.2.min.js ├── jquery-ui.min.js ├── purl.js └── underscore-min.js ├── misc ├── crx-config │ ├── icon128.png │ ├── icon16.png │ ├── icon48.png │ └── manifest.json ├── ext-config │ ├── Info.plist │ ├── Settings.plist │ ├── icon-128.png │ ├── icon-48.png │ └── icon-64.png └── xpi-config │ ├── icon.png │ ├── icon64.png │ ├── lib │ └── main.js │ ├── package.json │ └── test │ └── test-main.js ├── package.json ├── src ├── begin.js ├── end.js ├── izhihu.js ├── lib │ └── utils.js ├── meta.js ├── modules │ ├── Answer.js │ ├── Comment.js │ ├── Noti7.js │ ├── QuickBlock.js │ ├── QuickFavo.js │ ├── SearchingList.js │ ├── TopNav.js │ └── allLinks.js └── pages │ ├── README.md │ ├── answer.js │ ├── collection.js │ ├── home.js │ ├── question.js │ ├── settings.js │ └── settingsFilter.js └── test ├── answer_shift.css └── en_clip.js /.gitignore: -------------------------------------------------------------------------------- 1 | # Linux 2 | # backup files 3 | *~ 4 | 5 | # Windows 6 | # thumbnails 7 | Thumbs.db 8 | 9 | # Mac OS X 10 | # metadata 11 | .DS_Store 12 | # thumbnails 13 | ._* 14 | 15 | # Visual Studio PHP 16 | *.sln 17 | *.phpproj 18 | *.puo 19 | *.suo 20 | *.cache 21 | 22 | # Netbeans 23 | nbproject/ 24 | catalog.xml 25 | nbactions.xml 26 | 27 | # Eclipse 28 | .settings/ 29 | .buildpath 30 | .classpath 31 | .project 32 | 33 | # SVN 34 | # svn folders 35 | .svn/ 36 | 37 | # PHPStorm 38 | .idea/ 39 | .nameencodings 40 | .xmlmisc 41 | .xmlmodules 42 | .xmlprojectCodeStyle 43 | .xmlvcs.xml 44 | *.imlworkspace 45 | .xml 46 | 47 | 48 | # common # 49 | *.log 50 | logs/ 51 | tmp/ 52 | temp/ 53 | 54 | # nodejs # 55 | node_modules/ 56 | public/gen 57 | sea-modules/ 58 | dist/*.js 59 | 60 | # java # 61 | /plugin.xml 62 | web-app/WEB-INF/classes/ 63 | .settings/ 64 | target/ 65 | target-eclipse/ 66 | grails-*.zip 67 | *.war 68 | .link_to_grails_plugins/ 69 | 70 | # other # 71 | *.swp 72 | .DS_Store 73 | 74 | 75 | 76 | /.gitCfg.bat 77 | /iZhihu for Chrome/ 78 | 79 | # develop files 80 | build/ 81 | dist/iZhihu for Chrome/ 82 | 83 | #picasa 84 | .picasa.ini 85 | /dist/iZhihu for Firefox 86 | /dist/iZhihu.safariextension 87 | 88 | dist/ 89 | -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | // 安装 node.js 2 | // 安装 grunt - 在控制台( window 运行 cmd)输入 npm install -g grunt-cli 即可 3 | // 项目目录 npm install 安装关联库 4 | // grunt 执行相关任务 (在目录下) 5 | 6 | // 定义 grunt 的设置 7 | module.exports = function (grunt) { 8 | 9 | // 根据 package.json 获取 NpmTasks 并 loadNpmTasks 所用用到了什么常用 任务在 package.json 配置即可 10 | var npmTaskNames = JSON.stringify(grunt.file.readJSON('package.json').devDependencies).match(/grunt\-[^"^']+/g) 11 | , i = npmTaskNames.length; 12 | 13 | while (i--) { 14 | grunt.loadNpmTasks(npmTaskNames[i]); 15 | } 16 | 17 | // 引入配置 与 任务 18 | require('./grunt/config.js')(grunt); 19 | 20 | return grunt; 21 | }; -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT LICENSE 2 | 3 | Copyright (c) 2012 https://github.com/unogz/izhihu 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # iZhihu 我爱知乎 2 | 3 | ## 它是什么 4 | 5 | **What we do:** 6 | 7 | - 「知乎」([www.zhihu.com](www.zhihu.com))是一个类似 Quora.com 的 SNS 问答社区。 8 | - 此脚本用于在「知乎」当前产品的基础上满足用户自身需要,对「知乎」产品本身不产生任何影响。 9 | - 基于对知乎的热爱,而目前知乎还在进化中,一些知友广泛需求的小功能还不能及时满足。 10 | - 所以我们希望能对知乎社区有所回馈,不是简单的知乎反馈,而是通过我们的技术去改造去帮助知乎试错。 11 | - 并希望若某些功能经过一段时间知友的使用/完善/认可后,知乎团队能考虑整合进去,方便更多的用户。 12 | 13 | **What we don't:** 14 | 15 | - 数据挖掘类的需求,我们会谨慎评估。 16 | - 一方面因为我们是基于个人浏览器前端的,并无法获取到太多数据,也不希望抓取太多知乎的数据进行二次分析。 17 | - 因为那由知乎自己来做效果会更好,另一方不希望本插件被滥用。 18 | 19 | **更新历史** 20 | 21 | [http://zhuanlan.zhihu.com/izhihu/19566032](http://zhuanlan.zhihu.com/izhihu/19566032) 22 | 23 | **主要功能(标记 * 的功能为可配置选项)** 24 | 25 | - *美化包括首页布局在内的大多数常用页面样式外观 26 | - *滚动页面至下方时,自动收起顶部导航栏 27 | - *将回答者信息挪至回答的下方 28 | - *在页面右侧浮动弹出评论列表及输入框 29 | - *快速屏蔽/取消关注评论列表、赞同列表中的用户 30 | - *快速收藏(原收藏按钮处浮动弹出菜单) 31 | - *问题页回答目录(预览及跳转,回答数超过 100 条时将提示是否关闭) 32 | - *查看全部搜索结果使用「外部搜索引擎」(Google、百度) 33 | - 首页动态过滤选项 34 | - 自动展开「折叠区」 35 | - 问题下方提供「我要回答」、「我的回答」跳转 36 | - 收藏、回答列表的地址清单导出 37 | - 「消息通知列表」内提供「隐藏已读」开关 38 | - 搜索结果「在新页面打开」 39 | 40 | ## 下载安装 41 | 42 | **使用浏览器扩展** 43 | 44 | - iZhihu for Chrome:[https://chrome.google.com/webstore/detail/izhihu/omcldpfdihfogiklcdlopeokkedbhjop](https://chrome.google.com/webstore/detail/izhihu/omcldpfdihfogiklcdlopeokkedbhjop) 45 | - iZhihu for Firefox:[https://addons.mozilla.org/zh-CN/firefox/addon/izhihu/](https://addons.mozilla.org/zh-CN/firefox/addon/izhihu/) 46 | - iZhihu for Safari:[http://izhihu.unogz.com/safari/iZhihu.safariextz](http://izhihu.unogz.com/safari/iZhihu.safariextz) 47 | 48 | **使用油猴脚本** 49 | 50 | - Chrome 推荐使用扩展:「[Tampermonkey](https://chrome.google.com/webstore/detail/dhdgffkkebhmkfjojejmpbldmpobfkfo)」 51 | - Firefox 推荐使用扩展:「[Greasemonkey](https://addons.mozilla.org/en-US/firefox/addon/greasemonkey/)」 52 | - iZhihu 脚本:[https://greasyfork.org/scripts/350-izhihu](https://greasyfork.org/scripts/350-izhihu) 53 | 54 | ## 码农醒目 55 | 56 | - 安装 Node.js:[http://nodejs.org/](http://nodejs.org/) 57 | - 安装 Grunt:在命令行(终端)运行 `npm install -g grunt-cli`( Grunt 入门:[http://www.gruntjs.net/docs/getting-started/](http://www.gruntjs.net/docs/getting-started/)) 58 | - 安装依赖库: 59 | 1. 将命令行(终端)的当前目录转到项目的根目录下 60 | 2. 执行 `npm install` 命令安装项目依赖的库 61 | - build: 62 | 1. 将命令行(终端)的当前目录转到项目的根目录下 63 | 2. 执行 `grunt buildall`(更多配置请查看 grunt/config.js ) 64 | 3. 生成内容位于 dist 目录下 65 | 66 | ## 关于我们 67 | 68 | **知乎专栏** 69 | 70 | [http://zhuanlan.zhihu.com/izhihu](http://zhuanlan.zhihu.com/izhihu) 71 | 72 | **代码仓库** 73 | 74 | [https://github.com/unogz/izhihu](https://github.com/unogz/izhihu) 75 | 76 | **贡献者** 77 | 78 | - [@钢盅郭子](http://www.zhihu.com/people/unogzx) 79 | - [@刘勇](http://www.zhihu.com/people/liuyong25) 80 | - [@罗大睿](http://www.zhihu.com/people/luoxr) 81 | - [@墨磊](http://www.zhihu.com/people/morlay) 82 | 83 | **欢迎您的加入或反馈** 84 | -------------------------------------------------------------------------------- /dist/README.md: -------------------------------------------------------------------------------- 1 | 发布目录,用于存放打包后的 userscript 或 crx/ext/xpi 源码 2 | 3 | - `izhihu.js` 脚本主体 4 | - `izhihu.userscript.js` 油猴脚本 5 | - `iZhihu for Chrome` Chrome 扩展目录 6 | - `iZhihu for Firefox` Firefox 扩展目录 7 | - `iZhihu.safariextension` Safari 扩展目录 8 | -------------------------------------------------------------------------------- /dist/iZhihu for Chrome.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBANtsf4R5gTiDVfVxA 3 | 0wvPP0VbnNuzq2M+FE7x4VMkO60qLOq4zJgQk9V4OT5WtIpkOLJJqpYMETNeutj8Y 4 | ciWO2RiHdAEe2CxcaEODjycqiw1cnw01XknIZ75GGAa/qFZmOHoJ32ags0kzcCH+Q 5 | O9w2dDaoSqGQ9M/HvW7Fa31sxAgMBAAECgYAWglvWeCx0Yqy3v/8pmpL0F3W8K7rR 6 | /OsgUjSWjRM1GZ1QyRADg/JpdxLaCmZxtsfhK+dmhCN3e2jHqvoE9dYPYDk33a4lk 7 | +GOvSemxjgxo466M25iJJql6MKaE6o8jStfWFEEkQ+44EGd/zWyvUT/PYkMog5Prp 8 | 02Rz7Gq87YwQJBAPea6OsPJTXbRA3VMOacFKsfzgZIjLgk7DZngtf1W7TrXz39mRX 9 | zxoA+sv814lMiUxANVUuIuNE5zwpQLAmp6zkCQQDi3P0RROoc5O006l07b+y3SzjM 10 | GGo+wLF7zlNIE03YNpvQE8XuMn3SlWQvP69LqZrPtA3VhPe7wUoizktNRFe5AkEA2 11 | kOw7HxmVcpafEMhHzgZNBwONhXADhdmLjMi8RH1bE9Lns6tIt/IbIZYrYYnYxdP10 12 | eZl8MHAFCQRMwVddNWaQJBANzRu+aGTNbJIfbitNM485HKP0Ox9CCW0Wsv/rJmT9x 13 | H80wLIxrivMQwM68l7wvXz9+iY+DUp4py7yWH5ZYVEskCQAR4f7zRONvakoX8oMZt 14 | n7ECSBfJpN2gh5UHF5bhb5XWpCNSOjm5eQNA0lcU4+R1ZfR1pH/ZC/gVhW/ZqPzsb 15 | ps= 16 | -----END PRIVATE KEY----- 17 | -------------------------------------------------------------------------------- /docs/.gitCfg.bat: -------------------------------------------------------------------------------- 1 | :: Git Config http://zengrong.net/post/1249.htm && https://github.com/nvie/gitflow/ 2 | git config --global core.quotepath false 3 | git config --global gui.encoding utf-8 4 | git config --global i18n.commitencoding utf-8 5 | git config --global i18n.logoutputencoding gbk 6 | setx LESSCHARSET "utf-8" -m 7 | git config --list 8 | pause 9 | git log -3 10 | cmd -------------------------------------------------------------------------------- /docs/assets/comment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unogz/izhihu/f1efa7b0574723d1e04c682433ce303ed053edc4/docs/assets/comment.png -------------------------------------------------------------------------------- /docs/assets/favorites.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unogz/izhihu/f1efa7b0574723d1e04c682433ce303ed053edc4/docs/assets/favorites.png -------------------------------------------------------------------------------- /docs/icons/128128无空白.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unogz/izhihu/f1efa7b0574723d1e04c682433ce303ed053edc4/docs/icons/128128无空白.JPG -------------------------------------------------------------------------------- /docs/icons/128128无空白.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unogz/izhihu/f1efa7b0574723d1e04c682433ce303ed053edc4/docs/icons/128128无空白.png -------------------------------------------------------------------------------- /docs/icons/16边缘空白.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unogz/izhihu/f1efa7b0574723d1e04c682433ce303ed053edc4/docs/icons/16边缘空白.png -------------------------------------------------------------------------------- /docs/icons/源文件.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unogz/izhihu/f1efa7b0574723d1e04c682433ce303ed053edc4/docs/icons/源文件.psd -------------------------------------------------------------------------------- /docs/prototype/assets/comment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unogz/izhihu/f1efa7b0574723d1e04c682433ce303ed053edc4/docs/prototype/assets/comment.png -------------------------------------------------------------------------------- /docs/prototype/assets/favorites.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unogz/izhihu/f1efa7b0574723d1e04c682433ce303ed053edc4/docs/prototype/assets/favorites.png -------------------------------------------------------------------------------- /docs/prototype/comment.bmml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ./assets/comment.png 6 | 7 | 8 | 9 | 10 | 11 | tb-alert-info 12 | 13 | 14 | 15 | 16 | left 17 | 7317724 18 | 10470904 19 | roundRect 20 | 21 | 22 | 23 | 24 | 25 | 472931 26 | 14 27 | *Comments* 28 | 29 | 30 | 31 | 32 | 7317724 33 | 34 | 35 | 36 | 37 | %5B%u5F35%u7B71%u857E%5D%0A%20%0A%5B%u9648%u601D%u6770%5D%0A%20%0A%5B%u9A86%u542F%u660E%5D%0A%20%0A%5B%u9AD8%u98DE%5D 38 | 39 | 40 | 41 | 42 | AddPageIcon%7Cxsmall 43 | right 44 | Add 45 | 46 | 47 | 48 | 49 | UpArrowIcon%7Cxsmall 50 | right 51 | Top 52 | 53 | 54 | 55 | 56 | SquaredMinusIcon%7Cxsmall 57 | right 58 | Collapse 59 | 60 | 61 | 62 | 63 | 64 | 65 | *%20%u8BC4%u8BBA%u4FA7%u8FB9%u680F%2C%20scroll%20fix%2C%20%u7D27%u8D34%u5728%u8BC4%u8BBA%u53F3%u4FA7%2C%u6839%u636E%u6EDA%u52A8%u663E%u793A/%u9690%u85CF%0A*%20%u8BC4%u8BBA%u6846%u4E0A%u4E0B%u5404%u4E00%u4E2A%28%u4E0D%u8FC7%u6709%u4FA7%u8FB9%u680F%u7684add%2C%u8FD9%u4E2A%u5FC5%u8981%u6027%u4E0D%u5927%29 66 | 67 | 68 | 69 | 70 | 16750848 71 | bottom 72 | true 73 | false 74 | 75 | 76 | 77 | 78 | 16750848 79 | top 80 | false 81 | true 82 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /docs/prototype/comment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unogz/izhihu/f1efa7b0574723d1e04c682433ce303ed053edc4/docs/prototype/comment.png -------------------------------------------------------------------------------- /docs/prototype/favorites.bmml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | %u6DFB%u52A0%u300C%u6536%u85CF%u95EE%u9898%u300D%u529F%u80FD%uFF0C%u4FDD%u5B58%u5230cloudfoundry%u7684mongodb%u53BB%u3002 6 | 7 | 8 | 9 | 10 | %u589E%u52A0%u300C%u6295%u9012%u6536%u85CF%u5939%u300D%u529F%u80FD%uFF0C%u53EF%u4EE5%u641C%u7D22%u70ED%u95E8%u7684%u6536%u85CF%u5939%uFF0C%u81EA%u52A8%u751F%u6210%u8BC4%u8BBA%u5185%u5BB9%uFF0C%u5E76%u8BC4%u8BBA%u3002 11 | 12 | 13 | 14 | 15 | 16750848 16 | bottom 17 | true 18 | false 19 | 20 | 21 | 22 | 23 | ./assets/favorites.png 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /docs/prototype/favorites.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unogz/izhihu/f1efa7b0574723d1e04c682433ce303ed053edc4/docs/prototype/favorites.png -------------------------------------------------------------------------------- /docs/screenshots/「我要回答」快速跳转链接.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unogz/izhihu/f1efa7b0574723d1e04c682433ce303ed053edc4/docs/screenshots/「我要回答」快速跳转链接.png -------------------------------------------------------------------------------- /docs/screenshots/于回答右侧展开评论列表.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unogz/izhihu/f1efa7b0574723d1e04c682433ce303ed053edc4/docs/screenshots/于回答右侧展开评论列表.png -------------------------------------------------------------------------------- /docs/screenshots/功能开关选项.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unogz/izhihu/f1efa7b0574723d1e04c682433ce303ed053edc4/docs/screenshots/功能开关选项.png -------------------------------------------------------------------------------- /docs/screenshots/功能开关选项_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unogz/izhihu/f1efa7b0574723d1e04c682433ce303ed053edc4/docs/screenshots/功能开关选项_s.png -------------------------------------------------------------------------------- /docs/screenshots/原有评论框底部添加「收起」按钮.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unogz/izhihu/f1efa7b0574723d1e04c682433ce303ed053edc4/docs/screenshots/原有评论框底部添加「收起」按钮.png -------------------------------------------------------------------------------- /docs/screenshots/回答目录&预览.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unogz/izhihu/f1efa7b0574723d1e04c682433ce303ed053edc4/docs/screenshots/回答目录&预览.png -------------------------------------------------------------------------------- /docs/screenshots/快速屏蔽.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unogz/izhihu/f1efa7b0574723d1e04c682433ce303ed053edc4/docs/screenshots/快速屏蔽.png -------------------------------------------------------------------------------- /docs/screenshots/快速黑名单.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unogz/izhihu/f1efa7b0574723d1e04c682433ce303ed053edc4/docs/screenshots/快速黑名单.png -------------------------------------------------------------------------------- /docs/screenshots/搜索框增强.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unogz/izhihu/f1efa7b0574723d1e04c682433ce303ed053edc4/docs/screenshots/搜索框增强.png -------------------------------------------------------------------------------- /docs/screenshots/收藏夹地址清单.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unogz/izhihu/f1efa7b0574723d1e04c682433ce303ed053edc4/docs/screenshots/收藏夹地址清单.png -------------------------------------------------------------------------------- /docs/screenshots/消息通知下拉列表.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unogz/izhihu/f1efa7b0574723d1e04c682433ce303ed053edc4/docs/screenshots/消息通知下拉列表.png -------------------------------------------------------------------------------- /docs/screenshots/用户回答地址清单.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unogz/izhihu/f1efa7b0574723d1e04c682433ce303ed053edc4/docs/screenshots/用户回答地址清单.png -------------------------------------------------------------------------------- /docs/screenshots/首页动态过滤选项.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unogz/izhihu/f1efa7b0574723d1e04c682433ce303ed053edc4/docs/screenshots/首页动态过滤选项.png -------------------------------------------------------------------------------- /docs/screenshots/首页调整预览.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unogz/izhihu/f1efa7b0574723d1e04c682433ce303ed053edc4/docs/screenshots/首页调整预览.png -------------------------------------------------------------------------------- /grunt/README.md: -------------------------------------------------------------------------------- 1 | 这个目录用于存放 Grunt 的配置文件,及各种任务 2 | 3 | # 当前任务 4 | 5 | ## grunt chrome 6 | 7 | 为 Chrome 扩展合并代码并移动到 iZhihu for Chrome 8 | 9 | ## grunt watch 10 | 11 | 监听 src 中 js 文件变化,如果有变化执行 grunt chrome 12 | 13 | ## grunt buildnum 14 | 15 | build 编号自增 1 -------------------------------------------------------------------------------- /grunt/config.js: -------------------------------------------------------------------------------- 1 | module.exports = function(grunt) { 2 | var pkg = grunt.file.readJSON('package.json') 3 | grunt.initConfig({ 4 | version: [ pkg.version, pkg.buildNum ].join('.') // 5 | , 6 | buildNum: parseInt(pkg.buildNum) 7 | , 8 | dist: 'dist' // 9 | , 10 | filename: pkg.name // 11 | 12 | // 合并 js 文件 13 | // 文档 https://github.com/gruntjs/grunt-contrib-concat 14 | , 15 | concat: { 16 | dist: { 17 | options: { 18 | // banner: '<%= meta.modules %>\n' 19 | }, 20 | src: [ 21 | 'src/begin.js', 22 | "src/lib/*.js", 23 | 'src/izhihu.js', 24 | "src/modules/*.js", 25 | "src/pages/*.js", 26 | "src/end.js" 27 | ], //src filled in by build task 28 | dest: '<%= dist %>/<%= filename %>.js' 29 | }, 30 | distUserscript: { 31 | src: [ 32 | "src/meta.js", 33 | "<%= dist %>/<%= filename %>.js" 34 | ], //src filled in by build task 35 | dest: '<%= dist %>/<%= filename %>.user.js' 36 | } 37 | } 38 | // 压缩 js 文件 39 | // 文档 https://github.com/gruntjs/grunt-contrib-uglify 40 | , 41 | uglify: { 42 | options: { 43 | mangle: true, // 是否替换变量名 44 | report: 'gzip' 45 | }, 46 | dist: { 47 | src: ['<%= dist %>/<%= filename %>.js'], 48 | dest: '<%= dist %>/<%= filename %>.min.js' 49 | }, 50 | } 51 | // copy 文档 52 | // 文档 https://github.com/gruntjs/grunt-contrib-copy 53 | , 54 | copy: { 55 | toChrome: { 56 | files: [{ 57 | expand: true, 58 | filter: 'isFile', 59 | flatten: true, 60 | src: [ 61 | '<%= dist %>/<%= filename %>.js', 62 | 'misc/crx-config/manifest.json', 63 | 'misc/crx-config/*.png', 64 | 'import/*' 65 | ], 66 | dest: '<%= dist %>/iZhihu for Chrome/' 67 | }] 68 | }, 69 | toFirefox1: { 70 | files: [{ 71 | expand: true, 72 | flatten: false, 73 | cwd: 'misc/xpi-config', 74 | src: [ 75 | '**', 76 | ], 77 | dest: '<%= dist %>/iZhihu for Firefox/' 78 | }] 79 | }, 80 | toFirefox2: { 81 | files: [{ 82 | expand: true, 83 | filter: 'isFile', 84 | flatten: true, 85 | src: [ 86 | 'import/*' 87 | ], 88 | dest: '<%= dist %>/iZhihu for Firefox/data/' 89 | }] 90 | }, 91 | toSafari: { 92 | files: [{ 93 | expand: true, 94 | filter: 'isFile', 95 | flatten: true, 96 | src: [ 97 | 'misc/ext-config/**', 98 | '<%= dist %>/izhihu.js', 99 | 'import/*' 100 | ], 101 | dest: '<%= dist %>/iZhihu.safariextension/' 102 | }] 103 | } 104 | } 105 | // 监控文件变化并动态执行任务 106 | // 如下设置是 js 文件夹的任一 js 文件有变化则执行合并 107 | // 文档 https://github.com/gruntjs/grunt-contrib-watch 108 | , 109 | watch: { 110 | scripts: { 111 | files: ['src/**/**.js'], 112 | tasks: ['chrome'] 113 | } 114 | } 115 | , 116 | 'string-replace': { 117 | distSafari: { 118 | files: { 119 | 'dist/iZhihu.safariextension/Info.plist': 'dist/iZhihu.safariextension/Info.plist' 120 | }, 121 | options: { 122 | replacements: [{ 123 | pattern: '[version]', 124 | replacement: '<%= version %>' 125 | }] 126 | } 127 | } 128 | , 129 | distChrome: { 130 | files: { 131 | 'dist/iZhihu for Chrome/blue.css': 'dist/iZhihu for Chrome/blue.css' 132 | }, 133 | options: { 134 | replacements: [{ 135 | pattern: 'url(blue.png)', 136 | replacement: 'url("chrome-extension://__MSG_@@extension_id__/blue.png")' 137 | },{ 138 | pattern: 'url(blue@2x.png)', 139 | replacement: 'url("chrome-extension://__MSG_@@extension_id__/blue@2x.png")' 140 | }] 141 | } 142 | } 143 | } 144 | }); 145 | 146 | // 设定 任务 147 | grunt.registerTask('default', ['concat']); 148 | 149 | 150 | grunt.registerTask('buildnum', 'build num +1', function() { 151 | var manifest = grunt.file.readJSON('./package.json'); 152 | 153 | var buildNum = grunt.config('buildNum') + 1;//parseInt(manifest.buildNum) + 1; 154 | 155 | manifest.buildNum = [ buildNum ].join(); 156 | 157 | console.log('cur build', [ manifest.versions, buildNum ].join('.')); 158 | 159 | grunt.file.write('./package.json', JSON.stringify(manifest)); 160 | }); 161 | 162 | 163 | grunt.registerTask('manifestCRX', 'update crx manifest', function() { 164 | var manifest = grunt.file.readJSON('./dist/iZhihu for Chrome/manifest.json'); 165 | manifest.version = grunt.config('version')// + '.' + manifest.version.split('.')[3]; 166 | grunt.file.write('./dist/iZhihu for Chrome/manifest.json', JSON.stringify(manifest)); 167 | }); 168 | 169 | grunt.registerTask('manifestXPI', 'update xpi manifest', function() { 170 | var manifest = grunt.file.readJSON('./dist/iZhihu for Firefox/package.json'); 171 | manifest.version = grunt.config('version'); 172 | grunt.file.write('./dist/iZhihu for Firefox/package.json', JSON.stringify(manifest)); 173 | }); 174 | 175 | grunt.registerTask('chrome', ['copy:toChrome', 'manifestCRX', 'string-replace:distChrome']); 176 | grunt.registerTask('firefox', ['copy:toFirefox1', 'copy:toFirefox2', 'manifestXPI']); 177 | grunt.registerTask('safari', ['copy:toSafari', 'string-replace:distSafari']); 178 | 179 | grunt.registerTask('buildall', ['default', 'chrome', 'firefox', 'safari']) 180 | 181 | grunt.registerTask('test', '', function(){// using this task to test code for grunt 182 | console.log(grunt.config('version')) 183 | }) 184 | 185 | return grunt; 186 | }; -------------------------------------------------------------------------------- /import/blue.css: -------------------------------------------------------------------------------- 1 | /* iCheck plugin Square skin, blue 2 | ----------------------------------- */ 3 | .icheckbox_square-blue, 4 | .iradio_square-blue { 5 | display: inline-block; 6 | *display: inline; 7 | vertical-align: middle; 8 | margin: 0; 9 | padding: 0; 10 | width: 22px; 11 | height: 22px; 12 | background: url(blue.png) no-repeat; 13 | border: none; 14 | cursor: pointer; 15 | } 16 | 17 | .icheckbox_square-blue { 18 | background-position: 0 0; 19 | } 20 | .icheckbox_square-blue.hover { 21 | background-position: -24px 0; 22 | } 23 | .icheckbox_square-blue.checked { 24 | background-position: -48px 0; 25 | } 26 | .icheckbox_square-blue.disabled { 27 | background-position: -72px 0; 28 | cursor: default; 29 | } 30 | .icheckbox_square-blue.checked.disabled { 31 | background-position: -96px 0; 32 | } 33 | 34 | .iradio_square-blue { 35 | background-position: -120px 0; 36 | } 37 | .iradio_square-blue.hover { 38 | background-position: -144px 0; 39 | } 40 | .iradio_square-blue.checked { 41 | background-position: -168px 0; 42 | } 43 | .iradio_square-blue.disabled { 44 | background-position: -192px 0; 45 | cursor: default; 46 | } 47 | .iradio_square-blue.checked.disabled { 48 | background-position: -216px 0; 49 | } 50 | 51 | /* Retina support */ 52 | @media only screen and (-webkit-min-device-pixel-ratio: 1.5), 53 | only screen and (-moz-min-device-pixel-ratio: 1.5), 54 | only screen and (-o-min-device-pixel-ratio: 3/2), 55 | only screen and (min-device-pixel-ratio: 1.5) { 56 | .icheckbox_square-blue, 57 | .iradio_square-blue { 58 | background-image: url(blue@2x.png); 59 | -webkit-background-size: 240px 24px; 60 | background-size: 240px 24px; 61 | } 62 | } -------------------------------------------------------------------------------- /import/blue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unogz/izhihu/f1efa7b0574723d1e04c682433ce303ed053edc4/import/blue.png -------------------------------------------------------------------------------- /import/blue@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unogz/izhihu/f1efa7b0574723d1e04c682433ce303ed053edc4/import/blue@2x.png -------------------------------------------------------------------------------- /import/icheck.min.js: -------------------------------------------------------------------------------- 1 | /*! iCheck v1.0.1 by Damir Sultanov, http://git.io/arlzeA, MIT Licensed */ 2 | (function(h){function F(a,b,d){var c=a[0],e=/er/.test(d)?m:/bl/.test(d)?s:l,f=d==H?{checked:c[l],disabled:c[s],indeterminate:"true"==a.attr(m)||"false"==a.attr(w)}:c[e];if(/^(ch|di|in)/.test(d)&&!f)D(a,e);else if(/^(un|en|de)/.test(d)&&f)t(a,e);else if(d==H)for(e in f)f[e]?D(a,e,!0):t(a,e,!0);else if(!b||"toggle"==d){if(!b)a[p]("ifClicked");f?c[n]!==u&&t(a,e):D(a,e)}}function D(a,b,d){var c=a[0],e=a.parent(),f=b==l,A=b==m,B=b==s,K=A?w:f?E:"enabled",p=k(a,K+x(c[n])),N=k(a,b+x(c[n]));if(!0!==c[b]){if(!d&& 3 | b==l&&c[n]==u&&c.name){var C=a.closest("form"),r='input[name="'+c.name+'"]',r=C.length?C.find(r):h(r);r.each(function(){this!==c&&h(this).data(q)&&t(h(this),b)})}A?(c[b]=!0,c[l]&&t(a,l,"force")):(d||(c[b]=!0),f&&c[m]&&t(a,m,!1));L(a,f,b,d)}c[s]&&k(a,y,!0)&&e.find("."+I).css(y,"default");e[v](N||k(a,b)||"");B?e.attr("aria-disabled","true"):e.attr("aria-checked",A?"mixed":"true");e[z](p||k(a,K)||"")}function t(a,b,d){var c=a[0],e=a.parent(),f=b==l,h=b==m,q=b==s,p=h?w:f?E:"enabled",t=k(a,p+x(c[n])), 4 | u=k(a,b+x(c[n]));if(!1!==c[b]){if(h||!d||"force"==d)c[b]=!1;L(a,f,p,d)}!c[s]&&k(a,y,!0)&&e.find("."+I).css(y,"pointer");e[z](u||k(a,b)||"");q?e.attr("aria-disabled","false"):e.attr("aria-checked","false");e[v](t||k(a,p)||"")}function M(a,b){if(a.data(q)){a.parent().html(a.attr("style",a.data(q).s||""));if(b)a[p](b);a.off(".i").unwrap();h(G+'[for="'+a[0].id+'"]').add(a.closest(G)).off(".i")}}function k(a,b,d){if(a.data(q))return a.data(q).o[b+(d?"":"Class")]}function x(a){return a.charAt(0).toUpperCase()+ 5 | a.slice(1)}function L(a,b,d,c){if(!c){if(b)a[p]("ifToggled");a[p]("ifChanged")[p]("if"+x(d))}}var q="iCheck",I=q+"-helper",u="radio",l="checked",E="un"+l,s="disabled",w="determinate",m="in"+w,H="update",n="type",v="addClass",z="removeClass",p="trigger",G="label",y="cursor",J=/ipad|iphone|ipod|android|blackberry|windows phone|opera mini|silk/i.test(navigator.userAgent);h.fn[q]=function(a,b){var d='input[type="checkbox"], input[type="'+u+'"]',c=h(),e=function(a){a.each(function(){var a=h(this);c=a.is(d)? 6 | c.add(a):c.add(a.find(d))})};if(/^(check|uncheck|toggle|indeterminate|determinate|disable|enable|update|destroy)$/i.test(a))return a=a.toLowerCase(),e(this),c.each(function(){var c=h(this);"destroy"==a?M(c,"ifDestroyed"):F(c,!0,a);h.isFunction(b)&&b()});if("object"!=typeof a&&a)return this;var f=h.extend({checkedClass:l,disabledClass:s,indeterminateClass:m,labelHover:!0,aria:!1},a),k=f.handle,B=f.hoverClass||"hover",x=f.focusClass||"focus",w=f.activeClass||"active",y=!!f.labelHover,C=f.labelHoverClass|| 7 | "hover",r=(""+f.increaseArea).replace("%","")|0;if("checkbox"==k||k==u)d='input[type="'+k+'"]';-50>r&&(r=-50);e(this);return c.each(function(){var a=h(this);M(a);var c=this,b=c.id,e=-r+"%",d=100+2*r+"%",d={position:"absolute",top:e,left:e,display:"block",width:d,height:d,margin:0,padding:0,background:"#fff",border:0,opacity:0},e=J?{position:"absolute",visibility:"hidden"}:r?d:{position:"absolute",opacity:0},k="checkbox"==c[n]?f.checkboxClass||"icheckbox":f.radioClass||"i"+u,m=h(G+'[for="'+b+'"]').add(a.closest(G)), 8 | A=!!f.aria,E=q+"-"+Math.random().toString(36).replace("0.",""),g='
")[p]("ifCreated").parent().append(f.insert);d=h('').css(d).appendTo(g);a.data(q,{o:f,s:a.attr("style")}).css(e);f.inheritClass&&g[v](c.className||"");f.inheritID&&b&&g.attr("id",q+"-"+b);"static"==g.css("position")&&g.css("position","relative");F(a,!0,H); 9 | if(m.length)m.on("click.i mouseover.i mouseout.i touchbegin.i touchend.i",function(b){var d=b[n],e=h(this);if(!c[s]){if("click"==d){if(h(b.target).is("a"))return;F(a,!1,!0)}else y&&(/ut|nd/.test(d)?(g[z](B),e[z](C)):(g[v](B),e[v](C)));if(J)b.stopPropagation();else return!1}});a.on("click.i focus.i blur.i keyup.i keydown.i keypress.i",function(b){var d=b[n];b=b.keyCode;if("click"==d)return!1;if("keydown"==d&&32==b)return c[n]==u&&c[l]||(c[l]?t(a,l):D(a,l)),!1;if("keyup"==d&&c[n]==u)!c[l]&&D(a,l);else if(/us|ur/.test(d))g["blur"== 10 | d?z:v](x)});d.on("click mousedown mouseup mouseover mouseout touchbegin.i touchend.i",function(b){var d=b[n],e=/wn|up/.test(d)?w:B;if(!c[s]){if("click"==d)F(a,!1,!0);else{if(/wn|er|in/.test(d))g[v](e);else g[z](e+" "+w);if(m.length&&y&&e==B)m[/ut|nd/.test(d)?z:v](C)}if(J)b.stopPropagation();else return!1}})})}})(window.jQuery||window.Zepto); 11 | -------------------------------------------------------------------------------- /import/purl.js: -------------------------------------------------------------------------------- 1 | /* 2 | * JQuery URL Parser plugin, v2.2.1 3 | * Developed and maintanined by Mark Perkins, mark@allmarkedup.com 4 | * Source repository: https://github.com/allmarkedup/jQuery-URL-Parser 5 | * Licensed under an MIT-style license. See https://github.com/allmarkedup/jQuery-URL-Parser/blob/master/LICENSE for details. 6 | */ 7 | 8 | ;(function(factory) { 9 | if (typeof define === 'function' && define.amd) { 10 | // AMD available; use anonymous module 11 | if ( typeof jQuery !== 'undefined' ) { 12 | define(['jquery'], factory); 13 | } else { 14 | define([], factory); 15 | } 16 | } else { 17 | // No AMD available; mutate global vars 18 | if ( typeof jQuery !== 'undefined' ) { 19 | factory(jQuery); 20 | } else { 21 | factory(); 22 | } 23 | } 24 | })(function($, undefined) { 25 | 26 | var tag2attr = { 27 | a : 'href', 28 | img : 'src', 29 | form : 'action', 30 | base : 'href', 31 | script : 'src', 32 | iframe : 'src', 33 | link : 'href' 34 | }, 35 | 36 | key = ['source', 'protocol', 'authority', 'userInfo', 'user', 'password', 'host', 'port', 'relative', 'path', 'directory', 'file', 'query', 'fragment'], // keys available to query 37 | 38 | aliases = { 'anchor' : 'fragment' }, // aliases for backwards compatability 39 | 40 | parser = { 41 | strict : /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/, //less intuitive, more accurate to the specs 42 | loose : /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/ // more intuitive, fails on relative paths and deviates from specs 43 | }, 44 | 45 | toString = Object.prototype.toString, 46 | 47 | isint = /^[0-9]+$/; 48 | 49 | function parseUri( url, strictMode ) { 50 | var str = decodeURI( url ), 51 | res = parser[ strictMode || false ? 'strict' : 'loose' ].exec( str ), 52 | uri = { attr : {}, param : {}, seg : {} }, 53 | i = 14; 54 | 55 | while ( i-- ) { 56 | uri.attr[ key[i] ] = res[i] || ''; 57 | } 58 | 59 | // build query and fragment parameters 60 | uri.param['query'] = parseString(uri.attr['query']); 61 | uri.param['fragment'] = parseString(uri.attr['fragment']); 62 | 63 | // split path and fragement into segments 64 | uri.seg['path'] = uri.attr.path.replace(/^\/+|\/+$/g,'').split('/'); 65 | uri.seg['fragment'] = uri.attr.fragment.replace(/^\/+|\/+$/g,'').split('/'); 66 | 67 | // compile a 'base' domain attribute 68 | uri.attr['base'] = uri.attr.host ? (uri.attr.protocol ? uri.attr.protocol+'://'+uri.attr.host : uri.attr.host) + (uri.attr.port ? ':'+uri.attr.port : '') : ''; 69 | 70 | return uri; 71 | }; 72 | 73 | function getAttrName( elm ) { 74 | var tn = elm.tagName; 75 | if ( typeof tn !== 'undefined' ) return tag2attr[tn.toLowerCase()]; 76 | return tn; 77 | } 78 | 79 | function promote(parent, key) { 80 | if (parent[key].length == 0) return parent[key] = {}; 81 | var t = {}; 82 | for (var i in parent[key]) t[i] = parent[key][i]; 83 | parent[key] = t; 84 | return t; 85 | } 86 | 87 | function parse(parts, parent, key, val) { 88 | var part = parts.shift(); 89 | if (!part) { 90 | if (isArray(parent[key])) { 91 | parent[key].push(val); 92 | } else if ('object' == typeof parent[key]) { 93 | parent[key] = val; 94 | } else if ('undefined' == typeof parent[key]) { 95 | parent[key] = val; 96 | } else { 97 | parent[key] = [parent[key], val]; 98 | } 99 | } else { 100 | var obj = parent[key] = parent[key] || []; 101 | if (']' == part) { 102 | if (isArray(obj)) { 103 | if ('' != val) obj.push(val); 104 | } else if ('object' == typeof obj) { 105 | obj[keys(obj).length] = val; 106 | } else { 107 | obj = parent[key] = [parent[key], val]; 108 | } 109 | } else if (~part.indexOf(']')) { 110 | part = part.substr(0, part.length - 1); 111 | if (!isint.test(part) && isArray(obj)) obj = promote(parent, key); 112 | parse(parts, obj, part, val); 113 | // key 114 | } else { 115 | if (!isint.test(part) && isArray(obj)) obj = promote(parent, key); 116 | parse(parts, obj, part, val); 117 | } 118 | } 119 | } 120 | 121 | function merge(parent, key, val) { 122 | if (~key.indexOf(']')) { 123 | var parts = key.split('['), 124 | len = parts.length, 125 | last = len - 1; 126 | parse(parts, parent, 'base', val); 127 | } else { 128 | if (!isint.test(key) && isArray(parent.base)) { 129 | var t = {}; 130 | for (var k in parent.base) t[k] = parent.base[k]; 131 | parent.base = t; 132 | } 133 | set(parent.base, key, val); 134 | } 135 | return parent; 136 | } 137 | 138 | function parseString(str) { 139 | return reduce(String(str).split(/&|;/), function(ret, pair) { 140 | try { 141 | pair = decodeURIComponent(pair.replace(/\+/g, ' ')); 142 | } catch(e) { 143 | // ignore 144 | } 145 | var eql = pair.indexOf('='), 146 | brace = lastBraceInKey(pair), 147 | key = pair.substr(0, brace || eql), 148 | val = pair.substr(brace || eql, pair.length), 149 | val = val.substr(val.indexOf('=') + 1, val.length); 150 | 151 | if ('' == key) key = pair, val = ''; 152 | 153 | return merge(ret, key, val); 154 | }, { base: {} }).base; 155 | } 156 | 157 | function set(obj, key, val) { 158 | var v = obj[key]; 159 | if (undefined === v) { 160 | obj[key] = val; 161 | } else if (isArray(v)) { 162 | v.push(val); 163 | } else { 164 | obj[key] = [v, val]; 165 | } 166 | } 167 | 168 | function lastBraceInKey(str) { 169 | var len = str.length, 170 | brace, c; 171 | for (var i = 0; i < len; ++i) { 172 | c = str[i]; 173 | if (']' == c) brace = false; 174 | if ('[' == c) brace = true; 175 | if ('=' == c && !brace) return i; 176 | } 177 | } 178 | 179 | function reduce(obj, accumulator){ 180 | var i = 0, 181 | l = obj.length >> 0, 182 | curr = arguments[2]; 183 | while (i < l) { 184 | if (i in obj) curr = accumulator.call(undefined, curr, obj[i], i, obj); 185 | ++i; 186 | } 187 | return curr; 188 | } 189 | 190 | function isArray(vArg) { 191 | return Object.prototype.toString.call(vArg) === "[object Array]"; 192 | } 193 | 194 | function keys(obj) { 195 | var keys = []; 196 | for ( prop in obj ) { 197 | if ( obj.hasOwnProperty(prop) ) keys.push(prop); 198 | } 199 | return keys; 200 | } 201 | 202 | function purl( url, strictMode ) { 203 | if ( arguments.length === 1 && url === true ) { 204 | strictMode = true; 205 | url = undefined; 206 | } 207 | strictMode = strictMode || false; 208 | url = url || window.location.toString(); 209 | 210 | return { 211 | 212 | data : parseUri(url, strictMode), 213 | 214 | // get various attributes from the URI 215 | attr : function( attr ) { 216 | attr = aliases[attr] || attr; 217 | return typeof attr !== 'undefined' ? this.data.attr[attr] : this.data.attr; 218 | }, 219 | 220 | // return query string parameters 221 | param : function( param ) { 222 | return typeof param !== 'undefined' ? this.data.param.query[param] : this.data.param.query; 223 | }, 224 | 225 | // return fragment parameters 226 | fparam : function( param ) { 227 | return typeof param !== 'undefined' ? this.data.param.fragment[param] : this.data.param.fragment; 228 | }, 229 | 230 | // return path segments 231 | segment : function( seg ) { 232 | if ( typeof seg === 'undefined' ) { 233 | return this.data.seg.path; 234 | } else { 235 | seg = seg < 0 ? this.data.seg.path.length + seg : seg - 1; // negative segments count from the end 236 | return this.data.seg.path[seg]; 237 | } 238 | }, 239 | 240 | // return fragment segments 241 | fsegment : function( seg ) { 242 | if ( typeof seg === 'undefined' ) { 243 | return this.data.seg.fragment; 244 | } else { 245 | seg = seg < 0 ? this.data.seg.fragment.length + seg : seg - 1; // negative segments count from the end 246 | return this.data.seg.fragment[seg]; 247 | } 248 | } 249 | 250 | }; 251 | 252 | }; 253 | 254 | if ( typeof $ !== 'undefined' ) { 255 | 256 | $.fn.url = function( strictMode ) { 257 | var url = ''; 258 | if ( this.length ) { 259 | url = $(this).attr( getAttrName(this[0]) ) || ''; 260 | } 261 | return purl( url, strictMode ); 262 | }; 263 | 264 | $.url = purl; 265 | 266 | } else { 267 | window.purl = purl; 268 | } 269 | 270 | }); 271 | 272 | -------------------------------------------------------------------------------- /import/underscore-min.js: -------------------------------------------------------------------------------- 1 | (function(){var n=this,t=n._,r={},e=Array.prototype,u=Object.prototype,i=Function.prototype,a=e.push,o=e.slice,c=e.concat,l=u.toString,f=u.hasOwnProperty,s=e.forEach,p=e.map,h=e.reduce,v=e.reduceRight,d=e.filter,g=e.every,m=e.some,y=e.indexOf,b=e.lastIndexOf,x=Array.isArray,_=Object.keys,j=i.bind,w=function(n){return n instanceof w?n:this instanceof w?(this._wrapped=n,void 0):new w(n)};"undefined"!=typeof exports?("undefined"!=typeof module&&module.exports&&(exports=module.exports=w),exports._=w):n._=w,w.VERSION="1.4.4";var A=w.each=w.forEach=function(n,t,e){if(null!=n)if(s&&n.forEach===s)n.forEach(t,e);else if(n.length===+n.length){for(var u=0,i=n.length;i>u;u++)if(t.call(e,n[u],u,n)===r)return}else for(var a in n)if(w.has(n,a)&&t.call(e,n[a],a,n)===r)return};w.map=w.collect=function(n,t,r){var e=[];return null==n?e:p&&n.map===p?n.map(t,r):(A(n,function(n,u,i){e[e.length]=t.call(r,n,u,i)}),e)};var O="Reduce of empty array with no initial value";w.reduce=w.foldl=w.inject=function(n,t,r,e){var u=arguments.length>2;if(null==n&&(n=[]),h&&n.reduce===h)return e&&(t=w.bind(t,e)),u?n.reduce(t,r):n.reduce(t);if(A(n,function(n,i,a){u?r=t.call(e,r,n,i,a):(r=n,u=!0)}),!u)throw new TypeError(O);return r},w.reduceRight=w.foldr=function(n,t,r,e){var u=arguments.length>2;if(null==n&&(n=[]),v&&n.reduceRight===v)return e&&(t=w.bind(t,e)),u?n.reduceRight(t,r):n.reduceRight(t);var i=n.length;if(i!==+i){var a=w.keys(n);i=a.length}if(A(n,function(o,c,l){c=a?a[--i]:--i,u?r=t.call(e,r,n[c],c,l):(r=n[c],u=!0)}),!u)throw new TypeError(O);return r},w.find=w.detect=function(n,t,r){var e;return E(n,function(n,u,i){return t.call(r,n,u,i)?(e=n,!0):void 0}),e},w.filter=w.select=function(n,t,r){var e=[];return null==n?e:d&&n.filter===d?n.filter(t,r):(A(n,function(n,u,i){t.call(r,n,u,i)&&(e[e.length]=n)}),e)},w.reject=function(n,t,r){return w.filter(n,function(n,e,u){return!t.call(r,n,e,u)},r)},w.every=w.all=function(n,t,e){t||(t=w.identity);var u=!0;return null==n?u:g&&n.every===g?n.every(t,e):(A(n,function(n,i,a){return(u=u&&t.call(e,n,i,a))?void 0:r}),!!u)};var E=w.some=w.any=function(n,t,e){t||(t=w.identity);var u=!1;return null==n?u:m&&n.some===m?n.some(t,e):(A(n,function(n,i,a){return u||(u=t.call(e,n,i,a))?r:void 0}),!!u)};w.contains=w.include=function(n,t){return null==n?!1:y&&n.indexOf===y?n.indexOf(t)!=-1:E(n,function(n){return n===t})},w.invoke=function(n,t){var r=o.call(arguments,2),e=w.isFunction(t);return w.map(n,function(n){return(e?t:n[t]).apply(n,r)})},w.pluck=function(n,t){return w.map(n,function(n){return n[t]})},w.where=function(n,t,r){return w.isEmpty(t)?r?null:[]:w[r?"find":"filter"](n,function(n){for(var r in t)if(t[r]!==n[r])return!1;return!0})},w.findWhere=function(n,t){return w.where(n,t,!0)},w.max=function(n,t,r){if(!t&&w.isArray(n)&&n[0]===+n[0]&&65535>n.length)return Math.max.apply(Math,n);if(!t&&w.isEmpty(n))return-1/0;var e={computed:-1/0,value:-1/0};return A(n,function(n,u,i){var a=t?t.call(r,n,u,i):n;a>=e.computed&&(e={value:n,computed:a})}),e.value},w.min=function(n,t,r){if(!t&&w.isArray(n)&&n[0]===+n[0]&&65535>n.length)return Math.min.apply(Math,n);if(!t&&w.isEmpty(n))return 1/0;var e={computed:1/0,value:1/0};return A(n,function(n,u,i){var a=t?t.call(r,n,u,i):n;e.computed>a&&(e={value:n,computed:a})}),e.value},w.shuffle=function(n){var t,r=0,e=[];return A(n,function(n){t=w.random(r++),e[r-1]=e[t],e[t]=n}),e};var k=function(n){return w.isFunction(n)?n:function(t){return t[n]}};w.sortBy=function(n,t,r){var e=k(t);return w.pluck(w.map(n,function(n,t,u){return{value:n,index:t,criteria:e.call(r,n,t,u)}}).sort(function(n,t){var r=n.criteria,e=t.criteria;if(r!==e){if(r>e||r===void 0)return 1;if(e>r||e===void 0)return-1}return n.indexi;){var o=i+a>>>1;u>r.call(e,n[o])?i=o+1:a=o}return i},w.toArray=function(n){return n?w.isArray(n)?o.call(n):n.length===+n.length?w.map(n,w.identity):w.values(n):[]},w.size=function(n){return null==n?0:n.length===+n.length?n.length:w.keys(n).length},w.first=w.head=w.take=function(n,t,r){return null==n?void 0:null==t||r?n[0]:o.call(n,0,t)},w.initial=function(n,t,r){return o.call(n,0,n.length-(null==t||r?1:t))},w.last=function(n,t,r){return null==n?void 0:null==t||r?n[n.length-1]:o.call(n,Math.max(n.length-t,0))},w.rest=w.tail=w.drop=function(n,t,r){return o.call(n,null==t||r?1:t)},w.compact=function(n){return w.filter(n,w.identity)};var R=function(n,t,r){return A(n,function(n){w.isArray(n)?t?a.apply(r,n):R(n,t,r):r.push(n)}),r};w.flatten=function(n,t){return R(n,t,[])},w.without=function(n){return w.difference(n,o.call(arguments,1))},w.uniq=w.unique=function(n,t,r,e){w.isFunction(t)&&(e=r,r=t,t=!1);var u=r?w.map(n,r,e):n,i=[],a=[];return A(u,function(r,e){(t?e&&a[a.length-1]===r:w.contains(a,r))||(a.push(r),i.push(n[e]))}),i},w.union=function(){return w.uniq(c.apply(e,arguments))},w.intersection=function(n){var t=o.call(arguments,1);return w.filter(w.uniq(n),function(n){return w.every(t,function(t){return w.indexOf(t,n)>=0})})},w.difference=function(n){var t=c.apply(e,o.call(arguments,1));return w.filter(n,function(n){return!w.contains(t,n)})},w.zip=function(){for(var n=o.call(arguments),t=w.max(w.pluck(n,"length")),r=Array(t),e=0;t>e;e++)r[e]=w.pluck(n,""+e);return r},w.object=function(n,t){if(null==n)return{};for(var r={},e=0,u=n.length;u>e;e++)t?r[n[e]]=t[e]:r[n[e][0]]=n[e][1];return r},w.indexOf=function(n,t,r){if(null==n)return-1;var e=0,u=n.length;if(r){if("number"!=typeof r)return e=w.sortedIndex(n,t),n[e]===t?e:-1;e=0>r?Math.max(0,u+r):r}if(y&&n.indexOf===y)return n.indexOf(t,r);for(;u>e;e++)if(n[e]===t)return e;return-1},w.lastIndexOf=function(n,t,r){if(null==n)return-1;var e=null!=r;if(b&&n.lastIndexOf===b)return e?n.lastIndexOf(t,r):n.lastIndexOf(t);for(var u=e?r:n.length;u--;)if(n[u]===t)return u;return-1},w.range=function(n,t,r){1>=arguments.length&&(t=n||0,n=0),r=arguments[2]||1;for(var e=Math.max(Math.ceil((t-n)/r),0),u=0,i=Array(e);e>u;)i[u++]=n,n+=r;return i},w.bind=function(n,t){if(n.bind===j&&j)return j.apply(n,o.call(arguments,1));var r=o.call(arguments,2);return function(){return n.apply(t,r.concat(o.call(arguments)))}},w.partial=function(n){var t=o.call(arguments,1);return function(){return n.apply(this,t.concat(o.call(arguments)))}},w.bindAll=function(n){var t=o.call(arguments,1);return 0===t.length&&(t=w.functions(n)),A(t,function(t){n[t]=w.bind(n[t],n)}),n},w.memoize=function(n,t){var r={};return t||(t=w.identity),function(){var e=t.apply(this,arguments);return w.has(r,e)?r[e]:r[e]=n.apply(this,arguments)}},w.delay=function(n,t){var r=o.call(arguments,2);return setTimeout(function(){return n.apply(null,r)},t)},w.defer=function(n){return w.delay.apply(w,[n,1].concat(o.call(arguments,1)))},w.throttle=function(n,t){var r,e,u,i,a=0,o=function(){a=new Date,u=null,i=n.apply(r,e)};return function(){var c=new Date,l=t-(c-a);return r=this,e=arguments,0>=l?(clearTimeout(u),u=null,a=c,i=n.apply(r,e)):u||(u=setTimeout(o,l)),i}},w.debounce=function(n,t,r){var e,u;return function(){var i=this,a=arguments,o=function(){e=null,r||(u=n.apply(i,a))},c=r&&!e;return clearTimeout(e),e=setTimeout(o,t),c&&(u=n.apply(i,a)),u}},w.once=function(n){var t,r=!1;return function(){return r?t:(r=!0,t=n.apply(this,arguments),n=null,t)}},w.wrap=function(n,t){return function(){var r=[n];return a.apply(r,arguments),t.apply(this,r)}},w.compose=function(){var n=arguments;return function(){for(var t=arguments,r=n.length-1;r>=0;r--)t=[n[r].apply(this,t)];return t[0]}},w.after=function(n,t){return 0>=n?t():function(){return 1>--n?t.apply(this,arguments):void 0}},w.keys=_||function(n){if(n!==Object(n))throw new TypeError("Invalid object");var t=[];for(var r in n)w.has(n,r)&&(t[t.length]=r);return t},w.values=function(n){var t=[];for(var r in n)w.has(n,r)&&t.push(n[r]);return t},w.pairs=function(n){var t=[];for(var r in n)w.has(n,r)&&t.push([r,n[r]]);return t},w.invert=function(n){var t={};for(var r in n)w.has(n,r)&&(t[n[r]]=r);return t},w.functions=w.methods=function(n){var t=[];for(var r in n)w.isFunction(n[r])&&t.push(r);return t.sort()},w.extend=function(n){return A(o.call(arguments,1),function(t){if(t)for(var r in t)n[r]=t[r]}),n},w.pick=function(n){var t={},r=c.apply(e,o.call(arguments,1));return A(r,function(r){r in n&&(t[r]=n[r])}),t},w.omit=function(n){var t={},r=c.apply(e,o.call(arguments,1));for(var u in n)w.contains(r,u)||(t[u]=n[u]);return t},w.defaults=function(n){return A(o.call(arguments,1),function(t){if(t)for(var r in t)null==n[r]&&(n[r]=t[r])}),n},w.clone=function(n){return w.isObject(n)?w.isArray(n)?n.slice():w.extend({},n):n},w.tap=function(n,t){return t(n),n};var I=function(n,t,r,e){if(n===t)return 0!==n||1/n==1/t;if(null==n||null==t)return n===t;n instanceof w&&(n=n._wrapped),t instanceof w&&(t=t._wrapped);var u=l.call(n);if(u!=l.call(t))return!1;switch(u){case"[object String]":return n==t+"";case"[object Number]":return n!=+n?t!=+t:0==n?1/n==1/t:n==+t;case"[object Date]":case"[object Boolean]":return+n==+t;case"[object RegExp]":return n.source==t.source&&n.global==t.global&&n.multiline==t.multiline&&n.ignoreCase==t.ignoreCase}if("object"!=typeof n||"object"!=typeof t)return!1;for(var i=r.length;i--;)if(r[i]==n)return e[i]==t;r.push(n),e.push(t);var a=0,o=!0;if("[object Array]"==u){if(a=n.length,o=a==t.length)for(;a--&&(o=I(n[a],t[a],r,e)););}else{var c=n.constructor,f=t.constructor;if(c!==f&&!(w.isFunction(c)&&c instanceof c&&w.isFunction(f)&&f instanceof f))return!1;for(var s in n)if(w.has(n,s)&&(a++,!(o=w.has(t,s)&&I(n[s],t[s],r,e))))break;if(o){for(s in t)if(w.has(t,s)&&!a--)break;o=!a}}return r.pop(),e.pop(),o};w.isEqual=function(n,t){return I(n,t,[],[])},w.isEmpty=function(n){if(null==n)return!0;if(w.isArray(n)||w.isString(n))return 0===n.length;for(var t in n)if(w.has(n,t))return!1;return!0},w.isElement=function(n){return!(!n||1!==n.nodeType)},w.isArray=x||function(n){return"[object Array]"==l.call(n)},w.isObject=function(n){return n===Object(n)},A(["Arguments","Function","String","Number","Date","RegExp"],function(n){w["is"+n]=function(t){return l.call(t)=="[object "+n+"]"}}),w.isArguments(arguments)||(w.isArguments=function(n){return!(!n||!w.has(n,"callee"))}),"function"!=typeof/./&&(w.isFunction=function(n){return"function"==typeof n}),w.isFinite=function(n){return isFinite(n)&&!isNaN(parseFloat(n))},w.isNaN=function(n){return w.isNumber(n)&&n!=+n},w.isBoolean=function(n){return n===!0||n===!1||"[object Boolean]"==l.call(n)},w.isNull=function(n){return null===n},w.isUndefined=function(n){return n===void 0},w.has=function(n,t){return f.call(n,t)},w.noConflict=function(){return n._=t,this},w.identity=function(n){return n},w.times=function(n,t,r){for(var e=Array(n),u=0;n>u;u++)e[u]=t.call(r,u);return e},w.random=function(n,t){return null==t&&(t=n,n=0),n+Math.floor(Math.random()*(t-n+1))};var M={escape:{"&":"&","<":"<",">":">",'"':""","'":"'","/":"/"}};M.unescape=w.invert(M.escape);var S={escape:RegExp("["+w.keys(M.escape).join("")+"]","g"),unescape:RegExp("("+w.keys(M.unescape).join("|")+")","g")};w.each(["escape","unescape"],function(n){w[n]=function(t){return null==t?"":(""+t).replace(S[n],function(t){return M[n][t]})}}),w.result=function(n,t){if(null==n)return null;var r=n[t];return w.isFunction(r)?r.call(n):r},w.mixin=function(n){A(w.functions(n),function(t){var r=w[t]=n[t];w.prototype[t]=function(){var n=[this._wrapped];return a.apply(n,arguments),D.call(this,r.apply(w,n))}})};var N=0;w.uniqueId=function(n){var t=++N+"";return n?n+t:t},w.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var T=/(.)^/,q={"'":"'","\\":"\\","\r":"r","\n":"n"," ":"t","\u2028":"u2028","\u2029":"u2029"},B=/\\|'|\r|\n|\t|\u2028|\u2029/g;w.template=function(n,t,r){var e;r=w.defaults({},r,w.templateSettings);var u=RegExp([(r.escape||T).source,(r.interpolate||T).source,(r.evaluate||T).source].join("|")+"|$","g"),i=0,a="__p+='";n.replace(u,function(t,r,e,u,o){return a+=n.slice(i,o).replace(B,function(n){return"\\"+q[n]}),r&&(a+="'+\n((__t=("+r+"))==null?'':_.escape(__t))+\n'"),e&&(a+="'+\n((__t=("+e+"))==null?'':__t)+\n'"),u&&(a+="';\n"+u+"\n__p+='"),i=o+t.length,t}),a+="';\n",r.variable||(a="with(obj||{}){\n"+a+"}\n"),a="var __t,__p='',__j=Array.prototype.join,"+"print=function(){__p+=__j.call(arguments,'');};\n"+a+"return __p;\n";try{e=Function(r.variable||"obj","_",a)}catch(o){throw o.source=a,o}if(t)return e(t,w);var c=function(n){return e.call(this,n,w)};return c.source="function("+(r.variable||"obj")+"){\n"+a+"}",c},w.chain=function(n){return w(n).chain()};var D=function(n){return this._chain?w(n).chain():n};w.mixin(w),A(["pop","push","reverse","shift","sort","splice","unshift"],function(n){var t=e[n];w.prototype[n]=function(){var r=this._wrapped;return t.apply(r,arguments),"shift"!=n&&"splice"!=n||0!==r.length||delete r[0],D.call(this,r)}}),A(["concat","join","slice"],function(n){var t=e[n];w.prototype[n]=function(){return D.call(this,t.apply(this._wrapped,arguments))}}),w.extend(w.prototype,{chain:function(){return this._chain=!0,this},value:function(){return this._wrapped}})}).call(this); -------------------------------------------------------------------------------- /misc/crx-config/icon128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unogz/izhihu/f1efa7b0574723d1e04c682433ce303ed053edc4/misc/crx-config/icon128.png -------------------------------------------------------------------------------- /misc/crx-config/icon16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unogz/izhihu/f1efa7b0574723d1e04c682433ce303ed053edc4/misc/crx-config/icon16.png -------------------------------------------------------------------------------- /misc/crx-config/icon48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unogz/izhihu/f1efa7b0574723d1e04c682433ce303ed053edc4/misc/crx-config/icon48.png -------------------------------------------------------------------------------- /misc/crx-config/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "manifest_version":2, 3 | "converted_from_user_script":true, 4 | "name":"iZhihu", 5 | "description":"", 6 | "permissions":[ 7 | "http://*.zhihu.com/", 8 | "https://*.zhihu.com/", 9 | "http://ilovezhihu.duapp.com/" 10 | ], 11 | "content_scripts":[ 12 | { 13 | "run_at":"document_end", 14 | "exclude_globs":[], 15 | "include_globs":["*"], 16 | "matches":["http://www.zhihu.com/*","https://www.zhihu.com/*"], 17 | "css": ["blue.css"], 18 | "js":["jquery-1.8.2.min.js","jquery-ui.min.js","icheck.min.js","purl.js","underscore-min.js","izhihu.js"] 19 | } 20 | ], 21 | "web_accessible_resources": ["/*.png","/*.css","*.js"] 22 | } -------------------------------------------------------------------------------- /misc/ext-config/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Builder Version 6 | 9537.76.4 7 | CFBundleDisplayName 8 | iZhihu - 我爱知乎 9 | CFBundleIdentifier 10 | com.unogz.izhihu 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleShortVersionString 14 | [version] 15 | CFBundleVersion 16 | 1 17 | Chrome 18 | 19 | Content 20 | 21 | Scripts 22 | 23 | Start 24 | 25 | jquery-1.8.2.min.js 26 | jquery-ui.min.js 27 | icheck.min.js 28 | purl.js 29 | underscore-min.js 30 | 31 | End 32 | 33 | izhihu.js 34 | 35 | 36 | Stylesheets 37 | 38 | blue.css 39 | 40 | 41 | ExtensionInfoDictionaryVersion 42 | 1.0 43 | Permissions 44 | 45 | Website Access 46 | 47 | Allowed Domains 48 | 49 | *.zhihu.com 50 | ilovezhihu.duapp.com 51 | 52 | Include Secure Pages 53 | 54 | Level 55 | Some 56 | 57 | 58 | Update Manifest URL 59 | http://izhihu.unogz.com/safari/Info.plist 60 | Website 61 | http://zhuanlan.zhihu.com/izhihu 62 | 63 | 64 | -------------------------------------------------------------------------------- /misc/ext-config/Settings.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /misc/ext-config/icon-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unogz/izhihu/f1efa7b0574723d1e04c682433ce303ed053edc4/misc/ext-config/icon-128.png -------------------------------------------------------------------------------- /misc/ext-config/icon-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unogz/izhihu/f1efa7b0574723d1e04c682433ce303ed053edc4/misc/ext-config/icon-48.png -------------------------------------------------------------------------------- /misc/ext-config/icon-64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unogz/izhihu/f1efa7b0574723d1e04c682433ce303ed053edc4/misc/ext-config/icon-64.png -------------------------------------------------------------------------------- /misc/xpi-config/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unogz/izhihu/f1efa7b0574723d1e04c682433ce303ed053edc4/misc/xpi-config/icon.png -------------------------------------------------------------------------------- /misc/xpi-config/icon64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unogz/izhihu/f1efa7b0574723d1e04c682433ce303ed053edc4/misc/xpi-config/icon64.png -------------------------------------------------------------------------------- /misc/xpi-config/lib/main.js: -------------------------------------------------------------------------------- 1 | var data = require("sdk/self").data; 2 | var pageMod = require("sdk/page-mod"); 3 | pageMod.PageMod({ 4 | include: "*.zhihu.com", 5 | contentStyleFile: data.url("blue.css"), 6 | contentScriptWhen: 'ready', 7 | contentScriptFile: [data.url("jquery-1.8.2.min.js"),data.url("jquery-ui.min.js"),data.url("icheck.min.js"),data.url("purl.js"),data.url("underscore-min.js"),data.url("izhihu.js")] 8 | }); 9 | -------------------------------------------------------------------------------- /misc/xpi-config/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name":"izhihu", 3 | "title":"iZhihu", 4 | "id":"jid1-Q3Oc7rhwyTCWhA@jetpack", 5 | "description":"知乎插件", 6 | "author":"钢盅郭子", 7 | "license":"MPL 2.0", 8 | "permissions":{ 9 | "cross-domain-content":[ 10 | "http://*.zhihu.com/", 11 | "http://ilovezhihu.duapp.com/" 12 | ] 13 | }, 14 | "main": "lib/main.js", 15 | "engines": { 16 | "firefox": ">=38.0a1", 17 | "fennec": ">=38.0a1" 18 | }, 19 | "keywords": [ 20 | "jetpack" 21 | ], 22 | "homepage":"http://zhuanlan.zhihu.com/izhihu" 23 | } -------------------------------------------------------------------------------- /misc/xpi-config/test/test-main.js: -------------------------------------------------------------------------------- 1 | var main = require("./main"); 2 | 3 | exports["test main"] = function(assert) { 4 | assert.pass("Unit test running!"); 5 | }; 6 | 7 | exports["test main async"] = function(assert, done) { 8 | assert.pass("async Unit test running!"); 9 | done(); 10 | }; 11 | 12 | require("sdk/test").run(exports); 13 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | {"name":"izhihu","version":"2.13.1","buildNum":"532","license":"MIT","devDependencies":{"grunt":"*","grunt-contrib-concat":"*","grunt-contrib-uglify":"*","grunt-contrib-watch":"*","grunt-contrib-copy":"*","grunt-contrib-clean":"*","grunt-string-replace":"*"}} -------------------------------------------------------------------------------- /src/begin.js: -------------------------------------------------------------------------------- 1 | var version='2.13.1'; 2 | var updateDate='2015-12-2'; 3 | 4 | if ( typeof unsafeWindow === "undefined") { 5 | unsafeWindow = ( function () { 6 | var dummyElem = document.createElement('p'); 7 | dummyElem.onclick=function(){return window;}; 8 | return dummyElem.onclick (); 9 | } ) (); 10 | } 11 | 12 | //主入口 13 | //$(function main(){ 14 | 15 | -------------------------------------------------------------------------------- /src/end.js: -------------------------------------------------------------------------------- 1 | var firstRun = parseInt(utils.getValue('izh_fr','1')); 2 | 3 | function _FRshow(){ 4 | if(firstRun>0 && document.domain=='zhihu.com'){ 5 | var tboxleft=0; 6 | var accitem1= $('#zh-top-inner div.top-nav-profile .zu-top-nav-userinfo'); 7 | if(accitem1.length>0){ 8 | tboxleft = accitem1.offset().left; 9 | } 10 | if(tboxleft>0){ 11 | $('
', { id: 'iZhihu_tbox', 'class': 't_frshow' }).appendTo('body.zhi').hide() 12 | .append($('
', { 'class': 't_txtshow t_tbox' }) 13 | .append('感谢使用') 14 | .append($('').text('iZhihu')) 15 | .append($('
')) 16 | .append('您可通过菜单【iZhihu】对功能进行设置') 17 | .append($('
')) 18 | .append($('') 19 | .append($('')) 20 | ) 21 | ); 22 | $('#iZhihu_tbox').css('left',tboxleft-100).show().mouseenter(function(){ 23 | utils.setValue('izh_fr','0'); 24 | //_Menu(); 25 | $(this).remove(); 26 | }); 27 | } 28 | } 29 | } 30 | 31 | setTimeout(function(){ 32 | _FRshow(); 33 | },1000); 34 | 35 | 36 | console.log('iZhihu '+version+' started.'); 37 | //console.log(window.iZhihu); 38 | //console.log((new Date()).getTime()); 39 | //}); 40 | -------------------------------------------------------------------------------- /src/izhihu.js: -------------------------------------------------------------------------------- 1 | //console.log((new Date()).getTime()); 2 | 3 | var $ = window.$; 4 | var _ = this._; 5 | var purl = window.purl||$.url; 6 | 7 | //使用CasperJS的模拟用户操作: http://casperjs.org/api.html#client-utils 8 | //var client = window.create(); 9 | 10 | var url = purl(); 11 | var page = url.segment(1); 12 | 13 | var pageIs={} 14 | , $win=$(window) 15 | , _doc=window.document 16 | , $body=$(_doc.body) 17 | , _path=window.frameElement?window.frameElement.src.replace(/https?:\/\/www.zhihu.com/,''):url.data.attr['path'] 18 | , css='' 19 | , $h=$('head') 20 | , $s=$('