@getvitops/astro 7.0.0 → 8.0.1

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/CHANGELOG.md CHANGED
@@ -1,5 +1,130 @@
1
1
  # @getvitops/astro
2
2
 
3
+ ## 8.0.1
4
+
5
+ ### Patch Changes
6
+
7
+ - @getvitops/core@8.0.1
8
+ - @getvitops/generator@8.0.1
9
+ - @getvitops/utils@8.0.1
10
+ - @getvitops/vite@8.0.1
11
+
12
+ ## 8.0.0
13
+
14
+ ### Major Changes
15
+
16
+ - Rebuild the lightbox on one dialog + the existing carousel, fixing the flicker on
17
+ prev/next and the stutter on open.
18
+
19
+ **Breaking (`css`/`bricks` and `tailwind` formats — `.lightbox-dialog`'s markup
20
+ contract changed):**
21
+
22
+ - `<Gallery />` now emits ONE `<dialog class="lightbox-dialog">` per gallery,
23
+ wrapping a `<Carousel />`, instead of one dialog per image. A `.gallery__trigger`
24
+ is now a plain `<a href="#slide-id">`, not a `command="show-modal"` button.
25
+ - `.lightbox-dialog__content` / `__image` / `__nav` / `__nav-button` /
26
+ `__caption` are gone. The dialog's child is `.lightbox-dialog__track` (a
27
+ `.carousel`) — prev/next, dots, arrow keys and swipe are the carousel's,
28
+ reused rather than reimplemented. `.lightbox-dialog__close` is unchanged.
29
+ - `<wc-gallery>` no longer builds nav buttons or steps between images — the
30
+ nested `<wc-carousel>` does. It fires `gallery-open` (unchanged shape) and
31
+ re-emits the carousel's own stepping as `gallery-change`.
32
+ - `packages/core/src/web-components/utils/gallery.ts` dropped `keyToAction` and
33
+ `swipeAction` (the carousel's own key/swipe handling covers both now).
34
+ `stepIndex`/`preloadTargets` are unchanged.
35
+
36
+ **Why:** stepping used to close one `<dialog>` and open another, which made
37
+ `animation.css`'s top-layer driver play a full exit-then-entry transition on
38
+ every step — visible as a flicker on prev/next, by construction, not a bug to
39
+ tune away. Opening also awaited the full image's `decode()` before starting the
40
+ view-transition morph, so the dialog visibly stalled on a slow network. One
41
+ dialog containing one carousel makes the first failure mode unrepresentable
42
+ (stepping is a scroll, not a close/open pair) and removes the wait for the
43
+ second (the morph starts immediately, painting the thumbnail as a CSS
44
+ background placeholder until the full image arrives).
45
+
46
+ **Also improved, not just fixed:** the no-JS fallback is no longer a _stripped_
47
+ lightbox — it's a genuine one. Each trigger is ordinary fragment navigation
48
+ (`:has(:target)` in `lightbox.css` reveals the dialog), which needs no Invoker
49
+ Commands polyfill in any engine, and it now has working prev/next with no
50
+ JavaScript at all — the previous per-dialog fallback had no way to express that.
51
+
52
+ **Migration:** a consumer using `<Gallery />` needs no changes — the component's
53
+ props are unchanged. Anyone who hand-authored `.lightbox-dialog` markup (per
54
+ `docs/concepts/patterns.md` / `docs/css/classes.md`) must move to the new single-
55
+ dialog-wrapping-a-carousel shape; see `patterns.astro`'s "Gallery, hand-authored"
56
+ demo for the reference markup. `<wc-gallery>` consumers listening for
57
+ `gallery-change` keep the same event shape (`{ index, total }`).
58
+
59
+ ### Minor Changes
60
+
61
+ - Add Google Business Profile reviews: fetch, cache, render.
62
+
63
+ - **`vitops reviews`** (new CLI command) fetches a client's GBP reviews (legacy v4 API — the only
64
+ one that has them) and writes them to `.vitops/reviews.json`, meant to be committed so a build
65
+ never needs a live Google credential. `--dry` prints the plan; `--check` diffs against the cache
66
+ without writing. Requires the same `VITOPS_GOOGLE_CLIENT_ID`/`_CLIENT_SECRET`/`_REFRESH_TOKEN` (or
67
+ ADC login) `search setup` uses, scoped to `business.manage` — **and the calling GCP project must
68
+ be allowlisted by Google first**, a separate one-time approval from every other Google API here.
69
+ - **`site.reviews`** (config): which `organization.locations` to fetch, and per-location
70
+ `featured`/`minRating`/`sort`/`limit` selection. `schema` (JSON-LD) and `avatars` both default to
71
+ **off** — see the migration notes below.
72
+ - **`@getvitops/utils/reviews`** (new subpath): the pure plan/select/merge functions plus the GBP
73
+ fetcher and cache reader/writer, mirroring `./indexing`'s pure/IO split.
74
+ - **`<ReviewCard>`** (new Astro component, `@getvitops/astro`): one review card from a cache entry.
75
+ No web component — nothing here needs progressive enhancement. Composes the existing
76
+ `schemas/Review.astro` for JSON-LD only when both `schema` and `itemReviewed` are passed.
77
+ - **`<Marquee>`** (new Astro component): the tier-3 wrapper `wc-marquee`/`marquee.css` was missing.
78
+ - **`.review` pattern** (`css`/`bricks` and `tailwind` formats): a new config-generated
79
+ `patterns.items.review` entry plus `packages/core/css/patterns/review.css` for the structural
80
+ parts (rating, identity, body, reply, source link). Two new semantic icon names, `star` and
81
+ `star-half`, across every icon set.
82
+
83
+ **Migration:** no breaking change. A site adding `site.reviews` should read the "Google reviews"
84
+ section in AGENTS.md before enabling `schema` — Google's structured-data policy treats a business
85
+ marking up reviews of itself as ineligible for review rich results and risks a manual action, which
86
+ is why it defaults off.
87
+
88
+ - Repo-wide simplification pass: de-boilerplate the CLI, dedupe shared cache/plan
89
+ primitives in `@getvitops/utils`, drop dead code, and tighten dependency hygiene.
90
+
91
+ No breaking changes. (`vitops icons`'s `--site` flag was briefly going to be renamed to
92
+ `--input` for consistency with the other `Config`-anchored commands — deferred rather than
93
+ spending a major bump on a rename with no other breaking change riding along; it stays
94
+ `--site` for now.)
95
+
96
+ **Fixed:**
97
+
98
+ - `@getvitops/core`'s 12 runtime deps (`lit`, both `@oddbird` polyfills, both
99
+ `@webcomponents` packages, `colorjs.io`, etc.) were listed as `dependencies` despite
100
+ being bundled into `dist/elements.js`/`dist/polyfills.js`/`dist/deferred.js` — a
101
+ consumer installed them twice for nothing. Moved to `devDependencies`; no change to
102
+ what ships.
103
+ - Deleted `old-css-lib/` (59 files), superseded by `packages/core/css/` since the
104
+ in-memory bundling change — no consumer-facing effect, it was not part of any
105
+ published output.
106
+ - Deleted a dead Astro module (`packages/astro/src/scripts/deferred.ts`) that had
107
+ silently diverged from `packages/core/src/js/deferred.ts` and had zero importers.
108
+
109
+ **No consumer-facing change in `@getvitops/vite`** beyond the fixed-group version bump —
110
+ task-graph and caching fixes internal to this repo's own build.
111
+
112
+ Everything else (the `cli.ts` file split into `commands/{search,ads}.ts`, shared
113
+ `json-store.ts`/`plan-format.ts` helpers in `@getvitops/utils`, a `.github/actions/setup`
114
+ composite action, restatement-comment cleanup) is internal refactoring with no change to
115
+ any published API, CLI flag, or generated output.
116
+
117
+ ### Patch Changes
118
+
119
+ - Updated dependencies
120
+ - Updated dependencies
121
+ - Updated dependencies
122
+ - Updated dependencies [a84839b]
123
+ - @getvitops/core@8.0.0
124
+ - @getvitops/generator@8.0.0
125
+ - @getvitops/utils@8.0.0
126
+ - @getvitops/vite@8.0.0
127
+
3
128
  ## 7.0.0
4
129
 
5
130
  ### Major Changes
@@ -719,28 +844,20 @@ hidden` would pull it out of the accessible-name computation along with the visu
719
844
  {
720
845
  "designSystem": {
721
846
  "themes": {
722
- "default": {
723
- /* … */
724
- },
847
+ "default": {/* … */},
725
848
  },
726
849
  },
727
850
  "organization": {
728
851
  "name": "Acme",
729
852
  "contact": "hq",
730
853
  "locations": {
731
- "hq": {
732
- /* … */
733
- },
854
+ "hq": {/* … */},
734
855
  },
735
856
  },
736
857
  "site": {
737
858
  "defaultLocale": "en",
738
- "domains": {
739
- /* … */
740
- },
741
- "analytics": {
742
- /* … */
743
- },
859
+ "domains": {/* … */},
860
+ "analytics": {/* … */},
744
861
  },
745
862
  }
746
863
  ```
@@ -909,7 +1026,7 @@ open-fade-in"` composes slide and fade. Applied at zero specificity with identit
909
1026
  Also new, and worth wiring at the same time — **`gitLastmod()` for real sitemap dates**:
910
1027
 
911
1028
  ```js
912
- import vitops, { gitLastmod } from '@getvitops/astro';
1029
+ import vitops, { gitLastmod } from "@getvitops/astro";
913
1030
  vitops({ sitemap: { serialize: await gitLastmod() } });
914
1031
  ```
915
1032
 
@@ -1009,8 +1126,8 @@ ffmpeg`, `apt install ffmpeg`, `winget install Gyan.FFmpeg`). The command fails
1009
1126
 
1010
1127
  ```js
1011
1128
  vitops({
1012
- analytics: { googleAnalytics: 'G-XXXXXXXXXX', plausible: 'acme.com' },
1013
- consent: { policyUrl: '/legal/cookies' },
1129
+ analytics: { googleAnalytics: "G-XXXXXXXXXX", plausible: "acme.com" },
1130
+ consent: { policyUrl: "/legal/cookies" },
1014
1131
  });
1015
1132
  ```
1016
1133
 
@@ -1150,7 +1267,7 @@ inset(0 100% 0 0)`, and `clip-path` clips **hit-testing** as well as painting
1150
1267
 
1151
1268
  ```js
1152
1269
  // astro.config.mjs
1153
- getvitops({ css: { input: 'company.json', format: 'css' } });
1270
+ getvitops({ css: { input: "company.json", format: "css" } });
1154
1271
  ```
1155
1272
 
1156
1273
  ```
@@ -1249,11 +1366,11 @@ inset(0 100% 0 0)`, and `clip-path` clips **hit-testing** as well as painting
1249
1366
  getvitops({
1250
1367
  fonts: [
1251
1368
  {
1252
- name: 'League Spartan',
1253
- provider: 'fontsource',
1254
- cssVariable: '--font-league-spartan',
1255
- weights: ['100 900'],
1256
- subsets: ['latin'],
1369
+ name: "League Spartan",
1370
+ provider: "fontsource",
1371
+ cssVariable: "--font-league-spartan",
1372
+ weights: ["100 900"],
1373
+ subsets: ["latin"],
1257
1374
  preload: true,
1258
1375
  },
1259
1376
  ],
@@ -1481,14 +1598,14 @@ inset(0 100% 0 0)`, and `clip-path` clips **hit-testing** as well as painting
1481
1598
  // astro.config.mjs
1482
1599
  vitops({
1483
1600
  seo: {
1484
- siteName: 'Acme',
1485
- titleTemplate: '%s · Acme',
1486
- defaultDescription: 'We make the thing.',
1601
+ siteName: "Acme",
1602
+ titleTemplate: "%s · Acme",
1603
+ defaultDescription: "We make the thing.",
1487
1604
  openGraph: {
1488
- locale: 'en_CA',
1489
- image: { url: '/og.png', alt: 'Acme', width: 1200, height: 630 },
1605
+ locale: "en_CA",
1606
+ image: { url: "/og.png", alt: "Acme", width: 1200, height: 630 },
1490
1607
  },
1491
- twitter: { site: '@acme' },
1608
+ twitter: { site: "@acme" },
1492
1609
  },
1493
1610
  });
1494
1611
  ```
@@ -1532,7 +1649,7 @@ inset(0 100% 0 0)`, and `clip-path` clips **hit-testing** as well as painting
1532
1649
 
1533
1650
  ```js
1534
1651
  getvitops({ sitemap: true });
1535
- getvitops({ sitemap: { filter: (page) => !page.includes('/draft/') } });
1652
+ getvitops({ sitemap: { filter: (page) => !page.includes("/draft/") } });
1536
1653
  ```
1537
1654
 
1538
1655
  `@astrojs/sitemap` is an **optional peer** — install it yourself (`pnpm add -D @astrojs/sitemap`) and
@@ -1767,15 +1884,15 @@ inset(0 100% 0 0)`, and `clip-path` clips **hit-testing** as well as painting
1767
1884
  which `@getvitops/astro` re-exports wholesale. So from `astro.config.mjs`:
1768
1885
 
1769
1886
  ```js
1770
- import { generateIconInclude } from '@getvitops/astro';
1771
- import icon from 'astro-icon';
1887
+ import { generateIconInclude } from "@getvitops/astro";
1888
+ import icon from "astro-icon";
1772
1889
 
1773
1890
  integrations: [
1774
1891
  icon({
1775
1892
  include: generateIconInclude({
1776
- ui: 'fa7-solid',
1777
- brand: 'simple-icons',
1778
- semantic: ['menu', 'close', 'search', 'github'],
1893
+ ui: "fa7-solid",
1894
+ brand: "simple-icons",
1895
+ semantic: ["menu", "close", "search", "github"],
1779
1896
  }),
1780
1897
  }),
1781
1898
  ];
@@ -1809,7 +1926,7 @@ inset(0 100% 0 0)`, and `clip-path` clips **hit-testing** as well as painting
1809
1926
  ```js
1810
1927
  // astro.config.mjs
1811
1928
  getvitops({
1812
- css: { input: 'design-system.json', format: 'css', out: 'src/styles' },
1929
+ css: { input: "design-system.json", format: "css", out: "src/styles" },
1813
1930
  editor: true,
1814
1931
  });
1815
1932
  ```
package/dist/index.mjs CHANGED
@@ -2,7 +2,7 @@ import { n as TRACKING_ENDPOINT, r as resolveTracking, t as TRACKING_COOKIE } fr
2
2
  import { cpSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
3
3
  import { dirname, join, relative, resolve } from "node:path";
4
4
  import { fileURLToPath } from "node:url";
5
- import { isConfig, resolveConfig } from "@getvitops/generator";
5
+ import { isConfig, renderRobotsTxt, resolveConfig } from "@getvitops/generator";
6
6
  import { collectIconRefs, faviconLinks, generateFavicons, generateIconInclude, resolveIcon, scanFiles, writeFaviconManifest } from "@getvitops/utils";
7
7
  import vitopsPlugin from "@getvitops/vite";
8
8
  import { AD_PLATFORMS, AD_PROVIDER_KEYS } from "@getvitops/utils/ads";
@@ -672,14 +672,21 @@ function vitops(opts = {}) {
672
672
  }
673
673
  }
674
674
  if (siteInput) try {
675
- const key = resolveConfig(JSON.parse(readFileSync(resolve(root, siteInput), "utf8")), opts.site?.siteEnv ?? "production").site.seo?.indexing?.indexNow?.key;
675
+ const cfg = resolveConfig(JSON.parse(readFileSync(resolve(root, siteInput), "utf8")), opts.site?.siteEnv ?? "production");
676
+ const key = cfg.site.seo?.indexing?.indexNow?.key;
676
677
  if (key) {
677
678
  mkdirSync(publicDir, { recursive: true });
678
679
  writeFileSync(join(publicDir, `${key}.txt`), `${key}\n`);
679
680
  logger.info(`IndexNow key file → public/${key}.txt`);
680
681
  }
682
+ const robotsPath = join(publicDir, "robots.txt");
683
+ if (!existsSync(robotsPath)) {
684
+ mkdirSync(publicDir, { recursive: true });
685
+ writeFileSync(robotsPath, renderRobotsTxt(cfg, { env: opts.site?.siteEnv ?? "production" }));
686
+ logger.info("robots.txt → public/robots.txt");
687
+ }
681
688
  } catch (err) {
682
- logger.warn(`IndexNow key file skipped: ${err.message}`);
689
+ logger.warn(`IndexNow key file / robots.txt skipped: ${err.message}`);
683
690
  }
684
691
  let iconsData = null;
685
692
  if (opts.icons) {