@treeseed/core 0.8.19 → 0.9.4
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/dist/components/ui/shell/AppShell.astro +16 -4
- package/dist/components/ui/shell/BottomNav.astro +10 -3
- package/dist/components/ui/shell/RailNav.astro +10 -3
- package/dist/components/ui/shell/ShellIconLink.astro +30 -0
- package/dist/content-config.d.ts +1 -0
- package/dist/content.js +19 -2
- package/dist/dev.d.ts +10 -0
- package/dist/dev.js +283 -51
- package/dist/layouts/AuthoredEntryLayout.astro +136 -76
- package/dist/layouts/MainLayout.astro +2 -0
- package/dist/pages/decisions/[slug].astro +9 -1
- package/dist/pages/notes/[slug].astro +17 -4
- package/dist/pages/objectives/[slug].astro +4 -0
- package/dist/pages/proposals/[slug].astro +6 -0
- package/dist/pages/questions/[slug].astro +4 -0
- package/dist/scripts/build-dist.js +1 -1
- package/dist/scripts/dev-platform.js +23 -0
- package/dist/scripts/publish-package.js +5 -1
- package/dist/site.js +3 -0
- package/dist/styles/app-shell.css +26 -1
- package/dist/styles/theme.css +8 -8
- package/package.json +2 -2
|
@@ -9,16 +9,53 @@ type LocalContributor = {
|
|
|
9
9
|
};
|
|
10
10
|
};
|
|
11
11
|
|
|
12
|
+
type MetadataItem = {
|
|
13
|
+
label: string;
|
|
14
|
+
value?: unknown;
|
|
15
|
+
href?: string;
|
|
16
|
+
};
|
|
17
|
+
|
|
12
18
|
function entryTitle(entry: RuntimeReferenceEntry) {
|
|
13
19
|
return entry.data.title ?? entry.data.name ?? entry.id;
|
|
14
20
|
}
|
|
15
21
|
|
|
22
|
+
function displayValue(value: unknown) {
|
|
23
|
+
if (value instanceof Date) return value.toISOString().slice(0, 10);
|
|
24
|
+
if (Array.isArray(value)) return value.map((entry) => displayValue(entry)).filter(Boolean).join(', ');
|
|
25
|
+
if (typeof value === 'string') return value.trim();
|
|
26
|
+
if (typeof value === 'number' || typeof value === 'boolean') return String(value);
|
|
27
|
+
return '';
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function metadataItem(label: string, value: unknown, href?: string): MetadataItem | null {
|
|
31
|
+
const display = displayValue(value);
|
|
32
|
+
return display ? { label, value: display, href } : null;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function metadataKey(item: MetadataItem) {
|
|
36
|
+
return `${item.label.toLowerCase()}::${displayValue(item.value).toLowerCase()}::${item.href ?? ''}`;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function uniqueMetadata(items: MetadataItem[]) {
|
|
40
|
+
const seen = new Set<string>();
|
|
41
|
+
return items.filter((item) => {
|
|
42
|
+
const key = metadataKey(item);
|
|
43
|
+
if (seen.has(key)) return false;
|
|
44
|
+
seen.add(key);
|
|
45
|
+
return true;
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
|
|
16
49
|
const {
|
|
17
50
|
entry,
|
|
18
51
|
currentPath,
|
|
19
52
|
contributor,
|
|
53
|
+
contentTypeLabel = 'Content',
|
|
54
|
+
contentId,
|
|
55
|
+
collectionLabel,
|
|
20
56
|
metaLabel,
|
|
21
57
|
metaValue,
|
|
58
|
+
metadataItems = [],
|
|
22
59
|
relatedQuestions = [],
|
|
23
60
|
relatedObjectives = [],
|
|
24
61
|
relatedNotes = [],
|
|
@@ -35,11 +72,17 @@ const {
|
|
|
35
72
|
date: Date;
|
|
36
73
|
motivation?: string;
|
|
37
74
|
tags: string[];
|
|
75
|
+
canonicalRoute?: string;
|
|
76
|
+
author?: string;
|
|
38
77
|
};
|
|
39
78
|
currentPath: string;
|
|
40
79
|
contributor: LocalContributor | RuntimeReferenceEntry | undefined | null;
|
|
80
|
+
contentTypeLabel?: string;
|
|
81
|
+
contentId?: string;
|
|
82
|
+
collectionLabel?: string;
|
|
41
83
|
metaLabel?: string;
|
|
42
84
|
metaValue?: string;
|
|
85
|
+
metadataItems?: MetadataItem[];
|
|
43
86
|
relatedQuestions?: RuntimeReferenceEntry[];
|
|
44
87
|
relatedObjectives?: RuntimeReferenceEntry[];
|
|
45
88
|
relatedNotes?: RuntimeReferenceEntry[];
|
|
@@ -48,88 +91,105 @@ const {
|
|
|
48
91
|
relatedBooks?: RuntimeReferenceEntry[];
|
|
49
92
|
introText?: string;
|
|
50
93
|
};
|
|
94
|
+
|
|
95
|
+
const contributorName = contributor?.data.name ?? entry.author ?? '';
|
|
96
|
+
const normalizedTypeLabel = contentTypeLabel.trim() || 'Content';
|
|
97
|
+
const contentKind = displayValue(metaValue);
|
|
98
|
+
const recordMetadata = uniqueMetadata([
|
|
99
|
+
metadataItem('ID', contentId),
|
|
100
|
+
metadataItem('Collection', collectionLabel ?? (currentPath.replaceAll('/', '') || undefined)),
|
|
101
|
+
metadataItem(metaLabel ?? '', metaValue),
|
|
102
|
+
metadataItem('Route', entry.canonicalRoute, entry.canonicalRoute),
|
|
103
|
+
...metadataItems.map((item) => metadataItem(item.label, item.value, item.href)).filter(Boolean),
|
|
104
|
+
].filter(Boolean) as MetadataItem[]);
|
|
105
|
+
|
|
106
|
+
const relationSections = [
|
|
107
|
+
{ label: 'Questions', hrefBase: '/questions', items: relatedQuestions },
|
|
108
|
+
{ label: 'Objectives', hrefBase: '/objectives', items: relatedObjectives },
|
|
109
|
+
{ label: 'Notes', hrefBase: '/notes', items: relatedNotes },
|
|
110
|
+
{ label: 'Proposals', hrefBase: '/proposals', items: relatedProposals },
|
|
111
|
+
{ label: 'Decisions', hrefBase: '/decisions', items: relatedDecisions },
|
|
112
|
+
{ label: 'Books', hrefBase: '/books', items: relatedBooks },
|
|
113
|
+
].filter((section) => section.items.length > 0);
|
|
114
|
+
|
|
115
|
+
const relationCount = relationSections.reduce((total, section) => total + section.items.length, 0);
|
|
116
|
+
const plainIntroText = displayValue(introText ?? entry.motivation);
|
|
51
117
|
---
|
|
52
118
|
|
|
53
119
|
<MainLayout title={entry.title} description={entry.description} currentPath={currentPath}>
|
|
54
|
-
<article class="max-w-
|
|
55
|
-
<
|
|
56
|
-
<div class="
|
|
57
|
-
<
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
120
|
+
<article class="max-w-6xl space-y-8">
|
|
121
|
+
<header class="grid gap-6 border-b border-[color:var(--ts-color-border)] pb-7 lg:grid-cols-[minmax(0,1fr)_18rem]">
|
|
122
|
+
<div class="space-y-4">
|
|
123
|
+
<div class="flex flex-wrap items-center gap-2.5">
|
|
124
|
+
<p class="rounded-full border border-[color:var(--ts-color-border)] px-3 py-1 text-xs font-semibold uppercase text-[color:var(--ts-color-info-text)]">{normalizedTypeLabel}</p>
|
|
125
|
+
{contentKind && <p class="rounded-full bg-[color:var(--ts-color-surface-muted)] px-3 py-1 text-xs font-semibold uppercase text-[color:var(--ts-color-text-subtle)]">{contentKind}</p>}
|
|
126
|
+
<StatusBadge status={entry.status} />
|
|
127
|
+
<p class="text-sm font-medium text-[color:var(--ts-color-text-subtle)]">{entry.date.toISOString().slice(0, 10)}</p>
|
|
128
|
+
{contributorName && <p class="text-sm text-[color:var(--ts-color-text-subtle)]">{contributorName}</p>}
|
|
129
|
+
</div>
|
|
130
|
+
<h1 class="max-w-4xl font-serif text-4xl font-bold tracking-normal text-[color:var(--ts-color-text)] md:text-5xl">{entry.title}</h1>
|
|
131
|
+
<p class="max-w-3xl text-lg leading-8 text-[color:var(--ts-color-text-muted)] md:text-xl md:leading-9">{entry.summary}</p>
|
|
132
|
+
{plainIntroText && (
|
|
133
|
+
<div class="max-w-3xl border-l-2 border-[color:var(--ts-color-border-strong)] pl-4">
|
|
134
|
+
<p class="text-xs font-semibold uppercase tracking-[0.14em] text-[color:var(--ts-color-info-text)]">Why it matters</p>
|
|
135
|
+
<p class="mt-1 text-sm leading-7 text-[color:var(--ts-color-text-muted)]">{plainIntroText}</p>
|
|
136
|
+
</div>
|
|
137
|
+
)}
|
|
138
|
+
{entry.tags.length > 0 && (
|
|
139
|
+
<ul class="flex flex-wrap gap-2" aria-label="Tags">
|
|
140
|
+
{entry.tags.map((tag) => (
|
|
141
|
+
<li class="rounded-full bg-[color:var(--ts-color-surface-muted)] px-3 py-1 text-xs font-semibold uppercase text-[color:var(--ts-color-accent-strong)]">{tag}</li>
|
|
142
|
+
))}
|
|
143
|
+
</ul>
|
|
144
|
+
)}
|
|
61
145
|
</div>
|
|
62
|
-
<
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
146
|
+
<aside class="self-start border-l border-[color:var(--ts-color-border)] pl-5">
|
|
147
|
+
<div class="flex items-center justify-between gap-3 border-b border-[color:var(--ts-color-border)] pb-3">
|
|
148
|
+
<div>
|
|
149
|
+
<p class="text-xs font-semibold uppercase tracking-[0.14em] text-[color:var(--ts-color-info-text)]">Record</p>
|
|
150
|
+
<p class="mt-1 text-sm text-[color:var(--ts-color-text-muted)]">{relationCount} linked record{relationCount === 1 ? '' : 's'}</p>
|
|
151
|
+
</div>
|
|
152
|
+
</div>
|
|
153
|
+
<dl class="mt-2 text-sm">
|
|
154
|
+
{recordMetadata.map((item) => (
|
|
155
|
+
<div class="grid grid-cols-[5.75rem_minmax(0,1fr)] gap-3 py-2.5">
|
|
156
|
+
<dt class="text-[color:var(--ts-color-text-subtle)]">{item.label}</dt>
|
|
157
|
+
<dd class="min-w-0 break-words font-medium text-[color:var(--ts-color-text)]">
|
|
158
|
+
{item.href ? <a class="underline decoration-[color:var(--ts-color-border-strong)] underline-offset-4 hover:text-[color:var(--ts-color-accent-strong)]" href={item.href}>{displayValue(item.value)}</a> : displayValue(item.value)}
|
|
159
|
+
</dd>
|
|
160
|
+
</div>
|
|
161
|
+
))}
|
|
162
|
+
</dl>
|
|
163
|
+
</aside>
|
|
164
|
+
</header>
|
|
165
|
+
<div class="prose-karyon max-w-3xl">
|
|
70
166
|
<slot />
|
|
71
167
|
</div>
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
<div>
|
|
75
|
-
|
|
76
|
-
<
|
|
77
|
-
{relatedQuestions.map((question) => (
|
|
78
|
-
<li><a href={`/questions/${question.id}/`} class="hover:text-[color:var(--ts-color-text)]">{entryTitle(question)}</a></li>
|
|
79
|
-
))}
|
|
80
|
-
</ul>
|
|
81
|
-
</div>
|
|
82
|
-
)}
|
|
83
|
-
{relatedObjectives.length > 0 && (
|
|
84
|
-
<div>
|
|
85
|
-
<p class="text-sm font-semibold uppercase tracking-[0.14em] text-[color:var(--ts-color-info-text)]">Related objectives</p>
|
|
86
|
-
<ul class="mt-3 space-y-2 text-[color:var(--ts-color-text-muted)]">
|
|
87
|
-
{relatedObjectives.map((objective) => (
|
|
88
|
-
<li><a href={`/objectives/${objective.id}/`} class="hover:text-[color:var(--ts-color-text)]">{entryTitle(objective)}</a></li>
|
|
89
|
-
))}
|
|
90
|
-
</ul>
|
|
168
|
+
{relationSections.length > 0 && (
|
|
169
|
+
<section class="border-t border-[color:var(--ts-color-border)] pt-7">
|
|
170
|
+
<div class="mb-4 flex flex-wrap items-end justify-between gap-3">
|
|
171
|
+
<div>
|
|
172
|
+
<p class="text-xs font-semibold uppercase tracking-[0.14em] text-[color:var(--ts-color-info-text)]">Connections</p>
|
|
91
173
|
</div>
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
<
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
)}
|
|
113
|
-
{relatedDecisions.length > 0 && (
|
|
114
|
-
<div>
|
|
115
|
-
<p class="text-sm font-semibold uppercase tracking-[0.14em] text-[color:var(--ts-color-info-text)]">Related decisions</p>
|
|
116
|
-
<ul class="mt-3 space-y-2 text-[color:var(--ts-color-text-muted)]">
|
|
117
|
-
{relatedDecisions.map((decision) => (
|
|
118
|
-
<li><a href={`/decisions/${decision.id}/`} class="hover:text-[color:var(--ts-color-text)]">{entryTitle(decision)}</a></li>
|
|
119
|
-
))}
|
|
120
|
-
</ul>
|
|
121
|
-
</div>
|
|
122
|
-
)}
|
|
123
|
-
{relatedBooks.length > 0 && (
|
|
124
|
-
<div>
|
|
125
|
-
<p class="text-sm font-semibold uppercase tracking-[0.14em] text-[color:var(--ts-color-info-text)]">Related books</p>
|
|
126
|
-
<ul class="mt-3 space-y-2 text-[color:var(--ts-color-text-muted)]">
|
|
127
|
-
{relatedBooks.map((book) => (
|
|
128
|
-
<li><a href={`/books/${book.id}/`} class="hover:text-[color:var(--ts-color-text)]">{entryTitle(book)}</a></li>
|
|
129
|
-
))}
|
|
130
|
-
</ul>
|
|
131
|
-
</div>
|
|
132
|
-
)}
|
|
133
|
-
</div>
|
|
174
|
+
</div>
|
|
175
|
+
<div class="grid gap-4 md:grid-cols-2 xl:grid-cols-3">
|
|
176
|
+
{relationSections.map((section) => (
|
|
177
|
+
<div class="border-l border-[color:var(--ts-color-border)] pl-4">
|
|
178
|
+
<p class="text-xs font-semibold uppercase tracking-[0.12em] text-[color:var(--ts-color-text-subtle)]">{section.label}</p>
|
|
179
|
+
<ul class="mt-2 space-y-2">
|
|
180
|
+
{section.items.map((item) => (
|
|
181
|
+
<li>
|
|
182
|
+
<a href={`${section.hrefBase}/${item.id}/`} class="block text-[color:var(--ts-color-text)] hover:text-[color:var(--ts-color-accent-strong)]">
|
|
183
|
+
<span class="block text-sm font-semibold">{entryTitle(item)}</span>
|
|
184
|
+
<span class="block text-xs text-[color:var(--ts-color-text-subtle)]">{item.id}</span>
|
|
185
|
+
</a>
|
|
186
|
+
</li>
|
|
187
|
+
))}
|
|
188
|
+
</ul>
|
|
189
|
+
</div>
|
|
190
|
+
))}
|
|
191
|
+
</div>
|
|
192
|
+
</section>
|
|
193
|
+
)}
|
|
134
194
|
</article>
|
|
135
195
|
</MainLayout>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
import '../styles/global.css';
|
|
3
3
|
import PublicShell from '../components/ui/shell/PublicShell.astro';
|
|
4
|
+
import ShellIconLink from '../components/ui/shell/ShellIconLink.astro';
|
|
4
5
|
import { SITE_NAV_GROUPS } from '../utils/routes';
|
|
5
6
|
import { SITE } from '../utils/seo';
|
|
6
7
|
import { SITE_THEME_CSS } from '../utils/site-config';
|
|
@@ -36,6 +37,7 @@ const navItems = SITE_NAV_GROUPS.flatMap((group) => group.items);
|
|
|
36
37
|
{SITE_THEME_CSS && <style is:global>{SITE_THEME_CSS}</style>}
|
|
37
38
|
</Fragment>
|
|
38
39
|
<Fragment slot="actions">
|
|
40
|
+
<ShellIconLink href="/app/" label="Manager" icon="manager" />
|
|
39
41
|
<a
|
|
40
42
|
href={SITE.githubRepository}
|
|
41
43
|
target="_blank"
|
|
@@ -57,9 +57,17 @@ const supersededDecisions = publishedRuntime
|
|
|
57
57
|
entry={decision.data}
|
|
58
58
|
currentPath="/decisions/"
|
|
59
59
|
contributor={contributor}
|
|
60
|
+
contentTypeLabel="Decision"
|
|
61
|
+
contentId={decision.id}
|
|
62
|
+
collectionLabel="decisions"
|
|
60
63
|
metaLabel="Decision type"
|
|
61
64
|
metaValue={String(decision.data.decisionType ?? '')}
|
|
62
|
-
introText={
|
|
65
|
+
introText={decision.data.rationale}
|
|
66
|
+
metadataItems={[
|
|
67
|
+
{ label: 'Authority', value: decision.data.authority },
|
|
68
|
+
{ label: 'Route', value: decision.data.canonicalRoute, href: decision.data.canonicalRoute },
|
|
69
|
+
{ label: 'Implements', value: decision.data.implements },
|
|
70
|
+
]}
|
|
63
71
|
relatedObjectives={relatedObjectives}
|
|
64
72
|
relatedQuestions={relatedQuestions}
|
|
65
73
|
relatedNotes={relatedNotes}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
import { getCollection, render } from 'astro:content';
|
|
3
|
-
import
|
|
3
|
+
import AuthoredEntryLayout from '../../layouts/AuthoredEntryLayout.astro';
|
|
4
4
|
import PublishedContentBody from '../../components/site/PublishedContentBody.astro';
|
|
5
5
|
import RouteNotFound from '../../components/site/RouteNotFound.astro';
|
|
6
|
-
import { isPublishedRuntimeContentMode, loadPublishedEntry } from '../../utils/site-content-runtime';
|
|
6
|
+
import { isPublishedRuntimeContentMode, loadPublishedEntry, metadataFromPublishedContent } from '../../utils/site-content-runtime';
|
|
7
7
|
|
|
8
8
|
export const prerender = false;
|
|
9
9
|
|
|
@@ -13,6 +13,7 @@ const notes = publishedRuntime ? [] : await getCollection('notes', ({ data }) =>
|
|
|
13
13
|
const localNote = publishedRuntime ? null : notes.find((candidate) => candidate.id === slug) ?? null;
|
|
14
14
|
const publishedNote = publishedRuntime ? await loadPublishedEntry(Astro.locals, 'notes', slug) : null;
|
|
15
15
|
const note = publishedRuntime ? publishedNote?.entry ?? null : localNote;
|
|
16
|
+
const metadata = publishedRuntime ? metadataFromPublishedContent(publishedNote?.content) : null;
|
|
16
17
|
if (!note) {
|
|
17
18
|
Astro.response.status = 404;
|
|
18
19
|
}
|
|
@@ -24,8 +25,20 @@ const Content = rendered?.Content ?? null;
|
|
|
24
25
|
!note || (!Content && !publishedNote?.html) ? (
|
|
25
26
|
<RouteNotFound title="Note not found" description="The requested note could not be found in this Treeseed." currentPath="/notes/" />
|
|
26
27
|
) : (
|
|
27
|
-
<
|
|
28
|
+
<AuthoredEntryLayout
|
|
29
|
+
entry={note.data}
|
|
30
|
+
currentPath="/notes/"
|
|
31
|
+
contributor={null}
|
|
32
|
+
contentTypeLabel="Note"
|
|
33
|
+
contentId={note.id}
|
|
34
|
+
collectionLabel="notes"
|
|
35
|
+
metaLabel="Author"
|
|
36
|
+
metaValue={String(note.data.author ?? metadata?.author ?? '')}
|
|
37
|
+
metadataItems={[
|
|
38
|
+
{ label: 'Route', value: note.data.canonicalRoute ?? metadata?.canonicalRoute, href: note.data.canonicalRoute ?? metadata?.canonicalRoute },
|
|
39
|
+
]}
|
|
40
|
+
>
|
|
28
41
|
{publishedRuntime ? <PublishedContentBody html={publishedNote?.html ?? ''} /> : <Content />}
|
|
29
|
-
</
|
|
42
|
+
</AuthoredEntryLayout>
|
|
30
43
|
)
|
|
31
44
|
}
|
|
@@ -45,8 +45,12 @@ const relatedBooks = publishedRuntime
|
|
|
45
45
|
entry={objective.data}
|
|
46
46
|
currentPath="/objectives/"
|
|
47
47
|
contributor={contributor}
|
|
48
|
+
contentTypeLabel="Objective"
|
|
49
|
+
contentId={objective.id}
|
|
50
|
+
collectionLabel="objectives"
|
|
48
51
|
metaLabel="Time horizon"
|
|
49
52
|
metaValue={String(objective.data.timeHorizon ?? '')}
|
|
53
|
+
metadataItems={[]}
|
|
50
54
|
relatedQuestions={relatedQuestions}
|
|
51
55
|
relatedBooks={relatedBooks}
|
|
52
56
|
>
|
|
@@ -57,8 +57,14 @@ const supersededProposals = publishedRuntime
|
|
|
57
57
|
entry={proposal.data}
|
|
58
58
|
currentPath="/proposals/"
|
|
59
59
|
contributor={contributor}
|
|
60
|
+
contentTypeLabel="Proposal"
|
|
61
|
+
contentId={proposal.id}
|
|
62
|
+
collectionLabel="proposals"
|
|
60
63
|
metaLabel="Proposal type"
|
|
61
64
|
metaValue={String(proposal.data.proposalType ?? '')}
|
|
65
|
+
metadataItems={[
|
|
66
|
+
{ label: 'Route', value: proposal.data.canonicalRoute, href: proposal.data.canonicalRoute },
|
|
67
|
+
]}
|
|
62
68
|
relatedObjectives={relatedObjectives}
|
|
63
69
|
relatedQuestions={relatedQuestions}
|
|
64
70
|
relatedNotes={relatedNotes}
|
|
@@ -45,8 +45,12 @@ const relatedBooks = publishedRuntime
|
|
|
45
45
|
entry={question.data}
|
|
46
46
|
currentPath="/questions/"
|
|
47
47
|
contributor={contributor}
|
|
48
|
+
contentTypeLabel="Question"
|
|
49
|
+
contentId={question.id}
|
|
50
|
+
collectionLabel="questions"
|
|
48
51
|
metaLabel="Question type"
|
|
49
52
|
metaValue={String(question.data.questionType ?? '')}
|
|
53
|
+
metadataItems={[]}
|
|
50
54
|
relatedObjectives={relatedObjectives}
|
|
51
55
|
relatedBooks={relatedBooks}
|
|
52
56
|
>
|
|
@@ -391,7 +391,7 @@ async function main() {
|
|
|
391
391
|
writeCompatibilityEntrypoint(resolve(distRoot, 'config.d.ts'), "export declare function createTreeseedTenantSite(manifestPath?: string): import('astro').AstroUserConfig<never, never, never>;");
|
|
392
392
|
writeCompatibilityEntrypoint(resolve(distRoot, 'content.d.ts'), "export declare function createTreeseedCollections(tenantConfig: any, dependencies: any): Record<string, any>;");
|
|
393
393
|
writeCompatibilityEntrypoint(resolve(distRoot, 'content-config.js'), "import { loadTreeseedManifest } from '@treeseed/sdk/platform/tenant-config';\nimport { docsLoader } from './vendor/starlight/loaders.js';\nimport { docsSchema } from './vendor/starlight/schema.js';\nimport { createTreeseedCollections } from './content.js';\n\nexport function createTreeseedTenantCollections(manifestPath) {\n\tconst tenant = loadTreeseedManifest(manifestPath);\n\treturn createTreeseedCollections(tenant, { docsLoader, docsSchema });\n}");
|
|
394
|
-
writeCompatibilityEntrypoint(resolve(distRoot, 'content-config.d.ts'), "export declare function createTreeseedTenantCollections(manifestPath?: string): {\n\tpages: any;\n\tnotes: any;\n\tquestions: any;\n\tobjectives: any;\n\tpeople: any;\n\tagents: any;\n\tbooks: any;\n\tdocs: any;\n\tworkdays?: any;\n};");
|
|
394
|
+
writeCompatibilityEntrypoint(resolve(distRoot, 'content-config.d.ts'), "export declare function createTreeseedTenantCollections(manifestPath?: string): {\n\tpages: any;\n\tnotes: any;\n\tquestions: any;\n\tobjectives: any;\n\tpeople: any;\n\tagents: any;\n\tagent_tests?: any;\n\tbooks: any;\n\tdocs: any;\n\tworkdays?: any;\n};");
|
|
395
395
|
writeCompatibilityEntrypoint(resolve(distRoot, 'utils/forms/service.d.ts'), "import type { APIContext } from 'astro';\nimport type { SubmitResult } from '../../types/forms.js';\nexport declare function handleTokenRequest(context: APIContext): Promise<Response>;\nexport declare function handleFormSubmission(context: APIContext): Promise<SubmitResult>;");
|
|
396
396
|
rmSync(resolve(distRoot, 'config.d.js'), { force: true });
|
|
397
397
|
rmSync(resolve(distRoot, 'content-config.d.js'), { force: true });
|
|
@@ -50,6 +50,26 @@ function parseOpenMode(value) {
|
|
|
50
50
|
}
|
|
51
51
|
return undefined;
|
|
52
52
|
}
|
|
53
|
+
function parseLocalRuntimeMode(value) {
|
|
54
|
+
if (value === 'auto' || value === 'provider' || value === 'local') {
|
|
55
|
+
return value;
|
|
56
|
+
}
|
|
57
|
+
return undefined;
|
|
58
|
+
}
|
|
59
|
+
function readForwardedEnvironment() {
|
|
60
|
+
const keys = [
|
|
61
|
+
'TREESEED_DOCS_AUTOMATION_MODE',
|
|
62
|
+
'TREESEED_WORKDAY_ID',
|
|
63
|
+
'TREESEED_CAPACITY_BUDGET',
|
|
64
|
+
'TREESEED_WORKDAY_TASK_CREDIT_BUDGET',
|
|
65
|
+
'TREESEED_APPROVAL_POLICY',
|
|
66
|
+
'TREESEED_MANAGER_CONSOLE_SUMMARY',
|
|
67
|
+
'TREESEED_WORKER_CONSOLE_SUMMARY',
|
|
68
|
+
];
|
|
69
|
+
return Object.fromEntries(keys
|
|
70
|
+
.map((key) => [key, process.env[key]])
|
|
71
|
+
.filter((entry) => typeof entry[1] === 'string' && entry[1].length > 0));
|
|
72
|
+
}
|
|
53
73
|
const exitCode = await runTreeseedIntegratedDev({
|
|
54
74
|
surface: parseSurface(readOption('--surface')),
|
|
55
75
|
surfaces: readOption('--surfaces'),
|
|
@@ -58,13 +78,16 @@ const exitCode = await runTreeseedIntegratedDev({
|
|
|
58
78
|
webPort: readNumberOption('--port'),
|
|
59
79
|
apiHost: readOption('--api-host'),
|
|
60
80
|
apiPort: readNumberOption('--api-port'),
|
|
81
|
+
webRuntime: parseLocalRuntimeMode(readOption('--web-runtime')),
|
|
61
82
|
setupMode: parseSetupMode(readOption('--setup')),
|
|
62
83
|
feedbackMode: parseFeedbackMode(readOption('--feedback')),
|
|
63
84
|
openMode: parseOpenMode(readOption('--open')),
|
|
64
85
|
plan: readFlag('--plan'),
|
|
65
86
|
reset: readFlag('--reset'),
|
|
87
|
+
force: readFlag('--force'),
|
|
66
88
|
json: readFlag('--json'),
|
|
67
89
|
projectId: readOption('--project-id'),
|
|
68
90
|
teamId: readOption('--team-id'),
|
|
91
|
+
env: readForwardedEnvironment(),
|
|
69
92
|
});
|
|
70
93
|
process.exit(exitCode);
|
|
@@ -15,9 +15,13 @@ if (process.env.GITHUB_ACTIONS === 'true') {
|
|
|
15
15
|
npmArgs.push(...extraArgs);
|
|
16
16
|
const result = spawnSync('npm', npmArgs, {
|
|
17
17
|
cwd: packageRoot,
|
|
18
|
-
|
|
18
|
+
encoding: 'utf8',
|
|
19
19
|
env: process.env,
|
|
20
20
|
});
|
|
21
|
+
if (result.stdout)
|
|
22
|
+
process.stdout.write(result.stdout);
|
|
23
|
+
if (result.stderr)
|
|
24
|
+
process.stderr.write(result.stderr);
|
|
21
25
|
if (result.error) {
|
|
22
26
|
console.error(result.error.message);
|
|
23
27
|
process.exit(1);
|
package/dist/site.js
CHANGED
|
@@ -313,6 +313,9 @@ function createTreeseedSite(tenantConfig, { starlight }) {
|
|
|
313
313
|
__TREESEED_DEPLOY_CONFIG__: injectedDeployConfig,
|
|
314
314
|
__TREESEED_BOOK_RUNTIME__: injectedBookRuntime
|
|
315
315
|
},
|
|
316
|
+
optimizeDeps: {
|
|
317
|
+
exclude: ["libsodium-wrappers-sumo"]
|
|
318
|
+
},
|
|
316
319
|
plugins: [
|
|
317
320
|
createTenantThemeVitePlugin(tenantThemeCss),
|
|
318
321
|
tailwindcss(),
|
|
@@ -27,15 +27,25 @@
|
|
|
27
27
|
align-self: start;
|
|
28
28
|
background: var(--ts-color-canvas-subtle);
|
|
29
29
|
border-right: 1px solid var(--ts-color-border);
|
|
30
|
+
box-sizing: border-box;
|
|
30
31
|
display: grid;
|
|
31
32
|
gap: var(--ts-space-3);
|
|
33
|
+
grid-template-rows: minmax(0, 1fr) auto;
|
|
32
34
|
height: 100vh;
|
|
33
|
-
overflow:
|
|
35
|
+
overflow: hidden;
|
|
34
36
|
padding: var(--ts-space-3);
|
|
35
37
|
position: sticky;
|
|
36
38
|
top: 0;
|
|
37
39
|
}
|
|
38
40
|
|
|
41
|
+
.ts-app-shell__rail-scroll {
|
|
42
|
+
display: grid;
|
|
43
|
+
gap: var(--ts-space-3);
|
|
44
|
+
min-height: 0;
|
|
45
|
+
overflow: auto;
|
|
46
|
+
padding-right: 0.15rem;
|
|
47
|
+
}
|
|
48
|
+
|
|
39
49
|
.ts-shell-brand {
|
|
40
50
|
align-items: center;
|
|
41
51
|
color: var(--ts-color-text);
|
|
@@ -109,6 +119,12 @@
|
|
|
109
119
|
min-width: 0;
|
|
110
120
|
}
|
|
111
121
|
|
|
122
|
+
.ts-shell-utility-actions {
|
|
123
|
+
align-items: center;
|
|
124
|
+
display: inline-flex;
|
|
125
|
+
gap: var(--ts-space-1);
|
|
126
|
+
}
|
|
127
|
+
|
|
112
128
|
.ts-app-shell__rail-context,
|
|
113
129
|
.ts-app-shell__quick-actions {
|
|
114
130
|
border-top: 1px solid var(--ts-color-border);
|
|
@@ -117,6 +133,11 @@
|
|
|
117
133
|
padding-top: var(--ts-space-2);
|
|
118
134
|
}
|
|
119
135
|
|
|
136
|
+
.ts-app-shell__quick-actions {
|
|
137
|
+
background: var(--ts-color-canvas-subtle);
|
|
138
|
+
padding-bottom: 0.1rem;
|
|
139
|
+
}
|
|
140
|
+
|
|
120
141
|
.ts-app-shell__eyebrow {
|
|
121
142
|
color: var(--ts-color-text-subtle);
|
|
122
143
|
font-size: 0.75rem;
|
|
@@ -568,6 +589,10 @@
|
|
|
568
589
|
width: 100%;
|
|
569
590
|
}
|
|
570
591
|
|
|
592
|
+
.ts-app-shell__header-actions .ts-shell-utility-actions {
|
|
593
|
+
display: none;
|
|
594
|
+
}
|
|
595
|
+
|
|
571
596
|
.ts-bottom-nav {
|
|
572
597
|
display: grid;
|
|
573
598
|
}
|
package/dist/styles/theme.css
CHANGED
|
@@ -20,13 +20,13 @@ body {
|
|
|
20
20
|
|
|
21
21
|
.ts-theme-menu__trigger {
|
|
22
22
|
align-items: center;
|
|
23
|
-
background:
|
|
24
|
-
border: 1px solid
|
|
23
|
+
background: transparent;
|
|
24
|
+
border: 1px solid transparent;
|
|
25
25
|
border-radius: var(--ts-radius-md);
|
|
26
26
|
color: var(--ts-color-text-muted);
|
|
27
27
|
cursor: pointer;
|
|
28
28
|
display: inline-flex;
|
|
29
|
-
height:
|
|
29
|
+
height: 2.25rem;
|
|
30
30
|
justify-content: center;
|
|
31
31
|
list-style: none;
|
|
32
32
|
padding: 0;
|
|
@@ -34,7 +34,7 @@ body {
|
|
|
34
34
|
background-color 140ms ease,
|
|
35
35
|
border-color 140ms ease,
|
|
36
36
|
color 140ms ease;
|
|
37
|
-
width:
|
|
37
|
+
width: 2.25rem;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
.ts-theme-menu__trigger::-webkit-details-marker {
|
|
@@ -43,8 +43,8 @@ body {
|
|
|
43
43
|
|
|
44
44
|
.ts-theme-menu__trigger:hover,
|
|
45
45
|
.ts-theme-menu[open] .ts-theme-menu__trigger {
|
|
46
|
-
background: var(--ts-color-surface-
|
|
47
|
-
border-color: var(--ts-color-border
|
|
46
|
+
background: var(--ts-color-surface-raised);
|
|
47
|
+
border-color: var(--ts-color-border);
|
|
48
48
|
color: var(--ts-color-text);
|
|
49
49
|
}
|
|
50
50
|
|
|
@@ -56,8 +56,8 @@ body {
|
|
|
56
56
|
.ts-theme-menu__trigger svg {
|
|
57
57
|
display: block;
|
|
58
58
|
fill: currentColor;
|
|
59
|
-
height:
|
|
60
|
-
width:
|
|
59
|
+
height: 1.15rem;
|
|
60
|
+
width: 1.15rem;
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
.ts-theme-menu__panel {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@treeseed/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.4",
|
|
4
4
|
"description": "Treeseed web framework package for Astro/Starlight site runtimes.",
|
|
5
5
|
"license": "AGPL-3.0-only",
|
|
6
6
|
"repository": {
|
|
@@ -70,7 +70,7 @@
|
|
|
70
70
|
"@astrojs/sitemap": "3.7.0",
|
|
71
71
|
"@astrojs/starlight": "0.37.6",
|
|
72
72
|
"@tailwindcss/vite": "^4.1.4",
|
|
73
|
-
"@treeseed/sdk": "0.
|
|
73
|
+
"@treeseed/sdk": "github:treeseed-ai/sdk#0.10.6",
|
|
74
74
|
"astro": "^5.6.1",
|
|
75
75
|
"esbuild": "^0.28.0",
|
|
76
76
|
"katex": "^0.16.22",
|