@grove-dev/astro 0.3.2 → 0.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@grove-dev/astro",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.4",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Composable Astro UI, data adapters, and integration for Grove directories.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -51,13 +51,13 @@
|
|
|
51
51
|
"./server": "./src/server/index.ts"
|
|
52
52
|
},
|
|
53
53
|
"dependencies": {
|
|
54
|
-
"astro": "^
|
|
54
|
+
"astro": "^7.1.3",
|
|
55
55
|
"marked": "^18.0.0",
|
|
56
56
|
"sanitize-html": "^2.17.5",
|
|
57
|
-
"@grove-dev/core": "0.3.
|
|
57
|
+
"@grove-dev/core": "0.3.4"
|
|
58
58
|
},
|
|
59
59
|
"peerDependencies": {
|
|
60
|
-
"astro": "^6.0.0"
|
|
60
|
+
"astro": "^6.0.0 || ^7.0.0"
|
|
61
61
|
},
|
|
62
62
|
"devDependencies": {
|
|
63
63
|
"@types/sanitize-html": "^2.16.0"
|
|
@@ -63,8 +63,8 @@ interface Props {
|
|
|
63
63
|
*/
|
|
64
64
|
aliases?: Record<string, string>;
|
|
65
65
|
/**
|
|
66
|
-
*
|
|
67
|
-
*
|
|
66
|
+
* Optional complete asset registry supplied by a consumer. When omitted,
|
|
67
|
+
* Grove attempts the configured asset path and falls back on image error.
|
|
68
68
|
*/
|
|
69
69
|
available?: string[];
|
|
70
70
|
/**
|
|
@@ -124,25 +124,11 @@ function resolveName(raw: string): string {
|
|
|
124
124
|
}
|
|
125
125
|
|
|
126
126
|
const resolved = resolveName(name);
|
|
127
|
-
const bundledIcons: Record<"stack" | "platform", Set<string>> = {
|
|
128
|
-
stack: new Set([
|
|
129
|
-
"android", "apple", "bun", "capacitor", "clojure", "clojurescript",
|
|
130
|
-
"dart", "deno", "django", "docker", "firebase", "flutter", "go",
|
|
131
|
-
"graphql", "ionic", "java", "javascript", "kotlin", "llm", "mongodb",
|
|
132
|
-
"node.js", "nodejs", "python", "rag", "react", "react-native", "rust",
|
|
133
|
-
"solidity", "sveltekit", "swift", "tensorflow", "typescript", "vue",
|
|
134
|
-
]),
|
|
135
|
-
platform: new Set([
|
|
136
|
-
"android", "apple", "chrome", "chromeos", "desktop", "embedded", "ios",
|
|
137
|
-
"linux", "macos", "ubuntu", "web", "windows",
|
|
138
|
-
]),
|
|
139
|
-
};
|
|
140
127
|
const availableIcons = available?.map(slugify);
|
|
141
128
|
const hasAsset =
|
|
142
129
|
category === "brand" ||
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
: bundledIcons[category].has(resolved));
|
|
130
|
+
availableIcons === undefined ||
|
|
131
|
+
availableIcons.includes(resolved);
|
|
146
132
|
const effectiveMode: IconMode = resolved === "apple" ? "auto" : mode;
|
|
147
133
|
const platformStackIcons = new Set(["docker"]);
|
|
148
134
|
const textOnlyPlatforms = new Set(["self-host", "self-hosted"]);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
import type { IndexRecord } from "@grove-dev/core";
|
|
3
3
|
import Icon from "./Icon.astro";
|
|
4
|
-
import { formatRelative, formatStars, getOwnerAndRepoFromRepoUrl, getOwnerAvatarUrl, statusDisplay } from "@grove-dev/astro";
|
|
4
|
+
import { formatRelative, formatStars, getOwnerAndRepoFromRepoUrl, getOwnerAvatarUrl, projectStackIds, statusDisplay } from "@grove-dev/astro";
|
|
5
5
|
|
|
6
6
|
interface Props {
|
|
7
7
|
record: IndexRecord;
|
|
@@ -23,7 +23,7 @@ const repoHref = project?.repoUrl ?? item.links.github;
|
|
|
23
23
|
const { owner, repo } = getOwnerAndRepoFromRepoUrl(repoHref ?? "");
|
|
24
24
|
const avatar = project ? project.logoUrl ?? getOwnerAvatarUrl(owner, 80) : undefined;
|
|
25
25
|
const initials = name.split(/\s+/).map((word) => word[0]).filter(Boolean).slice(0, 2).join("").toUpperCase();
|
|
26
|
-
const stacks = project
|
|
26
|
+
const stacks = projectStackIds(project);
|
|
27
27
|
const platforms = project?.platforms ?? [];
|
|
28
28
|
const stars = project?.github?.stars;
|
|
29
29
|
const updatedAt = project?.github?.pushedAt ?? (item.kind === "resource" ? item.publishedAt : null);
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
*/
|
|
26
26
|
import type { IndexRecord, Resource, ProjectRecord, IndexProjectRecord } from "@grove-dev/core";
|
|
27
27
|
import Icon from "./Icon.astro";
|
|
28
|
-
import { getOwnerAndRepoFromRepoUrl, getOwnerAvatarUrl } from "@grove-dev/astro";
|
|
28
|
+
import { getOwnerAndRepoFromRepoUrl, getOwnerAvatarUrl, projectStackIds } from "@grove-dev/astro";
|
|
29
29
|
import { formatStars, formatRelative } from "@grove-dev/astro";
|
|
30
30
|
import { statusDisplay } from "@grove-dev/astro";
|
|
31
31
|
|
|
@@ -126,12 +126,7 @@ const platforms = isProject ? (item as { platforms?: string[] }).platforms ?? []
|
|
|
126
126
|
const visiblePlatforms = platforms.slice(0, 4);
|
|
127
127
|
const platformOverflow = platforms.length - visiblePlatforms.length;
|
|
128
128
|
|
|
129
|
-
const allStacks = isProject
|
|
130
|
-
? [
|
|
131
|
-
(item as { stack?: string }).stack,
|
|
132
|
-
...((item as { stacks?: string[] }).stacks ?? []),
|
|
133
|
-
].filter((s): s is string => Boolean(s))
|
|
134
|
-
: [];
|
|
129
|
+
const allStacks = isProject ? projectStackIds(item as ProjectRecord) : [];
|
|
135
130
|
const visibleStacks = allStacks.slice(0, 3);
|
|
136
131
|
const stackOverflow = allStacks.length - visibleStacks.length;
|
|
137
132
|
|
|
@@ -24,6 +24,8 @@ interface Props {
|
|
|
24
24
|
class?: string;
|
|
25
25
|
/** Override the visible lens list (defaults to LENSES). */
|
|
26
26
|
lensIds?: string[];
|
|
27
|
+
/** Consumer noun for the unfiltered lens, e.g. "All apps". */
|
|
28
|
+
allLabel?: string;
|
|
27
29
|
}
|
|
28
30
|
|
|
29
31
|
const {
|
|
@@ -31,6 +33,7 @@ const {
|
|
|
31
33
|
pathPrefix = "/",
|
|
32
34
|
class: className = "",
|
|
33
35
|
lensIds,
|
|
36
|
+
allLabel,
|
|
34
37
|
} = Astro.props;
|
|
35
38
|
|
|
36
39
|
// If `lensIds` is provided, filter LENSES to those ids in that order.
|
|
@@ -65,7 +68,7 @@ const lenses =
|
|
|
65
68
|
data-event="lens_tab_click"
|
|
66
69
|
data-event-source="smart_lens_tabs"
|
|
67
70
|
>
|
|
68
|
-
{lensDisplay(lens.id)}
|
|
71
|
+
{lens.id === "all" && allLabel ? allLabel : lensDisplay(lens.id)}
|
|
69
72
|
</a>
|
|
70
73
|
);
|
|
71
74
|
})}
|
|
@@ -11,8 +11,8 @@
|
|
|
11
11
|
* own config (typically `data/generated/site-config.json` for the
|
|
12
12
|
* showcase).
|
|
13
13
|
*
|
|
14
|
-
*
|
|
15
|
-
* privacy-first deployments.
|
|
14
|
+
* GA4 can be configured once through `site.analytics.googleAnalyticsId`
|
|
15
|
+
* or overridden per page with `gaId`. Omit both for privacy-first deployments.
|
|
16
16
|
*/
|
|
17
17
|
import "../styles.css";
|
|
18
18
|
import Header from "./Header.astro";
|
|
@@ -61,6 +61,9 @@ interface Site {
|
|
|
61
61
|
};
|
|
62
62
|
repoUrl?: string;
|
|
63
63
|
url?: string;
|
|
64
|
+
analytics?: {
|
|
65
|
+
googleAnalyticsId?: string;
|
|
66
|
+
};
|
|
64
67
|
/** Optional directory-level stats — populated from site-config.json
|
|
65
68
|
* at generate time. Components use it to render hero counts,
|
|
66
69
|
* origin card stats, and footer summary lines. */
|
|
@@ -103,6 +106,7 @@ const {
|
|
|
103
106
|
} = Astro.props;
|
|
104
107
|
const directoryPath =
|
|
105
108
|
searchPath ?? `/${site.blueprintConfig?.routeSlug ?? "items"}`;
|
|
109
|
+
const effectiveGaId = gaId ?? site.analytics?.googleAnalyticsId;
|
|
106
110
|
|
|
107
111
|
const favicon =
|
|
108
112
|
"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Crect width='16' height='16' rx='3' fill='%2318181b'/%3E%3C/svg%3E";
|
|
@@ -130,14 +134,14 @@ const favicon =
|
|
|
130
134
|
title="LLM usage guidance"
|
|
131
135
|
/>
|
|
132
136
|
|
|
133
|
-
{
|
|
137
|
+
{effectiveGaId && (
|
|
134
138
|
<>
|
|
135
139
|
<script
|
|
136
140
|
is:inline
|
|
137
141
|
async
|
|
138
|
-
src={`https://www.googletagmanager.com/gtag/js?id=${
|
|
142
|
+
src={`https://www.googletagmanager.com/gtag/js?id=${effectiveGaId}`}
|
|
139
143
|
/>
|
|
140
|
-
<script is:inline define:vars={{ gaId }}>
|
|
144
|
+
<script is:inline define:vars={{ gaId: effectiveGaId }}>
|
|
141
145
|
window.dataLayer = window.dataLayer || [];
|
|
142
146
|
function gtag() {
|
|
143
147
|
dataLayer.push(arguments);
|
|
@@ -290,8 +294,8 @@ const favicon =
|
|
|
290
294
|
|
|
291
295
|
<slot name="body-end" />
|
|
292
296
|
|
|
293
|
-
{
|
|
294
|
-
<script is:inline define:vars={{ gaId }}>
|
|
297
|
+
{effectiveGaId && (
|
|
298
|
+
<script is:inline define:vars={{ gaId: effectiveGaId }}>
|
|
295
299
|
(function () {
|
|
296
300
|
// GA4's `gtag('config', id)` call in the <head> already auto-pings
|
|
297
301
|
// `page_view` on full navigations, so this block only needs to
|
package/src/server/models.ts
CHANGED
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
formatStars,
|
|
20
20
|
getOwnerAndRepoFromRepoUrl,
|
|
21
21
|
getOwnerAvatarUrl,
|
|
22
|
+
projectStackIds,
|
|
22
23
|
statusDisplay,
|
|
23
24
|
totalPages,
|
|
24
25
|
} from "@grove-dev/core";
|
|
@@ -42,6 +43,9 @@ export interface DirectorySiteConfig {
|
|
|
42
43
|
repoUrl?: string;
|
|
43
44
|
nav?: Array<{ label: string; href: string }>;
|
|
44
45
|
facets?: string[];
|
|
46
|
+
analytics?: {
|
|
47
|
+
googleAnalyticsId?: string;
|
|
48
|
+
};
|
|
45
49
|
footer?: {
|
|
46
50
|
columns?: Array<{
|
|
47
51
|
heading: string;
|
|
@@ -283,7 +287,7 @@ export function getRecordDetailModel(
|
|
|
283
287
|
const description = record.description ?? `${name} on ${site.name}`;
|
|
284
288
|
const repoUrl = proj?.repoUrl ?? record.links?.github ?? "";
|
|
285
289
|
const homepageUrl = record.links?.website ?? "";
|
|
286
|
-
const stacks =
|
|
290
|
+
const stacks = projectStackIds(proj);
|
|
287
291
|
const platforms = proj?.platforms ?? [];
|
|
288
292
|
const github = proj?.github?.repository;
|
|
289
293
|
const stars = github?.stargazers_count ?? 0;
|