├── example ├── js │ └── main.js ├── css │ └── style.css └── index.html ├── .gitignore ├── LICENSE ├── DOCUMENTATION.md ├── dist ├── github-calendar-responsive.css ├── github-calendar.css └── github-calendar.min.js ├── CONTRIBUTING.md ├── package.json ├── lib └── index.js └── README.md /example/js/main.js: -------------------------------------------------------------------------------- 1 | GitHubCalendar(".calendar", "IonicaBizau", { 2 | responsive: true 3 | }); 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | *.swo 3 | *~ 4 | *.log 5 | node_modules 6 | *.env 7 | .DS_Store 8 | package-lock.json 9 | -------------------------------------------------------------------------------- /example/css/style.css: -------------------------------------------------------------------------------- 1 | @import url(../../dist/github-calendar-responsive.css); 2 | @import url(https://unpkg.com/bag.css@1.0.12/dist/bag.fixed.css); 3 | @import url(https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.0.0/styles/github.min.css); 4 | @import url(https://cdnjs.cloudflare.com/ajax/libs/octicons/3.3.0/octicons.css); 5 | @import url(https://fonts.googleapis.com/css?family=Cutive+Mono); 6 | 7 | .bag > h1 { 8 | text-align: center; 9 | font-weight: 100; 10 | font-size: 25px; 11 | } 12 | 13 | .monospace { 14 | font-family: 'Cutive Mono', monospace !important; 15 | } 16 | 17 | 18 | body { 19 | font-family: 'Cutive Mono', monospace; 20 | } 21 | 22 | @media(min-width:992px){.bag.fixed{width: 784px;}} 23 | 24 | pre { 25 | background: white; 26 | border: 1px solid #DDDDDD; 27 | padding: 10px; 28 | overflow: auto; 29 | border-radius: 3px; 30 | color: #373727; 31 | } 32 | 33 | .calendar { 34 | margin-bottom: 10px; 35 | } 36 | 37 | p { 38 | color: #444444; 39 | } 40 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016-19 Ionică Bizău (https://ionicabizau.net) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /DOCUMENTATION.md: -------------------------------------------------------------------------------- 1 | ## Documentation 2 | 3 | You can see below the API reference of this module. 4 | 5 | ### `GitHubCalendar(container, username, options)` 6 | Brings the contributions calendar from GitHub (provided username) into your page. 7 | 8 | #### Params 9 | 10 | - **String|HTMLElement** `container`: The calendar container (query selector or the element itself). 11 | - **String** `username`: The GitHub username. 12 | - **Object** `options`: An object containing the following fields: 13 | - `summary_text` (String): The text that appears under the calendar (defaults to: `"Summary of 14 | pull requests, issues opened, and commits made by "`). 15 | - `proxy` (Function): A function that receives as argument an url (string) and should return the proxied url. 16 | The default is using [@izuzak](https://github.com/izuzak)'s [`urlreq`](https://github.com/izuzak/urlreq). 17 | - `global_stats` (Boolean): If `false`, the global stats (total, longest and current streaks) will not be calculated and displayed. By default this is enabled. 18 | - `responsive` (Boolean): If `true`, the graph is changed to scale with the container. Custom CSS should be applied to the element to scale it appropriately. By default this is disabled. 19 | 20 | #### Return 21 | - **Promise** A promise returned by the `fetch()` call. 22 | 23 | -------------------------------------------------------------------------------- /example/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | GitHub Calendar 6 | 7 | 8 | 9 |
10 |

Embed your GitHub contributions calendar anywhere!

11 |
12 | 13 |

Crunching @IonicaBizau's contributions just for you.

14 |
15 | 16 | 17 | 18 | 19 |

If you want to know more about this project, check out the GitHub repository.

20 |

Embed guide <3

21 |
22 | <!-- Include the library. -->
23 | <script
24 |   src="https://unpkg.com/github-calendar@latest/dist/github-calendar.min.js"
25 | ></script>
26 | 
27 | <!-- Optionally, include the theme (if you don't want to struggle to write the CSS) -->
28 | <link
29 |    rel="stylesheet"
30 |    href="https://unpkg.com/github-calendar@latest/dist/github-calendar-responsive.css"
31 | />
32 | 
33 | <!-- Prepare a container for your calendar. -->
34 | <div class="calendar">
35 |     <!-- Loading stuff -->
36 |     Loading the data just for you.
37 | </div>
38 | 
39 | <script>
40 |     GitHubCalendar(".calendar", "your-username");
41 |     // or enable responsive functionality
42 |     GitHubCalendar(".calendar", "your-username", { responsive: true });
43 | </script>
44 |             
45 |
46 | with & JS by @IonicaBizau 47 |
48 |
49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /dist/github-calendar-responsive.css: -------------------------------------------------------------------------------- 1 | .calendar { 2 | font-family: Helvetica, arial; 3 | border: 1px solid #DDDDDD; 4 | border-radius: 3px; 5 | min-height: 243px; 6 | text-align: center; 7 | margin: 0 auto; 8 | } 9 | 10 | .calendar-graph text.wday, 11 | .calendar-graph text.month { 12 | font-size: 10px; 13 | fill: #aaa; 14 | } 15 | 16 | .contrib-legend { 17 | text-align: right; 18 | padding: 0 14px 10px 0; 19 | display: inline-block; 20 | float: right; 21 | } 22 | 23 | .contrib-legend .legend { 24 | display: inline-block; 25 | list-style: none; 26 | margin: 0 5px; 27 | position: relative; 28 | bottom: -1px; 29 | padding: 0; 30 | } 31 | 32 | .contrib-legend .legend li { 33 | display: inline-block; 34 | width: 10px; 35 | height: 10px; 36 | } 37 | 38 | .text-small { 39 | font-size: 12px; 40 | color: #767676; 41 | } 42 | 43 | .calendar-graph { 44 | padding: 5px 0 0; 45 | text-align: center; 46 | } 47 | 48 | .contrib-column { 49 | padding: 15px 0; 50 | text-align: center; 51 | border-left: 1px solid #ddd; 52 | border-top: 1px solid #ddd; 53 | font-size: 11px; 54 | } 55 | 56 | .contrib-column-first { 57 | border-left: 0; 58 | } 59 | 60 | .table-column { 61 | display: table-cell; 62 | width: 1%; 63 | padding-right: 10px; 64 | padding-left: 10px; 65 | vertical-align: top; 66 | } 67 | 68 | .contrib-number { 69 | font-weight: 300; 70 | line-height: 1.3em; 71 | font-size: 24px; 72 | display: block; 73 | color: #333; 74 | } 75 | 76 | .calendar img.spinner { 77 | width: 70px; 78 | margin-top: 50px; 79 | min-height: 70px; 80 | } 81 | 82 | .monospace { 83 | text-align: center; 84 | color: #000; 85 | font-family: monospace; 86 | } 87 | 88 | .monospace a { 89 | color: #1D75AB; 90 | text-decoration: none; 91 | } 92 | 93 | .contrib-footer { 94 | font-size: 11px; 95 | padding: 0 10px 12px; 96 | text-align: left; 97 | width: 100%; 98 | box-sizing: border-box; 99 | height: 26px; 100 | } 101 | 102 | .left.text-muted { 103 | float: left; 104 | margin-left: 9px; 105 | color: #767676; 106 | } 107 | .left.text-muted a { 108 | color: #4078c0; 109 | text-decoration: none; 110 | } 111 | .left.text-muted a:hover, 112 | .monospace a:hover { 113 | text-decoration: underline; 114 | } 115 | 116 | h2.f4.text-normal.mb-3 { 117 | display: none; 118 | } 119 | 120 | .float-left.text-gray { 121 | float: left; 122 | } 123 | #user-activity-overview{ 124 | display:none; 125 | } 126 | -------------------------------------------------------------------------------- /dist/github-calendar.css: -------------------------------------------------------------------------------- 1 | .calendar { 2 | width: 750px; 3 | font-family: Helvetica, arial; 4 | border: 1px solid #DDDDDD; 5 | border-radius: 3px; 6 | min-height: 243px; 7 | text-align: center; 8 | margin: 0 auto; 9 | } 10 | 11 | .calendar-graph text.wday, 12 | .calendar-graph text.month { 13 | font-size: 10px; 14 | fill: #aaa; 15 | } 16 | 17 | .contrib-legend { 18 | text-align: right; 19 | padding: 0 14px 10px 0; 20 | display: inline-block; 21 | float: right; 22 | } 23 | 24 | .contrib-legend .legend { 25 | display: inline-block; 26 | list-style: none; 27 | margin: 0 5px; 28 | position: relative; 29 | bottom: -1px; 30 | padding: 0; 31 | } 32 | 33 | .contrib-legend .legend li { 34 | display: inline-block; 35 | width: 10px; 36 | height: 10px; 37 | } 38 | 39 | .text-small { 40 | font-size: 12px; 41 | color: #767676; 42 | } 43 | 44 | .calendar-graph { 45 | padding: 5px 0 0; 46 | height: 126px; 47 | text-align: center; 48 | } 49 | 50 | .contrib-column { 51 | padding: 15px 0; 52 | text-align: center; 53 | border-left: 1px solid #ddd; 54 | border-top: 1px solid #ddd; 55 | font-size: 11px; 56 | } 57 | 58 | .contrib-column-first { 59 | border-left: 0; 60 | } 61 | 62 | .table-column { 63 | display: table-cell; 64 | width: 1%; 65 | padding-right: 10px; 66 | padding-left: 10px; 67 | vertical-align: top; 68 | } 69 | 70 | .contrib-number { 71 | font-weight: 300; 72 | line-height: 1.3em; 73 | font-size: 24px; 74 | display: block; 75 | color: #333; 76 | } 77 | 78 | .calendar img.spinner { 79 | width: 70px; 80 | margin-top: 50px; 81 | min-height: 70px; 82 | } 83 | 84 | .monospace { 85 | text-align: center; 86 | color: #000; 87 | font-family: monospace; 88 | } 89 | 90 | .monospace a { 91 | color: #1D75AB; 92 | text-decoration: none; 93 | } 94 | 95 | .contrib-footer { 96 | font-size: 11px; 97 | padding: 0 10px 12px; 98 | text-align: left; 99 | width: 100%; 100 | box-sizing: border-box; 101 | height: 26px; 102 | } 103 | 104 | .left.text-muted { 105 | float: left; 106 | margin-left: 9px; 107 | color: #767676; 108 | } 109 | .left.text-muted a { 110 | color: #4078c0; 111 | text-decoration: none; 112 | } 113 | .left.text-muted a:hover, 114 | .monospace a:hover { 115 | text-decoration: underline; 116 | } 117 | 118 | h2.f4.text-normal.mb-3 { 119 | display: none; 120 | } 121 | 122 | .float-left.text-gray { 123 | float: left; 124 | } 125 | #user-activity-overview{ 126 | display:none; 127 | } 128 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # :eight_spoked_asterisk: :stars: :sparkles: :dizzy: :star2: :star2: :sparkles: :dizzy: :star2: :star2: Contributing :star: :star2: :dizzy: :sparkles: :star: :star2: :dizzy: :sparkles: :stars: :eight_spoked_asterisk: 2 | 3 | So, you want to contribute to this project! That's awesome. However, before 4 | doing so, please read the following simple steps how to contribute. This will 5 | make the life easier and will avoid wasting time on things which are not 6 | requested. :sparkles: 7 | 8 | ## Discuss the changes before doing them 9 | - First of all, open an issue in the repository, using the [bug tracker][1], 10 | describing the contribution you would like to make, the bug you found or any 11 | other ideas you have. This will help us to get you started on the right 12 | foot. 13 | 14 | - If it makes sense, add the platform and software information (e.g. operating 15 | system, Node.JS version etc.), screenshots (so we can see what you are 16 | seeing). 17 | 18 | - It is recommended to wait for feedback before continuing to next steps. 19 | However, if the issue is clear (e.g. a typo) and the fix is simple, you can 20 | continue and fix it. 21 | 22 | ## Fixing issues 23 | - Fork the project in your account and create a branch with your fix: 24 | `some-great-feature` or `some-issue-fix`. 25 | 26 | - Commit your changes in that branch, writing the code following the 27 | [code style][2]. If the project contains tests (generally, the `test` 28 | directory), you are encouraged to add a test as well. :memo: 29 | 30 | - If the project contains a `package.json` or a `bower.json` file add yourself 31 | in the `contributors` array (or `authors` in the case of `bower.json`; 32 | if the array does not exist, create it): 33 | 34 | ```json 35 | { 36 | "contributors": [ 37 | "Your Name (http://your.website)" 38 | ] 39 | } 40 | ``` 41 | 42 | ## Creating a pull request 43 | 44 | - Open a pull request, and reference the initial issue in the pull request 45 | message (e.g. *fixes #*). Write a good description and 46 | title, so everybody will know what is fixed/improved. 47 | 48 | - If it makes sense, add screenshots, gifs etc., so it is easier to see what 49 | is going on. 50 | 51 | ## Wait for feedback 52 | Before accepting your contributions, we will review them. You may get feedback 53 | about what should be fixed in your modified code. If so, just keep committing 54 | in your branch and the pull request will be updated automatically. 55 | 56 | ## Everyone is happy! 57 | Finally, your contributions will be merged, and everyone will be happy! :smile: 58 | Contributions are more than welcome! 59 | 60 | Thanks! :sweat_smile: 61 | 62 | 63 | 64 | [1]: https://github.com/IonicaBizau/github-calendar/issues 65 | 66 | [2]: https://github.com/IonicaBizau/code-style 67 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "github-calendar", 3 | "version": "1.3.1", 4 | "description": "Embed your GitHub contributions calendar anywhere.", 5 | "main": "lib/index.js", 6 | "directories": { 7 | "example": "example" 8 | }, 9 | "scripts": { 10 | "test": "echo \"Error: no test specified\" && exit 1", 11 | "release": "dist-it lib/index.js github-calendar.min.js" 12 | }, 13 | "repository": { 14 | "type": "git", 15 | "url": "git+ssh://git@github.com/IonicaBizau/github-calendar.git" 16 | }, 17 | "keywords": [ 18 | "github", 19 | "calendar", 20 | "embed" 21 | ], 22 | "author": "Ionică Bizău (https://ionicabizau.net)", 23 | "contributors": [ 24 | "Evan Palmer (http://evanpalmer.net)", 25 | "Francesco Tonini (https://francescotonini.it)", 26 | "Miroslav Vidovic ", 27 | "Mike Roibu " 28 | ], 29 | "license": "MIT", 30 | "bugs": { 31 | "url": "https://github.com/IonicaBizau/github-calendar/issues" 32 | }, 33 | "homepage": "https://github.com/IonicaBizau/github-calendar#readme", 34 | "dependencies": { 35 | "add-subtract-date": "^1.0.5", 36 | "elly": "^1.0.0", 37 | "formatoid": "^1.0.3", 38 | "github-calendar-parser": "^1.1.3" 39 | }, 40 | "blah": { 41 | "example": [ 42 | { 43 | "code": { 44 | "language": "html", 45 | "content": [ 46 | "", 47 | "", 49 | "", 50 | "", 51 | "", 52 | "", 56 | "", 57 | "", 58 | "
", 59 | " ", 60 | " Loading the data just for you.", 61 | "
", 62 | "", 63 | "" 68 | ] 69 | } 70 | }, 71 | { 72 | "p": "[Here](http://codepen.io/anon/pen/aZmjvZ?editors=1000) you can see this example in action." 73 | } 74 | ], 75 | "thanks": { 76 | "ul": [ 77 | "Big thanks to [**@izuzak**](https://github.com/izuzak) for creating the [urlreq](https://github.com/izuzak/urlreq) project–the default proxy used by this library. :cake:", 78 | "Part of the CSS code was taken from the GitHub profile page to offer the same experience. :art:" 79 | ] 80 | }, 81 | "description": [ 82 | { 83 | "p": "Everybodywell, haters gonna hate loves GitHub and everybody loves stats. So, why not making the GitHub contributions calendar available for being embeded in your web pages? Now [you can](https://ionicabizau.github.io/github-calendar/example). :tada:" 84 | }, 85 | { 86 | "p": "[![](http://i.imgur.com/S1h8XoB.jpg)](https://ionicabizau.github.io/github-calendar/example)" 87 | } 88 | ], 89 | "title": "github-calendar.js", 90 | "related": { 91 | "ul": [ 92 | "github-profile-languages", 93 | "github-org-members.js", 94 | "gh-contributions", 95 | "github-emojify", 96 | "github-stats", 97 | "github-labeller", 98 | "cli-gh-cal", 99 | "gh-destroy", 100 | "ship-release", 101 | "github-calendar-legend", 102 | "github-pr-branch-links", 103 | "github-emoji-form-submit", 104 | "gh-repeat", 105 | "gh-repos", 106 | "github-old-header", 107 | "gh.js", 108 | "ghcal", 109 | "sort-github-user-repos", 110 | "github-calendar-parser", 111 | "gh-notifier", 112 | "octimatch", 113 | "github-portfolio", 114 | "gh-polyglot", 115 | "cli-github", 116 | "github-calendar", 117 | "git-stats", 118 | "repository-downloader", 119 | "github-colors" 120 | ] 121 | } 122 | }, 123 | "files": [ 124 | "bin/", 125 | "app/", 126 | "lib/", 127 | "dist/", 128 | "src/", 129 | "scripts/", 130 | "resources/", 131 | "menu/", 132 | "cli.js", 133 | "index.js", 134 | "bloggify.js", 135 | "bloggify.json", 136 | "bloggify/" 137 | ] 138 | } 139 | -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const parse = require("github-calendar-parser") 4 | , $ = require("elly") 5 | , addSubtractDate = require("add-subtract-date") 6 | , formatoid = require("formatoid") 7 | ; 8 | 9 | const DATE_FORMAT1 = "MMM D, YYYY" 10 | , DATE_FORMAT2 = "MMMM D" 11 | ; 12 | 13 | /** 14 | * GitHubCalendar 15 | * Brings the contributions calendar from GitHub (provided username) into your page. 16 | * 17 | * @name GitHubCalendar 18 | * @function 19 | * @param {String|HTMLElement} container The calendar container (query selector or the element itself). 20 | * @param {String} username The GitHub username. 21 | * @param {Object} options An object containing the following fields: 22 | * 23 | * - `summary_text` (String): The text that appears under the calendar (defaults to: `"Summary of 24 | * pull requests, issues opened, and commits made by "`). 25 | * - `proxy` (Function): A function that receives as argument an url (string) and should return the proxied url. 26 | * The default is using [@izuzak](https://github.com/izuzak)'s [`urlreq`](https://github.com/izuzak/urlreq). 27 | * - `global_stats` (Boolean): If `false`, the global stats (total, longest and current streaks) will not be calculated and displayed. By default this is enabled. 28 | * - `responsive` (Boolean): If `true`, the graph is changed to scale with the container. Custom CSS should be applied to the element to scale it appropriately. By default this is disabled. 29 | * 30 | * @return {Promise} A promise returned by the `fetch()` call. 31 | */ 32 | module.exports = function GitHubCalendar (container, username, options) { 33 | 34 | container = $(container); 35 | 36 | options = options || {}; 37 | options.summary_text = options.summary_text || `Summary of pull requests, issues opened, and commits made by @${username}`; 38 | 39 | if (options.global_stats === false) { 40 | container.style.minHeight = "175px"; 41 | } 42 | 43 | // We need a proxy for CORS 44 | // Thanks, @izuzak (https://github.com/izuzak/urlreq) 45 | options.proxy = options.proxy || function (url) { 46 | return "https://urlreq.appspot.com/req?method=GET&url=" + url; 47 | }; 48 | 49 | let fetchCalendar = () => fetch(options.proxy("https://github.com/" + username)).then(response => { 50 | return response.text() 51 | }).then(body => { 52 | let div = document.createElement("div"); 53 | div.innerHTML = body; 54 | let cal = div.querySelector(".js-yearly-contributions"); 55 | $(".position-relative h2", cal).remove(); 56 | cal.querySelector(".float-left.text-gray").innerHTML = options.summary_text; 57 | 58 | // If 'include-fragment' with spinner img loads instead of the svg, fetchCalendar again 59 | if (cal.querySelector("include-fragment")) { 60 | setTimeout(fetchCalendar, 500); 61 | } else { 62 | // If options includes responsive, SVG element has to be manipulated to be made responsive 63 | if (options.responsive === true) { 64 | let svg = cal.querySelector("svg.js-calendar-graph-svg"); 65 | // Get the width/height properties and use them to create the viewBox 66 | let width = svg.getAttribute("width"); 67 | let height = svg.getAttribute("height"); 68 | // Remove height property entirely 69 | svg.removeAttribute("height"); 70 | // Width property should be set to 100% to fill entire container 71 | svg.setAttribute("width", "100%"); 72 | // Add a viewBox property based on the former width/height 73 | svg.setAttribute("viewBox", "0 0 " + width + " " + height); 74 | } 75 | 76 | if (options.global_stats !== false) { 77 | let parsed = parse($("svg", cal).outerHTML) 78 | , currentStreakInfo = parsed.current_streak 79 | ? `${formatoid(parsed.current_streak_range[0], DATE_FORMAT2)} – ${formatoid(parsed.current_streak_range[1], DATE_FORMAT2)}` 80 | : parsed.last_contributed 81 | ? `Last contributed in ${formatoid(parsed.last_contributed, DATE_FORMAT2)}.` 82 | : "Rock - Hard Place" 83 | , longestStreakInfo = parsed.longest_streak 84 | ? `${formatoid(parsed.longest_streak_range[0], DATE_FORMAT2)} – ${formatoid(parsed.longest_streak_range[1], DATE_FORMAT2)}` 85 | : parsed.last_contributed 86 | ? `Last contributed in ${formatoid(parsed.last_contributed, DATE_FORMAT2)}.` 87 | : "Rock - Hard Place" 88 | , firstCol = $("
", { 89 | "class": "contrib-column contrib-column-first table-column" 90 | , html: `Contributions in the last year 91 | ${parsed.last_year} total 92 | ${formatoid(addSubtractDate.subtract(new Date(), 1, "year"), DATE_FORMAT1)} – ${formatoid(new Date(), DATE_FORMAT1)}` 93 | }) 94 | , secondCol = $("
", { 95 | "class": "contrib-column table-column" 96 | , html: `Longest streak 97 | ${parsed.longest_streak} days 98 | ${longestStreakInfo}` 99 | }) 100 | , thirdCol = $("
", { 101 | "class": "contrib-column table-column" 102 | , html: `Current streak 103 | ${parsed.current_streak} days 104 | ${currentStreakInfo}` 105 | }) 106 | ; 107 | 108 | cal.appendChild(firstCol); 109 | cal.appendChild(secondCol); 110 | cal.appendChild(thirdCol); 111 | } 112 | 113 | container.innerHTML = cal.innerHTML; 114 | } 115 | }).catch(e => console.error(e)); 116 | 117 | return fetchCalendar(); 118 | } 119 | 120 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | # github-calendar.js 5 | 6 | [![Support me on Patreon][badge_patreon]][patreon] [![Buy me a book][badge_amazon]][amazon] [![PayPal][badge_paypal_donate]][paypal-donations] [![Ask me anything](https://img.shields.io/badge/ask%20me-anything-1abc9c.svg)](https://github.com/IonicaBizau/ama) [![Version](https://img.shields.io/npm/v/github-calendar.svg)](https://www.npmjs.com/package/github-calendar) [![Downloads](https://img.shields.io/npm/dt/github-calendar.svg)](https://www.npmjs.com/package/github-calendar) 7 | 8 | > Embed your GitHub contributions calendar anywhere. 9 | 10 | 11 | Everybodywell, haters gonna hate loves GitHub and everybody loves stats. So, why not making the GitHub contributions calendar available for being embeded in your web pages? Now [you can](https://ionicabizau.github.io/github-calendar/example). :tada: 12 | 13 | 14 | [![](http://i.imgur.com/S1h8XoB.jpg)](https://ionicabizau.github.io/github-calendar/example) 15 | 16 | 17 | ## :cloud: Installation 18 | 19 | 20 | Check out the [`dist`](/dist) directory to download the needed files and include them on your page. 21 | 22 | If you're using this module in a CommonJS environment, you can install it using `npm` or `yarn` and `require` it: 23 | 24 | ```sh 25 | # Using npm 26 | npm install --save github-calendar 27 | 28 | # Using yarn 29 | yarn add github-calendar 30 | ``` 31 | 32 | 33 | ## :memo: Documentation 34 | 35 | 36 | ### `GitHubCalendar(container, username, options)` 37 | Brings the contributions calendar from GitHub (provided username) into your page. 38 | 39 | #### Params 40 | 41 | - **String|HTMLElement** `container`: The calendar container (query selector or the element itself). 42 | - **String** `username`: The GitHub username. 43 | - **Object** `options`: An object containing the following fields: 44 | - `summary_text` (String): The text that appears under the calendar (defaults to: `"Summary of 45 | pull requests, issues opened, and commits made by "`). 46 | - `proxy` (Function): A function that receives as argument an url (string) and should return the proxied url. 47 | The default is using [@izuzak](https://github.com/izuzak)'s [`urlreq`](https://github.com/izuzak/urlreq). 48 | - `global_stats` (Boolean): If `false`, the global stats (total, longest and current streaks) will not be calculated and displayed. By default this is enabled. 49 | - `responsive` (Boolean): If `true`, the graph is changed to scale with the container. Custom CSS should be applied to the element to scale it appropriately. By default this is disabled. 50 | 51 | #### Return 52 | - **Promise** A promise returned by the `fetch()` call. 53 | 54 | 55 | 56 | ## :yum: How to contribute 57 | Have an idea? Found a bug? See [how to contribute][contributing]. 58 | 59 | 60 | ## :sparkling_heart: Support my projects 61 | 62 | I open-source almost everything I can, and I try to reply to everyone needing help using these projects. Obviously, 63 | this takes time. You can integrate and use these projects in your applications *for free*! You can even change the source code and redistribute (even resell it). 64 | 65 | However, if you get some profit from this or just want to encourage me to continue creating stuff, there are few ways you can do it: 66 | 67 | 68 | - Starring and sharing the projects you like :rocket: 69 | - [![Buy me a book][badge_amazon]][amazon]—I love books! I will remember you after years if you buy me one. :grin: :book: 70 | - [![PayPal][badge_paypal]][paypal-donations]—You can make one-time donations via PayPal. I'll probably buy a ~~coffee~~ tea. :tea: 71 | - [![Support me on Patreon][badge_patreon]][patreon]—Set up a recurring monthly donation and you will get interesting news about what I'm doing (things that I don't share with everyone). 72 | - **Bitcoin**—You can send me bitcoins at this address (or scanning the code below): `1P9BRsmazNQcuyTxEqveUsnf5CERdq35V6` 73 | 74 | ![](https://i.imgur.com/z6OQI95.png) 75 | 76 | 77 | Thanks! :heart: 78 | 79 | 80 | ## :cake: Thanks 81 | 82 | - Big thanks to [**@izuzak**](https://github.com/izuzak) for creating the [urlreq](https://github.com/izuzak/urlreq) project–the default proxy used by this library. :cake: 83 | - Part of the CSS code was taken from the GitHub profile page to offer the same experience. :art: 84 | 85 | 86 | 87 | ## :sparkles: Related 88 | 89 | - [`github-profile-languages`](https://github.com/IonicaBizau/github-profile-languages)—Create a nice pie chart with the user's programming languages from their GitHub profile. 90 | - [`github-org-members.js`](https://github.com/IonicaBizau/github-org-members.js)—A JavaScript library for fetching and rendering in HTML the members of a GitHub organization. 91 | - [`gh-contributions`](https://github.com/IonicaBizau/github-contributions)—A tool that generates a repository which being pushed into your GitHub account creates a nice contributions calendar. 92 | - [`github-emojify`](https://github.com/IonicaBizau/github-emojify#readme)—Emojify your GitHub repository descriptions. 93 | - [`github-stats`](https://github.com/IonicaBizau/github-stats)—Visualize stats about GitHub users and projects in your terminal. 94 | - [`github-labeller`](https://github.com/IonicaBizau/github-labeller#readme)—Automagically create issue labels in your GitHub projects. 95 | - [`cli-gh-cal`](https://github.com/IonicaBizau/cli-gh-cal)—GitHub like calendar graphs in command line. 96 | - [`gh-destroy`](https://github.com/IonicaBizau/gh-destroy#readme)—Delete multiple GitHub repositories. 97 | - [`ship-release`](https://github.com/IonicaBizau/ship-release#readme)—Publish new versions on GitHub and npm with ease. 98 | - [`github-calendar-legend`](https://github.com/IonicaBizau/github-calendar-legend#readme)—The GitHub contributions calendar colors. 99 | - [`github-pr-branch-links`](https://github.com/IonicaBizau/github-pr-branch-links)—Open in a new tab the clicked branch on a pull request page. 100 | - [`github-emoji-form-submit`](https://github.com/IonicaBizau/github-emoji-form-submit#readme)—Autocomplete selected Emoji when submitting forms on GitHub.com. 101 | - [`gh-repeat`](https://github.com/IonicaBizau/gh-repeat#readme)—Repetitive actions on multiple GitHub repositories. 102 | - [`gh-repos`](https://github.com/IonicaBizau/gh-repos#readme)—Get one or all the owner repositories from GitHub. 103 | - [`github-old-header`](https://github.com/IonicaBizau/github-old-header)—Brings the old header links back. 104 | - [`gh.js`](https://github.com/IonicaBizau/gh.js)—Tiny GitHub API wrapper for server and client. 105 | - [`ghcal`](https://github.com/IonicaBizau/ghcal)—See the GitHub contributions calendar of a user in the command line. 106 | - [`sort-github-user-repos`](https://github.com/IonicaBizau/sort-github-user-repos#readme)—Sort GitHub repositories by stars for user. 107 | - [`github-calendar-parser`](https://github.com/IonicaBizau/github-calendar-parser#readme)—Parses the GitHub contributions calendar SVG code into JSON. 108 | - [`gh-notifier`](https://bitbucket.org/IonicaBizau/gh-notifier#readme)—Receive desktop notifications from your GitHub dashboard. 109 | - [`octimatch`](https://github.com/IonicaBizau/OctiMatch#readme)—A matching game with GitHub's Octicons. 110 | - [`github-portfolio`](https://github.com/IonicaBizau/github-portfolio#readme)—A tool to generate a portfolio using data from your Github projects. 111 | - [`gh-polyglot`](https://github.com/IonicaBizau/node-gh-polyglot)—Get language stats about GitHub users and repositories. 112 | - [`cli-github`](https://github.com/IonicaBizau/cli-github)—A fancy GitHub client for command line. 113 | - [`github-calendar`](https://github.com/IonicaBizau/github-calendar#readme)—Embed your GitHub contributions calendar anywhere. 114 | - [`git-stats`](https://github.com/IonicaBizau/git-stats)—Local git statistics including GitHub-like contributions calendars. 115 | - [`repository-downloader`](https://github.com/IonicaBizau/repository-downloader)—Download all the repositories from BitBucket and GitHub, including your account, teams and where you created pull requests. 116 | - [`github-colors`](https://github.com/IonicaBizau/github-colors)—GitHub colors and file extensions mapping 117 | 118 | 119 | 120 | ## :scroll: License 121 | 122 | [MIT][license] © [Ionică Bizău][website] 123 | 124 | 125 | [badge_patreon]: https://ionicabizau.github.io/badges/patreon.svg 126 | [badge_amazon]: https://ionicabizau.github.io/badges/amazon.svg 127 | [badge_paypal]: https://ionicabizau.github.io/badges/paypal.svg 128 | [badge_paypal_donate]: https://ionicabizau.github.io/badges/paypal_donate.svg 129 | 130 | [patreon]: https://www.patreon.com/ionicabizau 131 | [amazon]: http://amzn.eu/hRo9sIZ 132 | [paypal-donations]: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=RVXDDLKKLQRJW 133 | 134 | [license]: http://showalicense.com/?fullname=Ionic%C4%83%20Biz%C4%83u%20%3Cbizauionica%40gmail.com%3E%20(https%3A%2F%2Fionicabizau.net)&year=2016#license-mit 135 | [website]: https://ionicabizau.net 136 | [contributing]: /CONTRIBUTING.md 137 | [docs]: /DOCUMENTATION.md 138 | -------------------------------------------------------------------------------- /dist/github-calendar.min.js: -------------------------------------------------------------------------------- 1 | "use strict";var _typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e};!function(e){if("object"===("undefined"==typeof exports?"undefined":_typeof(exports))&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var t;t="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,t.GitHubCalendar=e()}}(function(){return function(){function e(t,r,n){function a(s,u){if(!r[s]){if(!t[s]){var i="function"==typeof require&&require;if(!u&&i)return i(s,!0);if(o)return o(s,!0);var c=new Error("Cannot find module '"+s+"'");throw c.code="MODULE_NOT_FOUND",c}var l=r[s]={exports:{}};t[s][0].call(l.exports,function(e){var r=t[s][1][e];return a(r||e)},l,l.exports,e,t,r,n)}return r[s].exports}for(var o="function"==typeof require&&require,s=0;s@'+t+"",i.responsive===!0&&e.classList.add("calendar-responsive"),i.global_stats===!1&&(e.style.minHeight="175px"),i.proxy=i.proxy||function(e){return"https://urlreq.appspot.com/req?method=GET&url="+e};var c=function l(){return fetch(i.proxy("https://github.com/"+t)).then(function(e){return e.text()}).then(function(t){var c=document.createElement("div");c.innerHTML=t;var d=c.querySelector(".js-yearly-contributions");if(n(".position-relative h2",d).remove(),d.querySelector(".float-left.text-gray").innerHTML=i.summary_text,d.querySelector("include-fragment"))setTimeout(l,500);else{if(i.responsive===!0){var f=d.querySelector("svg.js-calendar-graph-svg"),p=f.getAttribute("width"),b=f.getAttribute("height");f.removeAttribute("height"),f.setAttribute("width","100%"),f.setAttribute("viewBox","0 0 "+p+" "+b)}if(i.global_stats!==!1){var m=r(n("svg",d).outerHTML),g=m.current_streak?o(m.current_streak_range[0],u)+" – "+o(m.current_streak_range[1],u):m.last_contributed?"Last contributed in "+o(m.last_contributed,u)+".":"Rock - Hard Place",h=m.longest_streak?o(m.longest_streak_range[0],u)+" – "+o(m.longest_streak_range[1],u):m.last_contributed?"Last contributed in "+o(m.last_contributed,u)+".":"Rock - Hard Place",y=n("
",{"class":"contrib-column contrib-column-first table-column",html:'Contributions in the last year\n '+m.last_year+' total\n '+o(a.subtract(new Date,1,"year"),s)+" – "+o(new Date,s)+""}),v=n("
",{"class":"contrib-column table-column",html:'Longest streak\n '+m.longest_streak+' days\n '+h+""}),M=n("
",{"class":"contrib-column table-column",html:'Current streak\n '+m.current_streak+' days\n '+g+""});d.appendChild(y),d.appendChild(v),d.appendChild(M)}e.innerHTML=d.innerHTML}})["catch"](function(e){return console.error(e)})};return c()}},{"add-subtract-date":2,elly:4,formatoid:6,"github-calendar-parser":8}],2:[function(e,t){function r(e){return function t(r,n,a){switch(n=e*n,a){case"years":case"year":r.setFullYear(r.getFullYear()+n);break;case"months":case"month":r.setMonth(r.getMonth()+n);break;case"weeks":case"week":return t(r,7*n,"days");case"days":case"day":r.setDate(r.getDate()+n);break;case"hours":case"hour":r.setHours(r.getHours()+n);break;case"minutes":case"minute":r.setMinutes(r.getMinutes()+n);break;case"seconds":case"second":r.setSeconds(r.getSeconds()+n);break;case"milliseconds":case"millisecond":r.setMilliseconds(r.getMilliseconds()+n);break;default:throw new Error("Invalid range: "+a)}return r}}t.exports={add:r(1),subtract:r(-1)}},{}],3:[function(e,t){t.exports.en=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],t.exports.en.abbr=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],t.exports.en["short"]=["Su","Mo","Tu","We","Th","Fr","Sa"],t.exports.fr=["dimanche","lundi","mardi","mercredi","jeudi","vendredi","samedi"],t.exports.fr.abbr=["dim","lun","mar","mer","jeu","ven","sam"],t.exports.fr["short"]=["di","lu","ma","me","je","ve","sa"],t.exports.es=["domingo","lunes","martes","miercoles","jueves","viernes","sabado"],t.exports.es.abbr=["dom","lun","mar","mir","jue","vie","sab"],t.exports.es["short"]=["do","lu","ma","mi","ju","vi","sa"],t.exports.it=["Domenica","Lunedi","Martedi","Mercoledi","Giovedi","Venerdi","Sabato"],t.exports.it.abbr=["Dom","Lun","Mar","Mer","Gio","Ven","Sab"],t.exports.it["short"]=["D","L","Ma","Me","G","V","S"],t.exports=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],t.exports.abbr=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],t.exports["short"]=["Su","Mo","Tu","We","Th","Fr","Sa"]},{}],4:[function(e,t){function r(e,t){return"string"==typeof e?"<"===e.charAt(0)?(e=document.createElement(e.slice(1,-1)),n(t||{},function(t,r){switch(r){case"text":return void(e.textContent=t);case"html":return void(e.innerHTML=t)}e.setAttribute(r,t)}),e):(t=t||document,t.querySelector(e)):e}var n=e("iterate-object"),a=e("sliced");r.$$=function(e,t){return"string"==typeof e?(t=t||document,a(t.querySelectorAll(e))):[e]},t.exports=r},{"iterate-object":9,sliced:13}],5:[function(e,t){t.exports=function(e,t,r){t=t||2,r=r||"0",e=e.toString();var n=t-e.length;return(0>=n?"":r.repeat(n))+e}},{}],6:[function(e,t){var r=e("months"),n=e("days"),a=e("fillo"),o=e("parse-it").Parser,s={YYYY:function(e,t){return t?e.getUTCFullYear():e.getFullYear()},YY:function(e,t){return s.YYYY(e,t)%100},MMMM:function(e,t){return t?r[e.getUTCMonth()]:r[e.getMonth()]},MMM:function(e,t){return t?r.abbr[e.getUTCMonth()]:r.abbr[e.getMonth()]},MM:function(e,t){return a(t?e.getUTCMonth()+1:e.getMonth()+1)},M:function(e,t){return t?e.getUTCMonth()+1:e.getMonth()+1},dddd:function(e,t){return n[s.d(e,t)]},ddd:function(e,t){return n.abbr[s.d(e,t)]},dd:function(e,t){return n["short"][s.d(e,t)]},d:function(e,t){return t?e.getUTCDay():e.getDay()},DD:function(e,t){return a(s.D(e,t))},D:function(e,t){return t?e.getUTCDate():e.getDate()},A:function(e,t){return s.a(e,t).toUpperCase()},a:function(e,t){return s.H(e,t)>=12?"pm":"am"},hh:function(e,t){return a(s.h(e,t))},h:function(e,t){return s.H(e,t)%12||12},HH:function(e,t){return a(s.H(e,t))},H:function(e,t){return t?e.getUTCHours():e.getHours()},mm:function(e,t){return a(s.m(e,t))},m:function(e,t){return t?e.getUTCMinutes():e.getMinutes()},ss:function(e,t){return a(s.s(e,t))},s:function(e,t){return t?e.getUTCSeconds():e.getSeconds()},S:function(e,t){return Math.round(s.s(e,t)/60*10)},SS:function(e,t){return a(s.s(e,t)/60*100)},SSS:function(e,t){return a(s.s(e,t)/60*1e3,3)},Z:function(e){var t=-e.getTimezoneOffset();return(t>=0?"+":"-")+a(parseInt(t/60))+":"+a(t%60)},ZZ:function(e){var t=-e.getTimezoneOffset();return(t>=0?"+":"-")+a(parseInt(t/60))+a(t%60)}},u=new o(s);t.exports=function(e,t){return u.run(t,[e,e._useUTC])}},{days:3,fillo:5,months:10,"parse-it":11}],7:[function(e,t){t.exports=["#eee","#d6e685","#8cc665","#44a340","#1e6823"]},{}],8:[function(e,t){var r=e("github-calendar-legend");t.exports=function(e){var t={last_year:0,longest_streak:-1,longest_streak_range:[],current_streak:0,current_streak_range:[],weeks:[],days:[],last_contributed:null},n=[],a=function(){t.current_streak>t.longest_streak&&(t.longest_streak=t.current_streak,t.longest_streak_range[0]=t.current_streak_range[0],t.longest_streak_range[1]=t.current_streak_range[1])};return e.split("\n").slice(2).map(function(e){return e.trim()}).forEach(function(e){if(e.startsWith("t?Math.max(0,t+a):t||0;for(void 0!==r&&(a=0>r?r+a:r);a-->o;)n[a-o]=e[a];return n}},{}]},{},[1])(1)}); 2 | --------------------------------------------------------------------------------