feat: add GitHub repo card, admonitions (#77)

* Added remark-directive, unist-util-visit

* Add rehype custom components for Github, Admonitions

* pnpm

* Update pnpm-lock

* Corrected hastscript requierement

* Change ad- prefix so adblocks dont block content
This commit is contained in:
Fabrizio 2024-05-02 01:24:20 -03:00 committed by saicaca
parent 5e4ae01af6
commit e1dae88515
9 changed files with 6696 additions and 4724 deletions

View File

@ -8,6 +8,11 @@ import rehypeKatex from "rehype-katex"
import rehypeSlug from "rehype-slug" import rehypeSlug from "rehype-slug"
import remarkMath from "remark-math" import remarkMath from "remark-math"
import { remarkReadingTime } from "./src/plugins/remark-reading-time.mjs" import { remarkReadingTime } from "./src/plugins/remark-reading-time.mjs"
import { GithubCardComponent } from "./src/plugins/rehype-component-github-card.mjs"
import { AdmonitionComponent } from "./src/plugins/rehype-component-admonition.mjs"
import remarkDirective from "remark-directive" /* Handle directives */
import remarkDirectiveRehype from 'remark-directive-rehype' /* Pass directives to rehype */
import rehypeComponents from "rehype-components"; /* Render the custom directive content */
import svelte from "@astrojs/svelte" import svelte from "@astrojs/svelte"
import swup from '@swup/astro'; import swup from '@swup/astro';
import sitemap from '@astrojs/sitemap'; import sitemap from '@astrojs/sitemap';
@ -54,10 +59,20 @@ export default defineConfig({
sitemap(), sitemap(),
], ],
markdown: { markdown: {
remarkPlugins: [remarkMath, remarkReadingTime], remarkPlugins: [remarkMath, remarkReadingTime, remarkDirective, remarkDirectiveRehype],
rehypePlugins: [ rehypePlugins: [
rehypeKatex, rehypeKatex,
rehypeSlug, rehypeSlug,
[rehypeComponents, {
components: {
github: GithubCardComponent,
tip: (x, y) => AdmonitionComponent(x, y, "tip"),
note: (x, y) => AdmonitionComponent(x, y, "note"),
important: (x, y) => AdmonitionComponent(x, y, "important"),
caution: (x, y) => AdmonitionComponent(x, y, "caution"),
warning: (x, y) => AdmonitionComponent(x, y, "warning"),
},
}],
[ [
rehypeAutolinkHeadings, rehypeAutolinkHeadings,
{ {

View File

@ -25,20 +25,25 @@
"astro-compress": "^2.2.15", "astro-compress": "^2.2.15",
"astro-icon": "1.1.0", "astro-icon": "1.1.0",
"colorjs.io": "^0.5.0", "colorjs.io": "^0.5.0",
"hastscript": "^9.0.0",
"markdown-it": "^14.1.0", "markdown-it": "^14.1.0",
"mdast-util-to-string": "^4.0.0", "mdast-util-to-string": "^4.0.0",
"overlayscrollbars": "^2.6.1", "overlayscrollbars": "^2.6.1",
"pagefind": "^1.0.4", "pagefind": "^1.0.4",
"reading-time": "^1.5.0", "reading-time": "^1.5.0",
"rehype-autolink-headings": "^7.1.0", "rehype-autolink-headings": "^7.1.0",
"rehype-components": "^0.3.0",
"rehype-katex": "^7.0.0", "rehype-katex": "^7.0.0",
"rehype-slug": "^6.0.0", "rehype-slug": "^6.0.0",
"remark-directive": "^3.0.0",
"remark-directive-rehype": "^0.4.2",
"remark-math": "^6.0.0", "remark-math": "^6.0.0",
"sanitize-html": "^2.13.0", "sanitize-html": "^2.13.0",
"sharp": "^0.33.2", "sharp": "^0.33.3",
"svelte": "^4.2.12", "svelte": "^4.2.12",
"tailwindcss": "^3.4.1", "tailwindcss": "^3.4.1",
"typescript": "^5.4.2" "typescript": "^5.4.2",
"unist-util-visit": "^5.0.0"
}, },
"devDependencies": { "devDependencies": {
"@astrojs/ts-plugin": "^1.6.0", "@astrojs/ts-plugin": "^1.6.0",
@ -51,7 +56,8 @@
"@rollup/plugin-yaml": "^4.1.2", "@rollup/plugin-yaml": "^4.1.2",
"@tailwindcss/typography": "^0.5.10", "@tailwindcss/typography": "^0.5.10",
"@types/markdown-it": "^14.0.0", "@types/markdown-it": "^14.0.0",
"@types/mdast": "^4.0.3",
"@types/sanitize-html": "^2.11.0", "@types/sanitize-html": "^2.11.0",
"stylus": "^0.63.0" "stylus": "^0.63.0"
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -114,6 +114,12 @@ color_set({
--display-light-icon: 1 0 --display-light-icon: 1 0
--display-dark-icon: 0 1 --display-dark-icon: 0 1
--admonitions-color-tip: mix(#90d73e, hsl(0 1 20), 92%) #90d73e
--admonitions-color-note: mix(#13c6dd, hsl(0 1 20), 92%) #13c6dd
--admonitions-color-important: mix(#bf4ef0, hsl(0 1 20), 92%) #bf4ef0
--admonitions-color-warning: mix(#e3ab29, hsl(0 1 20), 92%) #e3ab29
--admonitions-color-caution: mix(#df3b38, hsl(0 1 20), 92%) #df3b38
}) })

View File

@ -30,7 +30,7 @@ const className = Astro.props.class;
&:hover &:hover
.anchor .anchor
opacity: 1 opacity: 1
a a:not(.no-styling)
position: relative position: relative
background: none background: none
margin: -0.25rem margin: -0.25rem
@ -125,6 +125,64 @@ const className = Astro.props.class;
content: none content: none
&:after &:after
content: none content: none
blockquote.admonition
.bdm-title
display: block
margin-bottom: -.9rem
font-weight: bold
&:before
content: ' '
display: inline-block
font-size: inherit
overflow: visible
margin-right: .6rem
height: 1em
width: 1em
vertical-align: -.126em
mask-size: contain
mask-position: center
mask-repeat: no-repeat
&.bdm-tip
.bdm-title
color: var(--admonitions-color-tip)
&:before
background: var(--admonitions-color-tip)
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' version='1.1' width='16' height='16' aria-hidden='true'%3E%3Cpath d='M8 1.5c-2.363 0-4 1.69-4 3.75 0 .984.424 1.625.984 2.304l.214.253c.223.264.47.556.673.848.284.411.537.896.621 1.49a.75.75 0 0 1-1.484.211c-.04-.282-.163-.547-.37-.847a8.456 8.456 0 0 0-.542-.68c-.084-.1-.173-.205-.268-.32C3.201 7.75 2.5 6.766 2.5 5.25 2.5 2.31 4.863 0 8 0s5.5 2.31 5.5 5.25c0 1.516-.701 2.5-1.328 3.259-.095.115-.184.22-.268.319-.207.245-.383.453-.541.681-.208.3-.33.565-.37.847a.751.751 0 0 1-1.485-.212c.084-.593.337-1.078.621-1.489.203-.292.45-.584.673-.848.075-.088.147-.173.213-.253.561-.679.985-1.32.985-2.304 0-2.06-1.637-3.75-4-3.75ZM5.75 12h4.5a.75.75 0 0 1 0 1.5h-4.5a.75.75 0 0 1 0-1.5ZM6 15.25a.75.75 0 0 1 .75-.75h2.5a.75.75 0 0 1 0 1.5h-2.5a.75.75 0 0 1-.75-.75Z'%3E%3C/path%3E%3C/svg%3E")
&:before
background: var(--admonitions-color-tip)
&.bdm-note
.bdm-title
color: var(--admonitions-color-note)
&:before
background: var(--admonitions-color-note)
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' version='1.1' width='16' height='16' aria-hidden='true'%3E%3Cpath fill='var(--admonitions-color-tip)' d='M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8Zm8-6.5a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13ZM6.5 7.75A.75.75 0 0 1 7.25 7h1a.75.75 0 0 1 .75.75v2.75h.25a.75.75 0 0 1 0 1.5h-2a.75.75 0 0 1 0-1.5h.25v-2h-.25a.75.75 0 0 1-.75-.75ZM8 6a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z'%3E%3C/path%3E%3C/svg%3E")
&:before
background: var(--admonitions-color-note)
&.bdm-important
.bdm-title
color: var(--admonitions-color-important)
&:before
background: var(--admonitions-color-important)
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' version='1.1' width='16' height='16' aria-hidden='true'%3E%3Cpath d='M0 1.75C0 .784.784 0 1.75 0h12.5C15.216 0 16 .784 16 1.75v9.5A1.75 1.75 0 0 1 14.25 13H8.06l-2.573 2.573A1.458 1.458 0 0 1 3 14.543V13H1.75A1.75 1.75 0 0 1 0 11.25Zm1.75-.25a.25.25 0 0 0-.25.25v9.5c0 .138.112.25.25.25h2a.75.75 0 0 1 .75.75v2.19l2.72-2.72a.749.749 0 0 1 .53-.22h6.5a.25.25 0 0 0 .25-.25v-9.5a.25.25 0 0 0-.25-.25Zm7 2.25v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 9a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z'%3E%3C/path%3E%3C/svg%3E")
&:before
background: var(--admonitions-color-important)
&.bdm-warning
.bdm-title
color: var(--admonitions-color-warning)
&:before
background: var(--admonitions-color-warning)
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' version='1.1' width='16' height='16' aria-hidden='true'%3E%3Cpath d='M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z'%3E%3C/path%3E%3C/svg%3E")
&:before
background: var(--admonitions-color-warning)
&.bdm-caution
.bdm-title
color: var(--admonitions-color-caution)
&:before
background: var(--admonitions-color-caution)
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' version='1.1' width='16' height='16' aria-hidden='true'%3E%3Cpath d='M4.47.22A.749.749 0 0 1 5 0h6c.199 0 .389.079.53.22l4.25 4.25c.141.14.22.331.22.53v6a.749.749 0 0 1-.22.53l-4.25 4.25A.749.749 0 0 1 11 16H5a.749.749 0 0 1-.53-.22L.22 11.53A.749.749 0 0 1 0 11V5c0-.199.079-.389.22-.53Zm.84 1.28L1.5 5.31v5.38l3.81 3.81h5.38l3.81-3.81V5.31L10.69 1.5ZM8 4a.75.75 0 0 1 .75.75v3.5a.75.75 0 0 1-1.5 0v-3.5A.75.75 0 0 1 8 4Zm0 8a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z'%3E%3C/path%3E%3C/svg%3E")
&:before
background: var(--admonitions-color-caution)
img img
border-radius: 0.75rem border-radius: 0.75rem
hr hr
@ -135,6 +193,147 @@ const className = Astro.props.class;
margin-left: auto margin-left: auto
margin-right: auto margin-right: auto
max-width: 100% max-width: 100%
a.card-github
display: block
position: relative
margin: 0.5rem 0
padding: 1.1rem 1.5rem 0.9rem 1.5rem
color: var(--tw-prose-body)
border-radius: var(--radius-large)
text-decoration-thickness: 0px
text-decoration-line: none
box-shadow: #00000020 0px 3px 12px
transition-property: color, background-color, opacity
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1)
transition-duration: 0.15s
&:hover
background-color: var(--btn-regular-bg-hover)
.gc-titlebar
color: var(--btn-content)
gap: 0.1rem
.gc-owner
background-color: transparent
padding: 0.1rem 0rem 0rem 0rem
gap: 0
.gc-avatar
width: 0
.gc-stars, .gc-forks, .gc-license, .gc-description
color: var(--tw-prose-headings)
&:before
background-color: var(--tw-prose-headings)
&:active
scale: .99
background-color: var(--btn-regular-bg-active);
.gc-titlebar
display: flex
flex-flow: row nowrap
gap: 0.5rem
align-items: center
margin-bottom: 0.5rem
color: var(--tw-prose-headings)
font-size: 1.25rem
font-weight: 500
transition-property: gap, padding, width;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1)
transition-duration: 0.15s
.gc-divider, .gc-repo
padding: 0.1rem 0rem 0rem 0rem
.gc-owner
position: relative
display: flex
flex-flow: row nowrap
gap: 0.5rem
align-items: center
padding: 0.1rem 0.6rem 0rem 0.6rem
color: var(--btn-content)
background-color: var(--btn-regular-bg)
border-radius: 0.5rem
transition-property: color, background, background-color, opacity, gap, padding, width;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1)
transition-duration: 0.15s
.gc-avatar
display: block
overflow: hidden
width: 1.4rem
height: 1.4rem
margin-top: -0.1rem
background-color: var(--primary)
background-size: cover
border-radius: 50%
transition-property: color, background-color, opacity, gap, padding, width;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1)
transition-duration: 0.15s
.gc-description
margin-bottom: 0.7rem
font-size: 0.96em
font-weight: 400
line-height: 1.4em
color: var(--tw-prose-body)
.gc-infobar
display: flex
flex-flow: row nowrap
gap: 1.4em
color: var(--tw-prose-body)
.gc-language
display: none
.gc-stars, .gc-forks, .gc-license
font-weight: 500
font-size: 0.96em
opacity: 0.9;
&:before
content: ' '
display: inline-block
height: 1.3em
width: 1.3em
margin-right: .4rem
vertical-align: -.24em
font-size: inherit
background-color: var(--tw-prose-body)
overflow: visible
mask-size: contain
mask-position: center
mask-repeat: no-repeat
transition-property: background-color, background;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1)
transition-duration: 0.15s
.gc-stars
&:before
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' aria-hidden='true' height='16' viewBox='0 0 16 16' version='1.1' width='16'%3E%3Cpath d='M8 .25a.75.75 0 0 1 .673.418l1.882 3.815 4.21.612a.75.75 0 0 1 .416 1.279l-3.046 2.97.719 4.192a.751.751 0 0 1-1.088.791L8 12.347l-3.766 1.98a.75.75 0 0 1-1.088-.79l.72-4.194L.818 6.374a.75.75 0 0 1 .416-1.28l4.21-.611L7.327.668A.75.75 0 0 1 8 .25Zm0 2.445L6.615 5.5a.75.75 0 0 1-.564.41l-3.097.45 2.24 2.184a.75.75 0 0 1 .216.664l-.528 3.084 2.769-1.456a.75.75 0 0 1 .698 0l2.77 1.456-.53-3.084a.75.75 0 0 1 .216-.664l2.24-2.183-3.096-.45a.75.75 0 0 1-.564-.41L8 2.694Z'%3E%3C/path%3E%3C/svg%3E")
.gc-license
&:before
margin-right: .5rem
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' aria-hidden='true' height='16' viewBox='0 0 16 16' version='1.1' width='16'%3E%3Cpath d='M8.75.75V2h.985c.304 0 .603.08.867.231l1.29.736c.038.022.08.033.124.033h2.234a.75.75 0 0 1 0 1.5h-.427l2.111 4.692a.75.75 0 0 1-.154.838l-.53-.53.529.531-.001.002-.002.002-.006.006-.006.005-.01.01-.045.04c-.21.176-.441.327-.686.45C14.556 10.78 13.88 11 13 11a4.498 4.498 0 0 1-2.023-.454 3.544 3.544 0 0 1-.686-.45l-.045-.04-.016-.015-.006-.006-.004-.004v-.001a.75.75 0 0 1-.154-.838L12.178 4.5h-.162c-.305 0-.604-.079-.868-.231l-1.29-.736a.245.245 0 0 0-.124-.033H8.75V13h2.5a.75.75 0 0 1 0 1.5h-6.5a.75.75 0 0 1 0-1.5h2.5V3.5h-.984a.245.245 0 0 0-.124.033l-1.289.737c-.265.15-.564.23-.869.23h-.162l2.112 4.692a.75.75 0 0 1-.154.838l-.53-.53.529.531-.001.002-.002.002-.006.006-.016.015-.045.04c-.21.176-.441.327-.686.45C4.556 10.78 3.88 11 3 11a4.498 4.498 0 0 1-2.023-.454 3.544 3.544 0 0 1-.686-.45l-.045-.04-.016-.015-.006-.006-.004-.004v-.001a.75.75 0 0 1-.154-.838L2.178 4.5H1.75a.75.75 0 0 1 0-1.5h2.234a.249.249 0 0 0 .125-.033l1.288-.737c.265-.15.564-.23.869-.23h.984V.75a.75.75 0 0 1 1.5 0Zm2.945 8.477c.285.135.718.273 1.305.273s1.02-.138 1.305-.273L13 6.327Zm-10 0c.285.135.718.273 1.305.273s1.02-.138 1.305-.273L3 6.327Z'%3E%3C/path%3E%3C/svg%3E")
.gc-forks
&:before
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' aria-hidden='true' height='16' viewBox='0 0 16 16' version='1.1' width='16'%3E%3Cpath d='M5 5.372v.878c0 .414.336.75.75.75h4.5a.75.75 0 0 0 .75-.75v-.878a2.25 2.25 0 1 1 1.5 0v.878a2.25 2.25 0 0 1-2.25 2.25h-1.5v2.128a2.251 2.251 0 1 1-1.5 0V8.5h-1.5A2.25 2.25 0 0 1 3.5 6.25v-.878a2.25 2.25 0 1 1 1.5 0ZM5 3.25a.75.75 0 1 0-1.5 0 .75.75 0 0 0 1.5 0Zm6.75.75a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5Zm-3 8.75a.75.75 0 1 0-1.5 0 .75.75 0 0 0 1.5 0Z'%3E%3C/path%3E%3C/svg%3E")
a.card-github.fetch-waiting
pointer-events: none
opacity: 0.7
transition: opacity 0.15s ease-in-out
.gc-description, .gc-stars, .gc-forks, .gc-license
background-color: var(--tw-prose-body)
color: transparent
opacity: 0.5;
border-radius: 1rem
animation: pulsate 2s infinite linear
user-select: none
&:before
background-color: transparent
.gc-avatar
display: none
.gc-repo
margin-left: -0.1rem
a.card-github.fetch-error
pointer-events: all
opacity: 1
@keyframes pulsate
0%
opacity: 0.2
50%
opacity: 0.5
100%
opacity: 0.2
</style> </style>
<style lang="css" is:global> <style lang="css" is:global>

View File

@ -0,0 +1,39 @@
---
title: Markdown extended features
published: 2024-05-01
description: 'Read more about Markdown features in Fuwari'
image: ''
tags: [Demo, Example, Markdown, Fuwari]
category: 'Examlpes'
draft: false
---
## Github repository cards
You can add dynamic cards that link to Github repositories, on page load, the repository information is pulled from the Github API. `::github{repo="saicaca/fuwari"}`
::github{repo="Fabrizz/MMM-OnSpotify"}
## Admonitions, notes, containers
Fuwari supports admonitions of type: `tip, note, important, warning, caution`
:::note
This is a note, other frameworks call them containers or alerts
:::
:::tip{title="TIP"}
This is a tip, you can change the title using the title property: `:::tip{title="Custom title"} \`
:::
:::important
Drink 8 glasses of water!
:::
:::warning
You should star the [Fuwari repository](https://github.com/saicaca/fuwari)
:::
:::caution
Admonitions can have other elements inside
::github{repo="saicaca/fuwari"}
:::

View File

@ -0,0 +1,26 @@
/// <reference types="mdast" />
import { h } from 'hastscript'
/**
* Creates an admonition component.
*
* @param {Object} properties - The properties of the component.
* @param {string} [properties.title] - An optional title.
* @param {('tip'|'note'|'important'|'caution'|'warning')} type - The admonition type.
* @param {import('mdast').RootContent[]} children - The children elements of the component.
* @returns {import('mdast').Parent} The created admonition component.
*/
export function AdmonitionComponent(properties, children, type) {
if (!Array.isArray(children) || children.length === 0)
return h("div",
{ class: 'hidden' },
'Invalid admonition directive. (Admonition directives must be of block type ":::note{name="name"} <content> :::")'
);
const title = properties?.title;
return h(`blockquote`,
{ class: `admonition bdm-${type}` },
[ h("span", { class: `bdm-title` }, title ? title : type.toUpperCase()), ...children]
);
}

View File

@ -0,0 +1,115 @@
/// <reference types="mdast" />
import { h } from 'hastscript'
/**
* Creates a GitHub Card component.
*
* @param {Object} properties - The properties of the component.
* @param {string} properties.repo - The GitHub repository in the format "owner/repo".
* @param {import('mdast').RootContent[]} children - The children elements of the component.
* @returns {import('mdast').Parent} The created GitHub Card component.
*/
export function GithubCardComponent(properties, children) {
if (Array.isArray(children) && children.length !== 0)
return h("div",
{ class: 'hidden' },
['Invalid directive. ("github" directive must be leaf type "::github{repo="owner/repo"}")']
);
if (!properties.repo || !properties.repo.includes("/"))
return h("div",
{ class: 'hidden' },
'Invalid repository. ("repo" attributte must be in the format "owner/repo")'
);
const repo = properties.repo;
const cardUuid = `GC${Math.random().toString(36).slice(-6)}` // Collisions are not important
const nAvatar = h(
`span#${cardUuid}-avatar`,
{ class: "gc-avatar"},
)
const nLanguage = h(
`span#${cardUuid}-language`,
{ class: "gc-language" },
"Waiting..."
)
const nTitle = h(
`div`,
{ class: "gc-titlebar" },
[
h("span", { class: "gc-owner" }, [
nAvatar,
h("span", { class: "gc-user" }, repo.split("/")[0] ),
]),
h("span", { class: "gc-divider" }, "/" ),
h("span", { class: "gc-repo" }, repo.split("/")[1] )
]
)
const nDescription = h(
`div#${cardUuid}-description`,
{ class: "gc-description" },
"Waiting for api.github.com..."
)
const nStars = h(
`span#${cardUuid}-stars`,
{ class: "gc-stars" },
"00K"
)
const nForks = h(
`span#${cardUuid}-forks`,
{ class: "gc-forks" },
"0K"
)
const nLicense = h(
`span#${cardUuid}-license`,
{ class: "gc-license" },
"0K"
)
const nScript = h(
`script#${cardUuid}-script`,
{ type: "text/javascript", defer: true },
`
fetch('https://api.github.com/repos/${repo}', { referrerPolicy: "no-referrer" }).then(response => response.json()).then(data => {
document.getElementById('${cardUuid}-card').href = data.html_url;
document.getElementById('${cardUuid}-description').innerText = data.description.replace(/:[a-zA-Z0-9_]+:/g, '');
document.getElementById('${cardUuid}-language').innerText = data.language;
document.getElementById('${cardUuid}-forks').innerText = Intl.NumberFormat('en-us', { notation: "compact", maximumFractionDigits: 1 }).format(data.forks).replaceAll("\u202f", '');
document.getElementById('${cardUuid}-stars').innerText = Intl.NumberFormat('en-us', { notation: "compact", maximumFractionDigits: 1 }).format(data.stargazers_count).replaceAll("\u202f", '');
const avatarEl = document.getElementById('${cardUuid}-avatar');
avatarEl.style.backgroundImage = 'url(' + data.owner.avatar_url + ')';
avatarEl.style.backgroundColor = 'transparent';
if (data.license?.spdx_id) {
document.getElementById('${cardUuid}-license').innerText = data.license?.spdx_id
} else {
document.getElementById('${cardUuid}-license').classList.add = "no-license"
};
document.getElementById('${cardUuid}-card').classList.remove("fetch-waiting");
console.log("[GITHUB-CARD] Loaded card for ${repo} | ${cardUuid}.")
}).catch(err => {
const c = document.getElementById('${cardUuid}-card');
c.classList.add("fetch-error");
console.warn("[GITHUB-CARD] (Error) Loading card for ${repo} | ${cardUuid}.")
})
`
)
return h(`a#${cardUuid}-card`,
{ class: "card-github fetch-waiting no-styling",
href: `https://github.com/${repo}`,
repo },
[
nTitle,
nDescription,
h("div",
{ class: "gc-infobar" },
[nStars, nForks, nLicense, nLanguage]
),
nScript
]
);
}

View File

@ -1,7 +1,7 @@
/** @type {import('tailwindcss').Config} */ /** @type {import('tailwindcss').Config} */
const defaultTheme = require("tailwindcss/defaultTheme") const defaultTheme = require("tailwindcss/defaultTheme")
module.exports = { module.exports = {
content: ["./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}"], content: ["./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue,mjs}"],
darkMode: "class", // allows toggling dark mode manually darkMode: "class", // allows toggling dark mode manually
theme: { theme: {
extend: { extend: {