├── docs
├── CNAME
├── _includes
│ ├── page.scss
│ └── example.html
├── robots.txt
├── _layouts
│ └── default.html
├── _sass
│ ├── _syntax.scss
│ └── _page.scss
├── github-btn.html
└── index.md
├── .gitattributes
├── .github
├── codeql
│ └── codeql-config.yml
├── dependabot.yml
└── workflows
│ ├── codeql.yml
│ └── ci.yml
├── Gemfile
├── .stylelintrc.json
├── _config.yml
├── src
├── btn.html
├── styles.css
└── js.js
├── .gitignore
├── html-minifier.json
├── xo.config.js
├── README.md
├── package.json
├── Gemfile.lock
└── LICENSE
/docs/CNAME:
--------------------------------------------------------------------------------
1 | ghbtns.com
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Enforce Unix newlines
2 | * text=auto eol=lf
3 |
--------------------------------------------------------------------------------
/.github/codeql/codeql-config.yml:
--------------------------------------------------------------------------------
1 | name: "CodeQL config"
2 | paths-ignore:
3 | - docs/github-btn.html
4 |
--------------------------------------------------------------------------------
/docs/_includes/page.scss:
--------------------------------------------------------------------------------
1 | // Our bundle CSS files are listed here so that we inlcude the dist file in Jekyll
2 | @use "page";
3 | @use "syntax";
4 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: "github-actions"
4 | directory: "/"
5 | schedule:
6 | interval: monthly
7 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 |
3 | gem 'jekyll', '~> 4.4.1'
4 | gem 'jekyll-seo-tag', '~> 2.8.0'
5 | gem 'jekyll-sitemap', '~> 1.4.0'
6 | gem 'wdm', '~> 0.2.0', :install_if => Gem.win_platform?
7 |
--------------------------------------------------------------------------------
/docs/robots.txt:
--------------------------------------------------------------------------------
1 | ---
2 | ---
3 |
4 | # www.robotstxt.org/
5 |
6 | # Allow crawling of all content
7 | User-agent: *
8 | Disallow: {% if jekyll.environment == "netlify" %}/{% else %}/*?*{% endif %}
9 | Sitemap: {{ site.url }}/sitemap.xml
10 |
--------------------------------------------------------------------------------
/.stylelintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": [
3 | "stylelint-config-twbs-bootstrap"
4 | ],
5 | "reportInvalidScopeDisables": true,
6 | "reportNeedlessDisables": true,
7 | "rules": {
8 | "no-duplicate-selectors": true,
9 | "property-no-vendor-prefix": null,
10 | "value-no-vendor-prefix": null
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/_config.yml:
--------------------------------------------------------------------------------
1 | title: "Unofficial GitHub Buttons"
2 | description: "A set of static buttons with dynamic watch and fork counts for any repo hosted on GitHub."
3 | url: "https://ghbtns.com"
4 |
5 | # Social
6 | author:
7 | name: "Mark Otto"
8 |
9 | twitter:
10 | username: "mdo"
11 |
12 | permalink: pretty
13 |
14 | sass:
15 | style: compressed
16 |
17 | source: docs
18 |
19 | plugins:
20 | - jekyll-seo-tag
21 | - jekyll-sitemap
22 |
--------------------------------------------------------------------------------
/src/btn.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Ignore docs files
2 | /.sass-cache/
3 | /_site/
4 | /docs/.jekyll-cache/
5 | /.ruby-version
6 |
7 | # Numerous always-ignore extensions
8 | *.diff
9 | *.err
10 | *.orig
11 | *.log
12 | *.rej
13 | *.swo
14 | *.swp
15 | *.zip
16 | *.vi
17 | *~
18 |
19 | # OS or Editor folders
20 | .DS_Store
21 | ._*
22 | Thumbs.db
23 | .cache
24 | .project
25 | .settings
26 | .tmproj
27 | *.esproj
28 | nbproject
29 | *.sublime-project
30 | *.sublime-workspace
31 | .idea
32 |
33 | # Komodo
34 | *.komodoproject
35 | .komodotools
36 |
37 | # Folders to ignore
38 | /.bundle/
39 | /node_modules/
40 | /vendor/
41 |
42 | # Local Netlify folder
43 | .netlify
44 |
--------------------------------------------------------------------------------
/docs/_includes/example.html:
--------------------------------------------------------------------------------
1 | {%- comment -%}
2 | Usage: include example.html content=markup [args],
3 | where content is a capture with the HTML content
4 |
5 | args can be one of the following:
6 | id - null (default)
7 | class - "example" (default)
8 | {%- endcomment -%}
9 |
10 | {%- assign id = include.id -%}
11 | {%- assign class = include.class -%}
12 |
13 |
14 | {%- assign url = site.url | append: '/' -%}
15 | {{- include.content | replace: url, '' | replace: ' frameborder="0" scrolling="0"' '' -}}
16 |
17 |
18 | {%- highlight html -%}
19 | {{- include.content -}}
20 | {%- endhighlight -%}
21 |
--------------------------------------------------------------------------------
/html-minifier.json:
--------------------------------------------------------------------------------
1 | {
2 | "collapseBooleanAttributes": true,
3 | "collapseWhitespace": true,
4 | "conservativeCollapse": false,
5 | "decodeEntities": true,
6 | "includeAutoGeneratedTags": false,
7 | "minifyCSS": {
8 | "level": {
9 | "1": {
10 | "specialComments": 0,
11 | "roundingPrecision": 6
12 | },
13 | "2": {
14 | "all": false,
15 | "mergeMedia": true,
16 | "removeDuplicateMediaBlocks": true,
17 | "removeEmpty": true
18 | }
19 | }
20 | },
21 | "minifyJS": {
22 | "compress": {
23 | "passes": 2
24 | },
25 | "mangle": true
26 | },
27 | "processConditionalComments": true,
28 | "removeAttributeQuotes": true,
29 | "removeComments": true,
30 | "removeOptionalTags": true,
31 | "removeRedundantAttributes": true,
32 | "removeScriptTypeAttributes": true,
33 | "removeStyleLinkTypeAttributes": true,
34 | "removeTagWhitespace": false,
35 | "sortAttributes": true,
36 | "sortClassName": true
37 | }
38 |
--------------------------------------------------------------------------------
/xo.config.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const globals = require('globals');
4 |
5 | module.exports = [
6 | {
7 | languageOptions: {
8 | ecmaVersion: 2020,
9 | sourceType: 'commonjs',
10 | globals: {
11 | ...globals.browser
12 | }
13 | },
14 | space: 2,
15 | rules: {
16 | '@stylistic/comma-dangle': [
17 | 'error',
18 | 'never'
19 | ],
20 | '@stylistic/object-curly-spacing': [
21 | 'error',
22 | 'always'
23 | ],
24 | '@stylistic/spaced-comment': 'off',
25 | '@stylistic/space-before-function-paren': [
26 | 'error',
27 | 'never'
28 | ],
29 | camelcase: [
30 | 'error',
31 | {
32 | properties: 'never'
33 | }
34 | ],
35 | 'no-negated-condition': 'off',
36 | 'capitalized-comments': 'off',
37 | 'default-case': 'off',
38 | 'prefer-template': 'error',
39 | 'unicorn/no-negated-condition': 'off',
40 | 'unicorn/prefer-global-this': 'off',
41 | 'unicorn/prefer-module': 'off',
42 | 'unicorn/prefer-top-level-await': 'off',
43 | 'unicorn/prevent-abbreviations': 'off'
44 | }
45 | }
46 | ];
47 |
--------------------------------------------------------------------------------
/.github/workflows/codeql.yml:
--------------------------------------------------------------------------------
1 | name: "CodeQL"
2 |
3 | on:
4 | push:
5 | branches:
6 | - master
7 | - "!dependabot/**"
8 | pull_request:
9 | branches:
10 | - master
11 | - "!dependabot/**"
12 | schedule:
13 | - cron: "0 0 * * 0"
14 | workflow_dispatch:
15 |
16 | jobs:
17 | analyze:
18 | name: Analyze
19 | runs-on: ubuntu-latest
20 | permissions:
21 | actions: read
22 | contents: read
23 | security-events: write
24 |
25 | steps:
26 | - name: Checkout repository
27 | uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
28 | with:
29 | persist-credentials: false
30 |
31 | - name: Initialize CodeQL
32 | uses: github/codeql-action/init@192325c86100d080feab897ff886c34abd4c83a3 # v3.30.3
33 | with:
34 | config-file: ./.github/codeql/codeql-config.yml
35 | languages: "javascript"
36 | queries: +security-and-quality
37 |
38 | - name: Autobuild
39 | uses: github/codeql-action/autobuild@192325c86100d080feab897ff886c34abd4c83a3 # v3.30.3
40 |
41 | - name: Perform CodeQL Analysis
42 | uses: github/codeql-action/analyze@192325c86100d080feab897ff886c34abd4c83a3 # v3.30.3
43 | with:
44 | category: "/language:javascript"
45 |
--------------------------------------------------------------------------------
/docs/_layouts/default.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | {% seo %}
9 |
10 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
25 |
26 |
Introducing the unofficial
27 |
GitHub buttons
28 |
Showcase your GitHub repo’s success with hotlinkable GitHub star, fork, sponsor, and follow buttons. Available in two sizes with up-to-date counts.
29 |
Made by @mdo . Available on GitHub . Licensed Apache 2 .
30 |
31 |
32 |
33 | {{ content }}
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/docs/_sass/_syntax.scss:
--------------------------------------------------------------------------------
1 | // stylelint-disable declaration-block-single-line-max-declarations
2 |
3 | .hll { background-color: #ffc; }
4 | .c { color: #727272; }
5 | .k { color: #069; }
6 | .o { color: #555; }
7 | .cm { color: #727272; }
8 | .cp { color: #008085; }
9 | .c1 { color: #727272; }
10 | .cs { color: #727272; }
11 | .gd { background-color: #fcc; border: 1px solid #c00; }
12 | .ge { font-style: italic; }
13 | .gr { color: #f00; }
14 | .gh { color: #030; }
15 | .gi { background-color: #cfc; border: 1px solid #0c0; }
16 | .go { color: #aaa; }
17 | .gp { color: #009; }
18 | .gu { color: #030; }
19 | .gt { color: #9c6; }
20 | .kc { color: #069; }
21 | .kd { color: #069; }
22 | .kn { color: #069; }
23 | .kp { color: #069; }
24 | .kr { color: #069; }
25 | .kt { color: #078; }
26 | .m { color: #bc511f; }
27 | .s { color: #d82d36; }
28 | .na { color: #006ee0; }
29 | .nb { color: #366; }
30 | .nc { color: #168174; }
31 | .no { color: #360; }
32 | .nd { color: #685fe3; }
33 | .ni { color: #727272; }
34 | .ne { color: #c00; }
35 | .nf { color: #b715f4; }
36 | .nl { color: #685fe3; }
37 | .nn { color: #007ca5; }
38 | .nt { color: #2f6f9f; }
39 | .nv { color: #033; }
40 | .ow { color: #000; }
41 | .w { color: #bbb; }
42 | .mf { color: #bc511f; }
43 | .mh { color: #bc511f; }
44 | .mi { color: #bc511f; }
45 | .mo { color: #bc511f; }
46 | .sb { color: #c30; }
47 | .sc { color: #c30; }
48 | .sd { font-style: italic; color: #c30; }
49 | .s2 { color: #c30; }
50 | .se { color: #c30; }
51 | .sh { color: #c30; }
52 | .si { color: #a00; }
53 | .sx { color: #c30; }
54 | .sr { color: #337e7e; }
55 | .s1 { color: #c30; }
56 | .ss { color: #fc3; }
57 | .bp { color: #366; }
58 | .vc { color: #033; }
59 | .vg { color: #033; }
60 | .vi { color: #033; }
61 | .il { color: #bc511f; }
62 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # GitHub Buttons [](https://github.com/mdo/github-buttons/actions/workflows/ci.yml?query=branch%3Amaster)
2 |
3 | Showcase your GitHub (repo's) success with these static buttons featuring links to your GitHub repo or profile page and up-to-date watch, fork, sponsor, and follower counts.
4 |
5 | To get started, checkout !
6 |
7 | ## Bug tracker
8 |
9 | Have a bug? Please create an issue here on GitHub at .
10 |
11 | ## Development
12 |
13 | Clone the project and install dependencies before getting started. GitHub Buttons require Node.js, Ruby, and Bundler for local development.
14 |
15 | ```shell
16 | npm i
17 | bundle i
18 | ```
19 |
20 | The GitHub buttons source code is split across three files in `src/`—the HTML, CSS, and JS. We use inline-source-cli and html-minifer to include it all in the compiled [`docs/github-btn.html`](docs/github-btn.html) file. To build this file:
21 |
22 | ```shell
23 | npm run build
24 | ```
25 |
26 | The `https://ghbtns.com/` site is built with Jekyll. After installing the dependencies, you can run a local server:
27 |
28 | ```shell
29 | bundle exec jekyll serve
30 | ```
31 |
32 | Open `http://127.0.0.1:4000` to browse locally.
33 |
34 | ## See also
35 |
36 | * [ntkme/github-buttons](https://buttons.github.io/)
37 |
38 | ## Twitter account
39 |
40 | Keep up to date on announcements and more by following Mark on Twitter, [@mdo](https://twitter.com/mdo).
41 |
42 | ## Author
43 |
44 | **Mark Otto**
45 |
46 | *
47 | *
48 |
49 | ## Copyright and license
50 |
51 | Copyright 2014-2022 Mark Otto. Released under the [Apache 2.0 License](LICENSE).
52 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 |
3 | on:
4 | push:
5 | branches-ignore:
6 | - "dependabot/**"
7 | tags:
8 | - "*"
9 | pull_request:
10 | workflow_dispatch:
11 |
12 | env:
13 | FORCE_COLOR: 2
14 | NODE: 22
15 | RUBY: "3.4"
16 |
17 | jobs:
18 | test:
19 | runs-on: ubuntu-latest
20 |
21 | steps:
22 | - name: Clone repository
23 | uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
24 | with:
25 | persist-credentials: false
26 |
27 | - name: Set up Node.js
28 | uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
29 | with:
30 | node-version: ${{ env.NODE }}
31 | cache: npm
32 |
33 | - name: Set up Ruby
34 | uses: ruby/setup-ruby@44511735964dcb71245e7e55f72539531f7bc0eb # v1.257.0
35 | with:
36 | ruby-version: ${{ env.RUBY }}
37 | bundler-cache: true
38 |
39 | - name: Install npm dependencies
40 | run: npm ci
41 |
42 | - name: Run tests
43 | run: npm test
44 |
45 | - name: Upload docs
46 | uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
47 | if: github.repository == 'mdo/github-buttons' && startsWith(github.ref, 'refs/tags/')
48 | with:
49 | name: docs
50 | path: ./_site/
51 | if-no-files-found: error
52 |
53 | deploy:
54 | runs-on: ubuntu-latest
55 | needs: test
56 | if: github.repository == 'mdo/github-buttons' && startsWith(github.ref, 'refs/tags/')
57 |
58 | steps:
59 | - name: Clone repository
60 | uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
61 | with:
62 | persist-credentials: false
63 |
64 | - name: Download docs
65 | uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
66 | with:
67 | name: docs
68 | path: ./_site/
69 |
70 | - name: Deploy
71 | uses: peaceiris/actions-gh-pages@4f9cc6602d3f66b9c108549d475ec49e8ef4d45e # v4.0.0
72 | with:
73 | allow_empty_commit: false
74 | personal_token: ${{ secrets.PERSONAL_TOKEN }}
75 | publish_branch: gh-pages
76 | publish_dir: ./_site/
77 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "github-buttons",
3 | "version": "4.2.3",
4 | "description": "Showcase your GitHub (repo's) success with these buttons",
5 | "private": true,
6 | "homepage": "https://ghbtns.com/",
7 | "author": "Mark Otto (https://github.com/mdo)",
8 | "license": "Apache-2.0",
9 | "repository": {
10 | "type": "git",
11 | "url": "git+https://github.com/mdo/github-buttons.git"
12 | },
13 | "bugs": {
14 | "url": "https://github.com/mdo/github-buttons/issues"
15 | },
16 | "keywords": [
17 | "github",
18 | "buttons",
19 | "iframe",
20 | "html"
21 | ],
22 | "scripts": {
23 | "start": "npm-run-all --parallel build docs-serve watch",
24 | "docs-build": "bundle exec jekyll build",
25 | "docs-serve": "bundle exec jekyll serve",
26 | "build": "inline-source --compress false --root src src/btn.html | html-minifier-terser --config-file html-minifier.json -o docs/github-btn.html",
27 | "dist": "npm run build",
28 | "stylelint": "stylelint \"**/*.{css,scss}\" --ignore-path .gitignore",
29 | "lockfile-lint": "lockfile-lint --allowed-hosts npm --allowed-schemes https: --empty-hostname false --type npm --path package-lock.json",
30 | "lint": "npm-run-all --continue-on-error --parallel lockfile-lint stylelint xo",
31 | "xo": "xo",
32 | "netlify": "cross-env-shell JEKYLL_ENV=netlify npm-run-all build docs-build",
33 | "test": "npm-run-all lint build docs-build",
34 | "watch": "npm-run-all --parallel watch-*",
35 | "watch-css": "chokidar \"{src,docs/_sass}/**/*.{css,scss}\" --initial --command \"npm run stylelint\"",
36 | "watch-js": "chokidar \"src/*.js\" --initial --command \"npm run xo\"",
37 | "watch-main": "chokidar src/ --initial --command \"npm run build\""
38 | },
39 | "devDependencies": {
40 | "chokidar-cli": "^3.0.0",
41 | "cross-env": "^10.0.0",
42 | "globals": "^16.4.0",
43 | "html-minifier-terser": "^7.2.0",
44 | "inline-source-cli": "^2.0.0",
45 | "lockfile-lint": "^4.14.1",
46 | "npm-run-all2": "^8.0.4",
47 | "stylelint": "^16.24.0",
48 | "stylelint-config-twbs-bootstrap": "^16.1.0",
49 | "xo": "^1.2.2"
50 | },
51 | "engines": {
52 | "node": ">=20"
53 | },
54 | "overrides": {
55 | "inline-source-cli": {
56 | "inline-source": "^8.0.2"
57 | }
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/Gemfile.lock:
--------------------------------------------------------------------------------
1 | GEM
2 | remote: https://rubygems.org/
3 | specs:
4 | addressable (2.8.7)
5 | public_suffix (>= 2.0.2, < 7.0)
6 | base64 (0.3.0)
7 | bigdecimal (3.2.3)
8 | colorator (1.1.0)
9 | concurrent-ruby (1.3.5)
10 | csv (3.3.5)
11 | em-websocket (0.5.3)
12 | eventmachine (>= 0.12.9)
13 | http_parser.rb (~> 0)
14 | eventmachine (1.2.7)
15 | ffi (1.17.2)
16 | ffi (1.17.2-x64-mingw-ucrt)
17 | forwardable-extended (2.6.0)
18 | google-protobuf (4.32.1)
19 | bigdecimal
20 | rake (>= 13)
21 | google-protobuf (4.32.1-x64-mingw-ucrt)
22 | bigdecimal
23 | rake (>= 13)
24 | http_parser.rb (0.8.0)
25 | i18n (1.14.7)
26 | concurrent-ruby (~> 1.0)
27 | jekyll (4.4.1)
28 | addressable (~> 2.4)
29 | base64 (~> 0.2)
30 | colorator (~> 1.0)
31 | csv (~> 3.0)
32 | em-websocket (~> 0.5)
33 | i18n (~> 1.0)
34 | jekyll-sass-converter (>= 2.0, < 4.0)
35 | jekyll-watch (~> 2.0)
36 | json (~> 2.6)
37 | kramdown (~> 2.3, >= 2.3.1)
38 | kramdown-parser-gfm (~> 1.0)
39 | liquid (~> 4.0)
40 | mercenary (~> 0.3, >= 0.3.6)
41 | pathutil (~> 0.9)
42 | rouge (>= 3.0, < 5.0)
43 | safe_yaml (~> 1.0)
44 | terminal-table (>= 1.8, < 4.0)
45 | webrick (~> 1.7)
46 | jekyll-sass-converter (3.1.0)
47 | sass-embedded (~> 1.75)
48 | jekyll-seo-tag (2.8.0)
49 | jekyll (>= 3.8, < 5.0)
50 | jekyll-sitemap (1.4.0)
51 | jekyll (>= 3.7, < 5.0)
52 | jekyll-watch (2.2.1)
53 | listen (~> 3.0)
54 | json (2.13.2)
55 | kramdown (2.5.1)
56 | rexml (>= 3.3.9)
57 | kramdown-parser-gfm (1.1.0)
58 | kramdown (~> 2.0)
59 | liquid (4.0.4)
60 | listen (3.9.0)
61 | rb-fsevent (~> 0.10, >= 0.10.3)
62 | rb-inotify (~> 0.9, >= 0.9.10)
63 | mercenary (0.4.0)
64 | pathutil (0.16.2)
65 | forwardable-extended (~> 2.6)
66 | public_suffix (6.0.2)
67 | rake (13.3.0)
68 | rb-fsevent (0.11.2)
69 | rb-inotify (0.11.1)
70 | ffi (~> 1.0)
71 | rexml (3.4.4)
72 | rouge (4.6.0)
73 | safe_yaml (1.0.5)
74 | sass-embedded (1.92.1)
75 | google-protobuf (~> 4.31)
76 | rake (>= 13)
77 | sass-embedded (1.92.1-x64-mingw-ucrt)
78 | google-protobuf (~> 4.31)
79 | terminal-table (3.0.2)
80 | unicode-display_width (>= 1.1.1, < 3)
81 | unicode-display_width (2.6.0)
82 | wdm (0.2.0)
83 | webrick (1.9.1)
84 |
85 | PLATFORMS
86 | ruby
87 | x64-mingw-ucrt
88 |
89 | DEPENDENCIES
90 | jekyll (~> 4.4.1)
91 | jekyll-seo-tag (~> 2.8.0)
92 | jekyll-sitemap (~> 1.4.0)
93 | wdm (~> 0.2.0)
94 |
95 | BUNDLED WITH
96 | 2.7.2
97 |
--------------------------------------------------------------------------------
/src/styles.css:
--------------------------------------------------------------------------------
1 | body {
2 | padding: 0;
3 | margin: 0;
4 | overflow: hidden;
5 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif;
6 | font-size: 11px;
7 | font-weight: 700;
8 | line-height: 14px;
9 | }
10 | .github-btn {
11 | height: 20px;
12 | overflow: hidden;
13 | }
14 | .gh-btn,
15 | .gh-count,
16 | .gh-ico {
17 | float: left;
18 | }
19 | .gh-btn,
20 | .gh-count {
21 | padding: 2px 5px 2px 4px;
22 | color: #333;
23 | text-decoration: none;
24 | white-space: nowrap;
25 | cursor: pointer;
26 | border-radius: 3px;
27 | }
28 | .gh-btn {
29 | background-color: #eee;
30 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #fcfcfc), to(#eee));
31 | background-image: linear-gradient(to bottom, #fcfcfc 0, #eee 100%);
32 | background-repeat: no-repeat;
33 | border: 1px solid #d5d5d5;
34 | }
35 | .gh-btn:hover,
36 | .gh-btn:focus {
37 | text-decoration: none;
38 | background-color: #ddd;
39 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #eee), to(#ddd));
40 | background-image: linear-gradient(to bottom, #eee 0, #ddd 100%);
41 | border-color: #ccc;
42 | }
43 | .gh-btn:active {
44 | background-color: #dcdcdc;
45 | background-image: none;
46 | border-color: #b5b5b5;
47 | box-shadow: inset 0 2px 4px rgba(0, 0, 0, .15);
48 | }
49 | .gh-ico {
50 | width: 14px;
51 | height: 14px;
52 | margin-right: 4px;
53 | background: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='40' height='40' viewBox='12 12 40 40'%3e%3cpath fill='%23333' d='M32 13.4c-10.5 0-19 8.5-19 19 0 8.4 5.5 15.5 13 18 1 .2 1.3-.4 1.3-.9v-3.2c-5.3 1.1-6.4-2.6-6.4-2.6-.9-2.1-2.1-2.7-2.1-2.7-1.7-1.2.1-1.1.1-1.1 1.9.1 2.9 2 2.9 2 1.7 2.9 4.5 2.1 5.5 1.6.2-1.2.7-2.1 1.2-2.6-4.2-.5-8.7-2.1-8.7-9.4 0-2.1.7-3.7 2-5.1-.2-.5-.8-2.4.2-5 0 0 1.6-.5 5.2 2 1.5-.4 3.1-.7 4.8-.7 1.6 0 3.3.2 4.7.7 3.6-2.4 5.2-2 5.2-2 1 2.6.4 4.6.2 5 1.2 1.3 2 3 2 5.1 0 7.3-4.5 8.9-8.7 9.4.7.6 1.3 1.7 1.3 3.5v5.2c0 .5.4 1.1 1.3.9 7.5-2.6 13-9.7 13-18.1 0-10.5-8.5-19-19-19z'/%3e%3c/svg%3e") 0 0 / 100% 100% no-repeat;
54 | }
55 | .gh-count {
56 | position: relative;
57 | display: none; /* hidden to start */
58 | margin-left: 4px;
59 | background-color: #fafafa;
60 | border: 1px solid #d4d4d4;
61 | }
62 | .gh-count:hover,
63 | .gh-count:focus {
64 | color: #0366d6;
65 | }
66 | .gh-count::before,
67 | .gh-count::after {
68 | position: absolute;
69 | display: inline-block;
70 | width: 0;
71 | height: 0;
72 | content: "";
73 | border-color: transparent;
74 | border-style: solid;
75 | }
76 | .gh-count::before {
77 | top: 50%;
78 | left: -3px;
79 | margin-top: -4px;
80 | border-width: 4px 4px 4px 0;
81 | border-right-color: #fafafa;
82 | }
83 | .gh-count::after {
84 | top: 50%;
85 | left: -4px;
86 | z-index: -1;
87 | margin-top: -5px;
88 | border-width: 5px 5px 5px 0;
89 | border-right-color: #d4d4d4;
90 | }
91 | .github-btn-large {
92 | height: 30px;
93 | }
94 | .github-btn-large .gh-btn,
95 | .github-btn-large .gh-count {
96 | padding: 3px 10px 3px 8px;
97 | font-size: 16px;
98 | line-height: 22px;
99 | border-radius: 4px;
100 | }
101 | .github-btn-large .gh-ico {
102 | width: 20px;
103 | height: 20px;
104 | }
105 | .github-btn-large .gh-count {
106 | margin-left: 6px;
107 | }
108 | .github-btn-large .gh-count::before {
109 | left: -5px;
110 | margin-top: -6px;
111 | border-width: 6px 6px 6px 0;
112 | }
113 | .github-btn-large .gh-count::after {
114 | left: -6px;
115 | margin-top: -7px;
116 | border-width: 7px 7px 7px 0;
117 | }
118 | .no-text .gh-ico {
119 | margin-right: 0;
120 | }
121 |
--------------------------------------------------------------------------------
/docs/_sass/_page.scss:
--------------------------------------------------------------------------------
1 | /*
2 | * Reset
3 | */
4 |
5 | * {
6 | -webkit-box-sizing: border-box;
7 | -moz-box-sizing: border-box;
8 | box-sizing: border-box;
9 | }
10 |
11 | html {
12 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif;
13 | font-size: 16px;
14 | line-height: 1.5;
15 | }
16 |
17 | body {
18 | padding: 1.5rem 1.5rem 3rem;
19 | margin: 0;
20 | font-size: 1rem;
21 | color: #333;
22 | background-color: #fff;
23 | }
24 |
25 | iframe {
26 | overflow: hidden;
27 | border: 0;
28 | }
29 |
30 | h1,
31 | h2 {
32 | margin-top: 0;
33 | line-height: 1;
34 | text-rendering: optimizelegibility;
35 | }
36 |
37 | h1 {
38 | margin-bottom: .5rem;
39 | font-size: 3rem;
40 | }
41 |
42 | h2 {
43 | margin-top: 2rem;
44 | margin-bottom: 1rem;
45 | }
46 |
47 | h3 {
48 | margin-top: 2rem;
49 | margin-bottom: .5rem;
50 | }
51 |
52 | p {
53 | margin-top: 0;
54 | margin-bottom: 1rem;
55 | }
56 |
57 | h1 + p {
58 | font-size: 1.25rem;
59 | color: #555;
60 | }
61 |
62 | a {
63 | color: #0366d6;
64 | text-decoration: none;
65 |
66 | &:hover {
67 | text-decoration: underline;
68 | }
69 | }
70 |
71 | table {
72 | width: 100%;
73 | border-collapse: collapse;
74 | }
75 |
76 | th,
77 | td {
78 | padding: .5rem;
79 | font-size: 90%;
80 | vertical-align: top;
81 | border: 1px solid #eee;
82 | }
83 |
84 | th {
85 | background-color: #f5f5f5;
86 | }
87 |
88 | .deprecated {
89 | display: inline-block;
90 | padding: .25rem .5rem;
91 | font-size: 75%;
92 | font-weight: 700;
93 | line-height: 1.6;
94 | color: #fff;
95 | background-color: #e5271c;
96 | border-radius: .2rem;
97 | }
98 |
99 | /*
100 | * Code
101 | */
102 |
103 | code,
104 | pre {
105 | font-family: Menlo, "Courier New", monospace;
106 | font-size: 95%;
107 | }
108 |
109 | code {
110 | padding: 2px 4px;
111 | font-size: 85%;
112 | color: #d53049;
113 | background-color: #f7f7f9;
114 | border-radius: .2rem;
115 | }
116 |
117 | pre {
118 | display: block;
119 | margin: 0 0 1rem;
120 | line-height: 1.4;
121 | white-space: pre;
122 | white-space: pre-wrap;
123 |
124 | code {
125 | padding: 0;
126 | color: inherit;
127 | background-color: transparent;
128 | border: 0;
129 | }
130 | }
131 |
132 | .highlight {
133 | padding: 1rem;
134 | margin: 0 0 1rem;
135 | background-color: #f7f7f9;
136 |
137 | pre {
138 | margin-bottom: 0;
139 | word-wrap: break-word;
140 | }
141 |
142 | + .highlight {
143 | margin-top: 1rem;
144 | }
145 | }
146 |
147 | /*
148 | * Download button
149 | */
150 |
151 | .btn {
152 | display: inline-block;
153 | padding: .5rem 1.25rem;
154 | font-weight: 700;
155 | color: #fff;
156 | text-decoration: none;
157 | background-color: #0366d6;
158 | border: 1px solid #0366d6;
159 | border-radius: 6px;
160 |
161 | &:hover {
162 | text-decoration: none;
163 | background-color: #005cc5;
164 | }
165 |
166 | &:active {
167 | border-color: #005cc5;
168 | box-shadow: inset 0 5px 10px rgba(0, 0, 0, .2);
169 | }
170 | }
171 |
172 | /*
173 | * Masthead
174 | */
175 |
176 | .tweet-button {
177 | height: 30px;
178 | overflow: hidden;
179 |
180 | + p {
181 | margin-top: 1rem;
182 | color: #767676;
183 | }
184 | }
185 |
186 |
187 | /*
188 | * Grid and columns
189 | */
190 |
191 | .container {
192 | max-width: 40rem;
193 | margin-right: auto;
194 | margin-left: auto;
195 | }
196 |
197 |
198 | /*
199 | * Misc
200 | */
201 |
202 | hr {
203 | display: block;
204 | width: 7rem;
205 | height: 1px;
206 | margin: 2.5rem 0;
207 | background-color: #eee;
208 | border: 0;
209 | }
210 |
211 | /*
212 | * Embed spacing
213 | */
214 |
215 | .example {
216 | margin-bottom: 1rem;
217 | overflow: auto;
218 |
219 | iframe {
220 | display: block;
221 |
222 | + iframe {
223 | margin-top: 1rem;
224 | }
225 | }
226 | }
227 |
228 | @media (min-width: 34em) {
229 | .example {
230 | display: inline-block;
231 | line-height: 30px;
232 |
233 | iframe {
234 | float: left;
235 |
236 | + iframe {
237 | margin-top: 5px;
238 | margin-left: 1rem;
239 | }
240 | }
241 | }
242 | }
243 |
244 | // stylelint-disable-next-line selector-max-id
245 | #markdown-toc li {
246 | margin-bottom: .25rem;
247 | }
248 |
--------------------------------------------------------------------------------
/docs/github-btn.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/js.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | 'use strict';
3 |
4 | const allowedQueryParams = new Set(['user', 'repo', 'type', 'count', 'size', 'text', 'v']);
5 |
6 | function getUrlParameters() {
7 | // TODO: Replace with URLSearchParams later
8 | const hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
9 | const parameters = new Map();
10 |
11 | for (const hash of hashes) {
12 | const [parameter, value] = hash.split('=');
13 |
14 | if (allowedQueryParams.has(parameter)) {
15 | parameters.set(parameter, value);
16 | }
17 | }
18 |
19 | return parameters;
20 | }
21 |
22 | // Add commas to numbers
23 | function addCommas(n) {
24 | // eslint-disable-next-line unicorn/prefer-string-replace-all
25 | return String(n).replace(/(\d)(?=(\d{3})+$)/g, '$1,');
26 | }
27 |
28 | function jsonp(path) {
29 | const script = document.createElement('script');
30 |
31 | script.src = `${path}?callback=callback`;
32 | document.head.insertBefore(script, document.head.firstChild);
33 | }
34 |
35 | // Parameters
36 | const parameters = getUrlParameters();
37 | const user = parameters.get('user');
38 | const repo = parameters.get('repo');
39 | const type = parameters.get('type');
40 | const count = parameters.get('count');
41 | const size = parameters.get('size');
42 | const noText = parameters.get('text');
43 | const v = parameters.get('v');
44 |
45 | // Elements
46 | const button = document.querySelector('.gh-btn');
47 | const mainButton = document.querySelector('.github-btn');
48 | const text = document.querySelector('.gh-text');
49 | const counter = document.querySelector('.gh-count');
50 |
51 | // Constants
52 | const LABEL_SUFFIX = 'on GitHub';
53 | const GITHUB_URL = 'https://github.com/';
54 | const API_URL = 'https://api.github.com/';
55 | const REPO_URL = `${GITHUB_URL + user}/${repo}`;
56 | const USER_REPO = `${user}/${repo}`;
57 |
58 | window.callback = function(obj) {
59 | if (obj.data.message === 'Not Found') {
60 | return;
61 | }
62 |
63 | switch (type) {
64 | case 'watch': {
65 | if (v === '2') {
66 | counter.textContent = obj.data.subscribers_count && addCommas(obj.data.subscribers_count);
67 | counter.setAttribute('aria-label', `${counter.textContent} watchers ${LABEL_SUFFIX}`);
68 | } else {
69 | counter.textContent = obj.data.stargazers_count && addCommas(obj.data.stargazers_count);
70 | counter.setAttribute('aria-label', `${counter.textContent} stargazers ${LABEL_SUFFIX}`);
71 | }
72 |
73 | break;
74 | }
75 |
76 | case 'star': {
77 | counter.textContent = obj.data.stargazers_count && addCommas(obj.data.stargazers_count);
78 | counter.setAttribute('aria-label', `${counter.textContent} stargazers ${LABEL_SUFFIX}`);
79 | break;
80 | }
81 |
82 | case 'fork': {
83 | counter.textContent = obj.data.network_count && addCommas(obj.data.network_count);
84 | counter.setAttribute('aria-label', `${counter.textContent} forks ${LABEL_SUFFIX}`);
85 | break;
86 | }
87 |
88 | case 'follow': {
89 | counter.textContent = obj.data.followers && addCommas(obj.data.followers);
90 | counter.setAttribute('aria-label', `${counter.textContent} followers ${LABEL_SUFFIX}`);
91 | break;
92 | }
93 | }
94 |
95 | // Show the count if asked and if it's not empty
96 | if (count === 'true' && counter.textContent !== '') {
97 | counter.style.display = 'block';
98 | counter.removeAttribute('aria-hidden');
99 | }
100 | };
101 |
102 | // Set href to be URL for repo
103 | button.href = REPO_URL;
104 |
105 | let title;
106 |
107 | // Add the class, change the text label, set count link href
108 | switch (type) {
109 | case 'watch': {
110 | if (v === '2') {
111 | mainButton.classList.add('github-watchers');
112 | text.textContent = 'Watch';
113 | counter.href = `${REPO_URL}/watchers`;
114 | } else {
115 | mainButton.classList.add('github-stargazers');
116 | text.textContent = 'Star';
117 | counter.href = `${REPO_URL}/stargazers`;
118 | }
119 |
120 | title = `${text.textContent} ${USER_REPO}`;
121 | break;
122 | }
123 |
124 | case 'star': {
125 | mainButton.classList.add('github-stargazers');
126 | text.textContent = 'Star';
127 | counter.href = `${REPO_URL}/stargazers`;
128 | title = `${text.textContent} ${USER_REPO}`;
129 | break;
130 | }
131 |
132 | case 'fork': {
133 | mainButton.classList.add('github-forks');
134 | text.textContent = 'Fork';
135 | button.href = `${REPO_URL}/fork`;
136 | counter.href = `${REPO_URL}/network`;
137 | title = `${text.textContent} ${USER_REPO}`;
138 | break;
139 | }
140 |
141 | case 'follow': {
142 | mainButton.classList.add('github-me');
143 | text.textContent = `Follow @${user}`;
144 | button.href = GITHUB_URL + user;
145 | counter.href = `${GITHUB_URL + user}?tab=followers`;
146 | title = text.textContent;
147 | break;
148 | }
149 |
150 | case 'sponsor': {
151 | mainButton.classList.add('github-me');
152 | text.textContent = `Sponsor @${user}`;
153 | button.href = `${GITHUB_URL}sponsors/${user}`;
154 | title = text.textContent;
155 | break;
156 | }
157 | }
158 |
159 | if (noText === 'false') {
160 | button.classList.add('no-text');
161 | text.setAttribute('aria-hidden', true);
162 | text.style.display = 'none';
163 | text.textContent = '';
164 | }
165 |
166 | button.setAttribute('aria-label', `${title} ${LABEL_SUFFIX}`);
167 | document.title = `${title} ${LABEL_SUFFIX}`;
168 |
169 | // Change the size if requested
170 | if (size === 'large') {
171 | mainButton.classList.add('github-btn-large');
172 | }
173 |
174 | // If count is not requested or type is sponsor,
175 | // there's no need to make an API call
176 | if (count !== 'true' || type === 'sponsor' || noText === 'false') {
177 | return;
178 | }
179 |
180 | if (type === 'follow') {
181 | jsonp(`${API_URL}users/${user}`);
182 | } else {
183 | jsonp(`${API_URL}repos/${user}/${repo}`);
184 | }
185 | })();
186 |
--------------------------------------------------------------------------------
/docs/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | ---
4 |
5 | ## Contents
6 | {:.no_toc}
7 |
8 | * Comment to trigger ToC generation
9 | {:toc}
10 |
11 | ---
12 |
13 | ## Star
14 |
15 | {% capture example %}
16 |
17 |
18 |
19 | {% endcapture %}
20 | {% include example.html content=example %}
21 |
22 | ## Watch
23 |
24 | Originally, GitHub's Watch button was used for notification settings (today's Watch) and repository bookmarking (today's Star). In August 2012, [they split the functionality into two buttons](https://github.blog/2012-08-06-notifications-stars/), after these unofficial buttons were released.
25 |
26 | As such, for today's unofficial Watch button, **you must add `v=2` to the parameters**. If you don't, you'll get [the deprecated button](#deprecated).
27 |
28 | {% capture example %}
29 |
30 |
31 |
32 | {% endcapture %}
33 | {% include example.html content=example %}
34 |
35 | ## Fork
36 |
37 | {% capture example %}
38 |
39 |
40 |
41 | {% endcapture %}
42 | {% include example.html content=example %}
43 |
44 | ## Follow
45 |
46 | {% capture example %}
47 |
48 |
49 |
50 | {% endcapture %}
51 | {% include example.html content=example %}
52 |
53 | ## Sponsor
54 |
55 | {% capture example %}
56 |
57 |
58 |
59 | {% endcapture %}
60 | {% include example.html content=example %}
61 |
62 | ## No text variant
63 |
64 | {% capture example %}
65 |
66 | {% endcapture %}
67 | {% include example.html content=example %}
68 |
69 | ---
70 |
71 | ## Available options
72 |
73 | ### SSL support
74 |
75 | Example buttons are shown with `https://` URLs. While they're hosted on GitHub Pages, the SSL option is provided via [Cloudflare's free Universal SSL](https://blog.cloudflare.com/introducing-universal-ssl/) offering.
76 |
77 | ### Required parameters
78 |
79 | You **must** declare a value for each of the following URL parameters:
80 |
81 | | Option | Description |
82 | | ------ | ----------- |
83 | | `user` | GitHub username that owns the repo/Username to sponsor |
84 | | `repo` | GitHub repository to pull the forks and watchers counts |
85 | | `type` | Type of button to show: `watch`, `fork`, `sponsor`, or `follow` |
86 |
87 | ### Optional parameters
88 |
89 | The following URL parameters are **not** required. Add them as you wish.
90 |
91 | | Option | Description |
92 | | ------ | ----------- |
93 | | `count` | Show the optional watchers or forks count: *none* by default or `true` |
94 | | `size` | Optional flag for using a larger button: *none* by default or `large` |
95 | | `text` | Optional flag for hiding the text: *none* by default or `false` |
96 |
97 | ---
98 |
99 | Deprecated
100 |
101 | ## Original Watch, aka Star
102 |
103 | With the button split in August 2012, GitHub's API continued to return the Star count for old Watch buttons. Thus, the original unofficial Watch button returns a makeshift Star button.
104 |
105 | This deprecated button is still around to avoid breaking every site that currently utilizes these embeds.
106 |
107 | {% capture example %}
108 |
109 |
110 |
111 | {% endcapture %}
112 | {% include example.html content=example %}
113 |
114 | ---
115 |
116 | ## Limitations
117 |
118 | For these first versions, functionality is limited and some concessions made:
119 |
120 | * Mind the GitHub API rate limit which is 60 requests per hour for unauthenticated users.
121 | * Width and height must be specified for all buttons (which actually adds some fun control for people like me).
122 | * Make sure you adapt the snippets to your needs by modifying the parameters and the title.
123 | * All attributes must be passed through via URL parameters.
124 | * CSS and JavaScript are all included in the same HTML file to reduce complexity.
125 | * We include the `frameborder` and `scrolling` attributes by default since we cannot know your setup, but you can optionally remove them and set them yourself via CSS:
126 |
127 | {% highlight css %}
128 | iframe {
129 | overflow: hidden;
130 | border: 0;
131 | }
132 | {% endhighlight %}
133 |
134 | More refinement and functionality is planned with open-sourcing—any help is always appreciated!
135 |
136 | ---
137 |
138 | ## Open source
139 |
140 | The unofficial GitHub buttons are available on GitHub for downloading, forking, or contributing.
141 |
142 |
143 |
144 |
145 |
146 |
147 | View on GitHub
148 |
149 | ---
150 |
151 | ❤️
152 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright 2011 Mark Otto
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------