mirror of
https://github.com/Aviortheking/codestats-readme.git
synced 2025-04-22 02:32:09 +00:00
Added History Card
Signed-off-by: Florian Bouillon <florian.bouillon@delta-wings.net>
This commit is contained in:
parent
383ff46c05
commit
332be009cf
71
.eslintrc.json
Normal file
71
.eslintrc.json
Normal file
@ -0,0 +1,71 @@
|
||||
{
|
||||
"env": {
|
||||
"browser": true,
|
||||
"es6": true,
|
||||
"node": true
|
||||
},
|
||||
"root": true,
|
||||
"ignorePatterns": [
|
||||
"out",
|
||||
".next",
|
||||
"node_modules",
|
||||
"*.js"
|
||||
],
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:react/recommended",
|
||||
"google",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"plugin:sonarjs/recommended",
|
||||
"plugin:import/errors",
|
||||
"plugin:import/warnings"
|
||||
],
|
||||
"globals": {
|
||||
"Atomics": "readonly",
|
||||
"SharedArrayBuffer": "readonly"
|
||||
},
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
"project": "tsconfig.json",
|
||||
"ecmaFeatures": {
|
||||
"jsx": true
|
||||
},
|
||||
"ecmaVersion": 2018,
|
||||
"sourceType": "module"
|
||||
},
|
||||
"settings": {
|
||||
"react": {
|
||||
"version": "detect"
|
||||
},
|
||||
"import/parsers": {
|
||||
"@typescript-eslint/parser": [".ts", ".tsx"]
|
||||
},
|
||||
"import/resolver": {
|
||||
"typescript": {
|
||||
"alwaysTryTypes": true // always try to resolve types under `<root>@types` directory even it doesn't contain any source code, like `@types/unist`
|
||||
}
|
||||
}
|
||||
},
|
||||
"plugins": [
|
||||
"react",
|
||||
"@typescript-eslint",
|
||||
"sonarjs",
|
||||
"import"
|
||||
],
|
||||
"rules": {
|
||||
"indent": ["error", "tab"],
|
||||
"@typescript-eslint/quotes": ["error", "single", { "avoidEscape": true }],
|
||||
"semi": ["error", "never"],
|
||||
"no-tabs": "off",
|
||||
"require-jsdoc": "off",
|
||||
"no-invalid-this": "off",
|
||||
"@typescript-eslint/explicit-module-boundary-types": "off",
|
||||
"max-len": ["warn", { "code": 120 }],
|
||||
"object-curly-spacing": ["error", "always"],
|
||||
"comma-dangle": ["error", "never"],
|
||||
"padded-blocks": ["error", { "classes": "always" }],
|
||||
"import/order": ["error"],
|
||||
"import/no-named-as-default-member": "off",
|
||||
"import/no-named-as-default": "off"
|
||||
}
|
||||
}
|
106
.github/logo.svg
vendored
106
.github/logo.svg
vendored
@ -1,105 +1 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
|
||||
sodipodi:docname="68747470733a2f2f7265732e636c6f7564696e6172792e636f6d2f616e7572616768617a72612f696d6167652f75706c6f61642f76313539343930383234322f6c6f676f5f636373776d652e737667.svg"
|
||||
id="svg21"
|
||||
version="1.1"
|
||||
fill="none"
|
||||
viewBox="0 0 39 39"
|
||||
height="39"
|
||||
width="39">
|
||||
<metadata
|
||||
id="metadata25">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<sodipodi:namedview
|
||||
inkscape:current-layer="svg21"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-x="0"
|
||||
inkscape:cy="16.453588"
|
||||
inkscape:cx="9.4393523"
|
||||
inkscape:zoom="13.852041"
|
||||
showgrid="false"
|
||||
id="namedview23"
|
||||
inkscape:window-height="1048"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="0"
|
||||
guidetolerance="10"
|
||||
gridtolerance="10"
|
||||
objecttolerance="10"
|
||||
borderopacity="1"
|
||||
bordercolor="#666666"
|
||||
pagecolor="#ffffff" />
|
||||
<g
|
||||
id="g14"
|
||||
clip-path="url(#clip0)">
|
||||
<circle
|
||||
id="circle2"
|
||||
fill="#D5E5FA"
|
||||
r="19.5"
|
||||
cy="19.5"
|
||||
cx="19.5" />
|
||||
<path
|
||||
id="path4"
|
||||
fill="#5094F0"
|
||||
d="M19.5 3.05176e-05C22.993 3.05592e-05 26.4219 0.938272 29.4282 2.71669C32.4346 4.49511 34.9081 7.04841 36.5901 10.1097C38.2722 13.171 39.1011 16.628 38.9902 20.1192C38.8793 23.6104 37.8326 27.0078 35.9596 29.9561C34.0867 32.9045 31.4561 35.2957 28.3429 36.8797C25.2297 38.4637 21.7482 39.1824 18.2623 38.9607C14.7763 38.739 11.4139 37.585 8.52653 35.6194C5.63911 33.6537 3.33268 30.9486 1.84832 27.7867L4.5253 26.5299C5.78456 29.2123 7.7412 31.5072 10.1907 33.1748C12.6402 34.8423 15.4927 35.8213 18.45 36.0094C21.4073 36.1975 24.3608 35.5877 27.0018 34.244C29.6429 32.9002 31.8745 30.8717 33.4634 28.3704C35.0524 25.8692 35.9403 22.9871 36.0344 20.0253C36.1285 17.0635 35.4253 14.1309 33.9983 11.5338C32.5713 8.93678 30.473 6.7707 27.9225 5.26199C25.3721 3.75328 22.4633 2.95733 19.5 2.95732L19.5 3.05176e-05Z" />
|
||||
<circle
|
||||
id="circle6"
|
||||
fill="white"
|
||||
r="17.5"
|
||||
cy="19.5"
|
||||
cx="19.5" />
|
||||
<path
|
||||
id="path8"
|
||||
fill="#5094F0"
|
||||
d="M11 20.0477C11 19.4954 11.4477 19.0477 12 19.0477H14.5238C15.0761 19.0477 15.5238 19.4954 15.5238 20.0477V29.0001H14C12.3431 29.0001 11 27.6569 11 26.0001V20.0477Z" />
|
||||
<path
|
||||
id="path10"
|
||||
fill="#5094F0"
|
||||
d="M17.3334 15.5238C17.3334 14.9715 17.7811 14.5238 18.3334 14.5238H20.8572C21.4095 14.5238 21.8572 14.9715 21.8572 15.5238V29H17.3334V15.5238Z" />
|
||||
<path
|
||||
id="path12"
|
||||
fill="#5094F0"
|
||||
d="M23.6667 11C23.6667 10.4477 24.1144 10 24.6667 10H27.1905C27.7428 10 28.1905 10.4477 28.1905 11V26C28.1905 27.6569 26.8474 29 25.1905 29H23.6667V11Z" />
|
||||
</g>
|
||||
<defs
|
||||
id="defs19">
|
||||
<clipPath
|
||||
id="clip0">
|
||||
<rect
|
||||
id="rect16"
|
||||
fill="white"
|
||||
height="39"
|
||||
width="39" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
<g
|
||||
style="fill:#000000"
|
||||
transform="matrix(0.02702317,0,0,0.02702317,14.63437,28.064701)"
|
||||
id="g131">
|
||||
<path
|
||||
style="fill:#000000"
|
||||
d="M 174,81.741 V 109.25 C 161.913,104 133.5,93.5 109.789,94.6 85.93,95.707 67.617,101.901 54.93,116.502 c -12.689,14.603 -19.033,35.71 -19.033,63.326 0,27.524 6.344,48.585 19.033,63.186 12.687,14.603 30.974,21.901 54.859,21.901 12.127,0 41.461,-5.665 64.211,-19.115 v 29.528 c -8.75,2.672 -33.75,12.422 -65.891,12.818 -31.625,0.39 -56.538,-9.678 -74.731,-29.039 -18.193,-19.358 -27.29,-45.784 -27.29,-79.28 0,-33.587 9.097,-60.059 27.29,-79.42 C 51.571,81.049 76.491,72.155 108.109,71.368 133,70.75 155.808,77.431 174,81.741 Z m 167.423,0.264 v 27.569 c -10.729,-5.13 -20.852,-8.957 -30.368,-11.476 -9.516,-2.519 -18.707,-3.778 -27.569,-3.778 -15.395,0 -27.268,2.987 -35.616,8.957 -8.352,5.972 -12.525,14.462 -12.525,25.47 0,9.236 2.774,16.212 8.327,20.922 5.55,4.712 16.069,8.515 31.558,11.406 l 17.073,3.499 c 21.084,4.013 36.643,11.08 46.673,21.202 10.027,10.124 15.044,23.675 15.044,40.654 0,20.247 -6.787,35.595 -20.362,46.043 -13.575,10.45 -33.472,15.674 -59.688,15.674 -9.89,0 -20.41,-1.119 -31.558,-3.358 -11.15,-2.239 -22.695,-5.55 -34.637,-9.937 v -29.109 c 11.476,6.438 22.717,11.29 33.727,14.555 11.008,3.267 21.832,4.898 32.468,4.898 16.14,0 28.596,-3.171 37.366,-9.517 8.769,-6.344 13.155,-15.395 13.155,-27.149 0,-10.262 -3.149,-18.285 -9.447,-24.071 -6.297,-5.783 -16.632,-10.122 -30.998,-13.015 l -17.213,-3.358 c -21.086,-4.199 -36.341,-10.776 -45.763,-19.733 -9.425,-8.957 -14.135,-21.412 -14.135,-37.366 0,-18.473 6.508,-33.027 19.522,-43.664 13.015,-10.636 30.95,-15.954 53.81,-15.954 9.796,0 19.778,0.888 29.948,2.659 10.168,1.773 20.572,4.432 31.208,7.977 z"
|
||||
id="path118" />
|
||||
<path
|
||||
style="fill:#000000"
|
||||
d="m 86.199,153.037 c 0,-2.98 1.024,-5.495 3.074,-7.544 2.048,-2.048 4.563,-3.073 7.544,-3.073 3.034,0 5.561,1.011 7.584,3.034 2.022,2.023 3.034,4.55 3.034,7.584 0,3.034 -1.012,5.563 -3.034,7.584 -2.023,2.023 -4.551,3.034 -7.584,3.034 -2.981,0 -5.496,-1.024 -7.544,-3.074 -2.05,-2.049 -3.074,-4.564 -3.074,-7.545 z m 0,52.052 c 0,-2.979 1.024,-5.509 3.074,-7.584 2.048,-2.076 4.563,-3.113 7.544,-3.113 2.98,0 5.495,1.037 7.544,3.113 2.048,2.075 3.074,4.604 3.074,7.584 0,2.981 -1.012,5.496 -3.034,7.545 -2.023,2.048 -4.551,3.073 -7.584,3.073 -3.033,0 -5.562,-1.025 -7.584,-3.073 -2.024,-2.049 -3.034,-4.564 -3.034,-7.545 z m 54.936,-52.052 c 0,-2.98 1.024,-5.495 3.074,-7.544 2.048,-2.048 4.563,-3.073 7.544,-3.073 3.034,0 5.561,1.011 7.584,3.034 2.022,2.023 3.034,4.55 3.034,7.584 0,3.034 -1.012,5.563 -3.034,7.584 -2.023,2.023 -4.551,3.034 -7.584,3.034 -2.981,0 -5.496,-1.024 -7.544,-3.074 -2.05,-2.049 -3.074,-4.564 -3.074,-7.545 z m 0,52.052 c 0,-2.979 1.024,-5.509 3.074,-7.584 2.048,-2.076 4.563,-3.113 7.544,-3.113 2.98,0 5.495,1.037 7.544,3.113 2.048,2.075 3.074,4.604 3.074,7.584 0,2.981 -1.012,5.496 -3.034,7.545 -2.023,2.048 -4.551,3.073 -7.584,3.073 -3.033,0 -5.563,-1.025 -7.584,-3.073 -2.023,-2.049 -3.034,-4.564 -3.034,-7.545 z"
|
||||
id="path120" />
|
||||
</g>
|
||||
</svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" height="39" width="39"><g clip-path="url(#a)"><circle fill="#D5E5FA" r="19.5" cy="19.5" cx="19.5"/><path fill="#5094F0" d="M19.5 0A19.5 19.5 0 111.848 27.787l2.677-1.257A16.543 16.543 0 1019.5 2.957V0z"/><circle fill="#fff" r="17.5" cy="19.5" cx="19.5"/><path fill="#5094F0" d="M11 20.048a1 1 0 011-1h2.524a1 1 0 011 1V29H14a3 3 0 01-3-3v-5.952zM17.333 15.524a1 1 0 011-1h2.524a1 1 0 011 1V29h-4.524V15.524zM23.667 11a1 1 0 011-1h2.523a1 1 0 011 1v15a3 3 0 01-3 3h-1.523V11z"/></g><defs><clipPath id="a"><path fill="#fff" d="M0 0h39v39H0z"/></clipPath></defs><g fill="#000"><path d="M19.336 30.274v.743c-.326-.142-1.094-.426-1.735-.396-.645.03-1.14.197-1.482.592-.343.395-.515.965-.515 1.711 0 .744.172 1.313.515 1.708.343.394.837.592 1.482.592.328 0 1.12-.154 1.735-.517v.798c-.236.072-.912.336-1.78.346-.855.01-1.528-.261-2.02-.784-.491-.524-.737-1.238-.737-2.143 0-.907.246-1.623.737-2.146.492-.523 1.165-.763 2.02-.785.672-.016 1.289.164 1.78.28zm4.525.007v.745a4.714 4.714 0 00-.82-.31 2.908 2.908 0 00-.746-.102c-.416 0-.737.08-.962.242-.226.161-.339.39-.339.688 0 .25.075.438.225.565.15.128.434.23.853.308l.461.095c.57.108.99.3 1.262.573.27.274.406.64.406 1.099 0 .547-.183.961-.55 1.244-.367.282-.905.423-1.613.423a4.34 4.34 0 01-.853-.09 6.34 6.34 0 01-.936-.269v-.787c.31.174.614.306.912.394.297.088.59.132.877.132.436 0 .773-.086 1.01-.257s.355-.416.355-.734c0-.277-.085-.494-.255-.65-.17-.156-.45-.274-.838-.352l-.465-.09c-.57-.114-.982-.292-1.237-.534-.254-.242-.382-.578-.382-1.01 0-.499.176-.892.528-1.18.352-.287.836-.43 1.454-.43.265 0 .535.023.81.071.274.048.555.12.843.216z"/><path d="M16.964 32.2c0-.08.027-.148.083-.204a.277.277 0 01.204-.083.278.278 0 01.287.287.278.278 0 01-.287.287.277.277 0 01-.204-.083.277.277 0 01-.083-.204zm0 1.407a.28.28 0 01.083-.205.275.275 0 01.204-.084c.08 0 .148.028.204.084a.28.28 0 01.083.205.28.28 0 01-.082.204.276.276 0 01-.205.083.276.276 0 01-.205-.083.279.279 0 01-.082-.204zm1.484-1.407c0-.08.028-.148.083-.204a.277.277 0 01.204-.083.278.278 0 01.287.287.278.278 0 01-.287.287.277.277 0 01-.204-.083.277.277 0 01-.083-.204zm0 1.407a.28.28 0 01.083-.205.275.275 0 01.204-.084c.08 0 .149.028.204.084a.28.28 0 01.083.205.28.28 0 01-.082.204.276.276 0 01-.205.083.276.276 0 01-.205-.083.279.279 0 01-.082-.204z"/></g></svg>
|
Before Width: | Height: | Size: 6.5 KiB After Width: | Height: | Size: 2.3 KiB |
1
.gitignore
vendored
1
.gitignore
vendored
@ -5,3 +5,4 @@ package-lock.json
|
||||
*.lock
|
||||
.vscode/
|
||||
coverage
|
||||
yarn-error.log
|
||||
|
64
api/history.ts
Normal file
64
api/history.ts
Normal file
@ -0,0 +1,64 @@
|
||||
import { parseBoolean, prepareResponse, setCache, parseNumber, clampValue, parseArray} from '../src/common/utils'
|
||||
import { fetchHistory } from '../src/fetcher'
|
||||
import { Request, Response } from 'express'
|
||||
import ReactDOMServer from 'react-dom/server'
|
||||
import Error from '../src/components/Error'
|
||||
import HistoryCard from '../src/cards/HistoryCard'
|
||||
|
||||
export interface query {
|
||||
username: string
|
||||
hide_title?: string
|
||||
hide_border?: string
|
||||
title_color?: string
|
||||
bg_color?: string
|
||||
days_count?: string
|
||||
cache_seconds?: string
|
||||
width?: string
|
||||
height?: string
|
||||
hide?: string
|
||||
language_count?: string
|
||||
layout?: 'horizontal'
|
||||
}
|
||||
|
||||
export default async (req: Request<unknown, unknown, unknown, query>, res: Response) => {
|
||||
const {
|
||||
username,
|
||||
hide_title,
|
||||
hide_border,
|
||||
title_color,
|
||||
bg_color,
|
||||
days_count,
|
||||
cache_seconds,
|
||||
width,
|
||||
height,
|
||||
language_count,
|
||||
hide,
|
||||
layout
|
||||
} = req.query;
|
||||
|
||||
prepareResponse(res)
|
||||
|
||||
try {
|
||||
const data = await fetchHistory(username, clampValue(parseNumber(days_count) || 14, 1, 30));
|
||||
|
||||
setCache(res, parseInt(cache_seconds || ''))
|
||||
|
||||
return res.send(ReactDOMServer.renderToStaticMarkup(
|
||||
new HistoryCard(username, data, {
|
||||
hide_title: parseBoolean(hide_title),
|
||||
hide_border: parseBoolean(hide_border),
|
||||
title_color,
|
||||
bg_color,
|
||||
layout,
|
||||
language_count: parseNumber(language_count),
|
||||
width: parseNumber(width),
|
||||
height: clampValue(parseNumber(height) || 300, 200),
|
||||
hide: parseArray(hide)
|
||||
}).render()
|
||||
))
|
||||
} catch (err) {
|
||||
return res.send(
|
||||
ReactDOMServer.renderToStaticMarkup(new Error(err).render())
|
||||
);
|
||||
}
|
||||
};
|
49
api/index.ts
49
api/index.ts
@ -1,10 +1,10 @@
|
||||
import { renderError, parseBoolean, parseArray, CONSTANTS} from '../src/common/utils'
|
||||
import { parseBoolean, parseArray, prepareResponse, setCache} from '../src/common/utils'
|
||||
import { fetchProfile } from '../src/fetcher'
|
||||
import renderStatsCard from '../src/cards/profileCard'
|
||||
import blacklist from '../src/common/blacklist'
|
||||
import { Request, Response } from 'express';
|
||||
import ReactDOMServer from 'react-dom/server'
|
||||
import themes from '../themes';
|
||||
import themes from '../themes/themes.json';
|
||||
import ProfileCard from '../src/cards/ProfileCard';
|
||||
import Error from '../src/components/Error';
|
||||
|
||||
export interface query {
|
||||
username: string
|
||||
@ -36,39 +36,34 @@ export default async (req: Request<unknown, unknown, unknown, query>, res: Respo
|
||||
text_color,
|
||||
bg_color,
|
||||
theme,
|
||||
cache_seconds
|
||||
} = req.query;
|
||||
|
||||
res.setHeader("Content-Type", "image/svg+xml");
|
||||
|
||||
if (blacklist.includes(username)) {
|
||||
return res.send(renderError("Username is in blacklist"));
|
||||
}
|
||||
prepareResponse(res)
|
||||
|
||||
try {
|
||||
const data = await fetchProfile(username);
|
||||
|
||||
const cacheSeconds = CONSTANTS.TWO_HOURS
|
||||
|
||||
res.setHeader("Cache-Control", `public, max-age=${cacheSeconds}`);
|
||||
setCache(res, parseInt(cache_seconds || ''))
|
||||
|
||||
return res.send(ReactDOMServer.renderToStaticMarkup(
|
||||
renderStatsCard(data, {
|
||||
hide: parseArray(hide),
|
||||
show_icons: parseBoolean(show_icons),
|
||||
hide_title: parseBoolean(hide_title),
|
||||
hide_border: parseBoolean(hide_border),
|
||||
hide_rank: parseBoolean(hide_rank),
|
||||
line_height: line_height ? parseInt(line_height , 10) : undefined,
|
||||
title_color,
|
||||
icon_color,
|
||||
text_color,
|
||||
bg_color,
|
||||
theme,
|
||||
}))
|
||||
);
|
||||
new ProfileCard(data.username, data.xp, data.recentXp, {
|
||||
hide: parseArray(hide),
|
||||
show_icons: parseBoolean(show_icons),
|
||||
hide_title: parseBoolean(hide_title),
|
||||
hide_border: parseBoolean(hide_border),
|
||||
hide_rank: parseBoolean(hide_rank),
|
||||
line_height: line_height ? parseInt(line_height , 10) : undefined,
|
||||
title_color,
|
||||
icon_color,
|
||||
text_color,
|
||||
bg_color,
|
||||
theme,
|
||||
}).render()
|
||||
))
|
||||
} catch (err) {
|
||||
return res.send(
|
||||
ReactDOMServer.renderToStaticMarkup(renderError(err.message, err.secondaryMessage))
|
||||
ReactDOMServer.renderToStaticMarkup(new Error(err).render())
|
||||
);
|
||||
}
|
||||
};
|
||||
|
@ -1,10 +1,10 @@
|
||||
import { renderError, clampValue, parseBoolean, parseArray, CONSTANTS} from '../src/common/utils'
|
||||
import { parseBoolean, parseArray, prepareResponse, setCache, parseNumber} from '../src/common/utils'
|
||||
import { fetchTopLanguages } from '../src/fetcher'
|
||||
import renderTopLanguages from '../src/cards/top-languages-card'
|
||||
import blacklist from '../src/common/blacklist'
|
||||
import TopLanguagesCard from '../src/cards/TopLanguagesCard'
|
||||
import { Request, Response } from 'express';
|
||||
import ReactDOMServer from 'react-dom/server'
|
||||
import themes from '../themes';
|
||||
import themes from '../themes/themes.json';
|
||||
import Error from '../src/components/Error';
|
||||
|
||||
export interface query {
|
||||
username: string
|
||||
@ -33,47 +33,35 @@ export default async (req: Request<unknown, unknown, unknown, query>, res: Respo
|
||||
text_color,
|
||||
bg_color,
|
||||
language_count,
|
||||
show_level,
|
||||
theme,
|
||||
cache_seconds,
|
||||
layout,
|
||||
} = req.query;
|
||||
|
||||
res.setHeader("Content-Type", "image/svg+xml");
|
||||
|
||||
if (blacklist.includes(username)) {
|
||||
return res.send(renderError("Something went wrong"));
|
||||
}
|
||||
prepareResponse(res)
|
||||
|
||||
try {
|
||||
const topLangs = await fetchTopLanguages(username);
|
||||
const topLangs = await fetchTopLanguages(username)
|
||||
|
||||
const cacheSeconds = clampValue(
|
||||
parseInt(cache_seconds || CONSTANTS.TWO_HOURS + '', 10),
|
||||
CONSTANTS.TWO_HOURS,
|
||||
CONSTANTS.ONE_DAY
|
||||
);
|
||||
|
||||
res.setHeader("Cache-Control", `public, max-age=${cacheSeconds}`);
|
||||
setCache(res, parseInt(cache_seconds || ''))
|
||||
|
||||
return res.send(ReactDOMServer.renderToStaticMarkup(
|
||||
renderTopLanguages(topLangs, {
|
||||
hide_title: parseBoolean(hide_title),
|
||||
hide_border: parseBoolean(hide_border),
|
||||
card_width: parseInt(card_width || '', 10),
|
||||
hide: parseArray(hide),
|
||||
language_count: parseInt(language_count || '6'),
|
||||
title_color,
|
||||
text_color,
|
||||
bg_color,
|
||||
show_level,
|
||||
theme,
|
||||
layout,
|
||||
}))
|
||||
);
|
||||
new TopLanguagesCard(username, topLangs.langs, {
|
||||
hide: parseArray(hide),
|
||||
language_count: parseNumber(language_count),
|
||||
card_width: parseNumber(card_width),
|
||||
layout,
|
||||
text_color,
|
||||
theme,
|
||||
title_color,
|
||||
bg_color,
|
||||
hide_border: parseBoolean(hide_border),
|
||||
hide_title: parseBoolean(hide_title)
|
||||
}).render()
|
||||
))
|
||||
} catch (err) {
|
||||
return res.send(
|
||||
ReactDOMServer.renderToStaticMarkup(renderError(err.message, err.secondaryMessage))
|
||||
);
|
||||
ReactDOMServer.renderToStaticMarkup(new Error(err).render())
|
||||
)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
13
codecov.yml
13
codecov.yml
@ -1,13 +0,0 @@
|
||||
codecov:
|
||||
require_ci_to_pass: yes
|
||||
|
||||
coverage:
|
||||
precision: 2
|
||||
round: down
|
||||
range: "70...100"
|
||||
|
||||
status:
|
||||
project:
|
||||
default:
|
||||
threshold: 5
|
||||
patch: false
|
@ -1,345 +0,0 @@
|
||||
<p align="center">
|
||||
<img width="100px" src="https://res.cloudinary.com/anuraghazra/image/upload/v1594908242/logo_ccswme.svg" align="center" alt="GitHub Readme Stats" />
|
||||
<h2 align="center">GitHub Readme Stats</h2>
|
||||
<p align="center">在你的 README 中获取动态生成的 GitHub 统计信息!</p>
|
||||
</p>
|
||||
<p align="center">
|
||||
<a href="https://github.com/anuraghazra/github-readme-stats/actions">
|
||||
<img alt="Tests Passing" src="https://github.com/anuraghazra/github-readme-stats/workflows/Test/badge.svg" />
|
||||
</a>
|
||||
<a href="https://codecov.io/gh/anuraghazra/github-readme-stats">
|
||||
<img src="https://codecov.io/gh/anuraghazra/github-readme-stats/branch/master/graph/badge.svg" />
|
||||
</a>
|
||||
<a href="https://github.com/anuraghazra/github-readme-stats/issues">
|
||||
<img alt="Issues" src="https://img.shields.io/github/issues/anuraghazra/github-readme-stats?color=0088ff" />
|
||||
</a>
|
||||
<a href="https://github.com/anuraghazra/github-readme-stats/pulls">
|
||||
<img alt="GitHub pull requests" src="https://img.shields.io/github/issues-pr/anuraghazra/github-readme-stats?color=0088ff" />
|
||||
</a>
|
||||
<br />
|
||||
<br />
|
||||
<a href="https://a.paddle.com/v2/click/16413/119403?link=1227">
|
||||
<img src="https://img.shields.io/badge/Supported%20by-VSCode%20Power%20User%20%E2%86%92-gray.svg?colorA=655BE1&colorB=4F44D6&style=for-the-badge"/>
|
||||
</a>
|
||||
<a href="https://a.paddle.com/v2/click/16413/119403?link=2345">
|
||||
<img src="https://img.shields.io/badge/Supported%20by-Node%20Cli.com%20%E2%86%92-gray.svg?colorA=61c265&colorB=4CAF50&style=for-the-badge"/>
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="#demo">查看 Demo</a>
|
||||
·
|
||||
<a href="https://github.com/anuraghazra/github-readme-stats/issues/new/choose">报告 Bug</a>
|
||||
·
|
||||
<a href="https://github.com/anuraghazra/github-readme-stats/issues/new/choose">请求增加功能</a>
|
||||
</p>
|
||||
<p align="center">
|
||||
<a href="/docs/readme_fr.md">Français</a>
|
||||
·
|
||||
<a href="/docs/readme_cn.md">简体中文</a>
|
||||
·
|
||||
<a href="/docs/readme_es.md">Español</a>
|
||||
·
|
||||
<a href="/docs/readme_de.md">Deutsch</a>
|
||||
·
|
||||
<a href="/docs/readme_ja.md">日本語</a>
|
||||
·
|
||||
<a href="/docs/readme_pt-BR.md">Português Brasileiro</a>
|
||||
·
|
||||
<a href="/docs/readme_it.md">Italiano</a>
|
||||
·
|
||||
<a href="/docs/readme_kr.md">한국어</a>
|
||||
</p>
|
||||
</p>
|
||||
<p align="center">喜欢这个项目?请考虑<a href="https://www.paypal.me/anuraghazra">捐赠</a>来帮助它完善!
|
||||
|
||||
# 特性
|
||||
|
||||
- [GitHub 统计卡片](#GitHub-统计卡片)
|
||||
- [GitHub 更多置顶](#GitHub-更多置顶)
|
||||
- [热门语言卡片](#热门语言卡片)
|
||||
- [主题](#主题)
|
||||
- [自定义](#自定义)
|
||||
- [自己部署](#自己部署)
|
||||
|
||||
# GitHub 统计卡片
|
||||
|
||||
将这行代码复制到你的 markdown 文件中,就是如此简单!
|
||||
|
||||
更改 `?username=` 的值为你的 GitHub 用户名。
|
||||
|
||||
```md
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
```
|
||||
|
||||
_注: 等级基于用户的统计信息计算得出,详见 [src/calculateRank.js](../src/calculateRank.js)_
|
||||
|
||||
### 隐藏指定统计
|
||||
|
||||
想要隐藏指定统计信息,你可以调用参数 `?hide=`,其值用 `,` 分隔。
|
||||
|
||||
> 选项:`&hide=stars,commits,prs,issues,contribs`
|
||||
|
||||
```md
|
||||

|
||||
```
|
||||
|
||||
### 将私人项目贡献添加到总提交计数中
|
||||
|
||||
你可以使用参数 `?count_private=true` 把私人贡献计数添加到总提交计数中。
|
||||
|
||||
_注:如果你是自己部署本项目,私人贡献将会默认被计数,如果不是自己部署,你需要分享你的私人贡献计数。_
|
||||
|
||||
> 选项: `&count_private=true`
|
||||
|
||||
```md
|
||||

|
||||
```
|
||||
|
||||
### 显示图标
|
||||
|
||||
如果想要显示图标,你可以调用 `show_icons=true` 参数,像这样:
|
||||
|
||||
```md
|
||||

|
||||
```
|
||||
|
||||
### 主题
|
||||
|
||||
你可以通过现有的主题进行卡片个性化,省去[手动自定义](#自定义)的麻烦。
|
||||
|
||||
通过调用 `?theme=THEME_NAME` 参数,像这样:
|
||||
|
||||
```md
|
||||

|
||||
```
|
||||
|
||||
#### 所有现有主题
|
||||
|
||||
dark, radical, merko, gruvbox, tokyonight, onedark, cobalt, synthwave, highcontrast, dracula
|
||||
|
||||
<img src="https://res.cloudinary.com/anuraghazra/image/upload/v1595174536/grs-themes_l4ynja.png" alt="GitHub Readme Stat Themes" width="600px"/>
|
||||
|
||||
你可以预览[所有可用主题](../themes/README.md)或者签出[主题配置文件](../themes/index.js), 而且如果你喜欢, **你也可以贡献新的主题** :D
|
||||
|
||||
### 自定义
|
||||
|
||||
你可以通过使用 URL 参数的方式,为你的 `Stats Card` 或 `Repo Card` 自定义样式。
|
||||
|
||||
常用选项:
|
||||
|
||||
- `title_color` - 卡片标题颜色 _(十六进制色码)_
|
||||
- `text_color` - 内容文本颜色 _(十六进制色码)_
|
||||
- `icon_color` - 图标颜色(如果可用)_(十六进制色码)_
|
||||
- `bg_color` - 卡片背景颜色 _(十六进制色码)_ **或者** 以 _angle,start,end_ 的形式渐变
|
||||
- `theme` - 主题名称,从[所有可用主题](../themes/README.md)中选择
|
||||
- `cache_seconds` - 手动设置缓存头 _(最小值: 1800,最大值: 86400)_
|
||||
|
||||
##### bg_color 渐变
|
||||
|
||||
你可以在 bg_color 选项中提供多个逗号分隔的值来呈现渐变,渐变的格式是 :-
|
||||
|
||||
```
|
||||
&bg_color=DEG,COLOR1,COLRO2,COLOR3...COLOR10
|
||||
```
|
||||
|
||||
> 缓存的注意事项: 如果 fork 数和 star 数 少于 1k , Repo 卡片默认缓存是 4 小时 (14400 秒) ,否则是 2 小时(7200)。另请注意缓存被限制为最短 2 小时,最长 24 小时。
|
||||
|
||||
#### 统计卡片专属选项:
|
||||
|
||||
- `hide` - 隐藏特定统计信息 _(以逗号分隔)_
|
||||
- `hide_title` - _(boolean)_
|
||||
- `hide_rank` - _(boolean)_
|
||||
- `show_icons` - _(boolean)_
|
||||
- `include_all_commits` - 统计总提交次数而不是仅统计今年的提交次数 _(boolean)_
|
||||
- `count_private` - 统计私人提交 _(boolean)_
|
||||
- `line_height` - 设置文本之间的行高 _(number)_
|
||||
|
||||
#### Repo 卡片专属选项:
|
||||
|
||||
- `show_owner` - 显示 Repo 的所有者名字 _(boolean)_
|
||||
|
||||
#### 语言卡片专属选项:
|
||||
|
||||
- `hide` - 从卡片中隐藏指定语言 _(Comma seperated values)_
|
||||
- `hide_title` - _(boolean)_
|
||||
- `layout` - 在两个可用布局 `default` & `compact` 间切换
|
||||
- `card_width` - 手动设置卡片的宽度 _(number)_
|
||||
|
||||
> :warning: **重要:**
|
||||
> 如 [Percent Encoding](https://en.wikipedia.org/wiki/Percent-encoding) 所指定,语言名称应使用 uri 转义。
|
||||
> (例: `c++` 应该是 `c%2B%2B`, `jupyter notebook` 应该是 `jupyter%20notebook`, 等.)
|
||||
|
||||
---
|
||||
|
||||
# GitHub 更多置顶
|
||||
|
||||
GitHub 更多置顶 允许你在使用 GitHub readme profile 时,在个人资料中置顶多于 6 个 repo 。
|
||||
|
||||
是的!你不再受限于置顶最多 6 个存储库了。
|
||||
|
||||
### 使用细则
|
||||
|
||||
复制粘贴这段代码到你的 README 文件中,并更改链接。
|
||||
|
||||
端点: `api/pin?username=anuraghazra&repo=github-readme-stats`
|
||||
|
||||
```md
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
```
|
||||
|
||||
### Demo
|
||||
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
|
||||
使用 [show_owner](#自定义) 变量将 Repo 所有者的用户名包含在内。
|
||||
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
|
||||
# 热门语言卡片
|
||||
|
||||
热门语言卡片显示了 GitHub 用户常用的编程语言。
|
||||
|
||||
_注意:热门语言并不表示我的技能水平或类似的水平,它是用来衡量用户在 github 上拥有最多代码的语言的一项指标,它是 github-readme-stats 的新特性_
|
||||
|
||||
### 使用细则
|
||||
|
||||
将此代码复制粘贴到您的 `README.md` 文件中,并修改链接。
|
||||
|
||||
端点: `api/top-langs?username=anuraghazra`
|
||||
|
||||
```md
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
```
|
||||
|
||||
### 隐藏指定语言
|
||||
|
||||
可以使用 `?hide=language1,language2` 参数来隐藏指定的语言。
|
||||
|
||||
```md
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
```
|
||||
|
||||
### 紧凑的语言卡片布局
|
||||
|
||||
你可以使用 `&layout=compact` 参数来改变卡片的样式。
|
||||
|
||||
```md
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
```
|
||||
|
||||
### Demo
|
||||
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
|
||||
- 紧凑布局
|
||||
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
|
||||
---
|
||||
|
||||
### 全部 Demos
|
||||
|
||||
- 默认
|
||||
|
||||

|
||||
|
||||
- 隐藏指定统计
|
||||
|
||||

|
||||
|
||||
- 显示图标
|
||||
|
||||

|
||||
|
||||
- 包含全部提交
|
||||
|
||||

|
||||
|
||||
- 主题
|
||||
|
||||
从[默认主题](#主题)中进行选择
|
||||
|
||||

|
||||
|
||||
- 渐变
|
||||
|
||||

|
||||
|
||||
- 自定义统计卡片
|
||||
|
||||

|
||||
|
||||
- 自定义 repo 卡片
|
||||
|
||||

|
||||
|
||||
- 热门语言
|
||||
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
|
||||
---
|
||||
|
||||
### 快速提示 (对齐 Repo 卡片)
|
||||
|
||||
你通常无法将图片靠边显示。为此,您可以使用以下方法:
|
||||
|
||||
```md
|
||||
<a href="https://github.com/anuraghazra/github-readme-stats">
|
||||
<img align="left" src="https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra&repo=github-readme-stats" />
|
||||
</a>
|
||||
<a href="https://github.com/anuraghazra/convoychat">
|
||||
<img align="left" src="https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra&repo=convoychat" />
|
||||
</a>
|
||||
```
|
||||
|
||||
## 自己部署
|
||||
|
||||
#### [Check Out Step By Step Video Tutorial By @codeSTACKr](https://youtu.be/n6d4KHSKqGk?t=107)
|
||||
|
||||
因为 GitHub 的 API 每个小时只允许 5 千次请求,我的 `https://github-readme-stats.vercel.app/api` 很有可能会触发限制。如果你将其托管在自己的 Vercel 服务器上,那么你就不必为此担心。点击 deploy 按钮来开始你的部署!
|
||||
|
||||
注意: 从 [#58](https://github.com/anuraghazra/github-readme-stats/pull/58) 开始,我们应该能够处理超过 5 千次的请求,并且不会出现宕机问题 :D
|
||||
|
||||
[](https://vercel.com/import/project?template=https://github.com/anuraghazra/github-readme-stats)
|
||||
|
||||
<details>
|
||||
<summary>设置 Vercel 的指导</summary>
|
||||
|
||||
1. 前往 [vercel.com](https://vercel.com/)
|
||||
1. 点击 `Log in`
|
||||

|
||||
1. 点击 `Continue with GitHub` 通过 GitHub 进行登录
|
||||

|
||||
1. 登录 GitHub 并允许访问所有存储库(如果系统这样提示)
|
||||
1. Fork 这个仓库
|
||||
1. 返回到你的 [Vercel dashboard](https://vercel.com/dashboard)
|
||||
1. 选择 `Import Project`
|
||||

|
||||
1. 选择 `Import Git Repository`
|
||||

|
||||
1. 选择 root 并将所有内容保持不变,并且只需添加名为 PAT_1 的环境变量(如图所示),其中将包含一个个人访问令牌(PAT),你可以在[这里](https://github.com/settings/tokens/new)轻松创建(保留默认,并且只需要命名下,名字随便)
|
||||

|
||||
1. 点击 deploy,这就完成了,查看你的域名就可使用 API 了!
|
||||
|
||||
</details>
|
||||
|
||||
## :sparkling_heart: 支持这个项目
|
||||
|
||||
我尽己所能地进行开源,并且我尽量回复每个在使用项目时需要帮助的人。很明显,这需要时间,但你可以免费享受这些。
|
||||
|
||||
然而, 如果你正在使用这个项目并感觉良好,或只是想要支持我继续开发,你可以通过如下方式:
|
||||
|
||||
- 在你的 readme 中使用 github-readme-stats 时,链接指向这里 :D
|
||||
- Star 并 分享这个项目 :rocket:
|
||||
- [](https://www.paypal.me/anuraghazra) - 你可以通过 PayPal 一次性捐款. 我多半会买一杯 ~~咖啡~~ 茶. :tea:
|
||||
|
||||
谢谢! :heart:
|
||||
|
||||
---
|
||||
|
||||

|
||||
|
||||
欢迎贡献! <3
|
||||
|
||||
用 :heart: 发电,用 JavaScript 制作。
|
@ -1,333 +0,0 @@
|
||||
<p align="center">
|
||||
<img width="100px" src="https://res.cloudinary.com/anuraghazra/image/upload/v1594908242/logo_ccswme.svg" align="center" alt="GitHub Readme Stats" />
|
||||
<h2 align="center">GitHub Readme Stats</h2>
|
||||
<p align="center">Zeige dynamisch generierte GitHub-Statistiken in deinen Readmes!</p>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/anuraghazra/github-readme-stats/actions">
|
||||
<img alt="Tests Passing" src="https://github.com/anuraghazra/github-readme-stats/workflows/Test/badge.svg" />
|
||||
</a>
|
||||
<a href="https://codecov.io/gh/anuraghazra/github-readme-stats">
|
||||
<img src="https://codecov.io/gh/anuraghazra/github-readme-stats/branch/master/graph/badge.svg" />
|
||||
</a>
|
||||
<a href="https://github.com/anuraghazra/github-readme-stats/issues">
|
||||
<img alt="Issues" src="https://img.shields.io/github/issues/anuraghazra/github-readme-stats?color=0088ff" />
|
||||
</a>
|
||||
<a href="https://github.com/anuraghazra/github-readme-stats/pulls">
|
||||
<img alt="GitHub pull requests" src="https://img.shields.io/github/issues-pr/anuraghazra/github-readme-stats?color=0088ff" />
|
||||
</a>
|
||||
<br />
|
||||
<br />
|
||||
<a href="https://a.paddle.com/v2/click/16413/119403?link=1227">
|
||||
<img src="https://img.shields.io/badge/Supported%20by-VSCode%20Power%20User%20%E2%86%92-gray.svg?colorA=655BE1&colorB=4F44D6&style=for-the-badge"/>
|
||||
</a>
|
||||
<a href="https://a.paddle.com/v2/click/16413/119403?link=2345">
|
||||
<img src="https://img.shields.io/badge/Supported%20by-Node%20Cli.com%20%E2%86%92-gray.svg?colorA=61c265&colorB=4CAF50&style=for-the-badge"/>
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="#demo">Beispiel ansehen</a>
|
||||
·
|
||||
<a href="https://github.com/anuraghazra/github-readme-stats/issues/new/choose">Fehler melden</a>
|
||||
·
|
||||
<a href="https://github.com/anuraghazra/github-readme-stats/issues/new/choose">Funktion wünschen</a>
|
||||
</p>
|
||||
<p align="center">
|
||||
<a href="/docs/readme_fr.md">Français</a>
|
||||
·
|
||||
<a href="/docs/readme_cn.md">简体中文</a>
|
||||
·
|
||||
<a href="/docs/readme_es.md">Español</a>
|
||||
·
|
||||
<a href="/docs/readme_de.md">Deutsch</a>
|
||||
·
|
||||
<a href="/docs/readme_ja.md">日本語</a>
|
||||
·
|
||||
<a href="/docs/readme_pt-BR.md">Português Brasileiro</a>
|
||||
·
|
||||
<a href="/docs/readme_it.md">Italiano</a>
|
||||
·
|
||||
<a href="/docs/readme_kr.md">한국어</a>
|
||||
</p>
|
||||
</p>
|
||||
<p align="center">Du magst das Projekt? Wie wäre es mit einer kleinen <a href="https://www.paypal.me/anuraghazra">Spende</a> um es weiterhin am Leben zu erhalten?
|
||||
|
||||
# Funktionen
|
||||
|
||||
- [GitHub Statistiken-Karte](#github-statistiken-karte)
|
||||
- [GitHub Extra Pins](#github-extra-pins)
|
||||
- [Top Programmiersprachen-Karte](#top-programmiersprachen-karte)
|
||||
- [Erscheinungsbild/Themes](#erscheinungsbildthemes)
|
||||
- [Anpassungen/Personalisierung](#anpassungenpersonalisierung)
|
||||
- [Selber betreiben](#betreibe-es-auf-deiner-eigenen-vercel-instanz)
|
||||
|
||||
# GitHub Statistiken-Karte
|
||||
|
||||
Kopiere einfach folgendes in dein Markdown und das wars. Echt simpel!
|
||||
|
||||
Passe den Wert des URL-Parameters `?username=` so an, dass dort dein GitHub Nutzername steht.
|
||||
|
||||
```md
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
```
|
||||
|
||||
_Hinweis: Die Berechnung des Ranges basiert auf den jeweiligen Benutzerstatistiken, siehe [src/calculateRank.js](../src/calculateRank.js)_
|
||||
|
||||
### Verbergen individueller Statistiken
|
||||
|
||||
Um eine spezifische Statistik auszublenden, kann dem Query-Parameter `?hide=` ein Array an Optionen, die nicht angezeigt werden sollen, übergeben werden.
|
||||
|
||||
> Optionen: `&hide=["stars","commits","prs","issues","contribs"]`
|
||||
|
||||
```md
|
||||

|
||||
```
|
||||
|
||||
### Symbole anzeigen
|
||||
|
||||
Um Symbole anzuzeigen kann der URL-Paramter `show_icons=true` wie folgt verwendet werden:
|
||||
|
||||
```md
|
||||

|
||||
```
|
||||
|
||||
### Erscheinungsbild/Themes
|
||||
|
||||
Mithilfe der eingebauten Themes kann das Aussehen der Karten verändern werden ohne manuelle Anpassungen vornehmen zu müssen.
|
||||
|
||||
Benutze den `?theme=THEME_NAME`-Parameter wie folgt :-
|
||||
|
||||
```md
|
||||

|
||||
```
|
||||
|
||||
#### Alle eingebauten Themes :-
|
||||
|
||||
dark, radical, merko, gruvbox, tokyonight, onedark, cobalt, synthwave, highcontrast, dracula
|
||||
|
||||
<img src="https://res.cloudinary.com/anuraghazra/image/upload/v1595174536/grs-themes_l4ynja.png" alt="GitHub Readme Stat Themes" width="600px"/>
|
||||
|
||||
Du kannst dir eine Vorschau [aller verfügbaren Themes](../themes/README.md) ansehen oder die [theme config Datei](../themes/index.js) ansehen.
|
||||
Außerdem **kannst du neue Themes beisteuern**, Beiträge sind gern gesehen :D
|
||||
|
||||
### Anpassungen/Personalisierung
|
||||
|
||||
Du kannst das Erscheinungsbild deiner `Stats Card` oder `Repo Card`, mithilfe von URL-Parametern, nach deinen Vorlieben anpassen.
|
||||
|
||||
#### Verbreitete Optionen:
|
||||
|
||||
- `title_color` - Titelfarbe _(hex color)_
|
||||
- `text_color` - Textkörperfarbe _(hex color)_
|
||||
- `icon_color` - Symbolfarbe (falls verfügbar) _(hex color)_
|
||||
- `bg_color` - Hintergrundfarbe _(hex color)_ **oder** ein Farbverlauf in der Form von _winkel,start,ende_
|
||||
- `theme` - Name des Erscheinungsbildes/Themes [alle verfügbaren Themes](../themes/README.md)
|
||||
- `cache_seconds` - manuelles festlegen der Cachezeiten _(min: 1800, max: 86400)_
|
||||
|
||||
##### Farbverlauf in bg_color
|
||||
|
||||
Du kannst mehrere, mit Kommas separierte, Werte in der bg_color Option angeben, um einen Farbverlauf anzuzeigen. Das Format ist:-
|
||||
|
||||
```
|
||||
&bg_color=WINKEL,FARBE1,FARBE2,FARBE3...FARBE10
|
||||
```
|
||||
|
||||
> Hinweis bzgl. des Caches: Wenn die Anzahl der Forks und Stars geringer als 1 Tsd ist, haben die Repo-Cards eine Standard-Cachezeit von 30 Minuten (1800 Sekunden), ansonsten beträgt diese 2 Stunden (7200 Sekunden). Außerdem ist der Cache auf ein Minimum von 30 Minuten und ein Maximum von 24 Stunden begrenzt.
|
||||
|
||||
#### Exklusive Optionen der Statistiken-Karte:
|
||||
|
||||
- `hide` - Verbirgt die angegeben Elemente _(mit Komma abgegrenzte Werte)_
|
||||
- `hide_title` - _(boolean)_
|
||||
- `hide_rank` - _(boolean)_
|
||||
- `show_icons` - _(boolean)_
|
||||
- `include_all_commits` - Zähle alle Beiträge anstatt nur das aktuelle Jahr _(boolean)_
|
||||
- `count_private` - Zähle private Beiträge _(boolean)_
|
||||
- `line_height` - Legt die Zeilenhöhe zwischen Text fest _(Zahl)_
|
||||
|
||||
#### Exklusive Optionen der Repo-Karte:
|
||||
|
||||
- `show_owner` - Zeigt den Besitzer des Repos _(boolean)_
|
||||
|
||||
#### Exklusive Optionen der Sprachen-Karte:
|
||||
|
||||
- `hide` - Verbirgt die angegebenen Sprachen von der Karte _(Komma separierte Werte)_
|
||||
- `hide_title` - _(boolean)_
|
||||
- `layout` - Wechsel zwischen den zwei verfügbaren Layouts `default` & `compact`
|
||||
- `card_width` - Lege die Breite der Karte manuell fest _(Zahl)_
|
||||
|
||||
> :warning: **Wichtig:**
|
||||
> Sprachennamen sollten uri-escaped sein, wie hier angegeben: [Percent Encoding](https://en.wikipedia.org/wiki/Percent-encoding)
|
||||
> (z.B.: `c++` sollte zu `c%2B%2B` werden, `jupyter notebook` sollte zu `jupyter%20notebook` werden, usw.)
|
||||
|
||||
---
|
||||
|
||||
# GitHub Extra Pins
|
||||
|
||||
GitHub extra pins ermöglicht es mit Hilfe einer Readme auf deinem Profil mehr als 6 Repositories anzuzeigen.
|
||||
|
||||
Und Bääm! Du bist nicht mehr auf 6 angeheftete Repositories limitiert.
|
||||
|
||||
### Benutzung
|
||||
|
||||
Füge diesen Code in deine Readme-Datei ein und passe die Links an.
|
||||
|
||||
Endpunkt: `api/pin?username=anuraghazra&repo=github-readme-stats`
|
||||
|
||||
```md
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
```
|
||||
|
||||
### Beispiele
|
||||
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
|
||||
Benutze die [show_owner](#anpassungenpersonalisierung) Variable, um den Nutzernamen des Repo Eigentümers anzuzeigen.
|
||||
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
|
||||
# Top Programmiersprachen-Karte
|
||||
|
||||
Die Top Programmiersprachen Card visualisiert die am meisten benutzten Programmiersprachen eines GitHub-Nutzers.
|
||||
|
||||
_HINWEIS: Die Top Programmiersprachen treffen keine Aussage über persönliche Fähigkeiten oder dergleichen, es ist lediglich eine auf den GitHub-Statistiken des Nutzers basierende Kennzahl, welche Programmiersprache wie häufig verwendet wurde._
|
||||
|
||||
### Benutzung
|
||||
|
||||
Füge diesen Code in deine Readme-Datei ein und passe die Links an.
|
||||
|
||||
Endpunkt: `api/top-langs?username=anuraghazra`
|
||||
|
||||
```md
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
```
|
||||
|
||||
### Verbirg einzelne Sprachen
|
||||
|
||||
Du kannst den `?hide=language1,language2` URL-Parameter benutzen, um einzelne Sprachen auszublenden.
|
||||
|
||||
```md
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
```
|
||||
|
||||
### Kompaktes Sprachen-Karte Layout
|
||||
|
||||
Du kannst die `&layout=compact` Option nutzen, um das Karten Design zu ändern.
|
||||
|
||||
```md
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
```
|
||||
|
||||
### Beispiel
|
||||
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
|
||||
- Kompaktes Layout
|
||||
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
|
||||
---
|
||||
|
||||
### Alle Beispiele
|
||||
|
||||
- Default
|
||||
|
||||

|
||||
|
||||
- Ausblenden bestimmter Statistiken
|
||||
|
||||

|
||||
|
||||
- Symbole anzeigen
|
||||
|
||||

|
||||
|
||||
- Alle Beiträge anzeigen
|
||||
|
||||

|
||||
|
||||
- Erscheinungsbild/Themes
|
||||
|
||||
Wähle Eines von den [Standard-Themes](#themes)
|
||||
|
||||

|
||||
|
||||
- Farbverlauf
|
||||
|
||||

|
||||
|
||||
- Statistiken-Karte anpassen
|
||||
|
||||

|
||||
|
||||
- Repo-Karte anpassen
|
||||
|
||||

|
||||
|
||||
- Top Programmiersprachen
|
||||
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
|
||||
---
|
||||
|
||||
### Kleiner Tipp (Ausrichten der Repo-Karte)
|
||||
|
||||
Üblicherweise ist es in `.md`-Dateien nicht möglich Bilder nebeneinander anzuzeigen. Um dies zu erreichen kann folgender Ansatz gewählt werden:
|
||||
|
||||
```md
|
||||
<a href="https://github.com/anuraghazra/github-readme-stats">
|
||||
<img align="left" src="https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra&repo=github-readme-stats" />
|
||||
</a>
|
||||
<a href="https://github.com/anuraghazra/convoychat">
|
||||
<img align="left" src="https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra&repo=convoychat" />
|
||||
</a>
|
||||
```
|
||||
|
||||
## Betreibe es auf deiner eigenen Vercel-Instanz
|
||||
|
||||
#### [Check Out Step By Step Video Tutorial By @codeSTACKr](https://youtu.be/n6d4KHSKqGk?t=107)
|
||||
|
||||
Da die GitHub API nur 5 Tsd Aufrufe pro Stunde zulässt, kann es passieren, dass meine `https://github-readme-stats.vercel.app/api` dieses Limit erreicht.
|
||||
Wenn du es auf deinem eigenen Vercel-Server hostest, brauchst du dich darum nicht zu kümmern. Klicke auf den Deploy-Knopf um loszulegen!
|
||||
|
||||
Hinweis: Seit [#58](https://github.com/anuraghazra/github-readme-stats/pull/58) sollte es möglich sein, mehr als 5 Tsd Aufrufe pro Stunde ohne Downtimes zu verkraften :D
|
||||
|
||||
[](https://vercel.com/import/project?template=https://github.com/anuraghazra/github-readme-stats)
|
||||
|
||||
<details>
|
||||
<summary><b>Anleitung zum Einrichten von Vercel 🔨 </b></summary>
|
||||
|
||||
1. Gehe zu [vercel.com](https://vercel.com/)
|
||||
1. Klicke auf `Log in`
|
||||

|
||||
1. Melde dich mit deinem GitHub-account an, indem du `Continue with GitHub` klickst
|
||||

|
||||
1. Verbinde dich mit GitHub und erlaube den Zugriff auf alle Repositories (falls gefordert)
|
||||
1. Forke dieses Repository
|
||||
1. Gehe zurück zu deinem [Vercel dashboard](https://vercel.com/dashboard)
|
||||
1. Klick `Import Project`
|
||||

|
||||
1. Klick `Import Git Repository`
|
||||

|
||||
1. Wähle root und füge eine Umgebungsvariable namens PAT_1 (siehe Abbildung) die als Wert deinen persönlichen Access Token (PAT) hat hinzu, den du einfach [hier](https://github.com/settings/tokens/new) erzeugen kannst (lasse alles wie es ist, vergebe einen beliebigen Namen)
|
||||

|
||||
1. Klicke deploy, und das wars. Besuche deine domains um die API zu benutzen!
|
||||
</details>
|
||||
|
||||
## :sparkling_heart: Unterstütze das Projekt
|
||||
|
||||
Ich versuche alles was ich kann als Open-Source zur Verfügung zu stellen, als auch jedem der Hilfe bei der Benutzung dieses Projektes braucht zu antworten. Natürlich beansprucht sowas Zeit und Du kannst diesen Dienst kostenlos benutzen.
|
||||
|
||||
Dennoch, wenn Du dieses Projekt benutzt und damit zufrieden bist oder mich einfach nur motivieren möchtest weiterhin daran zu arbeiten, gibt es verschiedene Sachen die Du machen kannst:-
|
||||
|
||||
- Erwähne und verlinke das Projekt in deiner Readme wenn du es benutzt :D
|
||||
- Geb dem Projekt einen Stern hier auf GitHub und teile es :rocket:
|
||||
- [](https://www.paypal.me/anuraghazra) - Du kannst einmalige Spenden via PayPal tätigen. Ich kaufe mir wahrscheinlich einen ~~Kaffee~~ Tee davon. :tea:
|
||||
|
||||
Vielen Dank! :heart:
|
||||
|
||||
---
|
||||
|
||||
Mitarbeit an dem Projekt ist immer Willkommen! <3
|
||||
|
||||
Gebaut mit :heart: und JavaScript.
|
@ -1,332 +0,0 @@
|
||||
<p align="center">
|
||||
<img width="100px" src="https://res.cloudinary.com/anuraghazra/image/upload/v1594908242/logo_ccswme.svg" align="center" alt="GitHub Readme Stats" />
|
||||
<h2 align="center">GitHub Readme Stats</h2>
|
||||
<p align="center">¡Obtén tus estadísticas de GitHub generadas dinámicamente en tu README!</p>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/anuraghazra/github-readme-stats/actions">
|
||||
<img alt="Tests Passing" src="https://github.com/anuraghazra/github-readme-stats/workflows/Test/badge.svg" />
|
||||
</a>
|
||||
<a href="https://codecov.io/gh/anuraghazra/github-readme-stats">
|
||||
<img src="https://codecov.io/gh/anuraghazra/github-readme-stats/branch/master/graph/badge.svg" />
|
||||
</a>
|
||||
<a href="https://github.com/anuraghazra/github-readme-stats/issues">
|
||||
<img alt="Issues" src="https://img.shields.io/github/issues/anuraghazra/github-readme-stats?color=0088ff" />
|
||||
</a>
|
||||
<a href="https://github.com/anuraghazra/github-readme-stats/pulls">
|
||||
<img alt="GitHub pull requests" src="https://img.shields.io/github/issues-pr/anuraghazra/github-readme-stats?color=0088ff" />
|
||||
</a>
|
||||
<br />
|
||||
<br />
|
||||
<a href="https://a.paddle.com/v2/click/16413/119403?link=1227">
|
||||
<img src="https://img.shields.io/badge/Supported%20by-VSCode%20Power%20User%20%E2%86%92-gray.svg?colorA=655BE1&colorB=4F44D6&style=for-the-badge"/>
|
||||
</a>
|
||||
<a href="https://a.paddle.com/v2/click/16413/119403?link=2345">
|
||||
<img src="https://img.shields.io/badge/Supported%20by-Node%20Cli.com%20%E2%86%92-gray.svg?colorA=61c265&colorB=4CAF50&style=for-the-badge"/>
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="#ejemplo">Ve un ejemplo</a>
|
||||
·
|
||||
<a href="https://github.com/anuraghazra/github-readme-stats/issues/new/choose">Reporta un bug</a>
|
||||
·
|
||||
<a href="https://github.com/anuraghazra/github-readme-stats/issues/new/choose">Solicita una mejora</a>
|
||||
</p>
|
||||
<p align="center">
|
||||
<a href="/docs/readme_fr.md">Français</a>
|
||||
·
|
||||
<a href="/docs/readme_cn.md">简体中文</a>
|
||||
·
|
||||
<a href="/docs/readme_es.md">Español</a>
|
||||
·
|
||||
<a href="/docs/readme_de.md">Deutsch</a>
|
||||
·
|
||||
<a href="/docs/readme_ja.md">日本語</a>
|
||||
·
|
||||
<a href="/docs/readme_pt-BR.md">Português Brasileiro</a>
|
||||
·
|
||||
<a href="/docs/readme_it.md">Italiano</a>
|
||||
·
|
||||
<a href="/docs/readme_kr.md">한국어</a>
|
||||
</p>
|
||||
</p>
|
||||
<p align="center">¿Te gusta este proyecto? ¡Por favor considera <a href="https://www.paypal.me/anuraghazra">donar</a> para ayudar a mejorarlo!
|
||||
|
||||
# Características
|
||||
|
||||
- [Tarjeta de estadísticas de GitHub](#tarjeta-de-estadísticas-de-github)
|
||||
- [Pins adicionales de GitHub](#pines-adicionales-de-github)
|
||||
- [Temas](#temas)
|
||||
- [Personalización](#personalización)
|
||||
- [Despliega por tu cuenta](#despliega-tu-propia-instancia-de-vercel)
|
||||
|
||||
# Tarjeta de estadísticas de GitHub
|
||||
|
||||
Copia y pega esto en el contenido de tu README.md y listo. ¡Simple!
|
||||
|
||||
Cambia el valor `?username=` al nombre de tu usuario de GitHub.
|
||||
|
||||
```md
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
```
|
||||
|
||||
_Nota: las clasificaciones se calculan basándose en las estadísticas del usuario. Ve [src/calculateRank.js](../src/calculateRank.js)._
|
||||
|
||||
### Ocultar estadísticas individualmente
|
||||
|
||||
Para ocultar alguna estadística específica, puedes utilizar el parámetro `?hide=` con un arreglo de items que quieras ocultar.
|
||||
|
||||
> Opciones: `&hide=["stars","commits","prs","issues","contribs"]`
|
||||
|
||||
```md
|
||||

|
||||
```
|
||||
|
||||
### Agregar contribuciones privadas al total de commits contados
|
||||
|
||||
Puede agregar el recuento de todas sus contribuciones privadas al recuento total de confirmaciones utilizando el parámetro de consulta `?count_private=true`.
|
||||
|
||||
_Nota: Si está desplegando este proyecto usted mismo, las contribuciones privadas se contarán de manera predeterminada; de lo contrario, deberá elegir compartir sus recuentos de contribuciones privadas._
|
||||
|
||||
> Opciones: `&count_private=true`
|
||||
|
||||
```md
|
||||

|
||||
```
|
||||
|
||||
### Mostrar íconos
|
||||
|
||||
Para habilitar los íconos, puedes utilizar `show_icons=true` como parámetro, de esta manera:
|
||||
|
||||
```md
|
||||

|
||||
```
|
||||
|
||||
### Temas
|
||||
|
||||
Puedes personalizar el aspecto de la tarjeta sin realizar ninguna [personalización manual](#personalización) con los temas incorporados.
|
||||
|
||||
Utiliza el parámetro `?theme=THEME_NAME`, de esta manera:
|
||||
|
||||
```md
|
||||

|
||||
```
|
||||
|
||||
#### Todos los temas incorporados
|
||||
|
||||
dark, radical, merko, gruvbox, tokyonight, onedark, cobalt, synthwave, highcontrast, dracula
|
||||
|
||||
<img src="https://res.cloudinary.com/anuraghazra/image/upload/v1595174536/grs-themes_l4ynja.png" alt="GitHub Readme Stat Themes" width="600px"/>
|
||||
|
||||
Puedes ver una vista previa de [todos los temas disponibles](../themes/README.md) o ver el [archivo de configuración](../themes/index.js) del tema y también **puedes contribuir con nuevos temas** si lo deseas :D
|
||||
|
||||
### Personalización
|
||||
|
||||
Puedes personalizar el aspecto de tu `Stats Card` o `Repo Card` de la manera que desees con los parámetros URL.
|
||||
|
||||
#### Opciones Comunes:
|
||||
|
||||
- `title_color` - Color del título _(hex color)_
|
||||
- `text_color` - Color del contenido _(hex color)_
|
||||
- `icon_color` - Color de icono si esta disponible _(hex color)_
|
||||
- `bg_color` - Color de fondo _(hex color)_
|
||||
- `theme` - Nombre del tema, elige uno de [todos los temas disponible ](../themes/README.md)
|
||||
- `cache_seconds` - Cache _(min: 1800, max: 86400)_
|
||||
|
||||
> Nota sobre la caché: las tarjetas de Repo tienen un caché predeterminado de 30 minutos (1800 segundos) si el recuento forks y el recuento de estrellas es inferior a 1k; de lo contrario, son 2 horas (7200). También tenga en cuenta que el caché está sujeto a un mínimo de 30 minutos y un máximo de 24 horas
|
||||
|
||||
#### Opciones exclusivas de la tarjeta de estadísticas:
|
||||
|
||||
- `hide` - Ocultar los elementos especificados de las estadísticas _ (valores separados por comas) _
|
||||
- `hide_title` - _(boolean)_
|
||||
- `hide_rank` - _(boolean)_
|
||||
- `show_icons` - _(boolean)_
|
||||
- `include_all_commits` - Cuente los commits totales en lugar de solo los commits del año actual _(boolean)_
|
||||
- `count_private` - Cuenta los commits privadas _(boolean)_
|
||||
- `line_height` - Establece el alto de línea entre texto _(number)_
|
||||
|
||||
#### Opciones exclusivas de la tarjeta Repo:
|
||||
|
||||
- `show_owner` - Mostrar el nombre del propietario del repositorio _(boolean)_
|
||||
|
||||
#### Opciones exclusivas de la tarjeta de lenguajes:
|
||||
|
||||
- `hide` - Ocultar los lenguajes especificados de la tarjeta _(valores separados por comas)_
|
||||
- `hide_title` - _(boolean)_
|
||||
- `layout` - Cambiar entre dos diseños disponibles `default` & `compact`
|
||||
- `card_width` - Establecer el ancho de la tarjeta manualmente _(number)_
|
||||
|
||||
> :warning: **Importante:**
|
||||
> Los nombres de los idiomas deben tener escape de uri, como se especifica en [Código porciento](https://es.wikipedia.org/wiki/C%C3%B3digo_porciento)
|
||||
> (es decir: `c++` debería convertirse en `c%2B%2B`,`jupyter notebook` debería convertirse en `jupyter%20notebook`, etc.)
|
||||
|
||||
---
|
||||
|
||||
# Pines adicionales de GitHub
|
||||
|
||||
Los pines adicionales de GitHub le permiten fijar más de 6 repositorios en su perfil utilizando un readme de perfil de GitHub.
|
||||
|
||||
Yey! Ya no está limitado a 6 repositorios anclados.
|
||||
|
||||
### Utilización
|
||||
|
||||
Copie y pegue este código en su archivo Léame y cambie los enlaces.
|
||||
|
||||
Endpoint: `api/pin?username=anuraghazra&repo=github-readme-stats`
|
||||
|
||||
```md
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
```
|
||||
|
||||
### Ejemplo
|
||||
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
|
||||
Utiliza la variable [show_owner](#customización) para incluir el nombre de usuario del propietario del repositorio.
|
||||
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
|
||||
# Tarjeta de lenguajes principales
|
||||
|
||||
La tarjeta de lenguajes principales muestra los lenguajes principales del usuario de github que se han utilizado principalmente.
|
||||
|
||||
_NOTA: los lenguajes principales no indican mi nivel de habilidad o algo así, es una métrica de github de los lenguajes que tengo más código en github, es una nueva característica de github-readme-stats_
|
||||
|
||||
### Utilización
|
||||
|
||||
Copie y pegue este código en su readme y cambie los enlaces.
|
||||
|
||||
Endpoint: `api/top-langs?username=anuraghazra`
|
||||
|
||||
```md
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
```
|
||||
|
||||
### Ocultar lenguajes individuales
|
||||
|
||||
Puede usar el parámetro `? Hide = language1, language2` para ocultar lenguajes individuales.
|
||||
|
||||
```md
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
```
|
||||
|
||||
### Diseño de tarjeta de lenguaje compacta
|
||||
|
||||
Puede usar la opción `& layout = compact` para cambiar el diseño de la tarjeta.
|
||||
|
||||
```md
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
```
|
||||
|
||||
### Ejemplo
|
||||
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
|
||||
- Diseño compacto
|
||||
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
|
||||
---
|
||||
|
||||
### Todos los ejemplos
|
||||
|
||||
- Por Defecto
|
||||
|
||||

|
||||
|
||||
- Ocultar estadísticas específicas
|
||||
|
||||

|
||||
|
||||
- Mostrando iconos
|
||||
|
||||

|
||||
|
||||
- Incluir todos los Commits
|
||||
|
||||

|
||||
|
||||
- Temas
|
||||
|
||||
Elija entre cualquiera de los [temas predeterminados](#themes)
|
||||
|
||||

|
||||
|
||||
- Personalizando tarjeta de estadísticas
|
||||
|
||||

|
||||
|
||||
- Personalizar la tarjeta de repositorio
|
||||
|
||||

|
||||
|
||||
- Lenguajes Principales
|
||||
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
|
||||
---
|
||||
|
||||
### Consejo rápido (alinee las tarjetas de repositorio)
|
||||
|
||||
Por lo general, no podrá diseñar las imágenes una al lado de la otra. Para hacerlo, puede usar este enfoque:
|
||||
|
||||
```md
|
||||
<a href="https://github.com/anuraghazra/github-readme-stats">
|
||||
<img align="left" src="https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra&repo=github-readme-stats" />
|
||||
</a>
|
||||
<a href="https://github.com/anuraghazra/convoychat">
|
||||
<img align="left" src="https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra&repo=convoychat" />
|
||||
</a>
|
||||
```
|
||||
|
||||
## Despliega tu propia instancia de vercel
|
||||
|
||||
#### [Check Out Step By Step Video Tutorial By @codeSTACKr](https://youtu.be/n6d4KHSKqGk?t=107)
|
||||
|
||||
Desde que la API de GitHub permite solo 5 mil peticiones por hora, es posible que mi `https://github-readme-stats.vercel.app/api` pueda llegar al límite. Si lo alojas en tu propio servidor de Vercel, no tendrás que preocuparte de nada. ¡Clickea en el botón "Deploy" para comenzar!
|
||||
|
||||
Nota: debido a esto [#58](https://github.com/anuraghazra/github-readme-stats/pull/58) podríamos manejar más de 5 mil peticiones sin tener ningún problema con el downtime :D
|
||||
|
||||
[](https://vercel.com/import/project?template=https://github.com/anuraghazra/github-readme-stats)
|
||||
|
||||
<details>
|
||||
<summary>Guía para comenzar en Vercel</summary>
|
||||
|
||||
1. Ve a [vercel.com](https://vercel.com/)
|
||||
1. Clickea en `Log in`
|
||||

|
||||
1. Inicia sesión con GitHub presionando `Continue with GitHub`
|
||||

|
||||
1. Permite el acceso a todos los repositorios (si se te pregunta)
|
||||
1. Haz un Fork de este repositorio
|
||||
1. Dirígete de nuevo a tu [Vercel dashboard](https://vercel.com/dashboard)
|
||||
1. Selecciona `Import Project`
|
||||

|
||||
1. Selecciona `Import Git Repository`
|
||||

|
||||
1. Selecciona "root" y matén todo como está, simplemente añade tu variable de entorno llamada PAT_1 (como se muestra), la cual contendrá un token de acceso personal (PAT), el cual puedes crear fácilmente [aquí](https://github.com/settings/tokens/new) (mantén todo como está, simplemente asígnale un nombre, puede ser cualquiera que desees)
|
||||

|
||||
1. Clickea "Deploy" y ya está listo. ¡Ve tus dominios para usar la API!
|
||||
|
||||
</details>
|
||||
|
||||
## :sparkling_heart: Apoya al proyecto
|
||||
|
||||
Casi todos mis proyectos son código-abierto e intento responder a todos los usuarios que necesiten ayuda con alguno de estos proyectos, Obviamente,
|
||||
esto toma tiempo. Puedes usar este servicio gratis.
|
||||
|
||||
No obstante, si estás utilizando este proyecto y estás feliz con él o simplemente quieres animarme a que siga creando cosas, aquí tienes algunas maneras de hacerlo:
|
||||
|
||||
- Darme créditos cuando estés utilizando github-readme-stats en tu README, añadiendo un link a este repositorio :D
|
||||
- Dándole una estrella (starring) y compartiendo el proyecto :rocket:
|
||||
- [](https://www.paypal.me/anuraghazra) - Puedes hacerme una única donación a través de PayPal. Probablemente me compraré un ~~café~~ té. :tea:
|
||||
|
||||
¡Gracias! :heart:
|
||||
|
||||
---
|
||||
|
||||
¡Las contribuciones son bienvenidas! <3
|
||||
|
||||
Hecho con :heart: y JavaScript.
|
@ -1,344 +0,0 @@
|
||||
<p align="center">
|
||||
<img width="100px" src="https://res.cloudinary.com/anuraghazra/image/upload/v1594908242/logo_ccswme.svg" align="center" alt="GitHub Readme Stats" />
|
||||
<h2 align="center">GitHub Readme Stats</h2>
|
||||
<p align="center">Obtenez des statistiques GitHub générées dynamiquement sur vos ReadME !</p>
|
||||
</p>
|
||||
<p align="center">
|
||||
<a href="https://github.com/anuraghazra/github-readme-stats/actions">
|
||||
<img alt="Tests Passing" src="https://github.com/anuraghazra/github-readme-stats/workflows/Test/badge.svg" />
|
||||
</a>
|
||||
<a href="https://codecov.io/gh/anuraghazra/github-readme-stats">
|
||||
<img src="https://codecov.io/gh/anuraghazra/github-readme-stats/branch/master/graph/badge.svg" />
|
||||
</a>
|
||||
<a href="https://github.com/anuraghazra/github-readme-stats/issues">
|
||||
<img alt="Issues" src="https://img.shields.io/github/issues/anuraghazra/github-readme-stats?color=0088ff" />
|
||||
</a>
|
||||
<a href="https://github.com/anuraghazra/github-readme-stats/pulls">
|
||||
<img alt="GitHub pull requests" src="https://img.shields.io/github/issues-pr/anuraghazra/github-readme-stats?color=0088ff" />
|
||||
</a>
|
||||
<br />
|
||||
<br />
|
||||
<a href="https://a.paddle.com/v2/click/16413/119403?link=1227">
|
||||
<img src="https://img.shields.io/badge/Supporté%20par-VSCode%20Power%20User%20%E2%86%92-gray.svg?colorA=655BE1&colorB=4F44D6&style=for-the-badge"/>
|
||||
</a>
|
||||
<a href="https://a.paddle.com/v2/click/16413/119403?link=2345">
|
||||
<img src="https://img.shields.io/badge/Supporté%20par-Node%20Cli.com%20%E2%86%92-gray.svg?colorA=61c265&colorB=4CAF50&style=for-the-badge"/>
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="#demo">Voir la Demo</a>
|
||||
·
|
||||
<a href="https://github.com/anuraghazra/github-readme-stats/issues/new/choose">Soumettre un bug</a>
|
||||
·
|
||||
<a href="https://github.com/anuraghazra/github-readme-stats/issues/new/choose">Demander une nouveauté</a>
|
||||
</p>
|
||||
<p align="center">
|
||||
<a href="/docs/readme_fr.md">Français</a>
|
||||
·
|
||||
<a href="/docs/readme_cn.md">简体中文</a>
|
||||
·
|
||||
<a href="/docs/readme_es.md">Español</a>
|
||||
·
|
||||
<a href="/docs/readme_de.md">Deutsch</a>
|
||||
·
|
||||
<a href="/docs/readme_ja.md">日本語</a>
|
||||
·
|
||||
<a href="/docs/readme_pt-BR.md">Português Brasileiro</a>
|
||||
·
|
||||
<a href="/docs/readme_it.md">Italiano</a>
|
||||
·
|
||||
<a href="/docs/readme_kr.md">한국어</a>
|
||||
</p>
|
||||
</p>
|
||||
<p align="center">Tu aimes ce projet? Penser <a href="https://www.paypal.me/anuraghazra">à faire un don</a> pour l'améliorer!
|
||||
|
||||
# Features
|
||||
|
||||
- [Carte des stats GitHub](#carte-des-stats-github)
|
||||
- [GitHub Extra Pins](#github-extra-pins)
|
||||
- [Carte des meilleurs langages](#carte-des-langages-les--utilisés)
|
||||
- [Themes](#thèmes)
|
||||
- [Personnalisation](#personnalisation)
|
||||
- [Deployer toi-même](#déployer-sur-votre-propre-instance-vercel)
|
||||
|
||||
# Carte des Stats GitHub
|
||||
|
||||
Copiez-collez ceci dans votre Markdown, et c'est tout. C'est simple !
|
||||
|
||||
Remplacez la valeur `?username=` par le nom d'utilisateur de votre GitHub.
|
||||
|
||||
```md
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
```
|
||||
|
||||
_Note: Les rangs sont calculés sur la base des statistiques de l'utilisateur, voir [src/calculateRank.js](./src/calculateRank.js)_
|
||||
|
||||
### Cacher les statistiques individuelles
|
||||
|
||||
Pour masquer des statistiques spécifiques, vous pouvez passer un paramètre de requête `?hide=` avec des valeurs séparées par des virgules.
|
||||
|
||||
> Options: `&hide=stars,commits,prs,issues,contribs`
|
||||
|
||||
```md
|
||||

|
||||
```
|
||||
|
||||
### Ajouter le compte des contributions privées au compte des commits totaux
|
||||
|
||||
Vous pouvez ajouter le compte de toutes vos contributions privées au compte total des engagements en utilisant le paramètre de requête `?count_private=true`.
|
||||
|
||||
_Note: Si vous déployez vous-même ce projet, les contributions privées seront comptées par défaut ; sinon, vous devez choisir de partager les comptes de vos contributions privées._
|
||||
|
||||
> Options: `&count_private=true`
|
||||
|
||||
```md
|
||||

|
||||
```
|
||||
|
||||
### Afficher les icônes
|
||||
|
||||
Pour activer les icônes, vous pouvez passer `show_icons=true` dans le paramètre de requête, comme ceci :
|
||||
|
||||
```md
|
||||

|
||||
```
|
||||
|
||||
### Thèmes
|
||||
|
||||
Avec les thèmes intégrés, vous pouvez personnaliser l'apparence de la carte sans faire de [personnalisation manuelle](#customization).
|
||||
|
||||
Use `?theme=THEME_NAME` parameter like so :-
|
||||
|
||||
```md
|
||||

|
||||
```
|
||||
|
||||
#### Tous les thèmes intégrés :-
|
||||
|
||||
dark, radical, merko, gruvbox, tokyonight, onedark, cobalt, synthwave, highcontrast, dracula
|
||||
|
||||
<img src="https://res.cloudinary.com/anuraghazra/image/upload/v1595174536/grs-themes_l4ynja.png" alt="GitHub Readme Stat Themes" width="600px"/>
|
||||
|
||||
Vous pouvez consulter un aperçu de [tous les thèmes disponibles](./themes/README.md) ou consulter le [fichier de configuration des thèmes](./themes/index.js) & **vous pouvez également ajouter de nouveaux thèmes** si vous le souhaitez :D
|
||||
|
||||
### Personnalisation
|
||||
|
||||
Vous pouvez personnaliser l'apparence de votre `Carte des stats` ou `Carte de répo` comme vous le souhaitez avec les paramètres d'URL.
|
||||
|
||||
#### Options principales:
|
||||
|
||||
- `title_color` - Couleur du titre de la carte _(hex color)_
|
||||
- `text_color` - Couleur du texte _(hex color)_
|
||||
- `icon_color` - Couleur des icônes si disponibles _(hex color)_
|
||||
- `bg_color` - Couleur du fond de la carte _(hex color)_ **ou** un gradiant de la forme _angle,start,end_
|
||||
- `theme` - Nom du thème, parmis [tous les thèmes disponibles](./themes/README.md)
|
||||
- `cache_seconds` - Paramétrer le cache manuellement _(min: 1800, max: 86400)_
|
||||
|
||||
##### Gradient in bg_color
|
||||
|
||||
Vous pouvez fournir plusieurs valeurs (suivie d'une virgule) dans l'option bg_color pour rendre un degradé, le format du degradé est :-
|
||||
|
||||
```
|
||||
&bg_color=DEG,COLOR1,COLRO2,COLOR3...COLOR10
|
||||
```
|
||||
|
||||
> Note relative: Les cartes répo ont un cache par défaut de 30 minutes (1800 secondes) si le nombre de bifurcations et d'étoiles est inférieur à 1K, alors il est de 2 heures (7200). Notez également que la mémoire cache est limitée à 30 minutes au minimum et à 24 heures au maximum.
|
||||
|
||||
#### Stats Card Exclusive Options:
|
||||
|
||||
- `hide` - Masquer les éléments spécifiés dans les statistiques _(Comma seperated values)_
|
||||
- `hide_title` - Masquer le titre _(boolean)_
|
||||
- `hide_rank` - Masquer le rang _(boolean)_
|
||||
- `show_icons` - Afficher les icônes _(boolean)_
|
||||
- `include_all_commits` - Compter le total de commits au lieu de ne compter que les commits de l'année en cours _(boolean)_
|
||||
- `count_private` - Compter les commits privés _(boolean)_
|
||||
- `line_height` - Fixer la hauteur de la ligne entre les textes _(number)_
|
||||
|
||||
#### Repo Card Exclusive Options:
|
||||
|
||||
- `show_owner` - Affiche le nom du propriétaire du répo _(boolean)_
|
||||
|
||||
#### Language Card Exclusive Options:
|
||||
|
||||
- `hide` - Masquer les langages spécifiés sur la carte _(Comma seperated values)_
|
||||
- `hide_title` - Masquer le titre _(boolean)_
|
||||
- `layout` - Alterner entre 2 mise en page `default` & `compact`
|
||||
- `card_width` - Fixer la largeur de la carte manuellement _(number)_
|
||||
|
||||
> :warning: **Important:**
|
||||
> Les noms des langages doivent être en format uri, comme spécifié dans [Percent Encoding](https://fr.wikipedia.org/wiki/Percent-encoding)
|
||||
> (c'est-à-dire que: `c++` devrait devenir `c%2B%2B`, `jupyter notebook` devrait devenir `jupyter%20notebook`, etc.)
|
||||
|
||||
---
|
||||
|
||||
# GitHub Extra Pins
|
||||
|
||||
Les épingles supplémentaires GitHub vous permettent d'épingler plus de 6 repos dans votre profil en utilisant un profil GitHub readme.
|
||||
|
||||
Et OUI ! Vous n'êtes plus limité à 6 dépôts épinglés.
|
||||
|
||||
### Usage
|
||||
|
||||
Copiez-collez ce code dans votre readme et modifiez les liens.
|
||||
|
||||
Extrémité: `api/pin?username=anuraghazra&repo=github-readme-stats`
|
||||
|
||||
```md
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
```
|
||||
|
||||
### Démo
|
||||
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
|
||||
Utiliser la variable [show_owner](#customization) pour inclure l'username du propriétaire du repo.
|
||||
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
|
||||
# Carte des langages les + utilisés
|
||||
|
||||
La carte des langages principaux montre les langages les plus utilisées par les utilisateurs de GitHub.
|
||||
|
||||
_NOTE: Les langages affichés n'indiquent pas mon niveau de compétence ou quelque chose comme ça, c'est une métrique GitHub de quelles langages j'ai le plus de code sur GitHub, c'est une nouvelle fonctionnalité de github-readme-stats_
|
||||
|
||||
### Usage
|
||||
|
||||
Copiez-collez ce code dans votre readme et modifiez les liens.
|
||||
|
||||
Extrémité: `api/top-langs?username=anuraghazra`
|
||||
|
||||
```md
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
```
|
||||
|
||||
### Cacher certaines langages
|
||||
|
||||
Tu peux utiliser le paramètre `?hide=language1,language2` pour masquer les langages individuels.
|
||||
|
||||
```md
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
```
|
||||
|
||||
### Carte compacte des langages
|
||||
|
||||
Tu peux utiliser l'option `&layout=compact` pour changer le style de la carte.
|
||||
|
||||
```md
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
```
|
||||
|
||||
### Démo
|
||||
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
|
||||
- Carte compacte
|
||||
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
|
||||
---
|
||||
|
||||
### Toutes les démos
|
||||
|
||||
- Défaut
|
||||
|
||||

|
||||
|
||||
- Ne pas afficher des stats spécifiques
|
||||
|
||||

|
||||
|
||||
- Afficher les icônes
|
||||
|
||||

|
||||
|
||||
- Inclure tous les commits
|
||||
|
||||

|
||||
|
||||
- Thèmes
|
||||
|
||||
Choisissez parmi l'un des [thèmes par défaut](#themes)
|
||||
|
||||

|
||||
|
||||
- Dégradé
|
||||
|
||||

|
||||
|
||||
- Personnaliser la carte des stats
|
||||
|
||||

|
||||
|
||||
- Personnaliser la carte repo
|
||||
|
||||

|
||||
|
||||
- Top Langages
|
||||
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
|
||||
---
|
||||
|
||||
### Conseil rapide (Aligner les cartes des repos)
|
||||
|
||||
En général, vous ne pourrez pas mettre les images côte à côte. Pour ce faire, vous pouvez utiliser cette approche :
|
||||
|
||||
```md
|
||||
<a href="https://github.com/anuraghazra/github-readme-stats">
|
||||
<img align="left" src="https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra&repo=github-readme-stats" />
|
||||
</a>
|
||||
<a href="https://github.com/anuraghazra/convoychat">
|
||||
<img align="left" src="https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra&repo=convoychat" />
|
||||
</a>
|
||||
```
|
||||
|
||||
## Déployer sur votre propre instance Vercel
|
||||
|
||||
#### [Check Out Step By Step Video Tutorial By @codeSTACKr](https://youtu.be/n6d4KHSKqGk?t=107)
|
||||
|
||||
Comme l'API GitHub ne permet que 5k requêtes par heure, il est possible que mon `https://github-readme-stats.vercel.app/api` puisse atteindre le limiteur de débit. Si vous l'hébergez sur votre propre serveur Vercel, alors vous n'avez pas à vous soucier de quoi que ce soit. Cliquez sur le bouton de déploiement pour commencer !
|
||||
|
||||
NOTE: Depuis [#58](https://github.com/anuraghazra/github-readme-stats/pull/58) nous devrions être en mesure de traiter plus de 5 000 demandes et ne pas avoir de problèmes de temps d'arrêt :D
|
||||
|
||||
[](https://vercel.com/import/project?template=https://github.com/anuraghazra/github-readme-stats)
|
||||
|
||||
<details>
|
||||
<summary><b> Guide pour la mise en place de Vercel 🔨 </b></summary>
|
||||
|
||||
1. Allez sur [vercel.com](https://vercel.com/)
|
||||
1. Cliquez sur `Log in`
|
||||

|
||||
1. Connectez-vous avec GitHub en cliquant `Continue with GitHub`
|
||||

|
||||
1. Connectez-vous à GitHub et autorisez l'accès à tous les dépôts, si vous y êtes invité
|
||||
1. Fork ce repo
|
||||
1. Retournez au [dashboard Vercel](https://vercel.com/dashboard)
|
||||
1. Selectez `Import Project`
|
||||

|
||||
1. Selectez `Import Git Repository`
|
||||

|
||||
1. Choisissez root et gardez tout tel quel, ajoutez simplement votre variable d'environnement nommée PAT_1 (comme indiqué), qui contiendra un jeton d'accès personnel (PAT), que vous pouvez facilement créer [ici](https://github.com/settings/tokens/new) (laissez tout tel quel, nommez le simplement quelque chose, cela peut être tout ce que vous voulez)
|
||||

|
||||
1. Cliquez sur "déployer" et vous êtes prêt à partir. Voir vos domaines pour utiliser l'API !
|
||||
|
||||
</details>
|
||||
|
||||
## :sparkling_heart: Supporter le project
|
||||
|
||||
Je mets open-source presque tout ce que je peux, et j'essaie de répondre à tous ceux qui ont besoin d'aide en utilisant ces projets. Évidemment,
|
||||
cela prend du temps. Vous pouvez utiliser ce service gratuitement.
|
||||
|
||||
Cependant, si vous utilisez ce projet et que vous en êtes satisfait ou si vous voulez simplement m'encourager à continuer à créer, il y a quelques façons de le faire :-
|
||||
|
||||
- Donner un crédit approprié lorsque vous utilisez github-readme-stats sur votre readme, avec un lien vers celui-ci :D
|
||||
- Mettre une étoile et partager le projet :rocket:
|
||||
- [](https://www.paypal.me/anuraghazra) - Vous pouvez faire des dons uniques via PayPal. Je vais probablement acheter un ~~café~~ thé. :tea:
|
||||
|
||||
Merci! :heart:
|
||||
|
||||
---
|
||||
|
||||
Les Contributions sont les bienvenus! <3
|
||||
|
||||
Fais avec :heart: et JavaScript.
|
@ -1,344 +0,0 @@
|
||||
<p align="center">
|
||||
<img width="100px" src="https://res.cloudinary.com/anuraghazra/image/upload/v1594908242/logo_ccswme.svg" align="center" alt="GitHub Readme Stats" />
|
||||
<h2 align="center">GitHub Readme Stats</h2>
|
||||
<p align="center">Mostra nei tuoi README file le statistiche GitHub generate dinamicamente!</p>
|
||||
</p>
|
||||
<p align="center">
|
||||
<a href="https://github.com/anuraghazra/github-readme-stats/actions">
|
||||
<img alt="Tests Passing" src="https://github.com/anuraghazra/github-readme-stats/workflows/Test/badge.svg" />
|
||||
</a>
|
||||
<a href="https://codecov.io/gh/anuraghazra/github-readme-stats">
|
||||
<img src="https://codecov.io/gh/anuraghazra/github-readme-stats/branch/master/graph/badge.svg" />
|
||||
</a>
|
||||
<a href="https://github.com/anuraghazra/github-readme-stats/issues">
|
||||
<img alt="Issues" src="https://img.shields.io/github/issues/anuraghazra/github-readme-stats?color=0088ff" />
|
||||
</a>
|
||||
<a href="https://github.com/anuraghazra/github-readme-stats/pulls">
|
||||
<img alt="GitHub pull requests" src="https://img.shields.io/github/issues-pr/anuraghazra/github-readme-stats?color=0088ff" />
|
||||
</a>
|
||||
<br />
|
||||
<br />
|
||||
<a href="https://a.paddle.com/v2/click/16413/119403?link=1227">
|
||||
<img src="https://img.shields.io/badge/Supportato%20da-VSCode%20Power%20User%20%E2%86%92-gray.svg?colorA=655BE1&colorB=4F44D6&style=for-the-badge"/>
|
||||
</a>
|
||||
<a href="https://a.paddle.com/v2/click/16413/119403?link=2345">
|
||||
<img src="https://img.shields.io/badge/Supportato%20da-Node%20Cli.com%20%E2%86%92-gray.svg?colorA=61c265&colorB=4CAF50&style=for-the-badge"/>
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="#demo">Anteprima</a>
|
||||
·
|
||||
<a href="https://github.com/anuraghazra/github-readme-stats/issues/new/choose">Segnala un errore</a>
|
||||
·
|
||||
<a href="https://github.com/anuraghazra/github-readme-stats/issues/new/choose">Richiedi una nuova funzionalità</a>
|
||||
</p>
|
||||
<p align="center">
|
||||
<a href="/docs/readme_fr.md">Français </a>
|
||||
·
|
||||
<a href="/docs/readme_cn.md">简体中文</a>
|
||||
·
|
||||
<a href="/docs/readme_es.md">Español</a>
|
||||
·
|
||||
<a href="/docs/readme_de.md">Deutsch</a>
|
||||
·
|
||||
<a href="/docs/readme_ja.md">日本語</a>
|
||||
·
|
||||
<a href="/docs/readme_pt-BR.md">Português Brasileiro</a>
|
||||
·
|
||||
<a href="/docs/readme_it.md">Italiano</a>
|
||||
·
|
||||
<a href="/docs/readme_kr.md">한국어</a>
|
||||
</p>
|
||||
</p>
|
||||
<p align="center">Se ti piace questo progetto, considera la possibilità di <a href="https://www.paypal.me/anuraghazra">donare</a> per aiutare a renderlo migliore!
|
||||
|
||||
# Caratteristiche
|
||||
|
||||
- [Statistiche GitHub (GitHub Stats Card)](#github-stats-card)
|
||||
- [GitHub Extra Pin](#github-extra-pins)
|
||||
- [Linguaggi più usati (Top Languages Card)](#top-languages-card)
|
||||
- [Temi](#temi)
|
||||
- [Personalizzazione](#personalizzazione)
|
||||
- [Effettua il Deploy](#deploy-su-vercel)
|
||||
|
||||
# GitHub Stats Card
|
||||
|
||||
Per creare una Card con le statistiche GitHub, copia e incolla nel tuo file markdown, tutto qua: è semplice!
|
||||
|
||||
Ricorda di cambiare il valore `?username=` con il tuo nome utente GitHub.
|
||||
|
||||
```md
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
```
|
||||
|
||||
_Nota: I punteggi sono calcolati sulla base delle tue statistiche, dai un'occhiata a [src/calculateRank.js](./src/calculateRank.js) per ulteriori informazioni_
|
||||
|
||||
### Nascondere statistiche individuali
|
||||
|
||||
Per nascondere qualche dato, puoi aggiungere i parametri `?hide=`, separando i valori con una virgola.
|
||||
|
||||
> Opzioni: `&hide=stars,commits,prs,issues,contribs`
|
||||
|
||||
```md
|
||||

|
||||
```
|
||||
|
||||
### Includere i contributi privati nel computo totale
|
||||
|
||||
Puoi aggiungere i tuoi contributi privati al totale dei commit, utilizzando il parametro `?count_private=true`.
|
||||
|
||||
_Nota: se hai deciso di fare il deploy del progetto, i contributi privati verranno inclusi in automatico._
|
||||
|
||||
> Opzioni: `&count_private=true`
|
||||
|
||||
```md
|
||||

|
||||
```
|
||||
|
||||
### Mostrare le icone
|
||||
|
||||
Per abilitare le icone, puoi specificare `show_icons=true`, ad esempio:
|
||||
|
||||
```md
|
||||

|
||||
```
|
||||
|
||||
### Temi
|
||||
|
||||
Esistono alcuni temi predefiniti coi quali è possibile personalizzare l'aspetto delle card. In alternativa, è possibile effettuare una [personalizzazione manuale](#personalizzazione).
|
||||
|
||||
Usa il parametro `?theme=NOME_TEMA` in questo modo:-
|
||||
|
||||
```md
|
||||

|
||||
```
|
||||
|
||||
#### Galleria dei temi:-
|
||||
|
||||
dark, radical, merko, gruvbox, tokyonight, onedark, cobalt, synthwave, highcontrast, dracula
|
||||
|
||||
<img src="https://res.cloudinary.com/anuraghazra/image/upload/v1595174536/grs-themes_l4ynja.png" alt="GitHub Readme Stat Themes" width="600px"/>
|
||||
|
||||
Puoi avere un'anteprima di [tutti i temi supportati](./themes/README.md) o controllare il [file di configurazione dei temi](./themes/index.js) e **puoi anche contribuire creando un nuovo tema** se vuoi :D
|
||||
|
||||
### Personalizzazione
|
||||
|
||||
Puoi personalizzare l'aspetto delle tue `Stats Card` o delle `Repo Card` in qualsiasi modo, semplicemente modificando i parametri dell'URL.
|
||||
|
||||
#### Opzioni comuni:
|
||||
|
||||
- `title_color` - Colore del titolo _(in esadecimale)_
|
||||
- `text_color` - Colore del testo _(in esadecimale)_
|
||||
- `icon_color` - Colore delle icone, se disponibili _(in esadecimale)_
|
||||
- `bg_color` - Colore dello sfondo _(in esadecimale)_ **oppure** un gradiente nella forma _angolo,inizio,fine_
|
||||
- `theme` - Nome del tema, dai un'occhiata a [tutti i temi disponibili](./themes/README.md)
|
||||
- `cache_seconds` - Specifica manualmente il valore di cache, in secondi _(min: 1800, max: 86400)_
|
||||
|
||||
##### Gradiente nello sfondo
|
||||
|
||||
Puoi fornire valori separati da virgola nel parametro bg_color per creare un gradiente, il cui formato è:-
|
||||
|
||||
```
|
||||
&bg_color=DEG,COLOR1,COLRO2,COLOR3...COLOR10
|
||||
```
|
||||
|
||||
> Nota sulla cache: le card hanno un valore di cache di 4 ore (14400 seconds) di default se il numero di fork & il numero di stelle è inferiore a 1000; altrimenti è pari a 2 ore (7200).
|
||||
|
||||
#### Opzioni valide solo per le card delle statistiche:
|
||||
|
||||
- `hide` - Nasconde gli oggetti selezionati _(valori separati da virgola)_
|
||||
- `hide_title` - Nasconde il titolo _(booleano)_
|
||||
- `hide_rank` - Nasconde il punteggio _(booleano)_
|
||||
- `show_icons` - Mostra le icone _(booleano)_
|
||||
- `include_all_commits` - Mostra tutti i commit e non solo quelli dell'anno corrente _(booleano)_
|
||||
- `count_private` - Include i contributi privati _(booleano)_
|
||||
- `line_height` - Specifica il valore dell'altezza di riga _(numero)_
|
||||
|
||||
#### Opzioni valide solo per le Repo Card:
|
||||
|
||||
- `show_owner` - Mostra il nome utente del proprietario _(booleano)_
|
||||
|
||||
#### Opzioni valide solo per le card dei linguaggi:
|
||||
|
||||
- `hide` - Nasconde un linguaggio specifico _(valori separati da virgola)_
|
||||
- `hide_title` - Nasconde il titolo _(booleano)_
|
||||
- `layout` - Specifica il tipo di layout, `default` (esteso) o `compact` (compatto)
|
||||
- `card_width` - Specifica il valore della larghezza _(numero)_
|
||||
|
||||
> :warning: **Importante:**
|
||||
> Per i nomi dei linguaggi, assicurati di effettuare l'encoding giusto nell'uri, come specificato in [Percent Encoding](https://en.wikipedia.org/wiki/Percent-encoding)
|
||||
> (ad esempio: `c++` diventa `c%2B%2B`, `jupyter notebook` diventa `jupyter%20notebook`, ecc.)
|
||||
|
||||
---
|
||||
|
||||
# GitHub Extra Pins
|
||||
|
||||
GitHub Extra Pins ti permette di fissare in alto più di 6 repository nel tuo profilo, sfruttando il README del profilo.
|
||||
|
||||
### Utilizzo
|
||||
|
||||
Copia e incolla il seguente codice, premurandoti di cambiare il link.
|
||||
|
||||
Endpoint: `api/pin?username=anuraghazra&repo=github-readme-stats`
|
||||
|
||||
```md
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
```
|
||||
|
||||
### Demo
|
||||
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
|
||||
Usa la variabile [show_owner](#personalizzazione) per includere il nome utente del proprietario
|
||||
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
|
||||
# Top Languages Card
|
||||
|
||||
La Top Languages Card mostra i linguaggi che utilizzi di più su GitHub.
|
||||
|
||||
_NOTA: questa card non indica il livello di abilità, ma piuttosto quanto codice hai scritto in un determinato linguaggio_
|
||||
|
||||
### Utilizzo
|
||||
|
||||
Copia e incolla nel tuo file README, cambiando i link.
|
||||
|
||||
Endpoint: `api/top-langs?username=anuraghazra`
|
||||
|
||||
```md
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
```
|
||||
|
||||
### Nascondi linguaggi specifici
|
||||
|
||||
Puoi utilizzare il parametro `?hide=linguaggio1,linguaggio2` per nascondere alcuni linguaggi.
|
||||
|
||||
```md
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
```
|
||||
|
||||
### Layout compatto
|
||||
|
||||
Puoi utilizzare l'opzione `&layout=compact` per cambiare l'aspetto della card.
|
||||
|
||||
```md
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
```
|
||||
|
||||
### Demo
|
||||
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
|
||||
- Layout Compatto
|
||||
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
|
||||
---
|
||||
|
||||
### Galleria di esempi
|
||||
|
||||
- Default
|
||||
|
||||

|
||||
|
||||
- Nascondere dati specifici
|
||||
|
||||

|
||||
|
||||
- Mostrare le icone
|
||||
|
||||

|
||||
|
||||
- Includere tutti i commit
|
||||
|
||||

|
||||
|
||||
- Temi
|
||||
|
||||
Scegli uno dei [temi di default](#themes)
|
||||
|
||||

|
||||
|
||||
- Gradiente
|
||||
|
||||

|
||||
|
||||
- Personalizzare le Stats Card
|
||||
|
||||

|
||||
|
||||
- Personalizzare le Repo Card
|
||||
|
||||

|
||||
|
||||
- Linguaggi più usati
|
||||
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
|
||||
---
|
||||
|
||||
### Consiglio veloce (Allineare le Card)
|
||||
|
||||
Per allineare le card una accanto all'altra, puoi adottare questo approccio:
|
||||
|
||||
```md
|
||||
<a href="https://github.com/anuraghazra/github-readme-stats">
|
||||
<img align="center" src="https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra&repo=github-readme-stats" />
|
||||
</a>
|
||||
<a href="https://github.com/anuraghazra/convoychat">
|
||||
<img align="center" src="https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra&repo=convoychat" />
|
||||
</a>
|
||||
```
|
||||
|
||||
## Deploy su Vercel
|
||||
|
||||
#### [Guarda questo Video Tutorial, realizzato da @codeSTACKr](https://youtu.be/n6d4KHSKqGk?t=107)
|
||||
|
||||
Since the GitHub API only allows 5k requests per hour, it is possible that my `https://github-readme-stats.vercel.app/api` could hit the rate limiter. If you host it on your own Vercel server, then you don't have to worry about anything. Click on the deploy button to get started!
|
||||
|
||||
NOTE: Since [#58](https://github.com/anuraghazra/github-readme-stats/pull/58) we should be able to handle more than 5k requests and have no issues with downtime :D
|
||||
|
||||
[](https://vercel.com/import/project?template=https://github.com/anuraghazra/github-readme-stats)
|
||||
|
||||
<details>
|
||||
<summary><b> Guide on setting up Vercel 🔨 </b></summary>
|
||||
|
||||
1. Go to [vercel.com](https://vercel.com/)
|
||||
1. Click on `Log in`
|
||||

|
||||
1. Sign in with GitHub by pressing `Continue with GitHub`
|
||||

|
||||
1. Sign into GitHub and allow access to all repositories, if prompted
|
||||
1. Fork this repo
|
||||
1. Go back to your [Vercel dashboard](https://vercel.com/dashboard)
|
||||
1. Select `Import Project`
|
||||

|
||||
1. Select `Import Git Repository`
|
||||

|
||||
1. Select root and keep everything as is, just add your environment variable named PAT_1 (as shown), which will contain a personal access token (PAT), which you can easily create [here](https://github.com/settings/tokens/new) (leave everything as is, just name it something, it can be anything you want)
|
||||

|
||||
1. Click deploy, and you're good to go. See your domains to use the API!
|
||||
|
||||
</details>
|
||||
|
||||
## :sparkling_heart: Supporta il progetto
|
||||
|
||||
Rendo open-source quasi tutto ciò che posso e provo a rispondere a chiunque sia in difficoltà nell'utilizzare questi progetti. Ovviamente, mi richiede del tempo.
|
||||
Puoi utilizzare questo servizio gratuitamente.
|
||||
|
||||
Tuttavia, se usi il progetto e ti piace e vuoi sostenermi, puoi:-
|
||||
|
||||
- Dare il giusto riconoscimento quando usi github-readme-stats nei tuoi readme, includendo un link :D
|
||||
- Mettere una stella e condividere il progetto :rocket:
|
||||
- [](https://www.paypal.me/anuraghazra) - Fare una donazione via PayPal. Probabilmente compreròun ~~caffè~~ tè. :tea:
|
||||
|
||||
Grazie! :heart:
|
||||
|
||||
---
|
||||
|
||||

|
||||
|
||||
I contributi sono benvenuti! <3
|
||||
|
||||
Realizzato col :heart: e in JavaScript.
|
@ -1,347 +0,0 @@
|
||||
<p align="center">
|
||||
<img width="100px" src="https://res.cloudinary.com/anuraghazra/image/upload/v1594908242/logo_ccswme.svg" align="center" alt="GitHub Readme Stats" />
|
||||
<h2 align="center">GitHub Readme Stats</h2>
|
||||
<p align="center">あなたの README に自動生成された GitHub の統計情報を載せましょう!</p>
|
||||
</p>
|
||||
<p align="center">
|
||||
<a href="https://github.com/anuraghazra/github-readme-stats/actions">
|
||||
<img alt="Tests Passing" src="https://github.com/anuraghazra/github-readme-stats/workflows/Test/badge.svg" />
|
||||
</a>
|
||||
<a href="https://codecov.io/gh/anuraghazra/github-readme-stats">
|
||||
<img src="https://codecov.io/gh/anuraghazra/github-readme-stats/branch/master/graph/badge.svg" />
|
||||
</a>
|
||||
<a href="https://github.com/anuraghazra/github-readme-stats/issues">
|
||||
<img alt="Issues" src="https://img.shields.io/github/issues/anuraghazra/github-readme-stats?color=0088ff" />
|
||||
</a>
|
||||
<a href="https://github.com/anuraghazra/github-readme-stats/pulls">
|
||||
<img alt="GitHub pull requests" src="https://img.shields.io/github/issues-pr/anuraghazra/github-readme-stats?color=0088ff" />
|
||||
</a>
|
||||
<br />
|
||||
<br />
|
||||
<a href="https://a.paddle.com/v2/click/16413/119403?link=1227">
|
||||
<img src="https://img.shields.io/badge/Supported%20by-VSCode%20Power%20User%20%E2%86%92-gray.svg?colorA=655BE1&colorB=4F44D6&style=for-the-badge"/>
|
||||
</a>
|
||||
<a href="https://a.paddle.com/v2/click/16413/119403?link=2345">
|
||||
<img src="https://img.shields.io/badge/Supported%20by-Node%20Cli.com%20%E2%86%92-gray.svg?colorA=61c265&colorB=4CAF50&style=for-the-badge"/>
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="#demo">View Demo</a>
|
||||
·
|
||||
<a href="https://github.com/anuraghazra/github-readme-stats/issues/new/choose">Report Bug</a>
|
||||
·
|
||||
<a href="https://github.com/anuraghazra/github-readme-stats/issues/new/choose">Request Feature</a>
|
||||
</p>
|
||||
<p align="center">
|
||||
<a href="/docs/readme_fr.md">Français</a>
|
||||
·
|
||||
<a href="/docs/readme_cn.md">简体中文</a>
|
||||
·
|
||||
<a href="/docs/readme_es.md">Español</a>
|
||||
·
|
||||
<a href="/docs/readme_de.md">Deutsch</a>
|
||||
·
|
||||
<a href="/docs/readme_ja.md">日本語</a>
|
||||
·
|
||||
<a href="/docs/readme_pt-BR.md">Português Brasileiro</a>
|
||||
·
|
||||
<a href="/docs/readme_it.md">Italiano</a>
|
||||
·
|
||||
<a href="/docs/readme_kr.md">한국어</a>
|
||||
</p>
|
||||
</p>
|
||||
<p align="center">このプロジェクトを気に入っていただけましたか?<br>もしよろしければ、プロジェクトのさらなる改善のために<a href="https://www.paypal.me/anuraghazra">寄付</a>を検討して頂けると嬉しいです!</p>
|
||||
|
||||
# 主な機能
|
||||
|
||||
- [GitHub Stats Card](#github-stats-card)
|
||||
- [GitHub Extra Pins](#github-extra-pins)
|
||||
- [Top Languages Card](#top-languages-card)
|
||||
- [Themes](#テーマの変更)
|
||||
- [Customization](#テーマを自分でカスタマイズする)
|
||||
- [Deploy Yourself](#自分の-Vercel-インスタンスにデプロイする)
|
||||
|
||||
# GitHub Stats Card
|
||||
|
||||
以下のコードをコピーして、あなたの Markdown ファイルに貼り付けるだけです。
|
||||
簡単ですね!
|
||||
|
||||
`?username=` の値は、あなたの GitHub アカウントのユーザー名に変更してください。
|
||||
|
||||
```md
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
```
|
||||
|
||||
_Note: カードに表示されるランクはユーザの統計情報に基づいて計算されています。詳しくは、[src/calculateRank.js](../src/calculateRank.js)をご覧ください。_
|
||||
|
||||
### 特定の統計情報を隠す
|
||||
|
||||
クエリパラメータ `?hide=` に値をカンマ区切りで渡すことで、特定の統計情報を隠すことができます。
|
||||
|
||||
> Options: `&hide=stars,commits,prs,issues,contribs`
|
||||
|
||||
```md
|
||||

|
||||
```
|
||||
|
||||
### プライベートリポジトリへのコミットをカウントする
|
||||
|
||||
クエリパラメータ `?count_private=true` を使用することで、プライベートリポジトリへのコミット数を総数に追加することができます。
|
||||
|
||||
_Note: このプロジェクトを自分でデプロイしている場合、デフォルトではプライベートリポジトリへのコミットがカウントされます。_
|
||||
|
||||
> Options: `&count_private=true`
|
||||
|
||||
```md
|
||||

|
||||
```
|
||||
|
||||
### アイコンを表示する
|
||||
|
||||
クエリパラメータ `?show_icons=true` を使用することで、アイコンの表示が有効になります。
|
||||
|
||||
```md
|
||||

|
||||
```
|
||||
|
||||
### テーマの変更
|
||||
|
||||
内蔵されているテーマを使用すれば、[手動のカスタマイズ](#customization)を行うことなくカードの外観を変更することができます。
|
||||
|
||||
`?theme=THEME_NAME` は以下のように使います。
|
||||
|
||||
```md
|
||||

|
||||
```
|
||||
|
||||
#### 内蔵テーマの一覧
|
||||
|
||||
dark, radical, merko, gruvbox, tokyonight, onedark, cobalt, synthwave, highcontrast, dracula
|
||||
|
||||
<img src="https://res.cloudinary.com/anuraghazra/image/upload/v1595174536/grs-themes_l4ynja.png" alt="GitHub Readme Stat Themes" width="600px"/>
|
||||
|
||||
その他の使用可能なテーマの[プレビュー](../themes/README.md)や[設定ファイル](../themes/index.js)もご覧ください。もしよろしければ、**新しいテーマを投稿してみてください** :smile:
|
||||
|
||||
### テーマを自分でカスタマイズする
|
||||
|
||||
`Stats Card` や `Repo Card` の外観を URL パラメータを使って好きなようにカスタマイズすることができます。
|
||||
|
||||
#### 共通のオプション
|
||||
|
||||
- `title_color` - タイトルの色 _(16 進数カラーコード)_
|
||||
- `text_color` - 中身のテキストの色 _(16 進数カラーコード)_
|
||||
- `icon_color` - アイコンの色(変更可能な場合のみ) _(16 進数カラーコード)_
|
||||
- `bg_color` - 背景の色 _(16 進数カラーコード)_ **または** _angle,start,end_ の形式でグラデーションを指定することも可
|
||||
- `theme` - [使用可能なテーマ一覧](../themes/README.md) から選んだテーマ名
|
||||
- `cache_seconds` - キャッシュ時間の秒数 _(最小値: 1800, 最大値: 86400)_
|
||||
|
||||
##### bg_color の グラデーション指定
|
||||
|
||||
bg_color オプションで複数のカンマ区切りの値を指定してグラデーションをレンダリングすることができます。フォーマットは以下の通りになります。
|
||||
|
||||
```
|
||||
&bg_color=DEG,COLOR1,COLRO2,COLOR3...COLOR10
|
||||
```
|
||||
|
||||
> キャッシュに関する注意点: Repo cards のデフォルトのキャッシュは、フォーク数とスター数が 1k 未満の場合は 30 分(1800 秒) で、それ以外の場合は 2 時間(7200) です。また、キャッシュは最低でも 30 分、最大でも 24 時間に制限されていることに注意してください。
|
||||
|
||||
#### Stats Card だけに存在するオプション
|
||||
|
||||
- `hide` - 特定の統計情報を隠す _(カンマ区切りで指定)_
|
||||
- `hide_title` - _(boolean)_
|
||||
- `hide_rank` - _(boolean)_
|
||||
- `show_icons` - _(boolean)_
|
||||
- `include_all_commits` - 今年度のコミット数だけでなく、コミット数の総数をカウントする _(boolean)_
|
||||
- `count_private` - プライベートリポジトリへのコミットをカウントする _(boolean)_
|
||||
- `line_height` - テキストの行の高さ _(number)_
|
||||
|
||||
#### Repo Card だけに存在するオプション
|
||||
|
||||
- `show_owner` - リポジトリのオーナーを表示する _(boolean)_
|
||||
|
||||
#### Language Card だけに存在するオプション
|
||||
|
||||
- `hide` - 特定の言語を隠す _(カンマ区切りで指定)_
|
||||
- `hide_title` - _(boolean)_
|
||||
- `layout` - `default` か `compact` のいずれかのレイアウトに切り替える
|
||||
- `card_width` - カードの横幅 _(number)_
|
||||
|
||||
> :warning: **重要:**
|
||||
> [Percent Encoding](https://en.wikipedia.org/wiki/Percent-encoding) で指定されているように、プログラミング言語の名前は URL エンコードされている必要があります。
|
||||
> (例: `c++` は `c%2B%2B`, `jupyter notebook` は `jupyter%20notebook`, など)
|
||||
|
||||
---
|
||||
|
||||
# GitHub Extra Pins
|
||||
|
||||
GitHub extra pins を使うと、GitHub の readme プロフィールを使って、自分のプロフィールに 6 つ以上のリポジトリをピン留めすることができます。
|
||||
|
||||
やったー! もはや、リポジトリをピン留めできる数が 6 つに制限されることはありません。
|
||||
|
||||
### 使い方
|
||||
|
||||
以下のコードをあなたの readme にコピー & ペーストし、リンクを変更してください。
|
||||
|
||||
エンドポイント: `api/pin?username=anuraghazra&repo=github-readme-stats`
|
||||
|
||||
```md
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
```
|
||||
|
||||
### デモ
|
||||
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
|
||||
リポジトリのオーナーのユーザー名を含める場合は、show_owner 変数を使用します。
|
||||
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
|
||||
# Top Languages Card
|
||||
|
||||
Top languages card には、その GitHub ユーザーが最も利用している Top languages が表示されます。
|
||||
|
||||
_NOTE: Top languages は、ユーザのスキルレベルを示すものではなく、GitHub 上でどの言語で最も多くのコードを書いているかを示す GitHub の指標です。_
|
||||
|
||||
### 使い方
|
||||
|
||||
以下のコードをあなたの readme にコピー & ペーストし、リンクを変更してください。
|
||||
|
||||
エンドポイント: `api/top-langs?username=anuraghazra`
|
||||
|
||||
```md
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
```
|
||||
|
||||
### 特定の言語を隠す
|
||||
|
||||
クエリパラメータ `?hide=language1,language2` 使用することで、特定の言語を非表示にすることができます。
|
||||
|
||||
```md
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
```
|
||||
|
||||
### レイアウトをコンパクトにする
|
||||
|
||||
クエリパラメータ `&layout=compact` を使用することで、カードのデザインを変更することができます。
|
||||
|
||||
```md
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
```
|
||||
|
||||
### デモ
|
||||
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
|
||||
- Compact layout の場合
|
||||
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
|
||||
---
|
||||
|
||||
### 全てのデモ
|
||||
|
||||
- デフォルト
|
||||
|
||||

|
||||
|
||||
- 特定の統計情報を隠す
|
||||
|
||||

|
||||
|
||||
- アイコンを表示する
|
||||
|
||||

|
||||
|
||||
- コミット数の総数をカウントする
|
||||
|
||||

|
||||
|
||||
- テーマの変更
|
||||
|
||||
任意の[テーマ](#themes)を選択できます。
|
||||
|
||||

|
||||
|
||||
- グラデーション
|
||||
|
||||

|
||||
|
||||
- stats card のカスタマイズ
|
||||
|
||||

|
||||
|
||||
- repo card のカスタマイズ
|
||||
|
||||

|
||||
|
||||
- Top languages
|
||||
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
|
||||
---
|
||||
|
||||
### クイックヒント (カードを並べる)
|
||||
|
||||
通常、画像を並べてレイアウトすることはできません。画像を並べるには、以下のような方法があります。
|
||||
|
||||
```md
|
||||
<a href="https://github.com/anuraghazra/github-readme-stats">
|
||||
<img align="left" src="https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra&repo=github-readme-stats" />
|
||||
</a>
|
||||
<a href="https://github.com/anuraghazra/convoychat">
|
||||
<img align="left" src="https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra&repo=convoychat" />
|
||||
</a>
|
||||
```
|
||||
|
||||
## 自分の Vercel インスタンスにデプロイする
|
||||
|
||||
#### [@codeSTACKr によるチュートリアルはこちら](https://youtu.be/n6d4KHSKqGk?t=107)
|
||||
|
||||
GitHub API は 1 時間あたり 5k リクエストしか受け付けていないので、私の `https://github-readme-stats.vercel.app/api` がレートリミッターを超えてしまう可能性があります。自分の Vercel サーバーでホストしているのであれば、何も心配する必要はありません。デプロイボタンをクリックして始めましょう!
|
||||
|
||||
NOTE: [#58](https://github.com/anuraghazra/github-readme-stats/pull/58) 以降は 5k 以上のリクエストに対応できるようになり、ダウンタイムの問題もなくなりました :smile:
|
||||
|
||||
[](https://vercel.com/import/project?template=https://github.com/anuraghazra/github-readme-stats)
|
||||
|
||||
<details>
|
||||
<summary>Vercelの設定ガイド</summary>
|
||||
|
||||
1. [vercel.com](https://vercel.com/)に行きます。
|
||||
1. `Log in`をクリックします。
|
||||

|
||||
1. `Continue with GitHub` を押して GitHub にサインインします。
|
||||

|
||||
1. GitHub にサインインし、すべてのリポジトリへのアクセスを許可します。
|
||||
1. このリポジトリをフォークします。
|
||||
1. [Vercel dashboard](https://vercel.com/dashboard)に戻ります。
|
||||
1. `Import Project` を選択します。
|
||||

|
||||
1. `Import Git Repository` を選択します。
|
||||

|
||||
1. root を選択して、すべてをそのままにしておき、PAT_1 という名前の環境変数を(下図のように)追加します。これには個人アクセストークン (PAT) が含まれており、[ここ](https://github.com/settings/tokens/new)で簡単に作成することができます (すべてをそのままにしておいて、何かに名前を付けてください。)
|
||||

|
||||
1. デプロイをクリックすれば完了です。API を使用するためにあなたのドメインを参照してください!
|
||||
|
||||
</details>
|
||||
|
||||
## :sparkling_heart: このプロジェクトを支援する
|
||||
|
||||
私はできる限りのことをオープンソースで行い、また、このプロジェクトを利用する上で困っている皆さん全員に返信するようにしています。もちろん返信には時間が掛かる場合がありますが。
|
||||
このプロジェクトは無料でご利用いただけます。
|
||||
|
||||
しかしながら、もしあなたがこのプロジェクトに満足しているのであれば、あるいはただ、私がソフトウェアを作り続けるよう励ましたいのであれば、いくつかの方法があります。
|
||||
|
||||
- あなたの readme で github-readme-stats を使用して適切なクレジットを付与し、それにリンクします :smile:
|
||||
- このプロジェクトにスターを贈り、他の人達にもシェアしてください :rocket:
|
||||
- [](https://www.paypal.me/anuraghazra) - PayPal を介して 1 回限りの寄付を行うことができます。私はおそらく ~~コーヒー~~ お茶を買うでしょう。 :tea:
|
||||
|
||||
Thanks! :heart:
|
||||
|
||||
---
|
||||
|
||||

|
||||
|
||||
コントリビュートは大歓迎です! :heart_eyes:
|
||||
|
||||
このプロジェクトは :heart: と JavaScript で作られています。
|
@ -1,332 +0,0 @@
|
||||
<p align="center">
|
||||
<img width="100px" src="https://res.cloudinary.com/anuraghazra/image/upload/v1594908242/logo_ccswme.svg" align="center" alt="GitHub Readme Stats" />
|
||||
<h2 align="center">GitHub Readme Stats</h2>
|
||||
<p align="center">동적으로 생성된 Github의 통계를 여러분의 README에 올려보세요!</p>
|
||||
</p>
|
||||
<p align="center">
|
||||
<a href="https://github.com/anuraghazra/github-readme-stats/actions">
|
||||
<img alt="Tests Passing" src="https://github.com/anuraghazra/github-readme-stats/workflows/Test/badge.svg" />
|
||||
</a>
|
||||
<a href="https://codecov.io/gh/anuraghazra/github-readme-stats">
|
||||
<img src="https://codecov.io/gh/anuraghazra/github-readme-stats/branch/master/graph/badge.svg" />
|
||||
</a>
|
||||
<a href="https://github.com/anuraghazra/github-readme-stats/issues">
|
||||
<img alt="Issues" src="https://img.shields.io/github/issues/anuraghazra/github-readme-stats?color=0088ff" />
|
||||
</a>
|
||||
<a href="https://github.com/anuraghazra/github-readme-stats/pulls">
|
||||
<img alt="GitHub pull requests" src="https://img.shields.io/github/issues-pr/anuraghazra/github-readme-stats?color=0088ff" />
|
||||
</a>
|
||||
<br />
|
||||
<br />
|
||||
<a href="https://a.paddle.com/v2/click/16413/119403?link=1227">
|
||||
<img src="https://img.shields.io/badge/Supported%20by-VSCode%20Power%20User%20%E2%86%92-gray.svg?colorA=655BE1&colorB=4F44D6&style=for-the-badge"/>
|
||||
</a>
|
||||
<a href="https://a.paddle.com/v2/click/16413/119403?link=2345">
|
||||
<img src="https://img.shields.io/badge/Supported%20by-Node%20Cli.com%20%E2%86%92-gray.svg?colorA=61c265&colorB=4CAF50&style=for-the-badge"/>
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="#데모">View Demo</a>
|
||||
·
|
||||
<a href="https://github.com/anuraghazra/github-readme-stats/issues/new/choose">Report Bug</a>
|
||||
·
|
||||
<a href="https://github.com/anuraghazra/github-readme-stats/issues/new/choose">Request Feature</a>
|
||||
</p>
|
||||
<p align="center">
|
||||
<a href="/docs/readme_fr.md">Français</a>
|
||||
·
|
||||
<a href="/docs/readme_cn.md">简体中文</a>
|
||||
·
|
||||
<a href="/docs/readme_es.md">Español</a>
|
||||
·
|
||||
<a href="/docs/readme_de.md">Deutsch</a>
|
||||
·
|
||||
<a href="/docs/readme_ja.md">日本語</a>
|
||||
·
|
||||
<a href="/docs/readme_pt-BR.md">Português Brasileiro</a>
|
||||
·
|
||||
<a href="/docs/readme_it.md">Italiano</a>
|
||||
·
|
||||
<a href="/docs/readme_kr.md">한국어</a>
|
||||
</p>
|
||||
</p>
|
||||
<p align="center">이 프로젝트가 마음에 드나요? 괜찮으시다면 더 나은 개선을 위해 <a href="https://www.paypal.me/anuraghazra">기부</a>를 고려해주세요!
|
||||
|
||||
# Features
|
||||
|
||||
- [GitHub Stats Card](#github-stats-card)
|
||||
- [GitHub Extra Pins](#github-extra-pins)
|
||||
- [상위 언어 카드](#상위-언어-카드)
|
||||
- [테마](#테마)
|
||||
- [사용자정의](#사용자정의)
|
||||
- [직접 배포하기](#자체-Vercel-인스턴스에-배포하기)
|
||||
|
||||
# GitHub Stats Card
|
||||
|
||||
아래 코드를 복사해서 당신의 마크다운 파일에 넣으면 됩니다. 간단합니다!
|
||||
|
||||
`?username=` 영역의 값은 당신의 Github 계정의 이름으로 바꿔주세요.
|
||||
|
||||
```md
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
```
|
||||
|
||||
_참고: 순위는 사용자의 통계를 기반으로 계산됩니다. [src/calculateRank.js](../src/calculateRank.js) 참고_
|
||||
|
||||
### 개별 통계 숨기기
|
||||
|
||||
특정 통계를 숨기려면 콤마로 구분된 값을 `?hide=` 쿼리 파라미터 값으로 나열하면 됩니다.
|
||||
|
||||
> 예시: `&hide=stars,commits,prs,issues,contribs`
|
||||
|
||||
```md
|
||||

|
||||
```
|
||||
|
||||
### 총 커밋 수에 private 컨트리뷰트 개수 추가하기
|
||||
|
||||
`?count_private=true` 쿼리 파라미터를 사용하면 총 커밋 수에 private 컨트리뷰트 개수를 추가할 수 있습니다.
|
||||
|
||||
_참고: 이 프로젝트를 직접 배포하는 경우 private 컨트리뷰트는 기본적으로 계산됩니다. 그렇지 않은 경우 private 컨트리뷰트 개수를 추가하도록 설정해야 합니다._
|
||||
|
||||
> 예시: `&count_private=true`
|
||||
|
||||
```md
|
||||

|
||||
```
|
||||
|
||||
### 아이콘 표기
|
||||
|
||||
아이콘을 활성화하려면 다음과 같이 `show_icons=true` 쿼리 파라미터를 사용하세요.
|
||||
|
||||
```md
|
||||

|
||||
```
|
||||
|
||||
### 테마
|
||||
|
||||
내장된 테마를 사용하여 수동 [사용자정의](#사용자정의)할 필요 없이 카드의 모양을 커스터마이징할 수 있습니다.
|
||||
|
||||
아래와 같이 `?theme=THEME_NAME` 파라미터를 사용하세요. :-
|
||||
|
||||
```md
|
||||

|
||||
```
|
||||
|
||||
#### 모든 내장된 테마 :-
|
||||
|
||||
dark, radical, merko, gruvbox, tokyonight, onedark, cobalt, synthwave, highcontrast, dracula
|
||||
|
||||
<img src="https://res.cloudinary.com/anuraghazra/image/upload/v1595174536/grs-themes_l4ynja.png" alt="GitHub Readme Stat Themes" width="600px"/>
|
||||
|
||||
[사용 가능한 모든 테마](../themes/README.md)의 미리보기와 [테마 설정 파일](../themes/index.js)을 확인할 수 있습니다. 괜찮으시다면 **새로운 테마를 만드셔서, 코드를 기여** 해주세요 :D
|
||||
|
||||
### 사용자정의
|
||||
|
||||
URL 파라미터를 사용하여 원하는대로 `Stats Card` 또는 `Repo Card` 모양을 사용자 정의할 수 있습니다.
|
||||
|
||||
#### Common Options:
|
||||
|
||||
- `title_color` - 카드 제목 색상 _(hex color)_
|
||||
- `text_color` - 본문 글자 색상 _(hex color)_
|
||||
- `icon_color` - 아이콘 색상(활성화된 경우) _(hex color)_
|
||||
- `bg_color` - 카드 배경 색상 _(hex color)_
|
||||
- `theme` - 테마의 이름, [사용 가능한 모든 테마](../themes/README.md)에서 선택
|
||||
- `cache_seconds` - 캐시 헤더를 수동으로 설정 _(min: 1800, max: 86400)_
|
||||
|
||||
> 캐시 관련 참고: Repo 카드는 fork 개수와 star 카운트가 1천 개 미만인 경우 기본 캐시가 30분(1800초)이고, 그렇지 않은 경우 2시간(7200초) 입니다. 또한 캐시는 최소 30분 및 최대 24시간으로 고정됩니다.
|
||||
|
||||
#### Stats Card의 제외 옵션:
|
||||
|
||||
- `hide` - 통계에서 특정 항목을 제외한다. _(콤마로 구분된 값)_
|
||||
- `hide_title` - _(boolean)_
|
||||
- `hide_rank` - _(boolean)_
|
||||
- `show_icons` - _(boolean)_
|
||||
- `include_all_commits` - 현재 년도 대신 전체 커밋 개수 카운트 _(boolean)_
|
||||
- `count_private` - private 커밋도 카운트 _(boolean)_
|
||||
- `line_height` - 글자 사이의 line-height 값 설정(자간) _(number)_
|
||||
|
||||
#### Repo Card의 제외 옵션:
|
||||
|
||||
- `show_owner` - repo의 소유자 이름 표기 _(boolean)_
|
||||
|
||||
#### Language Card의 제외 옵션:
|
||||
|
||||
- `hide` - 카드에서 특정 언어 숨기기 _(콤마로 구분된 값)_
|
||||
- `hide_title` - _(boolean)_
|
||||
- `layout` - `default` & `compact` 레이아웃 간의 전환
|
||||
- `card_width` - 카드의 너비를 수동으로 설정 _(숫자)_
|
||||
|
||||
> :warning: **중요:**
|
||||
> 언어 이름은 URI 이스케이프 처리되어야 합니다. [Percent Encoding](https://en.wikipedia.org/wiki/Percent-encoding)를 참고하세요.
|
||||
> (i.e: `c++` 는 `c%2B%2B`, `jupyter notebook` 는 `jupyter%20notebook`, etc.)
|
||||
|
||||
---
|
||||
|
||||
# GitHub Extra Pins
|
||||
|
||||
GitHub extra pins을 사용하면 Github readme 프로필에 6개 이상의 저장소를 고정할 수 있습니다.
|
||||
그렇습니다! 더 이상 고정된 6개의 저장소로 제한되지 않습니다.
|
||||
|
||||
### 사용법
|
||||
|
||||
이 코드를 복사해서 readme에 넣고 링크를 변경해주세요.
|
||||
|
||||
Endpoint: `api/pin?username=anuraghazra&repo=github-readme-stats`
|
||||
|
||||
```md
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
```
|
||||
|
||||
### 데모
|
||||
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
|
||||
[show_owner](#사용자정의) 값을 사용하여 저장소 소유자 이름을 포함할 수 있습니다.
|
||||
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
|
||||
# 상위 언어 카드
|
||||
|
||||
상위 언어 카드는 그 Github 사용자가 가장 많이 사용하고 있는 언어가 표시됩니다.
|
||||
|
||||
_참고: Top languages는 사용자의 기술 수준을 나타내는 것이 아니라 GitHub에서 어떤 언어로 코드를 많이 작성하는지 나타내는 Github 지표이며 github-readme-stats의 새로운 기능입니다._
|
||||
|
||||
### 사용법
|
||||
|
||||
이 코드를 복사해서 readme에 넣고 링크를 변경해주세요.
|
||||
|
||||
Endpoint: `api/top-langs?username=anuraghazra`
|
||||
|
||||
```md
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
```
|
||||
|
||||
### 개별 언어 숨기기
|
||||
|
||||
`?hide=language1,language2` 파라미터를 사용하여 특정 언어를 숨길 수 있습니다.
|
||||
|
||||
```md
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
```
|
||||
|
||||
### 컴팩트 언어 카드 레이아웃
|
||||
|
||||
`&layout=compact` 파라미터를 사용하여 카드의 디자인을 변경할 수 있습니다.
|
||||
|
||||
```md
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
```
|
||||
|
||||
### 데모
|
||||
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
|
||||
- 컴팩트 레이아웃
|
||||
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
|
||||
---
|
||||
|
||||
### 모든 데모
|
||||
|
||||
- 기본 설정
|
||||
|
||||

|
||||
|
||||
- 특정 통계 숨김
|
||||
|
||||

|
||||
|
||||
- 아이콘 표기
|
||||
|
||||

|
||||
|
||||
- 모든 커밋 표기
|
||||
|
||||

|
||||
|
||||
- 테마
|
||||
|
||||
[default themes](#테마)에서 선택
|
||||
|
||||

|
||||
|
||||
- Stats 카드 사용자 정의
|
||||
|
||||

|
||||
|
||||
- Repo 카드 사용자 정의
|
||||
|
||||

|
||||
|
||||
- 상위 언어
|
||||
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
|
||||
---
|
||||
|
||||
### 꿀팁 (Repo 카드 정렬)
|
||||
|
||||
일반적으로 사진을 나란히 배치할 수 없습니다. 따라서 다음과 같은 방법을 사용할 수 있습니다.
|
||||
|
||||
```md
|
||||
<a href="https://github.com/anuraghazra/github-readme-stats">
|
||||
<img align="left" src="https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra&repo=github-readme-stats" />
|
||||
</a>
|
||||
<a href="https://github.com/anuraghazra/convoychat">
|
||||
<img align="left" src="https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra&repo=convoychat" />
|
||||
</a>
|
||||
```
|
||||
|
||||
## 자체 Vercel 인스턴스에 배포하기
|
||||
|
||||
#### [Check Out Step By Step Video Tutorial By @codeSTACKr](https://youtu.be/n6d4KHSKqGk?t=107)
|
||||
|
||||
Github API는 시간당 5k 요청만을 허용하기 때문에, 이 `https://github-readme-stats.vercel.app/api`이 제한에 도달할 수 있습니다.
|
||||
물론 자신의 Vercel 서버에서 호스팅하는 것이라면 아무것도 걱정할 필요가 없습니다. 시작하려면 배포 버튼을 클릭하세요!
|
||||
|
||||
참고: [#58](https://github.com/anuraghazra/github-readme-stats/pull/58) 이슈 이후로는 5k 이상의 요청을 처리할 수 있게 되어, 다운 타임의 문제가 발생하지 않습니다 :D
|
||||
|
||||
[](https://vercel.com/import/project?template=https://github.com/anuraghazra/github-readme-stats)
|
||||
|
||||
<details>
|
||||
<summary><b> Guide on setting up Vercel 🔨 </b></summary>
|
||||
|
||||
1. [vercel.com](https://vercel.com/)에 접속하세요.
|
||||
1. `Log in` 클릭합니다.
|
||||

|
||||
1. `Continue with GitHub` 를 클릭하여 Github로 로그인하세요.
|
||||

|
||||
1. Github에 로그인하고 메시지가 표시되면 모든 저장소에 대한 접근을 허용합니다.
|
||||
1. 이 저장소를 fork 합니다.
|
||||
1. [Vercel dashboard](https://vercel.com/dashboard)로 돌아갑니다.
|
||||
1. `Import Project` 를 선택합니다.
|
||||

|
||||
1. `Import Git Repository` 를 선택합니다.
|
||||

|
||||
1. 루트를 선택한 다음에 다른 것들은 그대로 두고 PAT_1 이라는 환경 변수(아래처럼)를 추가합니다. 여기에는 개인 접근 토큰(PAT)이 포함되며, 토큰은 [여기](https://github.com/settings/tokens/new)에서 쉽게 만들 수 있습니다. (모두 그대로 두고, 이름만 지정하면 됩니다.)
|
||||

|
||||
1. 배포를 클릭하면 완료됩니다. API를 사용하기 위해 당신의 도메인을 참조하세요!
|
||||
|
||||
</details>
|
||||
|
||||
## :sparkling_heart: 프로젝트 후원
|
||||
|
||||
저는 제가 할 수 있는 거의 모든 것을 오픈소스로 제공하고, 이 프로젝트를 사용하면서 도움이 필요한 분들에게 회신하려고 합니다.
|
||||
분명한 것은, 이는 시간이 걸리는 일입니다. 하지만 여러분은 이 서비스를 무료로 사용할 수 있습니다.
|
||||
|
||||
하지만 여러분이 이 프로젝트를 사용하고 거기에 만족한다면, 아니면 제가 하는 활동을 격려하고자 싶다면 몇가지 방법이 있습니다. :-
|
||||
|
||||
- readme에서 github-readme-stats를 사용하고 다시 링크해주세요 :D
|
||||
- star를 눌러주거나 이 프로젝트를 공유해주세요. :rocket:
|
||||
- [](https://www.paypal.me/anuraghazra) - PayPal을 통해서 일회성 기부를 할 수 있습니다. 저는 아마 ~~커피~~ 차를 살겁니다.
|
||||
|
||||
고맙습니다! :heart:
|
||||
|
||||
---
|
||||
|
||||
코드 기여는 환영합니다!
|
||||
|
||||
:heart: and JavaScript로 만들어졌습니다.
|
@ -1,332 +0,0 @@
|
||||
<p align="center">
|
||||
<img width="100px" src="https://res.cloudinary.com/anuraghazra/image/upload/v1594908242/logo_ccswme.svg" align="center" alt="GitHub Readme Stats" />
|
||||
<h2 align="center">GitHub Readme Stats</h2>
|
||||
<p align="center">Adicione suas estatísticas no GitHub geradas dinamicamente em seus readmes!</p>
|
||||
</p>
|
||||
<p align="center">
|
||||
<a href="https://github.com/anuraghazra/github-readme-stats/actions">
|
||||
<img alt="Testes aprovados" src="https://github.com/anuraghazra/github-readme-stats/workflows/Test/badge.svg" />
|
||||
</a>
|
||||
<a href="https://codecov.io/gh/anuraghazra/github-readme-stats">
|
||||
<img src="https://codecov.io/gh/anuraghazra/github-readme-stats/branch/master/graph/badge.svg" />
|
||||
</a>
|
||||
<a href="https://github.com/anuraghazra/github-readme-stats/issues">
|
||||
<img alt="Issues" src="https://img.shields.io/github/issues/anuraghazra/github-readme-stats?color=0088ff" />
|
||||
</a>
|
||||
<a href="https://github.com/anuraghazra/github-readme-stats/pulls">
|
||||
<img alt="GitHub pull requests" src="https://img.shields.io/github/issues-pr/anuraghazra/github-readme-stats?color=0088ff" />
|
||||
</a>
|
||||
<br />
|
||||
<br />
|
||||
<a href="https://a.paddle.com/v2/click/16413/119403?link=1227">
|
||||
<img src="https://img.shields.io/badge/Apoiado%20por-VSCode%20Power%20User%20%E2%86%92-gray.svg?colorA=655BE1&colorB=4F44D6&style=for-the-badge"/>
|
||||
</a>
|
||||
<a href="https://a.paddle.com/v2/click/16413/119403?link=2345">
|
||||
<img src="https://img.shields.io/badge/Apoiado%20por-Node%20Cli.com%20%E2%86%92-gray.svg?colorA=61c265&colorB=4CAF50&style=for-the-badge"/>
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="#demo">Ver demonstração</a>
|
||||
·
|
||||
<a href="https://github.com/anuraghazra/github-readme-stats/issues/new/choose">Reportar erros</a>
|
||||
·
|
||||
<a href="https://github.com/anuraghazra/github-readme-stats/issues/new/choose">Solicitar recursos</a>
|
||||
</p>
|
||||
<p align="center">
|
||||
<a href="/docs/readme_fr.md">Français</a>
|
||||
·
|
||||
<a href="/docs/readme_cn.md">简体中文</a>
|
||||
·
|
||||
<a href="/docs/readme_es.md">Español</a>
|
||||
·
|
||||
<a href="/docs/readme_de.md">Deutsch</a>
|
||||
·
|
||||
<a href="/docs/readme_ja.md">日本語</a>
|
||||
·
|
||||
<a href="/docs/readme_pt-BR.md">Português Brasileiro</a>
|
||||
·
|
||||
<a href="/docs/readme_it.md">Italiano</a>
|
||||
·
|
||||
<a href="/docs/readme_kr.md">한국어</a>
|
||||
</p>
|
||||
</p>
|
||||
<p align="center">Gostou do projeto? Por favor considere <a href="https://www.paypal.me/anuraghazra">fazer uma doação</a> para ajudar a melhorá-lo!
|
||||
|
||||
# Características
|
||||
|
||||
- [Cartão de estatísticas do GitHub](#cartão-de-estatísticas-do-github)
|
||||
- [Pins extras do GitHub](#pins-extras-do-github)
|
||||
- [Cartão de principais linguagens de programação](#cartão-de-principais-linguagens-de-programação)
|
||||
- [Temas](#temas)
|
||||
- [Personalização](#personalização)
|
||||
- [Faça suas próprias implantações](#implante-em-sua-própria-instância-do-vercel)
|
||||
|
||||
# Cartão de estatísticas do GitHub
|
||||
|
||||
Copie e cole isso no seu conteúdo de remarcação e é isso. Simples!
|
||||
|
||||
Mude o valor de `?username=` para o seu nome de usuário no GitHub.
|
||||
|
||||
```md
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
```
|
||||
|
||||
_Nota: As classificações são baseadas nas estatísticas do usuário, veja [src/calculateRank.js](../src/calculateRank.js)_
|
||||
|
||||
### Ocultando estatísticas específicas
|
||||
|
||||
Para ocultar estatísticas individualmente, você pode passar um parâmetro de consulta `?hide=` com valores separados por vírgula.
|
||||
|
||||
> Opções: `&hide=stars,commits,prs,issues,contribs`
|
||||
|
||||
```md
|
||||

|
||||
```
|
||||
|
||||
### Adicionando contagem de contribuições privadas à contagem total de commits
|
||||
|
||||
Adicione a contagem de todas as suas contribuições privadas à contagem total de confirmações usando o parâmetro de consulta `?count_private=true`.
|
||||
|
||||
_Nota: Se você estiver implantando este projeto, as contribuições privadas serão contadas por padrão; caso contrário, você precisará compartilhar suas contagens de contribuições privadas._
|
||||
|
||||
> Opções: `&count_private=true`
|
||||
|
||||
```md
|
||||

|
||||
```
|
||||
|
||||
### Exibindo ícones
|
||||
|
||||
Para habilitar ícones, basta utilizar o parâmetro `show_icons=true` na sua requisição, da seguinte forma:
|
||||
|
||||
```md
|
||||

|
||||
```
|
||||
|
||||
### Temas
|
||||
|
||||
Com temas predefinidos, pode personalizar a aparência dos cartões sem precisar fazer nenhuma [configuração manual](#personalização).
|
||||
|
||||
Utilize o parâmetro `?theme=THEME_NAME`, da seguinte forma:
|
||||
|
||||
```md
|
||||

|
||||
```
|
||||
|
||||
#### Todos os temas predefinidos :
|
||||
|
||||
dark, radical, merko, gruvbox, tokyonight, onedark, cobalt, synthwave, highcontrast, dracula
|
||||
|
||||
<img src="https://res.cloudinary.com/anuraghazra/image/upload/v1595174536/grs-themes_l4ynja.png" alt="GitHub Readme Stat Themes" width="600px"/>
|
||||
|
||||
Visualize [todos o temas disponíveis](../themes/README.md) ou o [arquivo de configuração de tema](../themes/index.js), além de **também poder contribuir com novos temas**, se desejar :D
|
||||
|
||||
### Personalização
|
||||
|
||||
Personalize a aparência do seu `Stats Card` ou `Repo Card` da maneira que desejar com os parâmetros de URL.
|
||||
|
||||
#### Opções comuns
|
||||
|
||||
- `title_color` - Cor do título do cartão _(hex color)_
|
||||
- `text_color` - Cor de texto do conteúdo _(hex color)_
|
||||
- `icon_color` - Cor dos ícones (se disponível) _(hex color)_
|
||||
- `bg_color` - Cor de fundo do cartão _(hex color)_
|
||||
- `theme` - Nome do tema, escolha em [todos os temas disponíveis](../themes/README.md)
|
||||
- `cache_seconds` - Defina o cabeçalho do cache manualmente _(min: 1800, max: 86400)_
|
||||
|
||||
> Nota sobre o cache: Cartões de repositório tem um cache padrão de 30 minutos (1800 segundos), se o número a contagem de forks e contagem de estrelas é menor que 1 mil o padrão é 2 horas (7200). Note também que o cache é limitado a um mínimo de 30 minutos e um máximo de 24 horas.
|
||||
|
||||
#### Opções exclusivas do cartão de estatísticas:
|
||||
|
||||
- `hide` - Oculta itens específicos das estatísticas _(Valores separados por vírgulas)_
|
||||
- `hide_title` - Ocutar o título _(boolean)_
|
||||
- `hide_rank` - Ocultar a classificação _(boolean)_
|
||||
- `show_icons` - Mostrar ícones _(boolean)_
|
||||
- `include_all_commits` - Contabiliza todos os commits ao invés de apenas os atual ano _(boolean)_
|
||||
- `count_private` - Contabiliza commits privados _(boolean)_
|
||||
- `line_height` - Define a altura do espaçamento entre o texto _(number)_
|
||||
|
||||
#### Opções exclusivas do cartão de repositórios:
|
||||
|
||||
- `show_owner` - Exibir o nome da pessoa a quem o repositório pertence _(boolean)_
|
||||
|
||||
#### Opções exclusivas do cartão de linguagens:
|
||||
|
||||
- `hide` - Oculta linguagens específicas _(Valores separados por vírgulas)_
|
||||
- `hide_title` - Oculta o título _(boolean)_
|
||||
- `layout` - Alterna entre os dois layouts disponíveis `default` & `compact`
|
||||
- `card_width` - Define a largura do cartão manualmente _(number)_
|
||||
|
||||
> :warning: **Importante:**
|
||||
> Nomes de linguagens devem ser uma sequência escapada de URI, como específicado em [Codificação por cento](https://pt.wikipedia.org/wiki/Codificação_por_cento)
|
||||
> (Isso é: `c++` deve se tornar `c%2B%2B`, `jupyter notebook` deve se tornar `jupyter%20notebook`, etc.)
|
||||
|
||||
---
|
||||
|
||||
# Pins extras do GitHub
|
||||
|
||||
Os Pins extras do GitHub permitem fixar mais de 6 repositórios no seu perfil usando um perfil README.me do GitHub.
|
||||
|
||||
Uhu! Você não está mais limitado a 6 repositórios fixados.
|
||||
|
||||
### Utilização
|
||||
|
||||
Copie e cole esse código no seu README.md e altere os atributos.
|
||||
|
||||
Endpoint: `api/pin?username=anuraghazra&repo=github-readme-stats`
|
||||
|
||||
```md
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
```
|
||||
|
||||
### Demonstração
|
||||
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
|
||||
Utilize a variável [show_owner](#personalização) para incluir o nome de usuário do proprietária do repositório
|
||||
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
|
||||
# Cartão de principais linguagens de programação
|
||||
|
||||
Exibe uma métrica de linguagens de programação mais usadas pelo usuário do GitHub.
|
||||
|
||||
_Nota: As principais linguagens de programação não fazem declarações sobre habilidades pessoais ou similares, é apenas uma figura-chave com base nas estatísticas do GitHub do usuário indicando a frequência com que cada uma foi utilizada._
|
||||
|
||||
### Utilização
|
||||
|
||||
Copie e cole esse código no seu README.md e altere os atributos.
|
||||
|
||||
Endpoint: `api/top-langs?username=anuraghazra`
|
||||
|
||||
```md
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
```
|
||||
|
||||
### Ocultar linguagens individualmente
|
||||
|
||||
Utilize o parâmetro `?hide=language1,language2` para ocultar linguagens específicas.
|
||||
|
||||
```md
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
```
|
||||
|
||||
### Layout de cartão de linguagens compacto
|
||||
|
||||
Utilize a opção `&layout=compact` para mudar o layout do cartão.
|
||||
|
||||
```md
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
```
|
||||
|
||||
### Demonstração
|
||||
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
|
||||
- Layout compacto
|
||||
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
|
||||
---
|
||||
|
||||
### Todas as demonstrações
|
||||
|
||||
- Padronizado
|
||||
|
||||

|
||||
|
||||
- Ocultando estatísticas específicas
|
||||
|
||||

|
||||
|
||||
- Mostrando ícones
|
||||
|
||||

|
||||
|
||||
- Incluir todos os commits
|
||||
|
||||

|
||||
|
||||
- Temas
|
||||
|
||||
Escolha entre um dos [temas predefinidos](#temas)
|
||||
|
||||

|
||||
|
||||
- Personalizando o cartão de estatísticas
|
||||
|
||||

|
||||
|
||||
- Customizando o cartão de repositório
|
||||
|
||||

|
||||
|
||||
- Principais linguagens
|
||||
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
|
||||
---
|
||||
|
||||
### Dica (Alinhandos os cartões de repositório)
|
||||
|
||||
Por padrão, você não poderá organizar as imagens lado a lado. Para fazer isso, você pode usar a seguinte abordagem:
|
||||
|
||||
```md
|
||||
<a href="https://github.com/anuraghazra/github-readme-stats">
|
||||
<img align="left" src="https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra&repo=github-readme-stats" />
|
||||
</a>
|
||||
<a href="https://github.com/anuraghazra/convoychat">
|
||||
<img align="left" src="https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra&repo=convoychat" />
|
||||
</a>
|
||||
```
|
||||
|
||||
## Implante em sua própria instância do Vercel
|
||||
|
||||
#### [Check Out Step By Step Video Tutorial By @codeSTACKr](https://youtu.be/n6d4KHSKqGk?t=107)
|
||||
|
||||
Como a API do GitHub permite apenas 5 mil solicitações por hora, é possível que minha `https://github-readme-stats.vercel.app/api` atinja a cota limite. Se hospedar em seu próprio servidor Vercel, não precisará se preocupar com nada. Clique no botão de implantação para começar!
|
||||
|
||||
Nota: Desde [#58](https://github.com/anuraghazra/github-readme-stats/pull/58) há possibilidade de lidar com mais de 5 mil chamadas por hora, sem interrupções :D
|
||||
|
||||
[](https://vercel.com/import/project?template=https://github.com/anuraghazra/github-readme-stats)
|
||||
|
||||
<details>
|
||||
<summary>Guia de configuração do Vercel</summary>
|
||||
|
||||
1. Acesse [vercel.com](https://vercel.com/)
|
||||
1. Clique em `Login`
|
||||

|
||||
1. Acesse com o GitHub clicando em `Continue with GitHub`
|
||||

|
||||
1. Entre no GitHub e permita acesso a todos os repositórios, se solicitado
|
||||
1. Faça Fork neste repositório
|
||||
1. Volte ao seu [painel principal do Vercel](https://vercel.com/dashboard)
|
||||
1. Selecione `Import Project`
|
||||

|
||||
1. Selecione `Import Git Repository`
|
||||

|
||||
1. Selecione a raiz e mantenha tudo como está, basta adicionar sua variável de ambiente chamada PAT_1 (que será exibida), que conterá um token de acesso pessoal (PAT), que você pode criar facilmente [aqui](https://github.com/settings/tokens/new) (deixe tudo como está, apenas dê um nome, que pode ser o que você quiser)
|
||||

|
||||
1. Clique em `deploy` e já estará tudo pronto. Veja seus domínios para usar a API!
|
||||
|
||||
</details>
|
||||
|
||||
## :sparkling_heart: Apoie o projeto
|
||||
|
||||
Disponibilizo como código aberto quase tudo o que posso e tento responder a todos que precisam de ajuda para utilizar esses projetos. Claro,
|
||||
isso demanda tempo. Utilize este serviço gratuitamente.
|
||||
|
||||
No entanto, se você utilizar este projeto e estiver satisfeito com ele, ou apenas quiser me encorajar a continuar criando coisas, existem algumas formas fazê-lo:
|
||||
|
||||
- Dando os devidos créditos ao usar github-readme-stats no seu README.me, adicionando uma referência ao projeto :D
|
||||
- Dando uma estrela (Starring) e compartilhando o projeto 🚀
|
||||
- [](https://www.paypal.me/anuraghazra) - Você pode fazer doações únicas via PayPal. Provavelmente vou comprar um ~~café~~ chá. :tea:
|
||||
|
||||
Obrigado! :heart:
|
||||
|
||||
---
|
||||
|
||||
Contribuições são bem-vindas! <3
|
||||
|
||||
Feito com :heart: e JavaScript.
|
@ -1,3 +0,0 @@
|
||||
module.exports = {
|
||||
clearMocks: true,
|
||||
};
|
80
package.json
80
package.json
@ -1,40 +1,44 @@
|
||||
{
|
||||
"name": "github-readme-stats",
|
||||
"version": "1.0.0",
|
||||
"description": "Dynamically generate stats for your github readmes",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "jest --coverage",
|
||||
"test:watch": "jest --watch",
|
||||
"theme-readme-gen": "ts-node scripts/generate-theme-doc",
|
||||
"preview-theme": "node scripts/preview-theme"
|
||||
},
|
||||
"author": "Anurag Hazra",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@actions/core": "^1.2.4",
|
||||
"@actions/github": "^4.0.0",
|
||||
"@testing-library/dom": "^7.20.0",
|
||||
"@testing-library/jest-dom": "^5.11.0",
|
||||
"@types/express": "^4.17.8",
|
||||
"@types/react": "^16.9.49",
|
||||
"@types/react-dom": "^16.9.8",
|
||||
"axios": "^0.19.2",
|
||||
"axios-mock-adapter": "^1.18.1",
|
||||
"css-to-object": "^1.1.0",
|
||||
"husky": "^4.2.5",
|
||||
"jest": "^26.1.0",
|
||||
"parse-diff": "^0.7.0",
|
||||
"ts-node": "^9.0.0",
|
||||
"vercel": "^20.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"dotenv": "^8.2.0",
|
||||
"emoji-name-map": "^1.2.8",
|
||||
"github-username-regex": "^1.0.0",
|
||||
"react": "^16.13.1",
|
||||
"react-dom": "^16.13.1",
|
||||
"typescript": "^4.0.2",
|
||||
"word-wrap": "^1.2.3"
|
||||
}
|
||||
"name": "github-readme-stats",
|
||||
"version": "1.0.0",
|
||||
"description": "Dynamically generate stats for your github readmes",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"start": "vercel dev",
|
||||
"theme-readme-gen": "ts-node scripts/generate-theme-doc"
|
||||
},
|
||||
"author": "Anurag Hazra",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@actions/core": "^1.2.4",
|
||||
"@actions/github": "^4.0.0",
|
||||
"@testing-library/dom": "^7.20.0",
|
||||
"@testing-library/jest-dom": "^5.11.0",
|
||||
"@types/express": "^4.17.8",
|
||||
"@types/node-fetch": "^2.5.7",
|
||||
"@types/react": "^16.9.49",
|
||||
"@types/react-dom": "^16.9.8",
|
||||
"css-to-object": "^1.1.0",
|
||||
"eslint": "^7.9.0",
|
||||
"eslint-config-google": "^0.14.0",
|
||||
"eslint-import-resolver-typescript": "^2.3.0",
|
||||
"eslint-plugin-import": "^2.22.0",
|
||||
"eslint-plugin-react": "^7.20.6",
|
||||
"eslint-plugin-sonarjs": "^0.5.0",
|
||||
"husky": "^4.2.5",
|
||||
"jest": "^26.1.0",
|
||||
"parse-diff": "^0.7.0",
|
||||
"ts-node": "^9.0.0",
|
||||
"vercel": "^20.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"dotenv": "^8.2.0",
|
||||
"emoji-name-map": "^1.2.8",
|
||||
"github-username-regex": "^1.0.0",
|
||||
"node-fetch": "^2.6.1",
|
||||
"react": "^16.13.1",
|
||||
"react-dom": "^16.13.1",
|
||||
"typescript": "^4.0.2",
|
||||
"word-wrap": "^1.2.3"
|
||||
}
|
||||
}
|
||||
|
@ -1,87 +0,0 @@
|
||||
const core = require("@actions/core");
|
||||
const github = require("@actions/github");
|
||||
const parse = require("parse-diff");
|
||||
require("dotenv").config();
|
||||
|
||||
function getPrNumber() {
|
||||
const pullRequest = github.context.payload.pull_request;
|
||||
if (!pullRequest) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return pullRequest.number;
|
||||
}
|
||||
|
||||
async function run() {
|
||||
try {
|
||||
const token = core.getInput("token");
|
||||
const octokit = github.getOctokit(token || process.env.PERSONAL_TOKEN);
|
||||
const pullRequestId = getPrNumber();
|
||||
|
||||
if (!pullRequestId) {
|
||||
console.log("PR not found");
|
||||
return;
|
||||
}
|
||||
|
||||
let res = await octokit.pulls.get({
|
||||
owner: "anuraghazra",
|
||||
repo: "github-readme-stats",
|
||||
pull_number: pullRequestId,
|
||||
mediaType: {
|
||||
format: "diff",
|
||||
},
|
||||
});
|
||||
|
||||
let diff = parse(res.data);
|
||||
let colorStrings = diff
|
||||
.find((file) => file.to === "themes/index.js")
|
||||
.chunks[0].changes.filter((c) => c.type === "add")
|
||||
.map((c) => c.content.replace("+", ""))
|
||||
.join("");
|
||||
|
||||
let matches = colorStrings.match(/(title_color:.*bg_color.*\")/);
|
||||
let colors = matches && matches[0].split(",");
|
||||
|
||||
if (!colors) {
|
||||
await octokit.issues.createComment({
|
||||
owner: "anuraghazra",
|
||||
repo: "github-readme-stats",
|
||||
body: `
|
||||
\rTheme preview (bot)
|
||||
Cannot create theme preview
|
||||
`,
|
||||
issue_number: pullRequestId,
|
||||
});
|
||||
return;
|
||||
}
|
||||
colors = colors.map((color) =>
|
||||
color.replace(/.*\:\s/, "").replace(/\"/g, "")
|
||||
);
|
||||
|
||||
let titleColor = colors[0];
|
||||
let iconColor = colors[1];
|
||||
let textColor = colors[2];
|
||||
let bgColor = colors[3];
|
||||
const url = `https://github-readme-stats.vercel.app/api?username=anuraghazra&title_color=${titleColor}&icon_color=${iconColor}&text_color=${textColor}&bg_color=${bgColor}&show_icons=true`;
|
||||
|
||||
await octokit.issues.createComment({
|
||||
owner: "anuraghazra",
|
||||
repo: "github-readme-stats",
|
||||
body: `
|
||||
\rTheme preview (bot)
|
||||
|
||||
\ntitle-color: <code>#${titleColor}</code>
|
||||
\nicon-color: <code>#${iconColor}</code>
|
||||
\ntext-color: <code>#${textColor}</code>
|
||||
\nbg-color: <code>#${bgColor}</code>
|
||||
|
||||
\r[](${url})
|
||||
`,
|
||||
issue_number: pullRequestId,
|
||||
});
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
|
||||
run();
|
282
src/cards/HistoryCard.tsx
Normal file
282
src/cards/HistoryCard.tsx
Normal file
@ -0,0 +1,282 @@
|
||||
import { formatDateNumber, getColorOfLanguage } from "../common/utils"
|
||||
import Card, { CardOptions } from '../common/Card'
|
||||
import React from 'react'
|
||||
import FlexLayout from "../components/FlexLayout"
|
||||
|
||||
interface HistoryOptions extends CardOptions {
|
||||
width?: number
|
||||
height?: number
|
||||
layout?: 'horizontal'
|
||||
hide_legend?: boolean
|
||||
|
||||
// Put language in Other
|
||||
hide?: Array<string>
|
||||
language_count?: number
|
||||
}
|
||||
|
||||
export default class HistoryCard extends Card {
|
||||
|
||||
private topLanguages: Array<string>
|
||||
|
||||
public constructor(
|
||||
private username: string,
|
||||
private days: Array<{day: string, total: number, data: Array<{xp: number, language: string}>}>,
|
||||
private options: HistoryOptions
|
||||
) {
|
||||
super(options)
|
||||
|
||||
this.height = 45 + (this.days.length + 1) * 40
|
||||
this.width = options.width ?? 500
|
||||
if (options.layout === 'horizontal') {
|
||||
this.width = 45 + (this.days.length + 1) * 40 + 100
|
||||
this.height = options.height ?? 300
|
||||
}
|
||||
|
||||
const languagesToHide = options.hide || []
|
||||
|
||||
let languageCount: Array<{language: string, xp: number}> = []
|
||||
for (const day of this.days) {
|
||||
for (const data of day.data) {
|
||||
let index = languageCount.findIndex((item) => item.language === data.language)
|
||||
if (index === -1) {
|
||||
index = languageCount.push({
|
||||
language: data.language,
|
||||
xp: 0
|
||||
}) - 1
|
||||
}
|
||||
languageCount[index].xp += data.xp
|
||||
}
|
||||
}
|
||||
this.topLanguages = languageCount
|
||||
.sort((a, b) => b.xp - a.xp)
|
||||
.map((item) => item.language)
|
||||
.filter((lang) => !languagesToHide.includes(lang))
|
||||
languagesToHide.push(...this.topLanguages.splice((options.language_count || 8 )))
|
||||
if (languagesToHide.length > 0) {
|
||||
this.topLanguages.push('Other')
|
||||
}
|
||||
|
||||
for (const day of this.days) {
|
||||
const toRemove: Array<number> = []
|
||||
for (let i = 0; i < day.data.length; i++) {
|
||||
const element = day.data[i];
|
||||
if (languagesToHide.includes(element.language)) {
|
||||
const otherIndex = day.data.findIndex((el) => el.language === 'Other')
|
||||
if (otherIndex === -1) {
|
||||
day.data.push({
|
||||
language: 'Other',
|
||||
xp: element.xp
|
||||
})
|
||||
} else {
|
||||
day.data[otherIndex].xp += element.xp
|
||||
}
|
||||
toRemove.push(i)
|
||||
}
|
||||
}
|
||||
for (const index of toRemove.reverse()) {
|
||||
day.data.splice(index, 1)
|
||||
}
|
||||
}
|
||||
|
||||
this.title = 'Code History Language breakdown'
|
||||
this.css = ProgressNode.getCSS('#000')
|
||||
}
|
||||
|
||||
public render() {
|
||||
const totalTotal = this.days.reduce((prvs, crnt) => {
|
||||
if (prvs < crnt.total) {
|
||||
return crnt.total
|
||||
}
|
||||
return prvs
|
||||
}, 0)
|
||||
|
||||
const legendWidth = Math.max(this.width * 20 / 100 + 60, 150)
|
||||
const historyWidth = this.width - legendWidth
|
||||
return super.render(
|
||||
<svg x="25">
|
||||
<FlexLayout items={[(() => {
|
||||
if (this.options.layout === 'horizontal') {
|
||||
return (
|
||||
<FlexLayout items={
|
||||
this.days.reverse().map((el, index) => (
|
||||
<VerticalProgressNode
|
||||
{...el}
|
||||
totalTotal={totalTotal} height={this.height - 120} />
|
||||
))
|
||||
}
|
||||
gap={40}
|
||||
// direction="column"
|
||||
/>
|
||||
)
|
||||
} else {
|
||||
return (
|
||||
<FlexLayout items={
|
||||
this.days.map((el, index) => (
|
||||
<ProgressNode
|
||||
{...el}
|
||||
totalTotal={totalTotal} width={historyWidth - 30} />
|
||||
))
|
||||
}
|
||||
gap={40}
|
||||
direction="column"
|
||||
/>
|
||||
)
|
||||
}
|
||||
})(), (
|
||||
<FlexLayout items={
|
||||
this.topLanguages.map((el, index) => (
|
||||
<>
|
||||
<rect rx="5" x="2" y="7" height="12" width="12" fill={getColorOfLanguage(el)} />
|
||||
<text x="18" y="18" className="lang-name" key={index}>{el}</text>
|
||||
</>
|
||||
))
|
||||
}
|
||||
gap={20}
|
||||
direction="column"
|
||||
/>
|
||||
)]}
|
||||
gap={this.options.layout === 'horizontal' ? this.width - 180 : historyWidth - 20}
|
||||
/>
|
||||
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class ProgressNode extends React.Component<{
|
||||
day: string
|
||||
total: number
|
||||
totalTotal: number
|
||||
data: Array<{xp: number, language: string}>
|
||||
width: number
|
||||
}> {
|
||||
|
||||
public static getCSS = (textColor: string) => `
|
||||
.lang-name {
|
||||
font: 400 16px 'Segoe UI', Ubuntu, Sans-Serif;
|
||||
fill: ${textColor};
|
||||
}
|
||||
.xp-txt {
|
||||
font: 400 12px 'Segoe UI', Ubuntu, Sans-Serif;
|
||||
fill: ${textColor};
|
||||
}
|
||||
.xp-txt-invert {
|
||||
font: 600 12px 'Segoe UI', Ubuntu, Sans-Serif;
|
||||
fill: white;
|
||||
}
|
||||
.subtitle {
|
||||
font: 400 14px 'Segoe UI', Ubuntu, Sans-Serif;
|
||||
fill: ${textColor};
|
||||
}
|
||||
`
|
||||
|
||||
|
||||
public render() {
|
||||
let offset = 0
|
||||
const maskId = `mask-${this.props.day}`
|
||||
return (
|
||||
<>
|
||||
<text x="2" y="15" className="lang-name">{new Date(this.props.day).toDateString().substr(4, 6)}</text>
|
||||
<svg width={this.props.width}>
|
||||
<mask id={maskId}>
|
||||
<rect x="0" y="20" width={this.calcSize(this.props.total)} height="16" fill="white" rx="5" />
|
||||
</mask>
|
||||
<rect rx="5" ry="5" x="0" y="20" width={this.props.width} height="16" fill="#ddd" />
|
||||
{this.props.data.map((el, index) => {
|
||||
const color = getColorOfLanguage(el.language)
|
||||
offset += el.xp
|
||||
return (
|
||||
<rect
|
||||
key={index}
|
||||
mask={`url(#${maskId})`}
|
||||
height="16"
|
||||
fill={color}
|
||||
x={this.calcSize(offset - el.xp)} y="20"
|
||||
width={`${this.calcSize(el.xp)}px`}
|
||||
/>
|
||||
)
|
||||
})}
|
||||
{(() => {
|
||||
let size = this.calcSize(offset) + 6
|
||||
const txtSize = (this.props.total.toString().length + 3) * 8
|
||||
let classes = 'xp-txt'
|
||||
if (size + txtSize >= this.calcSize(this.props.totalTotal)) {
|
||||
size -= txtSize
|
||||
classes += ' xp-txt-invert'
|
||||
}
|
||||
return (
|
||||
<text x={size} y="33" className={classes}>{this.props.total} XP</text>
|
||||
)
|
||||
})()}
|
||||
|
||||
</svg>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
protected calcSize(number: number) {
|
||||
return number * this.props.width / this.props.totalTotal
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class VerticalProgressNode extends React.Component<{
|
||||
day: string
|
||||
total: number
|
||||
totalTotal: number
|
||||
data: Array<{xp: number, language: string}>
|
||||
height: number
|
||||
}> {
|
||||
public render() {
|
||||
let offset = this.props.totalTotal
|
||||
const maskId = `mask-${this.props.day}`
|
||||
|
||||
return (
|
||||
<>
|
||||
<svg x="7" y="-20" height={this.props.height + 60}>
|
||||
<mask id={maskId}>
|
||||
<rect x="0" y={25 + this.calcSize(this.props.totalTotal - this.props.total)} width="16" height={this.calcSize(this.props.total)} fill="white" rx="5" />
|
||||
</mask>
|
||||
<rect rx="5" ry="5" x="0" y="25" width="16" height={this.props.height} fill="#ddd" />
|
||||
{this.props.data.map((el, index) => {
|
||||
const color = getColorOfLanguage(el.language)
|
||||
offset -= el.xp
|
||||
return (
|
||||
<rect
|
||||
key={index}
|
||||
mask={`url(#${maskId})`}
|
||||
width="16"
|
||||
fill={color}
|
||||
y={25 + this.calcSize(offset)}
|
||||
x="0"
|
||||
height={`${this.calcSize(el.xp)}px`}
|
||||
/>
|
||||
)
|
||||
})}
|
||||
{this.getXPTxt()}
|
||||
|
||||
</svg>
|
||||
<text x="2" y={this.props.height + 18} className="subtitle">{new Date(this.props.day).toDateString().substr(4, 3)}</text>
|
||||
<text x="5" y={this.props.height + 34} className="subtitle">{formatDateNumber(new Date(this.props.day).getDate())}</text>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
protected calcSize(number: number) {
|
||||
return number * this.props.height / this.props.totalTotal
|
||||
}
|
||||
|
||||
private getXPTxt() {
|
||||
const txtLength = (this.props.total.toString().length + 3) * 13
|
||||
let position = 25 + this.calcSize(this.props.totalTotal - this.props.total) - txtLength
|
||||
let classes = 'xp-txt'
|
||||
if (position <= 28) {
|
||||
position += txtLength + 16
|
||||
classes += ' xp-txt-invert'
|
||||
}
|
||||
return (
|
||||
<text transform={`rotate(90, 4, ${position})`} letterSpacing="5" y={position} x="4" rotate="-90" className={classes}>{this.props.total} XP</text>
|
||||
)
|
||||
}
|
||||
}
|
214
src/cards/ProfileCard.tsx
Normal file
214
src/cards/ProfileCard.tsx
Normal file
@ -0,0 +1,214 @@
|
||||
import { kFormatter, encodeHTML, getProgress, getLevel, parseBoolean, calculateCircleProgress, getColor } from '../common/utils'
|
||||
import icons from '../common/icons'
|
||||
import Card, { CardOptions } from '../common/Card'
|
||||
import React from 'react'
|
||||
import FlexLayout from '../components/FlexLayout'
|
||||
|
||||
interface ProfileCardOptions extends CardOptions {
|
||||
hide?: Array<string>
|
||||
show_icons?: boolean
|
||||
hide_rank?: boolean
|
||||
line_height?: number
|
||||
icon_color?: string
|
||||
text_color?: string
|
||||
}
|
||||
|
||||
export default class ProfileCard extends Card {
|
||||
private stats: Record<string, {
|
||||
icon: JSX.Element
|
||||
label: string
|
||||
value: number
|
||||
}>
|
||||
|
||||
private defaults = {
|
||||
line_height: 25,
|
||||
hide: []
|
||||
}
|
||||
|
||||
public constructor(
|
||||
private username: string,
|
||||
private xp: number,
|
||||
private recentXp: number,
|
||||
private options: ProfileCardOptions
|
||||
) {
|
||||
super(
|
||||
options
|
||||
)
|
||||
|
||||
// This Element
|
||||
this.stats = {
|
||||
xp: {
|
||||
icon: icons.star,
|
||||
label: "XP",
|
||||
value: xp,
|
||||
},
|
||||
recent_xp: {
|
||||
icon: icons.commits,
|
||||
label: 'Recent xp',
|
||||
value: this.recentXp,
|
||||
},
|
||||
}
|
||||
|
||||
// Card Settings
|
||||
this.width = 495
|
||||
this.height = Math.max(
|
||||
45 + (Object.keys(this.stats).length + 1) * (this.options.line_height || this.defaults.line_height),
|
||||
options.hide_rank ? 0 : 120
|
||||
)
|
||||
|
||||
this.title = `${encodeHTML(this.username)}${
|
||||
["x", "s"].includes(this.username.slice(-1)) ? "" : "s"
|
||||
} Code::Stats Profile`
|
||||
|
||||
const textColor = getColor('text_color', options.text_color, options.theme)
|
||||
const iconColor = getColor('icon_color', options.icon_color, options.theme)
|
||||
|
||||
if (!this.options.hide_rank) {
|
||||
this.css += RankCircle.getCSS(textColor, iconColor, getProgress(xp))
|
||||
}
|
||||
if ((this.options.hide || []) < Object.keys(this.stats)) {
|
||||
this.css += TextNode.getCSS(textColor, !!this.options.show_icons ? iconColor : undefined)
|
||||
}
|
||||
}
|
||||
|
||||
public render() {
|
||||
return super.render(
|
||||
<>
|
||||
<RankCircle xp={this.options.hide_rank ? undefined : this.xp} />
|
||||
<svg x="0" y="0">
|
||||
<FlexLayout
|
||||
items={Object.keys(this.stats).filter((item) => !(this.options.hide || []).includes(item)).map((el, index) => {
|
||||
const item = this.stats[el]
|
||||
return (
|
||||
<TextNode
|
||||
{...item}
|
||||
icon={!!this.options.show_icons ? item.icon : undefined}
|
||||
key={index}
|
||||
index={index}
|
||||
|
||||
/>
|
||||
)
|
||||
})}
|
||||
gap={this.options.line_height || this.defaults.line_height}
|
||||
direction="column"
|
||||
/>
|
||||
</svg>
|
||||
</>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
class RankCircle extends React.Component<{
|
||||
xp?: number
|
||||
}> {
|
||||
|
||||
public static getCSS = (textColor: string, titleColor: string, progress: number) => `
|
||||
.rank-text {
|
||||
font: 800 24px 'Segoe UI', Ubuntu, Sans-Serif; fill: ${textColor};
|
||||
animation: scaleInAnimation 0.3s ease-in-out forwards;
|
||||
}
|
||||
|
||||
.rank-circle-rim {
|
||||
stroke: ${titleColor};
|
||||
fill: none;
|
||||
stroke-width: 6;
|
||||
opacity: 0.2;
|
||||
}
|
||||
.rank-circle {
|
||||
stroke: ${titleColor};
|
||||
stroke-dasharray: 250;
|
||||
fill: none;
|
||||
stroke-width: 6;
|
||||
stroke-linecap: round;
|
||||
opacity: 0.8;
|
||||
transform-origin: -10px 8px;
|
||||
transform: rotate(-90deg);
|
||||
animation: rankAnimation 1s forwards ease-in-out;
|
||||
}
|
||||
|
||||
@keyframes rankAnimation {
|
||||
from {
|
||||
stroke-dashoffset: ${calculateCircleProgress(0)};
|
||||
}
|
||||
to {
|
||||
stroke-dashoffset: ${calculateCircleProgress(progress)};
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
public render () {
|
||||
if (!this.props.xp) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
return (
|
||||
<g data-testid="rank-circle"
|
||||
transform="translate(400, 0)">
|
||||
<circle className="rank-circle-rim" cx="-10" cy="8" r="40" />
|
||||
<circle className="rank-circle" cx="-10" cy="8" r="40" />
|
||||
<g className="rank-text">
|
||||
<text
|
||||
x="-4"
|
||||
y="0"
|
||||
alignmentBaseline="central"
|
||||
dominantBaseline="central"
|
||||
textAnchor="middle"
|
||||
>
|
||||
lv {getLevel(this.props.xp)}
|
||||
</text>
|
||||
</g>
|
||||
</g>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
class TextNode extends React.Component<{
|
||||
icon?: JSX.Element
|
||||
label: string
|
||||
value: number
|
||||
index: number
|
||||
}> {
|
||||
|
||||
public static getCSS = (textColor: string, iconColor?: string) => `
|
||||
${
|
||||
iconColor ? `.icon {
|
||||
fill: ${iconColor};
|
||||
// display: block;
|
||||
}` : ''
|
||||
}
|
||||
.stagger {
|
||||
opacity: 0;
|
||||
animation: fadeInAnimation 0.3s ease-in-out forwards;
|
||||
}
|
||||
.stat {
|
||||
font: 600 14px 'Segoe UI', Ubuntu, "Helvetica Neue", Sans-Serif; fill: ${textColor};
|
||||
}
|
||||
.bold {
|
||||
font-weight: 700
|
||||
}
|
||||
`
|
||||
|
||||
public render() {
|
||||
|
||||
const delay = (this.props.index + 3 * 150)
|
||||
|
||||
// Icon prefixing line
|
||||
const icon = this.props.icon ? (
|
||||
<svg data-testid="icon" className="icon" viewBox="0 0 16 16" version="1.1" width="16" height="16">
|
||||
{this.props.icon}
|
||||
</svg>
|
||||
) : undefined
|
||||
|
||||
return (
|
||||
<g className="stagger" data-index={this.props.index} style={{animationDelay: `${delay}ms`}} transform="translate(25, 0)">
|
||||
{icon}
|
||||
<text className="stat bold" x={this.props.icon ? 25 : undefined} y="12.5">{this.props.label}:</text>
|
||||
<text
|
||||
className="stat"
|
||||
x={this.props.icon ? 120 : 100}
|
||||
y="12.5"
|
||||
>{kFormatter(this.props.value)}</text>
|
||||
</g>
|
||||
)
|
||||
}
|
||||
}
|
179
src/cards/TopLanguagesCard.tsx
Normal file
179
src/cards/TopLanguagesCard.tsx
Normal file
@ -0,0 +1,179 @@
|
||||
import { getColor, getProgress, trunc } from "../common/utils"
|
||||
import Card, { CardOptions } from '../common/Card'
|
||||
import React from 'react'
|
||||
import FlexLayout from "../components/FlexLayout";
|
||||
import { TopLanguage } from "../interfaces";
|
||||
|
||||
interface TopLanguagesOptions extends CardOptions {
|
||||
hide?: Array<string>
|
||||
language_count?: number
|
||||
card_width?: number
|
||||
layout?: string
|
||||
text_color?: string
|
||||
}
|
||||
|
||||
export default class TopLanguagesCard extends Card {
|
||||
|
||||
public constructor(
|
||||
private username: string,
|
||||
private langs: Array<TopLanguage>,
|
||||
private options: TopLanguagesOptions
|
||||
) {
|
||||
super(options)
|
||||
|
||||
|
||||
this.langs = this.langs
|
||||
.filter((item) => !(options.hide || []).includes(item.name))
|
||||
.slice(0, options.language_count || 5)
|
||||
|
||||
|
||||
this.height = 45 + (this.langs.length + 1) * 40
|
||||
this.width = 300
|
||||
if (options.card_width && !isNaN(options.card_width)) {
|
||||
this.width = options.card_width
|
||||
}
|
||||
|
||||
const textColor = getColor('text_color', options.text_color, options.theme)
|
||||
this.title = "Most Used Languages"
|
||||
this.css = CompactTextNode.getCSS(textColor as string)
|
||||
}
|
||||
|
||||
public render() {
|
||||
if (this.options.layout === 'compact') {
|
||||
this.width = this.width + 50
|
||||
this.height = 90 + Math.round(this.langs.length / 2) * 25
|
||||
return super.render(
|
||||
<svg x="25">
|
||||
<mask id="rect-mask">
|
||||
<rect x="0" y="0" width={this.width - 50} height="8" fill="white" rx="5" />
|
||||
</mask>
|
||||
<CompactProgressBar langs={this.langs} parentWidth={this.width} />
|
||||
{this.langs.map((el, index) => (
|
||||
<CompactTextNode key={index} index={index} lang={el} />
|
||||
))}
|
||||
</svg>
|
||||
)
|
||||
} else {
|
||||
return super.render(
|
||||
<svg x="25">
|
||||
<FlexLayout items={
|
||||
this.langs.map((el, index) => (
|
||||
<ProgressNode lang={el} parentWidth={this.width} />
|
||||
))
|
||||
}
|
||||
gap={40}
|
||||
direction="column"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class CompactProgressBar extends React.Component<{
|
||||
langs: Array<TopLanguage>
|
||||
parentWidth: number
|
||||
}> {
|
||||
public render() {
|
||||
|
||||
let offset = 0
|
||||
const totalSize = this.props.langs.reduce((acc, curr) => acc + curr.xp, 0)
|
||||
|
||||
return this.props.langs.map((lang, index) => {
|
||||
const percent = trunc((lang.xp / totalSize) * (this.props.parentWidth - 50), 2)
|
||||
const progress = percent < 10 ? percent + 10 : percent
|
||||
|
||||
const output = (
|
||||
<rect
|
||||
key={index}
|
||||
mask="url(#rect-mask)"
|
||||
data-testid="lang-progress"
|
||||
x={offset}
|
||||
y="0"
|
||||
width={progress}
|
||||
height="8"
|
||||
fill={lang.color || "#858585"}
|
||||
/>
|
||||
)
|
||||
|
||||
offset += percent
|
||||
return output
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
class CompactTextNode extends React.Component<{
|
||||
index: number
|
||||
lang: TopLanguage
|
||||
}> {
|
||||
|
||||
public static getCSS = (textColor: string) => `
|
||||
.lang-name {
|
||||
font: 400 11px 'Segoe UI', Ubuntu, Sans-Serif;
|
||||
fill: ${textColor};
|
||||
}
|
||||
`
|
||||
|
||||
public render() {
|
||||
const index = this.props.index
|
||||
|
||||
let x = 0
|
||||
let y = 12.5 * index + 25
|
||||
if (index % 2 !== 0) {
|
||||
x = 150
|
||||
y = 12.5 + 12.5 * index
|
||||
}
|
||||
|
||||
return (
|
||||
<g transform={`translate(${x}, ${y})`}>
|
||||
<circle cx="5" cy="6" r="5" fill={this.props.lang.color} />
|
||||
<text data-testid="lang-name" x="15" y="10" className='lang-name'>
|
||||
{this.props.lang.name} {getProgress(this.props.lang.xp)}%
|
||||
</text>
|
||||
</g>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class ProgressNode extends React.Component<{
|
||||
lang: TopLanguage
|
||||
parentWidth: number
|
||||
}> {
|
||||
|
||||
private paddingRight = 60
|
||||
|
||||
|
||||
public render() {
|
||||
const width = this.props.parentWidth - this.paddingRight
|
||||
const progress1 = getProgress(this.props.lang.xp)
|
||||
const progress2 = getProgress(this.props.lang.xp - this.props.lang.recentXp)
|
||||
|
||||
return (
|
||||
<>
|
||||
<text data-testid="lang-name" x="2" y="15" className="lang-name">{this.props.lang.name} {progress1}% {this.props.lang.recentXp >= 1 ? ' + ' + (trunc(progress1 - progress2, 2)) + '%' : ''}</text>
|
||||
<svg width={width}>
|
||||
<rect rx="5" ry="5" x="0" y="25" width={width} height="8" fill="#ddd" />
|
||||
{progress1 !== progress2 && (
|
||||
<rect
|
||||
height="8"
|
||||
fill="#f2b866"
|
||||
rx="5" ry="5" x="1" y="25"
|
||||
width={`${progress1}%`}
|
||||
/>
|
||||
)}
|
||||
{progress1 >= progress2 && (
|
||||
<rect
|
||||
height="8"
|
||||
fill={this.props.lang.color}
|
||||
rx="5" ry="5" x="0" y="25"
|
||||
data-testid="lang-progress"
|
||||
width={`${progress2}%`}
|
||||
/>
|
||||
)}
|
||||
|
||||
</svg>
|
||||
</>
|
||||
)
|
||||
}
|
||||
}
|
@ -1,185 +0,0 @@
|
||||
import { kFormatter, getCardColors, FlexLayout, encodeHTML, getProgress } from '../common/utils'
|
||||
import { getStyles } from '../getStyles'
|
||||
import icons from '../common/icons'
|
||||
import Card from '../common/Card'
|
||||
import React from 'react'
|
||||
import themes from '../../themes'
|
||||
|
||||
const createTextNode = ({
|
||||
icon,
|
||||
label,
|
||||
value,
|
||||
index,
|
||||
showIcons
|
||||
}: {
|
||||
icon: JSX.Element,
|
||||
label: string,
|
||||
value: number,
|
||||
index: number,
|
||||
showIcons: boolean
|
||||
}) => {
|
||||
const kValue = kFormatter(value);
|
||||
const staggerDelay = (index + 3) * 150;
|
||||
|
||||
const iconSvg = showIcons
|
||||
? (
|
||||
<svg data-testid="icon" className="icon" viewBox="0 0 16 16" version="1.1" width="16" height="16">
|
||||
{icon}
|
||||
</svg>
|
||||
)
|
||||
: undefined
|
||||
return (
|
||||
<g className="stagger" style={{animationDelay: `${staggerDelay}ms`}} transform="translate(25, 0)">
|
||||
{iconSvg}
|
||||
<text className="stat bold" x={showIcons ? 25 : undefined} y="12.5">{label}:</text>
|
||||
<text
|
||||
className="stat"
|
||||
x={showIcons ? 120 : 100}
|
||||
y="12.5"
|
||||
>{kValue}</text>
|
||||
</g>
|
||||
)
|
||||
};
|
||||
|
||||
interface Options {
|
||||
hide?: Array<string>
|
||||
show_icons?: boolean
|
||||
hide_title?: boolean
|
||||
hide_border?: boolean
|
||||
hide_rank?: boolean
|
||||
line_height?: number
|
||||
title_color?: string
|
||||
icon_color?: string
|
||||
text_color?: string
|
||||
bg_color?: string
|
||||
theme?: keyof typeof themes
|
||||
}
|
||||
|
||||
export default (stats: {username: string, xp: number, recentXp: number, level: number}, options: Options = { hide: [] }) => {
|
||||
const {
|
||||
username,
|
||||
xp,
|
||||
recentXp,
|
||||
level
|
||||
} = stats;
|
||||
const {
|
||||
hide = [],
|
||||
show_icons = false,
|
||||
hide_title = false,
|
||||
hide_border = false,
|
||||
hide_rank = false,
|
||||
line_height = 25,
|
||||
title_color,
|
||||
icon_color,
|
||||
text_color,
|
||||
bg_color,
|
||||
theme = "default",
|
||||
} = options;
|
||||
|
||||
const lheight = line_height
|
||||
|
||||
// returns theme based colors with proper overrides and defaults
|
||||
const { titleColor, textColor, iconColor, bgColor } = getCardColors({
|
||||
title_color,
|
||||
icon_color,
|
||||
text_color,
|
||||
bg_color,
|
||||
theme,
|
||||
});
|
||||
|
||||
// Meta data for creating text nodes with createTextNode function
|
||||
const STATS = {
|
||||
xp: {
|
||||
icon: icons.star,
|
||||
label: "XP",
|
||||
value: xp,
|
||||
id: "xp",
|
||||
},
|
||||
recent_xp: {
|
||||
icon: icons.commits,
|
||||
label: 'Recent xp',
|
||||
value: recentXp,
|
||||
id: "recent_xp",
|
||||
},
|
||||
};
|
||||
|
||||
// filter out hidden stats defined by user & create the text nodes
|
||||
const statItems = Object.keys(STATS)
|
||||
.filter((key) => !hide.includes(key))
|
||||
.map((key, index) =>
|
||||
// create the text nodes, and pass index so that we can calculate the line spacing
|
||||
createTextNode({
|
||||
...STATS[key],
|
||||
index,
|
||||
showIcons: show_icons
|
||||
})
|
||||
);
|
||||
|
||||
// Calculate the card height depending on how many items there are
|
||||
// but if rank circle is visible clamp the minimum height to `150`
|
||||
let height = Math.max(
|
||||
45 + (statItems.length + 1) * lheight,
|
||||
hide_rank ? 0 : 120
|
||||
);
|
||||
|
||||
// Conditionally rendered elements
|
||||
const rankCircle = hide_rank
|
||||
? undefined
|
||||
: (
|
||||
<g data-testid="rank-circle"
|
||||
transform={`translate(400, 0)`}>
|
||||
<circle className="rank-circle-rim" cx="-10" cy="8" r="40" />
|
||||
<circle className="rank-circle" cx="-10" cy="8" r="40" />
|
||||
<g className="rank-text">
|
||||
<text
|
||||
x="-4"
|
||||
y="0"
|
||||
alignmentBaseline="central"
|
||||
dominantBaseline="central"
|
||||
textAnchor="middle"
|
||||
>
|
||||
lv {level}
|
||||
</text>
|
||||
</g>
|
||||
</g>
|
||||
)
|
||||
|
||||
const progress = getProgress(xp + recentXp);
|
||||
const cssStyles = getStyles({
|
||||
titleColor,
|
||||
textColor,
|
||||
iconColor,
|
||||
show_icons,
|
||||
progress,
|
||||
});
|
||||
|
||||
const apostrophe = ["x", "s"].includes(username.slice(-1)) ? "" : "s";
|
||||
const card = new Card(
|
||||
495,
|
||||
height,
|
||||
{
|
||||
titleColor,
|
||||
textColor,
|
||||
iconColor,
|
||||
bgColor,
|
||||
},
|
||||
`${encodeHTML(username)}'${apostrophe} Code::stats Profile`
|
||||
)
|
||||
|
||||
card.setHideBorder(hide_border);
|
||||
card.setHideTitle(hide_title);
|
||||
card.setCSS(cssStyles);
|
||||
|
||||
return card.render(
|
||||
<>
|
||||
{rankCircle}
|
||||
<svg x="0" y="0">
|
||||
{FlexLayout({
|
||||
items: statItems,
|
||||
gap: lheight,
|
||||
direction: "column",
|
||||
})}
|
||||
</svg>
|
||||
</>
|
||||
)
|
||||
}
|
@ -1,242 +0,0 @@
|
||||
import { getCardColors, FlexLayout, clampValue } from "../common/utils"
|
||||
import Card from '../common/Card'
|
||||
import { data } from "../fetcher";
|
||||
import React from 'react'
|
||||
import themes from "../../themes";
|
||||
|
||||
export interface parsedQuery {
|
||||
hide?: Array<string>
|
||||
hide_title?: boolean
|
||||
hide_border?: boolean
|
||||
card_width?: number
|
||||
title_color?: string
|
||||
text_color?: string
|
||||
bg_color?: string
|
||||
language_count?: number
|
||||
show_level?: string
|
||||
theme?: keyof typeof themes
|
||||
cache_seconds?: string
|
||||
layout?: string
|
||||
}
|
||||
|
||||
const createProgressNode = ({ width, color, name, progress, progress2 }: {width: number ,color: string, name: string, progress: number, progress2:number}) => {
|
||||
const paddingRight = 60;
|
||||
const progressWidth = width - paddingRight;
|
||||
const progressPercentage = clampValue(progress, 2, 100);
|
||||
const progress2Percentage = clampValue(progress2, 2, 100);
|
||||
|
||||
return (
|
||||
<>
|
||||
<text data-testid="lang-name" x="2" y="15" className="lang-name">{name} {progress}%{progress2 > progress ? ` + ${progress2 - progress}%` : ''}</text>
|
||||
<svg width={progressWidth}>
|
||||
<rect rx="5" ry="5" x="0" y="25" width={progressWidth} height="8" fill="#ddd" />
|
||||
<rect
|
||||
height="8"
|
||||
fill="#f2b866"
|
||||
rx="5" ry="5" x="1" y="25"
|
||||
width={`calc(${progress2Percentage}% - 1px)`}
|
||||
/>
|
||||
<rect
|
||||
height="8"
|
||||
fill={color}
|
||||
rx="5" ry="5" x="0" y="25"
|
||||
data-testid="lang-progress"
|
||||
width={`${progressPercentage}%`}
|
||||
/>
|
||||
</svg>
|
||||
</>
|
||||
)
|
||||
};
|
||||
|
||||
const createCompactLangNode = ({ lang, totalSize, x, y }: {lang: data, totalSize: number, x: number, y: number}) => {
|
||||
const percentage = ((lang.size / totalSize) * 100).toFixed(2);
|
||||
const color = lang.color || "#858585";
|
||||
|
||||
return (
|
||||
<g transform={`translate(${x}, ${y})`}>
|
||||
<circle cx="5" cy="6" r="5" fill={color} />
|
||||
<text data-testid="lang-name" x="15" y="10" className='lang-name'>
|
||||
{lang.name} {percentage}%
|
||||
</text>
|
||||
</g>
|
||||
)
|
||||
};
|
||||
|
||||
const createLanguageTextNode = ({ langs, totalSize, x, y }: { langs: Array<data>, totalSize: number, x: number, y: number}) => {
|
||||
return langs.map((lang, index) => {
|
||||
if (index % 2 === 0) {
|
||||
return createCompactLangNode({
|
||||
lang,
|
||||
x,
|
||||
y: 12.5 * index + y,
|
||||
totalSize
|
||||
});
|
||||
}
|
||||
return createCompactLangNode({
|
||||
lang,
|
||||
x: 150,
|
||||
y: 12.5 + 12.5 * index,
|
||||
totalSize
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const lowercaseTrim = (name: string) => name.toLowerCase().trim();
|
||||
|
||||
const renderTopLanguages = (topLangs: Record<string, data>, options: parsedQuery = {}) => {
|
||||
const {
|
||||
hide_title,
|
||||
hide_border,
|
||||
card_width,
|
||||
title_color,
|
||||
text_color,
|
||||
bg_color,
|
||||
hide,
|
||||
language_count,
|
||||
theme,
|
||||
layout,
|
||||
} = options;
|
||||
|
||||
let langs = Object.values(topLangs);
|
||||
let langsToHide: Record<string, boolean> = {};
|
||||
|
||||
// populate langsToHide map for quick lookup
|
||||
// while filtering out
|
||||
if (hide) {
|
||||
hide.forEach((langName) => {
|
||||
langsToHide[lowercaseTrim(langName)] = true;
|
||||
});
|
||||
}
|
||||
|
||||
// filter out langauges to be hidden
|
||||
langs = langs
|
||||
.sort((a, b) => b.size - a.size)
|
||||
.filter((lang) => {
|
||||
return !langsToHide[lowercaseTrim(lang.name)];
|
||||
})
|
||||
.slice(0, language_count || 5);
|
||||
|
||||
const totalLanguageSize = langs.reduce((acc, curr) => {
|
||||
return acc + curr.size;
|
||||
}, 0);
|
||||
|
||||
// returns theme based colors with proper overrides and defaults
|
||||
const { titleColor, textColor, bgColor } = getCardColors({
|
||||
title_color,
|
||||
text_color,
|
||||
bg_color,
|
||||
theme,
|
||||
});
|
||||
|
||||
let width = typeof card_width !== 'number' ? 300 : isNaN(card_width) ? 300 : card_width;
|
||||
let height = 45 + (langs.length + 1) * 40;
|
||||
|
||||
let finalLayout: JSX.Element | Array<JSX.Element>;
|
||||
|
||||
// RENDER COMPACT LAYOUT
|
||||
if (layout === "compact") {
|
||||
width = width + 50;
|
||||
height = 30 + (langs.length / 2 + 1) * 40;
|
||||
|
||||
// progressOffset holds the previous language's width and used to offset the next language
|
||||
// so that we can stack them one after another, like this: [--][----][---]
|
||||
let progressOffset = 0;
|
||||
const compactProgressBar = langs
|
||||
.map((lang, index) => {
|
||||
const percentage = parseFloat((
|
||||
(lang.size / totalLanguageSize) *
|
||||
(width - 50)
|
||||
).toFixed(2));
|
||||
|
||||
const progress =
|
||||
percentage < 10 ? percentage + 10 : percentage;
|
||||
|
||||
const output = (
|
||||
<rect
|
||||
key={index}
|
||||
mask="url(#rect-mask)"
|
||||
data-testid="lang-progress"
|
||||
x={progressOffset}
|
||||
y="0"
|
||||
width={progress}
|
||||
height="8"
|
||||
fill={lang.color || "#858585"}
|
||||
/>
|
||||
)
|
||||
progressOffset += percentage;
|
||||
return output;
|
||||
})
|
||||
|
||||
finalLayout = (
|
||||
<>
|
||||
<mask id="rect-mask">
|
||||
<rect x="0" y="0" width={
|
||||
width - 50
|
||||
} height="8" fill="white" rx="5" />
|
||||
</mask>
|
||||
{compactProgressBar}
|
||||
{createLanguageTextNode({
|
||||
x: 0,
|
||||
y: 25,
|
||||
langs,
|
||||
totalSize: totalLanguageSize,
|
||||
})}
|
||||
</>
|
||||
)
|
||||
|
||||
finalLayout = (
|
||||
<>
|
||||
<mask id="rect-mask">
|
||||
<rect x="0" y="0" width={width - 50} height="8" fill="white" rx="5" />
|
||||
</mask>
|
||||
{compactProgressBar}
|
||||
{createLanguageTextNode({
|
||||
x: 0,
|
||||
y: 25,
|
||||
langs,
|
||||
totalSize: totalLanguageSize,
|
||||
})}
|
||||
</>
|
||||
)
|
||||
} else {
|
||||
finalLayout = FlexLayout({
|
||||
items: langs.map((lang) => {
|
||||
return createProgressNode({
|
||||
width: width,
|
||||
name: lang.name,
|
||||
color: lang.color || "#858585",
|
||||
progress: parseFloat(((lang.size / totalLanguageSize) * 100).toFixed(2)),
|
||||
progress2: parseFloat(((lang.recentSize / totalLanguageSize) * 100).toFixed(2)),
|
||||
});
|
||||
}),
|
||||
gap: 40,
|
||||
direction: "column",
|
||||
})
|
||||
}
|
||||
|
||||
const card = new Card(
|
||||
width,
|
||||
height,
|
||||
{
|
||||
titleColor,
|
||||
textColor,
|
||||
bgColor,
|
||||
},
|
||||
"Most Used Languages",
|
||||
)
|
||||
|
||||
card.disableAnimations();
|
||||
card.setHideBorder(hide_border || false);
|
||||
card.setHideTitle(hide_title || false);
|
||||
card.setCSS(`
|
||||
.lang-name { font: 400 11px 'Segoe UI', Ubuntu, Sans-Serif; fill: ${textColor} }
|
||||
`);
|
||||
|
||||
return card.render(
|
||||
<svg data-testid="lang-items" x="25">
|
||||
{finalLayout}
|
||||
</svg>
|
||||
)
|
||||
};
|
||||
|
||||
export default renderTopLanguages
|
@ -1,7 +1,16 @@
|
||||
import React from 'react'
|
||||
import themes from '../../themes/themes.json'
|
||||
import FlexLayout from '../components/FlexLayout'
|
||||
|
||||
import { FlexLayout } from './utils'
|
||||
import { getAnimations } from '../getStyles'
|
||||
import { getColor, parseBoolean } from './utils'
|
||||
|
||||
export interface CardOptions {
|
||||
title_color?: string
|
||||
bg_color?: string
|
||||
hide_border?: boolean
|
||||
hide_title?: boolean
|
||||
theme?: keyof typeof themes
|
||||
}
|
||||
|
||||
export default class Card {
|
||||
public hideBorder = false
|
||||
@ -10,45 +19,32 @@ export default class Card {
|
||||
public paddingX = 25
|
||||
public paddingY = 35
|
||||
public animations = true
|
||||
public height = 100
|
||||
public width = 100
|
||||
public title = ''
|
||||
public colors: {
|
||||
titleColor?: string | Array<string>,
|
||||
bgColor?: string | Array<string>
|
||||
} = {}
|
||||
public titlePrefix?: JSX.Element
|
||||
|
||||
constructor(
|
||||
public width = 100,
|
||||
public height = 100,
|
||||
public colors: {titleColor?: string | Array<string>, textColor?: string | Array<string>, bgColor?: string | Array<string>, iconColor?: string | Array<string>} = {},
|
||||
public title = "",
|
||||
public titlePrefixIcon?: string
|
||||
) {}
|
||||
|
||||
disableAnimations() {
|
||||
this.animations = false;
|
||||
}
|
||||
|
||||
setCSS(value: string) {
|
||||
this.css = value;
|
||||
}
|
||||
|
||||
setHideBorder(value: boolean) {
|
||||
this.hideBorder = value;
|
||||
}
|
||||
|
||||
setHideTitle(value: boolean) {
|
||||
this.hideTitle = value;
|
||||
if (value) {
|
||||
this.height -= 30;
|
||||
constructor(options?: CardOptions) {
|
||||
if (options) {
|
||||
this.hideBorder = parseBoolean(options.hide_border)
|
||||
this.hideTitle = parseBoolean(options.hide_title)
|
||||
this.colors = {
|
||||
titleColor: getColor('title_color', options.title_color, options.theme),
|
||||
bgColor: getColor('bg_color', options.bg_color, options.theme),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setTitle(text: string) {
|
||||
this.title = text;
|
||||
}
|
||||
|
||||
renderTitle() {
|
||||
const titleText = (
|
||||
<text
|
||||
x="0"
|
||||
y="0"
|
||||
className="header"
|
||||
data-testid="header"
|
||||
>{this.title}</text>
|
||||
)
|
||||
|
||||
@ -63,18 +59,17 @@ export default class Card {
|
||||
width="16"
|
||||
height="16"
|
||||
>
|
||||
${this.titlePrefixIcon}
|
||||
{this.titlePrefix}
|
||||
</svg>
|
||||
)
|
||||
return (
|
||||
<g
|
||||
data-testid="card-title"
|
||||
transform={`translate(${this.paddingX}, ${this.paddingY})`}
|
||||
>
|
||||
{FlexLayout({
|
||||
items: [this.titlePrefixIcon && prefixIcon, titleText],
|
||||
gap: 25,
|
||||
})}
|
||||
<FlexLayout
|
||||
items={[this.titlePrefix && prefixIcon, titleText]}
|
||||
gap={25}
|
||||
/>
|
||||
</g>
|
||||
)
|
||||
}
|
||||
@ -104,7 +99,7 @@ export default class Card {
|
||||
return (
|
||||
<svg
|
||||
width={this.width}
|
||||
height={this.height}
|
||||
height={this.height - (this.hideTitle ? 30 : 0)}
|
||||
viewBox={`0 0 ${this.width} ${this.height}`}
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
@ -117,17 +112,28 @@ export default class Card {
|
||||
}
|
||||
${this.css}
|
||||
|
||||
${
|
||||
process.env.NODE_ENV === "test" || !this.animations
|
||||
? ""
|
||||
: getAnimations()
|
||||
/* Animations */
|
||||
@keyframes scaleInAnimation {
|
||||
from {
|
||||
transform: translate(-5px, 5px) scale(0);
|
||||
}
|
||||
to {
|
||||
transform: translate(-5px, 5px) scale(1);
|
||||
}
|
||||
}
|
||||
@keyframes fadeInAnimation {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
`}</style>
|
||||
|
||||
{this.renderGradient()}
|
||||
|
||||
<rect
|
||||
data-testid="card-bg"
|
||||
x="0.5"
|
||||
y="0.5"
|
||||
rx="4.5"
|
||||
@ -145,7 +151,6 @@ export default class Card {
|
||||
{this.hideTitle ? "" : this.renderTitle()}
|
||||
|
||||
<g
|
||||
data-testid="main-card-body"
|
||||
transform={`translate(0, ${
|
||||
this.hideTitle ? this.paddingX : this.paddingY + 20
|
||||
})`}
|
||||
|
@ -1,3 +0,0 @@
|
||||
const blacklist = ["renovate-bot", "technote-space", "sw-yx"];
|
||||
|
||||
export default blacklist
|
@ -1,19 +1,20 @@
|
||||
import { CustomError, request } from './utils'
|
||||
import { AxiosPromise } from 'axios';
|
||||
import { CustomError } from './utils'
|
||||
import { CodeStatsResponse } from '../interfaces';
|
||||
|
||||
const retryer = async <T = AxiosPromise<{error: string}>>(fetcher: (variables: {login: string}) => T, variables: {login: string}, retries = 0): Promise<T> => {
|
||||
export default async function retryer<T = Promise<CodeStatsResponse>>(
|
||||
fetcher: (username: string) => T,
|
||||
data: string,
|
||||
retries = 0,
|
||||
err?: any
|
||||
): Promise<T> {
|
||||
if (retries > 7) {
|
||||
throw new CustomError("Maximum retries exceeded", 'MAX_RETRY');
|
||||
throw new CustomError("Maximum retries exceeded" + err, 'MAX_RETRY')
|
||||
}
|
||||
try {
|
||||
let response = await fetcher(
|
||||
variables
|
||||
return await fetcher(
|
||||
data
|
||||
)
|
||||
|
||||
return response;
|
||||
} catch (err) {
|
||||
return retryer(fetcher, variables, 1 + retries);
|
||||
return retryer(fetcher, data, ++retries, err)
|
||||
}
|
||||
};
|
||||
|
||||
export default retryer
|
||||
}
|
||||
|
208
src/common/utils.ts
Normal file
208
src/common/utils.ts
Normal file
@ -0,0 +1,208 @@
|
||||
import fetch from 'node-fetch'
|
||||
import { Response } from 'express'
|
||||
import wrap from 'word-wrap'
|
||||
import themes from '../../themes/themes.json'
|
||||
import { CodeStatsResponse } from '../interfaces';
|
||||
import languageColor from '../../themes/language-bar.json'
|
||||
|
||||
/**
|
||||
* Encode a string to escape HTML
|
||||
*
|
||||
* https://stackoverflow.com/a/48073476/10629172
|
||||
* @param str the string to encode
|
||||
*/
|
||||
export function encodeHTML(str: string) {
|
||||
return str
|
||||
.replace(/[\u00A0-\u9999<>&](?!#)/gim, (i) => {
|
||||
return "&#" + i.charCodeAt(0) + ";";
|
||||
})
|
||||
.replace(/\u0008/gim, "");
|
||||
}
|
||||
|
||||
export const kFormatter = (num: number) =>
|
||||
Math.abs(num) > 999 ?
|
||||
trunc(num / 1000) + 'k' :
|
||||
num
|
||||
|
||||
/**
|
||||
* Transform the `value` into a Boolean
|
||||
* @param value the value to transform
|
||||
*/
|
||||
export function parseBoolean(value: boolean | string | undefined) {
|
||||
if (value === "true" || value === true) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export function parseArray(str: string | undefined) {
|
||||
if (!str) return [];
|
||||
return str.split(",");
|
||||
}
|
||||
|
||||
export function clampValue(number: number, min: number, max?: number) {
|
||||
return Math.max(min, max ? Math.min(number, max) : number);
|
||||
}
|
||||
|
||||
export async function request(username: string): Promise<CodeStatsResponse> {
|
||||
const resp = await fetch(
|
||||
`https://codestats.net/api/users/${username}`
|
||||
);
|
||||
return resp.json();
|
||||
}
|
||||
|
||||
export async function profileGraphRequest<T>(body: string): Promise<T> {
|
||||
const resp = await fetch(
|
||||
'https://codestats.net/profile-graph',
|
||||
{
|
||||
body,
|
||||
method: 'POST'
|
||||
}
|
||||
)
|
||||
return resp.json()
|
||||
}
|
||||
|
||||
export function getColor(color: keyof typeof themes.default, replacementColor?: string, theme: keyof typeof themes = 'default') {
|
||||
return '#' + (replacementColor ? replacementColor : themes[theme][color])
|
||||
}
|
||||
|
||||
export function wrapTextMultiline(text: string, width = 60, maxLines = 3) {
|
||||
const wrapped = wrap(encodeHTML(text), { width })
|
||||
.split("\n") // Split wrapped lines to get an array of lines
|
||||
.map((line) => line.trim()); // Remove leading and trailing whitespace of each line
|
||||
|
||||
const lines = wrapped.slice(0, maxLines); // Only consider maxLines lines
|
||||
|
||||
// Add "..." to the last line if the text exceeds maxLines
|
||||
if (wrapped.length > maxLines) {
|
||||
lines[maxLines - 1] += "...";
|
||||
}
|
||||
|
||||
// Remove empty lines if text fits in less than maxLines lines
|
||||
const multiLineText = lines.filter(Boolean);
|
||||
return multiLineText;
|
||||
}
|
||||
|
||||
export const CONSTANTS = {
|
||||
THIRTY_MINUTES: 1800,
|
||||
TWO_HOURS: 7200,
|
||||
FOUR_HOURS: 14400,
|
||||
ONE_DAY: 86400,
|
||||
LEVEL_FACTOR: 0.025,
|
||||
};
|
||||
|
||||
export const SECONDARY_ERROR_MESSAGES = {
|
||||
MAX_RETRY: "Make sur your profile is not private"
|
||||
};
|
||||
|
||||
export class CustomError extends Error {
|
||||
public secondaryMessage: string
|
||||
|
||||
constructor(message: string, public type: keyof typeof SECONDARY_ERROR_MESSAGES) {
|
||||
super(message);
|
||||
this.secondaryMessage = SECONDARY_ERROR_MESSAGES[type] || "adsad";
|
||||
}
|
||||
|
||||
static MAX_RETRY = "MAX_RETRY";
|
||||
static USER_NOT_FOUND = "USER_NOT_FOUND";
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the level depending on the xp
|
||||
*
|
||||
* https://codestats.net/api-docs
|
||||
* @param xp the xp count
|
||||
*/
|
||||
export function getLevel(xp: number): number {
|
||||
return Math.trunc(Math.floor(CONSTANTS.LEVEL_FACTOR * Math.sqrt(xp)))
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the progress (0-99)% til next level
|
||||
* @param xp Xp number
|
||||
*/
|
||||
export function getProgress(xp: number): number {
|
||||
const currentLvl = getLevel(xp)
|
||||
return trunc((CONSTANTS.LEVEL_FACTOR * Math.sqrt(xp) - currentLvl) * 100, 2)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Truncate a number without moving it to a string and reparsing it
|
||||
*
|
||||
* https://stackoverflow.com/a/29494612/7335674
|
||||
* @param number the number to truncate
|
||||
* @param digits the number of digits after the dot
|
||||
*/
|
||||
export function trunc(number: number, digits: number = 0) {
|
||||
const pow = Math.pow(10, digits)
|
||||
return Math.round(number * pow) / pow
|
||||
}
|
||||
|
||||
export function parseNumber(number: string | number | undefined): number | undefined {
|
||||
if (typeof number === 'undefined' || typeof number === 'number') {
|
||||
return number
|
||||
}
|
||||
const n = parseFloat(number)
|
||||
if (isNaN(n)) {
|
||||
return undefined
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
|
||||
export function calculateCircleProgress(percent: number) {
|
||||
let radius = 40;
|
||||
let c = Math.PI * radius * 2
|
||||
|
||||
percent = clampValue(percent, 0, 100)
|
||||
|
||||
let percentage = ((100 - percent) / 100) * c
|
||||
return percentage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the response
|
||||
* @param res the response object
|
||||
*/
|
||||
export function prepareResponse(res: Response) {
|
||||
res.setHeader("Content-Type", "image/svg+xml")
|
||||
}
|
||||
|
||||
/**
|
||||
* set the cache in the response
|
||||
* @param res the Response object
|
||||
* @param cache The cache time in seconds
|
||||
*/
|
||||
export function setCache(res: Response, cache: number) {
|
||||
if (isNaN(cache)) {
|
||||
cache = CONSTANTS.THIRTY_MINUTES
|
||||
}
|
||||
const clampedCache = clampValue(cache, CONSTANTS.THIRTY_MINUTES, CONSTANTS.ONE_DAY)
|
||||
|
||||
res.setHeader('Cache-Control', `public, stale-while-revalidate, max-age=${clampedCache} s-maxage=${clampedCache}`)
|
||||
|
||||
}
|
||||
|
||||
|
||||
export function lowercaseTrim(str: string) {
|
||||
return str.toLowerCase().trim()
|
||||
}
|
||||
|
||||
|
||||
export function formatDateNumber(number: number): string {
|
||||
if (number < 10) {
|
||||
return '0' + number
|
||||
}
|
||||
return number + ''
|
||||
}
|
||||
|
||||
export function formatDate(date: Date): string {
|
||||
return `${date.getFullYear()}-${formatDateNumber(date.getMonth() + 1)}-${formatDateNumber(date.getDate())}`
|
||||
}
|
||||
|
||||
|
||||
export function getColorOfLanguage(name: string): string {
|
||||
return name in languageColor ? languageColor[name as keyof typeof languageColor].color || '#000' : '#000'
|
||||
}
|
@ -1,203 +0,0 @@
|
||||
import React from 'react'
|
||||
|
||||
import axios, { AxiosPromise } from 'axios'
|
||||
import wrap from 'word-wrap'
|
||||
import themes from '../../themes'
|
||||
import { CodeStatsResponse } from '../fetcher/interface';
|
||||
|
||||
export const renderError = (message: string, secondaryMessage = "") => {
|
||||
return (
|
||||
<svg width="495" height="120" viewBox="0 0 495 120" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<style>{`
|
||||
.text { font: 600 16px 'Segoe UI', Ubuntu, Sans-Serif; fill: #2F80ED }
|
||||
.small { font: 600 12px 'Segoe UI', Ubuntu, Sans-Serif; fill: #252525 }
|
||||
.gray { fill: #858585 }
|
||||
`}</style>
|
||||
<rect x="0.5" y="0.5" width="494" height="99%" rx="4.5" fill="#FFFEFE" stroke="#E4E2E2"/>
|
||||
<text x="25" y="45" className="text">Something went wrong! file an issue at https://dze.io/3nL29</text>
|
||||
<text data-testid="message" x="25" y="55" className="text small">
|
||||
<tspan x="25" dy="18">{encodeHTML(message)}</tspan>
|
||||
<tspan x="25" dy="18" className="gray">{secondaryMessage}</tspan>
|
||||
</text>
|
||||
</svg>
|
||||
)
|
||||
};
|
||||
|
||||
// https://stackoverflow.com/a/48073476/10629172
|
||||
export function encodeHTML(str: string) {
|
||||
return str
|
||||
.replace(/[\u00A0-\u9999<>&](?!#)/gim, (i) => {
|
||||
return "&#" + i.charCodeAt(0) + ";";
|
||||
})
|
||||
.replace(/\u0008/gim, "");
|
||||
}
|
||||
|
||||
export function kFormatter(num: number) {
|
||||
return Math.abs(num) > 999
|
||||
? Math.sign(num) * parseInt((Math.abs(num) / 1000).toFixed(1)) + "k"
|
||||
: Math.sign(num) * Math.abs(num);
|
||||
}
|
||||
|
||||
export function isValidHexColor(hexColor: string) {
|
||||
return new RegExp(
|
||||
/^([A-Fa-f0-9]{8}|[A-Fa-f0-9]{6}|[A-Fa-f0-9]{3}|[A-Fa-f0-9]{4})$/
|
||||
).test(hexColor);
|
||||
}
|
||||
|
||||
export function parseBoolean(value: string | undefined) {
|
||||
if (value === "true") {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export function parseArray(str: string | undefined) {
|
||||
if (!str) return [];
|
||||
return str.split(",");
|
||||
}
|
||||
|
||||
export function clampValue(number: number, min: number, max: number) {
|
||||
return Math.max(min, Math.min(number, max));
|
||||
}
|
||||
|
||||
export function isValidGradient(colors: Array<string>) {
|
||||
return isValidHexColor(colors[1]) && isValidHexColor(colors[2]);
|
||||
}
|
||||
|
||||
export function fallbackColor(color: string, fallbackColor: Array<string>| string) {
|
||||
let colors = color.split(",");
|
||||
let gradient = null;
|
||||
|
||||
if (colors.length > 1 && isValidGradient(colors)) {
|
||||
gradient = colors;
|
||||
}
|
||||
|
||||
return (
|
||||
(gradient ? gradient : isValidHexColor(color) && `#${color}`) ||
|
||||
fallbackColor
|
||||
);
|
||||
}
|
||||
|
||||
export function request(data: {login: string}): AxiosPromise<CodeStatsResponse> {
|
||||
return axios({
|
||||
url: "https://codestats.net/api/users/" + data.login,
|
||||
method: "get",
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {String[]} items
|
||||
* @param {Number} gap
|
||||
* @param {string} direction
|
||||
*
|
||||
* @description
|
||||
* Auto layout utility, allows us to layout things
|
||||
* vertically or horizontally with proper gaping
|
||||
*/
|
||||
export function FlexLayout({ items, gap, direction }: {items: Array<JSX.Element | string | undefined>, gap: number, direction?: string}) {
|
||||
// filter() for filtering out empty strings
|
||||
return items.filter(Boolean).map((item, i) => {
|
||||
let transform = `translate(${gap * i}, 0)`;
|
||||
if (direction === "column") {
|
||||
transform = `translate(0, ${gap * i})`;
|
||||
}
|
||||
return (
|
||||
<g key={i} transform={transform}>{item}</g>
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
// returns theme based colors with proper overrides and defaults
|
||||
export function getCardColors({
|
||||
title_color,
|
||||
text_color,
|
||||
icon_color,
|
||||
bg_color,
|
||||
theme,
|
||||
fallbackTheme = "default",
|
||||
}: {title_color?: string, text_color?: string, icon_color?: string, bg_color?: string, theme?: keyof typeof themes, fallbackTheme?: keyof typeof themes}) {
|
||||
const defaultTheme = themes[fallbackTheme];
|
||||
const selectedTheme = themes[theme as 'default'] || defaultTheme;
|
||||
|
||||
// get the color provided by the user else the theme color
|
||||
// finally if both colors are invalid fallback to default theme
|
||||
const titleColor = fallbackColor(
|
||||
title_color || selectedTheme.title_color,
|
||||
"#" + defaultTheme.title_color
|
||||
);
|
||||
const iconColor = fallbackColor(
|
||||
icon_color || selectedTheme.icon_color,
|
||||
"#" + defaultTheme.icon_color
|
||||
);
|
||||
const textColor = fallbackColor(
|
||||
text_color || selectedTheme.text_color,
|
||||
"#" + defaultTheme.text_color
|
||||
);
|
||||
const bgColor = fallbackColor(
|
||||
bg_color || selectedTheme.bg_color,
|
||||
"#" + defaultTheme.bg_color
|
||||
);
|
||||
|
||||
return { titleColor, iconColor, textColor, bgColor };
|
||||
}
|
||||
|
||||
export function wrapTextMultiline(text: string, width = 60, maxLines = 3) {
|
||||
const wrapped = wrap(encodeHTML(text), { width })
|
||||
.split("\n") // Split wrapped lines to get an array of lines
|
||||
.map((line) => line.trim()); // Remove leading and trailing whitespace of each line
|
||||
|
||||
const lines = wrapped.slice(0, maxLines); // Only consider maxLines lines
|
||||
|
||||
// Add "..." to the last line if the text exceeds maxLines
|
||||
if (wrapped.length > maxLines) {
|
||||
lines[maxLines - 1] += "...";
|
||||
}
|
||||
|
||||
// Remove empty lines if text fits in less than maxLines lines
|
||||
const multiLineText = lines.filter(Boolean);
|
||||
return multiLineText;
|
||||
}
|
||||
|
||||
export const noop = () => {};
|
||||
// return console instance based on the environment
|
||||
export const logger =
|
||||
process.env.NODE_ENV !== "test" ? console : { log: noop, error: noop };
|
||||
|
||||
export const CONSTANTS = {
|
||||
THIRTY_MINUTES: 1800,
|
||||
TWO_HOURS: 7200,
|
||||
FOUR_HOURS: 14400,
|
||||
ONE_DAY: 86400,
|
||||
LEVEL_FACTOR: 0.025,
|
||||
};
|
||||
|
||||
export const SECONDARY_ERROR_MESSAGES = {
|
||||
MAX_RETRY: "Make sur your profile is not private"
|
||||
};
|
||||
|
||||
export class CustomError extends Error {
|
||||
public secondaryMessage: string
|
||||
|
||||
constructor(message: string, public type: keyof typeof SECONDARY_ERROR_MESSAGES) {
|
||||
super(message);
|
||||
this.secondaryMessage = SECONDARY_ERROR_MESSAGES[type] || "adsad";
|
||||
}
|
||||
|
||||
static MAX_RETRY = "MAX_RETRY";
|
||||
static USER_NOT_FOUND = "USER_NOT_FOUND";
|
||||
}
|
||||
|
||||
export function getLevel(xp: number): number {
|
||||
return Math.trunc(Math.floor(CONSTANTS.LEVEL_FACTOR * Math.sqrt(xp)))
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the progress (0-99)% til next level
|
||||
* @param xp Xp number
|
||||
*/
|
||||
export function getProgress(xp: number): number {
|
||||
const currentLvl = getLevel(xp)
|
||||
return Math.trunc((CONSTANTS.LEVEL_FACTOR * Math.sqrt(xp) - currentLvl) * 100)
|
||||
}
|
24
src/components/Error.tsx
Normal file
24
src/components/Error.tsx
Normal file
@ -0,0 +1,24 @@
|
||||
import React from 'react'
|
||||
import { encodeHTML } from '../common/utils'
|
||||
|
||||
export default class Error extends React.Component<{
|
||||
message: string
|
||||
secondaryMessage?: string
|
||||
}> {
|
||||
|
||||
public render = () => (
|
||||
<svg width="495" height="120" viewBox="0 0 495 120" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<style>{`
|
||||
.text { font: 600 16px 'Segoe UI', Ubuntu, Sans-Serif; fill: #2F80ED }
|
||||
.small { font: 600 12px 'Segoe UI', Ubuntu, Sans-Serif; fill: #252525 }
|
||||
.gray { fill: #858585 }
|
||||
`}</style>
|
||||
<rect x="0.5" y="0.5" width="494" height="99%" rx="4.5" fill="#FFFEFE" stroke="#E4E2E2"/>
|
||||
<text x="25" y="45" className="text">Something went wrong! file an issue at https://dze.io/3nL29</text>
|
||||
<text data-testid="message" x="25" y="55" className="text small">
|
||||
<tspan x="25" dy="18">{encodeHTML(this.props.message)}</tspan>
|
||||
<tspan x="25" dy="18" className="gray">{this.props.secondaryMessage}</tspan>
|
||||
</text>
|
||||
</svg>
|
||||
)
|
||||
}
|
22
src/components/FlexLayout.tsx
Normal file
22
src/components/FlexLayout.tsx
Normal file
@ -0,0 +1,22 @@
|
||||
import React from 'react'
|
||||
|
||||
export default class FlexLayout extends React.Component<{
|
||||
items: Array<JSX.Element | string | undefined>
|
||||
gap: number
|
||||
direction?: 'column'
|
||||
}> {
|
||||
public render() {
|
||||
return this.props.items.filter(Boolean).map((item, index) => (
|
||||
<g key={index} transform={this.getGap(index)}>{item}</g>
|
||||
))
|
||||
}
|
||||
|
||||
private getGap(index: number) {
|
||||
const gap = this.props.gap * index
|
||||
let transform = `translate(${gap}, 0)`
|
||||
if (this.props.direction === 'column') {
|
||||
transform = `translate(0, ${gap})`
|
||||
}
|
||||
return transform
|
||||
}
|
||||
}
|
@ -1,70 +1,115 @@
|
||||
import { request, logger, CONSTANTS, getLevel, CustomError } from '../common/utils'
|
||||
import { request, CONSTANTS, getLevel, profileGraphRequest, CustomError, formatDateNumber, formatDate, getColorOfLanguage } from '../common/utils'
|
||||
import retryer from '../common/retryer'
|
||||
import languageColor from '../../themes/language-bar.json'
|
||||
|
||||
export interface data {
|
||||
name: string
|
||||
size: number
|
||||
color: string
|
||||
recentSize: number
|
||||
}
|
||||
import { CodeStatsHistoryGraph, TopLanguages } from '../interfaces'
|
||||
|
||||
export async function fetchProfile(username: string) {
|
||||
if (!username) throw Error('Invalid Username')
|
||||
|
||||
const response = await retryer(request, {login: username})
|
||||
const response = await retryer(request, username)
|
||||
|
||||
return {
|
||||
username,
|
||||
xp: response.data.total_xp,
|
||||
recentXp: response.data.new_xp,
|
||||
level: getLevel(response.data.total_xp + response.data.new_xp)
|
||||
xp: response.total_xp,
|
||||
recentXp: response.new_xp,
|
||||
level: getLevel(response.total_xp)
|
||||
}
|
||||
}
|
||||
|
||||
export async function fetchTopLanguages(username: string) {
|
||||
if (!username) throw Error("Invalid username");
|
||||
export async function fetchHistory(username: string, days: number) {
|
||||
if (!username) throw Error('Invalid Username')
|
||||
|
||||
let res = await retryer(request, { login: username });
|
||||
const date = new Date()
|
||||
date.setDate(date.getDate() - (days - 1))
|
||||
|
||||
let repoNodes = res.data.languages;
|
||||
const body = `{
|
||||
profile(username: "${username}") {
|
||||
day_language_xps: dayLanguageXps(since: "${formatDate(date)}") {date language xp}
|
||||
}
|
||||
}`
|
||||
|
||||
// Remap nodes
|
||||
const list = []
|
||||
for (const key in repoNodes) {
|
||||
const item = repoNodes[key]
|
||||
list.push({
|
||||
name: key,
|
||||
color: key in languageColor ? languageColor[key as keyof typeof languageColor].color || '#000000' : '#000000',
|
||||
xp: item.xps,
|
||||
recentXp: item.new_xps + item.xps,
|
||||
lvl: Math.trunc(Math.floor(CONSTANTS.LEVEL_FACTOR * Math.sqrt(item.xps)))
|
||||
})
|
||||
const response = await retryer<Promise<CodeStatsHistoryGraph>>(profileGraphRequest, body)
|
||||
if (response.errors) {
|
||||
throw new CustomError(response.errors[0].message, 'MAX_RETRY')
|
||||
}
|
||||
|
||||
repoNodes = list
|
||||
.filter((node) => {
|
||||
return node.xp > 0;
|
||||
const result: Record<string /* Date */, Array<{
|
||||
xp: number
|
||||
language: string
|
||||
}>> = {}
|
||||
|
||||
const languagesData: Record<string, number> = {}
|
||||
|
||||
for (const data of response.data.profile.day_language_xps) {
|
||||
let day = result[data.date]
|
||||
if (!day) {
|
||||
day = []
|
||||
}
|
||||
day.push({
|
||||
xp: data.xp,
|
||||
language: data.language
|
||||
})
|
||||
.sort((a, b) => b.xp - a.xp)
|
||||
.reduce((acc, prev) => {
|
||||
if (data.language in languagesData) {
|
||||
languagesData[data.language] += data.xp
|
||||
} else {
|
||||
languagesData[data.language] = data.xp
|
||||
}
|
||||
|
||||
result[data.date] = day
|
||||
}
|
||||
|
||||
for (const key of Object.keys(result)) {
|
||||
const item = result[key]
|
||||
result[key] = item.sort((a, b) => languagesData[b.language] - languagesData[a.language])
|
||||
}
|
||||
|
||||
const keys = Object.keys(result)
|
||||
|
||||
for (const day of keys) {
|
||||
if (keys.indexOf(day) === 0 && day === formatDate(date)) {
|
||||
continue
|
||||
}
|
||||
const date2 = new Date(day)
|
||||
date2.setDate(date2.getDate() - 1)
|
||||
const oldDate = formatDate(date2)
|
||||
if (!(oldDate in result)) {
|
||||
result[oldDate] = []
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return Object.keys(result).map((el) => {
|
||||
return {
|
||||
...acc,
|
||||
[prev.name]: {
|
||||
name: prev.name,
|
||||
color: prev.color,
|
||||
size: prev.xp,
|
||||
recentSize: prev.recentXp
|
||||
},
|
||||
};
|
||||
}, {});
|
||||
data: result[el],
|
||||
day: el,
|
||||
total: result[el].reduce((prvs, crnt) => prvs + crnt.xp, 0)
|
||||
}
|
||||
}).sort((a, b) => a.day < b.day ? 1 : -1)
|
||||
|
||||
const topLangs = Object.keys(repoNodes)
|
||||
// .slice(0, 5)
|
||||
.reduce((result: Record<string, any>, key) => {
|
||||
result[key] = repoNodes[key];
|
||||
return result;
|
||||
}, {});
|
||||
|
||||
return topLangs as Record<string, data>
|
||||
}
|
||||
|
||||
export async function fetchTopLanguages(username: string): Promise<TopLanguages> {
|
||||
if (!username) throw Error("Invalid username")
|
||||
|
||||
let res = await retryer(request, username)
|
||||
|
||||
const langs = res.languages
|
||||
|
||||
const resp = Object.keys(langs)
|
||||
.map((key) => {
|
||||
const item = langs[key]
|
||||
return {
|
||||
xp: item.xps,
|
||||
recentXp: item.new_xps,
|
||||
color: getColorOfLanguage(key),
|
||||
name: key,
|
||||
level: getLevel(item.xps)
|
||||
}
|
||||
})
|
||||
.sort((a, b) => (b.xp + b.recentXp) - (a.xp + a.recentXp))
|
||||
|
||||
return {
|
||||
username,
|
||||
langs: resp
|
||||
}
|
||||
}
|
||||
|
15
src/fetcher/interface.d.ts
vendored
15
src/fetcher/interface.d.ts
vendored
@ -1,15 +0,0 @@
|
||||
export interface CodeStatsResponse {
|
||||
user: string
|
||||
error?: string
|
||||
total_xp: number
|
||||
new_xp: number
|
||||
machines: Record<string, {
|
||||
xps: number
|
||||
new_xps: number
|
||||
}>
|
||||
languages: Record<string, {
|
||||
xps: number
|
||||
new_xps: number
|
||||
}>
|
||||
dates: Record<string, number>
|
||||
}
|
@ -1,92 +0,0 @@
|
||||
const calculateCircleProgress = (value: number) => {
|
||||
let radius = 40;
|
||||
let c = Math.PI * (radius * 2);
|
||||
|
||||
if (value < 0) value = 0;
|
||||
if (value > 100) value = 100;
|
||||
|
||||
let percentage = ((100 - value) / 100) * c;
|
||||
return percentage;
|
||||
};
|
||||
|
||||
const getProgressAnimation = ({ progress }: {progress: number}) => {
|
||||
return `
|
||||
@keyframes rankAnimation {
|
||||
from {
|
||||
stroke-dashoffset: ${calculateCircleProgress(0)};
|
||||
}
|
||||
to {
|
||||
stroke-dashoffset: ${calculateCircleProgress(progress)};
|
||||
}
|
||||
}
|
||||
`;
|
||||
};
|
||||
|
||||
export const getAnimations = () => {
|
||||
return `
|
||||
/* Animations */
|
||||
@keyframes scaleInAnimation {
|
||||
from {
|
||||
transform: translate(-5px, 5px) scale(0);
|
||||
}
|
||||
to {
|
||||
transform: translate(-5px, 5px) scale(1);
|
||||
}
|
||||
}
|
||||
@keyframes fadeInAnimation {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
`;
|
||||
};
|
||||
|
||||
export const getStyles = ({
|
||||
titleColor,
|
||||
textColor,
|
||||
iconColor,
|
||||
show_icons,
|
||||
progress,
|
||||
}: any) => {
|
||||
return `
|
||||
.stat {
|
||||
font: 600 14px 'Segoe UI', Ubuntu, "Helvetica Neue", Sans-Serif; fill: ${textColor};
|
||||
}
|
||||
.stagger {
|
||||
opacity: 0;
|
||||
animation: fadeInAnimation 0.3s ease-in-out forwards;
|
||||
}
|
||||
.rank-text {
|
||||
font: 800 24px 'Segoe UI', Ubuntu, Sans-Serif; fill: ${textColor};
|
||||
animation: scaleInAnimation 0.3s ease-in-out forwards;
|
||||
}
|
||||
|
||||
.bold { font-weight: 700 }
|
||||
.icon {
|
||||
fill: ${iconColor};
|
||||
display: ${!!show_icons ? "block" : "none"};
|
||||
}
|
||||
|
||||
.rank-circle-rim {
|
||||
stroke: ${titleColor};
|
||||
fill: none;
|
||||
stroke-width: 6;
|
||||
opacity: 0.2;
|
||||
}
|
||||
.rank-circle {
|
||||
stroke: ${titleColor};
|
||||
stroke-dasharray: 250;
|
||||
fill: none;
|
||||
stroke-width: 6;
|
||||
stroke-linecap: round;
|
||||
opacity: 0.8;
|
||||
transform-origin: -10px 8px;
|
||||
transform: rotate(-90deg);
|
||||
animation: rankAnimation 1s forwards ease-in-out;
|
||||
}
|
||||
${process.env.NODE_ENV === "test" ? "" : getProgressAnimation({ progress })}
|
||||
`;
|
||||
};
|
50
src/interfaces.d.ts
vendored
Normal file
50
src/interfaces.d.ts
vendored
Normal file
@ -0,0 +1,50 @@
|
||||
export interface CodeStatsResponse {
|
||||
user: string
|
||||
error?: string
|
||||
total_xp: number
|
||||
new_xp: number
|
||||
machines: Record<string, {
|
||||
xps: number
|
||||
new_xps: number
|
||||
}>
|
||||
languages: Record<string, {
|
||||
xps: number
|
||||
new_xps: number
|
||||
}>
|
||||
dates: Record<string, number>
|
||||
}
|
||||
|
||||
export interface CodeStatsHistoryGraph {
|
||||
data: {
|
||||
profile: {
|
||||
day_language_xps: Array<{
|
||||
xp: number,
|
||||
language: string
|
||||
date: string
|
||||
}>
|
||||
}
|
||||
}
|
||||
errors?: Array<{
|
||||
message: string
|
||||
}>
|
||||
}
|
||||
|
||||
export interface Profile {
|
||||
username: string
|
||||
xp: number
|
||||
recentXp: number
|
||||
level: number
|
||||
}
|
||||
|
||||
export interface TopLanguages {
|
||||
username: string
|
||||
langs: Array<TopLanguage>
|
||||
}
|
||||
|
||||
export interface TopLanguage {
|
||||
xp: number
|
||||
recentXp: number
|
||||
color: string
|
||||
name: string
|
||||
level: number
|
||||
}
|
226
themes/index.ts
226
themes/index.ts
@ -1,226 +0,0 @@
|
||||
const themes = {
|
||||
default: {
|
||||
title_color: "2f80ed",
|
||||
icon_color: "4c71f2",
|
||||
text_color: "333",
|
||||
bg_color: "fffefe",
|
||||
},
|
||||
default_repocard: {
|
||||
title_color: "2f80ed",
|
||||
icon_color: "586069", // icon color is different
|
||||
text_color: "333",
|
||||
bg_color: "fffefe",
|
||||
},
|
||||
dark: {
|
||||
title_color: "fff",
|
||||
icon_color: "79ff97",
|
||||
text_color: "9f9f9f",
|
||||
bg_color: "151515",
|
||||
},
|
||||
radical: {
|
||||
title_color: "fe428e",
|
||||
icon_color: "f8d847",
|
||||
text_color: "a9fef7",
|
||||
bg_color: "141321",
|
||||
},
|
||||
merko: {
|
||||
title_color: "abd200",
|
||||
icon_color: "b7d364",
|
||||
text_color: "68b587",
|
||||
bg_color: "0a0f0b",
|
||||
},
|
||||
gruvbox: {
|
||||
title_color: "fabd2f",
|
||||
icon_color: "fe8019",
|
||||
text_color: "8ec07c",
|
||||
bg_color: "282828",
|
||||
},
|
||||
tokyonight: {
|
||||
title_color: "70a5fd",
|
||||
icon_color: "bf91f3",
|
||||
text_color: "38bdae",
|
||||
bg_color: "1a1b27",
|
||||
},
|
||||
onedark: {
|
||||
title_color: "e4bf7a",
|
||||
icon_color: "8eb573",
|
||||
text_color: "df6d74",
|
||||
bg_color: "282c34",
|
||||
},
|
||||
cobalt: {
|
||||
title_color: "e683d9",
|
||||
icon_color: "0480ef",
|
||||
text_color: "75eeb2",
|
||||
bg_color: "193549",
|
||||
},
|
||||
synthwave: {
|
||||
title_color: "e2e9ec",
|
||||
icon_color: "ef8539",
|
||||
text_color: "e5289e",
|
||||
bg_color: "2b213a",
|
||||
},
|
||||
highcontrast: {
|
||||
title_color: "e7f216",
|
||||
icon_color: "00ffff",
|
||||
text_color: "fff",
|
||||
bg_color: "000",
|
||||
},
|
||||
dracula: {
|
||||
title_color: "ff6e96",
|
||||
icon_color: "79dafa",
|
||||
text_color: "f8f8f2",
|
||||
bg_color: "282a36",
|
||||
},
|
||||
prussian: {
|
||||
title_color: "bddfff",
|
||||
icon_color: "38a0ff",
|
||||
text_color: "6e93b5",
|
||||
bg_color: "172f45",
|
||||
},
|
||||
monokai: {
|
||||
title_color: "eb1f6a",
|
||||
icon_color: "e28905",
|
||||
text_color: "f1f1eb",
|
||||
bg_color: "272822",
|
||||
},
|
||||
vue: {
|
||||
title_color: "41b883",
|
||||
icon_color: "41b883",
|
||||
text_color: "273849",
|
||||
bg_color: "fffefe",
|
||||
},
|
||||
'vue-dark': {
|
||||
title_color: "41b883",
|
||||
icon_color: "41b883",
|
||||
text_color: "fffefe",
|
||||
bg_color: "273849",
|
||||
},
|
||||
"shades-of-purple": {
|
||||
title_color: "fad000",
|
||||
icon_color: "b362ff",
|
||||
text_color: "a599e9",
|
||||
bg_color: "2d2b55",
|
||||
},
|
||||
nightowl: {
|
||||
title_color: "c792ea",
|
||||
icon_color: "ffeb95",
|
||||
text_color: "7fdbca",
|
||||
bg_color: "011627",
|
||||
},
|
||||
buefy: {
|
||||
title_color: "7957d5",
|
||||
icon_color: "ff3860",
|
||||
text_color: "363636",
|
||||
bg_color: "ffffff",
|
||||
},
|
||||
"blue-green": {
|
||||
title_color: "2f97c1",
|
||||
icon_color: "f5b700",
|
||||
text_color: "0cf574",
|
||||
bg_color: "040f0f",
|
||||
},
|
||||
algolia: {
|
||||
title_color: "00AEFF",
|
||||
icon_color: "2DDE98",
|
||||
text_color: "FFFFFF",
|
||||
bg_color: "050F2C",
|
||||
},
|
||||
"great-gatsby": {
|
||||
title_color: "ffa726",
|
||||
icon_color: "ffb74d",
|
||||
text_color: "ffd95b",
|
||||
bg_color: "000000",
|
||||
},
|
||||
darcula: {
|
||||
title_color: "BA5F17",
|
||||
icon_color: "84628F",
|
||||
text_color: "BEBEBE",
|
||||
bg_color: "242424",
|
||||
},
|
||||
bear: {
|
||||
title_color: "e03c8a",
|
||||
icon_color: "00AEFF",
|
||||
text_color: "bcb28d",
|
||||
bg_color: "1f2023",
|
||||
},
|
||||
"solarized-dark": {
|
||||
title_color: "268bd2",
|
||||
icon_color: "b58900",
|
||||
text_color: "859900",
|
||||
bg_color: "002b36",
|
||||
},
|
||||
"solarized-light": {
|
||||
title_color: "268bd2",
|
||||
icon_color: "b58900",
|
||||
text_color: "859900",
|
||||
bg_color: "fdf6e3",
|
||||
},
|
||||
"chartreuse-dark": {
|
||||
title_color: "7fff00",
|
||||
icon_color: "00AEFF",
|
||||
text_color: "fff",
|
||||
bg_color: "000",
|
||||
},
|
||||
"nord": {
|
||||
title_color: "81a1c1",
|
||||
text_color: "d8dee9",
|
||||
icon_color: "88c0d0",
|
||||
bg_color: "2e3440",
|
||||
},
|
||||
"gotham": {
|
||||
title_color: "2aa889",
|
||||
icon_color: "599cab",
|
||||
text_color: "99d1ce",
|
||||
bg_color: "0c1014",
|
||||
},
|
||||
"material-palenight": {
|
||||
title_color: "c792ea",
|
||||
icon_color: "89ddff",
|
||||
text_color: "a6accd",
|
||||
bg_color: "292d3e",
|
||||
},
|
||||
"graywhite": {
|
||||
title_color: "24292e",
|
||||
icon_color: "24292e",
|
||||
text_color: "24292e",
|
||||
bg_color: "ffffff",
|
||||
},
|
||||
"vision-friendly-dark": {
|
||||
title_color: "ffb000",
|
||||
icon_color: "785ef0",
|
||||
text_color: "ffffff",
|
||||
bg_color: "000000",
|
||||
},
|
||||
"ayu-mirage": {
|
||||
title_color: "f4cd7c",
|
||||
icon_color: "73d0ff",
|
||||
text_color: "c7c8c2",
|
||||
bg_color: "1f2430",
|
||||
},
|
||||
"midnight-purple":{
|
||||
title_color: "9745f5",
|
||||
icon_color: "9f4bff",
|
||||
text_color: "ffffff",
|
||||
bg_color: "000000",
|
||||
},
|
||||
calm: {
|
||||
title_color: "e07a5f",
|
||||
icon_color: "edae49",
|
||||
text_color: "ebcfb2",
|
||||
bg_color: "373f51",
|
||||
},
|
||||
omni: {
|
||||
title_color: "FF79C6",
|
||||
icon_color: "e7de79",
|
||||
text_color: "E1E1E6",
|
||||
bg_color: "191622"
|
||||
},
|
||||
react: {
|
||||
title_color: "61dafb",
|
||||
icon_color: "61dafb",
|
||||
text_color: "ffffff",
|
||||
bg_color: "20232a",
|
||||
},
|
||||
};
|
||||
|
||||
export default themes
|
@ -1071,6 +1071,9 @@
|
||||
"color": null,
|
||||
"url": "https://github.com/trending?l=OpenSCAD"
|
||||
},
|
||||
"Other": {
|
||||
"color": "#b276b2"
|
||||
},
|
||||
"Ox": {
|
||||
"color": null,
|
||||
"url": "https://github.com/trending?l=Ox"
|
||||
|
218
themes/themes.json
Normal file
218
themes/themes.json
Normal file
@ -0,0 +1,218 @@
|
||||
{
|
||||
"default": {
|
||||
"title_color": "2f80ed",
|
||||
"icon_color": "4c71f2",
|
||||
"text_color": "333",
|
||||
"bg_color": "fffefe"
|
||||
},
|
||||
"dark": {
|
||||
"title_color": "fff",
|
||||
"icon_color": "79ff97",
|
||||
"text_color": "9f9f9f",
|
||||
"bg_color": "151515"
|
||||
},
|
||||
"radical": {
|
||||
"title_color": "fe428e",
|
||||
"icon_color": "f8d847",
|
||||
"text_color": "a9fef7",
|
||||
"bg_color": "141321"
|
||||
},
|
||||
"merko": {
|
||||
"title_color": "abd200",
|
||||
"icon_color": "b7d364",
|
||||
"text_color": "68b587",
|
||||
"bg_color": "0a0f0b"
|
||||
},
|
||||
"gruvbox": {
|
||||
"title_color": "fabd2f",
|
||||
"icon_color": "fe8019",
|
||||
"text_color": "8ec07c",
|
||||
"bg_color": "282828"
|
||||
},
|
||||
"tokyonight": {
|
||||
"title_color": "70a5fd",
|
||||
"icon_color": "bf91f3",
|
||||
"text_color": "38bdae",
|
||||
"bg_color": "1a1b27"
|
||||
},
|
||||
"onedark": {
|
||||
"title_color": "e4bf7a",
|
||||
"icon_color": "8eb573",
|
||||
"text_color": "df6d74",
|
||||
"bg_color": "282c34"
|
||||
},
|
||||
"cobalt": {
|
||||
"title_color": "e683d9",
|
||||
"icon_color": "0480ef",
|
||||
"text_color": "75eeb2",
|
||||
"bg_color": "193549"
|
||||
},
|
||||
"synthwave": {
|
||||
"title_color": "e2e9ec",
|
||||
"icon_color": "ef8539",
|
||||
"text_color": "e5289e",
|
||||
"bg_color": "2b213a"
|
||||
},
|
||||
"highcontrast": {
|
||||
"title_color": "e7f216",
|
||||
"icon_color": "00ffff",
|
||||
"text_color": "fff",
|
||||
"bg_color": "000"
|
||||
},
|
||||
"dracula": {
|
||||
"title_color": "ff6e96",
|
||||
"icon_color": "79dafa",
|
||||
"text_color": "f8f8f2",
|
||||
"bg_color": "282a36"
|
||||
},
|
||||
"prussian": {
|
||||
"title_color": "bddfff",
|
||||
"icon_color": "38a0ff",
|
||||
"text_color": "6e93b5",
|
||||
"bg_color": "172f45"
|
||||
},
|
||||
"monokai": {
|
||||
"title_color": "eb1f6a",
|
||||
"icon_color": "e28905",
|
||||
"text_color": "f1f1eb",
|
||||
"bg_color": "272822"
|
||||
},
|
||||
"vue": {
|
||||
"title_color": "41b883",
|
||||
"icon_color": "41b883",
|
||||
"text_color": "273849",
|
||||
"bg_color": "fffefe"
|
||||
},
|
||||
"vue-dark": {
|
||||
"title_color": "41b883",
|
||||
"icon_color": "41b883",
|
||||
"text_color": "fffefe",
|
||||
"bg_color": "273849"
|
||||
},
|
||||
"shades-of-purple": {
|
||||
"title_color": "fad000",
|
||||
"icon_color": "b362ff",
|
||||
"text_color": "a599e9",
|
||||
"bg_color": "2d2b55"
|
||||
},
|
||||
"nightowl": {
|
||||
"title_color": "c792ea",
|
||||
"icon_color": "ffeb95",
|
||||
"text_color": "7fdbca",
|
||||
"bg_color": "011627"
|
||||
},
|
||||
"buefy": {
|
||||
"title_color": "7957d5",
|
||||
"icon_color": "ff3860",
|
||||
"text_color": "363636",
|
||||
"bg_color": "ffffff"
|
||||
},
|
||||
"blue-green": {
|
||||
"title_color": "2f97c1",
|
||||
"icon_color": "f5b700",
|
||||
"text_color": "0cf574",
|
||||
"bg_color": "040f0f"
|
||||
},
|
||||
"algolia": {
|
||||
"title_color": "00AEFF",
|
||||
"icon_color": "2DDE98",
|
||||
"text_color": "FFFFFF",
|
||||
"bg_color": "050F2C"
|
||||
},
|
||||
"great-gatsby": {
|
||||
"title_color": "ffa726",
|
||||
"icon_color": "ffb74d",
|
||||
"text_color": "ffd95b",
|
||||
"bg_color": "000000"
|
||||
},
|
||||
"darcula": {
|
||||
"title_color": "BA5F17",
|
||||
"icon_color": "84628F",
|
||||
"text_color": "BEBEBE",
|
||||
"bg_color": "242424"
|
||||
},
|
||||
"bear": {
|
||||
"title_color": "e03c8a",
|
||||
"icon_color": "00AEFF",
|
||||
"text_color": "bcb28d",
|
||||
"bg_color": "1f2023"
|
||||
},
|
||||
"solarized-dark": {
|
||||
"title_color": "268bd2",
|
||||
"icon_color": "b58900",
|
||||
"text_color": "859900",
|
||||
"bg_color": "002b36"
|
||||
},
|
||||
"solarized-light": {
|
||||
"title_color": "268bd2",
|
||||
"icon_color": "b58900",
|
||||
"text_color": "859900",
|
||||
"bg_color": "fdf6e3"
|
||||
},
|
||||
"chartreuse-dark": {
|
||||
"title_color": "7fff00",
|
||||
"icon_color": "00AEFF",
|
||||
"text_color": "fff",
|
||||
"bg_color": "000"
|
||||
},
|
||||
"nord": {
|
||||
"title_color": "81a1c1",
|
||||
"text_color": "d8dee9",
|
||||
"icon_color": "88c0d0",
|
||||
"bg_color": "2e3440"
|
||||
},
|
||||
"gotham": {
|
||||
"title_color": "2aa889",
|
||||
"icon_color": "599cab",
|
||||
"text_color": "99d1ce",
|
||||
"bg_color": "0c1014"
|
||||
},
|
||||
"material-palenight": {
|
||||
"title_color": "c792ea",
|
||||
"icon_color": "89ddff",
|
||||
"text_color": "a6accd",
|
||||
"bg_color": "292d3e"
|
||||
},
|
||||
"graywhite": {
|
||||
"title_color": "24292e",
|
||||
"icon_color": "24292e",
|
||||
"text_color": "24292e",
|
||||
"bg_color": "ffffff"
|
||||
},
|
||||
"vision-friendly-dark": {
|
||||
"title_color": "ffb000",
|
||||
"icon_color": "785ef0",
|
||||
"text_color": "ffffff",
|
||||
"bg_color": "000000"
|
||||
},
|
||||
"ayu-mirage": {
|
||||
"title_color": "f4cd7c",
|
||||
"icon_color": "73d0ff",
|
||||
"text_color": "c7c8c2",
|
||||
"bg_color": "1f2430"
|
||||
},
|
||||
"midnight-purple":{
|
||||
"title_color": "9745f5",
|
||||
"icon_color": "9f4bff",
|
||||
"text_color": "ffffff",
|
||||
"bg_color": "000000"
|
||||
},
|
||||
"calm": {
|
||||
"title_color": "e07a5f",
|
||||
"icon_color": "edae49",
|
||||
"text_color": "ebcfb2",
|
||||
"bg_color": "373f51"
|
||||
},
|
||||
"omni": {
|
||||
"title_color": "FF79C6",
|
||||
"icon_color": "e7de79",
|
||||
"text_color": "E1E1E6",
|
||||
"bg_color": "191622"
|
||||
},
|
||||
"react": {
|
||||
"title_color": "61dafb",
|
||||
"icon_color": "61dafb",
|
||||
"text_color": "ffffff",
|
||||
"bg_color": "20232a"
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user