@scalemule/news-publication 0.0.57 → 0.0.59

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.
@@ -512,9 +512,28 @@ function SponsorAcknowledgment2({
512
512
  /* @__PURE__ */ jsx("small", { children: "Paid community sponsorship. Sponsorship does not influence editorial selections and is not an endorsement." })
513
513
  ] });
514
514
  }
515
+ var DEFAULT_COVER = {
516
+ url: "https://cdn-public.scalemule.com/01a1382e-6aff-7091-a757-12433a04eed1/anonymous/photos/01a13b52-a168-7131-90f6-a216dbe8dc3b/w800_h0_scaledown_q85_webp.webp",
517
+ alt: "A white Labrador retriever resting on a sunlit lawn",
518
+ credit: "Boyko Mihaylov"
519
+ };
520
+ function safeCoverUrl(url) {
521
+ if (!url || !/^https:\/\/[^\s"\\]+$/.test(url)) return null;
522
+ try {
523
+ return new URL(url).protocol === "https:" ? url : null;
524
+ } catch {
525
+ return null;
526
+ }
527
+ }
528
+ function resolveCover(cover) {
529
+ if (!cover || !safeCoverUrl(cover.url) || !cover.alt || !cover.credit)
530
+ return DEFAULT_COVER;
531
+ return cover;
532
+ }
515
533
  function PetsSection({
516
534
  name = "Bay Area Paw",
517
535
  tagline = "Happier pets. Closer communities.",
536
+ coverPhoto,
518
537
  community,
519
538
  communities,
520
539
  resources,
@@ -533,6 +552,8 @@ function PetsSection({
533
552
  eventsUrl,
534
553
  accountUrl
535
554
  }) {
555
+ const cover = resolveCover(coverPhoto);
556
+ const coverCreditUrl = safeCoverUrl(cover.credit_url);
536
557
  const location = community?.name || regionLabel || "the Bay Area";
537
558
  const link = (id) => `${resourceBasePath || basePath}/${encodeURIComponent(id)}`;
538
559
  const local = (id) => communities.find((c) => c.id === id)?.name || "Our community";
@@ -636,10 +657,15 @@ function PetsSection({
636
657
  "div",
637
658
  {
638
659
  role: "img",
639
- "aria-label": "A white Labrador retriever resting on a sunlit lawn"
660
+ "aria-label": cover.alt,
661
+ style: { backgroundImage: `url("${cover.url}")` }
640
662
  }
641
663
  ),
642
- /* @__PURE__ */ jsx("figcaption", { children: "Cover photograph by Boyko Mihaylov" })
664
+ /* @__PURE__ */ jsxs("figcaption", { children: [
665
+ "Cover photograph by",
666
+ " ",
667
+ coverCreditUrl ? /* @__PURE__ */ jsx("a", { href: coverCreditUrl, rel: "noopener noreferrer", children: cover.credit }) : cover.credit
668
+ ] })
643
669
  ] })
644
670
  ] }),
645
671
  !unavailable && /* @__PURE__ */ jsxs("nav", { className: "paw-shortcuts", "aria-label": "Useful pet resources", children: [
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import { PawMark } from './chunk-3HPE2Y7V.js';
2
+ import { PawMark } from './chunk-7HXSQY4T.js';
3
3
  import './chunk-4JRWZXAP.js';
4
4
  import './chunk-66GI2IX6.js';
5
5
  import { PET_PHOTO_CATEGORIES, PET_CELEBRATIONS, PET_SAFETY } from './chunk-AFJ6S5WJ.js';
@@ -1,4 +1,4 @@
1
- import { LostPetNotice, PetCelebrationCard, AdoptionListingCard, PetEventCard, PetProfileCard, PawMark } from './chunk-3HPE2Y7V.js';
1
+ import { LostPetNotice, PetCelebrationCard, AdoptionListingCard, PetEventCard, PetProfileCard, PawMark } from './chunk-7HXSQY4T.js';
2
2
  import './chunk-4JRWZXAP.js';
3
3
  import './chunk-66GI2IX6.js';
4
4
  import { petRequest } from './chunk-ABPJMDUG.js';
@@ -479,9 +479,28 @@ function SponsorAcknowledgment2({
479
479
  /* @__PURE__ */ jsxRuntime.jsx("small", { children: "Paid community sponsorship. Sponsorship does not influence editorial selections and is not an endorsement." })
480
480
  ] });
481
481
  }
482
+ var DEFAULT_COVER = {
483
+ url: "https://cdn-public.scalemule.com/01a1382e-6aff-7091-a757-12433a04eed1/anonymous/photos/01a13b52-a168-7131-90f6-a216dbe8dc3b/w800_h0_scaledown_q85_webp.webp",
484
+ alt: "A white Labrador retriever resting on a sunlit lawn",
485
+ credit: "Boyko Mihaylov"
486
+ };
487
+ function safeCoverUrl(url) {
488
+ if (!url || !/^https:\/\/[^\s"\\]+$/.test(url)) return null;
489
+ try {
490
+ return new URL(url).protocol === "https:" ? url : null;
491
+ } catch {
492
+ return null;
493
+ }
494
+ }
495
+ function resolveCover(cover) {
496
+ if (!cover || !safeCoverUrl(cover.url) || !cover.alt || !cover.credit)
497
+ return DEFAULT_COVER;
498
+ return cover;
499
+ }
482
500
  function PetsSection({
483
501
  name = "Bay Area Paw",
484
502
  tagline = "Happier pets. Closer communities.",
503
+ coverPhoto,
485
504
  community,
486
505
  communities,
487
506
  resources,
@@ -500,6 +519,8 @@ function PetsSection({
500
519
  eventsUrl,
501
520
  accountUrl
502
521
  }) {
522
+ const cover = resolveCover(coverPhoto);
523
+ const coverCreditUrl = safeCoverUrl(cover.credit_url);
503
524
  const location = community?.name || regionLabel || "the Bay Area";
504
525
  const link = (id) => `${resourceBasePath || basePath}/${encodeURIComponent(id)}`;
505
526
  const local = (id) => communities.find((c) => c.id === id)?.name || "Our community";
@@ -603,10 +624,15 @@ function PetsSection({
603
624
  "div",
604
625
  {
605
626
  role: "img",
606
- "aria-label": "A white Labrador retriever resting on a sunlit lawn"
627
+ "aria-label": cover.alt,
628
+ style: { backgroundImage: `url("${cover.url}")` }
607
629
  }
608
630
  ),
609
- /* @__PURE__ */ jsxRuntime.jsx("figcaption", { children: "Cover photograph by Boyko Mihaylov" })
631
+ /* @__PURE__ */ jsxRuntime.jsxs("figcaption", { children: [
632
+ "Cover photograph by",
633
+ " ",
634
+ coverCreditUrl ? /* @__PURE__ */ jsxRuntime.jsx("a", { href: coverCreditUrl, rel: "noopener noreferrer", children: cover.credit }) : cover.credit
635
+ ] })
610
636
  ] })
611
637
  ] }),
612
638
  !unavailable && /* @__PURE__ */ jsxRuntime.jsxs("nav", { className: "paw-shortcuts", "aria-label": "Useful pet resources", children: [
@@ -900,6 +926,7 @@ async function PublicationPetsSection({
900
926
  PetsSection,
901
927
  {
902
928
  basePath: "/pets",
929
+ coverPhoto: collection.config?.presentation?.cover_photo,
903
930
  regionLabel: region,
904
931
  resourceBasePath: native ? "/pets" : canonicalOrigin + "/pets",
905
932
  accountUrl: native ? "/pets/account" : void 0,
@@ -1,4 +1,4 @@
1
- import { PetsSection, PawOfTheWeekCard, AdoptionListingCard, PetEventCard, PetCelebrationCard, LostPetNotice, PetProfileCard } from './chunk-3HPE2Y7V.js';
1
+ import { PetsSection, PawOfTheWeekCard, AdoptionListingCard, PetEventCard, PetCelebrationCard, LostPetNotice, PetProfileCard } from './chunk-7HXSQY4T.js';
2
2
  import './chunk-4JRWZXAP.js';
3
3
  import './chunk-66GI2IX6.js';
4
4
  import { petRequest, petAcknowledgments, resolvePetReferences } from './chunk-ABPJMDUG.js';
@@ -92,6 +92,7 @@ async function PublicationPetsSection({
92
92
  PetsSection,
93
93
  {
94
94
  basePath: "/pets",
95
+ coverPhoto: collection.config?.presentation?.cover_photo,
95
96
  regionLabel: region,
96
97
  resourceBasePath: native ? "/pets" : canonicalOrigin + "/pets",
97
98
  accountUrl: native ? "/pets/account" : void 0,
@@ -602,9 +602,28 @@ function SponsorAcknowledgment2({
602
602
  /* @__PURE__ */ jsxRuntime.jsx("small", { children: "Paid community sponsorship. Sponsorship does not influence editorial selections and is not an endorsement." })
603
603
  ] });
604
604
  }
605
+ var DEFAULT_COVER = {
606
+ url: "https://cdn-public.scalemule.com/01a1382e-6aff-7091-a757-12433a04eed1/anonymous/photos/01a13b52-a168-7131-90f6-a216dbe8dc3b/w800_h0_scaledown_q85_webp.webp",
607
+ alt: "A white Labrador retriever resting on a sunlit lawn",
608
+ credit: "Boyko Mihaylov"
609
+ };
610
+ function safeCoverUrl(url) {
611
+ if (!url || !/^https:\/\/[^\s"\\]+$/.test(url)) return null;
612
+ try {
613
+ return new URL(url).protocol === "https:" ? url : null;
614
+ } catch {
615
+ return null;
616
+ }
617
+ }
618
+ function resolveCover(cover) {
619
+ if (!cover || !safeCoverUrl(cover.url) || !cover.alt || !cover.credit)
620
+ return DEFAULT_COVER;
621
+ return cover;
622
+ }
605
623
  function PetsSection({
606
624
  name = "Bay Area Paw",
607
625
  tagline = "Happier pets. Closer communities.",
626
+ coverPhoto,
608
627
  community,
609
628
  communities,
610
629
  resources,
@@ -623,6 +642,8 @@ function PetsSection({
623
642
  eventsUrl,
624
643
  accountUrl
625
644
  }) {
645
+ const cover = resolveCover(coverPhoto);
646
+ const coverCreditUrl = safeCoverUrl(cover.credit_url);
626
647
  const location = community?.name || regionLabel || "the Bay Area";
627
648
  const link = (id) => `${resourceBasePath || basePath}/${encodeURIComponent(id)}`;
628
649
  const local = (id) => communities.find((c) => c.id === id)?.name || "Our community";
@@ -726,10 +747,15 @@ function PetsSection({
726
747
  "div",
727
748
  {
728
749
  role: "img",
729
- "aria-label": "A white Labrador retriever resting on a sunlit lawn"
750
+ "aria-label": cover.alt,
751
+ style: { backgroundImage: `url("${cover.url}")` }
730
752
  }
731
753
  ),
732
- /* @__PURE__ */ jsxRuntime.jsx("figcaption", { children: "Cover photograph by Boyko Mihaylov" })
754
+ /* @__PURE__ */ jsxRuntime.jsxs("figcaption", { children: [
755
+ "Cover photograph by",
756
+ " ",
757
+ coverCreditUrl ? /* @__PURE__ */ jsxRuntime.jsx("a", { href: coverCreditUrl, rel: "noopener noreferrer", children: cover.credit }) : cover.credit
758
+ ] })
733
759
  ] })
734
760
  ] }),
735
761
  !unavailable && /* @__PURE__ */ jsxRuntime.jsxs("nav", { className: "paw-shortcuts", "aria-label": "Useful pet resources", children: [
@@ -35,9 +35,17 @@ declare function SponsorAcknowledgment({ acknowledgment, now, }: {
35
35
  acknowledgment: PublicAcknowledgment;
36
36
  now?: number;
37
37
  }): React__default.JSX.Element | null;
38
+ /** Collection-managed cover photograph (config.presentation.cover_photo). */
39
+ type PetCoverPhoto = {
40
+ url: string;
41
+ alt: string;
42
+ credit: string;
43
+ credit_url?: string | null;
44
+ };
38
45
  type PetsSectionProps = {
39
46
  name?: string;
40
47
  tagline?: string;
48
+ coverPhoto?: PetCoverPhoto | null;
41
49
  community?: PetCommunity;
42
50
  communities: PetCommunity[];
43
51
  resources: PetResource[];
@@ -56,6 +64,6 @@ type PetsSectionProps = {
56
64
  eventsUrl?: string;
57
65
  accountUrl?: string;
58
66
  };
59
- declare function PetsSection({ name, tagline, community, communities, resources, spotlight, acknowledgments, basePath, mediaUrl, contributeUrl, placesUrl, walksUrl, nextUrl, unavailable, regionLabel, resourceBasePath, browseBasePath, eventsUrl, accountUrl, }: PetsSectionProps): React__default.JSX.Element;
67
+ declare function PetsSection({ name, tagline, coverPhoto, community, communities, resources, spotlight, acknowledgments, basePath, mediaUrl, contributeUrl, placesUrl, walksUrl, nextUrl, unavailable, regionLabel, resourceBasePath, browseBasePath, eventsUrl, accountUrl, }: PetsSectionProps): React__default.JSX.Element;
60
68
 
61
- export { AdoptionListingCard, LostPetNotice, PawMark, PawNeighborhoodIllustration, PawOfTheWeekCard, PetCelebrationCard, PetEventCard, PetFriendlyPlaceCard, PetProfileCard, PetsSection, type PetsSectionProps, SponsorAcknowledgment };
69
+ export { AdoptionListingCard, LostPetNotice, PawMark, PawNeighborhoodIllustration, PawOfTheWeekCard, PetCelebrationCard, type PetCoverPhoto, PetEventCard, PetFriendlyPlaceCard, PetProfileCard, PetsSection, type PetsSectionProps, SponsorAcknowledgment };
@@ -35,9 +35,17 @@ declare function SponsorAcknowledgment({ acknowledgment, now, }: {
35
35
  acknowledgment: PublicAcknowledgment;
36
36
  now?: number;
37
37
  }): React__default.JSX.Element | null;
38
+ /** Collection-managed cover photograph (config.presentation.cover_photo). */
39
+ type PetCoverPhoto = {
40
+ url: string;
41
+ alt: string;
42
+ credit: string;
43
+ credit_url?: string | null;
44
+ };
38
45
  type PetsSectionProps = {
39
46
  name?: string;
40
47
  tagline?: string;
48
+ coverPhoto?: PetCoverPhoto | null;
41
49
  community?: PetCommunity;
42
50
  communities: PetCommunity[];
43
51
  resources: PetResource[];
@@ -56,6 +64,6 @@ type PetsSectionProps = {
56
64
  eventsUrl?: string;
57
65
  accountUrl?: string;
58
66
  };
59
- declare function PetsSection({ name, tagline, community, communities, resources, spotlight, acknowledgments, basePath, mediaUrl, contributeUrl, placesUrl, walksUrl, nextUrl, unavailable, regionLabel, resourceBasePath, browseBasePath, eventsUrl, accountUrl, }: PetsSectionProps): React__default.JSX.Element;
67
+ declare function PetsSection({ name, tagline, coverPhoto, community, communities, resources, spotlight, acknowledgments, basePath, mediaUrl, contributeUrl, placesUrl, walksUrl, nextUrl, unavailable, regionLabel, resourceBasePath, browseBasePath, eventsUrl, accountUrl, }: PetsSectionProps): React__default.JSX.Element;
60
68
 
61
- export { AdoptionListingCard, LostPetNotice, PawMark, PawNeighborhoodIllustration, PawOfTheWeekCard, PetCelebrationCard, PetEventCard, PetFriendlyPlaceCard, PetProfileCard, PetsSection, type PetsSectionProps, SponsorAcknowledgment };
69
+ export { AdoptionListingCard, LostPetNotice, PawMark, PawNeighborhoodIllustration, PawOfTheWeekCard, PetCelebrationCard, type PetCoverPhoto, PetEventCard, PetFriendlyPlaceCard, PetProfileCard, PetsSection, type PetsSectionProps, SponsorAcknowledgment };
package/dist/pets-view.js CHANGED
@@ -1,4 +1,4 @@
1
- export { AdoptionListingCard, LostPetNotice, PawMark, PawNeighborhoodIllustration, PawOfTheWeekCard, PetCelebrationCard, PetEventCard, PetFriendlyPlaceCard, PetProfileCard, PetsSection, SponsorAcknowledgment } from './chunk-3HPE2Y7V.js';
1
+ export { AdoptionListingCard, LostPetNotice, PawMark, PawNeighborhoodIllustration, PawOfTheWeekCard, PetCelebrationCard, PetEventCard, PetFriendlyPlaceCard, PetProfileCard, PetsSection, SponsorAcknowledgment } from './chunk-7HXSQY4T.js';
2
2
  import './chunk-4JRWZXAP.js';
3
3
  import './chunk-66GI2IX6.js';
4
4
  import './chunk-AFJ6S5WJ.js';
package/images/README.md CHANGED
@@ -4,8 +4,20 @@ Photograph: Boyko Mihaylov, “Jasper,” a white Labrador retriever resting on
4
4
  sunlit lawn. Supplied directly by the publisher on October 14, 2026 as
5
5
  `jasper.png`; used with the photographer's permission via the publisher.
6
6
 
7
+ The photograph is not stored in this repository or npm package. It is uploaded
8
+ to ScaleMule storage under the Bay Area Paw application as an
9
+ anonymous-visible, scan-gated object and delivered from the anonymous CDN with
10
+ photo-service `hero` renditions:
11
+
12
+ - storage file: `01a13b52-99ca-7c41-bd8b-61868d700678`
13
+ - photo manifest: `01a13b52-a168-7131-90f6-a216dbe8dc3b` (preset `hero`,
14
+ WebP 400w/800w)
15
+ - referenced from `pets.css` (`.paw-cover-photo`), 800w WebP rendition
16
+ - upload record: Bay Area Paw workspace `previews/editorial-cover-cdn.json`
17
+
7
18
  The photograph illustrates life with pets. It is not a Bay Area resident
8
19
  submission, an adoption listing, a featured winner or an endorsement. Keep the
9
- visible photographer credit. The WebP rendition is a portrait crop of the
10
- supplied image, optimized with cwebp (metadata stripped); no generative image
11
- editing was applied by this repository.
20
+ visible photographer credit in `src/pets-view.tsx`. The uploaded source is a
21
+ portrait crop of the supplied image; the platform pipeline strips metadata and
22
+ generates the optimized renditions. No generative image editing was applied by
23
+ this repository.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scalemule/news-publication",
3
- "version": "0.0.57",
3
+ "version": "0.0.59",
4
4
  "description": "Shared server framework for ScaleMule local news publications. Walnut Creek Times is the broadsheet default; each paper supplies its own identity and feature flags.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
package/pets.css CHANGED
@@ -1147,8 +1147,11 @@
1147
1147
  }
1148
1148
  .paw-cover-photo > div {
1149
1149
  height: 100%;
1150
- background: url("./images/paw-jasper-mobile.webp") center 57% / cover
1151
- no-repeat;
1150
+ /* The photograph is collection-managed content: the component sets
1151
+ background-image inline from config.presentation.cover_photo. */
1152
+ background-position: center 57%;
1153
+ background-size: cover;
1154
+ background-repeat: no-repeat;
1152
1155
  }
1153
1156
  .paw-cover-photo::after {
1154
1157
  content: "";
Binary file