@scalemule/news-publication 0.0.67 → 0.0.68
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/README.md +12 -0
- package/dist/article-presentation-0d1FiDgA.d.cts +21 -0
- package/dist/article-presentation-0d1FiDgA.d.ts +21 -0
- package/dist/article-workflow-client.cjs +265 -0
- package/dist/article-workflow-client.d.cts +131 -0
- package/dist/article-workflow-client.d.ts +131 -0
- package/dist/article-workflow-client.js +262 -0
- package/dist/{chunk-OISLCYER.js → chunk-DN3TBZLK.js} +37 -1
- package/dist/index.cjs +39 -0
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +3 -3
- package/dist/story-review.cjs +176 -115
- package/dist/story-review.d.cts +71 -2
- package/dist/story-review.d.ts +71 -2
- package/dist/story-review.js +146 -117
- package/package.json +7 -2
- package/story-review.css +5 -0
package/dist/story-review.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { parseDocumentBlocks, formatArtworkCaption } from './chunk-
|
|
2
|
+
import { articlePresentation, articleFormatLabel, parseDocumentBlocks, formatArtworkCaption } from './chunk-DN3TBZLK.js';
|
|
3
3
|
import { useState, useRef, useEffect } from 'react';
|
|
4
|
-
import {
|
|
4
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
5
5
|
|
|
6
6
|
var stable = (value) => Array.isArray(value) ? value.map(stable) : value && typeof value === "object" ? Object.fromEntries(Object.keys(value).sort().map((k) => [k, stable(value[k])])) : value;
|
|
7
7
|
var same = (a, b) => JSON.stringify(stable(a)) === JSON.stringify(stable(b));
|
|
@@ -329,10 +329,12 @@ function StoryReview({
|
|
|
329
329
|
publicationFooter,
|
|
330
330
|
readerAccountUrl,
|
|
331
331
|
renderSignIn,
|
|
332
|
-
feedbackEmail
|
|
332
|
+
feedbackEmail,
|
|
333
|
+
initialReview,
|
|
334
|
+
onReviewLoaded
|
|
333
335
|
}) {
|
|
334
336
|
const base = `/api/news/review/${encodeURIComponent(sessionId)}`;
|
|
335
|
-
const [review, setReview] = useState(null), [error, setError] = useState(""), [notice, setNotice] = useState(""), [busy, setBusy] = useState(false), [panel, setPanelState] = useState("article"), [verification, setVerification] = useState(false), [code, setCode] = useState("");
|
|
337
|
+
const [review, setReview] = useState(initialReview ?? null), [error, setError] = useState(""), [notice, setNotice] = useState(""), [busy, setBusy] = useState(false), [panel, setPanelState] = useState("article"), [verification, setVerification] = useState(false), [code, setCode] = useState("");
|
|
336
338
|
const [shareUrl, setShareUrl] = useState(""), [canShare, setCanShare] = useState(false);
|
|
337
339
|
const [contributorName, setContributorName] = useState(""), [contributorEmail, setContributorEmail] = useState("");
|
|
338
340
|
const [identityStep, setIdentityStep] = useState("name"), [requestedPanel, setRequestedPanel] = useState("comment");
|
|
@@ -387,6 +389,9 @@ function StoryReview({
|
|
|
387
389
|
const responseRef = useRef(null);
|
|
388
390
|
const thanksRef = useRef(null);
|
|
389
391
|
const [moreQuestions, setMoreQuestions] = useState(false);
|
|
392
|
+
useEffect(() => {
|
|
393
|
+
if (review) onReviewLoaded?.(review);
|
|
394
|
+
}, [review, onReviewLoaded]);
|
|
390
395
|
const [replacementPhoto, setReplacementPhoto] = useState(null);
|
|
391
396
|
const photoToReplace = pendingPhoto.photo?.replacement || replacementPhoto;
|
|
392
397
|
function openMedia(photo = null) {
|
|
@@ -507,7 +512,7 @@ function StoryReview({
|
|
|
507
512
|
const token = new URL(window.location.href).searchParams.get("key") || (/^[a-f0-9]{64}$/.test(window.location.hash.slice(1)) ? window.location.hash.slice(1) : void 0);
|
|
508
513
|
let exchange = {};
|
|
509
514
|
try {
|
|
510
|
-
exchange = await request("/session", token ? { token } : {});
|
|
515
|
+
exchange = await request("/session", { ...token ? { token } : {}, include_review: true });
|
|
511
516
|
} catch (e) {
|
|
512
517
|
if (token) throw e;
|
|
513
518
|
}
|
|
@@ -524,7 +529,7 @@ function StoryReview({
|
|
|
524
529
|
}
|
|
525
530
|
}
|
|
526
531
|
}
|
|
527
|
-
const data = await request();
|
|
532
|
+
const data = exchange.review ?? await request();
|
|
528
533
|
if (active) {
|
|
529
534
|
if (data.verification_required) {
|
|
530
535
|
setVerification(true);
|
|
@@ -691,10 +696,33 @@ function StoryReview({
|
|
|
691
696
|
/* @__PURE__ */ jsx("a", { href: emailLink, children: "Email the newsroom" }),
|
|
692
697
|
". Your email app will open; send your message there."
|
|
693
698
|
] });
|
|
699
|
+
const presentation = articlePresentation(review?.presentation);
|
|
700
|
+
const formatLabel = articleFormatLabel(presentation.format);
|
|
701
|
+
const sourceHero = review?.revision.document.media.filter((m) => m.position === "hero").map((m) => /* @__PURE__ */ jsx(
|
|
702
|
+
PrivatePhoto,
|
|
703
|
+
{
|
|
704
|
+
media: m,
|
|
705
|
+
base,
|
|
706
|
+
onChange: can("UPLOAD_MEDIA") ? () => openMedia(m) : void 0,
|
|
707
|
+
onSuggestCorrection: can("REQUEST_CHANGES") ? () => openCorrection(m) : void 0,
|
|
708
|
+
disabled: busy
|
|
709
|
+
},
|
|
710
|
+
m.file_id
|
|
711
|
+
));
|
|
712
|
+
const generated = review?.generated_visual;
|
|
713
|
+
const hero = sourceHero?.length ? sourceHero : generated && /^https:\/\//.test(generated.url) ? /* @__PURE__ */ jsxs("figure", { children: [
|
|
714
|
+
/* @__PURE__ */ jsx("img", { src: generated.url, alt: generated.alt || review?.revision.document.title || "Article illustration" }),
|
|
715
|
+
/* @__PURE__ */ jsxs("figcaption", { children: [
|
|
716
|
+
generated.caption,
|
|
717
|
+
" ",
|
|
718
|
+
generated.label
|
|
719
|
+
] })
|
|
720
|
+
] }) : null;
|
|
721
|
+
const heroBeforeHeadline = presentation.layout.headline_position === "after_hero";
|
|
694
722
|
return /* @__PURE__ */ jsxs("div", { className: `sm-review-frame${publicationHeader ? " sm-review-publication-frame" : ""}`, children: [
|
|
695
723
|
/* @__PURE__ */ jsx("div", { className: "sm-review-banner-wrap", children: /* @__PURE__ */ jsxs("div", { className: "sm-review-private", children: [
|
|
696
|
-
/* @__PURE__ */ jsx("strong", { children: review?.published ? "Private review" : "Private preview \xB7 Not published" }),
|
|
697
|
-
/* @__PURE__ */ jsx("span", { children: review?.published ? "This revision has been published. This review link remains private." : `Prepared by ${publicationName} for ${celebration ? "family " : ""}review.` })
|
|
724
|
+
/* @__PURE__ */ jsx("strong", { children: review?.article_published || review?.published ? "Private review" : "Private preview \xB7 Not published" }),
|
|
725
|
+
/* @__PURE__ */ jsx("span", { children: review?.published ? "This revision has been published. This review link remains private." : review?.article_published ? "The article is published. This private link preserves the version you were invited to review." : `Prepared by ${publicationName} for ${celebration ? "family " : ""}review.` })
|
|
698
726
|
] }) }),
|
|
699
727
|
publicationHeader ?? /* @__PURE__ */ jsx("div", { className: "sm-review-brand-wrap", children: /* @__PURE__ */ jsxs("header", { className: "sm-review-masthead", children: [
|
|
700
728
|
nameplateUrl && /* @__PURE__ */ jsx("img", { src: nameplateUrl, alt: "", width: 80, height: 80 }),
|
|
@@ -841,117 +869,118 @@ function StoryReview({
|
|
|
841
869
|
"newsroom for final editorial review. It has not been published yet."
|
|
842
870
|
] })
|
|
843
871
|
] }),
|
|
844
|
-
/* @__PURE__ */ jsxs(
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
]
|
|
877
|
-
}
|
|
878
|
-
),
|
|
879
|
-
(() => {
|
|
880
|
-
const blocks = parseDocumentBlocks({
|
|
881
|
-
content_markdown: review.revision.document.content_markdown,
|
|
882
|
-
media: review.revision.document.media,
|
|
883
|
-
blocks: review.revision.document.blocks
|
|
884
|
-
});
|
|
885
|
-
const mediaMap = /* @__PURE__ */ new Map();
|
|
886
|
-
for (const m of review.revision.document.media) {
|
|
887
|
-
mediaMap.set(m.file_id, m);
|
|
888
|
-
if (m.contribution_id) mediaMap.set(m.contribution_id, m);
|
|
889
|
-
}
|
|
890
|
-
return /* @__PURE__ */ jsx("div", { className: "sm-review-prose", children: blocks.length === 0 && review.revision.content_html ? /* @__PURE__ */ jsx("div", { dangerouslySetInnerHTML: { __html: review.revision.content_html } }) : blocks.map((block, idx) => {
|
|
891
|
-
switch (block.type) {
|
|
892
|
-
case "paragraph":
|
|
893
|
-
return /* @__PURE__ */ jsx(
|
|
894
|
-
"p",
|
|
895
|
-
{
|
|
896
|
-
dangerouslySetInnerHTML: { __html: block.html }
|
|
897
|
-
},
|
|
898
|
-
idx
|
|
899
|
-
);
|
|
900
|
-
case "heading": {
|
|
901
|
-
if (block.level === 1)
|
|
902
|
-
return /* @__PURE__ */ jsx("h1", { dangerouslySetInnerHTML: { __html: block.html } }, idx);
|
|
903
|
-
if (block.level === 2)
|
|
904
|
-
return /* @__PURE__ */ jsx("h2", { dangerouslySetInnerHTML: { __html: block.html } }, idx);
|
|
905
|
-
if (block.level === 3)
|
|
906
|
-
return /* @__PURE__ */ jsx("h3", { dangerouslySetInnerHTML: { __html: block.html } }, idx);
|
|
907
|
-
if (block.level === 4)
|
|
908
|
-
return /* @__PURE__ */ jsx("h4", { dangerouslySetInnerHTML: { __html: block.html } }, idx);
|
|
909
|
-
if (block.level === 5)
|
|
910
|
-
return /* @__PURE__ */ jsx("h5", { dangerouslySetInnerHTML: { __html: block.html } }, idx);
|
|
911
|
-
return /* @__PURE__ */ jsx("h6", { dangerouslySetInnerHTML: { __html: block.html } }, idx);
|
|
872
|
+
/* @__PURE__ */ jsxs(
|
|
873
|
+
"article",
|
|
874
|
+
{
|
|
875
|
+
className: "sm-review-article",
|
|
876
|
+
"data-article-layout": presentation.layout.renderer,
|
|
877
|
+
"data-wide-body": presentation.layout.wide_body,
|
|
878
|
+
"data-hero-aspect": presentation.layout.hero_aspect,
|
|
879
|
+
children: [
|
|
880
|
+
heroBeforeHeadline && /* @__PURE__ */ jsx("div", { className: "sm-review-hero", children: hero }),
|
|
881
|
+
/* @__PURE__ */ jsxs("p", { className: "sm-review-category", children: [
|
|
882
|
+
/* @__PURE__ */ jsx("span", { children: review.revision.document.section }),
|
|
883
|
+
formatLabel && /* @__PURE__ */ jsx("span", { children: formatLabel }),
|
|
884
|
+
celebration && /* @__PURE__ */ jsx("span", { children: human(review.celebration_type || "") })
|
|
885
|
+
] }),
|
|
886
|
+
/* @__PURE__ */ jsx("h1", { children: review.revision.document.title }),
|
|
887
|
+
/* @__PURE__ */ jsx("p", { className: "sm-review-dek", children: review.revision.document.subtitle }),
|
|
888
|
+
/* @__PURE__ */ jsx(EditorialNotices, { editorial: review.revision.editorial }),
|
|
889
|
+
!heroBeforeHeadline && /* @__PURE__ */ jsx("div", { className: "sm-review-hero", children: hero }),
|
|
890
|
+
celebration && !review.revision.document.media.some(
|
|
891
|
+
(m) => m.position === "hero"
|
|
892
|
+
) && can("UPLOAD_MEDIA") && /* @__PURE__ */ jsxs(
|
|
893
|
+
"aside",
|
|
894
|
+
{
|
|
895
|
+
className: "sm-review-photo-invitation",
|
|
896
|
+
"aria-label": "Family photograph",
|
|
897
|
+
children: [
|
|
898
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
899
|
+
/* @__PURE__ */ jsx("strong", { children: "A photograph makes it yours." }),
|
|
900
|
+
/* @__PURE__ */ jsx("p", { children: "Family photograph may be added before publication." })
|
|
901
|
+
] }),
|
|
902
|
+
/* @__PURE__ */ jsx("button", { onClick: () => openMedia(), children: "+ Add a photograph" })
|
|
903
|
+
]
|
|
912
904
|
}
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
if (!m) return null;
|
|
925
|
-
return /* @__PURE__ */ jsx(
|
|
926
|
-
PrivatePhoto,
|
|
927
|
-
{
|
|
928
|
-
media: m,
|
|
929
|
-
base,
|
|
930
|
-
onChange: m.kind !== "video" && can("UPLOAD_MEDIA") ? () => openMedia(m) : void 0,
|
|
931
|
-
onSuggestCorrection: can("REQUEST_CHANGES") ? () => openCorrection(m) : void 0,
|
|
932
|
-
disabled: busy,
|
|
933
|
-
isInline: true
|
|
934
|
-
},
|
|
935
|
-
m.file_id
|
|
936
|
-
);
|
|
905
|
+
),
|
|
906
|
+
(() => {
|
|
907
|
+
const blocks = parseDocumentBlocks({
|
|
908
|
+
content_markdown: review.revision.document.content_markdown,
|
|
909
|
+
media: review.revision.document.media,
|
|
910
|
+
blocks: review.revision.document.blocks
|
|
911
|
+
});
|
|
912
|
+
const mediaMap = /* @__PURE__ */ new Map();
|
|
913
|
+
for (const m of review.revision.document.media) {
|
|
914
|
+
mediaMap.set(m.file_id, m);
|
|
915
|
+
if (m.contribution_id) mediaMap.set(m.contribution_id, m);
|
|
937
916
|
}
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
917
|
+
return /* @__PURE__ */ jsx("div", { className: "sm-review-prose", children: blocks.length === 0 && review.revision.content_html ? /* @__PURE__ */ jsx("div", { dangerouslySetInnerHTML: { __html: review.revision.content_html } }) : blocks.map((block, idx) => {
|
|
918
|
+
switch (block.type) {
|
|
919
|
+
case "paragraph":
|
|
920
|
+
return /* @__PURE__ */ jsx(
|
|
921
|
+
"p",
|
|
922
|
+
{
|
|
923
|
+
dangerouslySetInnerHTML: { __html: block.html }
|
|
924
|
+
},
|
|
925
|
+
idx
|
|
926
|
+
);
|
|
927
|
+
case "heading": {
|
|
928
|
+
if (block.level === 1)
|
|
929
|
+
return /* @__PURE__ */ jsx("h1", { dangerouslySetInnerHTML: { __html: block.html } }, idx);
|
|
930
|
+
if (block.level === 2)
|
|
931
|
+
return /* @__PURE__ */ jsx("h2", { dangerouslySetInnerHTML: { __html: block.html } }, idx);
|
|
932
|
+
if (block.level === 3)
|
|
933
|
+
return /* @__PURE__ */ jsx("h3", { dangerouslySetInnerHTML: { __html: block.html } }, idx);
|
|
934
|
+
if (block.level === 4)
|
|
935
|
+
return /* @__PURE__ */ jsx("h4", { dangerouslySetInnerHTML: { __html: block.html } }, idx);
|
|
936
|
+
if (block.level === 5)
|
|
937
|
+
return /* @__PURE__ */ jsx("h5", { dangerouslySetInnerHTML: { __html: block.html } }, idx);
|
|
938
|
+
return /* @__PURE__ */ jsx("h6", { dangerouslySetInnerHTML: { __html: block.html } }, idx);
|
|
939
|
+
}
|
|
940
|
+
case "quote":
|
|
941
|
+
return /* @__PURE__ */ jsxs("blockquote", { children: [
|
|
942
|
+
/* @__PURE__ */ jsx("p", { dangerouslySetInnerHTML: { __html: block.html } }),
|
|
943
|
+
block.attribution && /* @__PURE__ */ jsx("cite", { children: block.attribution })
|
|
944
|
+
] }, idx);
|
|
945
|
+
case "list":
|
|
946
|
+
return block.ordered ? /* @__PURE__ */ jsx("ol", { children: block.items.map((it, i) => /* @__PURE__ */ jsx("li", { dangerouslySetInnerHTML: { __html: it } }, i)) }, idx) : /* @__PURE__ */ jsx("ul", { children: block.items.map((it, i) => /* @__PURE__ */ jsx("li", { dangerouslySetInnerHTML: { __html: it } }, i)) }, idx);
|
|
947
|
+
case "divider":
|
|
948
|
+
return /* @__PURE__ */ jsx("hr", {}, idx);
|
|
949
|
+
case "inline_media": {
|
|
950
|
+
const m = mediaMap.get(block.media_id);
|
|
951
|
+
if (!m) return null;
|
|
952
|
+
return /* @__PURE__ */ jsx(
|
|
953
|
+
PrivatePhoto,
|
|
954
|
+
{
|
|
955
|
+
media: m,
|
|
956
|
+
base,
|
|
957
|
+
onChange: m.kind !== "video" && can("UPLOAD_MEDIA") ? () => openMedia(m) : void 0,
|
|
958
|
+
onSuggestCorrection: can("REQUEST_CHANGES") ? () => openCorrection(m) : void 0,
|
|
959
|
+
disabled: busy,
|
|
960
|
+
isInline: true
|
|
961
|
+
},
|
|
962
|
+
m.file_id
|
|
963
|
+
);
|
|
964
|
+
}
|
|
965
|
+
default:
|
|
966
|
+
return null;
|
|
967
|
+
}
|
|
968
|
+
}) });
|
|
969
|
+
})(),
|
|
970
|
+
review.revision.document.media.filter((m) => m.position === "gallery").map((m) => /* @__PURE__ */ jsx(
|
|
971
|
+
PrivatePhoto,
|
|
972
|
+
{
|
|
973
|
+
media: m,
|
|
974
|
+
base,
|
|
975
|
+
onChange: m.kind !== "video" && can("UPLOAD_MEDIA") ? () => openMedia(m) : void 0,
|
|
976
|
+
onSuggestCorrection: can("REQUEST_CHANGES") ? () => openCorrection(m) : void 0,
|
|
977
|
+
disabled: busy
|
|
978
|
+
},
|
|
979
|
+
m.file_id
|
|
980
|
+
))
|
|
981
|
+
]
|
|
982
|
+
}
|
|
983
|
+
),
|
|
955
984
|
celebration && /* @__PURE__ */ jsxs("section", { id: "review-options", className: "sm-review-welcome", children: [
|
|
956
985
|
/* @__PURE__ */ jsx("h2", { children: "Help us make this just right" }),
|
|
957
986
|
/* @__PURE__ */ jsxs("p", { children: [
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@scalemule/news-publication",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.68",
|
|
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",
|
|
@@ -179,7 +179,12 @@
|
|
|
179
179
|
"import": "./dist/toys-server.js",
|
|
180
180
|
"require": "./dist/toys-server.cjs"
|
|
181
181
|
},
|
|
182
|
-
"./toys.css": "./toys.css"
|
|
182
|
+
"./toys.css": "./toys.css",
|
|
183
|
+
"./article-workflow": {
|
|
184
|
+
"types": "./dist/article-workflow-client.d.ts",
|
|
185
|
+
"import": "./dist/article-workflow-client.js",
|
|
186
|
+
"require": "./dist/article-workflow-client.cjs"
|
|
187
|
+
}
|
|
183
188
|
},
|
|
184
189
|
"files": [
|
|
185
190
|
"dist",
|
package/story-review.css
CHANGED
|
@@ -809,3 +809,8 @@
|
|
|
809
809
|
padding: 20px 16px max(20px, env(safe-area-inset-bottom));
|
|
810
810
|
}
|
|
811
811
|
}
|
|
812
|
+
|
|
813
|
+
/* The same finite layout vocabulary is used by public and private readers. */
|
|
814
|
+
.sm-review-article[data-wide-body="true"] { max-width: 900px; }
|
|
815
|
+
.sm-review-article[data-hero-aspect="portrait"] .sm-review-hero img { aspect-ratio: 4 / 5; object-fit: contain; max-height: 80vh; }
|
|
816
|
+
.sm-review-article[data-hero-aspect="square"] .sm-review-hero img { aspect-ratio: 1; object-fit: contain; }
|