@crossworks/content-core 0.239.35 → 0.239.37

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crossworks/content-core",
3
- "version": "0.239.35",
3
+ "version": "0.239.37",
4
4
  "description": "Browser-safe content logic — markdown, blocks, pages, tables, formulas — shared by the server and any client. Zero server deps by design: nothing here may reach @mantle/db, node-only APIs, or the network (the jackdaw-repo-split P0 boundary).",
5
5
  "exports": {
6
6
  "./app-nav": "./src/app-nav.ts",
@@ -33,7 +33,7 @@
33
33
  "./tree": "./src/tree.ts"
34
34
  },
35
35
  "dependencies": {
36
- "@mantle/client-types": "npm:@crossworks/client-types@0.239.35",
36
+ "@mantle/client-types": "npm:@crossworks/client-types@0.239.37",
37
37
  "marked": "^18.0.11",
38
38
  "mathjs": "15.2.0"
39
39
  },
@@ -0,0 +1,86 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import {
3
+ DEFAULT_PREFERENCES,
4
+ FRESH_APPEARANCE,
5
+ projectNeatBackground,
6
+ readAvatarStyle,
7
+ readColorTheme,
8
+ readNeatBackground,
9
+ } from './profile-projections';
10
+
11
+ /**
12
+ * The fresh-install look: a brain that never chose wears the Jackdaw theme,
13
+ * Lorelei avatars and the Neat background. A brain that DID choose keeps its
14
+ * choice, and "off" for the background is a choice too.
15
+ */
16
+ describe('FRESH_APPEARANCE', () => {
17
+ it('is the Jackdaw theme, Lorelei avatars and a valid Neat spec', () => {
18
+ expect(FRESH_APPEARANCE.colorTheme).toBe('jackdaw');
19
+ expect(FRESH_APPEARANCE.avatarStyle).toBe('lorelei');
20
+ // Survives the same projection a stored value goes through.
21
+ expect(projectNeatBackground(FRESH_APPEARANCE.neatBackground)).toBe(
22
+ FRESH_APPEARANCE.neatBackground,
23
+ );
24
+ expect(JSON.parse(FRESH_APPEARANCE.neatBackground)).toEqual({
25
+ v: 1,
26
+ seed: 55361,
27
+ tone: 'auto',
28
+ speed: 2,
29
+ });
30
+ });
31
+
32
+ it('is seeded into a new profile row', () => {
33
+ expect(DEFAULT_PREFERENCES.colorTheme).toBe(FRESH_APPEARANCE.colorTheme);
34
+ expect(DEFAULT_PREFERENCES.avatarStyle).toBe(FRESH_APPEARANCE.avatarStyle);
35
+ expect(DEFAULT_PREFERENCES.neatBackground).toBe(FRESH_APPEARANCE.neatBackground);
36
+ });
37
+ });
38
+
39
+ describe('readColorTheme', () => {
40
+ it('defaults an unset theme', () => {
41
+ expect(readColorTheme(undefined)).toBe('jackdaw');
42
+ expect(readColorTheme(null)).toBe('jackdaw');
43
+ expect(readColorTheme('')).toBe('jackdaw');
44
+ expect(readColorTheme('not a slug!')).toBe('jackdaw');
45
+ });
46
+
47
+ it('keeps a chosen theme, the old baseline included', () => {
48
+ expect(readColorTheme('clean-slate')).toBe('clean-slate');
49
+ expect(readColorTheme('darkmatter')).toBe('darkmatter');
50
+ });
51
+ });
52
+
53
+ describe('readAvatarStyle', () => {
54
+ it('defaults an unset style', () => {
55
+ expect(readAvatarStyle(undefined)).toBe('lorelei');
56
+ expect(readAvatarStyle('')).toBe('lorelei');
57
+ });
58
+
59
+ it('keeps a chosen style, the old default included', () => {
60
+ expect(readAvatarStyle('thumbs')).toBe('thumbs');
61
+ // Legacy ids survive storage; the web layer translates them on render.
62
+ expect(readAvatarStyle('beam')).toBe('beam');
63
+ });
64
+ });
65
+
66
+ describe('readNeatBackground', () => {
67
+ it('switches the background on for a brain that never set it', () => {
68
+ expect(readNeatBackground(undefined)).toBe(FRESH_APPEARANCE.neatBackground);
69
+ expect(readNeatBackground(null)).toBe(FRESH_APPEARANCE.neatBackground);
70
+ });
71
+
72
+ it('keeps an explicit OFF off', () => {
73
+ // '' is what the neat-background route stores for "off".
74
+ expect(readNeatBackground('')).toBeUndefined();
75
+ });
76
+
77
+ it('keeps a chosen spec', () => {
78
+ const mine = '{"v":1,"seed":7,"tone":"darker","speed":0}';
79
+ expect(readNeatBackground(mine)).toBe(mine);
80
+ });
81
+
82
+ it('reads garbage as off, never as the default', () => {
83
+ expect(readNeatBackground('{"v":2}')).toBeUndefined();
84
+ expect(readNeatBackground(42)).toBeUndefined();
85
+ });
86
+ });
@@ -30,6 +30,7 @@ import {
30
30
  thinkingEffortForBudget,
31
31
  type ThinkingEffort,
32
32
  } from './thinking-tiers';
33
+ import { FRESH_APPEARANCE } from '@mantle/client-types/fresh-appearance';
33
34
  import {
34
35
  APP_OPENS_MAX,
35
36
  APP_PINS_MAX,
@@ -538,10 +539,39 @@ export const DEFAULT_HOUSE_STYLE =
538
539
  'ranges (2020\u20132024, pages 10\u201314) are correct and stay, and hyphens in compound ' +
539
540
  'words (self-hosted, read-only) are unaffected.';
540
541
 
542
+ /** The fresh-install look (Jackdaw theme, Lorelei avatars, Neat on), shared
543
+ * with the clients from @mantle/client-types. Re-exported so brain code reads
544
+ * it from here like every other preference default. */
545
+ export { FRESH_APPEARANCE };
546
+
547
+ /** Read a stored `colorTheme` with the fresh-install default: any value that
548
+ * does not project (unset, empty, garbage) reads as the default theme. */
549
+ export function readColorTheme(raw: unknown): string {
550
+ return projectColorTheme(raw) ?? FRESH_APPEARANCE.colorTheme;
551
+ }
552
+
553
+ /** Read a stored `avatarStyle` with the fresh-install default, the
554
+ * readColorTheme contract. */
555
+ export function readAvatarStyle(raw: unknown): string {
556
+ return projectAvatarStyle(raw) ?? FRESH_APPEARANCE.avatarStyle;
557
+ }
558
+
559
+ /** Read a stored `neatBackground` with the fresh-install default. Only an
560
+ * ABSENT key takes it: '' is the deliberate "off" the neat-background route
561
+ * writes, so it must keep reading as off (undefined), never flip back on. */
562
+ export function readNeatBackground(raw: unknown): string | undefined {
563
+ if (raw === undefined || raw === null) return FRESH_APPEARANCE.neatBackground;
564
+ return projectNeatBackground(raw);
565
+ }
566
+
541
567
  export const DEFAULT_PREFERENCES: ProfilePreferences = {
542
568
  timezone: 'UTC',
543
569
  locale: 'en-GB',
544
570
  houseStyle: DEFAULT_HOUSE_STYLE,
571
+ // The fresh-install look, seeded so a new brain stores what it shows.
572
+ colorTheme: FRESH_APPEARANCE.colorTheme,
573
+ avatarStyle: FRESH_APPEARANCE.avatarStyle,
574
+ neatBackground: FRESH_APPEARANCE.neatBackground,
545
575
  // Live thinking on (streamThoughts defaults on) at Medium: the 4096 tier of
546
576
  // THINKING_TIERS. Unset would mean no thinking at all.
547
577
  thinkingBudget: 4096,