From d04550f2b0f4d6bd4c9464f841440369f6986f1d Mon Sep 17 00:00:00 2001 From: Diego Carrasco G <557703+dacog@users.noreply.github.com> Date: Sun, 23 Jun 2024 21:37:02 +0200 Subject: [PATCH 1/2] add a github_widget shortcode --- v8/github_widget/README.md | 110 ++++++++++++++++++++++++++ v8/github_widget/__init__.py | 0 v8/github_widget/conf.py.sample | 1 + v8/github_widget/github_widget.plugin | 14 ++++ v8/github_widget/github_widget.py | 81 +++++++++++++++++++ v8/github_widget/imgs/example-1.png | Bin 0 -> 80892 bytes v8/github_widget/imgs/example-2.png | Bin 0 -> 73193 bytes v8/github_widget/imgs/example-3.png | Bin 0 -> 108020 bytes v8/github_widget/requirements.txt | 1 + 9 files changed, 207 insertions(+) create mode 100644 v8/github_widget/README.md create mode 100644 v8/github_widget/__init__.py create mode 100644 v8/github_widget/conf.py.sample create mode 100644 v8/github_widget/github_widget.plugin create mode 100644 v8/github_widget/github_widget.py create mode 100644 v8/github_widget/imgs/example-1.png create mode 100644 v8/github_widget/imgs/example-2.png create mode 100644 v8/github_widget/imgs/example-3.png create mode 100644 v8/github_widget/requirements.txt diff --git a/v8/github_widget/README.md b/v8/github_widget/README.md new file mode 100644 index 00000000..e5c7b186 --- /dev/null +++ b/v8/github_widget/README.md @@ -0,0 +1,110 @@ +# GitHub Widget Plugin for Nikola + +This is a Nikola plugin that allows you to embed a GitHub repository widget in your Nikola-generated site. The widget displays repository details, including the description, languages, stars, forks, watchers, open issues, and latest activity (commits and releases). You can also customize the widget to show the repository owner's avatar or the default GitHub logo. + +## Installation + +```shell +nikola plugin -i github_widget +``` + +## Update conf.py (optional) + +Optionally you can add an access token to your config. This is optional. + +Without a token you can still use the shortcode, but you will get api rate limit errors if you use it too much. + +# Add your GitHub API token here + +The token should have repository -> Contents -> read-only permissions. + +```python +GITHUB_API_TOKEN = 'your_github_api_token_here' +``` + +## Use the shortcode + +here are some examples: + +```markdown +// Shortcode Example 1 +{{% github_widget %}}dacog/lazy-docker-compose-wordpress-setup{{% /github_widget %}} + +// Shortcode Example 2 +{{% github_widget avatar=true max_width=400px %}}dacog/lazy-docker-compose-wordpress-setup{{%/github_widget %}} + +// Shortcode Example 3 +{{% github_widget avatar=true latest_release=true latest_commit=true max_width=400px %}}dacog/textexpander_android{{%/github_widget %}} +``` + +Which gives these widgets: + +**Shortcode Example 1** + + + +**Shortcode Example 2** + + + +**Shortcode Example 3** + + + +## CSS + +Here is a sample CSS wich results in the examples above. + +```css +/* github shortcode */ +.github-widget { + display: flex; + align-items: center; + border: 1px solid #ddd; + padding: 10px; + margin: 10px 0; + border-radius: 5px; + background-color: #f9f9f9; +} + +.github-widget-image { + margin-right: 10px; +} + +.github-widget img { + border-radius: 50%; +} + +.github-widget .repo-info { + display: flex; + flex-direction: column; +} + +.github-widget .repo-info h3 { + margin: 0; + font-size: 1.2em; +} + +.github-widget .repo-info p { + margin: 5px 0; + font-size: 0.9em; + color: #555; +} + +.github-widget .repo-info ul { + list-style: none; + padding: 0; + display: flex; + gap: 10px; +} + +.github-widget .repo-info ul li { + font-size: 0.8em; + color: #333; +} + +.github-widget h4 { + color: black; +} +``` + diff --git a/v8/github_widget/__init__.py b/v8/github_widget/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/v8/github_widget/conf.py.sample b/v8/github_widget/conf.py.sample new file mode 100644 index 00000000..fef37bb3 --- /dev/null +++ b/v8/github_widget/conf.py.sample @@ -0,0 +1 @@ +GITHUB_API_TOKEN = 'your_github_api_token_here' \ No newline at end of file diff --git a/v8/github_widget/github_widget.plugin b/v8/github_widget/github_widget.plugin new file mode 100644 index 00000000..c8fb5887 --- /dev/null +++ b/v8/github_widget/github_widget.plugin @@ -0,0 +1,14 @@ +[Core] +Name = github_widget +Module = github_widget + +[Documentation] +Author = Diego Carrasco G. +Version = 0.1 +Website = https://plugins.getnikola.com/#github_widget +Description = A shortcode to embed GitHub repository widgets. + +[Nikola] +MinVersion = 8.0.0 # I haven't tested it with older versions +MaxVersion = 8.3.1 +PluginCategory = ShortCode \ No newline at end of file diff --git a/v8/github_widget/github_widget.py b/v8/github_widget/github_widget.py new file mode 100644 index 00000000..5fca977f --- /dev/null +++ b/v8/github_widget/github_widget.py @@ -0,0 +1,81 @@ +from nikola.plugin_categories import ShortcodePlugin +from nikola.utils import LOGGER +from github import Github +# Authentication is defined via github.Auth +from github import Auth +from github.GithubException import UnknownObjectException + + +def render_github_widget(repo_data, show_avatar, max_width): + image_url = repo_data.owner.avatar_url if show_avatar else "https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png" + + # Get the latest commit + latest_commit = repo_data.get_commits()[0] + + latest_activity_html = "" + + if latest_commit: + latest_activity_html += f"
Latest Commit: {latest_commit.commit.message} ({latest_commit.commit.author.date})
" + try: + # Get the latest release if exists, if not there will be a 404 error + latest_release = repo_data.get_latest_release() + + if latest_release: + latest_activity_html += f"Latest Release: {latest_release.title} - {latest_release.body} ({latest_release.created_at})
" + except UnknownObjectException: + pass + + widget_html = f""" + + """ + return widget_html + + +class GitHubWidgetPlugin(ShortcodePlugin): + name = "github_widget" + + def handler(self, **kwargs): + data = kwargs.get('data', '').strip().split() + repo = data[0] + show_avatar = kwargs.get('avatar', False) + max_width = kwargs.get('max_width', '100%') + latest_release = kwargs.get('latest_release', False) + latest_commit = kwargs.get('latest_commit', False) + + token = self.site.config.get('GITHUB_API_TOKEN') + + if token: + # using an access token + auth = Auth.Token(token) + g = Github(auth=auth) + else: + g = Github() # without token there will be api rate limits. + + repo_data = g.get_repo(repo) + + if repo_data: + return render_github_widget(repo_data, show_avatar, max_width), [] + else: + return f"Repository '{repo}' not found or an error occurred.
", [] diff --git a/v8/github_widget/imgs/example-1.png b/v8/github_widget/imgs/example-1.png new file mode 100644 index 0000000000000000000000000000000000000000..b86476974db09878f5b08abeafb7d7fff355fc54 GIT binary patch literal 80892 zcmeFZWn7e9xc04xg7nZJIUqKqF@EB7Ed$;_@sA3;#-qPgsJd`vZ
zeNA)jG>U2U otA_G$VzcL4LM#99^m1nD(4u^)f33-#9|+pgNn~M!QIkUiq7HlX8SsZNsLWpz@s&
z=L8L#rff^9xzy2CI2M%5-he%a3NhN8W1czI@!o%p^q&ocRo-M!6u<`!9_ynzT|xsQ
zF)F#>lTy!{)4Nllm@5pr*<}Y5q|t1~psSyuuoG-K*<0ei)O3-Re2-f@m#^Q8qWQX2
zQK(Q7Jf^>idh?`DPi98e{u4GZSbzi%ud)>~y2~VUyfmTr#6q;>LF)fQm=X8A;I~I!
zs@d-D06QpMc02T^g*fh~aninyJ86C%xz`T>j;WwRN^%R~S}qfwTtb$|qi2uUE<$VgOA8Gi)yC^9*7NAR$h
z0la5%p7%&AShlw{x0Uh>UJ@T&a{M`YWNJ*qI?;*o4}NZ0t@N%Y@u@LXrot3R6O$c)
z__Pb50#{SVy+4%>(=Ab$1>bCWtW@drE$rRMc=!^N2DG_f``jbOl2lC=GA;Ima=hb+
z=EJyC_E|`YiR71y6wSLHT#tTih#pr
bDalQTs5>!aRolUHy#rh+|icxq|s4tC|RH1SlHzBXy`4?q?EG|%vH6S~@K
zZS{;Vi9_=wefO7PWN!Juj1i`6oxEDP`dvn-6Rne6#5!Tl>-M^8>cjm^6$}slUvlyk
zXw0n(kXF7a$jYx*_|hRI5?t$G^k^CSKUytSnPz1FGv#}}Mj!+dezyC#2P+
z
@ClRN|=+4~Et+^OtjU7RZF
zOgjvPe23>!#bLi61@0XILw=HP9^o}BpMzH`=FB?$i5c3IcDK8%4Pn66R~zt9k0X2i
z1@bi2OC*wUU7PWhS+~l~&nT;Vmks
zjuwFHA9)r0w}d8kjRc61krVB(R=IVtr69jzkrNbs=Afik9j!)3zlW>Z0UN02n`&yQ
zh!GM-#?0xo1Gttg-_tk>kDYq`lN4Rn?h>L4!ZsWN6`7Ah2wj&)CJrk%*M-fulp68}
zll`@t@g&$$Rc=q$be}VX8*wzZOP0IsSxcwTmXEG#F*)F0x-?Xh{aTn9dIte~6KoB85;|bn4Vc^mNYG=+!go(%ksac|m}?)`bx{yn
z|6~$CsAakG!q_`E-P5|pcTaBV){1ZqQci)gcdMcAk*$!zMZ3w!q3ck)mh_REv3w~=
zU52@;glno@0|^~U6=~fO!LMgROxpzj=j%n<&Ph;L?Nhwr{Z)fJgnX0ZG&nQaN<;7I
zaR%TKijrK?-;|$Fw2;ZY9UDV>-5V1lN+kR;PL;brAYO54*X9Ya$g1n5V|8m`e}l^m
z6T4`_#J*;=qv%#itL>CoGB0$*YpxtSlY0HEXH!gJ_6IE*v-_ND@|^pEk5QvN7%xj?
zKmKdOXN4=HrkQz|y{Fv`n|Enj3Yn?AschmrSI;u!I$BG%%M2p8`En}BwIDOgr#NDf
z;bXpgNpPfey_+F&pQYpNm+`{F0%B=G&Is13PpnJn5099ue%rM+k1CdZ9yHEBK`K!r
zLp$04ge2X~TC>8;>^$~4N%iCm&0#*t@8zFsAXQ~S&Mf!OwW^#$Vh^^Gc7glAXY<*C
ziNTyAh<2a=_T{*NpHDp^-7DY+&P+DwMUa>{dk{qk7FP0UE3%O!2g!;6tC0xi1t09@
zDiAZ}*aZI53qqJnZ5QO%+t+Jep>^ALrZf;hW;SoG|Kw&oR-z@+w+Ve*YV>aI_q@gw
z5ge`a93&j-IFiQ+En*{$8Uq7H%m=)s;yiF-BzwZhZm-ub)1