@valbuild/shared 0.150.13 → 0.150.17
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/CHANGELOG.md +36 -0
- package/dist/declarations/src/internal/ApiRoutes.d.ts +264 -0
- package/dist/declarations/src/internal/aiTools/toolNames.d.ts +1 -1
- package/dist/declarations/src/internal/index.d.ts +2 -0
- package/dist/declarations/src/internal/localeAt.d.ts +86 -1
- package/dist/declarations/src/internal/localeRelocation.d.ts +46 -0
- package/dist/declarations/src/internal/sketchpad/sketchFormat.d.ts +118 -0
- package/internal/dist/valbuild-shared-internal.cjs.dev.js +855 -17
- package/internal/dist/valbuild-shared-internal.cjs.prod.js +855 -17
- package/internal/dist/valbuild-shared-internal.esm.js +840 -19
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,41 @@
|
|
|
1
1
|
# @valbuild/shared
|
|
2
2
|
|
|
3
|
+
## 0.150.17
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#992](https://github.com/valbuild/val/pull/992) [`ea3bf9b`](https://github.com/valbuild/val/commit/ea3bf9bbacd22bbb5485fd798d6b3a2d5916be81) Thanks [@freekh](https://github.com/freekh)! - Content analytics now counts on self-hosted sites (Custom hosting), not only on sites Val hosts.
|
|
8
|
+
|
|
9
|
+
A self-hosted app's own Val server now hands each analytics beacon on to Val's ingest, which counts it. To turn it on:
|
|
10
|
+
|
|
11
|
+
- Run the app with Val's content service: `VAL_API_KEY`, `VAL_SECRET` and `VAL_PROJECT` set. Most deployed apps already do.
|
|
12
|
+
- Set `VAL_ANALYTICS=true`. In TanStack Start, read it in your layout's loader (`{ enabled: process.env.VAL_ANALYTICS === "true" }`) and pass the result to `<ValProvider analytics>`. A self-hosted site has no platform to pass it for you.
|
|
13
|
+
- Switch analytics on for the project in Val's admin. While it is off there, the script on your pages is told so and stops sending.
|
|
14
|
+
|
|
15
|
+
The server forwards only same-origin beacons from a browser. It passes on the visitor's User-Agent and, where your host provides one (Vercel, Cloudflare or CloudFront), their country. It never passes on their IP address. If the api key is not accepted, the server logs one warning naming `VAL_API_KEY` and `VAL_PROJECT`. Local development (fs mode) works as before and counts nothing.
|
|
16
|
+
|
|
17
|
+
`VAL_ANALYTICS_INGEST_URL` overrides where beacons are sent. You will normally not need it.
|
|
18
|
+
|
|
19
|
+
## 0.150.16
|
|
20
|
+
|
|
21
|
+
### Patch Changes
|
|
22
|
+
|
|
23
|
+
- [#940](https://github.com/valbuild/val/pull/940) [`3ac24d4`](https://github.com/valbuild/val/commit/3ac24d46691c646dd5d2789cf2e1d6e2734195d3) Thanks [@freekh](https://github.com/freekh)! - Picking a language in the Studio now scopes the whole Studio to it.
|
|
24
|
+
|
|
25
|
+
- The Pages tree, the Data list, lists inside a field and search show only content in that language, plus content in no language (settings, authors, images), which every language shares. A page is in a language when its route names it (`s.router(router, { locale: … }, item)`) or its content has an `s.locale()` field.
|
|
26
|
+
- Picking a language while you are on something in another one moves you: to the same entry in the new language where Val knows it (a record keyed by `s.locale()`, or a route that differs only in its language segment), otherwise to the nearest parent that is not in another language, otherwise to the Studio's start screen with nothing selected.
|
|
27
|
+
- A link or a reference to something in another language still opens it, and that one item is listed while you are on it.
|
|
28
|
+
- Publish, Discard all and the error count are not filtered: they act on every language.
|
|
29
|
+
|
|
30
|
+
- [#969](https://github.com/valbuild/val/pull/969) [`7db39ef`](https://github.com/valbuild/val/commit/7db39ef722b4f743e6974effd5fedfadc76e6544) Thanks [@freekh](https://github.com/freekh)! - **Sketchpad**: work out a page's content and rough layout with the assistant before anyone builds it.
|
|
31
|
+
|
|
32
|
+
A sketchpad is a document of headings, text, boxes and columns, where you edit the text in place. A box can show an image or a video from a link: paste one, or drag an image in from a web page. The assistant sees the same sketch as text in one strict format, so what it reads is what is on screen. It has tools to list, create, read and write sketchpads, and **Send to AI** asks it to read the one you are on.
|
|
33
|
+
|
|
34
|
+
- Sketchpads live on the server, apart from any chat or page. They outlast the chat they started in, and the page a sketchpad is about can be changed. A sketchpad can be archived and reopened.
|
|
35
|
+
- Open one from a page's menu (**Sketch changes**), from the top bar, or when the assistant offers one.
|
|
36
|
+
- On a desktop the page, the sketchpad and the chat sit side by side, the chat docked beside them. On a phone a sketchpad can go full screen, with the page one tap away and the buttons at the bottom.
|
|
37
|
+
- In local development sketchpads are stored in `.val/sketchpads/`. A hosted project needs the content host's sketchpad API; without it the Studio does not offer sketchpads.
|
|
38
|
+
|
|
3
39
|
## 0.150.13
|
|
4
40
|
|
|
5
41
|
### Patch Changes
|
|
@@ -82,6 +82,43 @@ export declare const AnalyticsBeacon: z.ZodObject<{
|
|
|
82
82
|
viewed: z.ZodRecord<z.ZodString, z.ZodArray<z.ZodString>>;
|
|
83
83
|
}, z.core.$strip>;
|
|
84
84
|
export type AnalyticsBeacon = z.infer<typeof AnalyticsBeacon>;
|
|
85
|
+
/**
|
|
86
|
+
* A Sketchpad, as the server keeps it: a rough page written in the strict
|
|
87
|
+
* format of `sketchpad/sketchFormat.ts`, owned by the project and nothing
|
|
88
|
+
* else. Not by an AI session -- the assistant that made it remembers its id,
|
|
89
|
+
* and any chat can read it again -- and not by a page: `page` is a label for
|
|
90
|
+
* which page it is about, and can be changed or cleared.
|
|
91
|
+
*
|
|
92
|
+
* `version` goes up by one on every change, and a change names the version
|
|
93
|
+
* it was made against, so two writers cannot overwrite each other unseen.
|
|
94
|
+
*/
|
|
95
|
+
export declare const Sketchpad: z.ZodObject<{
|
|
96
|
+
id: z.ZodString;
|
|
97
|
+
page: z.ZodNullable<z.ZodString>;
|
|
98
|
+
title: z.ZodNullable<z.ZodString>;
|
|
99
|
+
text: z.ZodString;
|
|
100
|
+
version: z.ZodNumber;
|
|
101
|
+
archived: z.ZodBoolean;
|
|
102
|
+
createdAt: z.ZodString;
|
|
103
|
+
updatedAt: z.ZodString;
|
|
104
|
+
createdBy: z.ZodNullable<z.ZodString>;
|
|
105
|
+
updatedBy: z.ZodNullable<z.ZodString>;
|
|
106
|
+
}, z.core.$strip>;
|
|
107
|
+
export type SketchpadT = z.infer<typeof Sketchpad>;
|
|
108
|
+
export declare const SketchpadSummary: z.ZodObject<{
|
|
109
|
+
id: z.ZodString;
|
|
110
|
+
title: z.ZodNullable<z.ZodString>;
|
|
111
|
+
page: z.ZodNullable<z.ZodString>;
|
|
112
|
+
version: z.ZodNumber;
|
|
113
|
+
createdAt: z.ZodString;
|
|
114
|
+
updatedAt: z.ZodString;
|
|
115
|
+
archived: z.ZodBoolean;
|
|
116
|
+
createdBy: z.ZodNullable<z.ZodString>;
|
|
117
|
+
updatedBy: z.ZodNullable<z.ZodString>;
|
|
118
|
+
}, z.core.$strip>;
|
|
119
|
+
export type SketchpadSummaryT = z.infer<typeof SketchpadSummary>;
|
|
120
|
+
/** The most text a sketchpad holds, in UTF-8 bytes: a page, not a site. */
|
|
121
|
+
export declare const SKETCHPAD_MAX_TEXT_LENGTH: number;
|
|
85
122
|
export declare const Api: {
|
|
86
123
|
"/draft/enable": {
|
|
87
124
|
GET: {
|
|
@@ -139,6 +176,13 @@ export declare const Api: {
|
|
|
139
176
|
POST: {
|
|
140
177
|
req: {
|
|
141
178
|
body: z.ZodUnknown;
|
|
179
|
+
headers: {
|
|
180
|
+
"sec-fetch-site": z.ZodOptional<z.ZodString>;
|
|
181
|
+
"user-agent": z.ZodOptional<z.ZodString>;
|
|
182
|
+
"x-vercel-ip-country": z.ZodOptional<z.ZodString>;
|
|
183
|
+
"cf-ipcountry": z.ZodOptional<z.ZodString>;
|
|
184
|
+
"cloudfront-viewer-country": z.ZodOptional<z.ZodString>;
|
|
185
|
+
};
|
|
142
186
|
};
|
|
143
187
|
res: z.ZodUnion<readonly [z.ZodObject<{
|
|
144
188
|
status: z.ZodLiteral<200>;
|
|
@@ -150,6 +194,11 @@ export declare const Api: {
|
|
|
150
194
|
json: z.ZodObject<{
|
|
151
195
|
message: z.ZodString;
|
|
152
196
|
}, z.core.$strip>;
|
|
197
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
198
|
+
status: z.ZodLiteral<410>;
|
|
199
|
+
json: z.ZodObject<{
|
|
200
|
+
message: z.ZodString;
|
|
201
|
+
}, z.core.$strip>;
|
|
153
202
|
}, z.core.$strip>]>;
|
|
154
203
|
};
|
|
155
204
|
};
|
|
@@ -700,6 +749,221 @@ export declare const Api: {
|
|
|
700
749
|
}, z.core.$strip>;
|
|
701
750
|
};
|
|
702
751
|
};
|
|
752
|
+
/**
|
|
753
|
+
* The project's sketchpads: list them, or make one. See `Sketchpad`.
|
|
754
|
+
* Making one answers with its id, which is what an assistant keeps to
|
|
755
|
+
* read and change it later.
|
|
756
|
+
*/
|
|
757
|
+
"/sketchpads": {
|
|
758
|
+
GET: {
|
|
759
|
+
req: {
|
|
760
|
+
query: {
|
|
761
|
+
/** `exclude` (the default), `include`, or `only`. */
|
|
762
|
+
archived: z.ZodOptional<z.ZodPipe<z.ZodArray<z.ZodString>, z.ZodTransform<string, string[]>>>;
|
|
763
|
+
/** Only those about this page. */
|
|
764
|
+
page: z.ZodOptional<z.ZodPipe<z.ZodArray<z.ZodString>, z.ZodTransform<string, string[]>>>;
|
|
765
|
+
};
|
|
766
|
+
cookies: {
|
|
767
|
+
val_session: z.ZodOptional<z.ZodString>;
|
|
768
|
+
};
|
|
769
|
+
};
|
|
770
|
+
res: z.ZodUnion<readonly [z.ZodObject<{
|
|
771
|
+
status: z.ZodLiteral<401>;
|
|
772
|
+
json: z.ZodObject<{
|
|
773
|
+
message: z.ZodString;
|
|
774
|
+
}, z.core.$strip>;
|
|
775
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
776
|
+
status: z.ZodLiteral<400>;
|
|
777
|
+
json: z.ZodObject<{
|
|
778
|
+
message: z.ZodString;
|
|
779
|
+
}, z.core.$strip>;
|
|
780
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
781
|
+
status: z.ZodLiteral<500>;
|
|
782
|
+
json: z.ZodObject<{
|
|
783
|
+
message: z.ZodString;
|
|
784
|
+
}, z.core.$strip>;
|
|
785
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
786
|
+
status: z.ZodLiteral<200>;
|
|
787
|
+
json: z.ZodObject<{
|
|
788
|
+
sketchpads: z.ZodArray<z.ZodObject<{
|
|
789
|
+
id: z.ZodString;
|
|
790
|
+
title: z.ZodNullable<z.ZodString>;
|
|
791
|
+
page: z.ZodNullable<z.ZodString>;
|
|
792
|
+
version: z.ZodNumber;
|
|
793
|
+
createdAt: z.ZodString;
|
|
794
|
+
updatedAt: z.ZodString;
|
|
795
|
+
archived: z.ZodBoolean;
|
|
796
|
+
createdBy: z.ZodNullable<z.ZodString>;
|
|
797
|
+
updatedBy: z.ZodNullable<z.ZodString>;
|
|
798
|
+
}, z.core.$strip>>;
|
|
799
|
+
}, z.core.$strip>;
|
|
800
|
+
}, z.core.$strip>]>;
|
|
801
|
+
};
|
|
802
|
+
POST: {
|
|
803
|
+
req: {
|
|
804
|
+
body: z.ZodObject<{
|
|
805
|
+
text: z.ZodString;
|
|
806
|
+
page: z.ZodNullable<z.ZodString>;
|
|
807
|
+
}, z.core.$strip>;
|
|
808
|
+
cookies: {
|
|
809
|
+
val_session: z.ZodOptional<z.ZodString>;
|
|
810
|
+
};
|
|
811
|
+
};
|
|
812
|
+
res: z.ZodUnion<readonly [z.ZodObject<{
|
|
813
|
+
status: z.ZodLiteral<401>;
|
|
814
|
+
json: z.ZodObject<{
|
|
815
|
+
message: z.ZodString;
|
|
816
|
+
}, z.core.$strip>;
|
|
817
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
818
|
+
status: z.ZodLiteral<400>;
|
|
819
|
+
json: z.ZodObject<{
|
|
820
|
+
message: z.ZodString;
|
|
821
|
+
errors: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
822
|
+
line: z.ZodNumber;
|
|
823
|
+
message: z.ZodString;
|
|
824
|
+
}, z.core.$strip>>>;
|
|
825
|
+
}, z.core.$strip>;
|
|
826
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
827
|
+
status: z.ZodLiteral<500>;
|
|
828
|
+
json: z.ZodObject<{
|
|
829
|
+
message: z.ZodString;
|
|
830
|
+
}, z.core.$strip>;
|
|
831
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
832
|
+
status: z.ZodLiteral<201>;
|
|
833
|
+
json: z.ZodObject<{
|
|
834
|
+
sketchpad: z.ZodObject<{
|
|
835
|
+
id: z.ZodString;
|
|
836
|
+
page: z.ZodNullable<z.ZodString>;
|
|
837
|
+
title: z.ZodNullable<z.ZodString>;
|
|
838
|
+
text: z.ZodString;
|
|
839
|
+
version: z.ZodNumber;
|
|
840
|
+
archived: z.ZodBoolean;
|
|
841
|
+
createdAt: z.ZodString;
|
|
842
|
+
updatedAt: z.ZodString;
|
|
843
|
+
createdBy: z.ZodNullable<z.ZodString>;
|
|
844
|
+
updatedBy: z.ZodNullable<z.ZodString>;
|
|
845
|
+
}, z.core.$strip>;
|
|
846
|
+
}, z.core.$strip>;
|
|
847
|
+
}, z.core.$strip>]>;
|
|
848
|
+
};
|
|
849
|
+
};
|
|
850
|
+
/** One sketchpad: read it, or change its text, its page or whether it is archived. */
|
|
851
|
+
"/sketchpad": {
|
|
852
|
+
GET: {
|
|
853
|
+
req: {
|
|
854
|
+
query: {
|
|
855
|
+
id: z.ZodPipe<z.ZodArray<z.ZodString>, z.ZodTransform<string, string[]>>;
|
|
856
|
+
};
|
|
857
|
+
cookies: {
|
|
858
|
+
val_session: z.ZodOptional<z.ZodString>;
|
|
859
|
+
};
|
|
860
|
+
};
|
|
861
|
+
res: z.ZodUnion<readonly [z.ZodObject<{
|
|
862
|
+
status: z.ZodLiteral<401>;
|
|
863
|
+
json: z.ZodObject<{
|
|
864
|
+
message: z.ZodString;
|
|
865
|
+
}, z.core.$strip>;
|
|
866
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
867
|
+
status: z.ZodLiteral<404>;
|
|
868
|
+
json: z.ZodObject<{
|
|
869
|
+
message: z.ZodString;
|
|
870
|
+
}, z.core.$strip>;
|
|
871
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
872
|
+
status: z.ZodLiteral<500>;
|
|
873
|
+
json: z.ZodObject<{
|
|
874
|
+
message: z.ZodString;
|
|
875
|
+
}, z.core.$strip>;
|
|
876
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
877
|
+
status: z.ZodLiteral<200>;
|
|
878
|
+
json: z.ZodObject<{
|
|
879
|
+
sketchpad: z.ZodObject<{
|
|
880
|
+
id: z.ZodString;
|
|
881
|
+
page: z.ZodNullable<z.ZodString>;
|
|
882
|
+
title: z.ZodNullable<z.ZodString>;
|
|
883
|
+
text: z.ZodString;
|
|
884
|
+
version: z.ZodNumber;
|
|
885
|
+
archived: z.ZodBoolean;
|
|
886
|
+
createdAt: z.ZodString;
|
|
887
|
+
updatedAt: z.ZodString;
|
|
888
|
+
createdBy: z.ZodNullable<z.ZodString>;
|
|
889
|
+
updatedBy: z.ZodNullable<z.ZodString>;
|
|
890
|
+
}, z.core.$strip>;
|
|
891
|
+
}, z.core.$strip>;
|
|
892
|
+
}, z.core.$strip>]>;
|
|
893
|
+
};
|
|
894
|
+
PATCH: {
|
|
895
|
+
req: {
|
|
896
|
+
body: z.ZodObject<{
|
|
897
|
+
id: z.ZodString;
|
|
898
|
+
baseVersion: z.ZodNumber;
|
|
899
|
+
text: z.ZodOptional<z.ZodString>;
|
|
900
|
+
page: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
901
|
+
archived: z.ZodOptional<z.ZodBoolean>;
|
|
902
|
+
}, z.core.$strip>;
|
|
903
|
+
cookies: {
|
|
904
|
+
val_session: z.ZodOptional<z.ZodString>;
|
|
905
|
+
};
|
|
906
|
+
};
|
|
907
|
+
res: z.ZodUnion<readonly [z.ZodObject<{
|
|
908
|
+
status: z.ZodLiteral<401>;
|
|
909
|
+
json: z.ZodObject<{
|
|
910
|
+
message: z.ZodString;
|
|
911
|
+
}, z.core.$strip>;
|
|
912
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
913
|
+
status: z.ZodLiteral<404>;
|
|
914
|
+
json: z.ZodObject<{
|
|
915
|
+
message: z.ZodString;
|
|
916
|
+
}, z.core.$strip>;
|
|
917
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
918
|
+
status: z.ZodLiteral<400>;
|
|
919
|
+
json: z.ZodObject<{
|
|
920
|
+
message: z.ZodString;
|
|
921
|
+
errors: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
922
|
+
line: z.ZodNumber;
|
|
923
|
+
message: z.ZodString;
|
|
924
|
+
}, z.core.$strip>>>;
|
|
925
|
+
}, z.core.$strip>;
|
|
926
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
927
|
+
status: z.ZodLiteral<409>;
|
|
928
|
+
json: z.ZodObject<{
|
|
929
|
+
message: z.ZodString;
|
|
930
|
+
sketchpad: z.ZodObject<{
|
|
931
|
+
id: z.ZodString;
|
|
932
|
+
page: z.ZodNullable<z.ZodString>;
|
|
933
|
+
title: z.ZodNullable<z.ZodString>;
|
|
934
|
+
text: z.ZodString;
|
|
935
|
+
version: z.ZodNumber;
|
|
936
|
+
archived: z.ZodBoolean;
|
|
937
|
+
createdAt: z.ZodString;
|
|
938
|
+
updatedAt: z.ZodString;
|
|
939
|
+
createdBy: z.ZodNullable<z.ZodString>;
|
|
940
|
+
updatedBy: z.ZodNullable<z.ZodString>;
|
|
941
|
+
}, z.core.$strip>;
|
|
942
|
+
}, z.core.$strip>;
|
|
943
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
944
|
+
status: z.ZodLiteral<500>;
|
|
945
|
+
json: z.ZodObject<{
|
|
946
|
+
message: z.ZodString;
|
|
947
|
+
}, z.core.$strip>;
|
|
948
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
949
|
+
status: z.ZodLiteral<200>;
|
|
950
|
+
json: z.ZodObject<{
|
|
951
|
+
sketchpad: z.ZodObject<{
|
|
952
|
+
id: z.ZodString;
|
|
953
|
+
page: z.ZodNullable<z.ZodString>;
|
|
954
|
+
title: z.ZodNullable<z.ZodString>;
|
|
955
|
+
text: z.ZodString;
|
|
956
|
+
version: z.ZodNumber;
|
|
957
|
+
archived: z.ZodBoolean;
|
|
958
|
+
createdAt: z.ZodString;
|
|
959
|
+
updatedAt: z.ZodString;
|
|
960
|
+
createdBy: z.ZodNullable<z.ZodString>;
|
|
961
|
+
updatedBy: z.ZodNullable<z.ZodString>;
|
|
962
|
+
}, z.core.$strip>;
|
|
963
|
+
}, z.core.$strip>;
|
|
964
|
+
}, z.core.$strip>]>;
|
|
965
|
+
};
|
|
966
|
+
};
|
|
703
967
|
"/upload/patches": {
|
|
704
968
|
POST: {
|
|
705
969
|
req: {
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const toolNames: readonly ["get_all_schema", "get_source", "search_content", "validate_content", "create_patch", "add_session_image_to_gallery", "remove_image_gallery_entry", "navigate_to", "get_current_context", "get_patches", "get_source_path_from_route", "set_session_name", "show_compare_view", "ask_user_question", "duplicate_source", "empty_at_path", "count_entries", "get_record_keys"];
|
|
1
|
+
export declare const toolNames: readonly ["get_all_schema", "get_source", "search_content", "validate_content", "create_patch", "add_session_image_to_gallery", "remove_image_gallery_entry", "navigate_to", "get_current_context", "get_patches", "get_source_path_from_route", "set_session_name", "show_compare_view", "ask_user_question", "duplicate_source", "empty_at_path", "count_entries", "get_record_keys", "list_sketchpads", "create_sketchpad", "read_sketchpad", "write_sketchpad"];
|
|
2
2
|
export type ToolName = (typeof toolNames)[number];
|
|
@@ -21,6 +21,7 @@ export * from "./getNextAppRouterSourceFolder.js";
|
|
|
21
21
|
export * from "./routeValidation.js";
|
|
22
22
|
export * from "./resolveSchemaSourceFixes.js";
|
|
23
23
|
export * from "./localeAt.js";
|
|
24
|
+
export * from "./localeRelocation.js";
|
|
24
25
|
export * from "./getErrorMessageFromUnknownJson.js";
|
|
25
26
|
export * from "./zod/SerializedSchema.js";
|
|
26
27
|
export * from "./valCanvasProtocol.js";
|
|
@@ -30,6 +31,7 @@ export * from "./pageScreenshot.js";
|
|
|
30
31
|
export * from "./quickPreview.js";
|
|
31
32
|
export * from "./emptyOf.js";
|
|
32
33
|
export * from "./aiTools/toolNames.js";
|
|
34
|
+
export * from "./sketchpad/sketchFormat.js";
|
|
33
35
|
export * from "./aiTools/aiImageToolPatches.js";
|
|
34
36
|
export * from "./aiTools/aiSourceToolPatches.js";
|
|
35
37
|
export * from "./validation/partitionValidationErrors.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type SerializedEnumSchema, type SerializedSchema, type SourcePath } from "@valbuild/core";
|
|
1
|
+
import { type Json, type JsonObject, type ModuleFilePath, type SerializedEnumSchema, type SerializedSchema, type SourcePath } from "@valbuild/core";
|
|
2
2
|
import { type SchemaSourceSnapshot } from "./resolveSchemaSourceFixes.js";
|
|
3
3
|
/**
|
|
4
4
|
* Which of the project's languages governs a path, or `null` for none.
|
|
@@ -18,6 +18,52 @@ import { type SchemaSourceSnapshot } from "./resolveSchemaSourceFixes.js";
|
|
|
18
18
|
* in most projects, and for every project that has not declared any languages.
|
|
19
19
|
*/
|
|
20
20
|
export declare function localeAt(path: SourcePath, snapshot: SchemaSourceSnapshot): string | null;
|
|
21
|
+
/**
|
|
22
|
+
* Where the scope governing a path opens, and how.
|
|
23
|
+
*
|
|
24
|
+
* - `field`: the node `depth` segments down has a locale field. `depth` 0 is the
|
|
25
|
+
* module root.
|
|
26
|
+
* - `record-key`: segment `depth` is a key of a locale-keyed record, which sits
|
|
27
|
+
* `depth` segments down.
|
|
28
|
+
* - `route-key`: segment `depth` is a route whose parameters name the language,
|
|
29
|
+
* in the router `depth` segments down (in practice the module root).
|
|
30
|
+
*
|
|
31
|
+
* The opener is what decides where an editor goes when the Studio's language
|
|
32
|
+
* changes under them — the same entry in another language for a key, the
|
|
33
|
+
* parent for a field. See `relocateForLocale`.
|
|
34
|
+
*/
|
|
35
|
+
export type LocaleScope = {
|
|
36
|
+
locale: string;
|
|
37
|
+
depth: number;
|
|
38
|
+
} & ({
|
|
39
|
+
kind: "field";
|
|
40
|
+
} | {
|
|
41
|
+
kind: "record-key";
|
|
42
|
+
keySchema: SerializedSchema;
|
|
43
|
+
} | {
|
|
44
|
+
kind: "route-key";
|
|
45
|
+
router: SerializedSchema & {
|
|
46
|
+
type: "record";
|
|
47
|
+
};
|
|
48
|
+
});
|
|
49
|
+
/**
|
|
50
|
+
* The scope that governs a path, read from that module's schema and source
|
|
51
|
+
* alone, or `null` where none does.
|
|
52
|
+
*
|
|
53
|
+
* {@link localeAt} for a caller that already has the module in hand — the
|
|
54
|
+
* Studio, which has the project's languages from its own provider and would
|
|
55
|
+
* otherwise have to assemble a snapshot of every module to ask about one.
|
|
56
|
+
*/
|
|
57
|
+
export declare function localeScopeAt(path: SourcePath, schema: SerializedSchema, source: Json, available: readonly string[]): LocaleScope | null;
|
|
58
|
+
/**
|
|
59
|
+
* The language a whole module is in: the one its root's locale field names, or
|
|
60
|
+
* `null` where its root has none.
|
|
61
|
+
*
|
|
62
|
+
* The only way a module is in one language as a whole — a locale-keyed record
|
|
63
|
+
* or a router at the root is every one of its languages at once. Needs no path,
|
|
64
|
+
* so a list of modules can ask it of each.
|
|
65
|
+
*/
|
|
66
|
+
export declare function localeOfModuleRoot(schema: SerializedSchema, source: Json, available: readonly string[]): string | null;
|
|
21
67
|
/**
|
|
22
68
|
* The language a locale schema's value MEANS, or `null` if it means none of
|
|
23
69
|
* the project's.
|
|
@@ -44,3 +90,42 @@ export declare function enumLocaleTag(schema: SerializedEnumSchema, value: strin
|
|
|
44
90
|
* one.
|
|
45
91
|
*/
|
|
46
92
|
export declare function isLocaleSchema(schema: SerializedSchema): boolean;
|
|
93
|
+
/**
|
|
94
|
+
* Whether a router's URLs name the language each page is in — one of its route
|
|
95
|
+
* parameters is a locale (`s.router(router, { locale: … }, item)`).
|
|
96
|
+
*/
|
|
97
|
+
export declare function hasLocaleRouteParam(schema: SerializedSchema): boolean;
|
|
98
|
+
/**
|
|
99
|
+
* The language a router's key is in, where one of its route parameters is a
|
|
100
|
+
* locale — `/nb/blog/hei` is `nb-NO` when `locale` maps `nb` to it.
|
|
101
|
+
*
|
|
102
|
+
* Answered from the key alone, with no content read: which is what lets the
|
|
103
|
+
* Studio's page tree filter every page of a site without loading one of them.
|
|
104
|
+
*/
|
|
105
|
+
export declare function localeOfRouteKey(schema: SerializedSchema & {
|
|
106
|
+
type: "record";
|
|
107
|
+
}, moduleFilePath: ModuleFilePath, key: string, available: readonly string[]): string | null;
|
|
108
|
+
/**
|
|
109
|
+
* The route parameters a key gives its router, and which of them is the
|
|
110
|
+
* language — or `null` where the router has no locale parameter or the key is
|
|
111
|
+
* not one of its URLs.
|
|
112
|
+
*/
|
|
113
|
+
export declare function localeParamOfRouteKey(schema: SerializedSchema & {
|
|
114
|
+
type: "record";
|
|
115
|
+
}, moduleFilePath: ModuleFilePath, key: string): {
|
|
116
|
+
name: string;
|
|
117
|
+
schema: SerializedSchema;
|
|
118
|
+
value: string | null;
|
|
119
|
+
values: Record<string, string | null>;
|
|
120
|
+
} | null;
|
|
121
|
+
/** The child of a source value at a segment, or `null` where there is none. */
|
|
122
|
+
export declare function childSource(source: Json, segment: string): Json;
|
|
123
|
+
/**
|
|
124
|
+
* Whether `source` is a JSON object rather than an array or a primitive.
|
|
125
|
+
*
|
|
126
|
+
* A type predicate rather than the inline checks, because `Array.isArray` does
|
|
127
|
+
* NOT narrow `JsonArray` out of `Json` — it is `readonly Json[]`, and the
|
|
128
|
+
* built-in guard only narrows mutable arrays. Without this, every read of a
|
|
129
|
+
* property would need an assertion.
|
|
130
|
+
*/
|
|
131
|
+
export declare function isJsonObject(source: Json): source is JsonObject;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { type Json, type SerializedSchema, type SourcePath } from "@valbuild/core";
|
|
2
|
+
/**
|
|
3
|
+
* Where an editor goes when the Studio's language changes under them.
|
|
4
|
+
*
|
|
5
|
+
* - `stay`: the path is in that language, or in none.
|
|
6
|
+
* - `path`: the same entry in that language (`counterpart`), or the nearest
|
|
7
|
+
* parent that is not in another language (`parent`).
|
|
8
|
+
* - `home`: neither exists, so the editor goes to the Studio's start, with
|
|
9
|
+
* nothing selected.
|
|
10
|
+
*/
|
|
11
|
+
export type LocaleRelocation = {
|
|
12
|
+
type: "stay";
|
|
13
|
+
} | {
|
|
14
|
+
type: "path";
|
|
15
|
+
path: SourcePath;
|
|
16
|
+
reason: "counterpart" | "parent";
|
|
17
|
+
} | {
|
|
18
|
+
type: "home";
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Where to move a path to when the Studio is switched to `locale`.
|
|
22
|
+
*
|
|
23
|
+
* The rule, in the order it is tried:
|
|
24
|
+
*
|
|
25
|
+
* 1. **The same entry in `locale`, where Val KNOWS it.** That is two cases:
|
|
26
|
+
* a locale-keyed record, where the counterpart of `"en-US"` is the
|
|
27
|
+
* `"nb-NO"` key of the same record; and a router whose URLs name their
|
|
28
|
+
* language, where `/about` and `/nb/about` differ only in it. Only a key
|
|
29
|
+
* that exists is taken, and the rest of the path is kept as far as it
|
|
30
|
+
* still exists, so an editor on a field lands on that field.
|
|
31
|
+
* 2. **Otherwise the nearest parent that is not in another language.** An
|
|
32
|
+
* English post in a list of posts gives the list, now showing Norwegian.
|
|
33
|
+
* 3. **Otherwise the Studio's start**, which is `home`: nothing selected. That
|
|
34
|
+
* is where an object at the module root opened the scope (the whole module
|
|
35
|
+
* is in another language), and where the parent would be a router: a list
|
|
36
|
+
* of pages is not a page, and the Pages tree is how an editor sees one.
|
|
37
|
+
*
|
|
38
|
+
* Not the site's root page, and not any other page: which language a page is
|
|
39
|
+
* in is the page's own business, and `/` can be in the language the editor
|
|
40
|
+
* just left. The start screen is in no language.
|
|
41
|
+
*
|
|
42
|
+
* Never a guess. Two pages whose URLs differ in more than the language — a
|
|
43
|
+
* Norwegian slug for a Norwegian page — are not known to be translations of
|
|
44
|
+
* each other, so that is `home` rather than whichever page looks closest.
|
|
45
|
+
*/
|
|
46
|
+
export declare function relocateForLocale(path: SourcePath, locale: string, schema: SerializedSchema, source: Json, available: readonly string[]): LocaleRelocation;
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A page sketch: a page written as indented text, with four primitives.
|
|
3
|
+
*
|
|
4
|
+
* ```
|
|
5
|
+
* # Our people text (a heading: #, ## or ###)
|
|
6
|
+
* We are 40 people in Oslo. text (a paragraph)
|
|
7
|
+
* [image: Team photo] placeholder: [kind] or [kind: label]
|
|
8
|
+
* [hero: Roof](image: /a.jpg) a placeholder with an image (or video) in it
|
|
9
|
+
* icon hero M3 5h18v14H3z how every [hero] box is drawn: SVG path data
|
|
10
|
+
* row its children side by side
|
|
11
|
+
* col 2 its children stacked; 2 shares of the row
|
|
12
|
+
* ## Design
|
|
13
|
+
* col
|
|
14
|
+
* [button: Join us]
|
|
15
|
+
* ```
|
|
16
|
+
*
|
|
17
|
+
* It is a scratch pad, not a layout language: it says WHAT is on a page and
|
|
18
|
+
* roughly WHERE, so an assistant and a person can agree on a page's content
|
|
19
|
+
* before anyone worries about how it looks. The person never sees this text,
|
|
20
|
+
* only the page it describes; the assistant never sees the page, only this.
|
|
21
|
+
* So the two have to be the same thing, and the format is STRICT: there is
|
|
22
|
+
* exactly one way to write what is on the screen. `checkSketch` is that
|
|
23
|
+
* rule, and the server refuses a write that breaks it, with the line to fix.
|
|
24
|
+
*
|
|
25
|
+
* Parsing is still forgiving, so a sketch that breaks the rule shows what it
|
|
26
|
+
* can rather than nothing; that is for reading, never for accepting.
|
|
27
|
+
*
|
|
28
|
+
* A placeholder's kind is any word, and nothing here knows what one means. The
|
|
29
|
+
* assistant that writes the sketch also draws each kind's icon, as path data
|
|
30
|
+
* in a 24 by 24 box, so a kind nobody thought of looks as deliberate as an
|
|
31
|
+
* image. Media put in a box is written into the text too, so the assistant
|
|
32
|
+
* that builds the page reads it exactly as the person left it.
|
|
33
|
+
*/
|
|
34
|
+
export type SketchNode = SketchRow | SketchCol | SketchText | SketchPlaceholder;
|
|
35
|
+
export type SketchRow = {
|
|
36
|
+
type: "row";
|
|
37
|
+
line: number;
|
|
38
|
+
children: SketchNode[];
|
|
39
|
+
};
|
|
40
|
+
export type SketchCol = {
|
|
41
|
+
type: "col";
|
|
42
|
+
line: number;
|
|
43
|
+
/** Shares of the enclosing row this column takes. */
|
|
44
|
+
weight: number;
|
|
45
|
+
children: SketchNode[];
|
|
46
|
+
};
|
|
47
|
+
export type SketchText = {
|
|
48
|
+
type: "text";
|
|
49
|
+
line: number;
|
|
50
|
+
/** 0 is a paragraph; 1-3 are headings. */
|
|
51
|
+
level: 0 | 1 | 2 | 3;
|
|
52
|
+
text: string;
|
|
53
|
+
};
|
|
54
|
+
export type SketchPlaceholder = {
|
|
55
|
+
type: "placeholder";
|
|
56
|
+
line: number;
|
|
57
|
+
kind: string;
|
|
58
|
+
label: string | null;
|
|
59
|
+
media: SketchMedia | null;
|
|
60
|
+
};
|
|
61
|
+
export type SketchMedia = {
|
|
62
|
+
type: "image" | "video";
|
|
63
|
+
src: string;
|
|
64
|
+
};
|
|
65
|
+
export type SketchError = {
|
|
66
|
+
/** 1-based, like an editor's gutter. */
|
|
67
|
+
line: number;
|
|
68
|
+
message: string;
|
|
69
|
+
};
|
|
70
|
+
export type ParsedSketch = {
|
|
71
|
+
/** The page itself is a column. */
|
|
72
|
+
blocks: SketchNode[];
|
|
73
|
+
/**
|
|
74
|
+
* SVG path data by kind, lower case. Drawn as a 24 by 24 line icon: stroked
|
|
75
|
+
* in the text colour, not filled.
|
|
76
|
+
*/
|
|
77
|
+
icons: Record<string, string>;
|
|
78
|
+
errors: SketchError[];
|
|
79
|
+
};
|
|
80
|
+
export declare function parseSketch(source: string): ParsedSketch;
|
|
81
|
+
/**
|
|
82
|
+
* The line a text block is written as. Line breaks become spaces, and a
|
|
83
|
+
* paragraph that would read as something else is kept as text with `\`.
|
|
84
|
+
*/
|
|
85
|
+
export declare function formatSketchText(level: SketchText["level"], text: string): string;
|
|
86
|
+
/** The line a placeholder is written as. */
|
|
87
|
+
export declare function formatSketchBox(placeholder: Pick<SketchPlaceholder, "kind" | "label" | "media">): string;
|
|
88
|
+
/**
|
|
89
|
+
* The ONE way of writing `blocks` and `icons`: what `checkSketch` holds every
|
|
90
|
+
* other text to, and what the Studio's editor writes (its own serializer is
|
|
91
|
+
* tested against this one). Two spaces per level; an empty row gets an empty
|
|
92
|
+
* col, so it has somewhere to type; a col outside a row is written as its
|
|
93
|
+
* contents, which is all it shows; the icons last, after one blank line, and
|
|
94
|
+
* no blank line anywhere else; a final newline. Empty text is not written --
|
|
95
|
+
* it is not on the page.
|
|
96
|
+
*/
|
|
97
|
+
export declare function formatSketch(blocks: SketchNode[], icons: Record<string, string>): string;
|
|
98
|
+
/**
|
|
99
|
+
* What a list names a sketch by: its first top-level heading, the biggest
|
|
100
|
+
* one first. Null for a sketch with no heading, which a list then names by
|
|
101
|
+
* its page.
|
|
102
|
+
*/
|
|
103
|
+
export declare function sketchTitle(blocks: SketchNode[]): string | null;
|
|
104
|
+
/**
|
|
105
|
+
* Everything wrong with `source`, or nothing when it is a sketch exactly as
|
|
106
|
+
* `formatSketch` writes it.
|
|
107
|
+
*
|
|
108
|
+
* Strict on purpose. The person sees the page and the assistant sees the
|
|
109
|
+
* text, so a text with two spellings of one page -- a tab or two spaces, an
|
|
110
|
+
* icon line here or there, a blank line or none -- is a text the assistant
|
|
111
|
+
* cannot trust to be what is on the screen, and that would show it a change
|
|
112
|
+
* nobody made the next time the Studio writes it back. Holding every write
|
|
113
|
+
* to the one spelling rules all of that out at once.
|
|
114
|
+
*
|
|
115
|
+
* The parse errors come first; past those, the first line that is spelled
|
|
116
|
+
* differently, with how it should be spelled.
|
|
117
|
+
*/
|
|
118
|
+
export declare function checkSketch(source: string): SketchError[];
|