@anthusai/papyrus 1.0.0-next.2 → 1.0.0-next.3

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.
Files changed (42) hide show
  1. package/amplify/data/resource.js +26 -0
  2. package/amplify/data/resource.ts +30 -0
  3. package/amplify/data/schema.js +26 -0
  4. package/amplify/data/schema.ts +30 -0
  5. package/amplify/functions/content-actions/handler.py +107 -0
  6. package/amplify/functions/content-actions/requirements.txt +4 -0
  7. package/amplify/functions/content-actions/resource.js +40 -0
  8. package/amplify/functions/content-actions/resource.ts +54 -0
  9. package/amplify/functions/shared/python-bundle.js +17 -2
  10. package/amplify/functions/shared/python-bundle.ts +23 -2
  11. package/amplify/site-backend.js +10 -0
  12. package/amplify/site-backend.ts +15 -0
  13. package/app/[year]/[month]/[day]/[articleSlug]/page.tsx +2 -2
  14. package/app/globals.css +1 -4
  15. package/app/layout.tsx +4 -12
  16. package/components/news-desk-page.tsx +1 -4
  17. package/lib/content-actions-client.ts +98 -0
  18. package/lib/empty-theme.css +1 -0
  19. package/lib/layout-scenarios.ts +8 -8
  20. package/lib/site-brand-tenant.ts +3 -22
  21. package/lib/site-brand.ts +44 -42
  22. package/middleware.ts +10 -35
  23. package/package.json +2 -1
  24. package/renderers/pretext/article-page.tsx +1 -6
  25. package/renderers/pretext/presentation-shell.tsx +2 -9
  26. package/routes.manifest.json +1 -1
  27. package/src/with-papyrus.mjs +15 -2
  28. package/publications/anth_us/brand.ts +0 -68
  29. package/publications/anth_us/theme.css +0 -66
  30. package/publications/pilobol_us/brand.ts +0 -37
  31. package/publications/pilobol_us/theme.css +0 -140
  32. package/publications/threat_intelligence/blog-defense/graph.ts +0 -636
  33. package/publications/threat_intelligence/blog-defense/layout.ts +0 -934
  34. package/publications/threat_intelligence/blog-defense/page-background.tsx +0 -590
  35. package/publications/threat_intelligence/brand.ts +0 -40
  36. package/publications/threat_intelligence/pictograms/art.tsx +0 -608
  37. package/publications/threat_intelligence/pictograms/figure.tsx +0 -82
  38. package/publications/threat_intelligence/pictograms/registry.ts +0 -30
  39. package/publications/threat_intelligence/pictograms/system.tsx +0 -305
  40. package/publications/threat_intelligence/seed/seed-edition-content.json +0 -629
  41. package/publications/threat_intelligence/theme.css +0 -1440
  42. /package/{publications/papyrus/theme.css → app/papyrus-theme.css} +0 -0
@@ -1,30 +0,0 @@
1
- export const PICTOGRAM_CYCLE_MS = 20_000;
2
- export const PICTOGRAM_NODE_RADIUS = 4.75;
3
- export const PICTOGRAM_EDGE_WIDTH = 2.5;
4
-
5
- export const THREAT_INTELLIGENCE_PICTOGRAM_PHASE_OFFSETS = {
6
- hero: 1_400,
7
- "the-balance-of-power-is-shifting": 0,
8
- "how-our-newsroom-learns": 2_600,
9
- "audit-aws-exposure-before-attackers-do": 5_000,
10
- "audit-azure-blast-radius-before-attackers-do": 7_500,
11
- "treat-openai-accounts-like-production-infrastructure": 10_000,
12
- "how-to-play-games-securely": 12_500,
13
- } as const;
14
-
15
- export type ThreatIntelligencePictogramSlug = Exclude<
16
- keyof typeof THREAT_INTELLIGENCE_PICTOGRAM_PHASE_OFFSETS,
17
- "hero"
18
- >;
19
-
20
- export const THREAT_INTELLIGENCE_PICTOGRAM_SLUGS = Object.keys(THREAT_INTELLIGENCE_PICTOGRAM_PHASE_OFFSETS).filter(
21
- (key): key is ThreatIntelligencePictogramSlug => key !== "hero",
22
- );
23
-
24
- export function isThreatIntelligencePictogramSlug(slug: string): slug is ThreatIntelligencePictogramSlug {
25
- return THREAT_INTELLIGENCE_PICTOGRAM_SLUGS.includes(slug as ThreatIntelligencePictogramSlug);
26
- }
27
-
28
- export function getThreatIntelligencePictogramPhaseOffset(slug: ThreatIntelligencePictogramSlug): number {
29
- return THREAT_INTELLIGENCE_PICTOGRAM_PHASE_OFFSETS[slug];
30
- }
@@ -1,305 +0,0 @@
1
- "use client";
2
-
3
- import { motion, useReducedMotion } from "motion/react";
4
- import { useEffect, useMemo, useState, type CSSProperties, type ReactNode } from "react";
5
- import { PICTOGRAM_CYCLE_MS, PICTOGRAM_EDGE_WIDTH, PICTOGRAM_NODE_RADIUS } from "./registry";
6
-
7
- export type PictogramPalette = {
8
- frame: string;
9
- edge: string;
10
- node: string;
11
- muted: string;
12
- accent: string;
13
- accentSoft: string;
14
- accentGlow: string;
15
- safe: string;
16
- warning: string;
17
- barrier: string;
18
- };
19
-
20
- export const PICTOGRAM_PALETTE: PictogramPalette = {
21
- frame: "var(--background)",
22
- edge: "var(--ti-pictogram-edge)",
23
- node: "var(--ti-pictogram-node)",
24
- muted: "var(--ti-pictogram-muted)",
25
- accent: "var(--ti-pictogram-compromised)",
26
- accentSoft: "var(--ti-pictogram-throb)",
27
- accentGlow: "var(--ti-pictogram-accent-glow)",
28
- safe: "var(--grass-8)",
29
- warning: "var(--amber-8)",
30
- barrier: "var(--sand-8)",
31
- };
32
-
33
- export type PictogramMotion = {
34
- cycleS: number;
35
- phase: number;
36
- prefersReducedMotion: boolean;
37
- delayS: (offsetMs?: number) => number;
38
- };
39
-
40
- export function usePictogramMotion(phaseOffsetMs: number): PictogramMotion {
41
- const prefersReducedMotion = useReducedMotion() ?? false;
42
- const [epochMs, setEpochMs] = useState(0);
43
-
44
- useEffect(() => {
45
- setEpochMs(Date.now() % PICTOGRAM_CYCLE_MS);
46
- }, []);
47
-
48
- return useMemo(() => {
49
- const cycleS = PICTOGRAM_CYCLE_MS / 1000;
50
- const phase = ((epochMs + phaseOffsetMs) % PICTOGRAM_CYCLE_MS) / PICTOGRAM_CYCLE_MS;
51
- return {
52
- cycleS,
53
- phase,
54
- prefersReducedMotion,
55
- delayS: (offsetMs = 0) =>
56
- prefersReducedMotion ? 0 : -(((epochMs + phaseOffsetMs + offsetMs) % PICTOGRAM_CYCLE_MS) / 1000),
57
- };
58
- }, [epochMs, phaseOffsetMs, prefersReducedMotion]);
59
- }
60
-
61
- export function PictogramFrame({
62
- aspectRatio = 1,
63
- children,
64
- }: {
65
- aspectRatio?: number;
66
- children: ReactNode;
67
- }) {
68
- return (
69
- <div className="pictogram-figure__frame" style={{ "--pictogram-aspect-ratio": String(aspectRatio) } as CSSProperties}>
70
- {children}
71
- </div>
72
- );
73
- }
74
-
75
- export function PictogramSvg({
76
- alt,
77
- children,
78
- viewBox = "0 0 320 220",
79
- }: {
80
- alt: string;
81
- children: ReactNode;
82
- viewBox?: string;
83
- }) {
84
- return (
85
- <svg aria-label={alt} className="pictogram-figure__svg" role="img" viewBox={viewBox}>
86
- <title>{alt}</title>
87
- {children}
88
- </svg>
89
- );
90
- }
91
-
92
- export function Line({
93
- d,
94
- palette,
95
- tone = "edge",
96
- width = PICTOGRAM_EDGE_WIDTH,
97
- opacity = 1,
98
- dashArray,
99
- dashOffset,
100
- }: {
101
- d: string;
102
- palette: PictogramPalette;
103
- tone?: "edge" | "muted" | "accent" | "safe" | "warning" | "barrier";
104
- width?: number;
105
- opacity?: number;
106
- dashArray?: string;
107
- dashOffset?: number;
108
- }) {
109
- return (
110
- <path
111
- d={d}
112
- fill="none"
113
- opacity={opacity}
114
- stroke={resolveTone(palette, tone)}
115
- strokeDasharray={dashArray}
116
- strokeDashoffset={dashOffset}
117
- strokeLinecap="round"
118
- strokeLinejoin="round"
119
- strokeWidth={width}
120
- />
121
- );
122
- }
123
-
124
- export function MotionLine({
125
- animate,
126
- d,
127
- palette,
128
- tone = "edge",
129
- transition,
130
- width = PICTOGRAM_EDGE_WIDTH,
131
- opacity = 1,
132
- dashArray,
133
- }: {
134
- animate: any;
135
- d: string;
136
- palette: PictogramPalette;
137
- tone?: "edge" | "muted" | "accent" | "safe" | "warning" | "barrier";
138
- transition: any;
139
- width?: number;
140
- opacity?: number;
141
- dashArray?: string;
142
- }) {
143
- return (
144
- <motion.path
145
- animate={animate}
146
- d={d}
147
- fill="none"
148
- initial={false}
149
- opacity={opacity}
150
- stroke={resolveTone(palette, tone)}
151
- strokeDasharray={dashArray}
152
- strokeLinecap="round"
153
- strokeLinejoin="round"
154
- strokeWidth={width}
155
- transition={transition}
156
- />
157
- );
158
- }
159
-
160
- export function Node({
161
- glow = false,
162
- palette,
163
- r = PICTOGRAM_NODE_RADIUS,
164
- tone = "node",
165
- x,
166
- y,
167
- }: {
168
- glow?: boolean;
169
- palette: PictogramPalette;
170
- r?: number;
171
- tone?: "node" | "muted" | "accent" | "safe" | "warning";
172
- x: number;
173
- y: number;
174
- }) {
175
- const fill = resolveNodeTone(palette, tone);
176
- return (
177
- <g>
178
- {glow ? <circle cx={x} cy={y} fill={palette.accentGlow} r={r * 2.4} /> : null}
179
- <circle cx={x} cy={y} fill={fill} r={r} />
180
- </g>
181
- );
182
- }
183
-
184
- export function MotionNode({
185
- animate,
186
- glow = false,
187
- palette,
188
- r = PICTOGRAM_NODE_RADIUS,
189
- tone = "node",
190
- transition,
191
- x,
192
- y,
193
- }: {
194
- animate: any;
195
- glow?: boolean;
196
- palette: PictogramPalette;
197
- r?: number;
198
- tone?: "node" | "muted" | "accent" | "safe" | "warning";
199
- transition: any;
200
- x: number;
201
- y: number;
202
- }) {
203
- const fill = resolveNodeTone(palette, tone);
204
- return (
205
- <g>
206
- {glow ? (
207
- <motion.circle animate={animate} cx={x} cy={y} fill={palette.accentGlow} initial={false} r={r * 2.4} transition={transition} />
208
- ) : null}
209
- <motion.circle animate={animate} cx={x} cy={y} fill={fill} initial={false} r={r} transition={transition} />
210
- </g>
211
- );
212
- }
213
-
214
- export function Box({
215
- fillOpacity = 0.08,
216
- height,
217
- palette,
218
- strokeTone = "edge",
219
- width,
220
- x,
221
- y,
222
- }: {
223
- fillOpacity?: number;
224
- height: number;
225
- palette: PictogramPalette;
226
- strokeTone?: "edge" | "muted" | "accent" | "safe" | "warning" | "barrier";
227
- width: number;
228
- x: number;
229
- y: number;
230
- }) {
231
- const stroke = resolveTone(palette, strokeTone);
232
- return (
233
- <rect
234
- fill={stroke}
235
- fillOpacity={fillOpacity}
236
- height={height}
237
- rx={14}
238
- stroke={stroke}
239
- strokeWidth={PICTOGRAM_EDGE_WIDTH}
240
- width={width}
241
- x={x}
242
- y={y}
243
- />
244
- );
245
- }
246
-
247
- export function arrowPath(x1: number, y1: number, x2: number, y2: number, arrowSize = 9): string {
248
- const dx = x2 - x1;
249
- const dy = y2 - y1;
250
- const length = Math.sqrt(dx * dx + dy * dy) || 1;
251
- const ux = dx / length;
252
- const uy = dy / length;
253
- const px = -uy;
254
- const py = ux;
255
- const bx = x2 - ux * arrowSize;
256
- const by = y2 - uy * arrowSize;
257
- const leftX = bx + px * (arrowSize * 0.55);
258
- const leftY = by + py * (arrowSize * 0.55);
259
- const rightX = bx - px * (arrowSize * 0.55);
260
- const rightY = by - py * (arrowSize * 0.55);
261
- return `M ${x1} ${y1} L ${x2} ${y2} M ${leftX} ${leftY} L ${x2} ${y2} L ${rightX} ${rightY}`;
262
- }
263
-
264
- export function pointsPath(points: Array<[number, number]>): string {
265
- return points.map(([x, y], index) => `${index === 0 ? "M" : "L"} ${x} ${y}`).join(" ");
266
- }
267
-
268
- export function ringNodes(cx: number, cy: number, radius: number, count: number, startAngle = -90): Array<[number, number]> {
269
- return Array.from({ length: count }, (_, index) => {
270
- const angle = ((startAngle + (360 / count) * index) * Math.PI) / 180;
271
- return [cx + Math.cos(angle) * radius, cy + Math.sin(angle) * radius];
272
- });
273
- }
274
-
275
- function resolveTone(palette: PictogramPalette, tone: "edge" | "muted" | "accent" | "safe" | "warning" | "barrier"): string {
276
- switch (tone) {
277
- case "muted":
278
- return palette.muted;
279
- case "accent":
280
- return palette.accent;
281
- case "safe":
282
- return palette.safe;
283
- case "warning":
284
- return palette.warning;
285
- case "barrier":
286
- return palette.barrier;
287
- default:
288
- return palette.edge;
289
- }
290
- }
291
-
292
- function resolveNodeTone(palette: PictogramPalette, tone: "node" | "muted" | "accent" | "safe" | "warning"): string {
293
- switch (tone) {
294
- case "muted":
295
- return palette.muted;
296
- case "accent":
297
- return palette.accent;
298
- case "safe":
299
- return palette.safe;
300
- case "warning":
301
- return palette.warning;
302
- default:
303
- return palette.node;
304
- }
305
- }