@cratis/cast 0.1.0 → 0.2.0

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 (56) hide show
  1. package/README.md +3 -1
  2. package/badges/RegistryMember.ts +2 -0
  3. package/badges/registry.ts +5 -0
  4. package/cast-json.schema.json +1496 -0
  5. package/config/calendar.ts +34 -0
  6. package/config/castSchema.ts +3 -2
  7. package/github/gitHubSnapshotSchema.ts +58 -0
  8. package/machine/castJson.ts +17 -4
  9. package/machine/castJsonSchema.ts +35 -0
  10. package/machine/index.ts +6 -0
  11. package/machine/profileFromCastJson.ts +214 -0
  12. package/package.json +5 -1
  13. package/routes/404.astro +6 -4
  14. package/routes/cast.json.ts +7 -1
  15. package/routes/cv.astro +3 -365
  16. package/routes/index.astro +3 -55
  17. package/site/components/Activity.astro +8 -6
  18. package/site/components/Agentic.astro +11 -10
  19. package/site/components/CareerReplay.astro +11 -8
  20. package/site/components/CommandPalette.astro +10 -4
  21. package/site/components/Contact.astro +8 -5
  22. package/site/components/Cratis.astro +17 -15
  23. package/site/components/EventModel.astro +8 -5
  24. package/site/components/Footer.astro +9 -4
  25. package/site/components/Hero.astro +13 -10
  26. package/site/components/Inline.astro +45 -0
  27. package/site/components/Monogram.astro +4 -1
  28. package/site/components/Nav.astro +12 -9
  29. package/site/components/Now.astro +13 -10
  30. package/site/components/Projects.astro +11 -14
  31. package/site/components/PullRequestFeed.astro +6 -4
  32. package/site/components/SectionHeader.astro +6 -3
  33. package/site/components/Skills.astro +5 -2
  34. package/site/components/Stats.astro +7 -2
  35. package/site/components/Talks.astro +8 -5
  36. package/site/components/Terminal.astro +7 -2
  37. package/site/components/Writing.astro +9 -7
  38. package/site/data.ts +6 -43
  39. package/site/layouts/Base.astro +31 -19
  40. package/site/lib/blog.ts +42 -16
  41. package/site/lib/github.ts +48 -31
  42. package/site/lib/inline.ts +65 -9
  43. package/site/lib/nav.ts +14 -3
  44. package/site/pages/CvPage.astro +379 -0
  45. package/site/pages/ProfilePage.astro +78 -0
  46. package/site/profile/CastHost.ts +32 -0
  47. package/site/profile/CastView.ts +96 -0
  48. package/site/profile/assertRenderable.ts +151 -0
  49. package/site/profile/clientCast.ts +117 -0
  50. package/site/profile/index.ts +8 -0
  51. package/site/scripts/live.ts +21 -11
  52. package/site/scripts/palette.ts +30 -13
  53. package/site/scripts/replay.ts +2 -1
  54. package/site/scripts/terminal.ts +28 -25
  55. package/writing/fetchWriting.ts +17 -2
  56. package/writing/writingSnapshotSchema.ts +27 -0
@@ -5,6 +5,7 @@ import type { z } from 'zod';
5
5
  import type { writingSourceSchema } from '../config/castSchema';
6
6
  import { mergePosts, parseFeed, parseStarlightAuthorPage } from './parse';
7
7
  import type { Post, WritingSnapshot } from './WritingSnapshot';
8
+ import { postSchema, writingLimits } from './writingSnapshotSchema';
8
9
 
9
10
  type WritingSource = z.output<typeof writingSourceSchema>;
10
11
  const maximumPages = 10;
@@ -49,6 +50,20 @@ export async function fetchWriting(sources: readonly WritingSource[], warn: (mes
49
50
  warn(`writing source ${'rss' in source ? source.rss : source.starlightBlogAuthor}: ${error instanceof Error ? error.message : String(error)}`);
50
51
  }
51
52
  }
52
- if (posts.length === 0) return undefined;
53
- return { fetchedAt: new Date().toISOString(), sources: origins, posts: mergePosts(posts) };
53
+ const kept = withinLimits(posts);
54
+ if (kept.length === 0) return undefined;
55
+ return { fetchedAt: new Date().toISOString(), sources: origins.slice(0, writingLimits.sources), posts: kept };
56
+ }
57
+
58
+ /** Newest posts first, trimmed to the limits a reader of cast.json enforces; posts that would still fail them are left out. */
59
+ export function withinLimits(posts: readonly Post[]): Post[] {
60
+ return mergePosts(posts)
61
+ .map(post => ({
62
+ ...post,
63
+ title: post.title.slice(0, writingLimits.title),
64
+ description: post.description.slice(0, writingLimits.description),
65
+ tags: post.tags.map(tag => tag.slice(0, writingLimits.tag)).slice(0, writingLimits.tags),
66
+ }))
67
+ .filter(post => postSchema.safeParse(post).success)
68
+ .slice(0, writingLimits.posts);
54
69
  }
@@ -0,0 +1,27 @@
1
+ // Copyright (c) Cratis. All rights reserved.
2
+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
+
4
+ import { z } from 'zod';
5
+ import { isInstant } from '../config/calendar';
6
+
7
+ const instant = z.string().max(64).refine(isInstant, 'Use an ISO 8601 date and time on a real day');
8
+
9
+ /** The most a writing capture holds; the build that writes one keeps to the same limits. */
10
+ export const writingLimits = { sources: 20, posts: 300, title: 300, description: 2000, tags: 30, tag: 100 } as const;
11
+
12
+ /** One captured post. */
13
+ export const postSchema = z.object({
14
+ title: z.string().min(1).max(writingLimits.title),
15
+ url: z.url({ protocol: /^https?$/ }),
16
+ date: z.string().max(64).regex(/^\d{4}-\d{2}-\d{2}/, 'Start with YYYY-MM-DD').refine(isInstant, 'Use an ISO 8601 date on a real day'),
17
+ minutes: z.number().min(0).max(10_000).optional(),
18
+ description: z.string().max(writingLimits.description).default(''),
19
+ tags: z.array(z.string().max(writingLimits.tag)).max(writingLimits.tags).default([]),
20
+ });
21
+
22
+ /** Writing captured from feeds, as it appears in cast.json. */
23
+ export const writingSnapshotSchema = z.object({
24
+ fetchedAt: instant.optional(),
25
+ sources: z.array(z.url({ protocol: /^https?$/ })).max(writingLimits.sources).default([]),
26
+ posts: z.array(postSchema).max(writingLimits.posts).default([]),
27
+ });