[
  {
    "path": ".gitignore",
    "content": "/node_modules/\n.env\n"
  },
  {
    "path": "README.md",
    "content": "# ⚡️ Spark <img src=\"https://stars.medv.io/deployphp/deployer.svg\" align=\"right\"/>\n\nGo to [stars.medv.io](https://stars.medv.io)\n\nSpark is a generator of pretty little graphs called sparklines, which shows GitHub stars velocity of a repo.\n\n## Development\n\nClone repo, create _.env_ file with [personal access token](https://help.github.com/articles/creating-a-personal-access-token-for-the-command-line/):\n```\nACCESS_TOKEN=...\n```\n\nInstall packages, start server:\n```\nnpm install\nnode index.js\n```\n\n## Rate limit\n\nSpark can't eagerly load all stars of a repo, only 100 stargazers per requset allowed, and GitHub API v4 has rate limit of 5000 points per hour. \n\nSpark has special endpoint for monitoring remaining rate limit, queue size and processing svg: [stars.medv.io/status](https://stars.medv.io/status)\n\n## Related\n\n- https://github.com/qoomon/starline\n\n## License\n\nMIT\n"
  },
  {
    "path": "api.js",
    "content": "const delay = require('delay')\nconst r2 = require('r2')\n\nconst token = process.env.ACCESS_TOKEN\nconst headers = {\n  Authorization: `bearer ${token}`\n}\n\nasync function fetch(query, variables) {\n  let data\n  do {\n    try {\n\n      const response = await r2.post('https://api.github.com/graphql', {\n        headers,\n        json: {query, variables}\n      }).response\n\n      const json = await response.json()\n\n      if (json.data) {\n        data = json.data\n      } else {\n\n        if (json.message) {\n          process.stderr.write(json.message + '\\n')\n        } else {\n          process.stderr.write(JSON.stringify(json) + '\\n')\n        }\n\n        if (response.headers.has('Retry-After')) {\n          const retryAfter = parseInt(response.headers.get('Retry-After'))\n          await delay(retryAfter * 1000)\n        } else {\n          await delay(60 * 1000)\n        }\n\n      }\n\n    } catch (err) {\n      process.stderr.write(JSON.stringify(json) + '\\n')\n      await delay(5 * 1000)\n    }\n  } while (!data)\n\n  return data\n}\n\nmodule.exports = {fetch}\n"
  },
  {
    "path": "db.js",
    "content": "module.exports = {\n  \"freeCodeCamp/freeCodeCamp\": 291967,\n  \"twbs/bootstrap\": 123665,\n  \"EbookFoundation/free-programming-books\": 103899,\n  \"tensorflow/tensorflow\": 96276,\n  \"facebook/react\": 93486,\n  \"vuejs/vue\": 90762,\n  \"sindresorhus/awesome\": 82886,\n  \"getify/You-Dont-Know-JS\": 79982,\n  \"d3/d3\": 74789,\n  \"airbnb/javascript\": 69412,\n  \"robbyrussell/oh-my-zsh\": 68753,\n  \"github/gitignore\": 64371,\n  \"facebook/react-native\": 62561,\n  \"jwasham/coding-interview-university\": 60616,\n  \"electron/electron\": 58918,\n  \"angular/angular.js\": 58302,\n  \"torvalds/linux\": 57592,\n  \"FortAwesome/Font-Awesome\": 55827,\n  \"daneden/animate.css\": 50628,\n  \"jquery/jquery\": 48660,\n  \"moby/moby\": 48468,\n  \"vinta/awesome-python\": 48435,\n  \"Microsoft/vscode\": 47941,\n  \"nodejs/node\": 47596,\n  \"kamranahmedse/developer-roadmap\": 47131,\n  \"facebook/create-react-app\": 46967,\n  \"atom/atom\": 44391,\n  \"apple/swift\": 43374,\n  \"laravel/laravel\": 42122,\n  \"mrdoob/three.js\": 40970,\n  \"socketio/socket.io\": 40690,\n  \"Semantic-Org/Semantic-UI\": 40679,\n  \"golang/go\": 40273,\n  \"h5bp/html5-boilerplate\": 40215,\n  \"reactjs/redux\": 39939,\n  \"hakimel/reveal.js\": 39882,\n  \"webpack/webpack\": 39860,\n  \"axios/axios\": 39780,\n  \"meteor/meteor\": 39593,\n  \"rails/rails\": 39331,\n  \"expressjs/express\": 37664,\n  \"moment/moment\": 36429,\n  \"chartjs/Chart.js\": 36245,\n  \"nodejs/node-v0.x-archive\": 35921,\n  \"rg3/youtube-dl\": 35900,\n  \"resume/resume.github.com\": 35698,\n  \"toddmotto/public-apis\": 35543,\n  \"angular/angular\": 35067,\n  \"kubernetes/kubernetes\": 35043,\n  \"mui-org/material-ui\": 34936,\n  \"jakubroztocil/httpie\": 34896,\n  \"nvbn/thefuck\": 34760,\n  \"pallets/flask\": 34711,\n  \"jlevy/the-art-of-command-line\": 34536,\n  \"h5bp/Front-end-Developer-Interview-Questions\": 34300,\n  \"google/material-design-icons\": 34253,\n  \"getlantern/lantern\": 34117,\n  \"jekyll/jekyll\": 33940,\n  \"ionic-team/ionic\": 33858,\n  \"nwjs/nw.js\": 33529,\n  \"impress/impress.js\": 33358,\n  \"x64dbg/x64dbg\": 33232,\n  \"django/django\": 33192,\n  \"Microsoft/TypeScript\": 33047,\n  \"tensorflow/models\": 33001,\n  \"mtdvio/every-programmer-should-know\": 32793,\n  \"ReactiveX/RxJava\": 32304,\n  \"Dogfalo/materialize\": 32236,\n  \"iluwatar/java-design-patterns\": 32110,\n  \"josephmisiti/awesome-machine-learning\": 32064,\n  \"requests/requests\": 31725,\n  \"vuejs/awesome-vue\": 31362,\n  \"ossu/computer-science\": 31247,\n  \"yarnpkg/yarn\": 31173,\n  \"NARKOZ/hacker-scripts\": 31155,\n  \"lodash/lodash\": 31045,\n  \"justjavac/free-programming-books-zh_CN\": 31042,\n  \"AFNetworking/AFNetworking\": 30922,\n  \"necolas/normalize.css\": 30623,\n  \"bitcoin/bitcoin\": 30577,\n  \"typicode/json-server\": 30345,\n  \"GoogleChrome/puppeteer\": 30269,\n  \"elastic/elasticsearch\": 30180,\n  \"google/material-design-lite\": 29880,\n  \"avelino/awesome-go\": 29742,\n  \"ansible/ansible\": 29635,\n  \"ReactTraining/react-router\": 29565,\n  \"wasabeef/awesome-android-ui\": 29559,\n  \"papers-we-love/papers-we-love\": 29543,\n  \"gulpjs/gulp\": 29198,\n  \"adobe/brackets\": 28857,\n  \"firehol/netdata\": 28824,\n  \"blueimp/jQuery-File-Upload\": 28585,\n  \"Homebrew/legacy-homebrew\": 28560,\n  \"antirez/redis\": 28521,\n  \"keras-team/keras\": 28244,\n  \"adam-p/markdown-here\": 27980,\n  \"rust-lang/rust\": 27682,\n  \"Alamofire/Alamofire\": 27570,\n  \"scikit-learn/scikit-learn\": 27385,\n  \"square/retrofit\": 27360,\n  \"zurb/foundation-sites\": 27211,\n  \"jashkenas/backbone\": 27104,\n  \"babel/babel\": 27072,\n  \"thedaviddias/Front-End-Checklist\": 27038,\n  \"ant-design/ant-design\": 26940,\n  \"apache/incubator-echarts\": 26919,\n  \"scrapy/scrapy\": 26731,\n  \"neovim/neovim\": 26690,\n  \"googlesamples/android-architecture\": 26559,\n  \"Trinea/android-open-project\": 26470,\n  \"chrislgarry/Apollo-11\": 26319,\n  \"creationix/nvm\": 26079,\n  \"square/okhttp\": 26058,\n  \"jgthms/bulma\": 25902,\n  \"ElemeFE/element\": 25416,\n  \"TryGhost/Ghost\": 25352,\n  \"google/protobuf\": 25225,\n  \"ariya/phantomjs\": 25207,\n  \"donnemartin/system-design-primer\": 25206,\n  \"vsouza/awesome-ios\": 25077,\n  \"enaqx/awesome-react\": 24971,\n  \"gohugoio/hugo\": 24884,\n  \"tiimgreen/github-cheat-sheet\": 24824,\n  \"discourse/discourse\": 24721,\n  \"FreeCodeCampChina/freecodecamp.cn\": 24548,\n  \"shadowsocks/shadowsocks\": 24458,\n  \"Unitech/pm2\": 24269,\n  \"zeit/next.js\": 24248,\n  \"gogits/gogs\": 24192,\n  \"nylas/nylas-mail\": 23977,\n  \"dypsilon/frontend-dev-bookmarks\": 23969,\n  \"awesomedata/awesome-public-datasets\": 23885,\n  \"johnpapa/angular-styleguide\": 23803,\n  \"lukehoban/es6features\": 23794,\n  \"prakhar1989/awesome-courses\": 23768,\n  \"caolan/async\": 23759,\n  \"opencv/opencv\": 23757,\n  \"BVLC/caffe\": 23710,\n  \"minimaxir/big-list-of-naughty-strings\": 23630,\n  \"joshbuchea/HEAD\": 23569,\n  \"prettier/prettier\": 23564,\n  \"tastejs/todomvc\": 23459,\n  \"google/guava\": 23457,\n  \"spring-projects/spring-boot\": 23328,\n  \"facebook/immutable-js\": 23239,\n  \"sahat/hackathon-starter\": 23180,\n  \"sindresorhus/awesome-nodejs\": 23168,\n  \"alvarotrigo/fullPage.js\": 23108,\n  \"karan/Projects\": 23076,\n  \"serverless/serverless\": 22872,\n  \"lord/slate\": 22839,\n  \"jashkenas/underscore\": 22699,\n  \"storybooks/storybook\": 22583,\n  \"almasaeed2010/AdminLTE\": 22550,\n  \"Modernizr/Modernizr\": 22390,\n  \"Kickball/awesome-selfhosted\": 22364,\n  \"codepath/android_guides\": 22291,\n  \"tonsky/FiraCode\": 22223,\n  \"XX-net/XX-Net\": 22205,\n  \"select2/select2\": 22182,\n  \"kdn251/interviews\": 22174,\n  \"zeit/hyper\": 22161,\n  \"astaxie/build-web-application-with-golang\": 21908,\n  \"JetBrains/kotlin\": 21862,\n  \"certbot/certbot\": 21829,\n  \"git/git\": 21829,\n  \"zenorocha/clipboard.js\": 21776,\n  \"sdmg15/Best-websites-a-programmer-should-visit\": 21692,\n  \"mozilla/pdf.js\": 21674,\n  \"PhilJay/MPAndroidChart\": 21600,\n  \"hexojs/hexo\": 21588,\n  \"harvesthq/chosen\": 21549,\n  \"flutter/flutter\": 21540,\n  \"aymericdamien/TensorFlow-Examples\": 21512,\n  \"fastlane/fastlane\": 21405,\n  \"parcel-bundler/parcel\": 21376,\n  \"Leaflet/Leaflet\": 21320,\n  \"kenwheeler/slick\": 21261,\n  \"bayandin/awesome-awesomeness\": 21207,\n  \"bumptech/glide\": 21193,\n  \"grafana/grafana\": 21171,\n  \"shadowsocks/shadowsocks-windows\": 21168,\n  \"rethinkdb/rethinkdb\": 21086,\n  \"Hack-with-Github/Awesome-Hacking\": 21048,\n  \"photonstorm/phaser\": 21043,\n  \"videojs/video.js\": 20869,\n  \"gatsbyjs/gatsby\": 20781,\n  \"JakeWharton/butterknife\": 20742,\n  \"koajs/koa\": 20716,\n  \"alex/what-happens-when\": 20630,\n  \"gitlabhq/gitlabhq\": 20595,\n  \"kamranahmedse/design-patterns-for-humans\": 20494,\n  \"spring-projects/spring-framework\": 20385,\n  \"yangshun/tech-interview-handbook\": 20238,\n  \"syncthing/syncthing\": 20116,\n  \"airbnb/lottie-android\": 20046,\n  \"juliangarnier/anime\": 19820,\n  \"kelseyhightower/nocode\": 19752,\n  \"nvie/gitflow\": 19707,\n  \"rs/SDWebImage\": 19705,\n  \"k88hudson/git-flight-rules\": 19686,\n  \"Chalarangelo/30-seconds-of-code\": 19611,\n  \"open-guides/og-aws\": 19555,\n  \"Polymer/polymer\": 19393,\n  \"request/request\": 19165,\n  \"FezVrasta/bootstrap-material-design\": 19159,\n  \"square/leakcanary\": 19085,\n  \"herrbischoff/awesome-macos-command-line\": 19010,\n  \"Reactive-Extensions/RxJS\": 18929,\n  \"emberjs/ember.js\": 18904,\n  \"IanLunn/Hover\": 18898,\n  \"facebook/pop\": 18820,\n  \"balderdashy/sails\": 18818,\n  \"mathiasbynens/dotfiles\": 18810,\n  \"apache/incubator-superset\": 18775,\n  \"MaximAbramchuck/awesome-interview-questions\": 18650,\n  \"ReactiveCocoa/ReactiveCocoa\": 18597,\n  \"aosabook/500lines\": 18588,\n  \"ZuzooVn/machine-learning-for-software-engineers\": 18559,\n  \"Bilibili/ijkplayer\": 18550,\n  \"plataformatec/devise\": 18503,\n  \"pure-css/pure\": 18488,\n  \"huginn/huginn\": 18488,\n  \"railsware/upterm\": 18464,\n  \"ripienaar/free-for-dev\": 18460,\n  \"github/fetch\": 18454,\n  \"jondot/awesome-react-native\": 18453,\n  \"ziadoz/awesome-php\": 18451,\n  \"developit/preact\": 18398,\n  \"Tencent/weui\": 18330,\n  \"pixijs/pixi.js\": 18305,\n  \"t4t5/sweetalert\": 18278,\n  \"soimort/you-get\": 18211,\n  \"tipsy/profile-summary-for-github\": 18167,\n  \"postcss/postcss\": 18166,\n  \"hammerjs/hammer.js\": 18147,\n  \"google/web-starter-kit\": 18141,\n  \"zxing/zxing\": 18126,\n  \"ryanmcdermott/clean-code-javascript\": 18083,\n  \"isocpp/CppCoreGuidelines\": 18009,\n  \"GitbookIO/gitbook\": 18001,\n  \"apache/incubator-dubbo\": 17976,\n  \"greenrobot/EventBus\": 17933,\n  \"jaywcjlove/awesome-mac\": 17925,\n  \"danielgindi/Charts\": 17925,\n  \"Prinzhorn/skrollr\": 17880,\n  \"numbbbbb/the-swift-programming-language-in-chinese\": 17866,\n  \"coreos/etcd\": 17784,\n  \"react-boilerplate/react-boilerplate\": 17755,\n  \"freeCodeCamp/devdocs\": 17708,\n  \"tesseract-ocr/tesseract\": 17684,\n  \"bailicangdu/vue2-elm\": 17663,\n  \"quilljs/quill\": 17555,\n  \"bevacqua/dragula\": 17513,\n  \"standard/standard\": 17433,\n  \"FallibleInc/security-guide-for-developers\": 17407,\n  \"kriasoft/react-starter-kit\": 17390,\n  \"RocketChat/Rocket.Chat\": 17371,\n  \"Blankj/AndroidUtilCode\": 17295,\n  \"VundleVim/Vundle.vim\": 17278,\n  \"symfony/symfony\": 17277,\n  \"BradLarson/GPUImage\": 17270,\n  \"ajaxorg/ace\": 17268,\n  \"0xAX/linux-insides\": 17253,\n  \"elsewhencode/project-guidelines\": 17238,\n  \"php/php-src\": 17209,\n  \"racaljk/hosts\": 17176,\n  \"python/cpython\": 17156,\n  \"CyC2018/Interview-Notebook\": 17075,\n  \"exacity/deeplearningbook-chinese\": 17075,\n  \"verekia/js-stack-from-scratch\": 17034,\n  \"kahun/awesome-sysadmin\": 16983,\n  \"SamyPesse/How-to-Make-a-Computer-Operating-System\": 16980,\n  \"dkhamsing/open-source-ios-apps\": 16949,\n  \"angular/angular-cli\": 16940,\n  \"getlantern/forum\": 16922,\n  \"facebook/jest\": 16911,\n  \"apache/spark\": 16903,\n  \"tldr-pages/tldr\": 16848,\n  \"floodsung/Deep-Learning-Papers-Reading-Roadmap\": 16795,\n  \"raywenderlich/swift-algorithm-club\": 16778,\n  \"mholt/caddy\": 16736,\n  \"SwiftyJSON/SwiftyJSON\": 16721,\n  \"ethereum/go-ethereum\": 16623,\n  \"petkaantonov/bluebird\": 16611,\n  \"mbeaudru/modern-js-cheatsheet\": 16544,\n  \"usablica/intro.js\": 16521,\n  \"hashicorp/vagrant\": 16519,\n  \"webtorrent/webtorrent\": 16422,\n  \"alibaba/weex\": 16417,\n  \"pugjs/pug\": 16417,\n  \"houshanren/hangzhou_house_knowledge\": 16415,\n  \"gin-gonic/gin\": 16402,\n  \"akullpp/awesome-java\": 16321,\n  \"getsentry/sentry\": 16297,\n  \"SnapKit/Masonry\": 16258,\n  \"dimsemenov/PhotoSwipe\": 16229,\n  \"Valloric/YouCompleteMe\": 16217,\n  \"ftlabs/fastclick\": 16201,\n  \"futurice/android-best-practices\": 16175,\n  \"angular/material\": 16117,\n  \"facebook/flow\": 16114,\n  \"nostra13/Android-Universal-Image-Loader\": 16061,\n  \"npm/npm\": 16047,\n  \"bcit-ci/CodeIgniter\": 15985,\n  \"nolimits4web/swiper\": 15974,\n  \"markedjs/marked\": 15968,\n  \"rstacruz/nprogress\": 15950,\n  \"knsv/mermaid\": 15893,\n  \"prometheus/prometheus\": 15800,\n  \"defunkt/jquery-pjax\": 15759,\n  \"cheeriojs/cheerio\": 15648,\n  \"ReactiveX/RxAndroid\": 15601,\n  \"jcjohnson/neural-style\": 15565,\n  \"tornadoweb/tornado\": 15541,\n  \"wg/wrk\": 15520,\n  \"dhg/Skeleton\": 15489,\n  \"google/iosched\": 15475,\n  \"less/less.js\": 15463,\n  \"styled-components/styled-components\": 15432,\n  \"dokku/dokku\": 15420,\n  \"Automattic/mongoose\": 15414,\n  \"fouber/blog\": 15407,\n  \"Kong/kong\": 15364,\n  \"bower/bower\": 15306,\n  \"segmentio/nightmare\": 15297,\n  \"square/picasso\": 15291,\n  \"fzaninotto/Faker\": 15285,\n  \"facebook/hhvm\": 15252,\n  \"mochajs/mocha\": 15148,\n  \"twitter/typeahead.js\": 15119,\n  \"DefinitelyTyped/DefinitelyTyped\": 15091,\n  \"postcss/autoprefixer\": 15070,\n  \"facebook/flux\": 15048,\n  \"faif/python-patterns\": 14964,\n  \"parse-community/parse-server\": 14954,\n  \"jlmakes/scrollreveal\": 14936,\n  \"ggreer/the_silver_searcher\": 14919,\n  \"astaxie/beego\": 14870,\n  \"tobiasahlin/SpinKit\": 14775,\n  \"grpc/grpc\": 14759,\n  \"domnikl/DesignPatternsPHP\": 14757,\n  \"CamDavidsonPilon/Probabilistic-Programming-and-Bayesian-Methods-for-Hackers\": 14721,\n  \"jashkenas/coffeescript\": 14676,\n  \"syl20bnr/spacemacs\": 14666,\n  \"VincentGarreau/particles.js\": 14657,\n  \"angular-ui/bootstrap\": 14634,\n  \"godotengine/godot\": 14623,\n  \"puikinsh/gentelella\": 14526,\n  \"containous/traefik\": 14476,\n  \"skylot/jadx\": 14473,\n  \"mobxjs/mobx\": 14469,\n  \"CodeHubApp/CodeHub\": 14459,\n  \"kripken/emscripten\": 14443,\n  \"gothinkster/realworld\": 14439,\n  \"reddit-archive/reddit\": 14438,\n  \"julianshapiro/velocity\": 14436,\n  \"jdg/MBProgressHUD\": 14414,\n  \"terryum/awesome-deep-learning-papers\": 14393,\n  \"codemirror/CodeMirror\": 14371,\n  \"facebook/fresco\": 14366,\n  \"twbs/ratchet\": 14311,\n  \"matteocrippa/awesome-swift\": 14292,\n  \"jiahaog/nativefier\": 14284,\n  \"remy/nodemon\": 14258,\n  \"Microsoft/CNTK\": 14225,\n  \"ruby/ruby\": 14198,\n  \"sindresorhus/awesome-electron\": 14175,\n  \"kriskowal/q\": 14127,\n  \"iview/iview\": 14093,\n  \"kennethreitz/python-guide\": 14081,\n  \"zeeshanu/learn-regex\": 14055,\n  \"composer/composer\": 14044,\n  \"pytorch/pytorch\": 14014,\n  \"junegunn/fzf\": 13992,\n  \"hubotio/hubot\": 13980,\n  \"StreisandEffect/streisand\": 13957,\n  \"designmodo/Flat-UI\": 13940,\n  \"shadowsocks/shadowsocks-android\": 13922,\n  \"sequelize/sequelize\": 13911,\n  \"drone/drone\": 13901,\n  \"vuejs/vuex\": 13887,\n  \"angular/material2\": 13878,\n  \"sorrycc/awesome-javascript\": 13862,\n  \"bbatsov/ruby-style-guide\": 13828,\n  \"pandas-dev/pandas\": 13824,\n  \"angular-ui/ui-router\": 13815,\n  \"rwaldron/idiomatic.js\": 13809,\n  \"google/styleguide\": 13806,\n  \"Marak/faker.js\": 13790,\n  \"cmderdev/cmder\": 13784,\n  \"dotnet/corefx\": 13758,\n  \"home-assistant/home-assistant\": 13735,\n  \"limetext/lime\": 13722,\n  \"libgdx/libgdx\": 13677,\n  \"madrobby/zepto\": 13670,\n  \"apache/incubator-mxnet\": 13670,\n  \"julycoding/The-Art-Of-Programming-By-July\": 13651,\n  \"enyo/dropzone\": 13623,\n  \"wangshub/wechat_jump_game\": 13600,\n  \"markerikson/react-redux-links\": 13569,\n  \"facebookresearch/fastText\": 13565,\n  \"netty/netty\": 13550,\n  \"avajs/ava\": 13535,\n  \"HubSpot/pace\": 13522,\n  \"mongodb/mongo\": 13499,\n  \"MostlyAdequate/mostly-adequate-guide\": 13457,\n  \"jasmine/jasmine\": 13442,\n  \"facebookresearch/Detectron\": 13434,\n  \"brillout/awesome-react-components\": 13430,\n  \"justjavac/awesome-wechat-weapp\": 13410,\n  \"yangshun/front-end-interview-handbook\": 13401,\n  \"airbnb/enzyme\": 13394,\n  \"vapor/vapor\": 13359,\n  \"naptha/tesseract.js\": 13325,\n  \"google/leveldb\": 13322,\n  \"airbnb/lottie-ios\": 13297,\n  \"lkzhao/Hero\": 13266,\n  \"i0natan/nodebestpractices\": 13264,\n  \"angular/angular-seed\": 13261,\n  \"ruanyf/jstraining\": 13244,\n  \"Netflix/Hystrix\": 13241,\n  \"alibaba/fastjson\": 13201,\n  \"legomushroom/mojs\": 13189,\n  \"wycats/handlebars.js\": 13184,\n  \"NativeScript/NativeScript\": 13171,\n  \"cockroachdb/cockroach\": 13157,\n  \"xitu/gold-miner\": 13138,\n  \"nefe/You-Dont-Need-jQuery\": 13135,\n  \"GoogleChrome/lighthouse\": 13102,\n  \"inconshreveable/ngrok\": 13100,\n  \"influxdata/influxdb\": 13097,\n  \"jaredhanson/passport\": 13096,\n  \"RubaXa/Sortable\": 13081,\n  \"wsargent/docker-cheat-sheet\": 13045,\n  \"desandro/masonry\": 13041,\n  \"tootsuite/mastodon\": 13020,\n  \"afollestad/material-dialogs\": 13009,\n  \"drduh/macOS-Security-and-Privacy-Guide\": 13002,\n  \"CymChad/BaseRecyclerViewAdapterHelper\": 12990,\n  \"ReactiveX/RxSwift\": 12986,\n  \"riot/riot\": 12928,\n  \"fxsjy/jieba\": 12874,\n  \"chrisbanes/PhotoView\": 12858,\n  \"kilimchoi/engineering-blogs\": 12846,\n  \"amix/vimrc\": 12844,\n  \"feathericons/feather\": 12836,\n  \"PerfectlySoft/Perfect\": 12826,\n  \"Popmotion/popmotion\": 12819,\n  \"redux-saga/redux-saga\": 12818,\n  \"chenglou/react-motion\": 12810,\n  \"wagerfield/parallax\": 12807,\n  \"fffaraz/awesome-cpp\": 12803,\n  \"etsy/statsd\": 12791,\n  \"ipader/SwiftGuide\": 12774,\n  \"react-bootstrap/react-bootstrap\": 12758,\n  \"caskroom/homebrew-cask\": 12741,\n  \"interagent/http-api-design\": 12736,\n  \"braydie/HowToBeAProgrammer\": 12730,\n  \"paularmstrong/normalizr\": 12719,\n  \"elixir-lang/elixir\": 12719,\n  \"ruanyf/react-demos\": 12703,\n  \"git-tips/tips\": 12703,\n  \"donnemartin/interactive-coding-challenges\": 12672,\n  \"ageitgey/face_recognition\": 12669,\n  \"pingcap/tidb\": 12649,\n  \"geekcompany/ResumeSample\": 12646,\n  \"ipython/ipython\": 12641,\n  \"wekan/wekan\": 12631,\n  \"twbs/bootstrap-sass\": 12625,\n  \"github/hub\": 12623,\n  \"facebook/draft-js\": 12609,\n  \"visionmedia/superagent\": 12586,\n  \"ionic-team/ionicons\": 12570,\n  \"danielmiessler/SecLists\": 12551,\n  \"sentsin/layui\": 12541,\n  \"adobe-fonts/source-code-pro\": 12512,\n  \"infernojs/inferno\": 12472,\n  \"facebookarchive/AsyncDisplayKit\": 12469,\n  \"ipfs/ipfs\": 12469,\n  \"keystonejs/keystone\": 12466,\n  \"SnapKit/SnapKit\": 12454,\n  \"graphcool/chromeless\": 12427,\n  \"docker/compose\": 12406,\n  \"altercation/solarized\": 12374,\n  \"ccgus/fmdb\": 12374,\n  \"rollup/rollup\": 12357,\n  \"vim/vim\": 12310,\n  \"guzzle/guzzle\": 12281,\n  \"FormidableLabs/webpack-dashboard\": 12275,\n  \"google/gson\": 12270,\n  \"donnemartin/data-science-ipython-notebooks\": 12258,\n  \"ruanyf/es6tutorial\": 12223,\n  \"mattermost/mattermost-server\": 12216,\n  \"google/xi-editor\": 12194,\n  \"uikit/uikit\": 12189,\n  \"JacksonTian/fks\": 12174,\n  \"gorhill/uBlock\": 12131,\n  \"framework7io/framework7\": 12127,\n  \"alsotang/node-lessons\": 12124,\n  \"fbsamples/f8app\": 12123,\n  \"spf13/spf13-vim\": 12122,\n  \"hyperapp/hyperapp\": 12105,\n  \"yabwe/medium-editor\": 12100,\n  \"MengTo/Spring\": 12096,\n  \"node-inspector/node-inspector\": 12084,\n  \"alebcay/awesome-shell\": 12080,\n  \"reactjs/react-redux\": 12066,\n  \"facebook/osquery\": 12056,\n  \"realm/realm-cocoa\": 12045,\n  \"isagalaev/highlight.js\": 12017,\n  \"buunguyen/octotree\": 12012,\n  \"rapid7/metasploit-framework\": 11982,\n  \"nsqio/nsq\": 11964,\n  \"airyland/vux\": 11941,\n  \"browserify/browserify\": 11904,\n  \"janl/mustache.js\": 11878,\n  \"hashicorp/consul\": 11868,\n  \"yiisoft/yii2\": 11843,\n  \"Homebrew/brew\": 11839,\n  \"ibireme/YYKit\": 11822,\n  \"cocos2d/cocos2d-x\": 11798,\n  \"CoderMJLee/MJRefresh\": 11794,\n  \"diaspora/diaspora\": 11791,\n  \"Bilibili/flv.js\": 11774,\n  \"gruntjs/grunt\": 11771,\n  \"laravel/framework\": 11771,\n  \"hemanth/functional-programming-jargon\": 11759,\n  \"ReactiveX/rxjs\": 11759,\n  \"hashicorp/terraform\": 11728,\n  \"mysqljs/mysql\": 11726,\n  \"ramda/ramda\": 11688,\n  \"localForage/localForage\": 11680,\n  \"iissnan/hexo-theme-next\": 11662,\n  \"Tencent/tinker\": 11650,\n  \"oxford-cs-deepnlp-2017/lectures\": 11636,\n  \"facebook/prepack\": 11624,\n  \"HelloZeroNet/ZeroNet\": 11612,\n  \"phoenixframework/phoenix\": 11606,\n  \"amazeui/amazeui\": 11596,\n  \"bolshchikov/js-must-watch\": 11590,\n  \"textmate/textmate\": 11579,\n  \"dmlc/xgboost\": 11563,\n  \"Developer-Y/cs-video-courses\": 11548,\n  \"lukasz-madon/awesome-remote-job\": 11543,\n  \"substack/stream-handbook\": 11521,\n  \"servo/servo\": 11512,\n  \"benweet/stackedit\": 11510,\n  \"localstack/localstack\": 11506,\n  \"reactnativecn/react-native-guide\": 11492,\n  \"chriskempson/tomorrow-theme\": 11484,\n  \"lhc70000/iina\": 11479,\n  \"requirejs/requirejs\": 11477,\n  \"powerline/fonts\": 11473,\n  \"android10/Android-CleanArchitecture\": 11468,\n  \"nuxt/nuxt.js\": 11466,\n  \"onevcat/Kingfisher\": 11444,\n  \"ampproject/amphtml\": 11438,\n  \"niklasvh/html2canvas\": 11435,\n  \"openai/gym\": 11432,\n  \"airbnb/react-sketchapp\": 11373,\n  \"lgvalle/Material-Animations\": 11352,\n  \"denysdovhan/wtfjs\": 11347,\n  \"Carthage/Carthage\": 11344,\n  \"jgm/pandoc\": 11340,\n  \"fatedier/frp\": 11319,\n  \"tj/git-extras\": 11306,\n  \"jtoy/awesome-tensorflow\": 11294,\n  \"scottjehl/Respond\": 11282,\n  \"hackiftekhar/IQKeyboardManager\": 11271,\n  \"sass/sass\": 11262,\n  \"swagger-api/swagger-ui\": 11231,\n  \"cayleygraph/cayley\": 11219,\n  \"PanJiaChen/vue-element-admin\": 11217,\n  \"JedWatson/react-select\": 11211,\n  \"apache/predictionio\": 11200,\n  \"keon/algorithms\": 11188,\n  \"stedolan/jq\": 11177,\n  \"adobe-webplatform/Snap.svg\": 11154,\n  \"marcuswestin/store.js\": 11152,\n  \"google/flexbox-layout\": 11150,\n  \"h5bp/Effeckt.css\": 11147,\n  \"google/deepdream\": 11145,\n  \"sqlmapproject/sqlmap\": 11142,\n  \"scwang90/SmartRefreshLayout\": 11129,\n  \"Flipboard/react-canvas\": 11124,\n  \"erikras/react-redux-universal-hot-example\": 11121,\n  \"Shopify/dashing\": 11111,\n  \"eslint/eslint\": 11103,\n  \"google/guetzli\": 11098,\n  \"akveo/ngx-admin\": 11082,\n  \"reactjs/reselect\": 11064,\n  \"linnovate/mean\": 11039,\n  \"binux/pyspider\": 11038,\n  \"abhishekbanthia/Public-APIs\": 11034,\n  \"react-navigation/react-navigation\": 11023,\n  \"jessesquires/JSQMessagesViewController\": 11018,\n  \"foreverjs/forever\": 11012,\n  \"viccalexander/Chameleon\": 11009,\n  \"yaronn/blessed-contrib\": 10993,\n  \"shadowsocks/ShadowsocksX-NG\": 10989,\n  \"vuejs/vue-cli\": 10985,\n  \"philipwalton/solved-by-flexbox\": 10985,\n  \"airbnb/lottie-web\": 10979,\n  \"shieldfy/API-Security-Checklist\": 10957,\n  \"ty4z2008/Qix\": 10954,\n  \"Mantle/Mantle\": 10952,\n  \"jfeinstein10/SlidingMenu\": 10943,\n  \"minio/minio\": 10937,\n  \"sampotts/plyr\": 10934,\n  \"cubiq/iscroll\": 10930,\n  \"alibaba/druid\": 10907,\n  \"JohnCoates/Aerial\": 10904,\n  \"frappe/charts\": 10895,\n  \"nickbutcher/plaid\": 10885,\n  \"nagadomi/waifu2x\": 10875,\n  \"jmcunningham/AngularJS-Learning\": 10870,\n  \"PHPMailer/PHPMailer\": 10869,\n  \"selectize/selectize.js\": 10868,\n  \"strongloop/loopback\": 10858,\n  \"SVProgressHUD/SVProgressHUD\": 10847,\n  \"facebook/relay\": 10819,\n  \"tj/commander.js\": 10815,\n  \"WordPress/WordPress\": 10797,\n  \"source-foundry/Hack\": 10789,\n  \"sindresorhus/quick-look-plugins\": 10769,\n  \"loverajoel/jstips\": 10740,\n  \"uxsolutions/bootstrap-datepicker\": 10730,\n  \"pyenv/pyenv\": 10728,\n  \"hzlzh/Best-App\": 10700,\n  \"leereilly/games\": 10683,\n  \"Kotlin/anko\": 10656,\n  \"JuliaLang/julia\": 10645,\n  \"vim-airline/vim-airline\": 10645,\n  \"magicalpanda/MagicalRecord\": 10642,\n  \"Shopify/draggable\": 10641,\n  \"koalaman/shellcheck\": 10630,\n  \"gionkunz/chartist-js\": 10619,\n  \"MrRio/jsPDF\": 10613,\n  \"begriffs/postgrest\": 10612,\n  \"luanfujun/deep-photo-styletransfer\": 10574,\n  \"react-native-training/react-native-elements\": 10566,\n  \"marcuswestin/WebViewJavascriptBridge\": 10547,\n  \"nswbmw/N-blog\": 10546,\n  \"crystal-lang/crystal\": 10524,\n  \"junegunn/vim-plug\": 10517,\n  \"ocornut/imgui\": 10504,\n  \"aurelia/framework\": 10482,\n  \"google/fonts\": 10481,\n  \"ElemeFE/mint-ui\": 10473,\n  \"Tencent/mars\": 10461,\n  \"mitmproxy/mitmproxy\": 10452,\n  \"FFmpeg/FFmpeg\": 10438,\n  \"rbenv/rbenv\": 10433,\n  \"facebook/folly\": 10431,\n  \"nicklockwood/iCarousel\": 10402,\n  \"transloadit/uppy\": 10398,\n  \"VerbalExpressions/JSVerbalExpressions\": 10396,\n  \"equinusocio/material-theme\": 10395,\n  \"chaozh/awesome-blockchain-cn\": 10391,\n  \"grab/front-end-guide\": 10389,\n  \"jquery/jquery-ui\": 10388,\n  \"xgrommx/awesome-redux\": 10386,\n  \"pouchdb/pouchdb\": 10386,\n  \"jwagner/smartcrop.js\": 10385,\n  \"CocoaPods/CocoaPods\": 10384,\n  \"resin-io/etcher\": 10374,\n  \"phanan/htaccess\": 10372,\n  \"DrkSephy/es6-cheatsheet\": 10370,\n  \"bang590/JSPatch\": 10346,\n  \"playframework/playframework\": 10340,\n  \"capistrano/capistrano\": 10323,\n  \"facebook/rocksdb\": 10322,\n  \"froala/design-blocks\": 10249,\n  \"RestKit/RestKit\": 10246,\n  \"AllThingsSmitty/css-protips\": 10242,\n  \"encode/django-rest-framework\": 10236,\n  \"jeromeetienne/AR.js\": 10230,\n  \"androidannotations/androidannotations\": 10206,\n  \"loopj/android-async-http\": 10201,\n  \"pypa/pipenv\": 10196,\n  \"browserstate/history.js\": 10185,\n  \"SeleniumHQ/selenium\": 10177,\n  \"ptmt/react-native-macos\": 10162,\n  \"thomaspark/bootswatch\": 10158,\n  \"CocoaLumberjack/CocoaLumberjack\": 10154,\n  \"dimsemenov/Magnific-Popup\": 10139,\n  \"yudai/gotty\": 10138,\n  \"jwilm/alacritty\": 10137,\n  \"cjwirth/awesome-ios-ui\": 10134,\n  \"davezuko/react-redux-starter-kit\": 10132,\n  \"alcatraz/Alcatraz\": 10130,\n  \"chriso/validator.js\": 10129,\n  \"HubSpot/youmightnotneedjquery\": 10125,\n  \"maxwellito/vivus\": 10123,\n  \"parkjs814/AlgorithmVisualizer\": 10120,\n  \"learn-anything/learn-anything\": 10119,\n  \"dzenbot/DZNEmptyDataSet\": 10115,\n  \"LightTable/LightTable\": 10110,\n  \"jhipster/generator-jhipster\": 10110,\n  \"graphql/graphql-js\": 10101,\n  \"TeamStuQ/skill-map\": 10099,\n  \"emilwallner/Screenshot-to-code-in-Keras\": 10094,\n  \"norvig/pytudes\": 10078,\n  \"php-fig/fig-standards\": 10052,\n  \"octocat/Spoon-Knife\": 10051,\n  \"tpope/vim-pathogen\": 10049,\n  \"scala/scala\": 10038,\n  \"bvaughn/react-virtualized\": 10037,\n  \"go-martini/martini\": 10033,\n  \"nikitavoloboev/my-mac-os\": 10033,\n  \"PHPOffice/PHPExcel\": 10032,\n  \"bmorelli25/Become-A-Full-Stack-Web-Developer\": 10031,\n  \"labstack/echo\": 10031,\n  \"jquery/jquery-mobile\": 10023,\n  \"petehunt/webpack-howto\": 10022,\n  \"winstonjs/winston\": 10006,\n  \"veggiemonk/awesome-docker\": 10006,\n  \"xdissent/ievms\": 10006,\n  \"petehunt/react-howto\": 10001,\n  \"keen/dashboards\": 10001,\n  \"geeeeeeeeek/electronic-wechat\": 9988,\n  \"littlecodersh/ItChat\": 9975,\n  \"dawnlabs/carbon\": 9958,\n  \"PowerShell/PowerShell\": 9955,\n  \"jamiebuilds/the-super-tiny-compiler\": 9942,\n  \"vurtun/nuklear\": 9937,\n  \"acdlite/recompose\": 9935,\n  \"robbiehanson/CocoaAsyncSocket\": 9927,\n  \"sinatra/sinatra\": 9924,\n  \"kangax/fabric.js\": 9921,\n  \"you-dont-need/You-Dont-Need-JavaScript\": 9918,\n  \"daimajia/AndroidSwipeLayout\": 9889,\n  \"kataras/iris\": 9880,\n  \"Automattic/wp-calypso\": 9876,\n  \"allenwong/30DaysofSwift\": 9876,\n  \"so-fancy/diff-so-fancy\": 9852,\n  \"tmux/tmux\": 9848,\n  \"jaredreich/pell\": 9833,\n  \"vuetifyjs/vuetify\": 9832,\n  \"SheetJS/js-xlsx\": 9831,\n  \"fabric/fabric\": 9828,\n  \"BrowserSync/browser-sync\": 9826,\n  \"goldfire/howler.js\": 9803,\n  \"greenrobot/greenDAO\": 9775,\n  \"Seldaek/monolog\": 9771,\n  \"flatpickr/flatpickr\": 9769,\n  \"WickyNilliams/headroom.js\": 9768,\n  \"date-fns/date-fns\": 9736,\n  \"openfaas/faas\": 9713,\n  \"revel/revel\": 9708,\n  \"nicolargo/glances\": 9701,\n  \"JakeWharton/ViewPagerIndicator\": 9701,\n  \"google/ExoPlayer\": 9689,\n  \"addyosmani/backbone-fundamentals\": 9675,\n  \"handsontable/handsontable\": 9672,\n  \"gdi2290/angular-starter\": 9664,\n  \"go-kit/kit\": 9651,\n  \"scrooloose/nerdtree\": 9651,\n  \"cmusatyalab/openface\": 9650,\n  \"CosmicMind/Material\": 9648,\n  \"DmitryBaranovskiy/raphael\": 9644,\n  \"tensorflow/magenta\": 9635,\n  \"sebastianbergmann/phpunit\": 9630,\n  \"jsdom/jsdom\": 9629,\n  \"janpaepke/ScrollMagic\": 9625,\n  \"facebook/yoga\": 9620,\n  \"jessepollak/card\": 9618,\n  \"karma-runner/karma\": 9613,\n  \"OAI/OpenAPI-Specification\": 9612,\n  \"zeit/pkg\": 9598,\n  \"scottjehl/picturefill\": 9590,\n  \"imathis/octopress\": 9556,\n  \"dexteryy/spellbook-of-modern-webdev\": 9552,\n  \"tj/co\": 9539,\n  \"redox-os/redox\": 9533,\n  \"salomonelli/best-resume-ever\": 9531,\n  \"gaearon/redux-devtools\": 9529,\n  \"gabrielecirulli/2048\": 9525,\n  \"phacility/phabricator\": 9517,\n  \"facebook/stetho\": 9515,\n  \"shuzheng/zheng\": 9510,\n  \"css-modules/css-modules\": 9510,\n  \"fish-shell/fish-shell\": 9510,\n  \"kesenhoo/android-training-course-in-chinese\": 9501,\n  \"DrKLO/Telegram\": 9494,\n  \"hdodenhof/CircleImageView\": 9491,\n  \"vuejs/vue-router\": 9474,\n  \"metabase/metabase\": 9427,\n  \"Microsoft/dotnet\": 9425,\n  \"realm/realm-java\": 9419,\n  \"NodeRedis/node_redis\": 9413,\n  \"erikras/redux-form\": 9409,\n  \"svg/svgo\": 9395,\n  \"ochococo/Design-Patterns-In-Swift\": 9393,\n  \"eczarny/spectacle\": 9371,\n  \"jobbole/awesome-python-cn\": 9360,\n  \"hapijs/hapi\": 9348,\n  \"tpope/vim-fugitive\": 9343,\n  \"nodemailer/nodemailer\": 9339,\n  \"jakevdp/PythonDataScienceHandbook\": 9325,\n  \"odoo/odoo\": 9315,\n  \"kailashahirwar/cheatsheets-ai\": 9300,\n  \"peachananr/onepage-scroll\": 9295,\n  \"gztchan/awesome-design\": 9294,\n  \"tabler/tabler\": 9292,\n  \"Konloch/bytecode-viewer\": 9287,\n  \"joewalnes/websocketd\": 9278,\n  \"google/flatbuffers\": 9276,\n  \"daimajia/AndroidViewAnimations\": 9262,\n  \"fivethirtyeight/data\": 9259,\n  \"hehonghui/android-tech-frontier\": 9259,\n  \"googlesamples/android-UniversalMusicPlayer\": 9258,\n  \"signalapp/Signal-Android\": 9255,\n  \"pockethub/PocketHub\": 9238,\n  \"Tencent/wepy\": 9237,\n  \"imakewebthings/waypoints\": 9226,\n  \"roots/sage\": 9225,\n  \"react-community/create-react-native-app\": 9213,\n  \"dotnet/coreclr\": 9205,\n  \"mxcl/PromiseKit\": 9204,\n  \"nlohmann/json\": 9203,\n  \"kevinzhow/PNChart\": 9193,\n  \"elastic/kibana\": 9173,\n  \"celery/celery\": 9164,\n  \"aria2/aria2\": 9160,\n  \"ethereum/wiki\": 9159,\n  \"dotnet/roslyn\": 9159,\n  \"gollum/gollum\": 9141,\n  \"realm/SwiftLint\": 9130,\n  \"spree/spree\": 9129,\n  \"philipwalton/flexbugs\": 9118,\n  \"paperjs/paper.js\": 9113,\n  \"mikepenz/MaterialDrawer\": 9107,\n  \"js-cookie/js-cookie\": 9099,\n  \"luongvo209/Awesome-Linux-Software\": 9095,\n  \"StevenBlack/hosts\": 9094,\n  \"FelisCatus/SwitchyOmega\": 9091,\n  \"obsproject/obs-studio\": 9075,\n  \"nathanmarz/storm\": 9075,\n  \"NetEase/pomelo\": 9053,\n  \"winterbe/java8-tutorial\": 9048,\n  \"matomo-org/matomo\": 9041,\n  \"bitcoinbook/bitcoinbook\": 9037,\n  \"matryer/bitbar\": 9035,\n  \"Matt-Esch/virtual-dom\": 9034,\n  \"stylus/stylus\": 9031,\n  \"google/python-fire\": 9024,\n  \"apenwarr/sshuttle\": 9023,\n  \"channelcat/sanic\": 9018,\n  \"vim-syntastic/syntastic\": 9011,\n  \"Flipboard/FLEX\": 9009,\n  \"spotify/luigi\": 9006,\n  \"karpathy/convnetjs\": 8990,\n  \"lerna/lerna\": 8989,\n  \"fgnass/spin.js\": 8986,\n  \"systemjs/systemjs\": 8985,\n  \"phanan/koel\": 8965,\n  \"kelseyhightower/kubernetes-the-hard-way\": 8962,\n  \"palantir/blueprint\": 8956,\n  \"ncw/rclone\": 8956,\n  \"hashicorp/vault\": 8951,\n  \"liaohuqiu/android-Ultra-Pull-To-Refresh\": 8950,\n  \"Wox-launcher/Wox\": 8948,\n  \"libuv/libuv\": 8947,\n  \"explosion/spaCy\": 8938,\n  \"vasanthk/react-bits\": 8938,\n  \"tonybeltramelli/pix2code\": 8937,\n  \"thoughtbot/paperclip\": 8936,\n  \"tj/n\": 8931,\n  \"binhnguyennus/awesome-scalability\": 8922,\n  \"metafizzy/isotope\": 8921,\n  \"dvajs/dva\": 8919,\n  \"acgotaku/BaiduExporter\": 8917,\n  \"yeoman/yeoman\": 8915,\n  \"bbatsov/rubocop\": 8903,\n  \"sdelements/lets-chat\": 8896,\n  \"rwaldron/johnny-five\": 8893,\n  \"javve/list.js\": 8888,\n  \"apache/incubator-weex\": 8884,\n  \"slimphp/Slim\": 8869,\n  \"getredash/redash\": 8869,\n  \"aFarkas/html5shiv\": 8867,\n  \"uNetworking/uWebSockets\": 8866,\n  \"orhanobut/logger\": 8864,\n  \"google/grumpy\": 8860,\n  \"philc/vimium\": 8843,\n  \"phalcon/cphalcon\": 8841,\n  \"knockout/knockout\": 8837,\n  \"elastic/logstash\": 8836,\n  \"getgrav/grav\": 8834,\n  \"feathersjs/feathers\": 8832,\n  \"powerline/powerline\": 8825,\n  \"sorin-ionescu/prezto\": 8825,\n  \"daylerees/colour-schemes\": 8815,\n  \"Ramotion/animated-tab-bar\": 8790,\n  \"audreyr/favicon-cheat-sheet\": 8781,\n  \"forkingdog/UITableView-FDTemplateLayoutCell\": 8775,\n  \"francistao/LearningNotes\": 8771,\n  \"google/WebFundamentals\": 8766,\n  \"fogleman/primitive\": 8765,\n  \"EnterpriseQualityCoding/FizzBuzzEnterpriseEdition\": 8762,\n  \"dcloudio/mui\": 8762,\n  \"v8/v8\": 8760,\n  \"saltstack/salt\": 8756,\n  \"ant-design/ant-design-pro\": 8743,\n  \"briannesbitt/Carbon\": 8741,\n  \"Rochester-NRT/RocAlphaGo\": 8731,\n  \"datasciencemasters/go\": 8731,\n  \"buger/goreplay\": 8713,\n  \"ccampbell/mousetrap\": 8710,\n  \"gaearon/react-hot-loader\": 8702,\n  \"deeplearning4j/deeplearning4j\": 8701,\n  \"bazelbuild/bazel\": 8699,\n  \"WebAssembly/design\": 8694,\n  \"ksoichiro/Android-ObservableScrollView\": 8689,\n  \"Netflix/falcor\": 8688,\n  \"akveo/blur-admin\": 8682,\n  \"byoungd/English-level-up-tips-for-Chinese\": 8681,\n  \"zyedidia/micro\": 8674,\n  \"recharts/recharts\": 8673,\n  \"navasmdc/MaterialDesignLibrary\": 8668,\n  \"docker/kitematic\": 8663,\n  \"jquery-validation/jquery-validation\": 8650,\n  \"chalk/chalk\": 8645,\n  \"fullstackio/FlappySwift\": 8637,\n  \"airbnb/lottie-react-native\": 8634,\n  \"chrisbanes/Android-PullToRefresh\": 8633,\n  \"Microsoft/monaco-editor\": 8628,\n  \"ApolloAuto/apollo\": 8624,\n  \"OpenEmu/OpenEmu\": 8623,\n  \"basecamp/trix\": 8619,\n  \"markets/awesome-ruby\": 8605,\n  \"Hacker0x01/hacker101\": 8597,\n  \"NodeBB/NodeBB\": 8596,\n  \"zenorocha/alfred-workflows\": 8590,\n  \"nfarina/homebridge\": 8583,\n  \"nodejitsu/node-http-proxy\": 8581,\n  \"thoughtbot/bourbon\": 8577,\n  \"jinzhu/gorm\": 8573,\n  \"golang/dep\": 8567,\n  \"wulkano/kap\": 8560,\n  \"BurntSushi/ripgrep\": 8558,\n  \"apple/swift-evolution\": 8558,\n  \"dropbox/zxcvbn\": 8556,\n  \"Moya/Moya\": 8546,\n  \"ConnorAtherton/loaders.css\": 8531,\n  \"mperham/sidekiq\": 8528,\n  \"MithrilJS/mithril.js\": 8523,\n  \"raywenderlich/swift-style-guide\": 8522,\n  \"NUKnightLab/TimelineJS\": 8517,\n  \"necolas/react-native-web\": 8516,\n  \"gfwlist/gfwlist\": 8514,\n  \"mxgmn/WaveFunctionCollapse\": 8499,\n  \"ChristosChristofidis/awesome-deep-learning\": 8490,\n  \"chentsulin/electron-react-boilerplate\": 8488,\n  \"gaearon/redux-thunk\": 8485,\n  \"mishoo/UglifyJS2\": 8481,\n  \"shichuan/javascript-patterns\": 8477,\n  \"carhartl/jquery-cookie\": 8474,\n  \"onevcat/VVDocumenter-Xcode\": 8468,\n  \"alibaba/p3c\": 8458,\n  \"facebook/Shimmer\": 8456,\n  \"swoole/swoole-src\": 8452,\n  \"alexjc/neural-doodle\": 8442,\n  \"FezVrasta/popper.js\": 8438,\n  \"sqlitebrowser/sqlitebrowser\": 8426,\n  \"chinese-poetry/chinese-poetry\": 8425,\n  \"guillaumepotier/Parsley.js\": 8424,\n  \"ruby-grape/grape\": 8423,\n  \"jordansissel/fpm\": 8422,\n  \"kubernetes/minikube\": 8421,\n  \"akka/akka\": 8420,\n  \"GeekyAnts/NativeBase\": 8416,\n  \"StackExchange/Dapper\": 8389,\n  \"purifycss/purifycss\": 8386,\n  \"coryhouse/react-slingshot\": 8381,\n  \"slackhq/SlackTextViewController\": 8372,\n  \"irungentoo/toxcore\": 8366,\n  \"boltdb/bolt\": 8357,\n  \"Idnan/bash-guide\": 8345,\n  \"Automattic/_s\": 8313,\n  \"mhinz/vim-galore\": 8310,\n  \"teamcapybara/capybara\": 8310,\n  \"fatih/vim-go\": 8306,\n  \"rasbt/python-machine-learning-book\": 8304,\n  \"facebook/infer\": 8298,\n  \"sindresorhus/pageres\": 8296,\n  \"cyclejs/cyclejs\": 8278,\n  \"mbadolato/iTerm2-Color-Schemes\": 8274,\n  \"qrohlf/trianglify\": 8257,\n  \"connors/photon\": 8255,\n  \"jikexueyuanwiki/tensorflow-zh\": 8251,\n  \"afaqurk/linux-dash\": 8250,\n  \"websockets/ws\": 8249,\n  \"nosir/cleave.js\": 8238,\n  \"arasatasaygin/is.js\": 8236,\n  \"aFarkas/lazysizes\": 8228,\n  \"1c7/chinese-independent-developer\": 8199\n}\n"
  },
  {
    "path": "index.js",
    "content": "require('dotenv').config()\nconst koa = require('koa')\nconst route = require('koa-route')\nconst serve = require('koa-static')\nconst fs = require('mz/fs')\nconst {createTextSvg} = require('./svg')\nconst {total, rateLimit} = require('./render')\nconst queue = require('./queue')\nconst page = require('./page')\nconst ttl = require('./ttl')\n\nconst app = new koa()\nqueue.worker()\napp.use(serve('public'));\n\napp.use(route.get('/:owner/:name.svg', async (ctx, owner, name) => {\n  ctx.type = 'image/svg+xml; charset=utf-8'\n\n  const repo = `${owner}/${name}`\n  const path = `svg/${owner}/${name}.svg`.toLowerCase()\n\n  let stats\n  try {\n    const maxAge = ttl(repo)\n    stats = await fs.stat(path)\n\n    ctx.set('Last-Modified', stats.mtime.toUTCString())\n    ctx.set('Cache-Control', 'max-age=' + maxAge)\n    ctx.body = fs.createReadStream(path)\n\n    const now = new Date().getTime()\n    const mtime = stats.mtime.getTime()\n\n    if (now - mtime > maxAge * 1000) {\n      queue.push(path, owner, name)\n    }\n\n  } catch (err) {\n    if (err.code === 'ENOENT') {\n      queue.push(path, owner, name)\n\n      const p = total.get(path)\n      if (p) {\n        ctx.body = createTextSvg(`⚡️ loading stars ${p}%`)\n      } else {\n        ctx.body = createTextSvg(`👋️ waiting in queue ${queue.indexOf(path) + 1}`)\n      }\n    } else {\n      ctx.body = createTextSvg(`⚠️ error`)\n    }\n  }\n}))\n\napp.use(route.get('/', async (ctx) => {\n  if (ctx.query.repo) {\n    ctx.redirect('/' + ctx.query.repo)\n  } else {\n    ctx.type = 'text/html'\n    ctx.body = page.index()\n  }\n}))\n\napp.use(route.get('/:owner/:name', async (ctx, owner, name) => {\n  ctx.type = 'text/html'\n  ctx.body = page.repo({owner, name})\n}))\n\napp.use(route.get('/status', async (ctx) => {\n  ctx.type = 'application/json'\n  ctx.body = {\n    queueSize: queue.size(),\n    processing: [...total.keys()],\n    rateLimit: rateLimit.remaining\n  }\n}))\n\nconst port = process.env.PORT || 3000\napp.listen(port)\nconsole.log('App started on port ' + port)\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"@medv/spark\",\n  \"version\": \"1.0.0\",\n  \"description\": \"GitHub Stars Sparklines\",\n  \"main\": \"index.js\",\n  \"author\": \"Anton Medvedev <anton@medv.io>\",\n  \"repository\": \"antonmedv/spark\",\n  \"license\": \"MIT\",\n  \"dependencies\": {\n    \"delay\": \"^2.0.0\",\n    \"dotenv\": \"^5.0.1\",\n    \"koa\": \"^2.5.0\",\n    \"koa-route\": \"^3.2.0\",\n    \"koa-static\": \"^4.0.2\",\n    \"mz\": \"^2.7.0\",\n    \"r2\": \"^2.0.1\"\n  }\n}\n"
  },
  {
    "path": "page.js",
    "content": "const style = require('fs').readFileSync('style.css')\nconst rand = () => Math.round(100 * Math.random())\n\nconst layout = (content) => `\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"UTF-8\">\n  <title>⚡️ GitHub Stars Sparklines</title>\n  <meta name=\"description\" content=\"⚡️ Spark is GitHub stars graph generator, it plots tiny little graph called sparkline, which reflects the growth rate of stars on GitHub thought history.\">\n  <meta name=\"viewport\" content=\"width=device-width, user-scalable=yes\">\n  <link rel=\"apple-touch-icon\" sizes=\"180x180\" href=\"/apple-touch-icon.png\">\n  <link rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/favicon.png\">\n  <style>\n    ${style}\n  </style>\n  <style>.github-corner:hover .octo-arm{animation:octocat-wave 560ms ease-in-out}@keyframes octocat-wave{0%,100%{transform:rotate(0)}20%,60%{transform:rotate(-25deg)}40%,80%{transform:rotate(10deg)}}@media (max-width:500px){.github-corner:hover .octo-arm{animation:none}.github-corner .octo-arm{animation:octocat-wave 560ms ease-in-out}}</style>\n  <script async src=\"https://www.googletagmanager.com/gtag/js?id=UA-72806543-2\"></script>\n  <script>\n    window.dataLayer = window.dataLayer || [];\n    function gtag(){dataLayer.push(arguments);}\n    gtag('js', new Date());\n  \n    gtag('config', 'UA-72806543-2');\n  </script>\n</head>\n<body>\n  <a href=\"https://github.com/antonmedv/spark\" class=\"github-corner\" aria-label=\"View source on Github\">\n    <svg width=\"80\" height=\"80\" viewBox=\"0 0 250 250\" style=\"fill:#70B7FD; color:#fff; position: absolute; top: 0; border: 0; right: 0;\" aria-hidden=\"true\"><path d=\"M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z\"></path><path d=\"M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2\" fill=\"currentColor\" style=\"transform-origin: 130px 106px;\" class=\"octo-arm\"></path><path d=\"M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z\" fill=\"currentColor\" class=\"octo-body\"></path></svg>\n  </a>\n  <div class=\"content\">\n    ${content}\n  </div>\n  <div class=\"r\">\n    <div class=\"r1\" style=\"${`top: ${rand()}vh; left: ${rand()}vw`}\"></div>\n    <div class=\"r2\" style=\"${`top: ${rand()}vh; left: ${rand()}vw`}\"></div>\n    <div class=\"r3\" style=\"${`top: ${rand()}vh; left: ${rand()}vw`}\"></div>\n    <div class=\"r4\" style=\"${`top: ${rand()}vh; left: ${rand()}vw`}\"></div>\n  </div>\n</body>\n</html>\n`\n\nconst box = (owner, name) => {\n  let title = owner + '/' + name\n  if (title.length > 20) {\n    title = name\n  }\n  return `\n    <div class=\"box\">\n      <div class=\"name\">${title}</div>\n      <img class=\"spark\" src=\"/${owner + '/' + name}.svg\"/>\n    </div>\n  `\n}\n\nconst a = (path) => {\n  const [owner, name] = path.split('/')\n  return `\n    <a href=\"/${owner + '/' + name}\">\n      ${box(owner, name)}\n    </a>  \n  `\n}\n\nconst h1 = () => `<h1><a href=\"/\">⚡️ Spark </a><span>GitHub Stars Sparklines</span></h1>`\n\nexports.index = () => layout(`\n${h1()}\n<div class=\"grid\">\n  ${a('facebook/react')}\n  ${a('angular/angular')}\n  ${a('vuejs/vue')}\n  ${a('freeCodeCamp/freeCodeCamp')}\n  ${a('jquery/jquery')}\n  ${a('twbs/bootstrap')}\n  ${a('rails/rails')}\n  ${a('FortAwesome/Font-Awesome')}\n  ${a('jashkenas/backbone')}\n  ${a('php/php-src')}\n  ${a('nodejs/node')}\n  ${a('torvalds/linux')}\n  ${a('moby/moby')}\n  ${a('laravel/laravel')}\n  ${a('reactjs/redux')}\n  ${a('d3/d3')}\n  ${a('axios/axios')}\n  ${a('robbyrussell/oh-my-zsh')}\n  ${a('facebook/react-native')}\n  ${a('meteor/meteor')}\n</div>\n<div class=\"add-repo\">\n  <form method=\"get\">\n    <label for=\"repo\">Create sparkline for any repo:</label>\n    <input id=\"repo\" name=\"repo\" type=\"text\" placeholder=\"owner/repo\">\n    <button type=\"submit\">Let's Go 🔮</button>\n  </form>\n</div>\n`)\n\n\nexports.repo = ({owner, name}) => layout(`\n${h1()}\n<div class=\"one\">\n  <a class=\"one-link\" href=\"https://github.com/${owner + '/' + name}\">   \n    ${box(owner, name)}\n  </a>\n  <p>\n    The Sparkline shows GitHub stars velocity of <em>${owner + '/' + name}</em> repo for the entire lifetime of the repository.\n    <br>\n    <br>\n    Add the Sparkline to repo's readme, copy markdown code below.\n  </p>\n  <code>[![Sparkline](https://stars.medv.io/${owner + '/' + name}.svg)](https://stars.medv.io/${owner + '/' + name})</code>\n</div>\n`)\n"
  },
  {
    "path": "queue.js",
    "content": "const {render} = require('./render')\nconst delay = require('delay')\n\nconst queue = []\nconst set = new Set()\n\nfunction size() {\n  return queue.length\n}\n\nasync function worker() {\n  do {\n    try {\n      const work = queue.shift()\n      if (work) {\n        const [path, owner, name] = work\n\n        await render(path, owner, name)\n\n        set.delete(path)\n      } else {\n        await delay(100)\n      }\n    } catch (err) {\n      console.error(err)\n    }\n  } while (true)\n}\n\nfunction push(path, owner, name) {\n  if (!set.has(path)) {\n    queue.push([path, owner, name])\n    set.add(path)\n  }\n}\n\nfunction indexOf(path) {\n  return queue.findIndex(([p]) => path === p)\n}\n\nmodule.exports = {worker, push, size, indexOf}\n"
  },
  {
    "path": "render.js",
    "content": "const {dirname} = require('path')\nconst fs = require('mz/fs')\nconst {fetch} = require('./api')\nconst {createSvg} = require('./svg')\n\nconst total = new Map()\n\nconst query = `\n  query($owner: String!, $name: String!, $endCursor: String) {\n    repository(owner: $owner, name: $name) {\n      stargazers(first: 100, after: $endCursor) {\n        totalCount\n        edges {\n          starredAt\n        }\n        pageInfo {\n          hasNextPage\n          endCursor\n        }\n      }\n    }\n    rateLimit {\n      remaining\n    }  \n  }\n`\n\nlet rateLimit = {\n  remaining: 5000\n}\n\nasync function render(path, owner, name) {\n  total.set(path, 0)\n\n  const data = await fetch(query, {owner, name})\n\n  if (data.repository) {\n    let {\n      stargazers: {\n        totalCount,\n        edges: dates,\n        pageInfo: {hasNextPage, endCursor}\n      }\n    } = data.repository\n\n    while (hasNextPage) {\n      total.set(path, Math.round(100 * dates.length / totalCount))\n      console.log(`${owner}/${name}: ${total.get(path)}%`)\n\n      const data = await fetch(query, {owner, name, endCursor})\n\n      hasNextPage = data.repository.stargazers.pageInfo.hasNextPage\n      endCursor = data.repository.stargazers.pageInfo.endCursor\n      rateLimit.remaining = data.rateLimit.remaining\n\n      dates = dates.concat(data.repository.stargazers.edges)\n    }\n\n    dates = dates.map(({starredAt}) => +(new Date(starredAt)))\n\n    const svg = createSvg(dates)\n\n    const dir = dirname(path)\n    await fs.exists(dir) || await fs.mkdir(dir)\n\n    fs.writeFile(path, svg)\n  }\n\n  total.delete(path)\n}\n\nmodule.exports = {render, total, rateLimit}\n"
  },
  {
    "path": "style.css",
    "content": "html {\n    -webkit-box-sizing: border-box;\n    -moz-box-sizing: border-box;\n    box-sizing: border-box;\n}\n\n*, *:before, *:after {\n    -webkit-box-sizing: inherit;\n    -moz-box-sizing: inherit;\n    box-sizing: inherit;\n    padding: 0;\n    margin: 0;\n}\n\nbody {\n    font-family: Helvetica, serif;\n    font-size: 14px;\n    line-height: 1.5;\n    color: rgba(0, 0, 0, .65);\n    background-color: #f9fbff;\n}\n\n.content {\n    display: flex;\n    flex-direction: column;\n    margin: 40px auto;\n    padding-left: 20px;\n    padding-right: 20px;\n    max-width: 1400px;\n}\n\nh1 {\n    margin-bottom: 50px;\n    font-size: 32px;\n}\n\nh1 > span {\n    font-size: 16px;\n    font-weight: normal;\n}\n\n@media only screen and (max-device-width: 350px) {\n    h1 > span {\n        display: block;\n    }\n}\n\n.grid {\n    display: grid;\n    grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));\n    grid-gap: 15px 15px;\n}\n\na {\n    color: inherit;\n    text-decoration: none;\n}\n\n.box {\n    display: flex;\n    flex-direction: column;\n    padding: 10px 15px;\n    white-space: nowrap;\n    font-size: 16px;\n    font-weight: 500;\n    color: inherit;\n    background: #fff;\n    border-radius: 3px;\n    -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, .12), 0 1px 2px rgba(0, 0, 0, .24);\n    box-shadow: 0 1px 3px rgba(0, 0, 0, .12), 0 1px 2px rgba(0, 0, 0, .24);\n    -webkit-transition: all .3s cubic-bezier(.25, .8, .25, 1);\n    -o-transition: all .3s cubic-bezier(.25, .8, .25, 1);\n    transition: all .3s cubic-bezier(.25, .8, .25, 1);\n}\n\n.box:hover {\n    text-decoration: none;\n    color: inherit;\n    -webkit-transform: scale(1.01);\n    -ms-transform: scale(1.01);\n    transform: scale(1.01);\n    -webkit-box-shadow: 0 10px 20px rgba(0, 0, 0, .19), 0 6px 6px rgba(0, 0, 0, .23);\n    box-shadow: 0 10px 20px rgba(0, 0, 0, .19), 0 6px 6px rgba(0, 0, 0, .23);\n}\n\n.name {\n    font-weight: 500;\n    font-size: 18px;\n    margin-bottom: 5px;\n    padding-left: 20px;\n    background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='currentColor' preserveAspectRatio='xMidYMid meet' height='1em' width='1em' viewBox='0 0 40 40' style='vertical-align: middle;'%3E%3Cg%3E%3Cpath d='m17.5 10h-2.5v2.5h2.5v-2.5z m0-5h-2.5v2.5h2.5v-2.5z m15-5h-25s-2.5 1.3-2.5 2.5v30s1.3 2.5 2.5 2.5h5v5l3.8-3.7 3.7 3.7v-5h12.5s2.5-1.2 2.5-2.5v-30s-1.2-2.5-2.5-2.5z m0 31.3c0 0.6-0.6 1.2-1.2 1.2h-11.3v-2.5h-7.5v2.5h-3.7s-1.3-0.7-1.3-1.2v-3.8h25v3.8z m0-6.3h-20v-22.5h20l0 22.5z m-15-5h-2.5v2.5h2.5v-2.5z m0-5h-2.5v2.5h2.5v-2.5z'%3E%3C/path%3E%3C/g%3E%3C/svg%3E\");\n    background-position: 0 8px;\n    background-repeat: no-repeat;\n    overflow-x: hidden;\n    -o-text-overflow: ellipsis;\n    text-overflow: ellipsis;\n}\n\n.spark {\n    width: 200px;\n    align-self: center;\n}\n\n.one {\n    display: flex;\n    flex-direction: column;\n}\n\n.one-link {\n    display: inline-block;\n    align-self: center;\n    margin-top: 30px;\n    margin-bottom: 60px;\n    transform: scale(1.5);\n}\n\n.one > p {\n    display: block;\n    font-size: 16px;\n    margin-top: 10px;\n    max-width: 600px;\n    align-self: center;    \n}\n\ncode {\n    margin-top: 40px;\n    padding: 10px 15px;\n    max-width: 600px;\n    overflow-x: scroll;\n    align-self: center;\n    white-space: nowrap;\n    font-family: monospace;\n    background-color: #eeeeee;\n}\n\n@media only screen and (max-device-width: 812px) {\n    code {\n        width: 100%;\n        max-width: none;\n    }\n}\n\n.add-repo {\n    margin-top: 90px;\n    align-self: center;\n}\n\n.add-repo label {\n    display: block;\n    padding: 5px;\n    font-size: 16px;\n    text-align: center;\n}\n\n.add-repo input[type=\"text\"] {\n    border: none;\n    border-radius: 4px;\n    outline: none;\n    padding: 10px 17px;\n    font-family: monospace;\n    font-size: 16px;\n    width: 200px;\n    background-color: #fff;\n    box-shadow: 2px 5px 10px rgb(228, 228, 228);\n}\n\n.add-repo button {\n    margin: 10px;\n    padding: 12px 12px;\n    cursor: pointer;\n    user-select: none;\n    text-align: center;\n    white-space: nowrap;\n    border: 0 none;\n    border-radius: 4px;\n    font-size: 13px;\n    font-weight: 500;\n    line-height: 1.3;\n    -webkit-appearance: none;\n    -moz-appearance: none;\n    box-shadow: 2px 5px 10px rgb(228, 228, 228);\n    color: #7e8091;\n    background-color: #fff;\n    transition: background-color 150ms linear;\n}\n\n.add-repo button:hover {\n    background-color: #f2f2f2;\n}\n\n.r {\n    top: 0;\n    left: 0;\n    right: 0;\n    bottom: 0;\n    position: absolute;\n    z-index: -1;\n    overflow: hidden;\n}\n\n.r1, .r2, .r3, .r4{\n    position: relative;\n    width: 50px;\n    height: 50px;\n    border-radius: 100%;\n    border: solid 12px #fc607f;\n}\n\n.r2 {\n    border-color: #4580fe;\n}\n\n.r3 {\n    border-color: #fcb84d;\n}\n\n.r4 {\n    border-color: #78faca;\n    border-radius: 0;\n}\n"
  },
  {
    "path": "svg.js",
    "content": "const height = 30\nconst x0 = 5\nconst y0 = 40\nconst steps = 40\nconst dx = 5\nconst basis = 1.5\nconst gradient = ['#3023AE', '#C86DD7']\n\nconst round = num => Math.round(num * 100) / 100\nconst vec = (x, y) => ({\n  x, y,\n  toString() {\n    return `${round(this.x)} ${round(this.y)}`\n  }\n})\nconst norm = v => Math.sqrt(v.x * v.x + v.y * v.y)\nconst unit = v => {\n  const n = norm(v)\n  return vec(basis * v.x / n, basis * v.y / n)\n}\nconst add = (a, b) => vec(a.x + b.x, a.y + b.y)\nconst sub = (a, b) => vec(a.x - b.x, a.y - b.y)\nconst end = px => px[px.length - 1]\n\nfunction createSvg(data) {\n  if (data.length <= steps) {\n    return createTextSvg('⭐️ not enough stars')\n  }\n\n  const min = data[0]\n  const max = end(data)\n  const step = (max - min) / steps\n\n  const yx = []\n  {\n    let i = min\n    let count = 0\n    for (let d of data) {\n      if (d < i + step) {\n        count++\n      } else {\n        yx.push(count)\n        count = 1\n        i += step\n      }\n    }\n  }\n\n  const scale = Math.max(...yx) / height\n  {\n    for (let i = 0; i < yx.length; i++) {\n      yx[i] = round(yx[i] / scale)\n    }\n  }\n\n  const points = []\n  {\n    let x = x0\n    for (let y of yx) {\n      x += dx\n      points.push(vec(x, y0 - y))\n    }\n  }\n\n  const p0 = vec(x0, y0)\n  const p1 = points[0]\n  const p2 = points[1]\n  const c1 = add(p0, unit(sub(p1, p0)))\n  const c2 = add(p1, unit(sub(p0, p2)))\n  let path = `M${p0} C ${c1}, ${c2}, ${p1}`\n\n  for (let i = 1; i < points.length; i++) {\n    const p0 = points[i - 1]\n    const p1 = points[i]\n    const p2 = points[i + 1] || p1\n    const c = add(p1, unit(sub(p0, p2)))\n    path += ` S ${c}, ${p1}`\n  }\n\n  const pN = end(points)\n\n  return `<svg width=\"200\" height=\"50\" viewBox=\"0 0 210 50\" xmlns=\"http://www.w3.org/2000/svg\">\n    <defs>\n        <linearGradient x1=\"0%\" y1=\"0%\" x2=\"100%\" y2=\"0%\" id=\"a\">\n            <stop stop-color=\"${gradient[0]}\" offset=\"0%\"/>\n            <stop stop-color=\"${gradient[1]}\" offset=\"100%\"/>\n        </linearGradient>\n    </defs>\n    <path stroke=\"url(#a)\"\n          stroke-width=\"3\"\n          stroke-linejoin=\"round\"\n          stroke-linecap=\"round\"\n          d=\"${path}\"\n          fill=\"none\"/>\n    <circle r=\"4\" cx=\"${p0.x}\" cy=\"${p0.y}\" fill=\"${gradient[0]}\"/>\n    <circle r=\"4\" cx=\"${pN.x}\" cy=\"${pN.y}\" fill=\"${gradient[1]}\"/>      \n</svg>`\n}\n\nfunction createTextSvg(text) {\n  return `<svg width=\"200\" height=\"50\" viewBox=\"0 0 210 50\" xmlns=\"http://www.w3.org/2000/svg\">\n    <text x=\"40\" y=\"30\">${text}</text>     \n</svg>`\n}\n\nmodule.exports = {createSvg, createTextSvg}\n"
  },
  {
    "path": "sync.js",
    "content": "require('dotenv').config()\nconst fs = require('mz/fs')\nconst {fetch} = require('./api')\n\nconst query = `\n  query ($endCursor: String) {\n    search(type: REPOSITORY, query: \"stars:>8000\", first: 100, after: $endCursor) {\n      repositoryCount\n      nodes {\n        ... on Repository {\n          owner {\n            login\n          }\n          name\n          stargazers {\n            totalCount\n          }\n        }\n      }\n      pageInfo {\n        hasNextPage\n        endCursor\n      }\n    }\n  }\n`\n\nasync function main() {\n  let {\n    search: {\n      repositoryCount,\n      nodes,\n      pageInfo: {hasNextPage, endCursor}\n    }\n  } = await fetch(query)\n\n  while (hasNextPage) {\n    const pt = Math.round(100 * nodes.length / repositoryCount)\n    console.log(`loading ${pt}%  ${nodes.length}/${repositoryCount}`)\n\n    const data = await fetch(query, {endCursor})\n\n    endCursor = data.search.pageInfo.endCursor\n    hasNextPage = data.search.pageInfo.hasNextPage\n    nodes = nodes.concat(data.search.nodes)\n  }\n\n  console.log('Total repos: ' + nodes.length)\n\n  const db = {}\n\n  for (let node of nodes) {\n    const {\n      owner: {login},\n      name,\n      stargazers: {totalCount}\n    } = node\n\n    db[login + '/' + name] = totalCount\n  }\n\n  fs.writeFile('db.js', `module.exports = ${JSON.stringify(db, null, 2)}\\n`)\n}\n\nmain().catch(console.log)\n"
  },
  {
    "path": "ttl.js",
    "content": "const db = require('./db')\n\nfunction ttl(repo) {\n  const stars = db[repo] || 0\n\n  if (stars > 10000) {\n    return 604800 // one week\n  } else if (stars > 8000) {\n    return 3 * 86400 // three days\n  } else {\n    return 86400 // one day\n  }\n}\n\nmodule.exports = ttl\n"
  }
]