├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── _travis ├── build.sh └── deploy-gh-pages.sh ├── app ├── css │ ├── style.css │ ├── style.css.map │ └── style.scss ├── index.html ├── js │ ├── config │ │ ├── reloadConfig.js │ │ └── userData.js │ ├── github │ │ ├── builder-util.js │ │ ├── extend-node-github.js │ │ ├── github-client.js │ │ ├── parse-event-body.js │ │ └── response-builder.js │ ├── index.js │ ├── main │ │ ├── commentHeaderViewController.js │ │ ├── frameController.js │ │ ├── inputFocusController.js │ │ ├── listViewController.js │ │ ├── mainController.js │ │ └── scrollController.js │ ├── notification │ │ ├── icon.png │ │ └── notification.js │ └── typings │ │ ├── ReceivedEvents.json │ │ ├── github-event.js │ │ └── receivedEvents.d.ts ├── menu │ └── menu.js ├── node-webkit │ └── workaround.js └── view │ ├── user-config.html │ └── user-config.js ├── examples └── user-filter-example.js ├── package.json ├── readme.md └── test └── builder-util-test.js /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | 5 | # Runtime data 6 | pids 7 | *.pid 8 | *.seed 9 | 10 | # Directory for instrumented libs generated by jscoverage/JSCover 11 | lib-cov 12 | 13 | # Coverage directory used by tools like istanbul 14 | coverage 15 | 16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 17 | .grunt 18 | 19 | # Compiled binary addons (http://nodejs.org/api/addons.html) 20 | build/Release 21 | 22 | # Dependency directory 23 | # Deployed apps should consider commenting this line out: 24 | # see https://npmjs.org/doc/faq.html#Should-I-check-my-node_modules-folder-into-git 25 | node_modules 26 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: node_js 3 | env: 4 | global: 5 | - GH_REF: github.com/azu/github-reader.git 6 | - secure: Lf1oit8BeLq7mPKBSDLrKLV9xdxwERJ/36p/nN4nonnzXoJzezbMd8RdFYq+R+uNmxeOSdiwvJV+KaNVGGJzIWhM0rdQKXE+ums+hLyLOrTDIxbI7kHpZkiRogQwB1AynAR7MvQlInXcCxNud2aplMBQUp/TfkV5HltIjOTjVOA= 7 | node_js: 8 | - '0.12' 9 | before_deploy: 10 | - npm run build 11 | deploy: 12 | provider: releases 13 | api_key: 14 | secure: qS2igPviHIlN6zGVUPa9s5lh/TnYH/nELBxb9EfjXQzhaScV1/R3csjg0AI28Bh0ReSp1xhRWc7I5EiKLsS5wqYM821MfTiyrjoKneAjDYy5XeW4+kFKXaqvMgYK+v5f1CoiuJVKtJwVv5uEVb3NsXpX5qUGcLmIvmWmUoRrjik= 15 | file: 16 | - build/github-reader/github-reader-osx64.zip 17 | # - build/github-reader/github-reader-win64.zip 18 | # - build/github-reader/github-reader-linux64.zip 19 | on: 20 | repo: azu/github-reader 21 | tags: true 22 | all_branches: true 23 | skip_cleanup: true -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ### 1.2.1 (2015-01-07) 2 | 3 | 4 | #### Bug Fixes 5 | 6 | * **growl:** add name ([6e43df17](https://github.com/azu/github-reader/commit/6e43df17229b54431d3d22e98d6c9217f00ef926)) 7 | 8 | 9 | ## 1.2.0 (2015-01-07) 10 | 11 | 12 | #### Bug Fixes 13 | 14 | * **growl:** fix to check items at first ([a8016a16](https://github.com/azu/github-reader/commit/a8016a16ac769fe3f51cebd80406aaaae1b4eb41)) 15 | 16 | 17 | #### Features 18 | 19 | * **growl:** when click the growl, then open the issue url and focus app ([1badd141](https://github.com/azu/github-reader/commit/1badd141ab0e3fa5deb6fc6c69475b9ae69a038a)) 20 | 21 | 22 | ## 1.1.0 (2014-09-02) 23 | 24 | 25 | #### Features 26 | 27 | * **travis:** integrate automatically releasing binary ([93567fd2](https://github.com/azu/github-reader/commit/93567fd2346f44005fc6f93f979edcd2e619b658)) 28 | 29 | 30 | ### 1.0.3 (2014-08-24) 31 | 32 | 33 | ### 1.0.2 (2014-08-24) 34 | 35 | 36 | ### 1.0.1 (2014-08-24) 37 | 38 | 39 | #### Features 40 | 41 | * **travis:** add release build task ([e1cc3e9f](https://github.com/azu/github-reader/commit/e1cc3e9f228de0d7c2c11e1fa15029697e76d299)) 42 | 43 | 44 | ## 1.0.0 (2014-08-04) 45 | 46 | 47 | #### Bug Fixes 48 | 49 | * **build:** 50 | * fix wrong zip ([85c0a89f](https://github.com/azu/github-reader/commit/85c0a89f8c348323f515242348f72da829776aad)) 51 | * quite zip message ([a5d09071](https://github.com/azu/github-reader/commit/a5d090717f55e6abe28c1aa6594073d9a78f3231)) 52 | * fix packaging path ([14bf826e](https://github.com/azu/github-reader/commit/14bf826e8f00708affcf0dc37040e1d2e7a4ccbd)) 53 | * fix build script ([8799c5a1](https://github.com/azu/github-reader/commit/8799c5a126134d0710cd19cfbd19d5bcf584d32c)) 54 | * **github:** 55 | * improve error handling ([ac16fc73](https://github.com/azu/github-reader/commit/ac16fc735eb0e91c92024a5b222998cda61b9d9b)) 56 | * fix request for notification api. ([6d08357d](https://github.com/azu/github-reader/commit/6d08357dba187aa5da8056a30ba8a24faa2c4f99)) 57 | * support commit notification ([d0ffb751](https://github.com/azu/github-reader/commit/d0ffb75116a144dfb127a4cb77478f56d07401ac)) 58 | * **list:** 59 | * fix sort items ([5e5d03c2](https://github.com/azu/github-reader/commit/5e5d03c2a5b5984205f076b404fb15664190f9e7)) 60 | * scroll workaround ([7a371e2d](https://github.com/azu/github-reader/commit/7a371e2db6228ad0a6c1764d481dd4717cd6033a)) 61 | * fix scroll top ([4362e42c](https://github.com/azu/github-reader/commit/4362e42ce789544260119a2ea1f7a29e710bf3b3)) 62 | * **menu:** support node-webkit 0.10.1 ([a32be4b7](https://github.com/azu/github-reader/commit/a32be4b7a9d1e99bffb3aff656ecf89ad5441193)) 63 | * **notification:** fix detection rule ([ecf887a8](https://github.com/azu/github-reader/commit/ecf887a8b96927ae7dc056e8fa3bdb5be5f4f5d7)) 64 | * **search:** 65 | * deselect item when off search mode ([37a4e384](https://github.com/azu/github-reader/commit/37a4e384ccbffca9ccae898f45d08a139dba6d42)) 66 | * doesn't reload while search mode ([e981f63f](https://github.com/azu/github-reader/commit/e981f63f8c0029509f2211ba4912bab9d9ead4e1)) 67 | * ignore case-sensitive ([6921bb2b](https://github.com/azu/github-reader/commit/6921bb2bd4870afa5b7ba272b9333d1c20ba58da)) 68 | * **travis:** update secure token ([11fdd2f1](https://github.com/azu/github-reader/commit/11fdd2f19fc83fc089d50a396dea868a646896e5)) 69 | * **workaround:** add workaroung methods. ([cbf60dab](https://github.com/azu/github-reader/commit/cbf60dab767aba3e914c1953cd4f1770445d067d)) 70 | 71 | 72 | #### Features 73 | 74 | * **config:** Add config for auto-reload timer ([75976713](https://github.com/azu/github-reader/commit/75976713403e155ea59831314c928bf95cb0fab9)) 75 | * **github:** api as promised ([b1a5f0d3](https://github.com/azu/github-reader/commit/b1a5f0d3cf7c03054db5cb4be8df674c94598299)) 76 | * **growl:** growl early phase ([3d9eba90](https://github.com/azu/github-reader/commit/3d9eba90956600f30a3e115a430dd76479b6ab34)) 77 | * **keyboard:** add shortcut JK Scroll. ([bd8a0e0b](https://github.com/azu/github-reader/commit/bd8a0e0ba94de7c2380f70b76be6906dc56bc4a6)) 78 | * **list:** 79 | * add filtering by word. ([d8b00143](https://github.com/azu/github-reader/commit/d8b00143b4222e96a6787a383a08189f9fa555d3)) 80 | * add `repo_name` to list object ([d7b46194](https://github.com/azu/github-reader/commit/d7b4619448d5c316c247b5e0cd815fbd3afacddc)) 81 | * **main:** add notification to list ([a59b0199](https://github.com/azu/github-reader/commit/a59b0199ef7c35b554d7b209a08abc26545ab0a6)) 82 | * **notification:** 83 | * add icon to growl ([6391d3f8](https://github.com/azu/github-reader/commit/6391d3f84d034266f02a41dbd8ce02ca60190b71)) 84 | * support growl clicked ([905dcd0a](https://github.com/azu/github-reader/commit/905dcd0a1ec69267714c258b64ab0679039f9b81)) 85 | * **shortcut:** key `o` : open in browser ([e918f13b](https://github.com/azu/github-reader/commit/e918f13b24db5d7853ef8c281eddba299c0d6e41)) 86 | * **window:** Open external browser when middle click link ([9f48abfd](https://github.com/azu/github-reader/commit/9f48abfd0cf1f8f40a034e1e0de922a447ebbb24)) 87 | 88 | 89 | -------------------------------------------------------------------------------- /_travis/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [[ "$TRAVIS_TAG" ]]; then 4 | rm -rf build 5 | npm run dist 6 | cd build 7 | # ziped in build/ 8 | zip -q github-reader-osx32.zip -r github-reader/osx32 9 | zip -q github-reader-osx64.zip -r github-reader/osx64 10 | zip -q github-reader-win32.zip -r github-reader/win32 11 | zip -q github-reader-win64.zip -r github-reader/win64 12 | zip -q github-reader-linux32.zip -r github-reader/linux32 13 | zip -q github-reader-linux64.zip -r github-reader/linux64 14 | cd ../ 15 | echo "ziped!" 16 | else 17 | echo "Not Release" 18 | fi -------------------------------------------------------------------------------- /_travis/deploy-gh-pages.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ $TRAVIS_PULL_REQUEST != 'false' ]; then 4 | echo "This is a pull request. No deployment will be done."; 5 | exit 0; 6 | fi 7 | 8 | git checkout -B gh-pages 9 | 10 | lastCommit=$(git log --oneline | head -n 1) 11 | echo "=COMMIT=" 12 | echo "MESSAGE :" $lastCommit 13 | 14 | git config --global user.email "travis@travis-ci.org" 15 | git config --global user.name "travis-ci" 16 | git add -A . 17 | git commit -m "Travis build $TRAVIS_BUILD_NUMBER" 18 | git push --force --quiet "https://${GH_TOKEN}@${GH_REF}" gh-pages > /dev/null -------------------------------------------------------------------------------- /app/css/style.css: -------------------------------------------------------------------------------- 1 | #layout { 2 | margin: 0; 3 | padding: 0; } 4 | 5 | #content-list { 6 | width: 200px; 7 | word-wrap: break-word; } 8 | #content-list .content-list-filter-input { 9 | transition: all .1s ease; 10 | box-sizing: border-box; 11 | border: 1px solid #0b97c4; 12 | width: 100%; 13 | overflow: hidden; } 14 | #content-list .content-list-filter-input.v-enter, #content-list .content-list-filter-input.v-leave { 15 | height: 0; 16 | padding: 0 10px; 17 | opacity: 0; } 18 | 19 | #github-webview { 20 | height: 100%; 21 | width: 100%; 22 | position: fixed; 23 | overflow: hidden; } 24 | #github-webview #comment-preview-header { 25 | box-sizing: border-box; 26 | height: 80px; 27 | max-height: 10%; 28 | margin: 0 10px; 29 | border-bottom: 2px solid #ddd; 30 | font-size: 1.2em; 31 | overflow: hidden; } 32 | #github-webview #comment-preview-header .repo_name { 33 | position: relative; 34 | font-size: 0.7em; 35 | right: 0; 36 | top: 0; 37 | margin: 0; 38 | padding: 0; } 39 | #github-webview #github-iframe { 40 | width: 100%; 41 | height: 89%; 42 | overflow: hidden; 43 | border: none; } 44 | #github-webview .comment-description { 45 | margin: 0 .5em; 46 | overflow: hidden; } 47 | 48 | /* 49 | * -- BASE STYLES -- 50 | * Most of these are inherited from Base, but I want to change a few. 51 | */ 52 | body { 53 | color: #333; 54 | margin: auto; } 55 | 56 | a { 57 | text-decoration: none; 58 | color: #1b98f8; } 59 | 60 | /* 61 | * -- HELPER STYLES -- 62 | * Over-riding some of the .pure-button styles to make my buttons look unique 63 | */ 64 | .primary-button, 65 | .secondary-button { 66 | -webkit-box-shadow: none; 67 | -moz-box-shadow: none; 68 | box-shadow: none; 69 | border-radius: 20px; } 70 | 71 | .primary-button { 72 | color: #fff; 73 | background: #1b98f8; 74 | margin: 1em 0; } 75 | 76 | .secondary-button { 77 | background: #fff; 78 | border: 1px solid #ddd; 79 | color: #666; 80 | padding: 0.5em 2em; 81 | font-size: 80%; } 82 | 83 | /* 84 | * -- LAYOUT STYLES -- 85 | * This layout consists of three main elements, `#nav` (navigation bar), `#content-list` (email list), and `#main` (email content). All 3 elements are within `#layout` 86 | */ 87 | #layout, #nav, #content-list, #main { 88 | margin: 0; 89 | padding: 0; } 90 | 91 | /* Make the navigation 100% width on phones */ 92 | #nav { 93 | width: 100%; 94 | height: 40px; 95 | position: relative; 96 | background: #252a3a; 97 | text-align: center; } 98 | 99 | /* Show the "Menu" button on phones */ 100 | #nav .nav-menu-button { 101 | display: block; 102 | top: 0.5em; 103 | right: 0.5em; 104 | position: absolute; } 105 | 106 | /* When "Menu" is clicked, the navbar should be 80% height */ 107 | #nav.active { 108 | height: 80%; } 109 | 110 | /* Don't show the navigation items... */ 111 | .nav-inner { 112 | display: none; } 113 | 114 | /* ...until the "Menu" button is clicked */ 115 | #nav.active .nav-inner { 116 | display: block; 117 | padding: 2em 0; } 118 | 119 | /* 120 | * -- NAV BAR STYLES -- 121 | * Styling the default .pure-menu to look a little more unique. 122 | */ 123 | #nav .pure-menu.pure-menu-open { 124 | background: transparent; 125 | border: none; 126 | text-align: left; } 127 | 128 | #nav .pure-menu a:hover, 129 | #nav .pure-menu a:focus { 130 | background: #373c5a; } 131 | 132 | #nav .pure-menu a { 133 | color: #fff; 134 | margin-left: 0.5em; } 135 | 136 | #nav .pure-menu-heading { 137 | border-bottom: none; 138 | font-size: 110%; 139 | color: #4b7197; } 140 | 141 | /* 142 | * -- EMAIL STYLES -- 143 | * Styles relevant to the email messages, labels, counts, and more. 144 | */ 145 | .email-count { 146 | color: #4b7197; } 147 | 148 | .email-label-personal, 149 | .email-label-work, 150 | .email-label-travel { 151 | width: 15px; 152 | height: 15px; 153 | display: inline-block; 154 | margin-right: 0.5em; 155 | border-radius: 3px; } 156 | 157 | .email-label-personal { 158 | background: #ffc94c; } 159 | 160 | .email-label-work { 161 | background: #41ccb4; } 162 | 163 | .email-label-travel { 164 | background: #40c365; } 165 | 166 | .avatar-img { 167 | width: 30px; 168 | height: 30px; 169 | margin: 5px; 170 | float: left; } 171 | 172 | .event-item { 173 | cursor: pointer; 174 | padding: 0.9em 1em; 175 | border-bottom: 1px solid #ddd; 176 | border-left: 6px solid transparent; } 177 | .event-item .event-header { 178 | clear: all; } 179 | .event-item .event-subject { 180 | font-size: 0.9em; } 181 | 182 | .email-avatar { 183 | border-radius: 3px; 184 | margin-right: 0.5em; } 185 | 186 | .event-username, 187 | .event-subject { 188 | margin: 0; } 189 | 190 | .event-username { 191 | color: #999; } 192 | 193 | .event-description { 194 | font-size: 80%; 195 | margin: 0.4em 0; 196 | overflow: hidden; 197 | max-height: 150px; } 198 | 199 | .event-item-selected { 200 | background: #eee; } 201 | 202 | /* Email Content Styles */ 203 | .event-content-header, .email-content-body, .email-content-footer { 204 | padding: 1em 2em; } 205 | 206 | .email-content-title { 207 | margin: 0.5em 0 0; } 208 | 209 | .email-content-subtitle { 210 | font-size: 1em; 211 | margin: 0; 212 | font-weight: normal; } 213 | 214 | .email-content-subtitle span { 215 | color: #999; } 216 | 217 | .email-content-controls { 218 | margin-top: 2em; 219 | text-align: right; } 220 | 221 | .email-content-controls .secondary-button { 222 | margin-bottom: 0.3em; } 223 | 224 | .email-avatar { 225 | width: 40px; 226 | height: 40px; } 227 | 228 | /* Move the layout over so we can fit the nav + list in on the left */ 229 | #layout { 230 | padding-left: 250px; 231 | /* "left col (nav + list)" width */ 232 | position: relative; } 233 | 234 | /* These are position:fixed; elements that will be in the left $left-width of the screen */ 235 | #nav, #content-list { 236 | position: fixed; 237 | top: 0; 238 | bottom: 0; 239 | overflow: auto; } 240 | 241 | #nav { 242 | margin-left: -250px; 243 | /* "left col (nav + list)" width */ 244 | width: 0; 245 | height: 100%; } 246 | 247 | /* Show the menu items on the larger screen */ 248 | .nav-inner { 249 | display: block; 250 | padding: 2em 0; } 251 | 252 | /* Hide the "Menu" button on larger screens */ 253 | #nav .nav-menu-button { 254 | display: none; } 255 | 256 | #main { 257 | position: fixed; 258 | top: 33%; 259 | right: 0; 260 | bottom: 0; 261 | left: 0; 262 | overflow: auto; 263 | width: auto; 264 | /* so that it's not 100% */ } 265 | 266 | /* This will take up the entire height, and be a little thinner */ 267 | #content-list { 268 | margin-left: -250px; 269 | width: 250px; 270 | height: 100%; 271 | border-right: 1px solid #ddd; } 272 | 273 | /* This will now take up it's own column, so don't need position: fixed; */ 274 | #main { 275 | position: static; 276 | margin: 0; 277 | padding: 0; } 278 | 279 | /*# sourceMappingURL=style.css.map */ 280 | -------------------------------------------------------------------------------- /app/css/style.css.map: -------------------------------------------------------------------------------- 1 | { 2 | "version": 3, 3 | "mappings": "AAMA,OAAQ;EACN,MAAM,EAAE,CAAC;EACT,OAAO,EAAE,CAAC;;AAMZ,aAAc;EACZ,KAAK,EAbM,KAAK;EAchB,SAAS,EAAE,UAAU;EACrB,wCAA2B;IACzB,UAAU,EAAE,YAAY;IACxB,UAAU,EAAE,UAAU;IACtB,MAAM,EAAE,iBAAiB;IACzB,KAAK,EAAE,IAAI;IACX,QAAQ,EAAE,MAAM;EAElB,kGAAuE;IACrE,MAAM,EAAE,CAAC;IACT,OAAO,EAAE,MAAM;IACf,OAAO,EAAE,CAAC;;AAKd,eAAgB;EACd,MAAM,EAAE,IAAI;EACZ,KAAK,EAAE,IAAI;EACX,QAAQ,EAAE,KAAK;EACf,QAAQ,EAAE,MAAM;EAChB,uCAAwB;IACtB,UAAU,EAAE,UAAU;IACtB,MAAM,EAAE,IAAI;IACZ,UAAU,EAAE,GAAG;IACf,MAAM,EAAE,MAAM;IACd,aAAa,EAAE,cAAc;IAC7B,SAAS,EAAE,KAAK;IAChB,QAAQ,EAAE,MAAM;IAChB,kDAAW;MACT,QAAQ,EAAE,QAAQ;MAClB,SAAS,EAAE,KAAK;MAChB,KAAK,EAAE,CAAC;MACR,GAAG,EAAE,CAAC;MACN,MAAM,EAAE,CAAC;MACT,OAAO,EAAE,CAAC;EAGd,8BAAe;IACb,KAAK,EAAE,IAAI;IACX,MAAM,EAAE,GAAG;IACX,QAAQ,EAAE,MAAM;IAChB,MAAM,EAAE,IAAI;EAGd,oCAAqB;IACnB,MAAM,EAAE,MAAM;IACd,QAAQ,EAAE,MAAM;;;;;;AASpB,IAAK;EACH,KAAK,EAAE,IAAI;EACX,MAAM,EAAE,IAAI;;AAGd,CAAE;EACA,eAAe,EAAE,IAAI;EACrB,KAAK,EAAE,OAAO;;;;;;AAOhB;iBACkB;EAChB,kBAAkB,EAAE,IAAI;EACxB,eAAe,EAAE,IAAI;EACrB,UAAU,EAAE,IAAI;EAChB,aAAa,EAAE,IAAI;;AAGrB,eAAgB;EACd,KAAK,EAAE,IAAI;EACX,UAAU,EAAE,OAAO;EACnB,MAAM,EAAE,KAAK;;AAGf,iBAAkB;EAChB,UAAU,EAAE,IAAI;EAChB,MAAM,EAAE,cAAc;EACtB,KAAK,EAAE,IAAI;EACX,OAAO,EAAE,SAAS;EAClB,SAAS,EAAE,GAAG;;;;;;AAOhB,mCAAoC;EAClC,MAAM,EAAE,CAAC;EACT,OAAO,EAAE,CAAC;;;AAIZ,IAAK;EACH,KAAK,EAAE,IAAI;EACX,MAAM,EAAE,IAAI;EACZ,QAAQ,EAAE,QAAQ;EAClB,UAAU,EAAE,OAAe;EAC3B,UAAU,EAAE,MAAM;;;AAIpB,qBAAsB;EACpB,OAAO,EAAE,KAAK;EACd,GAAG,EAAE,KAAK;EACV,KAAK,EAAE,KAAK;EACZ,QAAQ,EAAE,QAAQ;;;AAIpB,WAAY;EACV,MAAM,EAAE,GAAG;;;AAIb,UAAW;EACT,OAAO,EAAE,IAAI;;;AAIf,sBAAuB;EACrB,OAAO,EAAE,KAAK;EACd,OAAO,EAAE,KAAK;;;;;;AAOhB,8BAA+B;EAC7B,UAAU,EAAE,WAAW;EACvB,MAAM,EAAE,IAAI;EACZ,UAAU,EAAE,IAAI;;AAGlB;uBACwB;EACtB,UAAU,EAAE,OAAe;;AAG7B,iBAAkB;EAChB,KAAK,EAAE,IAAI;EACX,WAAW,EAAE,KAAK;;AAGpB,uBAAwB;EACtB,aAAa,EAAE,IAAI;EACnB,SAAS,EAAE,IAAI;EACf,KAAK,EAAE,OAAiB;;;;;;AAO1B,YAAa;EACX,KAAK,EAAE,OAAiB;;AAG1B;;mBAEoB;EAClB,KAAK,EAAE,IAAI;EACX,MAAM,EAAE,IAAI;EACZ,OAAO,EAAE,YAAY;EACrB,YAAY,EAAE,KAAK;EACnB,aAAa,EAAE,GAAG;;AAGpB,qBAAsB;EACpB,UAAU,EAAE,OAAO;;AAGrB,iBAAkB;EAChB,UAAU,EAAE,OAAO;;AAGrB,mBAAoB;EAClB,UAAU,EAAE,OAAO;;AAGrB,WAAY;EACV,KAAK,EAAE,IAAI;EACX,MAAM,EAAE,IAAI;EACZ,MAAM,EAAE,GAAG;EACX,KAAK,EAAE,IAAI;;AAGb,WAAY;EACV,MAAM,EAAE,OAAO;EACf,OAAO,EAAE,SAAS;EAClB,aAAa,EAAE,cAAc;EAC7B,WAAW,EAAE,qBAAqB;EAClC,yBAAc;IACZ,KAAK,EAAE,GAAG;EAEZ,0BAAe;IACb,SAAS,EAAE,KAAK;;AAIpB,aAAc;EACZ,aAAa,EAAE,GAAG;EAClB,YAAY,EAAE,KAAK;;AAGrB;cACe;EACb,MAAM,EAAE,CAAC;;AAGX,eAAgB;EACd,KAAK,EAAE,IAAI;;AAGb,kBAAmB;EACjB,SAAS,EAAE,GAAG;EACd,MAAM,EAAE,OAAO;EACf,QAAQ,EAAE,MAAM;EAChB,UAAU,EAAE,KAAK;;AAGnB,oBAAqB;EACnB,UAAU,EAAE,IAAI;;;AAKlB,iEAAkE;EAChE,OAAO,EAAE,OAAO;;AAGlB,oBAAqB;EACnB,MAAM,EAAE,SAAS;;AAGnB,uBAAwB;EACtB,SAAS,EAAE,GAAG;EACd,MAAM,EAAE,CAAC;EACT,WAAW,EAAE,MAAM;;AAGrB,4BAA6B;EAC3B,KAAK,EAAE,IAAI;;AAGb,uBAAwB;EACtB,UAAU,EAAE,GAAG;EACf,UAAU,EAAE,KAAK;;AAGnB,yCAA0C;EACxC,aAAa,EAAE,KAAK;;AAGtB,aAAc;EACZ,KAAK,EAAE,IAAI;EACX,MAAM,EAAE,IAAI;;;AAId,OAAQ;EACN,YAAY,EA3RD,KAAsC;;EA4RjD,QAAQ,EAAE,QAAQ;;;AAIpB,mBAAoB;EAClB,QAAQ,EAAE,KAAK;EACf,GAAG,EAAE,CAAC;EACN,MAAM,EAAE,CAAC;EACT,QAAQ,EAAE,IAAI;;AAGhB,IAAK;EACH,WAAW,EAAE,MAAY;;EACzB,KAAK,EA1SM,CAAC;EA2SZ,MAAM,EAAE,IAAI;;;AAId,UAAW;EACT,OAAO,EAAE,KAAK;EACd,OAAO,EAAE,KAAK;;;AAIhB,qBAAsB;EACpB,OAAO,EAAE,IAAI;;AAGf,KAAM;EACJ,QAAQ,EAAE,KAAK;EACf,GAAG,EAAE,GAAG;EACR,KAAK,EAAE,CAAC;EACR,MAAM,EAAE,CAAC;EACT,IAAI,EA9TO,CAAC;EA+TZ,QAAQ,EAAE,IAAI;EACd,KAAK,EAAE,IAAI;;;;AAIb,aAAc;EACZ,WAAW,EAAE,MAA4B;EACzC,KAAK,EAAE,KAA0B;EACjC,MAAM,EAAE,IAAI;EACZ,YAAY,EAAE,cAAc;;;AAI9B,KAAM;EACJ,QAAQ,EAAE,MAAM;EAChB,MAAM,EAAE,CAAC;EACT,OAAO,EAAE,CAAC", 4 | "sources": ["style.scss"], 5 | "names": [], 6 | "file": "style.css" 7 | } -------------------------------------------------------------------------------- /app/css/style.scss: -------------------------------------------------------------------------------- 1 | @charset "UTF-8"; 2 | $left-margin: 50px; 3 | $list-width: 200px; 4 | $menu-width: 0; 5 | $left-width: $list-width +$menu-width +$left-margin; 6 | 7 | #layout { 8 | margin: 0; 9 | padding: 0; 10 | } 11 | 12 | #content { 13 | } 14 | 15 | #content-list { 16 | width: $list-width; 17 | word-wrap: break-word; 18 | .content-list-filter-input { 19 | transition: all .1s ease; 20 | box-sizing: border-box; 21 | border: 1px solid #0b97c4; 22 | width: 100%; 23 | overflow: hidden; 24 | } 25 | .content-list-filter-input.v-enter, .content-list-filter-input.v-leave { 26 | height: 0; 27 | padding: 0 10px; 28 | opacity: 0; 29 | } 30 | } 31 | 32 | #github-webview { 33 | height: 100%; 34 | width: 100%; 35 | position: fixed; 36 | overflow: hidden; 37 | #comment-preview-header { 38 | box-sizing: border-box; 39 | height: 80px; 40 | max-height: 10%; 41 | margin: 0 10px; 42 | border-bottom: 2px solid #ddd; 43 | font-size: 1.2em; 44 | overflow: hidden; 45 | .repo_name { 46 | position: relative; 47 | font-size: 0.7em; 48 | right: 0; 49 | top: 0; 50 | margin: 0; 51 | padding: 0; 52 | } 53 | } 54 | #github-iframe { 55 | width: 100%; 56 | height: 89%; // TOOD: missing 1%... 57 | overflow: hidden; 58 | border: none; 59 | } 60 | 61 | .comment-description { 62 | margin: 0 .5em; 63 | overflow: hidden; 64 | } 65 | } 66 | 67 | // 68 | /* 69 | * -- BASE STYLES -- 70 | * Most of these are inherited from Base, but I want to change a few. 71 | */ 72 | body { 73 | color: #333; 74 | margin: auto; 75 | } 76 | 77 | a { 78 | text-decoration: none; 79 | color: #1b98f8; 80 | } 81 | 82 | /* 83 | * -- HELPER STYLES -- 84 | * Over-riding some of the .pure-button styles to make my buttons look unique 85 | */ 86 | .primary-button, 87 | .secondary-button { 88 | -webkit-box-shadow: none; 89 | -moz-box-shadow: none; 90 | box-shadow: none; 91 | border-radius: 20px; 92 | } 93 | 94 | .primary-button { 95 | color: #fff; 96 | background: #1b98f8; 97 | margin: 1em 0; 98 | } 99 | 100 | .secondary-button { 101 | background: #fff; 102 | border: 1px solid #ddd; 103 | color: #666; 104 | padding: 0.5em 2em; 105 | font-size: 80%; 106 | } 107 | 108 | /* 109 | * -- LAYOUT STYLES -- 110 | * This layout consists of three main elements, `#nav` (navigation bar), `#content-list` (email list), and `#main` (email content). All 3 elements are within `#layout` 111 | */ 112 | #layout, #nav, #content-list, #main { 113 | margin: 0; 114 | padding: 0; 115 | } 116 | 117 | /* Make the navigation 100% width on phones */ 118 | #nav { 119 | width: 100%; 120 | height: 40px; 121 | position: relative; 122 | background: rgb(37, 42, 58); 123 | text-align: center; 124 | } 125 | 126 | /* Show the "Menu" button on phones */ 127 | #nav .nav-menu-button { 128 | display: block; 129 | top: 0.5em; 130 | right: 0.5em; 131 | position: absolute; 132 | } 133 | 134 | /* When "Menu" is clicked, the navbar should be 80% height */ 135 | #nav.active { 136 | height: 80%; 137 | } 138 | 139 | /* Don't show the navigation items... */ 140 | .nav-inner { 141 | display: none; 142 | } 143 | 144 | /* ...until the "Menu" button is clicked */ 145 | #nav.active .nav-inner { 146 | display: block; 147 | padding: 2em 0; 148 | } 149 | 150 | /* 151 | * -- NAV BAR STYLES -- 152 | * Styling the default .pure-menu to look a little more unique. 153 | */ 154 | #nav .pure-menu.pure-menu-open { 155 | background: transparent; 156 | border: none; 157 | text-align: left; 158 | } 159 | 160 | #nav .pure-menu a:hover, 161 | #nav .pure-menu a:focus { 162 | background: rgb(55, 60, 90); 163 | } 164 | 165 | #nav .pure-menu a { 166 | color: #fff; 167 | margin-left: 0.5em; 168 | } 169 | 170 | #nav .pure-menu-heading { 171 | border-bottom: none; 172 | font-size: 110%; 173 | color: rgb(75, 113, 151); 174 | } 175 | 176 | /* 177 | * -- EMAIL STYLES -- 178 | * Styles relevant to the email messages, labels, counts, and more. 179 | */ 180 | .email-count { 181 | color: rgb(75, 113, 151); 182 | } 183 | 184 | .email-label-personal, 185 | .email-label-work, 186 | .email-label-travel { 187 | width: 15px; 188 | height: 15px; 189 | display: inline-block; 190 | margin-right: 0.5em; 191 | border-radius: 3px; 192 | } 193 | 194 | .email-label-personal { 195 | background: #ffc94c; 196 | } 197 | 198 | .email-label-work { 199 | background: #41ccb4; 200 | } 201 | 202 | .email-label-travel { 203 | background: #40c365; 204 | } 205 | 206 | .avatar-img { 207 | width: 30px; 208 | height: 30px; 209 | margin: 5px; 210 | float: left 211 | } 212 | 213 | .event-item { 214 | cursor: pointer; 215 | padding: 0.9em 1em; 216 | border-bottom: 1px solid #ddd; 217 | border-left: 6px solid transparent; 218 | .event-header { 219 | clear: all; 220 | } 221 | .event-subject { 222 | font-size: 0.9em 223 | } 224 | } 225 | 226 | .email-avatar { 227 | border-radius: 3px; 228 | margin-right: 0.5em; 229 | } 230 | 231 | .event-username, 232 | .event-subject { 233 | margin: 0; 234 | } 235 | 236 | .event-username { 237 | color: #999; 238 | } 239 | 240 | .event-description { 241 | font-size: 80%; 242 | margin: 0.4em 0; 243 | overflow: hidden; 244 | max-height: 150px; 245 | } 246 | 247 | .event-item-selected { 248 | background: #eee; 249 | } 250 | 251 | 252 | /* Email Content Styles */ 253 | .event-content-header, .email-content-body, .email-content-footer { 254 | padding: 1em 2em; 255 | } 256 | 257 | .email-content-title { 258 | margin: 0.5em 0 0; 259 | } 260 | 261 | .email-content-subtitle { 262 | font-size: 1em; 263 | margin: 0; 264 | font-weight: normal; 265 | } 266 | 267 | .email-content-subtitle span { 268 | color: #999; 269 | } 270 | 271 | .email-content-controls { 272 | margin-top: 2em; 273 | text-align: right; 274 | } 275 | 276 | .email-content-controls .secondary-button { 277 | margin-bottom: 0.3em; 278 | } 279 | 280 | .email-avatar { 281 | width: 40px; 282 | height: 40px; 283 | } 284 | 285 | /* Move the layout over so we can fit the nav + list in on the left */ 286 | #layout { 287 | padding-left: $left-width; /* "left col (nav + list)" width */ 288 | position: relative; 289 | } 290 | 291 | /* These are position:fixed; elements that will be in the left $left-width of the screen */ 292 | #nav, #content-list { 293 | position: fixed; 294 | top: 0; 295 | bottom: 0; 296 | overflow: auto; 297 | } 298 | 299 | #nav { 300 | margin-left: -$left-width; /* "left col (nav + list)" width */ 301 | width: $menu-width; 302 | height: 100%; 303 | } 304 | 305 | /* Show the menu items on the larger screen */ 306 | .nav-inner { 307 | display: block; 308 | padding: 2em 0; 309 | } 310 | 311 | /* Hide the "Menu" button on larger screens */ 312 | #nav .nav-menu-button { 313 | display: none; 314 | } 315 | 316 | #main { 317 | position: fixed; 318 | top: 33%; 319 | right: 0; 320 | bottom: 0; 321 | left: $menu-width; 322 | overflow: auto; 323 | width: auto; /* so that it's not 100% */ 324 | } 325 | 326 | /* This will take up the entire height, and be a little thinner */ 327 | #content-list { 328 | margin-left: -($left-width - $menu-width); 329 | width: $list-width + $left-margin; 330 | height: 100%; 331 | border-right: 1px solid #ddd; 332 | } 333 | 334 | /* This will now take up it's own column, so don't need position: fixed; */ 335 | #main { 336 | position: static; 337 | margin: 0; 338 | padding: 0; 339 | } 340 | -------------------------------------------------------------------------------- /app/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | GitHub Reader 6 | 7 | 8 | 9 | 10 | 11 |
12 |
13 | 14 | 15 |
19 |
20 |
21 | 22 | 23 |

{{item.date}}

24 |
{{item.user_name}}
25 |

{{item.title}}

26 |
27 |

28 | {{item.body}} 29 |

30 |
31 |
32 |
33 | 34 |
35 |
36 |

{{repo_name}}

37 | 38 |
39 | 40 | 41 |

42 | {{body | removeMd}} 43 |

44 |
45 |
46 | 47 |
48 |
49 | 50 | 51 | 67 | 68 | -------------------------------------------------------------------------------- /app/js/config/reloadConfig.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by azu on 2014/04/27. 3 | * LICENSE : MIT 4 | */ 5 | "use strict"; 6 | function getAutoReloadTime() { 7 | return window.localStorage.getItem("auto-reload-interval") || 60 * 1000; 8 | } 9 | function setAutoReloadTime(timeInterval) { 10 | return window.localStorage.setItem("auto-reload-interval", timeInterval); 11 | } 12 | function setLastUpdated(date) { 13 | window.localStorage.setItem("last-updated", date.toISOString()); 14 | } 15 | function getLastUpdated() { 16 | return window.localStorage.getItem("last-updated"); 17 | } 18 | 19 | function getFilterScriptPath() { 20 | return window.localStorage.getItem("filter-script-path"); 21 | } 22 | 23 | function setFilterScriptPath(scriptPath) { 24 | window.localStorage.setItem("filter-script-path", scriptPath) 25 | } 26 | module.exports = { 27 | getAutoReloadTime: getAutoReloadTime, 28 | setAutoReloadTime: setAutoReloadTime, 29 | getLastUpdated: getLastUpdated, 30 | setLastUpdated: setLastUpdated, 31 | getFilterScriptPath: getFilterScriptPath, 32 | setFilterScriptPath: setFilterScriptPath 33 | }; -------------------------------------------------------------------------------- /app/js/config/userData.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by azu on 2014/04/24. 3 | * LICENSE : MIT 4 | */ 5 | "use strict"; 6 | /** 7 | * 8 | * @returns {{name: string, token: string}} 9 | */ 10 | function getUserData() { 11 | var saved = window.localStorage.getItem("user-data"); 12 | if(saved) { 13 | return JSON.parse(saved); 14 | } 15 | return {}; 16 | } 17 | 18 | function setUserData(userData) { 19 | window.localStorage.setItem("user-data", JSON.stringify(userData)); 20 | } 21 | function hasUserData() { 22 | var user = getUserData(); 23 | return user.name && user.token; 24 | } 25 | module.exports.hasUserData = hasUserData; 26 | module.exports.getUserData = getUserData; 27 | module.exports.setUserData = setUserData; -------------------------------------------------------------------------------- /app/js/github/builder-util.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by azu on 2014/04/29. 3 | * LICENSE : MIT 4 | */ 5 | "use strict"; 6 | function normalizeResponseAPIURL(url) { 7 | return url.replace(/^https:\/\/api\.github\.com\/repos\/(.*?)\/(commits|pulls|issues)\/(.*?)/, function (all, repo, type, number) { 8 | return "https://github.com/" + repo + "/" + type.replace("pulls", "pull") + "/" + number 9 | }) 10 | } 11 | module.exports.normalizeResponseAPIURL = normalizeResponseAPIURL; -------------------------------------------------------------------------------- /app/js/github/extend-node-github.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by azu on 2014/04/27. 3 | * LICENSE : MIT 4 | */ 5 | "use strict"; 6 | 7 | function applyNotificationExtend(Client) { 8 | Client.prototype.ex_notifications = function (options, callback) { 9 | var client = this; 10 | // base block 11 | var block = { 12 | url: "/notifications", 13 | method: "GET", 14 | params: options 15 | }; 16 | client.httpSend(options, block, function (err, res) { 17 | if (err) { 18 | return client[client.version].sendError(err, null, options, callback); 19 | } 20 | 21 | var ret; 22 | try { 23 | ret = res.data && JSON.parse(res.data); 24 | } 25 | catch (ex) { 26 | if (callback) { 27 | callback(new error.InternalServerError(ex.message), res); 28 | } 29 | return; 30 | } 31 | 32 | if (!ret) { 33 | ret = {}; 34 | } 35 | if (!ret.meta) { 36 | ret.meta = {}; 37 | } 38 | var headers = [ 39 | "x-ratelimit-limit", "x-ratelimit-remaining", "x-oauth-scopes", "link", "location", "last-modified", 40 | "etag", 41 | "status" 42 | ]; 43 | headers.forEach(function (header) { 44 | if (res.headers[header]) { 45 | ret.meta[header] = res.headers[header]; 46 | } 47 | }); 48 | if (callback) { 49 | callback(null, ret); 50 | } 51 | }); 52 | } 53 | } 54 | module.exports = applyNotificationExtend; -------------------------------------------------------------------------------- /app/js/github/github-client.js: -------------------------------------------------------------------------------- 1 | var Promise = require("bluebird"); 2 | var GitHubApi = require("github"); 3 | require("./extend-node-github")(GitHubApi); 4 | function newClient(userData) { 5 | var githubClient = new GitHubApi({ 6 | // required 7 | version: "3.0.0", 8 | // optional 9 | timeout: 5000 10 | }); 11 | githubClient.authenticate({ 12 | type: "oauth", 13 | token: userData.getUserData().token 14 | }); 15 | return new GithubClientPromise(githubClient); 16 | } 17 | function GithubClientPromise(client) { 18 | this.client = client; 19 | } 20 | GithubClientPromise.prototype.eventsAsPromise = function (user) { 21 | var client = this.client; 22 | return new Promise(function (resolve, reject) { 23 | client.events.getReceived({ user: user }, 24 | function (error, events) { 25 | if (error) { 26 | return reject(error); 27 | } 28 | resolve(events); 29 | }); 30 | }); 31 | }; 32 | GithubClientPromise.prototype.notificationsAsPromise = function () { 33 | var client = this.client; 34 | return new Promise(function (resolve, reject) { 35 | var options = { 36 | all : true 37 | }; 38 | var lastUpdated = require("../config/reloadConfig").getLastUpdated(); 39 | if (lastUpdated) { 40 | options["since"] = lastUpdated; 41 | } 42 | client.ex_notifications(options, function (error, events) { 43 | if (error) { 44 | return reject(error); 45 | } 46 | require("../config/reloadConfig").setLastUpdated(new Date()); 47 | resolve(events); 48 | }); 49 | }); 50 | }; 51 | module.exports.newClient = newClient; 52 | -------------------------------------------------------------------------------- /app/js/github/parse-event-body.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by azu on 2014/04/27. 3 | * LICENSE : MIT 4 | */ 5 | "use strict"; 6 | // https://developer.github.com/v3/repos/commits/ 7 | function compileFormPushEvent(event) { 8 | var commits = event.payload.commits; 9 | return commits.map(function (commit) { 10 | return "- " + commit.message; 11 | }).join("\n"); 12 | } 13 | 14 | function parseEventBody(event) { 15 | var payload = event.payload; 16 | if (payload.comment) { 17 | return payload.comment.body; 18 | } else if (payload.issue) { 19 | return payload.issue.body; 20 | } else if (event.type === "PushEvent") { 21 | return compileFormPushEvent(event); 22 | } 23 | return null; 24 | } 25 | 26 | module.exports.parseEventBody = parseEventBody; -------------------------------------------------------------------------------- /app/js/github/response-builder.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by azu on 2014/04/27. 3 | * LICENSE : MIT 4 | */ 5 | "use strict"; 6 | var parseGithubEvent = require("parse-github-event"); 7 | function buildEvents(events) { 8 | require("assert")(Array.isArray(events)); 9 | return events.map(function (event) { 10 | var parsedEvent = parseGithubEvent.parse(event); 11 | return { 12 | "id": event.id,// github global event id 13 | "date": event.created_at, 14 | "user_name": event.actor.login, 15 | "avatar_url": event.actor.avatar_url, 16 | "repo_name": event.repo.name, 17 | "title": parseGithubEvent.compile(event), 18 | "html_url": parsedEvent.html_url, 19 | "body": require("./parse-event-body").parseEventBody(event) || parseGithubEvent.compile(event) 20 | }; 21 | }) 22 | } 23 | function buildNotifications(notifications) { 24 | require("assert")(Array.isArray(notifications)); 25 | return notifications.map(function (notification) { 26 | return { 27 | "id": notification.id,// github global event id 28 | "date": notification.updated_at, 29 | "user_name": notification.repository.owner.login, 30 | "avatar_url": notification.repository.owner.avatar_url, 31 | "repo_name": notification.repository.name, 32 | "title": notification.repository.full_name, 33 | "html_url": require("./builder-util").normalizeResponseAPIURL(notification.subject.url), 34 | "request_url": notification.subject.latest_comment_url, 35 | "body": notification.subject.title 36 | }; 37 | }) 38 | } 39 | module.exports.buildEvents = buildEvents; 40 | module.exports.buildNotifications = buildNotifications; -------------------------------------------------------------------------------- /app/js/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by azu on 2014/04/24. 3 | * LICENSE : MIT 4 | */ 5 | "use strict"; 6 | var userData = require("./config/userData"); 7 | module.exports = function (gui) { 8 | if (userData.hasUserData()) { 9 | require("./main/mainController")(gui); 10 | } else { 11 | gui.Window.open('./view/user-config.html', '_blank', 'width=400,height=400'); 12 | } 13 | }; -------------------------------------------------------------------------------- /app/js/main/commentHeaderViewController.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by azu on 2014/04/27. 3 | * LICENSE : MIT 4 | */ 5 | "use strict"; 6 | var Vue = require('vue'); 7 | var headerView; 8 | var removeMd = require('remove-markdown'); 9 | function reloadView() { 10 | headerView = new Vue({ 11 | el: '#comment-preview-header', 12 | data: { 13 | "avatar_url": "", 14 | "user_name": "", 15 | "title": "", 16 | "body": "" 17 | }, 18 | filters: { 19 | removeMd: removeMd 20 | } 21 | }); 22 | return headerView; 23 | } 24 | function updateWithItem(item) { 25 | headerView.avatar_url = item.avatar_url; 26 | headerView.title = item.title; 27 | headerView.user_name = item.user_name; 28 | headerView.body = item.body; 29 | headerView.repo_name = item.repo_name; 30 | } 31 | module.exports.reloadView = reloadView; 32 | module.exports.updateWithItem = updateWithItem; -------------------------------------------------------------------------------- /app/js/main/frameController.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by azu on 2014/04/27. 3 | * LICENSE : MIT 4 | */ 5 | "use strict"; 6 | function loadURL(URL) { 7 | var frame = document.getElementById("github-iframe"); 8 | frame.src = URL; 9 | } 10 | module.exports.loadURL = loadURL; -------------------------------------------------------------------------------- /app/js/main/inputFocusController.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by azu on 2014/05/04. 3 | * LICENSE : MIT 4 | */ 5 | "use strict"; 6 | function _focusHandler(event) { 7 | event.target.focus(); 8 | document.querySelector(".content-list-filter-input").removeEventListener("transitionend", _focusHandler); 9 | } 10 | function focus() { 11 | var node = document.querySelector(".content-list-filter-input"); 12 | node.value = ""; 13 | node.addEventListener("transitionend", _focusHandler, false); 14 | } 15 | module.exports.focus = focus; -------------------------------------------------------------------------------- /app/js/main/listViewController.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by azu on 2014/04/27. 3 | * LICENSE : MIT 4 | */ 5 | "use strict"; 6 | var assert = require("assert"); 7 | var notifier = require("../notification/notification"); 8 | var userData = require("../config/userData"); 9 | var userConfig = require("../config/reloadConfig"); 10 | var Vue = require('vue'); 11 | var frameController = require("./frameController"); 12 | var _ = require("lodash"); 13 | var Promise = require("bluebird"); 14 | var request = Promise.promisify(require("request")); 15 | var listView; 16 | function reloadView() { 17 | listView = new Vue({ 18 | el: '#content-list', 19 | data: { 20 | selectedItem: null, 21 | items: [], 22 | isSearchMode: false, 23 | displayItems: [] 24 | }, 25 | methods: { 26 | selectPrevItem: function () { 27 | if (this.selectedItem == null) { 28 | return; 29 | } 30 | var items = this.displayItems; 31 | var currentIndex = items.indexOf(this.selectedItem); 32 | if (currentIndex !== -1 && 0 <= currentIndex - 1) { 33 | this.$root.loadHTMLView(items[currentIndex - 1]); 34 | } 35 | }, 36 | selectNextItem: function () { 37 | var items = this.displayItems; 38 | if (this.selectedItem == null) { 39 | if (items.length > 0) { 40 | this.$root.loadHTMLView(items[0]); 41 | } 42 | return; 43 | } 44 | var currentIndex = items.indexOf(this.selectedItem); 45 | if (currentIndex !== -1 && items.length > currentIndex + 1) { 46 | var nextItem = items[currentIndex + 1]; 47 | this.$root.loadHTMLView(nextItem); 48 | } 49 | }, 50 | loadHTMLView: function (item) { 51 | this.selectedItem = item.$data || item;// raw data 52 | frameController.loadURL(item.html_url); 53 | if (item.request_url != null) { 54 | var options = { 55 | url: item.request_url, 56 | headers: { 57 | 'User-Agent': 'github-reader', 58 | 'Authorization': 'token ' + userData.getUserData().token 59 | } 60 | }; 61 | request(options).spread(function (request, body) { 62 | var res = JSON.parse(body); 63 | if (res.html_url.indexOf("#") !== -1) { 64 | frameController.loadURL(res.html_url); 65 | } 66 | }).catch(function (error) { 67 | console.error(error); 68 | }); 69 | } 70 | } 71 | } 72 | }); 73 | return listView 74 | } 75 | 76 | function sortDate(aItem, bItem) { 77 | var a = new Date(aItem.date), 78 | b = new Date(bItem.date); 79 | return (b.getTime() - a.getTime()); 80 | } 81 | 82 | /** 83 | * if the item is filtered, then return true. 84 | * @param item 85 | * @returns {boolean} 86 | */ 87 | function userFilter(item) { 88 | var filterScriptPath = userConfig.getFilterScriptPath(); 89 | if (filterScriptPath == null) { 90 | return true; 91 | } 92 | var canFilter = require(filterScriptPath); 93 | return canFilter(item); 94 | } 95 | 96 | function mergeData(list) { 97 | var existItems = listView.items; 98 | var existKeys = _.pluck(existItems, "id"); 99 | var newItems = list.filter(function (item) { 100 | return !_.contains(existKeys, item.id); 101 | }); 102 | console.log("new Item : " + newItems.length); 103 | if (newItems.length === 0) { 104 | return; 105 | } 106 | if (existItems.length !== 0) { 107 | var userFilteredItems = newItems.filter(userFilter); 108 | userFilteredItems.forEach(function (item, index) { 109 | setTimeout(function () { 110 | notifier.sendNotification({ 111 | id: item.id, 112 | title: item.repo_name, 113 | subtitle: item.user_name, 114 | icon: item.avatar_url, 115 | text: item.body, 116 | url: item.html_url 117 | }, function (error) { 118 | if (error) { 119 | console.error("Growl Error", error); 120 | } 121 | }); 122 | }, index * 1500); 123 | }); 124 | } 125 | var mergeItem = existItems.concat(newItems); 126 | listView.items = mergeItem.sort(sortDate); 127 | } 128 | 129 | function reloadData() { 130 | if (isSearchMode()) { 131 | return; 132 | } 133 | listView.displayItems = listView.items; 134 | } 135 | function filterByWord(word) { 136 | /* Filter target 137 | 138 | "user_name" 139 | "repo_name" 140 | "html_url" 141 | "body" 142 | */ 143 | function escapeRegExp(string) { 144 | return string.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1"); 145 | } 146 | 147 | var regexp = new RegExp(escapeRegExp(word), "i"); 148 | listView.displayItems = listView.items.filter(function (item) { 149 | return [item.user_name, item.repo_name, item.html_url, item.body].some(function (target) { 150 | return regexp.test(target); 151 | }) 152 | }); 153 | } 154 | function isSearchMode() { 155 | return listView.isSearchMode; 156 | } 157 | function toggleSearchMode() { 158 | listView.isSearchMode = !listView.isSearchMode; 159 | if (!listView.isSearchMode) { 160 | // remove search word when no search mode. 161 | reloadData(); 162 | } else { 163 | listView.selectedItem = null; 164 | } 165 | } 166 | 167 | function indexOfItem(item) { 168 | assert(listView != null, "listView doesn't initialize. Please call `reloadView`"); 169 | var items = listView.$data.displayItems; 170 | return items.indexOf(item); 171 | } 172 | function elementAtIndex(currentIndex) { 173 | var target = listView.$el; 174 | return target.children[currentIndex]; 175 | } 176 | 177 | notifier.addClickCallback(function (options) { 178 | var gui = global.window.nwDispatcher.requireNwGui(); 179 | var win = gui.Window.get(); 180 | win.focus(); 181 | var itemID = options.id; 182 | var matchItems = listView.displayItems.filter(function (item) { 183 | return item.id === itemID; 184 | }); 185 | if (matchItems.length > 0) { 186 | listView.loadHTMLView(matchItems[0]); 187 | } 188 | }); 189 | 190 | module.exports.elementAtIndex = elementAtIndex; 191 | module.exports.indexOfItem = indexOfItem; 192 | module.exports.mergeData = mergeData; 193 | module.exports.reloadData = reloadData; 194 | module.exports.reloadView = reloadView; 195 | module.exports.filterByWord = filterByWord; 196 | module.exports.toggleSearchMode = toggleSearchMode; 197 | module.exports.isSearchMode = isSearchMode; 198 | -------------------------------------------------------------------------------- /app/js/main/mainController.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by azu on 2014/04/23. 3 | * LICENSE : MIT 4 | */ 5 | "use strict"; 6 | var userData = require("../config/userData"); 7 | var scrollController = require("./scrollController"); 8 | var commentHeaderController = require("./commentHeaderViewController"); 9 | var listController = require("./listViewController"); 10 | var inputFocusController = require("./inputFocusController"); 11 | var Promise = require("bluebird"); 12 | var Mousetrap = require("mousetrap"); 13 | // gui is chrome context object 14 | module.exports = function (gui) { 15 | var commentHeaderView = commentHeaderController.reloadView(); 16 | var listView = listController.reloadView(); 17 | listView.$watch("selectedItem", function (item) { 18 | if (item == null) { 19 | return; 20 | } 21 | // update header 22 | commentHeaderController.updateWithItem(item); 23 | // Scroll position 24 | scrollController.scrollToTop(); 25 | var currentIndex = listController.indexOfItem(item); 26 | var cellElement = listController.elementAtIndex(currentIndex); 27 | if (!cellElement) { 28 | return; 29 | } 30 | window.setTimeout(function () { 31 | document.getElementById("content-list").scrollTop = cellElement.offsetTop - 50; 32 | }, 0); 33 | }); 34 | listView.$watch("searchWord", function (word) { 35 | listController.filterByWord(word); 36 | }); 37 | Mousetrap.bind('o', function () { 38 | var iframeURL = document.getElementById("github-iframe").src; 39 | if (!iframeURL) { 40 | return; 41 | } 42 | gui.Shell.openExternal(iframeURL); 43 | }); 44 | Mousetrap.bind('j', function () { 45 | listView.selectNextItem(); 46 | }); 47 | Mousetrap.bind('k', function () { 48 | listView.selectPrevItem(); 49 | }); 50 | Mousetrap.bind('r r', function () { 51 | console.log("reload"); 52 | reloadData(); 53 | }); 54 | ['command+f', 'ctrl+f'].forEach(function (key) { 55 | Mousetrap.bind(key, function () { 56 | listController.toggleSearchMode(); 57 | if (listController.isSearchMode()) { 58 | inputFocusController.focus(); 59 | } 60 | }) 61 | }); 62 | var timerID = setInterval(reloadData, require("../config/reloadConfig").getAutoReloadTime()); 63 | var githubClient = require("../github/github-client").newClient(userData); 64 | 65 | function reloadData() { 66 | console.log("reload"); 67 | var eventsPromise = githubClient.eventsAsPromise(userData.getUserData().name); 68 | var notificationsAsPromise = githubClient.notificationsAsPromise(); 69 | Promise.all([eventsPromise, notificationsAsPromise]).spread(function (events, notifications) { 70 | var builder = require("../github/response-builder"); 71 | var eventList = builder.buildEvents(events); 72 | var notificationList = builder.buildNotifications(notifications); 73 | listController.mergeData(eventList.concat(notificationList)); 74 | listController.reloadData(); 75 | }).catch(function (error) { 76 | console.log("ReloadData Error", error); 77 | }); 78 | } 79 | 80 | reloadData(); 81 | }; 82 | -------------------------------------------------------------------------------- /app/js/main/scrollController.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by azu on 2014/04/27. 3 | * LICENSE : MIT 4 | */ 5 | "use strict"; 6 | 7 | function scrollToTop() { 8 | document.documentElement.scrollTop = 0; 9 | } 10 | module.exports.scrollToTop = scrollToTop; 11 | -------------------------------------------------------------------------------- /app/js/notification/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/azu/github-reader/785a17c34f7f8e0d8fd6b7d06a0395428cfc5a48/app/js/notification/icon.png -------------------------------------------------------------------------------- /app/js/notification/notification.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by azu on 2014/04/29. 3 | * LICENSE : MIT 4 | */ 5 | "use strict"; 6 | 7 | var growl = require('node-notifier'); 8 | var EventEmitter = require('events').EventEmitter; 9 | var download = require('download-cache'); 10 | var notificationEvent = new EventEmitter(); 11 | var __CLICK_EVENT = "GROWL__CLICK_EVENT"; 12 | function addClickCallback(callback) { 13 | notificationEvent.on(__CLICK_EVENT, function (event, options) { 14 | callback(options); 15 | }); 16 | } 17 | growl.on('click', function (notifierObject, options) { 18 | notificationEvent.emit(__CLICK_EVENT, notifierObject, options) 19 | }); 20 | 21 | function sendNotification(options, callback) { 22 | download(options.icon).then(function (filePath) { 23 | growl.notify({ 24 | appIcon: __dirname + "/icon.png", 25 | id: options.id, 26 | title: options.title, 27 | message: options.text, 28 | icon: filePath, 29 | html_url: options.url, 30 | sound: true, // Only Notification Center or Windows Toasters 31 | wait: true // wait with callback until user action is taken on notification 32 | }, function (err, response) { 33 | if (err) { 34 | return callback(err); 35 | } 36 | }); 37 | }).catch(function (error) { 38 | callback(error); 39 | }); 40 | } 41 | module.exports = { 42 | addClickCallback: addClickCallback, 43 | sendNotification: sendNotification 44 | }; -------------------------------------------------------------------------------- /app/js/typings/ReceivedEvents.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "2070416128", 4 | "type": "PullRequestEvent", 5 | "actor": { 6 | "id": 1062518, 7 | "login": "pivotal-brian-croom", 8 | "gravatar_id": "92d36bd6d9b53539fcec282452872710", 9 | "url": "https://api.github.com/users/pivotal-brian-croom", 10 | "avatar_url": "https://avatars.githubusercontent.com/u/1062518?" 11 | }, 12 | "repo": { 13 | "id": 708684, 14 | "name": "pivotal/cedar", 15 | "url": "https://api.github.com/repos/pivotal/cedar" 16 | }, 17 | "payload": { 18 | "action": "opened", 19 | "number": 231, 20 | "pull_request": { 21 | "url": "https://api.github.com/repos/pivotal/cedar/pulls/231", 22 | "id": 15102666, 23 | "html_url": "https://github.com/pivotal/cedar/pull/231", 24 | "diff_url": "https://github.com/pivotal/cedar/pull/231.diff", 25 | "patch_url": "https://github.com/pivotal/cedar/pull/231.patch", 26 | "issue_url": "https://api.github.com/repos/pivotal/cedar/issues/231", 27 | "number": 231, 28 | "state": "open", 29 | "title": "Refactor test boot methods", 30 | "user": { 31 | "login": "pivotal-brian-croom", 32 | "id": 1062518, 33 | "avatar_url": "https://avatars.githubusercontent.com/u/1062518?", 34 | "gravatar_id": "92d36bd6d9b53539fcec282452872710", 35 | "url": "https://api.github.com/users/pivotal-brian-croom", 36 | "html_url": "https://github.com/pivotal-brian-croom", 37 | "followers_url": "https://api.github.com/users/pivotal-brian-croom/followers", 38 | "following_url": "https://api.github.com/users/pivotal-brian-croom/following{/other_user}", 39 | "gists_url": "https://api.github.com/users/pivotal-brian-croom/gists{/gist_id}", 40 | "starred_url": "https://api.github.com/users/pivotal-brian-croom/starred{/owner}{/repo}", 41 | "subscriptions_url": "https://api.github.com/users/pivotal-brian-croom/subscriptions", 42 | "organizations_url": "https://api.github.com/users/pivotal-brian-croom/orgs", 43 | "repos_url": "https://api.github.com/users/pivotal-brian-croom/repos", 44 | "events_url": "https://api.github.com/users/pivotal-brian-croom/events{/privacy}", 45 | "received_events_url": "https://api.github.com/users/pivotal-brian-croom/received_events", 46 | "type": "User", 47 | "site_admin": false 48 | }, 49 | "body": "- Common code consolidated into CDROTestRunner and CDROTestIPhoneRunner\r\n- CDROTestIPhoneRunner subclasses CDROTestRunner\r\n[#67878220]\r\n\r\nThoughts?\r\n@idoru, @jeffh", 50 | "created_at": "2014-04-24T05:01:39Z", 51 | "updated_at": "2014-04-24T05:01:39Z", 52 | "closed_at": null, 53 | "merged_at": null, 54 | "merge_commit_sha": null, 55 | "assignee": null, 56 | "milestone": null, 57 | "commits_url": "https://api.github.com/repos/pivotal/cedar/pulls/231/commits", 58 | "review_comments_url": "https://api.github.com/repos/pivotal/cedar/pulls/231/comments", 59 | "review_comment_url": "https://api.github.com/repos/pivotal/cedar/pulls/comments/{number}", 60 | "comments_url": "https://api.github.com/repos/pivotal/cedar/issues/231/comments", 61 | "statuses_url": "https://api.github.com/repos/pivotal/cedar/statuses/196e2ba6c2f35302ff4a6534943bddc798d726ad", 62 | "head": { 63 | "label": "pivotal-brian-croom:refactor-boot-methods", 64 | "ref": "refactor-boot-methods", 65 | "sha": "196e2ba6c2f35302ff4a6534943bddc798d726ad", 66 | "user": { 67 | "login": "pivotal-brian-croom", 68 | "id": 1062518, 69 | "avatar_url": "https://avatars.githubusercontent.com/u/1062518?", 70 | "gravatar_id": "92d36bd6d9b53539fcec282452872710", 71 | "url": "https://api.github.com/users/pivotal-brian-croom", 72 | "html_url": "https://github.com/pivotal-brian-croom", 73 | "followers_url": "https://api.github.com/users/pivotal-brian-croom/followers", 74 | "following_url": "https://api.github.com/users/pivotal-brian-croom/following{/other_user}", 75 | "gists_url": "https://api.github.com/users/pivotal-brian-croom/gists{/gist_id}", 76 | "starred_url": "https://api.github.com/users/pivotal-brian-croom/starred{/owner}{/repo}", 77 | "subscriptions_url": "https://api.github.com/users/pivotal-brian-croom/subscriptions", 78 | "organizations_url": "https://api.github.com/users/pivotal-brian-croom/orgs", 79 | "repos_url": "https://api.github.com/users/pivotal-brian-croom/repos", 80 | "events_url": "https://api.github.com/users/pivotal-brian-croom/events{/privacy}", 81 | "received_events_url": "https://api.github.com/users/pivotal-brian-croom/received_events", 82 | "type": "User", 83 | "site_admin": false 84 | }, 85 | "repo": { 86 | "id": 18118188, 87 | "name": "cedar", 88 | "full_name": "pivotal-brian-croom/cedar", 89 | "owner": { 90 | "login": "pivotal-brian-croom", 91 | "id": 1062518, 92 | "avatar_url": "https://avatars.githubusercontent.com/u/1062518?", 93 | "gravatar_id": "92d36bd6d9b53539fcec282452872710", 94 | "url": "https://api.github.com/users/pivotal-brian-croom", 95 | "html_url": "https://github.com/pivotal-brian-croom", 96 | "followers_url": "https://api.github.com/users/pivotal-brian-croom/followers", 97 | "following_url": "https://api.github.com/users/pivotal-brian-croom/following{/other_user}", 98 | "gists_url": "https://api.github.com/users/pivotal-brian-croom/gists{/gist_id}", 99 | "starred_url": "https://api.github.com/users/pivotal-brian-croom/starred{/owner}{/repo}", 100 | "subscriptions_url": "https://api.github.com/users/pivotal-brian-croom/subscriptions", 101 | "organizations_url": "https://api.github.com/users/pivotal-brian-croom/orgs", 102 | "repos_url": "https://api.github.com/users/pivotal-brian-croom/repos", 103 | "events_url": "https://api.github.com/users/pivotal-brian-croom/events{/privacy}", 104 | "received_events_url": "https://api.github.com/users/pivotal-brian-croom/received_events", 105 | "type": "User", 106 | "site_admin": false 107 | }, 108 | "private": false, 109 | "html_url": "https://github.com/pivotal-brian-croom/cedar", 110 | "description": "BDD-style testing using Objective-C", 111 | "fork": true, 112 | "url": "https://api.github.com/repos/pivotal-brian-croom/cedar", 113 | "forks_url": "https://api.github.com/repos/pivotal-brian-croom/cedar/forks", 114 | "keys_url": "https://api.github.com/repos/pivotal-brian-croom/cedar/keys{/key_id}", 115 | "collaborators_url": "https://api.github.com/repos/pivotal-brian-croom/cedar/collaborators{/collaborator}", 116 | "teams_url": "https://api.github.com/repos/pivotal-brian-croom/cedar/teams", 117 | "hooks_url": "https://api.github.com/repos/pivotal-brian-croom/cedar/hooks", 118 | "issue_events_url": "https://api.github.com/repos/pivotal-brian-croom/cedar/issues/events{/number}", 119 | "events_url": "https://api.github.com/repos/pivotal-brian-croom/cedar/events", 120 | "assignees_url": "https://api.github.com/repos/pivotal-brian-croom/cedar/assignees{/user}", 121 | "branches_url": "https://api.github.com/repos/pivotal-brian-croom/cedar/branches{/branch}", 122 | "tags_url": "https://api.github.com/repos/pivotal-brian-croom/cedar/tags", 123 | "blobs_url": "https://api.github.com/repos/pivotal-brian-croom/cedar/git/blobs{/sha}", 124 | "git_tags_url": "https://api.github.com/repos/pivotal-brian-croom/cedar/git/tags{/sha}", 125 | "git_refs_url": "https://api.github.com/repos/pivotal-brian-croom/cedar/git/refs{/sha}", 126 | "trees_url": "https://api.github.com/repos/pivotal-brian-croom/cedar/git/trees{/sha}", 127 | "statuses_url": "https://api.github.com/repos/pivotal-brian-croom/cedar/statuses/{sha}", 128 | "languages_url": "https://api.github.com/repos/pivotal-brian-croom/cedar/languages", 129 | "stargazers_url": "https://api.github.com/repos/pivotal-brian-croom/cedar/stargazers", 130 | "contributors_url": "https://api.github.com/repos/pivotal-brian-croom/cedar/contributors", 131 | "subscribers_url": "https://api.github.com/repos/pivotal-brian-croom/cedar/subscribers", 132 | "subscription_url": "https://api.github.com/repos/pivotal-brian-croom/cedar/subscription", 133 | "commits_url": "https://api.github.com/repos/pivotal-brian-croom/cedar/commits{/sha}", 134 | "git_commits_url": "https://api.github.com/repos/pivotal-brian-croom/cedar/git/commits{/sha}", 135 | "comments_url": "https://api.github.com/repos/pivotal-brian-croom/cedar/comments{/number}", 136 | "issue_comment_url": "https://api.github.com/repos/pivotal-brian-croom/cedar/issues/comments/{number}", 137 | "contents_url": "https://api.github.com/repos/pivotal-brian-croom/cedar/contents/{+path}", 138 | "compare_url": "https://api.github.com/repos/pivotal-brian-croom/cedar/compare/{base}...{head}", 139 | "merges_url": "https://api.github.com/repos/pivotal-brian-croom/cedar/merges", 140 | "archive_url": "https://api.github.com/repos/pivotal-brian-croom/cedar/{archive_format}{/ref}", 141 | "downloads_url": "https://api.github.com/repos/pivotal-brian-croom/cedar/downloads", 142 | "issues_url": "https://api.github.com/repos/pivotal-brian-croom/cedar/issues{/number}", 143 | "pulls_url": "https://api.github.com/repos/pivotal-brian-croom/cedar/pulls{/number}", 144 | "milestones_url": "https://api.github.com/repos/pivotal-brian-croom/cedar/milestones{/number}", 145 | "notifications_url": "https://api.github.com/repos/pivotal-brian-croom/cedar/notifications{?since,all,participating}", 146 | "labels_url": "https://api.github.com/repos/pivotal-brian-croom/cedar/labels{/name}", 147 | "releases_url": "https://api.github.com/repos/pivotal-brian-croom/cedar/releases{/id}", 148 | "created_at": "2014-03-25T22:03:41Z", 149 | "updated_at": "2014-04-24T05:01:39Z", 150 | "pushed_at": "2014-04-24T04:58:41Z", 151 | "git_url": "git://github.com/pivotal-brian-croom/cedar.git", 152 | "ssh_url": "git@github.com:pivotal-brian-croom/cedar.git", 153 | "clone_url": "https://github.com/pivotal-brian-croom/cedar.git", 154 | "svn_url": "https://github.com/pivotal-brian-croom/cedar", 155 | "homepage": "http://groups.google.com/group/cedar-discuss", 156 | "size": 3067, 157 | "stargazers_count": 0, 158 | "watchers_count": 0, 159 | "language": "Objective-C", 160 | "has_issues": false, 161 | "has_downloads": true, 162 | "has_wiki": true, 163 | "forks_count": 0, 164 | "mirror_url": null, 165 | "open_issues_count": 0, 166 | "forks": 0, 167 | "open_issues": 0, 168 | "watchers": 0, 169 | "default_branch": "master" 170 | } 171 | }, 172 | "base": { 173 | "label": "pivotal:master", 174 | "ref": "master", 175 | "sha": "12d925bb7c1d5f53d759ac6c612be12953b61593", 176 | "user": { 177 | "login": "pivotal", 178 | "id": 9148, 179 | "avatar_url": "https://avatars.githubusercontent.com/u/9148?", 180 | "gravatar_id": "9f7ca4684008e71a26ff490caa985d8b", 181 | "url": "https://api.github.com/users/pivotal", 182 | "html_url": "https://github.com/pivotal", 183 | "followers_url": "https://api.github.com/users/pivotal/followers", 184 | "following_url": "https://api.github.com/users/pivotal/following{/other_user}", 185 | "gists_url": "https://api.github.com/users/pivotal/gists{/gist_id}", 186 | "starred_url": "https://api.github.com/users/pivotal/starred{/owner}{/repo}", 187 | "subscriptions_url": "https://api.github.com/users/pivotal/subscriptions", 188 | "organizations_url": "https://api.github.com/users/pivotal/orgs", 189 | "repos_url": "https://api.github.com/users/pivotal/repos", 190 | "events_url": "https://api.github.com/users/pivotal/events{/privacy}", 191 | "received_events_url": "https://api.github.com/users/pivotal/received_events", 192 | "type": "Organization", 193 | "site_admin": false 194 | }, 195 | "repo": { 196 | "id": 708684, 197 | "name": "cedar", 198 | "full_name": "pivotal/cedar", 199 | "owner": { 200 | "login": "pivotal", 201 | "id": 9148, 202 | "avatar_url": "https://avatars.githubusercontent.com/u/9148?", 203 | "gravatar_id": "9f7ca4684008e71a26ff490caa985d8b", 204 | "url": "https://api.github.com/users/pivotal", 205 | "html_url": "https://github.com/pivotal", 206 | "followers_url": "https://api.github.com/users/pivotal/followers", 207 | "following_url": "https://api.github.com/users/pivotal/following{/other_user}", 208 | "gists_url": "https://api.github.com/users/pivotal/gists{/gist_id}", 209 | "starred_url": "https://api.github.com/users/pivotal/starred{/owner}{/repo}", 210 | "subscriptions_url": "https://api.github.com/users/pivotal/subscriptions", 211 | "organizations_url": "https://api.github.com/users/pivotal/orgs", 212 | "repos_url": "https://api.github.com/users/pivotal/repos", 213 | "events_url": "https://api.github.com/users/pivotal/events{/privacy}", 214 | "received_events_url": "https://api.github.com/users/pivotal/received_events", 215 | "type": "Organization", 216 | "site_admin": false 217 | }, 218 | "private": false, 219 | "html_url": "https://github.com/pivotal/cedar", 220 | "description": "BDD-style testing using Objective-C", 221 | "fork": false, 222 | "url": "https://api.github.com/repos/pivotal/cedar", 223 | "forks_url": "https://api.github.com/repos/pivotal/cedar/forks", 224 | "keys_url": "https://api.github.com/repos/pivotal/cedar/keys{/key_id}", 225 | "collaborators_url": "https://api.github.com/repos/pivotal/cedar/collaborators{/collaborator}", 226 | "teams_url": "https://api.github.com/repos/pivotal/cedar/teams", 227 | "hooks_url": "https://api.github.com/repos/pivotal/cedar/hooks", 228 | "issue_events_url": "https://api.github.com/repos/pivotal/cedar/issues/events{/number}", 229 | "events_url": "https://api.github.com/repos/pivotal/cedar/events", 230 | "assignees_url": "https://api.github.com/repos/pivotal/cedar/assignees{/user}", 231 | "branches_url": "https://api.github.com/repos/pivotal/cedar/branches{/branch}", 232 | "tags_url": "https://api.github.com/repos/pivotal/cedar/tags", 233 | "blobs_url": "https://api.github.com/repos/pivotal/cedar/git/blobs{/sha}", 234 | "git_tags_url": "https://api.github.com/repos/pivotal/cedar/git/tags{/sha}", 235 | "git_refs_url": "https://api.github.com/repos/pivotal/cedar/git/refs{/sha}", 236 | "trees_url": "https://api.github.com/repos/pivotal/cedar/git/trees{/sha}", 237 | "statuses_url": "https://api.github.com/repos/pivotal/cedar/statuses/{sha}", 238 | "languages_url": "https://api.github.com/repos/pivotal/cedar/languages", 239 | "stargazers_url": "https://api.github.com/repos/pivotal/cedar/stargazers", 240 | "contributors_url": "https://api.github.com/repos/pivotal/cedar/contributors", 241 | "subscribers_url": "https://api.github.com/repos/pivotal/cedar/subscribers", 242 | "subscription_url": "https://api.github.com/repos/pivotal/cedar/subscription", 243 | "commits_url": "https://api.github.com/repos/pivotal/cedar/commits{/sha}", 244 | "git_commits_url": "https://api.github.com/repos/pivotal/cedar/git/commits{/sha}", 245 | "comments_url": "https://api.github.com/repos/pivotal/cedar/comments{/number}", 246 | "issue_comment_url": "https://api.github.com/repos/pivotal/cedar/issues/comments/{number}", 247 | "contents_url": "https://api.github.com/repos/pivotal/cedar/contents/{+path}", 248 | "compare_url": "https://api.github.com/repos/pivotal/cedar/compare/{base}...{head}", 249 | "merges_url": "https://api.github.com/repos/pivotal/cedar/merges", 250 | "archive_url": "https://api.github.com/repos/pivotal/cedar/{archive_format}{/ref}", 251 | "downloads_url": "https://api.github.com/repos/pivotal/cedar/downloads", 252 | "issues_url": "https://api.github.com/repos/pivotal/cedar/issues{/number}", 253 | "pulls_url": "https://api.github.com/repos/pivotal/cedar/pulls{/number}", 254 | "milestones_url": "https://api.github.com/repos/pivotal/cedar/milestones{/number}", 255 | "notifications_url": "https://api.github.com/repos/pivotal/cedar/notifications{?since,all,participating}", 256 | "labels_url": "https://api.github.com/repos/pivotal/cedar/labels{/name}", 257 | "releases_url": "https://api.github.com/repos/pivotal/cedar/releases{/id}", 258 | "created_at": "2010-06-08T01:34:14Z", 259 | "updated_at": "2014-04-23T03:57:29Z", 260 | "pushed_at": "2014-04-23T03:57:28Z", 261 | "git_url": "git://github.com/pivotal/cedar.git", 262 | "ssh_url": "git@github.com:pivotal/cedar.git", 263 | "clone_url": "https://github.com/pivotal/cedar.git", 264 | "svn_url": "https://github.com/pivotal/cedar", 265 | "homepage": "http://groups.google.com/group/cedar-discuss", 266 | "size": 6672, 267 | "stargazers_count": 769, 268 | "watchers_count": 769, 269 | "language": "Objective-C", 270 | "has_issues": true, 271 | "has_downloads": true, 272 | "has_wiki": true, 273 | "forks_count": 110, 274 | "mirror_url": null, 275 | "open_issues_count": 11, 276 | "forks": 110, 277 | "open_issues": 11, 278 | "watchers": 769, 279 | "default_branch": "master" 280 | } 281 | }, 282 | "_links": { 283 | "self": { 284 | "href": "https://api.github.com/repos/pivotal/cedar/pulls/231" 285 | }, 286 | "html": { 287 | "href": "https://github.com/pivotal/cedar/pull/231" 288 | }, 289 | "issue": { 290 | "href": "https://api.github.com/repos/pivotal/cedar/issues/231" 291 | }, 292 | "comments": { 293 | "href": "https://api.github.com/repos/pivotal/cedar/issues/231/comments" 294 | }, 295 | "review_comments": { 296 | "href": "https://api.github.com/repos/pivotal/cedar/pulls/231/comments" 297 | }, 298 | "review_comment": { 299 | "href": "https://api.github.com/repos/pivotal/cedar/pulls/comments/{number}" 300 | }, 301 | "commits": { 302 | "href": "https://api.github.com/repos/pivotal/cedar/pulls/231/commits" 303 | }, 304 | "statuses": { 305 | "href": "https://api.github.com/repos/pivotal/cedar/statuses/196e2ba6c2f35302ff4a6534943bddc798d726ad" 306 | } 307 | }, 308 | "merged": false, 309 | "mergeable": null, 310 | "mergeable_state": "unknown", 311 | "merged_by": null, 312 | "comments": 0, 313 | "review_comments": 0, 314 | "commits": 1, 315 | "additions": 143, 316 | "deletions": 122, 317 | "changed_files": 11 318 | } 319 | }, 320 | "public": true, 321 | "created_at": "2014-04-24T05:01:39Z", 322 | "org": { 323 | "id": 9148, 324 | "login": "pivotal", 325 | "gravatar_id": "9f7ca4684008e71a26ff490caa985d8b", 326 | "url": "https://api.github.com/orgs/pivotal", 327 | "avatar_url": "https://avatars.githubusercontent.com/u/9148?" 328 | } 329 | }, 330 | { 331 | "id": "2070414830", 332 | "type": "CreateEvent", 333 | "actor": { 334 | "id": 12631, 335 | "login": "substack", 336 | "gravatar_id": "d4a2f12ceae3b7f211b661576d22bfb9", 337 | "url": "https://api.github.com/users/substack", 338 | "avatar_url": "https://avatars.githubusercontent.com/u/12631?" 339 | }, 340 | "repo": { 341 | "id": 19096306, 342 | "name": "substack/scrux", 343 | "url": "https://api.github.com/repos/substack/scrux" 344 | }, 345 | "payload": { 346 | "ref": null, 347 | "ref_type": "repository", 348 | "master_branch": "master", 349 | "description": "screen reader terminal multiplexer", 350 | "pusher_type": "user" 351 | }, 352 | "public": true, 353 | "created_at": "2014-04-24T04:59:35Z" 354 | }, 355 | { 356 | "id": "2070406273", 357 | "type": "IssueCommentEvent", 358 | "actor": { 359 | "id": 1315816, 360 | "login": "jamesmortensen", 361 | "gravatar_id": "5b36a81be1209394d5b70daa1767e0d7", 362 | "url": "https://api.github.com/users/jamesmortensen", 363 | "avatar_url": "https://avatars.githubusercontent.com/u/1315816?" 364 | }, 365 | "repo": { 366 | "id": 1451352, 367 | "name": "visionmedia/mocha", 368 | "url": "https://api.github.com/repos/visionmedia/mocha" 369 | }, 370 | "payload": { 371 | "action": "created", 372 | "issue": { 373 | "url": "https://api.github.com/repos/visionmedia/mocha/issues/960", 374 | "labels_url": "https://api.github.com/repos/visionmedia/mocha/issues/960/labels{/name}", 375 | "comments_url": "https://api.github.com/repos/visionmedia/mocha/issues/960/comments", 376 | "events_url": "https://api.github.com/repos/visionmedia/mocha/issues/960/events", 377 | "html_url": "https://github.com/visionmedia/mocha/issues/960", 378 | "id": 18534362, 379 | "number": 960, 380 | "title": "Feature request: make it possible for Mocha to run on node-webkit without a complex workaround", 381 | "user": { 382 | "login": "Mithgol", 383 | "id": 1088720, 384 | "avatar_url": "https://avatars.githubusercontent.com/u/1088720?", 385 | "gravatar_id": "794261fc53b3e7ea6ba2d19a4f265803", 386 | "url": "https://api.github.com/users/Mithgol", 387 | "html_url": "https://github.com/Mithgol", 388 | "followers_url": "https://api.github.com/users/Mithgol/followers", 389 | "following_url": "https://api.github.com/users/Mithgol/following{/other_user}", 390 | "gists_url": "https://api.github.com/users/Mithgol/gists{/gist_id}", 391 | "starred_url": "https://api.github.com/users/Mithgol/starred{/owner}{/repo}", 392 | "subscriptions_url": "https://api.github.com/users/Mithgol/subscriptions", 393 | "organizations_url": "https://api.github.com/users/Mithgol/orgs", 394 | "repos_url": "https://api.github.com/users/Mithgol/repos", 395 | "events_url": "https://api.github.com/users/Mithgol/events{/privacy}", 396 | "received_events_url": "https://api.github.com/users/Mithgol/received_events", 397 | "type": "User", 398 | "site_admin": false 399 | }, 400 | "labels": [], 401 | "state": "closed", 402 | "assignee": null, 403 | "milestone": null, 404 | "comments": 4, 405 | "created_at": "2013-08-26T05:48:44Z", 406 | "updated_at": "2014-04-24T04:46:01Z", 407 | "closed_at": "2013-12-07T20:34:36Z", 408 | "body": "As some of you might already know, **[node-webkit](https://github.com/rogerwang/node-webkit/)** is a fine amalgamation of the [Node](http://nodejs.org/)'s API and a WebKit-based (Chromium-based) web browser. The resulting engine makes it possible for cross-platform GUI applications (for Windows, Mac OS X and Linux) to be developed with web technologies (HTML, CSS, JS, WebGL, etc.), their windows are essentially “local webpages” using [Node API](http://nodejs.org/docs/latest/api/) to access the underlying system.\r\n\r\nAnd it's quite possible to use [existing Node modules](https://github.com/rogerwang/node-webkit/wiki/Using-Node-modules) in a node-webkit-based application.\r\n\r\nHowever, when I try running Mocha on node-webkit, there's an issue.\r\n\r\nMost of Mocha's reporters use `console.log` output with ANSI commands to define colours and to move the cursor. However, inside the node-webkit `console.log()` is [rerouted to the WebKit's “Developer Tools” window,](https://github.com/rogerwang/node-webkit/wiki/Changes-related-to-node#console) and the reports of Mocha are far from being pretty there.\r\n\r\nMocha does also have [a browser-oriented reporter,](http://visionmedia.github.io/mocha/#browser-support) but, when it runs on node-webkit, there are two problems with it:\r\n\r\n* It tries to create some minimal versions for a couple of Node interfaces (`require` and `process`), though both exist in node-webkit and have their complete form.\r\n\r\n* It does not walk through the `test/` subdirectory; the tests have to be enumerated (as ``) below.\r\n\r\nThat's because the reporter thinks it has only browser's interfaces in its avail, while actually it could also use Node API in node-webkit.\r\n\r\nOf course, there's always a workaround. For example, the authors of node-webkit still use Mocha for testing. It is possible to read [`/tests/index.html`](https://github.com/rogerwang/node-webkit/blob/925d1e03dfd74f045169f74f88464f9dc4b3748c/tests/index.html) and discover how it has been done:\r\n\r\n* The Node API objects [are hidden](https://github.com/rogerwang/node-webkit/blob/925d1e03dfd74f045169f74f88464f9dc4b3748c/tests/index.html#L6-13) from the Mocha's browser-oriented reporter:\r\n\r\n```html\r\n\r\n```\r\n\r\n* These objects [are then restored](https://github.com/rogerwang/node-webkit/blob/925d1e03dfd74f045169f74f88464f9dc4b3748c/tests/index.html#L19-24) in their original form, replacing the reporter's minimalistic mockups:\r\n\r\n```html\r\n\r\n```\r\n\r\n* Mocha is [used programmatically](https://github.com/visionmedia/mocha/wiki/Using-mocha-programmatically). A wrapper script discovers the necessary options and traverses subdirectories in a search for tests.\r\n\r\nHowever, that workaround is a complex one. It's unreasonable to expect the end users of node-webkit to be willing to repeat all these steps to run Mocha tests for their node-webkit-based applications.\r\n\r\nHence the feature request.\r\n\r\nPlease make a node-webkit-oriented reporter.\r\n\r\nIt should be similar to the browser-oriented reporter (should make some HTML output inside a `
`), with a couple of differences:\r\n\r\n* It should expect (and use) Node API instead of building its own versions of them.\r\n\r\n* It should use Node API to walk through the `test/` subdirectory for tests. These tests should then run in the same window's context (by adding `` to the DOM) instead of the Node's isolated context (`require()`), because the tests should have access to that window's DOM.\r\n\r\nThe reporter could check `process.versions['node-webkit']` to ensure that it's indeed running on node-webkit (not in a traditional web browser, not on a vanilla Node.js, not on some other Node+browser system such as [AppJS.)](https://github.com/appjs/appjs)" 409 | }, 410 | "comment": { 411 | "url": "https://api.github.com/repos/visionmedia/mocha/issues/comments/41242251", 412 | "html_url": "https://github.com/visionmedia/mocha/issues/960#issuecomment-41242251", 413 | "issue_url": "https://api.github.com/repos/visionmedia/mocha/issues/960", 414 | "id": 41242251, 415 | "user": { 416 | "login": "jamesmortensen", 417 | "id": 1315816, 418 | "avatar_url": "https://avatars.githubusercontent.com/u/1315816?", 419 | "gravatar_id": "5b36a81be1209394d5b70daa1767e0d7", 420 | "url": "https://api.github.com/users/jamesmortensen", 421 | "html_url": "https://github.com/jamesmortensen", 422 | "followers_url": "https://api.github.com/users/jamesmortensen/followers", 423 | "following_url": "https://api.github.com/users/jamesmortensen/following{/other_user}", 424 | "gists_url": "https://api.github.com/users/jamesmortensen/gists{/gist_id}", 425 | "starred_url": "https://api.github.com/users/jamesmortensen/starred{/owner}{/repo}", 426 | "subscriptions_url": "https://api.github.com/users/jamesmortensen/subscriptions", 427 | "organizations_url": "https://api.github.com/users/jamesmortensen/orgs", 428 | "repos_url": "https://api.github.com/users/jamesmortensen/repos", 429 | "events_url": "https://api.github.com/users/jamesmortensen/events{/privacy}", 430 | "received_events_url": "https://api.github.com/users/jamesmortensen/received_events", 431 | "type": "User", 432 | "site_admin": false 433 | }, 434 | "created_at": "2014-04-24T04:46:01Z", 435 | "updated_at": "2014-04-24T04:46:01Z", 436 | "body": "It's also worth noting that after about v1.12.0 of Mocha, even the workarounds don't work anymore. Thus, this means node-webkit developers are relying on outdated versions of Mocha to operate." 437 | } 438 | }, 439 | "public": true, 440 | "created_at": "2014-04-24T04:46:01Z" 441 | }, 442 | { 443 | "id": "2070404467", 444 | "type": "GollumEvent", 445 | "actor": { 446 | "id": 53785, 447 | "login": "jaekwon", 448 | "gravatar_id": "44f47adfcff58848fd96e055c04437d0", 449 | "url": "https://api.github.com/users/jaekwon", 450 | "avatar_url": "https://avatars.githubusercontent.com/u/53785?" 451 | }, 452 | "repo": { 453 | "id": 211666, 454 | "name": "joyent/node", 455 | "url": "https://api.github.com/repos/joyent/node" 456 | }, 457 | "payload": { 458 | "pages": [ 459 | { 460 | "page_name": "Modules", 461 | "title": "Modules", 462 | "summary": null, 463 | "action": "edited", 464 | "sha": "cfeed05ff833685a4c92ec90cea27532d8931ff0", 465 | "html_url": "https://github.com/joyent/node/wiki/Modules" 466 | } 467 | ] 468 | }, 469 | "public": true, 470 | "created_at": "2014-04-24T04:42:57Z", 471 | "org": { 472 | "id": 10161, 473 | "login": "joyent", 474 | "gravatar_id": "95c8b4070c2ba024f87a8fdca63e9d24", 475 | "url": "https://api.github.com/orgs/joyent", 476 | "avatar_url": "https://avatars.githubusercontent.com/u/10161?" 477 | } 478 | }, 479 | { 480 | "id": "2070387951", 481 | "type": "WatchEvent", 482 | "actor": { 483 | "id": 66100, 484 | "login": "taichi", 485 | "gravatar_id": "bb720baee7aef49cecf54dbd91e8c57a", 486 | "url": "https://api.github.com/users/taichi", 487 | "avatar_url": "https://avatars.githubusercontent.com/u/66100?" 488 | }, 489 | "repo": { 490 | "id": 15437343, 491 | "name": "docker-atlassian/stash", 492 | "url": "https://api.github.com/repos/docker-atlassian/stash" 493 | }, 494 | "payload": { 495 | "action": "started" 496 | }, 497 | "public": true, 498 | "created_at": "2014-04-24T04:15:07Z" 499 | }, 500 | { 501 | "id": "2070387377", 502 | "type": "WatchEvent", 503 | "actor": { 504 | "id": 66100, 505 | "login": "taichi", 506 | "gravatar_id": "bb720baee7aef49cecf54dbd91e8c57a", 507 | "url": "https://api.github.com/users/taichi", 508 | "avatar_url": "https://avatars.githubusercontent.com/u/66100?" 509 | }, 510 | "repo": { 511 | "id": 15406929, 512 | "name": "docker-atlassian/jira", 513 | "url": "https://api.github.com/repos/docker-atlassian/jira" 514 | }, 515 | "payload": { 516 | "action": "started" 517 | }, 518 | "public": true, 519 | "created_at": "2014-04-24T04:14:12Z" 520 | }, 521 | { 522 | "id": "2070386659", 523 | "type": "WatchEvent", 524 | "actor": { 525 | "id": 66100, 526 | "login": "taichi", 527 | "gravatar_id": "bb720baee7aef49cecf54dbd91e8c57a", 528 | "url": "https://api.github.com/users/taichi", 529 | "avatar_url": "https://avatars.githubusercontent.com/u/66100?" 530 | }, 531 | "repo": { 532 | "id": 18286232, 533 | "name": "GitbookIO/javascript", 534 | "url": "https://api.github.com/repos/GitbookIO/javascript" 535 | }, 536 | "payload": { 537 | "action": "started" 538 | }, 539 | "public": true, 540 | "created_at": "2014-04-24T04:13:04Z", 541 | "org": { 542 | "id": 7111340, 543 | "login": "GitbookIO", 544 | "gravatar_id": null, 545 | "url": "https://api.github.com/orgs/GitbookIO", 546 | "avatar_url": "https://avatars.githubusercontent.com/u/7111340?" 547 | } 548 | }, 549 | { 550 | "id": "2070386134", 551 | "type": "WatchEvent", 552 | "actor": { 553 | "id": 66100, 554 | "login": "taichi", 555 | "gravatar_id": "bb720baee7aef49cecf54dbd91e8c57a", 556 | "url": "https://api.github.com/users/taichi", 557 | "avatar_url": "https://avatars.githubusercontent.com/u/66100?" 558 | }, 559 | "repo": { 560 | "id": 18655678, 561 | "name": "GitbookIO/editor", 562 | "url": "https://api.github.com/repos/GitbookIO/editor" 563 | }, 564 | "payload": { 565 | "action": "started" 566 | }, 567 | "public": true, 568 | "created_at": "2014-04-24T04:12:13Z", 569 | "org": { 570 | "id": 7111340, 571 | "login": "GitbookIO", 572 | "gravatar_id": null, 573 | "url": "https://api.github.com/orgs/GitbookIO", 574 | "avatar_url": "https://avatars.githubusercontent.com/u/7111340?" 575 | } 576 | }, 577 | { 578 | "id": "2070385250", 579 | "type": "IssueCommentEvent", 580 | "actor": { 581 | "id": 201344, 582 | "login": "lazd", 583 | "gravatar_id": "764bf1eb322b51f2db54f2e09266d5be", 584 | "url": "https://api.github.com/users/lazd", 585 | "avatar_url": "https://avatars.githubusercontent.com/u/201344?" 586 | }, 587 | "repo": { 588 | "id": 2560988, 589 | "name": "karma-runner/karma", 590 | "url": "https://api.github.com/repos/karma-runner/karma" 591 | }, 592 | "payload": { 593 | "action": "created", 594 | "issue": { 595 | "url": "https://api.github.com/repos/karma-runner/karma/issues/1037", 596 | "labels_url": "https://api.github.com/repos/karma-runner/karma/issues/1037/labels{/name}", 597 | "comments_url": "https://api.github.com/repos/karma-runner/karma/issues/1037/comments", 598 | "events_url": "https://api.github.com/repos/karma-runner/karma/issues/1037/events", 599 | "html_url": "https://github.com/karma-runner/karma/issues/1037", 600 | "id": 31779825, 601 | "number": 1037, 602 | "title": "Public API does not provide hooks for server started, all browsers captured, etc", 603 | "user": { 604 | "login": "lazd", 605 | "id": 201344, 606 | "avatar_url": "https://avatars.githubusercontent.com/u/201344?", 607 | "gravatar_id": "764bf1eb322b51f2db54f2e09266d5be", 608 | "url": "https://api.github.com/users/lazd", 609 | "html_url": "https://github.com/lazd", 610 | "followers_url": "https://api.github.com/users/lazd/followers", 611 | "following_url": "https://api.github.com/users/lazd/following{/other_user}", 612 | "gists_url": "https://api.github.com/users/lazd/gists{/gist_id}", 613 | "starred_url": "https://api.github.com/users/lazd/starred{/owner}{/repo}", 614 | "subscriptions_url": "https://api.github.com/users/lazd/subscriptions", 615 | "organizations_url": "https://api.github.com/users/lazd/orgs", 616 | "repos_url": "https://api.github.com/users/lazd/repos", 617 | "events_url": "https://api.github.com/users/lazd/events{/privacy}", 618 | "received_events_url": "https://api.github.com/users/lazd/received_events", 619 | "type": "User", 620 | "site_admin": false 621 | }, 622 | "labels": [ 623 | { 624 | "url": "https://api.github.com/repos/karma-runner/karma/labels/type%3A+feature", 625 | "name": "type: feature", 626 | "color": "02e10c" 627 | } 628 | ], 629 | "state": "open", 630 | "assignee": null, 631 | "milestone": { 632 | "url": "https://api.github.com/repos/karma-runner/karma/milestones/4", 633 | "labels_url": "https://api.github.com/repos/karma-runner/karma/milestones/4/labels", 634 | "id": 611486, 635 | "number": 4, 636 | "title": "Backlog", 637 | "description": "Holds the backlog of issues and pull requests that have been triaged.", 638 | "creator": { 639 | "login": "vojtajina", 640 | "id": 46647, 641 | "avatar_url": "https://avatars.githubusercontent.com/u/46647?", 642 | "gravatar_id": "d59bdceef864e67df13167d806d6da63", 643 | "url": "https://api.github.com/users/vojtajina", 644 | "html_url": "https://github.com/vojtajina", 645 | "followers_url": "https://api.github.com/users/vojtajina/followers", 646 | "following_url": "https://api.github.com/users/vojtajina/following{/other_user}", 647 | "gists_url": "https://api.github.com/users/vojtajina/gists{/gist_id}", 648 | "starred_url": "https://api.github.com/users/vojtajina/starred{/owner}{/repo}", 649 | "subscriptions_url": "https://api.github.com/users/vojtajina/subscriptions", 650 | "organizations_url": "https://api.github.com/users/vojtajina/orgs", 651 | "repos_url": "https://api.github.com/users/vojtajina/repos", 652 | "events_url": "https://api.github.com/users/vojtajina/events{/privacy}", 653 | "received_events_url": "https://api.github.com/users/vojtajina/received_events", 654 | "type": "User", 655 | "site_admin": false 656 | }, 657 | "open_issues": 7, 658 | "closed_issues": 2, 659 | "state": "open", 660 | "created_at": "2014-03-27T04:13:48Z", 661 | "updated_at": "2014-04-23T21:39:04Z", 662 | "due_on": null 663 | }, 664 | "comments": 5, 665 | "created_at": "2014-04-18T03:45:27Z", 666 | "updated_at": "2014-04-24T04:10:57Z", 667 | "closed_at": null, 668 | "body": "### Problem\r\n\r\nThe [public API](http://karma-runner.github.io/0.12/dev/public-api.html) does not provide enough insight into the state of the server.\r\n\r\n### Why?\r\n\r\nBecause server tasks that are dependent on its state can be triggered programmatically by outside entities, it is necessary for said entities to have knowledge of the server's state.\r\n\r\nFor instance, imagine if you wanted to do the following, programmatically:\r\n\r\n1. Start a Karma server (`server.start()`)\r\n2. When all browsers are connected, run tests (`runner.run()`)\r\n3. Trigger additional runs at arbitrary times (such as when files change) (`runner.run()`)\r\n\r\nCurrently, this is not possible. Yes, this is exactly what `autoWatch` does, but runs cannot being triggered programatically. Yes, `singleRun` will run tests when all browsers are connected, but it will kill the server and exit when tests are done running, which makes the third step impossible.\r\n\r\n### Workaround\r\n\r\nIn order to work around this, implementors are forced watch `process.stdout` for messages to infer what's going on inside of Karma, which is incredibly brittle and hackish.\r\n\r\n### Solution\r\n\r\nI tried digging to find a way to get access to the event emitter that triggers some of these events, but it seems it's not currently possible via the public API.\r\n\r\nIf `server.start` returned and object with a reference the `globalEmitter` object, we'd be halfway there." 669 | }, 670 | "comment": { 671 | "url": "https://api.github.com/repos/karma-runner/karma/issues/comments/41241033", 672 | "html_url": "https://github.com/karma-runner/karma/issues/1037#issuecomment-41241033", 673 | "issue_url": "https://api.github.com/repos/karma-runner/karma/issues/1037", 674 | "id": 41241033, 675 | "user": { 676 | "login": "lazd", 677 | "id": 201344, 678 | "avatar_url": "https://avatars.githubusercontent.com/u/201344?", 679 | "gravatar_id": "764bf1eb322b51f2db54f2e09266d5be", 680 | "url": "https://api.github.com/users/lazd", 681 | "html_url": "https://github.com/lazd", 682 | "followers_url": "https://api.github.com/users/lazd/followers", 683 | "following_url": "https://api.github.com/users/lazd/following{/other_user}", 684 | "gists_url": "https://api.github.com/users/lazd/gists{/gist_id}", 685 | "starred_url": "https://api.github.com/users/lazd/starred{/owner}{/repo}", 686 | "subscriptions_url": "https://api.github.com/users/lazd/subscriptions", 687 | "organizations_url": "https://api.github.com/users/lazd/orgs", 688 | "repos_url": "https://api.github.com/users/lazd/repos", 689 | "events_url": "https://api.github.com/users/lazd/events{/privacy}", 690 | "received_events_url": "https://api.github.com/users/lazd/received_events", 691 | "type": "User", 692 | "site_admin": false 693 | }, 694 | "created_at": "2014-04-24T04:10:57Z", 695 | "updated_at": "2014-04-24T04:10:57Z", 696 | "body": "@pkozlowski-opensource, the practical need is to know when Karma is in certain states so we can trigger test runs (as described above).\r\n\r\n@vojtajina, registering events on `globalEmitter` might be sufficient, but it may cause the expected public API to break when when Karma's internals change (removed events, event names changed). Furthermore, the events emitted by `globalEmitter` are underscore_separated, whereas configuration file keys are camelCase, and it would make sense for the public events to be camelCase as well. As such, it may be better to expose a specific subset of events triggered on `globalEmitter` on the objects returned by `start()` and `run()` under different names.\r\n\r\nWithout knowing if all of these are possible, I imagine the events could be something like this:\r\n\r\n### runner\r\n\r\n* **runStart** - Test run started\r\n* **runComplete** - Test run completed\r\n* **runFailure** - Test run completed with failing tests\r\n* **runSuccess** - Test run completed with all tests passing\r\n\r\n### server\r\n\r\n* **browserRegister** - Browser registered, but not ready\r\n* **browserReady** - Browser ready to run tests\r\n* **browserRunStart** - Browser started test run\r\n* **browserRunComplete** - Browser finished test run\r\n* **browsersReady** - All browsers are ready\r\n* **browsersChange** - Browser removed or added\r\n\r\nI'm not sure what other events are available or useful, but **server.browsersReady** is the one that's blocking my use case." 697 | } 698 | }, 699 | "public": true, 700 | "created_at": "2014-04-24T04:10:58Z", 701 | "org": { 702 | "id": 3284117, 703 | "login": "karma-runner", 704 | "gravatar_id": "847cab27bf461c01b135512af49191d6", 705 | "url": "https://api.github.com/orgs/karma-runner", 706 | "avatar_url": "https://avatars.githubusercontent.com/u/3284117?" 707 | } 708 | }, 709 | { 710 | "id": "2070384089", 711 | "type": "WatchEvent", 712 | "actor": { 713 | "id": 66100, 714 | "login": "taichi", 715 | "gravatar_id": "bb720baee7aef49cecf54dbd91e8c57a", 716 | "url": "https://api.github.com/users/taichi", 717 | "avatar_url": "https://avatars.githubusercontent.com/u/66100?" 718 | }, 719 | "repo": { 720 | "id": 6400367, 721 | "name": "EngineeringMode/Grapnel.js", 722 | "url": "https://api.github.com/repos/EngineeringMode/Grapnel.js" 723 | }, 724 | "payload": { 725 | "action": "started" 726 | }, 727 | "public": true, 728 | "created_at": "2014-04-24T04:09:04Z" 729 | }, 730 | { 731 | "id": "2070382684", 732 | "type": "WatchEvent", 733 | "actor": { 734 | "id": 66100, 735 | "login": "taichi", 736 | "gravatar_id": "bb720baee7aef49cecf54dbd91e8c57a", 737 | "url": "https://api.github.com/users/taichi", 738 | "avatar_url": "https://avatars.githubusercontent.com/u/66100?" 739 | }, 740 | "repo": { 741 | "id": 17327241, 742 | "name": "zenazn/goji", 743 | "url": "https://api.github.com/repos/zenazn/goji" 744 | }, 745 | "payload": { 746 | "action": "started" 747 | }, 748 | "public": true, 749 | "created_at": "2014-04-24T04:06:48Z" 750 | }, 751 | { 752 | "id": "2070381993", 753 | "type": "IssueCommentEvent", 754 | "actor": { 755 | "id": 633843, 756 | "login": "jpillora", 757 | "gravatar_id": "37c81072743814b8b9af1f963e6f7ecb", 758 | "url": "https://api.github.com/users/jpillora", 759 | "avatar_url": "https://avatars.githubusercontent.com/u/633843?" 760 | }, 761 | "repo": { 762 | "id": 317757, 763 | "name": "Modernizr/Modernizr", 764 | "url": "https://api.github.com/repos/Modernizr/Modernizr" 765 | }, 766 | "payload": { 767 | "action": "created", 768 | "issue": { 769 | "url": "https://api.github.com/repos/Modernizr/Modernizr/issues/388", 770 | "labels_url": "https://api.github.com/repos/Modernizr/Modernizr/issues/388/labels{/name}", 771 | "comments_url": "https://api.github.com/repos/Modernizr/Modernizr/issues/388/comments", 772 | "events_url": "https://api.github.com/repos/Modernizr/Modernizr/issues/388/events", 773 | "html_url": "https://github.com/Modernizr/Modernizr/issues/388", 774 | "id": 1820109, 775 | "number": 388, 776 | "title": "postMessage string or data", 777 | "user": { 778 | "login": "forresto", 779 | "id": 395307, 780 | "avatar_url": "https://avatars.githubusercontent.com/u/395307?", 781 | "gravatar_id": "4f084531176322b8d3fdfa1dc1ff01b7", 782 | "url": "https://api.github.com/users/forresto", 783 | "html_url": "https://github.com/forresto", 784 | "followers_url": "https://api.github.com/users/forresto/followers", 785 | "following_url": "https://api.github.com/users/forresto/following{/other_user}", 786 | "gists_url": "https://api.github.com/users/forresto/gists{/gist_id}", 787 | "starred_url": "https://api.github.com/users/forresto/starred{/owner}{/repo}", 788 | "subscriptions_url": "https://api.github.com/users/forresto/subscriptions", 789 | "organizations_url": "https://api.github.com/users/forresto/orgs", 790 | "repos_url": "https://api.github.com/users/forresto/repos", 791 | "events_url": "https://api.github.com/users/forresto/events{/privacy}", 792 | "received_events_url": "https://api.github.com/users/forresto/received_events", 793 | "type": "User", 794 | "site_admin": false 795 | }, 796 | "labels": [], 797 | "state": "open", 798 | "assignee": null, 799 | "milestone": null, 800 | "comments": 25, 801 | "created_at": "2011-10-05T02:44:06Z", 802 | "updated_at": "2014-04-24T04:05:52Z", 803 | "closed_at": null, 804 | "body": "FF 6+ and Safari 5+ allow any data (except dom) to be passed as the postMessage() message. Before, it was only Strings.\r\n\r\nhttps://developer.mozilla.org/en/DOM/The_structured_clone_algorithm\r\n\r\nIt would be helpful if Modernizr could report if the browser can send only strings or data. Any idea how to test for this?" 805 | }, 806 | "comment": { 807 | "url": "https://api.github.com/repos/Modernizr/Modernizr/issues/comments/41240844", 808 | "html_url": "https://github.com/Modernizr/Modernizr/issues/388#issuecomment-41240844", 809 | "issue_url": "https://api.github.com/repos/Modernizr/Modernizr/issues/388", 810 | "id": 41240844, 811 | "user": { 812 | "login": "jpillora", 813 | "id": 633843, 814 | "avatar_url": "https://avatars.githubusercontent.com/u/633843?", 815 | "gravatar_id": "37c81072743814b8b9af1f963e6f7ecb", 816 | "url": "https://api.github.com/users/jpillora", 817 | "html_url": "https://github.com/jpillora", 818 | "followers_url": "https://api.github.com/users/jpillora/followers", 819 | "following_url": "https://api.github.com/users/jpillora/following{/other_user}", 820 | "gists_url": "https://api.github.com/users/jpillora/gists{/gist_id}", 821 | "starred_url": "https://api.github.com/users/jpillora/starred{/owner}{/repo}", 822 | "subscriptions_url": "https://api.github.com/users/jpillora/subscriptions", 823 | "organizations_url": "https://api.github.com/users/jpillora/orgs", 824 | "repos_url": "https://api.github.com/users/jpillora/repos", 825 | "events_url": "https://api.github.com/users/jpillora/events{/privacy}", 826 | "received_events_url": "https://api.github.com/users/jpillora/received_events", 827 | "type": "User", 828 | "site_admin": false 829 | }, 830 | "created_at": "2014-04-24T04:05:52Z", 831 | "updated_at": "2014-04-24T04:05:52Z", 832 | "body": "\r\n\r\n@gregersrygg Ah great there's a fix :) A cross-domain version of the test would be awesome. Probably doesn't need an extra box, though maybe just flag it somehow it if either same/cross domains tests fail. Maybe for cross-domain, you could use http://rawgit.com/ to serve a file on github (like a `test.html`) with the proper content-type (`text/html`). Or Amazon or dropbox etc etc. :)\r\n\r\n@ryanseddon As @gregersrygg mentioned, there's a bug fix, on the bug tracker, so it like a firefox only browser bug, though I guess it could be spec'ed somewhere to prevent Blobs from being sent cross-domain. Though that would be very strange as Array Buffers are allowed, which I'm [currently using](https://github.com/jpillora/xdomain/blob/gh-pages/src/master.coffee#L27-L62) to get around this issue." 833 | } 834 | }, 835 | "public": true, 836 | "created_at": "2014-04-24T04:05:53Z", 837 | "org": { 838 | "id": 131060, 839 | "login": "Modernizr", 840 | "gravatar_id": "af17f0f78f7697b3e2bf70b26fb184ac", 841 | "url": "https://api.github.com/orgs/Modernizr", 842 | "avatar_url": "https://avatars.githubusercontent.com/u/131060?" 843 | } 844 | }, 845 | { 846 | "id": "2070379868", 847 | "type": "IssueCommentEvent", 848 | "actor": { 849 | "id": 465414, 850 | "login": "patrickkettner", 851 | "gravatar_id": "3fada965c1f65adc0599bb9cd606524d", 852 | "url": "https://api.github.com/users/patrickkettner", 853 | "avatar_url": "https://avatars.githubusercontent.com/u/465414?" 854 | }, 855 | "repo": { 856 | "id": 317757, 857 | "name": "Modernizr/Modernizr", 858 | "url": "https://api.github.com/repos/Modernizr/Modernizr" 859 | }, 860 | "payload": { 861 | "action": "created", 862 | "issue": { 863 | "url": "https://api.github.com/repos/Modernizr/Modernizr/issues/100", 864 | "labels_url": "https://api.github.com/repos/Modernizr/Modernizr/issues/100/labels{/name}", 865 | "comments_url": "https://api.github.com/repos/Modernizr/Modernizr/issues/100/comments", 866 | "events_url": "https://api.github.com/repos/Modernizr/Modernizr/issues/100/events", 867 | "html_url": "https://github.com/Modernizr/Modernizr/issues/100", 868 | "id": 273196, 869 | "number": 100, 870 | "title": "camera input detection", 871 | "user": { 872 | "login": "paulirish", 873 | "id": 39191, 874 | "avatar_url": "https://avatars.githubusercontent.com/u/39191?", 875 | "gravatar_id": "ffe68d6f71b225f7661d33f2a8908281", 876 | "url": "https://api.github.com/users/paulirish", 877 | "html_url": "https://github.com/paulirish", 878 | "followers_url": "https://api.github.com/users/paulirish/followers", 879 | "following_url": "https://api.github.com/users/paulirish/following{/other_user}", 880 | "gists_url": "https://api.github.com/users/paulirish/gists{/gist_id}", 881 | "starred_url": "https://api.github.com/users/paulirish/starred{/owner}{/repo}", 882 | "subscriptions_url": "https://api.github.com/users/paulirish/subscriptions", 883 | "organizations_url": "https://api.github.com/users/paulirish/orgs", 884 | "repos_url": "https://api.github.com/users/paulirish/repos", 885 | "events_url": "https://api.github.com/users/paulirish/events{/privacy}", 886 | "received_events_url": "https://api.github.com/users/paulirish/received_events", 887 | "type": "User", 888 | "site_admin": false 889 | }, 890 | "labels": [ 891 | { 892 | "url": "https://api.github.com/repos/Modernizr/Modernizr/labels/port+to+plugin", 893 | "name": "port to plugin", 894 | "color": "e102d8" 895 | } 896 | ], 897 | "state": "open", 898 | "assignee": null, 899 | "milestone": null, 900 | "comments": 6, 901 | "created_at": "2010-08-09T17:37:54Z", 902 | "updated_at": "2014-04-24T04:02:23Z", 903 | "closed_at": null, 904 | "body": " \r\n\r\nWill be the HTML required.. detectability unknown.\r\n\r\nvia https://groups.google.com/a/chromium.org/group/chromium-html5/browse_thread/thread/e6f125022dfadb39" 905 | }, 906 | "comment": { 907 | "url": "https://api.github.com/repos/Modernizr/Modernizr/issues/comments/41240703", 908 | "html_url": "https://github.com/Modernizr/Modernizr/issues/100#issuecomment-41240703", 909 | "issue_url": "https://api.github.com/repos/Modernizr/Modernizr/issues/100", 910 | "id": 41240703, 911 | "user": { 912 | "login": "patrickkettner", 913 | "id": 465414, 914 | "avatar_url": "https://avatars.githubusercontent.com/u/465414?", 915 | "gravatar_id": "3fada965c1f65adc0599bb9cd606524d", 916 | "url": "https://api.github.com/users/patrickkettner", 917 | "html_url": "https://github.com/patrickkettner", 918 | "followers_url": "https://api.github.com/users/patrickkettner/followers", 919 | "following_url": "https://api.github.com/users/patrickkettner/following{/other_user}", 920 | "gists_url": "https://api.github.com/users/patrickkettner/gists{/gist_id}", 921 | "starred_url": "https://api.github.com/users/patrickkettner/starred{/owner}{/repo}", 922 | "subscriptions_url": "https://api.github.com/users/patrickkettner/subscriptions", 923 | "organizations_url": "https://api.github.com/users/patrickkettner/orgs", 924 | "repos_url": "https://api.github.com/users/patrickkettner/repos", 925 | "events_url": "https://api.github.com/users/patrickkettner/events{/privacy}", 926 | "received_events_url": "https://api.github.com/users/patrickkettner/received_events", 927 | "type": "User", 928 | "site_admin": false 929 | }, 930 | "created_at": "2014-04-24T04:02:23Z", 931 | "updated_at": "2014-04-24T04:02:23Z", 932 | "body": "@stucox wanna open up that as a PR to get the ball rolling?" 933 | } 934 | }, 935 | "public": true, 936 | "created_at": "2014-04-24T04:02:24Z", 937 | "org": { 938 | "id": 131060, 939 | "login": "Modernizr", 940 | "gravatar_id": "af17f0f78f7697b3e2bf70b26fb184ac", 941 | "url": "https://api.github.com/orgs/Modernizr", 942 | "avatar_url": "https://avatars.githubusercontent.com/u/131060?" 943 | } 944 | }, 945 | { 946 | "id": "2070375931", 947 | "type": "IssuesEvent", 948 | "actor": { 949 | "id": 77849, 950 | "login": "jameswomack", 951 | "gravatar_id": "472e3bfb17175fb5d741356aa40b9605", 952 | "url": "https://api.github.com/users/jameswomack", 953 | "avatar_url": "https://avatars.githubusercontent.com/u/77849?" 954 | }, 955 | "repo": { 956 | "id": 2328523, 957 | "name": "n1k0/casperjs", 958 | "url": "https://api.github.com/repos/n1k0/casperjs" 959 | }, 960 | "payload": { 961 | "action": "opened", 962 | "issue": { 963 | "url": "https://api.github.com/repos/n1k0/casperjs/issues/898", 964 | "labels_url": "https://api.github.com/repos/n1k0/casperjs/issues/898/labels{/name}", 965 | "comments_url": "https://api.github.com/repos/n1k0/casperjs/issues/898/comments", 966 | "events_url": "https://api.github.com/repos/n1k0/casperjs/issues/898/events", 967 | "html_url": "https://github.com/n1k0/casperjs/issues/898", 968 | "id": 32118616, 969 | "number": 898, 970 | "title": "Cannot find module 'path'", 971 | "user": { 972 | "login": "jameswomack", 973 | "id": 77849, 974 | "avatar_url": "https://avatars.githubusercontent.com/u/77849?", 975 | "gravatar_id": "472e3bfb17175fb5d741356aa40b9605", 976 | "url": "https://api.github.com/users/jameswomack", 977 | "html_url": "https://github.com/jameswomack", 978 | "followers_url": "https://api.github.com/users/jameswomack/followers", 979 | "following_url": "https://api.github.com/users/jameswomack/following{/other_user}", 980 | "gists_url": "https://api.github.com/users/jameswomack/gists{/gist_id}", 981 | "starred_url": "https://api.github.com/users/jameswomack/starred{/owner}{/repo}", 982 | "subscriptions_url": "https://api.github.com/users/jameswomack/subscriptions", 983 | "organizations_url": "https://api.github.com/users/jameswomack/orgs", 984 | "repos_url": "https://api.github.com/users/jameswomack/repos", 985 | "events_url": "https://api.github.com/users/jameswomack/events{/privacy}", 986 | "received_events_url": "https://api.github.com/users/jameswomack/received_events", 987 | "type": "User", 988 | "site_admin": false 989 | }, 990 | "labels": [], 991 | "state": "open", 992 | "assignee": null, 993 | "milestone": null, 994 | "comments": 0, 995 | "created_at": "2014-04-24T03:56:43Z", 996 | "updated_at": "2014-04-24T03:56:43Z", 997 | "closed_at": null, 998 | "body": "Hello Casper folks :ghost: \r\n\r\nIn a casper test, I import another JS module, which itself requires the node core module 'path'. Upon running the test, I get the error:\r\n```\r\nError: Cannot find module 'path'\r\n\r\n phantomjs://bootstrap.js:289\r\n phantomjs://bootstrap.js:254 in require\r\n```\r\n\r\nThe test:\r\n```\r\nvar server = require('../..'); // this module requires path, i.e. `require('path')`\r\n\r\nvar port = server.httpListener.address().port;\r\nvar url = 'http://localhost:'+String(port);\r\n\r\ncasper.test.begin('titles', 2, function(test){\r\n casper\r\n .start(url)\r\n .waitForSelector('header#header', function(){\r\n test.assertSelectorHasText('.timeZoneTitle:nth-child(1), :not(.timeZoneTitle) + .timeZoneTitle', 'Tokyo');\r\n test.assertSelectorHasText('.timeZoneTitle:nth-child(2), :not(.timeZoneTitle) + .timeZoneTitle', 'Tijuana');\r\n })\r\n .run();\r\n});\r\n```\r\n\r\nRunning a nearly identical script using NightwatchJS works." 999 | } 1000 | }, 1001 | "public": true, 1002 | "created_at": "2014-04-24T03:56:44Z" 1003 | }, 1004 | { 1005 | "id": "2070375330", 1006 | "type": "IssueCommentEvent", 1007 | "actor": { 1008 | "id": 143402, 1009 | "login": "ryanseddon", 1010 | "gravatar_id": "8677c9f7c0f6d947bf318c1430d00bfd", 1011 | "url": "https://api.github.com/users/ryanseddon", 1012 | "avatar_url": "https://avatars.githubusercontent.com/u/143402?" 1013 | }, 1014 | "repo": { 1015 | "id": 317757, 1016 | "name": "Modernizr/Modernizr", 1017 | "url": "https://api.github.com/repos/Modernizr/Modernizr" 1018 | }, 1019 | "payload": { 1020 | "action": "created", 1021 | "issue": { 1022 | "url": "https://api.github.com/repos/Modernizr/Modernizr/issues/388", 1023 | "labels_url": "https://api.github.com/repos/Modernizr/Modernizr/issues/388/labels{/name}", 1024 | "comments_url": "https://api.github.com/repos/Modernizr/Modernizr/issues/388/comments", 1025 | "events_url": "https://api.github.com/repos/Modernizr/Modernizr/issues/388/events", 1026 | "html_url": "https://github.com/Modernizr/Modernizr/issues/388", 1027 | "id": 1820109, 1028 | "number": 388, 1029 | "title": "postMessage string or data", 1030 | "user": { 1031 | "login": "forresto", 1032 | "id": 395307, 1033 | "avatar_url": "https://avatars.githubusercontent.com/u/395307?", 1034 | "gravatar_id": "4f084531176322b8d3fdfa1dc1ff01b7", 1035 | "url": "https://api.github.com/users/forresto", 1036 | "html_url": "https://github.com/forresto", 1037 | "followers_url": "https://api.github.com/users/forresto/followers", 1038 | "following_url": "https://api.github.com/users/forresto/following{/other_user}", 1039 | "gists_url": "https://api.github.com/users/forresto/gists{/gist_id}", 1040 | "starred_url": "https://api.github.com/users/forresto/starred{/owner}{/repo}", 1041 | "subscriptions_url": "https://api.github.com/users/forresto/subscriptions", 1042 | "organizations_url": "https://api.github.com/users/forresto/orgs", 1043 | "repos_url": "https://api.github.com/users/forresto/repos", 1044 | "events_url": "https://api.github.com/users/forresto/events{/privacy}", 1045 | "received_events_url": "https://api.github.com/users/forresto/received_events", 1046 | "type": "User", 1047 | "site_admin": false 1048 | }, 1049 | "labels": [], 1050 | "state": "open", 1051 | "assignee": null, 1052 | "milestone": null, 1053 | "comments": 24, 1054 | "created_at": "2011-10-05T02:44:06Z", 1055 | "updated_at": "2014-04-24T03:55:51Z", 1056 | "closed_at": null, 1057 | "body": "FF 6+ and Safari 5+ allow any data (except dom) to be passed as the postMessage() message. Before, it was only Strings.\r\n\r\nhttps://developer.mozilla.org/en/DOM/The_structured_clone_algorithm\r\n\r\nIt would be helpful if Modernizr could report if the browser can send only strings or data. Any idea how to test for this?" 1058 | }, 1059 | "comment": { 1060 | "url": "https://api.github.com/repos/Modernizr/Modernizr/issues/comments/41240445", 1061 | "html_url": "https://github.com/Modernizr/Modernizr/issues/388#issuecomment-41240445", 1062 | "issue_url": "https://api.github.com/repos/Modernizr/Modernizr/issues/388", 1063 | "id": 41240445, 1064 | "user": { 1065 | "login": "ryanseddon", 1066 | "id": 143402, 1067 | "avatar_url": "https://avatars.githubusercontent.com/u/143402?", 1068 | "gravatar_id": "8677c9f7c0f6d947bf318c1430d00bfd", 1069 | "url": "https://api.github.com/users/ryanseddon", 1070 | "html_url": "https://github.com/ryanseddon", 1071 | "followers_url": "https://api.github.com/users/ryanseddon/followers", 1072 | "following_url": "https://api.github.com/users/ryanseddon/following{/other_user}", 1073 | "gists_url": "https://api.github.com/users/ryanseddon/gists{/gist_id}", 1074 | "starred_url": "https://api.github.com/users/ryanseddon/starred{/owner}{/repo}", 1075 | "subscriptions_url": "https://api.github.com/users/ryanseddon/subscriptions", 1076 | "organizations_url": "https://api.github.com/users/ryanseddon/orgs", 1077 | "repos_url": "https://api.github.com/users/ryanseddon/repos", 1078 | "events_url": "https://api.github.com/users/ryanseddon/events{/privacy}", 1079 | "received_events_url": "https://api.github.com/users/ryanseddon/received_events", 1080 | "type": "User", 1081 | "site_admin": false 1082 | }, 1083 | "created_at": "2014-04-24T03:55:51Z", 1084 | "updated_at": "2014-04-24T03:55:51Z", 1085 | "body": "@jpillora is that a firefox only issue is it spec'ed behaviour or a browser bug?" 1086 | } 1087 | }, 1088 | "public": true, 1089 | "created_at": "2014-04-24T03:55:51Z", 1090 | "org": { 1091 | "id": 131060, 1092 | "login": "Modernizr", 1093 | "gravatar_id": "af17f0f78f7697b3e2bf70b26fb184ac", 1094 | "url": "https://api.github.com/orgs/Modernizr", 1095 | "avatar_url": "https://avatars.githubusercontent.com/u/131060?" 1096 | } 1097 | }, 1098 | { 1099 | "id": "2070372883", 1100 | "type": "IssuesEvent", 1101 | "actor": { 1102 | "id": 1162160, 1103 | "login": "Rich-Harris", 1104 | "gravatar_id": "329f9d32fe20b186838ee237d3eb2d43", 1105 | "url": "https://api.github.com/users/Rich-Harris", 1106 | "avatar_url": "https://avatars.githubusercontent.com/u/1162160?" 1107 | }, 1108 | "repo": { 1109 | "id": 5245894, 1110 | "name": "ractivejs/ractive", 1111 | "url": "https://api.github.com/repos/ractivejs/ractive" 1112 | }, 1113 | "payload": { 1114 | "action": "opened", 1115 | "issue": { 1116 | "url": "https://api.github.com/repos/ractivejs/ractive/issues/629", 1117 | "labels_url": "https://api.github.com/repos/ractivejs/ractive/issues/629/labels{/name}", 1118 | "comments_url": "https://api.github.com/repos/ractivejs/ractive/issues/629/comments", 1119 | "events_url": "https://api.github.com/repos/ractivejs/ractive/issues/629/events", 1120 | "html_url": "https://github.com/ractivejs/ractive/issues/629", 1121 | "id": 32118462, 1122 | "number": 629, 1123 | "title": "Pattern observers fail if the first key is *", 1124 | "user": { 1125 | "login": "Rich-Harris", 1126 | "id": 1162160, 1127 | "avatar_url": "https://avatars.githubusercontent.com/u/1162160?", 1128 | "gravatar_id": "329f9d32fe20b186838ee237d3eb2d43", 1129 | "url": "https://api.github.com/users/Rich-Harris", 1130 | "html_url": "https://github.com/Rich-Harris", 1131 | "followers_url": "https://api.github.com/users/Rich-Harris/followers", 1132 | "following_url": "https://api.github.com/users/Rich-Harris/following{/other_user}", 1133 | "gists_url": "https://api.github.com/users/Rich-Harris/gists{/gist_id}", 1134 | "starred_url": "https://api.github.com/users/Rich-Harris/starred{/owner}{/repo}", 1135 | "subscriptions_url": "https://api.github.com/users/Rich-Harris/subscriptions", 1136 | "organizations_url": "https://api.github.com/users/Rich-Harris/orgs", 1137 | "repos_url": "https://api.github.com/users/Rich-Harris/repos", 1138 | "events_url": "https://api.github.com/users/Rich-Harris/events{/privacy}", 1139 | "received_events_url": "https://api.github.com/users/Rich-Harris/received_events", 1140 | "type": "User", 1141 | "site_admin": false 1142 | }, 1143 | "labels": [], 1144 | "state": "open", 1145 | "assignee": null, 1146 | "milestone": null, 1147 | "comments": 0, 1148 | "created_at": "2014-04-24T03:52:00Z", 1149 | "updated_at": "2014-04-24T03:52:00Z", 1150 | "closed_at": null, 1151 | "body": "This fails:\r\n\r\n```js\r\nractive.observe('*.foo', function (n, o, k) {\r\n // k will be 'foo' the first time this function is called!\r\n});\r\n```\r\n\r\nThe offending code is [here](https://github.com/ractivejs/ractive/blob/master/src/Ractive/prototype/observe/getPattern.js)." 1152 | } 1153 | }, 1154 | "public": true, 1155 | "created_at": "2014-04-24T03:52:00Z", 1156 | "org": { 1157 | "id": 4751469, 1158 | "login": "ractivejs", 1159 | "gravatar_id": "9ab10f16b1b77550d4d0f58adb1eab17", 1160 | "url": "https://api.github.com/orgs/ractivejs", 1161 | "avatar_url": "https://avatars.githubusercontent.com/u/4751469?" 1162 | } 1163 | }, 1164 | { 1165 | "id": "2070369463", 1166 | "type": "CreateEvent", 1167 | "actor": { 1168 | "id": 1042866, 1169 | "login": "jason0x43", 1170 | "gravatar_id": "17f86938646f77675595f346c485bb14", 1171 | "url": "https://api.github.com/users/jason0x43", 1172 | "avatar_url": "https://avatars.githubusercontent.com/u/1042866?" 1173 | }, 1174 | "repo": { 1175 | "id": 9037631, 1176 | "name": "theintern/intern", 1177 | "url": "https://api.github.com/repos/theintern/intern" 1178 | }, 1179 | "payload": { 1180 | "ref": "sinon", 1181 | "ref_type": "branch", 1182 | "master_branch": "master", 1183 | "description": "A next-generation code testing stack for JavaScript.", 1184 | "pusher_type": "user" 1185 | }, 1186 | "public": true, 1187 | "created_at": "2014-04-24T03:46:55Z", 1188 | "org": { 1189 | "id": 3977877, 1190 | "login": "theintern", 1191 | "gravatar_id": "8dfcc23c784d69800577e249b0891bda", 1192 | "url": "https://api.github.com/orgs/theintern", 1193 | "avatar_url": "https://avatars.githubusercontent.com/u/3977877?" 1194 | } 1195 | }, 1196 | { 1197 | "id": "2070368142", 1198 | "type": "WatchEvent", 1199 | "actor": { 1200 | "id": 86519, 1201 | "login": "t32k", 1202 | "gravatar_id": "4cf842e43a782a585d8707f2ba7f9a5c", 1203 | "url": "https://api.github.com/users/t32k", 1204 | "avatar_url": "https://avatars.githubusercontent.com/u/86519?" 1205 | }, 1206 | "repo": { 1207 | "id": 2913921, 1208 | "name": "fbzhong/sublime-closure-linter", 1209 | "url": "https://api.github.com/repos/fbzhong/sublime-closure-linter" 1210 | }, 1211 | "payload": { 1212 | "action": "started" 1213 | }, 1214 | "public": true, 1215 | "created_at": "2014-04-24T03:45:11Z" 1216 | }, 1217 | { 1218 | "id": "2070365775", 1219 | "type": "IssuesEvent", 1220 | "actor": { 1221 | "id": 229244, 1222 | "login": "csnover", 1223 | "gravatar_id": "ffe1561ee79aea59ef8a68a56c365883", 1224 | "url": "https://api.github.com/users/csnover", 1225 | "avatar_url": "https://avatars.githubusercontent.com/u/229244?" 1226 | }, 1227 | "repo": { 1228 | "id": 9037631, 1229 | "name": "theintern/intern", 1230 | "url": "https://api.github.com/repos/theintern/intern" 1231 | }, 1232 | "payload": { 1233 | "action": "closed", 1234 | "issue": { 1235 | "url": "https://api.github.com/repos/theintern/intern/issues/173", 1236 | "labels_url": "https://api.github.com/repos/theintern/intern/issues/173/labels{/name}", 1237 | "comments_url": "https://api.github.com/repos/theintern/intern/issues/173/comments", 1238 | "events_url": "https://api.github.com/repos/theintern/intern/issues/173/events", 1239 | "html_url": "https://github.com/theintern/intern/issues/173", 1240 | "id": 31019876, 1241 | "number": 173, 1242 | "title": "lengthOf assertion in geezer fails with 0-length array", 1243 | "user": { 1244 | "login": "jason0x43", 1245 | "id": 1042866, 1246 | "avatar_url": "https://avatars.githubusercontent.com/u/1042866?", 1247 | "gravatar_id": "17f86938646f77675595f346c485bb14", 1248 | "url": "https://api.github.com/users/jason0x43", 1249 | "html_url": "https://github.com/jason0x43", 1250 | "followers_url": "https://api.github.com/users/jason0x43/followers", 1251 | "following_url": "https://api.github.com/users/jason0x43/following{/other_user}", 1252 | "gists_url": "https://api.github.com/users/jason0x43/gists{/gist_id}", 1253 | "starred_url": "https://api.github.com/users/jason0x43/starred{/owner}{/repo}", 1254 | "subscriptions_url": "https://api.github.com/users/jason0x43/subscriptions", 1255 | "organizations_url": "https://api.github.com/users/jason0x43/orgs", 1256 | "repos_url": "https://api.github.com/users/jason0x43/repos", 1257 | "events_url": "https://api.github.com/users/jason0x43/events{/privacy}", 1258 | "received_events_url": "https://api.github.com/users/jason0x43/received_events", 1259 | "type": "User", 1260 | "site_admin": false 1261 | }, 1262 | "labels": [ 1263 | { 1264 | "url": "https://api.github.com/repos/theintern/intern/labels/bug", 1265 | "name": "bug", 1266 | "color": "fc2929" 1267 | } 1268 | ], 1269 | "state": "closed", 1270 | "assignee": null, 1271 | "milestone": null, 1272 | "comments": 2, 1273 | "created_at": "2014-04-07T20:38:34Z", 1274 | "updated_at": "2014-04-24T03:41:43Z", 1275 | "closed_at": "2014-04-24T03:41:43Z", 1276 | "body": "The `lengthOf` assertion in geezer uses `!object.length` to check if the object being tested has a length property. This fails when length is 0." 1277 | } 1278 | }, 1279 | "public": true, 1280 | "created_at": "2014-04-24T03:41:43Z", 1281 | "org": { 1282 | "id": 3977877, 1283 | "login": "theintern", 1284 | "gravatar_id": "8dfcc23c784d69800577e249b0891bda", 1285 | "url": "https://api.github.com/orgs/theintern", 1286 | "avatar_url": "https://avatars.githubusercontent.com/u/3977877?" 1287 | } 1288 | }, 1289 | { 1290 | "id": "2070365773", 1291 | "type": "IssueCommentEvent", 1292 | "actor": { 1293 | "id": 229244, 1294 | "login": "csnover", 1295 | "gravatar_id": "ffe1561ee79aea59ef8a68a56c365883", 1296 | "url": "https://api.github.com/users/csnover", 1297 | "avatar_url": "https://avatars.githubusercontent.com/u/229244?" 1298 | }, 1299 | "repo": { 1300 | "id": 9037631, 1301 | "name": "theintern/intern", 1302 | "url": "https://api.github.com/repos/theintern/intern" 1303 | }, 1304 | "payload": { 1305 | "action": "created", 1306 | "issue": { 1307 | "url": "https://api.github.com/repos/theintern/intern/issues/173", 1308 | "labels_url": "https://api.github.com/repos/theintern/intern/issues/173/labels{/name}", 1309 | "comments_url": "https://api.github.com/repos/theintern/intern/issues/173/comments", 1310 | "events_url": "https://api.github.com/repos/theintern/intern/issues/173/events", 1311 | "html_url": "https://github.com/theintern/intern/issues/173", 1312 | "id": 31019876, 1313 | "number": 173, 1314 | "title": "lengthOf assertion in geezer fails with 0-length array", 1315 | "user": { 1316 | "login": "jason0x43", 1317 | "id": 1042866, 1318 | "avatar_url": "https://avatars.githubusercontent.com/u/1042866?", 1319 | "gravatar_id": "17f86938646f77675595f346c485bb14", 1320 | "url": "https://api.github.com/users/jason0x43", 1321 | "html_url": "https://github.com/jason0x43", 1322 | "followers_url": "https://api.github.com/users/jason0x43/followers", 1323 | "following_url": "https://api.github.com/users/jason0x43/following{/other_user}", 1324 | "gists_url": "https://api.github.com/users/jason0x43/gists{/gist_id}", 1325 | "starred_url": "https://api.github.com/users/jason0x43/starred{/owner}{/repo}", 1326 | "subscriptions_url": "https://api.github.com/users/jason0x43/subscriptions", 1327 | "organizations_url": "https://api.github.com/users/jason0x43/orgs", 1328 | "repos_url": "https://api.github.com/users/jason0x43/repos", 1329 | "events_url": "https://api.github.com/users/jason0x43/events{/privacy}", 1330 | "received_events_url": "https://api.github.com/users/jason0x43/received_events", 1331 | "type": "User", 1332 | "site_admin": false 1333 | }, 1334 | "labels": [ 1335 | { 1336 | "url": "https://api.github.com/repos/theintern/intern/labels/bug", 1337 | "name": "bug", 1338 | "color": "fc2929" 1339 | } 1340 | ], 1341 | "state": "closed", 1342 | "assignee": null, 1343 | "milestone": null, 1344 | "comments": 2, 1345 | "created_at": "2014-04-07T20:38:34Z", 1346 | "updated_at": "2014-04-24T03:41:43Z", 1347 | "closed_at": "2014-04-24T03:41:43Z", 1348 | "body": "The `lengthOf` assertion in geezer uses `!object.length` to check if the object being tested has a length property. This fails when length is 0." 1349 | }, 1350 | "comment": { 1351 | "url": "https://api.github.com/repos/theintern/intern/issues/comments/41239886", 1352 | "html_url": "https://github.com/theintern/intern/issues/173#issuecomment-41239886", 1353 | "issue_url": "https://api.github.com/repos/theintern/intern/issues/173", 1354 | "id": 41239886, 1355 | "user": { 1356 | "login": "csnover", 1357 | "id": 229244, 1358 | "avatar_url": "https://avatars.githubusercontent.com/u/229244?", 1359 | "gravatar_id": "ffe1561ee79aea59ef8a68a56c365883", 1360 | "url": "https://api.github.com/users/csnover", 1361 | "html_url": "https://github.com/csnover", 1362 | "followers_url": "https://api.github.com/users/csnover/followers", 1363 | "following_url": "https://api.github.com/users/csnover/following{/other_user}", 1364 | "gists_url": "https://api.github.com/users/csnover/gists{/gist_id}", 1365 | "starred_url": "https://api.github.com/users/csnover/starred{/owner}{/repo}", 1366 | "subscriptions_url": "https://api.github.com/users/csnover/subscriptions", 1367 | "organizations_url": "https://api.github.com/users/csnover/orgs", 1368 | "repos_url": "https://api.github.com/users/csnover/repos", 1369 | "events_url": "https://api.github.com/users/csnover/events{/privacy}", 1370 | "received_events_url": "https://api.github.com/users/csnover/received_events", 1371 | "type": "User", 1372 | "site_admin": false 1373 | }, 1374 | "created_at": "2014-04-24T03:41:43Z", 1375 | "updated_at": "2014-04-24T03:41:43Z", 1376 | "body": "Fixed in 7e2c546e4df970caca4a81ea13a70264a95b424f" 1377 | } 1378 | }, 1379 | "public": true, 1380 | "created_at": "2014-04-24T03:41:43Z", 1381 | "org": { 1382 | "id": 3977877, 1383 | "login": "theintern", 1384 | "gravatar_id": "8dfcc23c784d69800577e249b0891bda", 1385 | "url": "https://api.github.com/orgs/theintern", 1386 | "avatar_url": "https://avatars.githubusercontent.com/u/3977877?" 1387 | } 1388 | }, 1389 | { 1390 | "id": "2070365629", 1391 | "type": "PushEvent", 1392 | "actor": { 1393 | "id": 229244, 1394 | "login": "csnover", 1395 | "gravatar_id": "ffe1561ee79aea59ef8a68a56c365883", 1396 | "url": "https://api.github.com/users/csnover", 1397 | "avatar_url": "https://avatars.githubusercontent.com/u/229244?" 1398 | }, 1399 | "repo": { 1400 | "id": 9037631, 1401 | "name": "theintern/intern", 1402 | "url": "https://api.github.com/repos/theintern/intern" 1403 | }, 1404 | "payload": { 1405 | "push_id": 352948307, 1406 | "size": 1, 1407 | "distinct_size": 1, 1408 | "ref": "refs/heads/geezer", 1409 | "head": "7e2c546e4df970caca4a81ea13a70264a95b424f", 1410 | "before": "46ce00addfcd0a062cd512c483d3bcf140488132", 1411 | "commits": [ 1412 | { 1413 | "sha": "7e2c546e4df970caca4a81ea13a70264a95b424f", 1414 | "author": { 1415 | "email": "github.com@zetafleet.com", 1416 | "name": "Colin Snover" 1417 | }, 1418 | "message": "Make lengthOf detect length property the same way as Chai\n\nFixes #173.", 1419 | "distinct": true, 1420 | "url": "https://api.github.com/repos/theintern/intern/commits/7e2c546e4df970caca4a81ea13a70264a95b424f" 1421 | } 1422 | ] 1423 | }, 1424 | "public": true, 1425 | "created_at": "2014-04-24T03:41:31Z", 1426 | "org": { 1427 | "id": 3977877, 1428 | "login": "theintern", 1429 | "gravatar_id": "8dfcc23c784d69800577e249b0891bda", 1430 | "url": "https://api.github.com/orgs/theintern", 1431 | "avatar_url": "https://avatars.githubusercontent.com/u/3977877?" 1432 | } 1433 | }, 1434 | { 1435 | "id": "2070360109", 1436 | "type": "PushEvent", 1437 | "actor": { 1438 | "id": 229244, 1439 | "login": "csnover", 1440 | "gravatar_id": "ffe1561ee79aea59ef8a68a56c365883", 1441 | "url": "https://api.github.com/users/csnover", 1442 | "avatar_url": "https://avatars.githubusercontent.com/u/229244?" 1443 | }, 1444 | "repo": { 1445 | "id": 9037631, 1446 | "name": "theintern/intern", 1447 | "url": "https://api.github.com/repos/theintern/intern" 1448 | }, 1449 | "payload": { 1450 | "push_id": 352945466, 1451 | "size": 2, 1452 | "distinct_size": 1, 1453 | "ref": "refs/heads/geezer", 1454 | "head": "46ce00addfcd0a062cd512c483d3bcf140488132", 1455 | "before": "f00aacf2a1feb03b8c375842715c07a4879fd255", 1456 | "commits": [ 1457 | { 1458 | "sha": "c72adf14887d52a8ddd3bd93aee525cdeebe622f", 1459 | "author": { 1460 | "email": "github.com@zetafleet.com", 1461 | "name": "Colin Snover" 1462 | }, 1463 | "message": "Update sauce-connect-launcher\n\nFixes #179.", 1464 | "distinct": false, 1465 | "url": "https://api.github.com/repos/theintern/intern/commits/c72adf14887d52a8ddd3bd93aee525cdeebe622f" 1466 | }, 1467 | { 1468 | "sha": "46ce00addfcd0a062cd512c483d3bcf140488132", 1469 | "author": { 1470 | "email": "github.com@zetafleet.com", 1471 | "name": "Colin Snover" 1472 | }, 1473 | "message": "Merge branch 'master' into geezer\n\nConflicts:\n\tpackage.json", 1474 | "distinct": true, 1475 | "url": "https://api.github.com/repos/theintern/intern/commits/46ce00addfcd0a062cd512c483d3bcf140488132" 1476 | } 1477 | ] 1478 | }, 1479 | "public": true, 1480 | "created_at": "2014-04-24T03:33:18Z", 1481 | "org": { 1482 | "id": 3977877, 1483 | "login": "theintern", 1484 | "gravatar_id": "8dfcc23c784d69800577e249b0891bda", 1485 | "url": "https://api.github.com/orgs/theintern", 1486 | "avatar_url": "https://avatars.githubusercontent.com/u/3977877?" 1487 | } 1488 | }, 1489 | { 1490 | "id": "2070359714", 1491 | "type": "PushEvent", 1492 | "actor": { 1493 | "id": 229244, 1494 | "login": "csnover", 1495 | "gravatar_id": "ffe1561ee79aea59ef8a68a56c365883", 1496 | "url": "https://api.github.com/users/csnover", 1497 | "avatar_url": "https://avatars.githubusercontent.com/u/229244?" 1498 | }, 1499 | "repo": { 1500 | "id": 9037631, 1501 | "name": "theintern/intern", 1502 | "url": "https://api.github.com/repos/theintern/intern" 1503 | }, 1504 | "payload": { 1505 | "push_id": 352945276, 1506 | "size": 1, 1507 | "distinct_size": 1, 1508 | "ref": "refs/heads/master", 1509 | "head": "c72adf14887d52a8ddd3bd93aee525cdeebe622f", 1510 | "before": "71cc8891a9aa2f7687a228b00cb6e107ccf312be", 1511 | "commits": [ 1512 | { 1513 | "sha": "c72adf14887d52a8ddd3bd93aee525cdeebe622f", 1514 | "author": { 1515 | "email": "github.com@zetafleet.com", 1516 | "name": "Colin Snover" 1517 | }, 1518 | "message": "Update sauce-connect-launcher\n\nFixes #179.", 1519 | "distinct": true, 1520 | "url": "https://api.github.com/repos/theintern/intern/commits/c72adf14887d52a8ddd3bd93aee525cdeebe622f" 1521 | } 1522 | ] 1523 | }, 1524 | "public": true, 1525 | "created_at": "2014-04-24T03:32:43Z", 1526 | "org": { 1527 | "id": 3977877, 1528 | "login": "theintern", 1529 | "gravatar_id": "8dfcc23c784d69800577e249b0891bda", 1530 | "url": "https://api.github.com/orgs/theintern", 1531 | "avatar_url": "https://avatars.githubusercontent.com/u/3977877?" 1532 | } 1533 | }, 1534 | { 1535 | "id": "2070359710", 1536 | "type": "IssuesEvent", 1537 | "actor": { 1538 | "id": 229244, 1539 | "login": "csnover", 1540 | "gravatar_id": "ffe1561ee79aea59ef8a68a56c365883", 1541 | "url": "https://api.github.com/users/csnover", 1542 | "avatar_url": "https://avatars.githubusercontent.com/u/229244?" 1543 | }, 1544 | "repo": { 1545 | "id": 9037631, 1546 | "name": "theintern/intern", 1547 | "url": "https://api.github.com/repos/theintern/intern" 1548 | }, 1549 | "payload": { 1550 | "action": "closed", 1551 | "issue": { 1552 | "url": "https://api.github.com/repos/theintern/intern/issues/179", 1553 | "labels_url": "https://api.github.com/repos/theintern/intern/issues/179/labels{/name}", 1554 | "comments_url": "https://api.github.com/repos/theintern/intern/issues/179/comments", 1555 | "events_url": "https://api.github.com/repos/theintern/intern/issues/179/events", 1556 | "html_url": "https://github.com/theintern/intern/issues/179", 1557 | "id": 32085842, 1558 | "number": 179, 1559 | "title": "update sauce-connect-launcher to 0.4.2", 1560 | "user": { 1561 | "login": "lbod", 1562 | "id": 733371, 1563 | "avatar_url": "https://avatars.githubusercontent.com/u/733371?", 1564 | "gravatar_id": "bb097c169912557514d09aa387819199", 1565 | "url": "https://api.github.com/users/lbod", 1566 | "html_url": "https://github.com/lbod", 1567 | "followers_url": "https://api.github.com/users/lbod/followers", 1568 | "following_url": "https://api.github.com/users/lbod/following{/other_user}", 1569 | "gists_url": "https://api.github.com/users/lbod/gists{/gist_id}", 1570 | "starred_url": "https://api.github.com/users/lbod/starred{/owner}{/repo}", 1571 | "subscriptions_url": "https://api.github.com/users/lbod/subscriptions", 1572 | "organizations_url": "https://api.github.com/users/lbod/orgs", 1573 | "repos_url": "https://api.github.com/users/lbod/repos", 1574 | "events_url": "https://api.github.com/users/lbod/events{/privacy}", 1575 | "received_events_url": "https://api.github.com/users/lbod/received_events", 1576 | "type": "User", 1577 | "site_admin": false 1578 | }, 1579 | "labels": [], 1580 | "state": "closed", 1581 | "assignee": null, 1582 | "milestone": null, 1583 | "comments": 4, 1584 | "created_at": "2014-04-23T18:20:44Z", 1585 | "updated_at": "2014-04-24T03:32:43Z", 1586 | "closed_at": "2014-04-24T03:32:43Z", 1587 | "body": "I'd submit a pr but it's just an npm config change. \r\nOne reason to move quickly to it is private keys are exposed in travis e.g. https://github.com/bermi/sauce-connect-launcher/issues/23\r\n" 1588 | } 1589 | }, 1590 | "public": true, 1591 | "created_at": "2014-04-24T03:32:43Z", 1592 | "org": { 1593 | "id": 3977877, 1594 | "login": "theintern", 1595 | "gravatar_id": "8dfcc23c784d69800577e249b0891bda", 1596 | "url": "https://api.github.com/orgs/theintern", 1597 | "avatar_url": "https://avatars.githubusercontent.com/u/3977877?" 1598 | } 1599 | }, 1600 | { 1601 | "id": "2070346032", 1602 | "type": "WatchEvent", 1603 | "actor": { 1604 | "id": 137, 1605 | "login": "josh", 1606 | "gravatar_id": "bbe5dc8dcf248706525ab76f46185520", 1607 | "url": "https://api.github.com/users/josh", 1608 | "avatar_url": "https://avatars.githubusercontent.com/u/137?" 1609 | }, 1610 | "repo": { 1611 | "id": 12271469, 1612 | "name": "JoshData/mailinabox", 1613 | "url": "https://api.github.com/repos/JoshData/mailinabox" 1614 | }, 1615 | "payload": { 1616 | "action": "started" 1617 | }, 1618 | "public": true, 1619 | "created_at": "2014-04-24T03:12:09Z" 1620 | }, 1621 | { 1622 | "id": "2070344752", 1623 | "type": "CreateEvent", 1624 | "actor": { 1625 | "id": 28143, 1626 | "login": "edvakf", 1627 | "gravatar_id": "ccecb4725f29a35a9dd6d1d0bef096ea", 1628 | "url": "https://api.github.com/users/edvakf", 1629 | "avatar_url": "https://avatars.githubusercontent.com/u/28143?" 1630 | }, 1631 | "repo": { 1632 | "id": 19094027, 1633 | "name": "edvakf/heroku-php-sample", 1634 | "url": "https://api.github.com/repos/edvakf/heroku-php-sample" 1635 | }, 1636 | "payload": { 1637 | "ref": null, 1638 | "ref_type": "repository", 1639 | "master_branch": "master", 1640 | "description": "", 1641 | "pusher_type": "user" 1642 | }, 1643 | "public": true, 1644 | "created_at": "2014-04-24T03:10:15Z" 1645 | }, 1646 | { 1647 | "id": "2070342297", 1648 | "type": "IssueCommentEvent", 1649 | "actor": { 1650 | "id": 1355710, 1651 | "login": "sheelc", 1652 | "gravatar_id": "e6efc5eee76717888394fc0d7057af0f", 1653 | "url": "https://api.github.com/users/sheelc", 1654 | "avatar_url": "https://avatars.githubusercontent.com/u/1355710?" 1655 | }, 1656 | "repo": { 1657 | "id": 84009, 1658 | "name": "pivotal/jasmine", 1659 | "url": "https://api.github.com/repos/pivotal/jasmine" 1660 | }, 1661 | "payload": { 1662 | "action": "created", 1663 | "issue": { 1664 | "url": "https://api.github.com/repos/pivotal/jasmine/issues/579", 1665 | "labels_url": "https://api.github.com/repos/pivotal/jasmine/issues/579/labels{/name}", 1666 | "comments_url": "https://api.github.com/repos/pivotal/jasmine/issues/579/comments", 1667 | "events_url": "https://api.github.com/repos/pivotal/jasmine/issues/579/events", 1668 | "html_url": "https://github.com/pivotal/jasmine/issues/579", 1669 | "id": 31915361, 1670 | "number": 579, 1671 | "title": "-0 should equal 0", 1672 | "user": { 1673 | "login": "jonatr35", 1674 | "id": 1761692, 1675 | "avatar_url": "https://avatars.githubusercontent.com/u/1761692?", 1676 | "gravatar_id": "d327f615f6275cb23f9f6ef08e5e1158", 1677 | "url": "https://api.github.com/users/jonatr35", 1678 | "html_url": "https://github.com/jonatr35", 1679 | "followers_url": "https://api.github.com/users/jonatr35/followers", 1680 | "following_url": "https://api.github.com/users/jonatr35/following{/other_user}", 1681 | "gists_url": "https://api.github.com/users/jonatr35/gists{/gist_id}", 1682 | "starred_url": "https://api.github.com/users/jonatr35/starred{/owner}{/repo}", 1683 | "subscriptions_url": "https://api.github.com/users/jonatr35/subscriptions", 1684 | "organizations_url": "https://api.github.com/users/jonatr35/orgs", 1685 | "repos_url": "https://api.github.com/users/jonatr35/repos", 1686 | "events_url": "https://api.github.com/users/jonatr35/events{/privacy}", 1687 | "received_events_url": "https://api.github.com/users/jonatr35/received_events", 1688 | "type": "User", 1689 | "site_admin": false 1690 | }, 1691 | "labels": [], 1692 | "state": "open", 1693 | "assignee": null, 1694 | "milestone": null, 1695 | "comments": 1, 1696 | "created_at": "2014-04-21T18:50:46Z", 1697 | "updated_at": "2014-04-24T03:06:32Z", 1698 | "closed_at": null, 1699 | "body": "I've written a unit test for a function were I expect my returned value to be rounded to 0 (example -0.4 should return 0). I've written my unit test as expect(result).toEqual(0) and it is failing. \r\n\r\nWhen attempting to debug I eventually found out that it was failing because it thought that -0 did not equal 0. It did however pass when using expect(result).toBe(0), however I should still be able to use expect(-0).toEqual(0)." 1700 | }, 1701 | "comment": { 1702 | "url": "https://api.github.com/repos/pivotal/jasmine/issues/comments/41238392", 1703 | "html_url": "https://github.com/pivotal/jasmine/issues/579#issuecomment-41238392", 1704 | "issue_url": "https://api.github.com/repos/pivotal/jasmine/issues/579", 1705 | "id": 41238392, 1706 | "user": { 1707 | "login": "sheelc", 1708 | "id": 1355710, 1709 | "avatar_url": "https://avatars.githubusercontent.com/u/1355710?", 1710 | "gravatar_id": "e6efc5eee76717888394fc0d7057af0f", 1711 | "url": "https://api.github.com/users/sheelc", 1712 | "html_url": "https://github.com/sheelc", 1713 | "followers_url": "https://api.github.com/users/sheelc/followers", 1714 | "following_url": "https://api.github.com/users/sheelc/following{/other_user}", 1715 | "gists_url": "https://api.github.com/users/sheelc/gists{/gist_id}", 1716 | "starred_url": "https://api.github.com/users/sheelc/starred{/owner}{/repo}", 1717 | "subscriptions_url": "https://api.github.com/users/sheelc/subscriptions", 1718 | "organizations_url": "https://api.github.com/users/sheelc/orgs", 1719 | "repos_url": "https://api.github.com/users/sheelc/repos", 1720 | "events_url": "https://api.github.com/users/sheelc/events{/privacy}", 1721 | "received_events_url": "https://api.github.com/users/sheelc/received_events", 1722 | "type": "User", 1723 | "site_admin": false 1724 | }, 1725 | "created_at": "2014-04-24T03:06:32Z", 1726 | "updated_at": "2014-04-24T03:06:32Z", 1727 | "body": "There's more discussion about this issue [here](https://github.com/pivotal/jasmine/issues/496) which can hopefully give some context as to why -0 does not `toEqual` 0. There's still some ongoing discussion if this is the correct decision.\r\n\r\nA quick summary though, `toBe` is JavaScript's `===` while `toEqual` is Underscore.js's notion of what equality means. The error message is better on master now where it does print out that one of the values is '-0' which can help users debug this more quickly." 1728 | } 1729 | }, 1730 | "public": true, 1731 | "created_at": "2014-04-24T03:06:32Z", 1732 | "org": { 1733 | "id": 9148, 1734 | "login": "pivotal", 1735 | "gravatar_id": "9f7ca4684008e71a26ff490caa985d8b", 1736 | "url": "https://api.github.com/orgs/pivotal", 1737 | "avatar_url": "https://avatars.githubusercontent.com/u/9148?" 1738 | } 1739 | }, 1740 | { 1741 | "id": "2070336435", 1742 | "type": "IssueCommentEvent", 1743 | "actor": { 1744 | "id": 43438, 1745 | "login": "timoxley", 1746 | "gravatar_id": "f0deca4576206207a882928e7ff32ddb", 1747 | "url": "https://api.github.com/users/timoxley", 1748 | "avatar_url": "https://avatars.githubusercontent.com/u/43438?" 1749 | }, 1750 | "repo": { 1751 | "id": 11456310, 1752 | "name": "termi/es6-transpiler", 1753 | "url": "https://api.github.com/repos/termi/es6-transpiler" 1754 | }, 1755 | "payload": { 1756 | "action": "created", 1757 | "issue": { 1758 | "url": "https://api.github.com/repos/termi/es6-transpiler/issues/34", 1759 | "labels_url": "https://api.github.com/repos/termi/es6-transpiler/issues/34/labels{/name}", 1760 | "comments_url": "https://api.github.com/repos/termi/es6-transpiler/issues/34/comments", 1761 | "events_url": "https://api.github.com/repos/termi/es6-transpiler/issues/34/events", 1762 | "html_url": "https://github.com/termi/es6-transpiler/issues/34", 1763 | "id": 32114197, 1764 | "number": 34, 1765 | "title": "Semicolon insertion", 1766 | "user": { 1767 | "login": "timoxley", 1768 | "id": 43438, 1769 | "avatar_url": "https://avatars.githubusercontent.com/u/43438?", 1770 | "gravatar_id": "f0deca4576206207a882928e7ff32ddb", 1771 | "url": "https://api.github.com/users/timoxley", 1772 | "html_url": "https://github.com/timoxley", 1773 | "followers_url": "https://api.github.com/users/timoxley/followers", 1774 | "following_url": "https://api.github.com/users/timoxley/following{/other_user}", 1775 | "gists_url": "https://api.github.com/users/timoxley/gists{/gist_id}", 1776 | "starred_url": "https://api.github.com/users/timoxley/starred{/owner}{/repo}", 1777 | "subscriptions_url": "https://api.github.com/users/timoxley/subscriptions", 1778 | "organizations_url": "https://api.github.com/users/timoxley/orgs", 1779 | "repos_url": "https://api.github.com/users/timoxley/repos", 1780 | "events_url": "https://api.github.com/users/timoxley/events{/privacy}", 1781 | "received_events_url": "https://api.github.com/users/timoxley/received_events", 1782 | "type": "User", 1783 | "site_admin": false 1784 | }, 1785 | "labels": [], 1786 | "state": "open", 1787 | "assignee": null, 1788 | "milestone": null, 1789 | "comments": 1, 1790 | "created_at": "2014-04-24T01:39:41Z", 1791 | "updated_at": "2014-04-24T02:58:41Z", 1792 | "closed_at": null, 1793 | "body": "The transpiler should probably insert semicolons wherever they would be inserted automatically in the source code, otherwise it can generate invalid JS when semicolons are omitted. See example below.\r\n\r\nMaybe it'd be possible to only auto-insert them whenever a *generated* line will be broken by their omission e.g. any generated line starting with ( or [.\r\n\r\nedit: found more minimal test case.\r\n\r\nES6 input:\r\n```js\r\nlet a = {\r\n b: {\r\n c: () => 0\r\n }\r\n}\r\n\r\nlet exec = () => {\r\n let args = []\r\n a.b.c(...args)\r\n}\r\n\r\nexec()\r\n```\r\n\r\nGenerated output:\r\n\r\n```js\r\nvar a = {\r\n b: {\r\n c: function() {return 0}\r\n }\r\n}\r\n\r\nvar exec = function() {var $D$0;function ITER$0(v,f){var $Symbol_iterator=typeof Symbol!=='undefined'&&Symbol.iterator||'@@iterator';if(v){if(Array.isArray(v))return f?v.slice():v;var i,r;if(typeof v==='object'&&typeof (f=v[$Symbol_iterator])==='function'){i=f.call(v);r=[];while((f=i['next']()),f['done']!==true)r.push(f['value']);return r;}}throw new Error(v+' is not iterable')};\r\n var args = []\r\n ($D$0 = a.b).c.apply($D$0, ITER$0(args))\r\n;$D$0 = void 0}\r\n\r\nexec()\r\n```\r\n\r\nError: \r\n\r\n```js\r\n ($D$0 = a.b).c.apply($D$0, ITER$0(args))\r\n ^\r\nTypeError: object is not a function\r\n```\r\n\r\nProblem is there's no semi between these two lines, so it's interpreted as `var args = []($D$0 = a.b)`, but would be valid es6 without the transpiler.\r\n```js\r\n...\r\n var args = []\r\n ($D$0 = a.b).c.apply($D$0, ITER$0(args))\r\n...\r\n```\r\n\r\nPerhaps the most minimal fix would be to just add a semi for the specific case of accessing arrow functions nested in other objects." 1794 | }, 1795 | "comment": { 1796 | "url": "https://api.github.com/repos/termi/es6-transpiler/issues/comments/41238088", 1797 | "html_url": "https://github.com/termi/es6-transpiler/issues/34#issuecomment-41238088", 1798 | "issue_url": "https://api.github.com/repos/termi/es6-transpiler/issues/34", 1799 | "id": 41238088, 1800 | "user": { 1801 | "login": "timoxley", 1802 | "id": 43438, 1803 | "avatar_url": "https://avatars.githubusercontent.com/u/43438?", 1804 | "gravatar_id": "f0deca4576206207a882928e7ff32ddb", 1805 | "url": "https://api.github.com/users/timoxley", 1806 | "html_url": "https://github.com/timoxley", 1807 | "followers_url": "https://api.github.com/users/timoxley/followers", 1808 | "following_url": "https://api.github.com/users/timoxley/following{/other_user}", 1809 | "gists_url": "https://api.github.com/users/timoxley/gists{/gist_id}", 1810 | "starred_url": "https://api.github.com/users/timoxley/starred{/owner}{/repo}", 1811 | "subscriptions_url": "https://api.github.com/users/timoxley/subscriptions", 1812 | "organizations_url": "https://api.github.com/users/timoxley/orgs", 1813 | "repos_url": "https://api.github.com/users/timoxley/repos", 1814 | "events_url": "https://api.github.com/users/timoxley/events{/privacy}", 1815 | "received_events_url": "https://api.github.com/users/timoxley/received_events", 1816 | "type": "User", 1817 | "site_admin": false 1818 | }, 1819 | "created_at": "2014-04-24T02:58:41Z", 1820 | "updated_at": "2014-04-24T02:58:41Z", 1821 | "body": "Dug into this a bit, it's this spread handling code causing the problem: \r\n```js\r\n\t\t\t\tlet tempVar = core.getScopeTempVar(node.callee.object, node.$scope);\r\n\r\n\t\t\t\tthis.alter.wrap(\r\n\t\t\t\t\tnode.callee.object.range[0]\r\n\t\t\t\t\t, node.callee.object.range[1]\r\n\t\t\t\t\t, \"(\" + tempVar + \" = \"\r\n\t\t\t\t\t, \")\"\r\n\t\t\t\t);\r\n\r\n\t\t\t\texpressionAfter =\r\n\t\t\t\t\t\".apply(\" + tempVar\r\n\t\t\t\t\t+ \", \"\r\n\t\t\t\t;\r\n\r\n\t\t\t\tcore.setScopeTempVar(tempVar, node, node.$scope, true);\r\n```\r\n[Source](https://github.com/termi/es6-transpiler/blob/ce76ed49bb4fffe6866d3f5d8ca6ffb96c0c7fed/transpiler/spread.js#L90-L94)\r\n\r\nOne can fix this specific issue with:\r\n\r\n```js\r\n\t\t\t\tthis.alter.wrap(\r\n\t\t\t\t\tnode.callee.object.range[0]\r\n\t\t\t\t\t, node.callee.object.range[1]\r\n\t\t\t\t\t, \";(\" + tempVar + \" = \" // added leading semi\r\n\t\t\t\t\t, \")\"\r\n\t\t\t\t);\r\n```\r\n\r\nBut this causes a bunch of other issues if the statement isn't at the start of the line, e.g:\r\n\r\n```js\r\nconsole.log( ;($D$0 = obj$0.obj).test.apply($D$0, [28].concat(ITER$0(arr))) === \"THIS|28|6|3\" )\r\n```\r\n```js\r\n var T$3 = ;($D$0 = obj$0.obj).test.apply($D$0, [27].concat(ITER$0(arr)));\r\n```\r\nso looks like it requires some probing around the context to detect if there's any leading code… or perhaps some other type of handling, going to have to leave this to you though, sorry!\r\n\r\n\r\n\r\n\r\n" 1822 | } 1823 | }, 1824 | "public": true, 1825 | "created_at": "2014-04-24T02:58:44Z" 1826 | }, 1827 | { 1828 | "id": "2070328849", 1829 | "type": "PullRequestEvent", 1830 | "actor": { 1831 | "id": 164497, 1832 | "login": "jgable", 1833 | "gravatar_id": "2ed341e37f2c3ef44296019c9e9829bf", 1834 | "url": "https://api.github.com/users/jgable", 1835 | "avatar_url": "https://avatars.githubusercontent.com/u/164497?" 1836 | }, 1837 | "repo": { 1838 | "id": 12670444, 1839 | "name": "petkaantonov/bluebird", 1840 | "url": "https://api.github.com/repos/petkaantonov/bluebird" 1841 | }, 1842 | "payload": { 1843 | "action": "opened", 1844 | "number": 188, 1845 | "pull_request": { 1846 | "url": "https://api.github.com/repos/petkaantonov/bluebird/pulls/188", 1847 | "id": 15100350, 1848 | "html_url": "https://github.com/petkaantonov/bluebird/pull/188", 1849 | "diff_url": "https://github.com/petkaantonov/bluebird/pull/188.diff", 1850 | "patch_url": "https://github.com/petkaantonov/bluebird/pull/188.patch", 1851 | "issue_url": "https://api.github.com/repos/petkaantonov/bluebird/issues/188", 1852 | "number": 188, 1853 | "state": "open", 1854 | "title": "Clarify .spread tip in example", 1855 | "user": { 1856 | "login": "jgable", 1857 | "id": 164497, 1858 | "avatar_url": "https://avatars.githubusercontent.com/u/164497?", 1859 | "gravatar_id": "2ed341e37f2c3ef44296019c9e9829bf", 1860 | "url": "https://api.github.com/users/jgable", 1861 | "html_url": "https://github.com/jgable", 1862 | "followers_url": "https://api.github.com/users/jgable/followers", 1863 | "following_url": "https://api.github.com/users/jgable/following{/other_user}", 1864 | "gists_url": "https://api.github.com/users/jgable/gists{/gist_id}", 1865 | "starred_url": "https://api.github.com/users/jgable/starred{/owner}{/repo}", 1866 | "subscriptions_url": "https://api.github.com/users/jgable/subscriptions", 1867 | "organizations_url": "https://api.github.com/users/jgable/orgs", 1868 | "repos_url": "https://api.github.com/users/jgable/repos", 1869 | "events_url": "https://api.github.com/users/jgable/events{/privacy}", 1870 | "received_events_url": "https://api.github.com/users/jgable/received_events", 1871 | "type": "User", 1872 | "site_admin": false 1873 | }, 1874 | "body": "Naming the parameter `request` could lead to confusion and possible unexpected behavior since there is already a `request` module defined.", 1875 | "created_at": "2014-04-24T02:47:46Z", 1876 | "updated_at": "2014-04-24T02:47:46Z", 1877 | "closed_at": null, 1878 | "merged_at": null, 1879 | "merge_commit_sha": null, 1880 | "assignee": null, 1881 | "milestone": null, 1882 | "commits_url": "https://api.github.com/repos/petkaantonov/bluebird/pulls/188/commits", 1883 | "review_comments_url": "https://api.github.com/repos/petkaantonov/bluebird/pulls/188/comments", 1884 | "review_comment_url": "https://api.github.com/repos/petkaantonov/bluebird/pulls/comments/{number}", 1885 | "comments_url": "https://api.github.com/repos/petkaantonov/bluebird/issues/188/comments", 1886 | "statuses_url": "https://api.github.com/repos/petkaantonov/bluebird/statuses/ccebcbe86b6a52c43291ed4ed07e8feea9c4960a", 1887 | "head": { 1888 | "label": "jgable:patch-1", 1889 | "ref": "patch-1", 1890 | "sha": "ccebcbe86b6a52c43291ed4ed07e8feea9c4960a", 1891 | "user": { 1892 | "login": "jgable", 1893 | "id": 164497, 1894 | "avatar_url": "https://avatars.githubusercontent.com/u/164497?", 1895 | "gravatar_id": "2ed341e37f2c3ef44296019c9e9829bf", 1896 | "url": "https://api.github.com/users/jgable", 1897 | "html_url": "https://github.com/jgable", 1898 | "followers_url": "https://api.github.com/users/jgable/followers", 1899 | "following_url": "https://api.github.com/users/jgable/following{/other_user}", 1900 | "gists_url": "https://api.github.com/users/jgable/gists{/gist_id}", 1901 | "starred_url": "https://api.github.com/users/jgable/starred{/owner}{/repo}", 1902 | "subscriptions_url": "https://api.github.com/users/jgable/subscriptions", 1903 | "organizations_url": "https://api.github.com/users/jgable/orgs", 1904 | "repos_url": "https://api.github.com/users/jgable/repos", 1905 | "events_url": "https://api.github.com/users/jgable/events{/privacy}", 1906 | "received_events_url": "https://api.github.com/users/jgable/received_events", 1907 | "type": "User", 1908 | "site_admin": false 1909 | }, 1910 | "repo": { 1911 | "id": 19093382, 1912 | "name": "bluebird", 1913 | "full_name": "jgable/bluebird", 1914 | "owner": { 1915 | "login": "jgable", 1916 | "id": 164497, 1917 | "avatar_url": "https://avatars.githubusercontent.com/u/164497?", 1918 | "gravatar_id": "2ed341e37f2c3ef44296019c9e9829bf", 1919 | "url": "https://api.github.com/users/jgable", 1920 | "html_url": "https://github.com/jgable", 1921 | "followers_url": "https://api.github.com/users/jgable/followers", 1922 | "following_url": "https://api.github.com/users/jgable/following{/other_user}", 1923 | "gists_url": "https://api.github.com/users/jgable/gists{/gist_id}", 1924 | "starred_url": "https://api.github.com/users/jgable/starred{/owner}{/repo}", 1925 | "subscriptions_url": "https://api.github.com/users/jgable/subscriptions", 1926 | "organizations_url": "https://api.github.com/users/jgable/orgs", 1927 | "repos_url": "https://api.github.com/users/jgable/repos", 1928 | "events_url": "https://api.github.com/users/jgable/events{/privacy}", 1929 | "received_events_url": "https://api.github.com/users/jgable/received_events", 1930 | "type": "User", 1931 | "site_admin": false 1932 | }, 1933 | "private": false, 1934 | "html_url": "https://github.com/jgable/bluebird", 1935 | "description": "Bluebird is a full featured promise library with unmatched performance.", 1936 | "fork": true, 1937 | "url": "https://api.github.com/repos/jgable/bluebird", 1938 | "forks_url": "https://api.github.com/repos/jgable/bluebird/forks", 1939 | "keys_url": "https://api.github.com/repos/jgable/bluebird/keys{/key_id}", 1940 | "collaborators_url": "https://api.github.com/repos/jgable/bluebird/collaborators{/collaborator}", 1941 | "teams_url": "https://api.github.com/repos/jgable/bluebird/teams", 1942 | "hooks_url": "https://api.github.com/repos/jgable/bluebird/hooks", 1943 | "issue_events_url": "https://api.github.com/repos/jgable/bluebird/issues/events{/number}", 1944 | "events_url": "https://api.github.com/repos/jgable/bluebird/events", 1945 | "assignees_url": "https://api.github.com/repos/jgable/bluebird/assignees{/user}", 1946 | "branches_url": "https://api.github.com/repos/jgable/bluebird/branches{/branch}", 1947 | "tags_url": "https://api.github.com/repos/jgable/bluebird/tags", 1948 | "blobs_url": "https://api.github.com/repos/jgable/bluebird/git/blobs{/sha}", 1949 | "git_tags_url": "https://api.github.com/repos/jgable/bluebird/git/tags{/sha}", 1950 | "git_refs_url": "https://api.github.com/repos/jgable/bluebird/git/refs{/sha}", 1951 | "trees_url": "https://api.github.com/repos/jgable/bluebird/git/trees{/sha}", 1952 | "statuses_url": "https://api.github.com/repos/jgable/bluebird/statuses/{sha}", 1953 | "languages_url": "https://api.github.com/repos/jgable/bluebird/languages", 1954 | "stargazers_url": "https://api.github.com/repos/jgable/bluebird/stargazers", 1955 | "contributors_url": "https://api.github.com/repos/jgable/bluebird/contributors", 1956 | "subscribers_url": "https://api.github.com/repos/jgable/bluebird/subscribers", 1957 | "subscription_url": "https://api.github.com/repos/jgable/bluebird/subscription", 1958 | "commits_url": "https://api.github.com/repos/jgable/bluebird/commits{/sha}", 1959 | "git_commits_url": "https://api.github.com/repos/jgable/bluebird/git/commits{/sha}", 1960 | "comments_url": "https://api.github.com/repos/jgable/bluebird/comments{/number}", 1961 | "issue_comment_url": "https://api.github.com/repos/jgable/bluebird/issues/comments/{number}", 1962 | "contents_url": "https://api.github.com/repos/jgable/bluebird/contents/{+path}", 1963 | "compare_url": "https://api.github.com/repos/jgable/bluebird/compare/{base}...{head}", 1964 | "merges_url": "https://api.github.com/repos/jgable/bluebird/merges", 1965 | "archive_url": "https://api.github.com/repos/jgable/bluebird/{archive_format}{/ref}", 1966 | "downloads_url": "https://api.github.com/repos/jgable/bluebird/downloads", 1967 | "issues_url": "https://api.github.com/repos/jgable/bluebird/issues{/number}", 1968 | "pulls_url": "https://api.github.com/repos/jgable/bluebird/pulls{/number}", 1969 | "milestones_url": "https://api.github.com/repos/jgable/bluebird/milestones{/number}", 1970 | "notifications_url": "https://api.github.com/repos/jgable/bluebird/notifications{?since,all,participating}", 1971 | "labels_url": "https://api.github.com/repos/jgable/bluebird/labels{/name}", 1972 | "releases_url": "https://api.github.com/repos/jgable/bluebird/releases{/id}", 1973 | "created_at": "2014-04-24T02:44:50Z", 1974 | "updated_at": "2014-04-24T02:47:46Z", 1975 | "pushed_at": "2014-04-24T02:47:33Z", 1976 | "git_url": "git://github.com/jgable/bluebird.git", 1977 | "ssh_url": "git@github.com:jgable/bluebird.git", 1978 | "clone_url": "https://github.com/jgable/bluebird.git", 1979 | "svn_url": "https://github.com/jgable/bluebird", 1980 | "homepage": "", 1981 | "size": 9569, 1982 | "stargazers_count": 0, 1983 | "watchers_count": 0, 1984 | "language": "JavaScript", 1985 | "has_issues": false, 1986 | "has_downloads": true, 1987 | "has_wiki": true, 1988 | "forks_count": 0, 1989 | "mirror_url": null, 1990 | "open_issues_count": 0, 1991 | "forks": 0, 1992 | "open_issues": 0, 1993 | "watchers": 0, 1994 | "default_branch": "master" 1995 | } 1996 | }, 1997 | "base": { 1998 | "label": "petkaantonov:master", 1999 | "ref": "master", 2000 | "sha": "35453ee5e20256e510d0d6adf80ba211add48d2b", 2001 | "user": { 2002 | "login": "petkaantonov", 2003 | "id": 829734, 2004 | "avatar_url": "https://avatars.githubusercontent.com/u/829734?", 2005 | "gravatar_id": "9f54c1f814e618404997a7291930064a", 2006 | "url": "https://api.github.com/users/petkaantonov", 2007 | "html_url": "https://github.com/petkaantonov", 2008 | "followers_url": "https://api.github.com/users/petkaantonov/followers", 2009 | "following_url": "https://api.github.com/users/petkaantonov/following{/other_user}", 2010 | "gists_url": "https://api.github.com/users/petkaantonov/gists{/gist_id}", 2011 | "starred_url": "https://api.github.com/users/petkaantonov/starred{/owner}{/repo}", 2012 | "subscriptions_url": "https://api.github.com/users/petkaantonov/subscriptions", 2013 | "organizations_url": "https://api.github.com/users/petkaantonov/orgs", 2014 | "repos_url": "https://api.github.com/users/petkaantonov/repos", 2015 | "events_url": "https://api.github.com/users/petkaantonov/events{/privacy}", 2016 | "received_events_url": "https://api.github.com/users/petkaantonov/received_events", 2017 | "type": "User", 2018 | "site_admin": false 2019 | }, 2020 | "repo": { 2021 | "id": 12670444, 2022 | "name": "bluebird", 2023 | "full_name": "petkaantonov/bluebird", 2024 | "owner": { 2025 | "login": "petkaantonov", 2026 | "id": 829734, 2027 | "avatar_url": "https://avatars.githubusercontent.com/u/829734?", 2028 | "gravatar_id": "9f54c1f814e618404997a7291930064a", 2029 | "url": "https://api.github.com/users/petkaantonov", 2030 | "html_url": "https://github.com/petkaantonov", 2031 | "followers_url": "https://api.github.com/users/petkaantonov/followers", 2032 | "following_url": "https://api.github.com/users/petkaantonov/following{/other_user}", 2033 | "gists_url": "https://api.github.com/users/petkaantonov/gists{/gist_id}", 2034 | "starred_url": "https://api.github.com/users/petkaantonov/starred{/owner}{/repo}", 2035 | "subscriptions_url": "https://api.github.com/users/petkaantonov/subscriptions", 2036 | "organizations_url": "https://api.github.com/users/petkaantonov/orgs", 2037 | "repos_url": "https://api.github.com/users/petkaantonov/repos", 2038 | "events_url": "https://api.github.com/users/petkaantonov/events{/privacy}", 2039 | "received_events_url": "https://api.github.com/users/petkaantonov/received_events", 2040 | "type": "User", 2041 | "site_admin": false 2042 | }, 2043 | "private": false, 2044 | "html_url": "https://github.com/petkaantonov/bluebird", 2045 | "description": "Bluebird is a full featured promise library with unmatched performance.", 2046 | "fork": false, 2047 | "url": "https://api.github.com/repos/petkaantonov/bluebird", 2048 | "forks_url": "https://api.github.com/repos/petkaantonov/bluebird/forks", 2049 | "keys_url": "https://api.github.com/repos/petkaantonov/bluebird/keys{/key_id}", 2050 | "collaborators_url": "https://api.github.com/repos/petkaantonov/bluebird/collaborators{/collaborator}", 2051 | "teams_url": "https://api.github.com/repos/petkaantonov/bluebird/teams", 2052 | "hooks_url": "https://api.github.com/repos/petkaantonov/bluebird/hooks", 2053 | "issue_events_url": "https://api.github.com/repos/petkaantonov/bluebird/issues/events{/number}", 2054 | "events_url": "https://api.github.com/repos/petkaantonov/bluebird/events", 2055 | "assignees_url": "https://api.github.com/repos/petkaantonov/bluebird/assignees{/user}", 2056 | "branches_url": "https://api.github.com/repos/petkaantonov/bluebird/branches{/branch}", 2057 | "tags_url": "https://api.github.com/repos/petkaantonov/bluebird/tags", 2058 | "blobs_url": "https://api.github.com/repos/petkaantonov/bluebird/git/blobs{/sha}", 2059 | "git_tags_url": "https://api.github.com/repos/petkaantonov/bluebird/git/tags{/sha}", 2060 | "git_refs_url": "https://api.github.com/repos/petkaantonov/bluebird/git/refs{/sha}", 2061 | "trees_url": "https://api.github.com/repos/petkaantonov/bluebird/git/trees{/sha}", 2062 | "statuses_url": "https://api.github.com/repos/petkaantonov/bluebird/statuses/{sha}", 2063 | "languages_url": "https://api.github.com/repos/petkaantonov/bluebird/languages", 2064 | "stargazers_url": "https://api.github.com/repos/petkaantonov/bluebird/stargazers", 2065 | "contributors_url": "https://api.github.com/repos/petkaantonov/bluebird/contributors", 2066 | "subscribers_url": "https://api.github.com/repos/petkaantonov/bluebird/subscribers", 2067 | "subscription_url": "https://api.github.com/repos/petkaantonov/bluebird/subscription", 2068 | "commits_url": "https://api.github.com/repos/petkaantonov/bluebird/commits{/sha}", 2069 | "git_commits_url": "https://api.github.com/repos/petkaantonov/bluebird/git/commits{/sha}", 2070 | "comments_url": "https://api.github.com/repos/petkaantonov/bluebird/comments{/number}", 2071 | "issue_comment_url": "https://api.github.com/repos/petkaantonov/bluebird/issues/comments/{number}", 2072 | "contents_url": "https://api.github.com/repos/petkaantonov/bluebird/contents/{+path}", 2073 | "compare_url": "https://api.github.com/repos/petkaantonov/bluebird/compare/{base}...{head}", 2074 | "merges_url": "https://api.github.com/repos/petkaantonov/bluebird/merges", 2075 | "archive_url": "https://api.github.com/repos/petkaantonov/bluebird/{archive_format}{/ref}", 2076 | "downloads_url": "https://api.github.com/repos/petkaantonov/bluebird/downloads", 2077 | "issues_url": "https://api.github.com/repos/petkaantonov/bluebird/issues{/number}", 2078 | "pulls_url": "https://api.github.com/repos/petkaantonov/bluebird/pulls{/number}", 2079 | "milestones_url": "https://api.github.com/repos/petkaantonov/bluebird/milestones{/number}", 2080 | "notifications_url": "https://api.github.com/repos/petkaantonov/bluebird/notifications{?since,all,participating}", 2081 | "labels_url": "https://api.github.com/repos/petkaantonov/bluebird/labels{/name}", 2082 | "releases_url": "https://api.github.com/repos/petkaantonov/bluebird/releases{/id}", 2083 | "created_at": "2013-09-07T19:39:57Z", 2084 | "updated_at": "2014-04-24T00:45:55Z", 2085 | "pushed_at": "2014-04-23T10:17:34Z", 2086 | "git_url": "git://github.com/petkaantonov/bluebird.git", 2087 | "ssh_url": "git@github.com:petkaantonov/bluebird.git", 2088 | "clone_url": "https://github.com/petkaantonov/bluebird.git", 2089 | "svn_url": "https://github.com/petkaantonov/bluebird", 2090 | "homepage": "", 2091 | "size": 9569, 2092 | "stargazers_count": 1886, 2093 | "watchers_count": 1886, 2094 | "language": "JavaScript", 2095 | "has_issues": true, 2096 | "has_downloads": true, 2097 | "has_wiki": true, 2098 | "forks_count": 102, 2099 | "mirror_url": null, 2100 | "open_issues_count": 4, 2101 | "forks": 102, 2102 | "open_issues": 4, 2103 | "watchers": 1886, 2104 | "default_branch": "master" 2105 | } 2106 | }, 2107 | "_links": { 2108 | "self": { 2109 | "href": "https://api.github.com/repos/petkaantonov/bluebird/pulls/188" 2110 | }, 2111 | "html": { 2112 | "href": "https://github.com/petkaantonov/bluebird/pull/188" 2113 | }, 2114 | "issue": { 2115 | "href": "https://api.github.com/repos/petkaantonov/bluebird/issues/188" 2116 | }, 2117 | "comments": { 2118 | "href": "https://api.github.com/repos/petkaantonov/bluebird/issues/188/comments" 2119 | }, 2120 | "review_comments": { 2121 | "href": "https://api.github.com/repos/petkaantonov/bluebird/pulls/188/comments" 2122 | }, 2123 | "review_comment": { 2124 | "href": "https://api.github.com/repos/petkaantonov/bluebird/pulls/comments/{number}" 2125 | }, 2126 | "commits": { 2127 | "href": "https://api.github.com/repos/petkaantonov/bluebird/pulls/188/commits" 2128 | }, 2129 | "statuses": { 2130 | "href": "https://api.github.com/repos/petkaantonov/bluebird/statuses/ccebcbe86b6a52c43291ed4ed07e8feea9c4960a" 2131 | } 2132 | }, 2133 | "merged": false, 2134 | "mergeable": null, 2135 | "mergeable_state": "unknown", 2136 | "merged_by": null, 2137 | "comments": 0, 2138 | "review_comments": 0, 2139 | "commits": 1, 2140 | "additions": 1, 2141 | "deletions": 1, 2142 | "changed_files": 1 2143 | } 2144 | }, 2145 | "public": true, 2146 | "created_at": "2014-04-24T02:47:46Z" 2147 | }, 2148 | { 2149 | "id": "2070328344", 2150 | "type": "IssuesEvent", 2151 | "actor": { 2152 | "id": 4852269, 2153 | "login": "cdisdero", 2154 | "gravatar_id": "fc893cde1f76b4b3ca86518b026b74c0", 2155 | "url": "https://api.github.com/users/cdisdero", 2156 | "avatar_url": "https://avatars.githubusercontent.com/u/4852269?" 2157 | }, 2158 | "repo": { 2159 | "id": 9639981, 2160 | "name": "facebook/xctool", 2161 | "url": "https://api.github.com/repos/facebook/xctool" 2162 | }, 2163 | "payload": { 2164 | "action": "opened", 2165 | "issue": { 2166 | "url": "https://api.github.com/repos/facebook/xctool/issues/359", 2167 | "labels_url": "https://api.github.com/repos/facebook/xctool/issues/359/labels{/name}", 2168 | "comments_url": "https://api.github.com/repos/facebook/xctool/issues/359/comments", 2169 | "events_url": "https://api.github.com/repos/facebook/xctool/issues/359/events", 2170 | "html_url": "https://github.com/facebook/xctool/issues/359", 2171 | "id": 32116375, 2172 | "number": 359, 2173 | "title": "Jenkins error \"Process leaked file descriptors\" running xctool", 2174 | "user": { 2175 | "login": "cdisdero", 2176 | "id": 4852269, 2177 | "avatar_url": "https://avatars.githubusercontent.com/u/4852269?", 2178 | "gravatar_id": "fc893cde1f76b4b3ca86518b026b74c0", 2179 | "url": "https://api.github.com/users/cdisdero", 2180 | "html_url": "https://github.com/cdisdero", 2181 | "followers_url": "https://api.github.com/users/cdisdero/followers", 2182 | "following_url": "https://api.github.com/users/cdisdero/following{/other_user}", 2183 | "gists_url": "https://api.github.com/users/cdisdero/gists{/gist_id}", 2184 | "starred_url": "https://api.github.com/users/cdisdero/starred{/owner}{/repo}", 2185 | "subscriptions_url": "https://api.github.com/users/cdisdero/subscriptions", 2186 | "organizations_url": "https://api.github.com/users/cdisdero/orgs", 2187 | "repos_url": "https://api.github.com/users/cdisdero/repos", 2188 | "events_url": "https://api.github.com/users/cdisdero/events{/privacy}", 2189 | "received_events_url": "https://api.github.com/users/cdisdero/received_events", 2190 | "type": "User", 2191 | "site_admin": false 2192 | }, 2193 | "labels": [], 2194 | "state": "open", 2195 | "assignee": null, 2196 | "milestone": null, 2197 | "comments": 0, 2198 | "created_at": "2014-04-24T02:47:02Z", 2199 | "updated_at": "2014-04-24T02:47:02Z", 2200 | "closed_at": null, 2201 | "body": "Why is it that when I try to run the latest version of xctool.sh from Jenkins (latest version) I get the following error?\r\n\r\nStarted by user cdisdero\r\nBuilding in workspace /Users/Shared/Jenkins/Home/jobs/MyProject/workspace\r\nFetching changes from the remote Git repository\r\nFetching upstream changes from git@bitbucket.org:cdisdero/MyProject.git\r\nusing GIT_SSH to set credentials jenkins Bitbucket.org key\r\nChecking out Revision 6da41d06cf7da87d01204f8ce0951cab6f359523 (origin/master)\r\n[workspace] $ /bin/sh -xe /Users/Shared/Jenkins/tmp/hudson4580931669760076203.sh\r\n+ /Users/Shared/Jenkins/Home/tools/xctool/scripts/xctool.sh -project MyProject.xcodeproj -scheme MyProject -sdk iphonesimulator -reporter junit:test-reports/junit-report.xml clean build\r\n\r\n...\r\n** BUILD SUCCEEDED ** (3502 ms)\r\n\r\nProcess leaked file descriptors. See http://wiki.jenkins-ci.org/display/JENKINS/Spawning+processes+from+build for more information\r\nFATAL: Could not initialize class hudson.util.ProcessTree$UnixReflection\r\njava.lang.NoClassDefFoundError: Could not initialize class hudson.util.ProcessTree$UnixReflection\r\n\tat hudson.util.ProcessTree$UnixProcess.kill(ProcessTree.java:553)\r\n\tat hudson.util.ProcessTree$UnixProcess.killRecursively(ProcessTree.java:573)\r\n\tat hudson.util.ProcessTree$UnixProcess.killRecursively(ProcessTree.java:572)\r\n\tat hudson.util.ProcessTree$Unix.killAll(ProcessTree.java:497)\r\n\tat hudson.Launcher$LocalLauncher.kill(Launcher.java:798)\r\n\tat hudson.model.AbstractBuild$AbstractBuildExecution.run(AbstractBuild.java:546)\r\n\tat hudson.model.Run.execute(Run.java:1700)\r\n\tat hudson.model.FreeStyleBuild.run(FreeStyleBuild.java:43)\r\n\tat hudson.model.ResourceController.execute(ResourceController.java:88)\r\n\tat hudson.model.Executor.run(Executor.java:231)\r\n\r\n----\r\n\r\nI can run the exact same xctool.sh command from the command line using the jenkins user account on my Mac without error." 2202 | } 2203 | }, 2204 | "public": true, 2205 | "created_at": "2014-04-24T02:47:02Z", 2206 | "org": { 2207 | "id": 69631, 2208 | "login": "facebook", 2209 | "gravatar_id": "18a83f753fa76b3ea0d594247f4c93b1", 2210 | "url": "https://api.github.com/orgs/facebook", 2211 | "avatar_url": "https://avatars.githubusercontent.com/u/69631?" 2212 | } 2213 | } 2214 | ] -------------------------------------------------------------------------------- /app/js/typings/github-event.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | /** 3 | * Github EventType 4 | * @readonly 5 | * @enum {string} 6 | */ 7 | var GithubEventTypes = { 8 | CommitCommentEvent: "CommitCommentEvent", 9 | CreateEvent: "CreateEvent", 10 | DeleteEvent: "DeleteEvent", 11 | DownloadEvent: "DownloadEvent", 12 | FollowEvent: "FollowEvent", 13 | ForkEvent: "ForkEvent", 14 | ForkApplyEvent: "ForkApplyEvent", 15 | GistEvent: "GistEvent", 16 | GollumEvent: "GollumEvent", 17 | IssueCommentEvent: "IssueCommentEvent", 18 | IssuesEvent: "IssuesEvent", 19 | MemberEvent: "MemberEvent", 20 | PublicEvent: "PublicEvent", 21 | PullRequestEvent: "PullRequestEvent", 22 | PullRequestReviewCommentEvent: "PullRequestReviewCommentEvent", 23 | PushEvent: "PushEvent", 24 | TeamAddEvent: "TeamAddEvent", 25 | WatchEvent: "WatchEvent" 26 | }; 27 | module.exports.GithubEventTypes = GithubEventTypes; -------------------------------------------------------------------------------- /app/js/typings/receivedEvents.d.ts: -------------------------------------------------------------------------------- 1 | module modulename 2 | { 3 | interface Actor 4 | { 5 | id:number; 6 | login:string; 7 | gravatar_id:string; 8 | url:string; 9 | avatar_url:string; 10 | } 11 | 12 | interface Author 13 | { 14 | email:string; 15 | name:string; 16 | } 17 | 18 | interface Comment 19 | { 20 | url:string; 21 | html_url:string; 22 | issue_url:string; 23 | id:number; 24 | user:User; 25 | created_at:string; 26 | updated_at:string; 27 | body:string; 28 | } 29 | 30 | interface Comment1 31 | { 32 | url:string; 33 | id:number; 34 | diff_hunk:string; 35 | path:string; 36 | position:number; 37 | original_position:number; 38 | commit_id:string; 39 | original_commit_id:string; 40 | user:User; 41 | body:string; 42 | created_at:string; 43 | updated_at:string; 44 | html_url:string; 45 | pull_request_url:string; 46 | _links:Links1; 47 | } 48 | 49 | interface Commits 50 | { 51 | sha:string; 52 | author:Author; 53 | message:string; 54 | distinct:boolean; 55 | url:string; 56 | } 57 | 58 | interface Head 59 | { 60 | label:string; 61 | ref:string; 62 | sha:string; 63 | user:User; 64 | repo:Repo1; 65 | } 66 | 67 | interface Issue 68 | { 69 | url:string; 70 | labels_url:string; 71 | comments_url:string; 72 | events_url:string; 73 | html_url:string; 74 | id:number; 75 | number:number; 76 | title:string; 77 | user:User; 78 | labels:any[]; 79 | state:string; 80 | assignee:string; 81 | milestone:string; 82 | comments:number; 83 | created_at:string; 84 | updated_at:string; 85 | closed_at:string; 86 | body:string; 87 | } 88 | 89 | interface Issue1 90 | { 91 | url:string; 92 | labels_url:string; 93 | comments_url:string; 94 | events_url:string; 95 | html_url:string; 96 | id:number; 97 | number:number; 98 | title:string; 99 | user:User; 100 | labels:Labels[]; 101 | state:string; 102 | assignee:string; 103 | milestone:string; 104 | comments:number; 105 | created_at:string; 106 | updated_at:string; 107 | closed_at:string; 108 | pull_request:PullRequest; 109 | body:string; 110 | } 111 | 112 | interface Labels 113 | { 114 | url:string; 115 | name:string; 116 | color:string; 117 | } 118 | 119 | interface Links 120 | { 121 | self:Self; 122 | html:Self; 123 | issue:Self; 124 | comments:Self; 125 | review_comments:Self; 126 | review_comment:Self; 127 | commits:Self; 128 | statuses:Self; 129 | } 130 | 131 | interface Links1 132 | { 133 | self:Self; 134 | html:Self; 135 | pull_request:Self; 136 | } 137 | 138 | interface Payload 139 | { 140 | action:string; 141 | issue:Issue; 142 | comment:Comment; 143 | } 144 | 145 | interface Payload1 146 | { 147 | action:string; 148 | issue:Issue; 149 | } 150 | 151 | interface Payload2 152 | { 153 | action:string; 154 | number:number; 155 | pull_request:PullRequest1; 156 | } 157 | 158 | interface Payload3 159 | { 160 | comment:Comment1; 161 | } 162 | 163 | interface Payload4 164 | { 165 | push_id:number; 166 | size:number; 167 | distinct_size:number; 168 | ref:string; 169 | head:string; 170 | before:string; 171 | commits:Commits[]; 172 | } 173 | 174 | interface Payload5 175 | { 176 | action:string; 177 | } 178 | 179 | interface Payload6 180 | { 181 | ref:string; 182 | ref_type:string; 183 | master_branch:string; 184 | description:string; 185 | pusher_type:string; 186 | } 187 | 188 | interface PullRequest 189 | { 190 | url:string; 191 | html_url:string; 192 | diff_url:string; 193 | patch_url:string; 194 | } 195 | 196 | interface PullRequest1 197 | { 198 | url:string; 199 | id:number; 200 | html_url:string; 201 | diff_url:string; 202 | patch_url:string; 203 | issue_url:string; 204 | number:number; 205 | state:string; 206 | title:string; 207 | user:User; 208 | body:string; 209 | created_at:string; 210 | updated_at:string; 211 | closed_at:string; 212 | merged_at:string; 213 | merge_commit_sha:string; 214 | assignee:string; 215 | milestone:string; 216 | commits_url:string; 217 | review_comments_url:string; 218 | review_comment_url:string; 219 | comments_url:string; 220 | statuses_url:string; 221 | head:Head; 222 | base:Head; 223 | _links:Links; 224 | merged:boolean; 225 | mergeable:string; 226 | mergeable_state:string; 227 | merged_by:string; 228 | comments:number; 229 | review_comments:number; 230 | commits:number; 231 | additions:number; 232 | deletions:number; 233 | changed_files:number; 234 | } 235 | 236 | interface Repo 237 | { 238 | id:number; 239 | name:string; 240 | url:string; 241 | } 242 | 243 | interface Repo1 244 | { 245 | id:number; 246 | name:string; 247 | full_name:string; 248 | owner:User; 249 | private:boolean; 250 | html_url:string; 251 | description:string; 252 | fork:boolean; 253 | url:string; 254 | forks_url:string; 255 | keys_url:string; 256 | collaborators_url:string; 257 | teams_url:string; 258 | hooks_url:string; 259 | issue_events_url:string; 260 | events_url:string; 261 | assignees_url:string; 262 | branches_url:string; 263 | tags_url:string; 264 | blobs_url:string; 265 | git_tags_url:string; 266 | git_refs_url:string; 267 | trees_url:string; 268 | statuses_url:string; 269 | languages_url:string; 270 | stargazers_url:string; 271 | contributors_url:string; 272 | subscribers_url:string; 273 | subscription_url:string; 274 | commits_url:string; 275 | git_commits_url:string; 276 | comments_url:string; 277 | issue_comment_url:string; 278 | contents_url:string; 279 | compare_url:string; 280 | merges_url:string; 281 | archive_url:string; 282 | downloads_url:string; 283 | issues_url:string; 284 | pulls_url:string; 285 | milestones_url:string; 286 | notifications_url:string; 287 | labels_url:string; 288 | releases_url:string; 289 | created_at:string; 290 | updated_at:string; 291 | pushed_at:string; 292 | git_url:string; 293 | ssh_url:string; 294 | clone_url:string; 295 | svn_url:string; 296 | homepage:string; 297 | size:number; 298 | stargazers_count:number; 299 | watchers_count:number; 300 | language:string; 301 | has_issues:boolean; 302 | has_downloads:boolean; 303 | has_wiki:boolean; 304 | forks_count:number; 305 | mirror_url:string; 306 | open_issues_count:number; 307 | forks:number; 308 | open_issues:number; 309 | watchers:number; 310 | default_branch:string; 311 | } 312 | 313 | interface Self 314 | { 315 | href:string; 316 | } 317 | 318 | interface User 319 | { 320 | login:string; 321 | id:number; 322 | avatar_url:string; 323 | gravatar_id:string; 324 | url:string; 325 | html_url:string; 326 | followers_url:string; 327 | following_url:string; 328 | gists_url:string; 329 | starred_url:string; 330 | subscriptions_url:string; 331 | organizations_url:string; 332 | repos_url:string; 333 | events_url:string; 334 | received_events_url:string; 335 | type:string; 336 | site_admin:boolean; 337 | } 338 | 339 | 340 | } -------------------------------------------------------------------------------- /app/menu/menu.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by azu on 2014/04/29. 3 | * LICENSE : MIT 4 | */ 5 | "use strict"; 6 | (function () { 7 | var gui = require('nw.gui'); 8 | var win = gui.Window.get(); 9 | var githubReaderMenu = new gui.Menu(); 10 | // Create the open and close menu options 11 | var openMenuItem = new gui.MenuItem({ label: 'Config' }).on("click", function () { 12 | gui.Window.open('./view/user-config.html', '_blank', 'width=400,height=400'); 13 | }); 14 | 15 | githubReaderMenu.append(openMenuItem); 16 | var nativeMenuBar = new gui.Menu({ type: 'menubar' }); 17 | nativeMenuBar.createMacBuiltin("My App"); 18 | win.menu = nativeMenuBar; 19 | win.menu.insert(new gui.MenuItem({ label: 'GithubReader', submenu: githubReaderMenu}), 1); 20 | })(); -------------------------------------------------------------------------------- /app/node-webkit/workaround.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by azu on 2014/04/23. 3 | * LICENSE : MIT 4 | */ 5 | "use strict"; 6 | global.document = window.document; 7 | global.DocumentFragment = window.DocumentFragment; 8 | global.navigator = window.navigator; 9 | window.setTimeout = global.setTimeout; 10 | window.requestAnimationFrame = global.requestAnimationFrame; 11 | window.webkitRequestAnimationFrame = global.webkitRequestAnimationFrame; -------------------------------------------------------------------------------- /app/view/user-config.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | User Data 6 | 7 | 12 | 13 | 14 |
15 |
16 |
17 |
18 | 19 | 20 |
21 | 22 |
23 | 24 | 25 |
26 |
27 | 28 | 30 |
31 |
32 | 33 | 35 |
36 |
37 | 38 |
39 |
40 |
41 |
42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /app/view/user-config.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var saveButton = document.getElementById("js-save"); 3 | var userData = require("./js/config/userData"); 4 | var userConfig = require("./js/config/reloadConfig"); 5 | var Vue = require("vue"); 6 | var view = new Vue({ 7 | el: '#config-content', 8 | data: { 9 | name: "", 10 | token: "", 11 | timeInterval: 60 * 1000, 12 | filterScriptPath: "" 13 | } 14 | }); 15 | function didLodView() { 16 | var user = userData.getUserData(); 17 | view.name = user.name; 18 | view.token = user.token; 19 | view.timeInterval = userConfig.getAutoReloadTime(); 20 | view.filterScriptPath = userConfig.getFilterScriptPath(); 21 | } 22 | function saveUserData(name, token) { 23 | userData.setUserData({ 24 | name: name, 25 | token: token 26 | }) 27 | } 28 | saveButton.addEventListener("click", function (event) { 29 | if (view.name && view.token) { 30 | saveUserData(view.name, view.token); 31 | } 32 | var interval = parseInt(view.timeInterval, 10); 33 | if (!isNaN(interval)) { 34 | userConfig.setAutoReloadTime(interval); 35 | } 36 | if (view.filterScriptPath != null) { 37 | userConfig.setFilterScriptPath(view.filterScriptPath); 38 | } 39 | window.close(); 40 | }); 41 | 42 | (function () { 43 | didLodView(); 44 | })(); -------------------------------------------------------------------------------- /examples/user-filter-example.js: -------------------------------------------------------------------------------- 1 | // LICENSE : MIT 2 | "use strict"; 3 | /* 4 | item 5 | { 6 | "id": event.id,// github global event id 7 | "date": event.created_at, 8 | "user_name": event.actor.login, 9 | "avatar_url": event.actor.avatar_url, 10 | "repo_name": event.repo.name, 11 | "title": parseGithubEvent.compile(event), 12 | "html_url": parsedEvent.html_url, 13 | "body": require("./parse-event-body").parseEventBody(event) || parseGithubEvent.compile(event) 14 | } 15 | */ 16 | /** 17 | * return true == preserve item, return false == ignore item 18 | * @param item 19 | * @returns {boolean} 20 | */ 21 | module.exports = function (item) { 22 | if (item.user_name === "coveralls") { 23 | return false; 24 | } 25 | return true; 26 | }; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "github-reader", 3 | "description": "github-reader app on node-webkit", 4 | "keywords": [ 5 | "node-webkit", 6 | "github", 7 | "viewer", 8 | "notitification" 9 | ], 10 | "version": "1.4.6", 11 | "homepage": "https://github.com/azu/github-reader/", 12 | "repository": { 13 | "url": "git://github.com/azu/github-reader.git" 14 | }, 15 | "main": "app/index.html", 16 | "scripts": { 17 | "test": "mocha test/*.js", 18 | "build": "nw-zip-builder -v 0.12.3 -p 'osx64,linux64' ./ -o ./build" 19 | }, 20 | "directories": { 21 | "test": "test/" 22 | }, 23 | "author": "azu", 24 | "license": "MIT", 25 | "bugs": { 26 | "url": "https://github.com/azu/github-reader/issues" 27 | }, 28 | "dependencies": { 29 | "bluebird": "^3.1.1", 30 | "download-cache": "^1.1.1", 31 | "github": "^0.2.1", 32 | "lodash": "^3.5.0", 33 | "mousetrap": "^1.5.3", 34 | "node-notifier": "^4.0.3", 35 | "node-webkit-winstate": "^1.1.0", 36 | "parse-github-event": "^0.2.0", 37 | "purecss": "^0.6.0", 38 | "remove-markdown": "0.0.6", 39 | "request": "^2.51.0", 40 | "vue": "^1.0.13" 41 | }, 42 | "devDependencies": { 43 | "espower-loader": "^1.0.0", 44 | "intelli-espower-loader": "^1.0.1", 45 | "mocha": "^2.0.1", 46 | "nw-zip-builder": "^1.0.5", 47 | "power-assert": "^1.2.0" 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # github-reader [![Build Status](https://travis-ci.org/azu/github-reader.svg?branch=master)](https://travis-ci.org/azu/github-reader) 2 | 3 | Github Client - Viewer for [Notifications](https://github.com/notifications "Notifications") and [News Feed](https://github.com/ "GitHub") 4 | 5 | ![ScreenShot](http://cl.ly/image/2v053R0Y0s0a/2014-04-29%2022_38_04.gif) 6 | 7 | Built with [node-webkit](https://github.com/nwjs/nw.js "node-webkit"). 8 | 9 | ## Features 10 | 11 | * Viewer for mixed [Notifications](https://github.com/notifications "Notifications") and [News Feed](https://github.com/ "GitHub") 12 | * Growl Notification(for Mac only, relate issue - [Implement desktop notifications](https://github.com/nwjs/nw.js/issues/27 "Implement desktop notifications [$50] · Issue #27 · rogerwang/node-webkit")) 13 | * `J`,`K` scroll shortcut 14 | * `O` : open in browser 15 | * `Ctrl + R` reload 16 | * `Ctrl + f` : toggle search bar - [gif](http://gyazo.com/0c5ed12adcc0b22e50457d1e7e6f82e3) 17 | 18 | ## Installation 19 | 20 | **[Download latest binary](https://github.com/azu/github-reader/releases/latest)** 21 | 22 | Multi-platform support 23 | 24 | - Windows 25 | - Mac OS X 26 | - Linux 32,64bit 27 | 28 | ### Config 29 | 30 | ![token](http://monosnap.com/image/xNMXVDIlfH6Lom2Q2DMDKxPbc3kLaJ.png) 31 | 32 | * Create [New personal access token](https://github.com/settings/tokens/new "New personal access token") 33 | * require **scopes** are `notifications` and `user` 34 | 35 | ![config](http://monosnap.com/image/Dgh7zSUetiJTNuQQ55w76CYVur7G0h.png) 36 | 37 | * Open `Config` in Github-Reader.app 38 | * Input Github **username** 39 | * Input personal access token 40 | * Save & Reload 41 | 42 | #### UserFilterScript 43 | 44 | Filter notifications by using filter script 45 | 46 | ![2015-03-21_13-20-50](https://cloud.githubusercontent.com/assets/19714/6763724/1cd57b6e-cfcd-11e4-90be-8ad299c82386.jpg) 47 | 48 | 1. Create `UserFilterScript.js` 49 | 2. Set `UserFilterScript` file path in config view. 50 | 51 | [examples/user-filter-example.js](examples/user-filter-example.js): ignore "coveralls" account. 52 | 53 | ```js 54 | module.exports = function (item) { 55 | if(item.user_name === "coveralls"){ 56 | return false; 57 | } 58 | return true; 59 | }; 60 | ``` 61 | 62 | ## Develop 63 | 64 | ``` sh 65 | npm install 66 | ``` 67 | 68 | [Run apps](https://github.com/nwjs/nw.js/wiki/How-to-run-apps "run apps") with node-webkit. 69 | 70 | ## Contributing 71 | 72 | 1. Fork it! 73 | 2. Create your feature branch: `git checkout -b my-new-feature` 74 | 3. Commit your changes: `git commit -am 'Add some feature'` 75 | 4. Push to the branch: `git push origin my-new-feature` 76 | 5. Submit a pull request :D 77 | 78 | ## License 79 | 80 | MIT 81 | -------------------------------------------------------------------------------- /test/builder-util-test.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by azu on 2014/04/29. 3 | * LICENSE : MIT 4 | */ 5 | "use strict"; 6 | var builderUtil = require("../app/js/github/builder-util"); 7 | var assert = require("power-assert"); 8 | describe("builder-util", function () { 9 | describe("#normalizeResponseAPIURL", function () { 10 | context("when type is pull-request", function () { 11 | var URL = "https://api.github.com/repos/jshint/jshint/pulls/1627"; 12 | var expectedURL = "https://github.com/jshint/jshint/pull/1627"; 13 | it("should convert accessible URL", function () { 14 | assert.equal(builderUtil.normalizeResponseAPIURL(URL), expectedURL); 15 | }); 16 | }); 17 | context("when type is issues", function () { 18 | var URL = "https://api.github.com/repos/squarefrog/UIDeviceIdentifier/issues/5"; 19 | var expectedURL = "https://github.com/squarefrog/UIDeviceIdentifier/issues/5"; 20 | it("should convert accessible URL", function () { 21 | assert.equal(builderUtil.normalizeResponseAPIURL(URL), expectedURL); 22 | }); 23 | }); 24 | }); 25 | }); --------------------------------------------------------------------------------