@valbuild/shared 0.150.12 → 0.150.16
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 +31 -0
- package/client/dist/valbuild-shared-client.cjs.dev.js +2 -1
- package/client/dist/valbuild-shared-client.cjs.prod.js +2 -1
- package/client/dist/valbuild-shared-client.esm.js +1 -1
- package/dist/declarations/src/client/index.d.ts +1 -0
- package/dist/declarations/src/internal/ApiRoutes.d.ts +375 -94
- package/dist/declarations/src/internal/aiTools/toolNames.d.ts +1 -1
- package/dist/declarations/src/internal/index.d.ts +3 -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/pageScreenshot.d.ts +40 -0
- package/dist/declarations/src/internal/server/types.d.ts +3 -3
- package/dist/declarations/src/internal/sketchpad/sketchFormat.d.ts +118 -0
- package/dist/declarations/src/internal/valCanvasProtocol.d.ts +21 -0
- package/dist/declarations/src/internal/zod/History.d.ts +7 -7
- package/dist/declarations/src/internal/zod/Patch.d.ts +1 -0
- package/dist/declarations/src/internal/zod/SerializedSchema.d.ts +20 -2
- package/dist/{getSitemapTree-97b3166f.esm.js → getSitemapTree-7c848c94.esm.js} +137 -2
- package/dist/{getSitemapTree-5354ce90.cjs.prod.js → getSitemapTree-97713490.cjs.prod.js} +155 -1
- package/dist/{getSitemapTree-d934ff9c.cjs.dev.js → getSitemapTree-98642b57.cjs.dev.js} +155 -1
- package/internal/dist/valbuild-shared-internal.cjs.dev.js +837 -15
- package/internal/dist/valbuild-shared-internal.cjs.prod.js +837 -15
- package/internal/dist/valbuild-shared-internal.esm.js +821 -17
- package/package.json +2 -1
|
@@ -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,14 +21,17 @@ 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";
|
|
27
28
|
export * from "./elementPicker.js";
|
|
28
29
|
export * from "./pageInspection.js";
|
|
30
|
+
export * from "./pageScreenshot.js";
|
|
29
31
|
export * from "./quickPreview.js";
|
|
30
32
|
export * from "./emptyOf.js";
|
|
31
33
|
export * from "./aiTools/toolNames.js";
|
|
34
|
+
export * from "./sketchpad/sketchFormat.js";
|
|
32
35
|
export * from "./aiTools/aiImageToolPatches.js";
|
|
33
36
|
export * from "./aiTools/aiSourceToolPatches.js";
|
|
34
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,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A picture of the page, taken in the page: the assistant's
|
|
3
|
+
* `screenshot_page`, so it can see a change it made rather than only read it
|
|
4
|
+
* (`read_page` gives the words and the boxes).
|
|
5
|
+
*
|
|
6
|
+
* Taken HERE because nothing else can: the design tab is another origin than
|
|
7
|
+
* the proposal's page in its frame, and a browser lets no page photograph a
|
|
8
|
+
* frame of another origin. So the bridge renders its own document --
|
|
9
|
+
* `modern-screenshot` draws the DOM, with its computed styles, fonts and
|
|
10
|
+
* same-origin images, into a canvas -- and hands back a JPEG.
|
|
11
|
+
*
|
|
12
|
+
* It is a rendering of the DOM, not of the screen: an image from another
|
|
13
|
+
* origin that does not allow it, a video frame, a `<canvas>` a script drew
|
|
14
|
+
* and an iframe come out blank. Good enough to see a layout, a colour, a
|
|
15
|
+
* button that wrapped; the tool says what it cannot show.
|
|
16
|
+
*
|
|
17
|
+
* Loaded when asked: the library is not in a page that is never
|
|
18
|
+
* photographed.
|
|
19
|
+
*/
|
|
20
|
+
/** What `screenshotPage` answers. */
|
|
21
|
+
export type PageScreenshot = {
|
|
22
|
+
/** A JPEG, as a data URL. */
|
|
23
|
+
dataUrl: string;
|
|
24
|
+
width: number;
|
|
25
|
+
height: number;
|
|
26
|
+
/** The whole page, from the top, rather than what was on screen. */
|
|
27
|
+
fullPage: boolean;
|
|
28
|
+
/** The page went on below what the picture shows. */
|
|
29
|
+
clipped: boolean;
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* The page in `win`, as it is now: what is on screen, or (`fullPage`) the
|
|
33
|
+
* whole page from the top, cut off at {@link MAX_FULL_PAGE_HEIGHT}. Elements
|
|
34
|
+
* `exclude` says are not the page's -- the picker's highlight -- are left
|
|
35
|
+
* out.
|
|
36
|
+
*/
|
|
37
|
+
export declare function screenshotPage(win: Window, options?: {
|
|
38
|
+
fullPage?: boolean;
|
|
39
|
+
exclude?: (element: Element) => boolean;
|
|
40
|
+
}): Promise<PageScreenshot>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Json } from "@valbuild/core";
|
|
2
|
-
export declare const VAL_SESSION_COOKIE:
|
|
3
|
-
export declare const VAL_STATE_COOKIE:
|
|
4
|
-
export declare const VAL_ENABLE_COOKIE_NAME:
|
|
2
|
+
export declare const VAL_SESSION_COOKIE: "val_session";
|
|
3
|
+
export declare const VAL_STATE_COOKIE: "val_state";
|
|
4
|
+
export declare const VAL_ENABLE_COOKIE_NAME: "val_enable";
|
|
5
5
|
export type VAL_SESSION_COOKIE = typeof VAL_SESSION_COOKIE;
|
|
6
6
|
export type VAL_STATE_COOKIE = typeof VAL_STATE_COOKIE;
|
|
7
7
|
export type VAL_ENABLE_COOKIE_NAME = typeof VAL_ENABLE_COOKIE_NAME;
|
|
@@ -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[];
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
import type { ModuleFilePath, SourcePath } from "@valbuild/core";
|
|
23
23
|
import type { PickedElement, PickModifier } from "./elementPicker.js";
|
|
24
24
|
import type { PageLocation, PageSnapshot } from "./pageInspection.js";
|
|
25
|
+
import type { PageScreenshot } from "./pageScreenshot.js";
|
|
25
26
|
import { type QuickPreviewFiles } from "./quickPreview.js";
|
|
26
27
|
/** Marks a page load as the studio's canvas frame. */
|
|
27
28
|
export declare const VAL_CANVAS_PARAM = "val_canvas";
|
|
@@ -205,6 +206,16 @@ export type ValCanvasPageMessage = {
|
|
|
205
206
|
requestId: string;
|
|
206
207
|
snapshot: PageSnapshot | null;
|
|
207
208
|
error?: string;
|
|
209
|
+
} | {
|
|
210
|
+
/**
|
|
211
|
+
* What `screenshotPage` asked for: the page as a JPEG data URL, or why
|
|
212
|
+
* it could not be taken (`pageScreenshot.ts`).
|
|
213
|
+
*/
|
|
214
|
+
val: typeof VAL_CANVAS_MESSAGE;
|
|
215
|
+
type: "pageScreenshot";
|
|
216
|
+
requestId: string;
|
|
217
|
+
screenshot: PageScreenshot | null;
|
|
218
|
+
error?: string;
|
|
208
219
|
} | {
|
|
209
220
|
/**
|
|
210
221
|
* A quick preview's files are stored in the page's worker, and a page
|
|
@@ -334,6 +345,16 @@ export type ValCanvasStudioMessage = {
|
|
|
334
345
|
requestId: string;
|
|
335
346
|
selector?: string;
|
|
336
347
|
maxItems?: number;
|
|
348
|
+
} | {
|
|
349
|
+
/**
|
|
350
|
+
* Take a picture of the page (`screenshotPage`): the assistant's
|
|
351
|
+
* `screenshot_page`. Answered with `pageScreenshot` and the same
|
|
352
|
+
* `requestId`; a bridge that predates it never answers.
|
|
353
|
+
*/
|
|
354
|
+
val: typeof VAL_CANVAS_MESSAGE;
|
|
355
|
+
type: "screenshotPage";
|
|
356
|
+
requestId: string;
|
|
357
|
+
fullPage?: boolean;
|
|
337
358
|
} | {
|
|
338
359
|
/**
|
|
339
360
|
* Store a quick preview's files in this origin's worker
|
|
@@ -64,9 +64,9 @@ export declare const BinaryFileRef: z.ZodObject<{
|
|
|
64
64
|
}, z.core.$strip>;
|
|
65
65
|
export type BinaryFileRef = z.infer<typeof BinaryFileRef>;
|
|
66
66
|
export declare const HistoricalModule: z.ZodObject<{
|
|
67
|
-
source: z.ZodNullable<z.ZodType<
|
|
68
|
-
schema: z.ZodNullable<z.ZodType<
|
|
69
|
-
patchIds: z.ZodArray<z.ZodString & z.ZodType<
|
|
67
|
+
source: z.ZodNullable<z.ZodType<import("@valbuild/core/patch").JSONValue, unknown, z.core.$ZodTypeInternals<import("@valbuild/core/patch").JSONValue, unknown>>>;
|
|
68
|
+
schema: z.ZodNullable<z.ZodType<import("@valbuild/core").SerializedSchema, unknown, z.core.$ZodTypeInternals<import("@valbuild/core").SerializedSchema, unknown>>>;
|
|
69
|
+
patchIds: z.ZodArray<z.ZodString & z.ZodType<import("@valbuild/core").PatchId, string, z.core.$ZodTypeInternals<import("@valbuild/core").PatchId, string>>>;
|
|
70
70
|
changedPaths: z.ZodArray<z.ZodString>;
|
|
71
71
|
failures: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
72
72
|
kind: z.ZodLiteral<"commit-not-found">;
|
|
@@ -109,9 +109,9 @@ export declare const HistoricalPatchSet: z.ZodObject<{
|
|
|
109
109
|
hasArchive: z.ZodBoolean;
|
|
110
110
|
}, z.core.$strip>;
|
|
111
111
|
modules: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
112
|
-
source: z.ZodNullable<z.ZodType<
|
|
113
|
-
schema: z.ZodNullable<z.ZodType<
|
|
114
|
-
patchIds: z.ZodArray<z.ZodString & z.ZodType<
|
|
112
|
+
source: z.ZodNullable<z.ZodType<import("@valbuild/core/patch").JSONValue, unknown, z.core.$ZodTypeInternals<import("@valbuild/core/patch").JSONValue, unknown>>>;
|
|
113
|
+
schema: z.ZodNullable<z.ZodType<import("@valbuild/core").SerializedSchema, unknown, z.core.$ZodTypeInternals<import("@valbuild/core").SerializedSchema, unknown>>>;
|
|
114
|
+
patchIds: z.ZodArray<z.ZodString & z.ZodType<import("@valbuild/core").PatchId, string, z.core.$ZodTypeInternals<import("@valbuild/core").PatchId, string>>>;
|
|
115
115
|
changedPaths: z.ZodArray<z.ZodString>;
|
|
116
116
|
failures: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
117
117
|
kind: z.ZodLiteral<"commit-not-found">;
|
|
@@ -139,7 +139,7 @@ export declare const HistoricalPatchSet: z.ZodObject<{
|
|
|
139
139
|
}, z.core.$strip>], "kind">>;
|
|
140
140
|
}, z.core.$strip>>;
|
|
141
141
|
patches: z.ZodArray<z.ZodObject<{
|
|
142
|
-
patchId: z.ZodString & z.ZodType<
|
|
142
|
+
patchId: z.ZodString & z.ZodType<import("@valbuild/core").PatchId, string, z.core.$ZodTypeInternals<import("@valbuild/core").PatchId, string>>;
|
|
143
143
|
moduleFilePath: z.ZodString;
|
|
144
144
|
patch: z.ZodUnknown;
|
|
145
145
|
authorId: z.ZodNullable<z.ZodString>;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { JSONValue as JSONValueT, PatchJSON as PatchJSONT, PatchBlock as PatchBlockT, ParentRef as ParentRefT } from "@valbuild/core/patch";
|
|
2
|
+
import type { PatchId as PatchIdT } from "@valbuild/core";
|
|
2
3
|
import { z } from "zod";
|
|
3
4
|
/**
|
|
4
5
|
* JSON, recursively — the shape of a Source over the wire.
|
|
@@ -66,7 +66,25 @@ export declare const ColorOptions: z.ZodObject<{
|
|
|
66
66
|
export declare const SerializedColorSchema: z.ZodType<SerializedColorSchemaT>;
|
|
67
67
|
export declare const CodeOptions: z.ZodObject<{
|
|
68
68
|
language: z.ZodOptional<z.ZodEnum<{
|
|
69
|
-
|
|
69
|
+
html: "html";
|
|
70
|
+
css: "css";
|
|
71
|
+
json: "json";
|
|
72
|
+
typescript: "typescript";
|
|
73
|
+
javascript: "javascript";
|
|
74
|
+
javascriptreact: "javascriptreact";
|
|
75
|
+
typescriptreact: "typescriptreact";
|
|
76
|
+
java: "java";
|
|
77
|
+
xml: "xml";
|
|
78
|
+
markdown: "markdown";
|
|
79
|
+
sql: "sql";
|
|
80
|
+
python: "python";
|
|
81
|
+
rust: "rust";
|
|
82
|
+
php: "php";
|
|
83
|
+
go: "go";
|
|
84
|
+
cpp: "cpp";
|
|
85
|
+
sass: "sass";
|
|
86
|
+
vue: "vue";
|
|
87
|
+
angular: "angular";
|
|
70
88
|
}>>;
|
|
71
89
|
}, z.core.$strip>;
|
|
72
90
|
export declare const SerializedCodeSchema: z.ZodType<SerializedCodeSchemaT>;
|
|
@@ -83,7 +101,7 @@ export declare const SerializedSettingsSchema: z.ZodType<SerializedSettingsSchem
|
|
|
83
101
|
*/
|
|
84
102
|
export declare const SerializedValViewSchema: z.ZodObject<{
|
|
85
103
|
type: z.ZodLiteral<"view">;
|
|
86
|
-
moduleFilePath: z.ZodType<
|
|
104
|
+
moduleFilePath: z.ZodType<import("@valbuild/core").ModuleFilePath, unknown, z.core.$ZodTypeInternals<import("@valbuild/core").ModuleFilePath, unknown>>;
|
|
87
105
|
opt: z.ZodLiteral<false>;
|
|
88
106
|
readonly: z.ZodOptional<z.ZodBoolean>;
|
|
89
107
|
hidden: z.ZodOptional<z.ZodBoolean>;
|
|
@@ -322,7 +322,7 @@ function isValCanvasPageMessage(data) {
|
|
|
322
322
|
if (_typeof(data) !== "object" || data === null) return false;
|
|
323
323
|
var message = data;
|
|
324
324
|
if (message.val !== VAL_CANVAS_MESSAGE) return false;
|
|
325
|
-
return message.type === "ready" || message.type === "elements" || message.type === "clicked" || message.type === "pinch" || message.type === "zoom" || message.type === "refreshing" || message.type === "elementPickingStopped" || message.type === "elementPicked" && isPickedElement(data.element) || message.type === "location" && isPageLocation(data) || message.type === "pageRead" && typeof data.requestId === "string" || message.type === "quickPreviewStored" && typeof data.id === "string";
|
|
325
|
+
return message.type === "ready" || message.type === "elements" || message.type === "clicked" || message.type === "pinch" || message.type === "zoom" || message.type === "refreshing" || message.type === "elementPickingStopped" || message.type === "elementPicked" && isPickedElement(data.element) || message.type === "location" && isPageLocation(data) || message.type === "pageRead" && typeof data.requestId === "string" || message.type === "pageScreenshot" && typeof data.requestId === "string" || message.type === "quickPreviewStored" && typeof data.id === "string";
|
|
326
326
|
}
|
|
327
327
|
function isPageLocation(value) {
|
|
328
328
|
var location = value;
|
|
@@ -379,6 +379,10 @@ function isValCanvasStudioMessage(data) {
|
|
|
379
379
|
var preview = data;
|
|
380
380
|
return typeof preview.id === "string" && /^[A-Za-z0-9_-]{1,64}$/.test(preview.id) && isQuickPreviewFiles(preview.files);
|
|
381
381
|
}
|
|
382
|
+
if (message.type === "screenshotPage") {
|
|
383
|
+
var asked = data;
|
|
384
|
+
return typeof asked.requestId === "string" && (asked.fullPage === undefined || typeof asked.fullPage === "boolean");
|
|
385
|
+
}
|
|
382
386
|
if (message.type === "readPage") {
|
|
383
387
|
var read = data;
|
|
384
388
|
return typeof read.requestId === "string" && (read.selector === undefined || typeof read.selector === "string") && (read.maxItems === undefined || typeof read.maxItems === "number");
|
|
@@ -1137,6 +1141,137 @@ function selectorOf(element, root) {
|
|
|
1137
1141
|
return parts.join(" > ");
|
|
1138
1142
|
}
|
|
1139
1143
|
|
|
1144
|
+
/**
|
|
1145
|
+
* A picture of the page, taken in the page: the assistant's
|
|
1146
|
+
* `screenshot_page`, so it can see a change it made rather than only read it
|
|
1147
|
+
* (`read_page` gives the words and the boxes).
|
|
1148
|
+
*
|
|
1149
|
+
* Taken HERE because nothing else can: the design tab is another origin than
|
|
1150
|
+
* the proposal's page in its frame, and a browser lets no page photograph a
|
|
1151
|
+
* frame of another origin. So the bridge renders its own document --
|
|
1152
|
+
* `modern-screenshot` draws the DOM, with its computed styles, fonts and
|
|
1153
|
+
* same-origin images, into a canvas -- and hands back a JPEG.
|
|
1154
|
+
*
|
|
1155
|
+
* It is a rendering of the DOM, not of the screen: an image from another
|
|
1156
|
+
* origin that does not allow it, a video frame, a `<canvas>` a script drew
|
|
1157
|
+
* and an iframe come out blank. Good enough to see a layout, a colour, a
|
|
1158
|
+
* button that wrapped; the tool says what it cannot show.
|
|
1159
|
+
*
|
|
1160
|
+
* Loaded when asked: the library is not in a page that is never
|
|
1161
|
+
* photographed.
|
|
1162
|
+
*/
|
|
1163
|
+
|
|
1164
|
+
/** What `screenshotPage` answers. */
|
|
1165
|
+
|
|
1166
|
+
/** Wider than this is scaled down: a model reads a page no better larger. */
|
|
1167
|
+
var MAX_WIDTH = 1280;
|
|
1168
|
+
/** A whole page longer than this, in CSS pixels, is cut off below it. */
|
|
1169
|
+
var MAX_FULL_PAGE_HEIGHT = 4000;
|
|
1170
|
+
var JPEG_QUALITY = 0.85;
|
|
1171
|
+
/** How long an image or a font on the page is waited for. */
|
|
1172
|
+
var LOAD_TIMEOUT_MS = 8000;
|
|
1173
|
+
|
|
1174
|
+
/**
|
|
1175
|
+
* The page in `win`, as it is now: what is on screen, or (`fullPage`) the
|
|
1176
|
+
* whole page from the top, cut off at {@link MAX_FULL_PAGE_HEIGHT}. Elements
|
|
1177
|
+
* `exclude` says are not the page's -- the picker's highlight -- are left
|
|
1178
|
+
* out.
|
|
1179
|
+
*/
|
|
1180
|
+
function screenshotPage(_x) {
|
|
1181
|
+
return _screenshotPage.apply(this, arguments);
|
|
1182
|
+
}
|
|
1183
|
+
|
|
1184
|
+
/** What the page is drawn on: the body's background, else the root's, else white. */
|
|
1185
|
+
function _screenshotPage() {
|
|
1186
|
+
_screenshotPage = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee(win) {
|
|
1187
|
+
var _doc$body$scrollHeigh, _doc$body;
|
|
1188
|
+
var options,
|
|
1189
|
+
_yield$import,
|
|
1190
|
+
domToCanvas,
|
|
1191
|
+
doc,
|
|
1192
|
+
root,
|
|
1193
|
+
fullPage,
|
|
1194
|
+
pageWidth,
|
|
1195
|
+
pageHeight,
|
|
1196
|
+
top,
|
|
1197
|
+
height,
|
|
1198
|
+
exclude,
|
|
1199
|
+
drawn,
|
|
1200
|
+
scale,
|
|
1201
|
+
out,
|
|
1202
|
+
context,
|
|
1203
|
+
_args = arguments;
|
|
1204
|
+
return _regenerator().w(function (_context) {
|
|
1205
|
+
while (1) switch (_context.n) {
|
|
1206
|
+
case 0:
|
|
1207
|
+
options = _args.length > 1 && _args[1] !== undefined ? _args[1] : {};
|
|
1208
|
+
_context.n = 1;
|
|
1209
|
+
return import('modern-screenshot');
|
|
1210
|
+
case 1:
|
|
1211
|
+
_yield$import = _context.v;
|
|
1212
|
+
domToCanvas = _yield$import.domToCanvas;
|
|
1213
|
+
doc = win.document;
|
|
1214
|
+
root = doc.documentElement;
|
|
1215
|
+
fullPage = options.fullPage === true;
|
|
1216
|
+
pageWidth = root.clientWidth || win.innerWidth;
|
|
1217
|
+
pageHeight = Math.max(root.scrollHeight, (_doc$body$scrollHeigh = (_doc$body = doc.body) === null || _doc$body === void 0 ? void 0 : _doc$body.scrollHeight) !== null && _doc$body$scrollHeigh !== void 0 ? _doc$body$scrollHeigh : 0);
|
|
1218
|
+
top = fullPage ? 0 : win.scrollY;
|
|
1219
|
+
height = fullPage ? Math.min(pageHeight, MAX_FULL_PAGE_HEIGHT) : Math.min(win.innerHeight, pageHeight - top);
|
|
1220
|
+
exclude = options.exclude; // Drawn to the bottom of what is wanted, and no further: the cost is the
|
|
1221
|
+
// page's size, so a viewport near the top is cheap.
|
|
1222
|
+
_context.n = 2;
|
|
1223
|
+
return domToCanvas(root, _objectSpread2({
|
|
1224
|
+
width: pageWidth,
|
|
1225
|
+
height: top + height,
|
|
1226
|
+
scale: 1,
|
|
1227
|
+
backgroundColor: pageBackground(win),
|
|
1228
|
+
timeout: LOAD_TIMEOUT_MS
|
|
1229
|
+
}, exclude !== undefined ? {
|
|
1230
|
+
filter: function filter(node) {
|
|
1231
|
+
return !(isElement(node) && exclude(node));
|
|
1232
|
+
}
|
|
1233
|
+
} : {}));
|
|
1234
|
+
case 2:
|
|
1235
|
+
drawn = _context.v;
|
|
1236
|
+
scale = Math.min(1, MAX_WIDTH / pageWidth);
|
|
1237
|
+
out = doc.createElement("canvas");
|
|
1238
|
+
out.width = Math.round(pageWidth * scale);
|
|
1239
|
+
out.height = Math.round(height * scale);
|
|
1240
|
+
context = out.getContext("2d");
|
|
1241
|
+
if (!(context === null)) {
|
|
1242
|
+
_context.n = 3;
|
|
1243
|
+
break;
|
|
1244
|
+
}
|
|
1245
|
+
throw new Error("This browser would not draw the picture.");
|
|
1246
|
+
case 3:
|
|
1247
|
+
context.drawImage(drawn, 0, top, pageWidth, height, 0, 0, out.width, out.height);
|
|
1248
|
+
return _context.a(2, {
|
|
1249
|
+
dataUrl: out.toDataURL("image/jpeg", JPEG_QUALITY),
|
|
1250
|
+
width: out.width,
|
|
1251
|
+
height: out.height,
|
|
1252
|
+
fullPage: fullPage,
|
|
1253
|
+
clipped: top + height < pageHeight
|
|
1254
|
+
});
|
|
1255
|
+
}
|
|
1256
|
+
}, _callee);
|
|
1257
|
+
}));
|
|
1258
|
+
return _screenshotPage.apply(this, arguments);
|
|
1259
|
+
}
|
|
1260
|
+
function pageBackground(win) {
|
|
1261
|
+
for (var _i = 0, _arr = [win.document.body, win.document.documentElement]; _i < _arr.length; _i++) {
|
|
1262
|
+
var element = _arr[_i];
|
|
1263
|
+
if (element === null) continue;
|
|
1264
|
+
var color = win.getComputedStyle(element).backgroundColor;
|
|
1265
|
+
if (color && color !== "transparent" && color !== "rgba(0, 0, 0, 0)") {
|
|
1266
|
+
return color;
|
|
1267
|
+
}
|
|
1268
|
+
}
|
|
1269
|
+
return "#ffffff";
|
|
1270
|
+
}
|
|
1271
|
+
function isElement(node) {
|
|
1272
|
+
return node.nodeType === 1;
|
|
1273
|
+
}
|
|
1274
|
+
|
|
1140
1275
|
function parseRoutePattern(pattern) {
|
|
1141
1276
|
if (pattern === "" || pattern === "/") {
|
|
1142
1277
|
return [];
|
|
@@ -1378,4 +1513,4 @@ function getPatternFromModuleFilePath(moduleFilePath, srcFolder) {
|
|
|
1378
1513
|
.replace("/page.val.ts", "").replace("/page.val.js", "");
|
|
1379
1514
|
}
|
|
1380
1515
|
|
|
1381
|
-
export {
|
|
1516
|
+
export { withQuickPreviewParam as A, quickPreviewSiteOrigin as B, isDesignTabOrigin as C, DEFAULT_CANVAS_SELECTION as D, parseRoutePattern as E, formatRoutePattern as F, getNextAppRouterSourceFolder as G, getTanStackRouterSourceFolder as H, getPageRouterSourceFolder as I, isTanStackRoutesFolder as J, getPageRouterSitemapTree as K, getPatternFromModuleFilePath as L, QUICK_PREVIEW_PARAM as Q, VAL_CONFIG_SESSION_STORAGE_KEY as V, VAL_THEME_SESSION_STORAGE_KEY as a, VAL_AI_SESSION_STORAGE_KEY as b, VAL_CANVAS_PARAM as c, VAL_CANVAS_MESSAGE as d, DEFAULT_CANVAS_SELECTION_SOFT as e, isValCanvasStudioMessage as f, isValCanvasFrame as g, describeElement as h, isValCanvasPageMessage as i, attachElementPicker as j, createPickerOverlay as k, elementLabel as l, modifierLabel as m, watchPageLocation as n, readPageSnapshot as o, pageLocationOf as p, findBySelector as q, restoreScroll as r, startElementPicking as s, screenshotPage as t, QUICK_PREVIEW_SERVICE_WORKER_PATH as u, QUICK_PREVIEW_STORE_MESSAGE as v, withValCanvasParam as w, isQuickPreviewFiles as x, QUICK_PREVIEW_SERVICE_WORKER_SOURCE as y, storeQuickPreview as z };
|