Skip to content

Commit 17d570e

Browse files
authored
Merge branch 'npmx-dev:main' into feat/changelog-1
2 parents d4bce55 + 57687cc commit 17d570e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+2055
-597
lines changed
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
name: remove-needs-review-on-review
2+
3+
on:
4+
pull_request_review:
5+
types:
6+
- submitted
7+
8+
jobs:
9+
remove-needs-review:
10+
name: 🏷️ Remove needs review label
11+
if: github.repository == 'npmx-dev/npmx.dev'
12+
runs-on: ubuntu-slim
13+
permissions:
14+
contents: read
15+
issues: write
16+
pull-requests: write
17+
steps:
18+
- name: 🏷️ Remove needs review label
19+
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
20+
with:
21+
script: |
22+
const pr = context.payload.pull_request;
23+
const review = context.payload.review;
24+
const LABEL = 'needs review';
25+
const reviewer = review?.user?.login;
26+
const author = pr.user?.login;
27+
const reviewerType = review?.user?.type;
28+
29+
if (!reviewer) {
30+
console.log('No reviewer login found in payload, skipping.');
31+
return;
32+
}
33+
34+
if (reviewerType === 'Bot') {
35+
console.log(`Skipping bot review from @${reviewer} on PR #${pr.number}.`);
36+
return;
37+
}
38+
39+
if (reviewer === author) {
40+
console.log(`Skipping self-review from @${reviewer} on PR #${pr.number}.`);
41+
return;
42+
}
43+
44+
if (!pr.labels.some(({ name }) => name === LABEL)) {
45+
console.log(`PR #${pr.number} does not have the "${LABEL}" label.`);
46+
return;
47+
}
48+
49+
const { data: permission } = await github.rest.repos.getCollaboratorPermissionLevel({
50+
owner: context.repo.owner,
51+
repo: context.repo.repo,
52+
username: reviewer,
53+
});
54+
55+
console.log(`Reviewer @${reviewer} permission is "${permission.permission}".`);
56+
57+
if (!['admin', 'maintain', 'write'].includes(permission.permission)) {
58+
console.log(`Reviewer @${reviewer} is not a maintainer, skipping.`);
59+
return;
60+
}
61+
62+
await github.rest.issues.removeLabel({
63+
owner: context.repo.owner,
64+
repo: context.repo.repo,
65+
issue_number: pr.number,
66+
name: LABEL,
67+
});
68+
69+
console.log(`Removed "${LABEL}" from PR #${pr.number}.`);

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ What npmx offers:
7777
| Organization pages |||
7878
| Provenance indicators |||
7979
| Code browser |||
80-
| Dark mode | ||
80+
| Dark mode | ||
8181
| Outdated dependency warnings |||
8282
| Module format badges (ESM/CJS) |||
8383
| TypeScript types indicator |||

app/components/CollapsibleSection.vue

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,13 @@ function toggle() {
6262
}
6363
6464
const ariaLabel = computed(() => {
65-
const action = isOpen.value ? 'Collapse' : 'Expand'
66-
return props.title ? `${action} ${props.title}` : action
65+
if (!props.title) {
66+
return isOpen.value ? $t('common.collapse') : $t('common.expand')
67+
}
68+
69+
return isOpen.value
70+
? $t('common.collapse_with_name', { name: props.title })
71+
: $t('common.expand_with_name', { name: props.title })
6772
})
6873
useHead({
6974
style: [

app/components/ColorScheme/Img.vue

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<script setup lang="ts">
2+
const props = defineProps<{
3+
lightSrc: string
4+
darkSrc: string
5+
}>()
6+
</script>
7+
8+
<template>
9+
<img
10+
:src="props.darkSrc"
11+
class="color-mode-img"
12+
:style="`--light-src: url('${props.lightSrc}')`"
13+
/>
14+
</template>
15+
16+
<style>
17+
.light .color-mode-img {
18+
content: var(--light-src);
19+
}
20+
</style>

app/components/Compare/FacetQuadrantChart.vue

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -376,13 +376,59 @@ const config = computed<VueUiQuadrantConfig>(() => {
376376
colors: watermarkColors,
377377
translateFn: $t,
378378
positioning: 'bottom',
379-
sizeRatioTagline: 0.6,
379+
sizeRatioTagline: 0.5,
380380
sizeRatioLogo: 0.4,
381-
offsetYTagline: 20,
382-
offsetYLogo: 12,
381+
offsetYTagline: 0,
382+
offsetYLogo: -8,
383383
})
384384
"
385385
/>
386+
387+
<foreignObject :x="0" :y="30" style="overflow: visible" :width="svg.width" :height="12">
388+
<div class="flex items-center justify-center gap-2">
389+
<TooltipApp interactive>
390+
<button
391+
data-dom-to-png-ignore
392+
type="button"
393+
class="i-lucide:info w-3.5 h-3.5 text-fg-muted cursor-help"
394+
:aria-label="$t('compare.quadrant_chart.explanation.tooltip_help_efficiency')"
395+
/>
396+
<template #content>
397+
<div class="flex flex-col gap-3">
398+
<p class="text-xs text-fg-muted">
399+
{{ $t('compare.quadrant_chart.explanation.efficiency') }}
400+
</p>
401+
</div>
402+
</template>
403+
</TooltipApp>
404+
</div>
405+
</foreignObject>
406+
407+
<foreignObject
408+
:x="svg.width - 40"
409+
:y="svg.height / 2 - 8"
410+
style="overflow: visible"
411+
:width="20"
412+
:height="12"
413+
>
414+
<div class="flex items-center justify-center gap-2">
415+
<TooltipApp interactive>
416+
<button
417+
data-dom-to-png-ignore
418+
type="button"
419+
class="i-lucide:info w-3.5 h-3.5 text-fg-muted cursor-help"
420+
:aria-label="$t('compare.quadrant_chart.explanation.tooltip_help_adoption')"
421+
/>
422+
<template #content>
423+
<div class="flex flex-col gap-3">
424+
<p class="text-xs text-fg-muted">
425+
{{ $t('compare.quadrant_chart.explanation.adoption') }}
426+
</p>
427+
</div>
428+
</template>
429+
</TooltipApp>
430+
</div>
431+
</foreignObject>
386432
</template>
387433

388434
<template #menuIcon="{ isOpen }">
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
<script setup lang="ts">
2+
import { ACTIVE_NOODLES, PERMANENT_NOODLES, type Noodle } from '../Noodle'
3+
4+
const { env } = useAppConfig().buildInfo
5+
6+
const activeNoodlesData = ACTIVE_NOODLES.map(noodle => ({
7+
key: noodle.key,
8+
date: noodle.date,
9+
dateTo: noodle.dateTo,
10+
timezone: noodle.timezone,
11+
tagline: noodle.tagline,
12+
}))
13+
14+
const permanentNoodlesData = PERMANENT_NOODLES.map(noodle => ({
15+
key: noodle.key,
16+
tagline: noodle.tagline,
17+
}))
18+
19+
onPrehydrate(el => {
20+
const tagline = el.querySelector<HTMLElement>('#intro-header-tagline')
21+
const defaultLogo = el.querySelector<HTMLElement>('#intro-header-noodle-default')
22+
23+
if (!tagline || !defaultLogo) return
24+
25+
let permanentNoodles
26+
try {
27+
permanentNoodles = JSON.parse(el.dataset.permanentNoodles as string) as Noodle[]
28+
} catch {
29+
return
30+
}
31+
const activePermanentNoodle = permanentNoodles?.find(noodle =>
32+
new URLSearchParams(window.location.search).has(noodle.key),
33+
)
34+
35+
if (activePermanentNoodle) {
36+
const permanentNoodleLogo = el.querySelector<HTMLElement>(
37+
`#intro-header-noodle-${activePermanentNoodle.key}`,
38+
)
39+
40+
if (!permanentNoodleLogo) return
41+
42+
permanentNoodleLogo.style.display = 'block'
43+
defaultLogo.style.display = 'none'
44+
if (activePermanentNoodle.tagline === false) {
45+
tagline.style.display = 'none'
46+
}
47+
return
48+
}
49+
50+
let activeNoodles
51+
try {
52+
activeNoodles = JSON.parse(el.dataset.activeNoodles as string) as Noodle[]
53+
} catch {
54+
return
55+
}
56+
57+
const currentActiveNoodles = activeNoodles.filter(noodle => {
58+
const todayDate = new Date()
59+
const todayDateRaw = new Intl.DateTimeFormat('en-US', {
60+
timeZone: noodle.timezone === 'auto' ? undefined : noodle.timezone,
61+
month: '2-digit',
62+
day: '2-digit',
63+
year: 'numeric',
64+
}).format(todayDate)
65+
66+
const noodleDateFrom = new Date(noodle.date!)
67+
if (!noodle.dateTo) {
68+
const noodleDateFromRaw = new Intl.DateTimeFormat('en-US', {
69+
timeZone: noodle.timezone === 'auto' ? undefined : noodle.timezone,
70+
month: '2-digit',
71+
day: '2-digit',
72+
year: 'numeric',
73+
}).format(noodleDateFrom)
74+
return todayDateRaw === noodleDateFromRaw
75+
}
76+
const noodleDateTo = new Date(noodle.dateTo!)
77+
return todayDate >= noodleDateFrom && todayDate <= noodleDateTo
78+
})
79+
80+
if (!currentActiveNoodles.length) return
81+
82+
const roll = Math.floor(Math.random() * currentActiveNoodles.length)
83+
const selectedNoodle = currentActiveNoodles[roll]
84+
85+
if (!selectedNoodle) return
86+
87+
const noodleLogo = el.querySelector<HTMLElement>(`#intro-header-noodle-${selectedNoodle.key}`)
88+
89+
if (!defaultLogo || !noodleLogo || !tagline) return
90+
91+
defaultLogo.style.display = 'none'
92+
noodleLogo.style.display = 'block'
93+
if (selectedNoodle.tagline === false) {
94+
tagline.style.display = 'none'
95+
}
96+
})
97+
</script>
98+
99+
<template>
100+
<div
101+
:data-active-noodles="JSON.stringify(activeNoodlesData)"
102+
:data-permanent-noodles="JSON.stringify(permanentNoodlesData)"
103+
>
104+
<h1 class="sr-only">
105+
{{ $t('alt_logo') }}
106+
</h1>
107+
<div
108+
id="intro-header-noodle-default"
109+
class="relative mb-6 w-fit mx-auto motion-safe:animate-fade-in motion-safe:animate-fill-both"
110+
aria-hidden="true"
111+
>
112+
<AppLogo id="npmx-index-h1-logo-normal" class="w-42 h-auto sm:w-58 md:w-70" />
113+
<span
114+
id="npmx-index-h1-logo-env"
115+
class="text-sm sm:text-base md:text-lg transform-origin-br font-mono tracking-widest text-accent absolute -bottom-4 -inset-ie-1.5"
116+
>
117+
{{ env === 'release' ? 'alpha' : env }}
118+
</span>
119+
</div>
120+
<component
121+
v-for="noodle in PERMANENT_NOODLES"
122+
:key="noodle.key"
123+
:id="`intro-header-noodle-${noodle.key}`"
124+
class="hidden"
125+
aria-hidden="true"
126+
:is="noodle.logo"
127+
/>
128+
<component
129+
v-for="noodle in ACTIVE_NOODLES"
130+
:key="noodle.key"
131+
:id="`intro-header-noodle-${noodle.key}`"
132+
class="hidden"
133+
aria-hidden="true"
134+
:is="noodle.logo"
135+
/>
136+
<p
137+
id="intro-header-tagline"
138+
class="text-fg-muted text-lg sm:text-xl max-w-xl mb-12 lg:mb-14 motion-safe:animate-slide-up motion-safe:animate-fill-both delay-100"
139+
>
140+
{{ $t('tagline') }}
141+
</p>
142+
</div>
143+
</template>

app/components/LandingLogo.vue

Lines changed: 0 additions & 76 deletions
This file was deleted.

0 commit comments

Comments
 (0)