Skip to content

Commit 7e58db5

Browse files
authored
feat: continuous releases badge (#371)
1 parent c6c1272 commit 7e58db5

File tree

5 files changed

+188
-0
lines changed

5 files changed

+188
-0
lines changed

README.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,24 @@ It is aiming to reduce the number of these comments :)
2626

2727
> This was fixed in #18. Can we release that fix?
2828
29+
## Badge
30+
31+
Show that your project uses pkg.pr.new by adding a badge to your README:
32+
33+
[![pkg.pr.new](https://pkg.pr.new/badge/stackblitz-labs/pkg.pr.new)](https://pkg.pr.new/~/stackblitz-labs/pkg.pr.new)
34+
35+
### How to Get a Badge for Your Repository
36+
37+
1. **Automatically on Repository Page**:
38+
Visit your repository page at `https://pkg.pr.new/~/OWNER/REPO` and you'll find a badge with a copy button that will copy the markdown code for you.
39+
40+
2. **Direct Badge URL**:
41+
Use this format to create a badge for your repository:
42+
```markdown
43+
[![pkg.pr.new](https://pkg.pr.new/badge/OWNER/REPO)](https://pkg.pr.new/~/OWNER/REPO)
44+
```
45+
Just replace `OWNER` and `REPO` with your GitHub username/organization and repository name.
46+
2947
These are some of the projects and companies using pkg.pr.new:
3048

3149
<p align="center">
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<script setup lang="ts">
2+
import { ref, onMounted, computed } from "vue";
3+
4+
const props = defineProps<{
5+
owner: string;
6+
repo: string;
7+
color?: string;
8+
}>();
9+
10+
const copied = ref(false);
11+
const style = "flat";
12+
const color = props.color || "000";
13+
14+
const baseUrl = ref("https://pkg.pr.new");
15+
onMounted(() => {
16+
baseUrl.value = window.location.origin;
17+
});
18+
19+
const badgeUrl = computed(
20+
() =>
21+
`${baseUrl.value}/badge/${props.owner}/${props.repo}` +
22+
`?style=${style}` +
23+
`&color=${encodeURIComponent(color)}` +
24+
`&logoSize=auto`,
25+
);
26+
27+
const redirectUrl = computed(
28+
() => `${baseUrl.value}/~/${props.owner}/${props.repo}`,
29+
);
30+
31+
function copyBadgeCode() {
32+
const md = `[![${props.repo}](${badgeUrl.value})](${redirectUrl.value})`;
33+
navigator.clipboard.writeText(md);
34+
copied.value = true;
35+
setTimeout(() => (copied.value = false), 2000);
36+
}
37+
</script>
38+
39+
<template>
40+
<div class="inline-flex items-center gap-[2px]">
41+
<a :href="redirectUrl" target="_blank" rel="noopener">
42+
<img
43+
:src="badgeUrl"
44+
:alt="`${props.repo} badge`"
45+
class="h-5 w-auto block max-w-none"
46+
/>
47+
</a>
48+
49+
<UButton
50+
@click="copyBadgeCode"
51+
size="xs"
52+
color="gray"
53+
:icon="copied ? 'i-ph-check-bold' : 'i-ph-copy'"
54+
variant="ghost"
55+
class="!p-1 cursor-pointer"
56+
/>
57+
</div>
58+
</template>

packages/app/app/components/GettingStarted.vue

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,5 +51,32 @@
5151

5252
<img src="/pr-screenshot.png" alt="PR Screenshot" class="rounded-lg" />
5353
</GettingStartedStep>
54+
55+
<GettingStartedStep step="4">
56+
<div>Promote pkg.pr.new by adding a badge to your repository README:</div>
57+
58+
<div class="w-[550px]">
59+
<CodeSnippet
60+
class="text-[10px]"
61+
code="[![pkg.pr.new](https://pkg.pr.new/badge/OWNER/REPO)](https://pkg.pr.new/~/OWNER/REPO)"
62+
/>
63+
</div>
64+
65+
<div class="text-gray-500 text-sm">
66+
Replace OWNER and REPO with your GitHub username/organization and
67+
repository name.
68+
</div>
69+
70+
<template #actions>
71+
<UButton
72+
href="https://github.com/stackblitz-labs/pkg.pr.new?tab=readme-ov-file#badge"
73+
target="_blank"
74+
icon="ph-badge"
75+
trailing-icon="ph-arrow-square-out"
76+
>
77+
Learn more about badge options
78+
</UButton>
79+
</template>
80+
</GettingStartedStep>
5481
</div>
5582
</template>

packages/app/app/pages/~/[owner]/[repo].vue

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
<script setup lang="ts">
2+
import { computed } from "vue";
3+
24
definePageMeta({
35
name: "repo:details",
46
});
@@ -76,6 +78,16 @@ useSeoMeta({
7678
variant="link"
7779
/>
7880
</div>
81+
82+
<div class="flex flex-col items-center justify-center mt-2">
83+
<p class="text-sm mb-[10px]">
84+
You can copy the badge and put in your README!
85+
</p>
86+
<BadgeGenerator
87+
:owner="repository.owner.login"
88+
:repo="repository.name"
89+
/>
90+
</div>
7991
</div>
8092

8193
<Commits :owner="repository.owner.login" :repo="repository.name" />
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import {
2+
defineEventHandler,
3+
setHeader,
4+
getRouterParams,
5+
createError,
6+
getQuery,
7+
} from "h3";
8+
9+
export default defineEventHandler(async (event) => {
10+
const { owner, repo } = getRouterParams(event) as {
11+
owner: string;
12+
repo: string;
13+
};
14+
if (!owner || !repo) {
15+
throw createError({
16+
statusCode: 400,
17+
statusMessage: "Owner and repo are required",
18+
});
19+
}
20+
21+
const { style = "flat", color = "000" } = getQuery(event) as Record<
22+
string,
23+
string
24+
>;
25+
const logoBase64 = getPkgPrNewLogoBase64();
26+
const shieldsUrl =
27+
`https://img.shields.io/static/v1?` +
28+
`label=&message=${encodeURIComponent(repo)}` +
29+
`&color=${color}` +
30+
`&style=${style}` +
31+
`&logo=data:image/svg+xml;base64,${logoBase64}` +
32+
`&logoSize=auto`;
33+
34+
const res = await fetch(shieldsUrl);
35+
const svg = await res.text();
36+
37+
setHeader(event, "Content-Type", "image/svg+xml");
38+
setHeader(event, "Cache-Control", "public, max-age=86400");
39+
return svg;
40+
});
41+
42+
function getPkgPrNewLogoBase64(): string {
43+
const logo = `<svg xmlns="http://www.w3.org/2000/svg" width="71" height="73" viewBox="0 0 71 73" fill="none">
44+
<g transform="translate(0,7)">
45+
<g filter="url(#filter0_di_18_22)">
46+
<path d="M29.6539 2.52761C26.8827 3.91317 24.6248 5.06781 24.6248 5.10629C24.6248 5.14478 31.2447 8.57019 39.3399 12.7269C47.448 16.8707 54.1706 20.3731 54.2988 20.4886C54.5169 20.681 54.5298 21.1942 54.5298 28.9046C54.5298 36.6149 54.5169 37.1281 54.2988 37.3847C54.1706 37.5386 52.7208 38.3597 51.0915 39.2193C49.4494 40.0788 47.9612 40.7716 47.7816 40.7716C47.5891 40.7716 47.3839 40.6562 47.2684 40.4894C47.1016 40.2328 47.076 39.1166 47.076 32.2402L47.0632 24.286L16.9914 8.80112C5.66316 14.446 4.62399 15.0105 4.35458 15.3825L4.03385 15.8187C3.98253 41.7723 3.99536 49.4314 4.03385 49.5981C4.07233 49.7521 4.25194 50.06 4.45721 50.2781C4.7138 50.586 8.54974 52.5617 19.7882 58.1681C31.0266 63.7873 34.8754 65.6604 35.2089 65.6604C35.5425 65.6604 38.1725 64.4159 45.3184 60.8879C50.6169 58.2579 57.5062 54.8453 60.6108 53.2801C65.9863 50.586 66.2685 50.432 66.538 49.9445L66.833 49.4314C66.833 17.1273 66.8202 16.0496 66.6021 15.6263C66.3968 15.2029 65.4988 14.7282 51.1813 7.58234C36.928 0.474933 35.9402 -0.0125789 35.3372 0.000250395C34.7727 0.0130796 34.0928 0.320982 29.6539 2.52761Z" fill="url(#paint0_linear_18_22)"/>
47+
</g>
48+
<defs>
49+
<filter id="filter0_di_18_22" x="0.460111" y="1.52588e-05" width="69.9128" height="72.7401" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
50+
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
51+
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
52+
<feOffset dy="3.53989"/>
53+
<feGaussianBlur stdDeviation="1.76994"/>
54+
<feComposite in2="hardAlpha" operator="out"/>
55+
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
56+
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_18_22"/>
57+
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_18_22" result="shape"/>
58+
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
59+
<feOffset dy="1.76994"/>
60+
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
61+
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.95 0"/>
62+
<feBlend mode="normal" in2="shape" result="effect2_innerShadow_18_22"/>
63+
</filter>
64+
<linearGradient id="paint0_linear_18_22" x1="35.4165" y1="1.52588e-05" x2="35.4165" y2="66.8238" gradientUnits="userSpaceOnUse">
65+
<stop stop-color="white"/>
66+
<stop offset="1" stop-color="#999999"/>
67+
</linearGradient>
68+
</defs>
69+
</g>
70+
</svg>`;
71+
72+
return Buffer.from(logo).toString("base64");
73+
}

0 commit comments

Comments
 (0)