@valbuild/core 0.111.0 → 0.120.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,97 @@
1
+ # @valbuild/core
2
+
3
+ ## 0.120.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#589](https://github.com/valbuild/val/pull/589) [`c2d3c0e`](https://github.com/valbuild/val/commit/c2d3c0e6c2010c0a94c725d9dbaa618998773e8a) Thanks [@freekh](https://github.com/freekh)! - **Breaking:** `s.richtext()` options are flat.
8
+
9
+ The `style`, `block` and `inline` groups are gone — every option is a key of its
10
+ own. The names are unchanged, so updating a schema is only a matter of removing
11
+ the wrappers:
12
+
13
+ ```ts
14
+ // before
15
+ s.richtext({
16
+ style: { bold: true, italic: true },
17
+ block: { h1: true, ul: true },
18
+ inline: { a: true, img: s.image() },
19
+ });
20
+
21
+ // after
22
+ s.richtext({
23
+ bold: true,
24
+ italic: true,
25
+ h1: true,
26
+ ul: true,
27
+ a: true,
28
+ img: s.image(),
29
+ });
30
+ ```
31
+
32
+ The groups never carried any meaning the option names did not already have, and
33
+ they cost something real: an option name and its `ValRichText` theme key were
34
+ spelled differently (`block.h1` vs `theme.h1`), so the type that keeps a theme
35
+ exhaustive had to restate all thirteen options by hand. It is now a mapped type
36
+ over the options themselves — which also fixes an inconsistency in it: enabling
37
+ links with a schema (`a: s.route()`) rather than `a: true` now requires an `a`
38
+ key in the theme, the way `img` always has.
39
+
40
+ `ValRichText` themes were already flat and are unchanged. The serialized schema
41
+ that the server sends the Studio is flat too, so a project must not mix
42
+ `@valbuild/*` versions across this release.
43
+
44
+ ## 0.117.0
45
+
46
+ ### Patch Changes
47
+
48
+ - [#581](https://github.com/valbuild/val/pull/581) [`d94a40f`](https://github.com/valbuild/val/commit/d94a40f8bd11027636d183e293aced820b6f341f) Thanks [@freekh](https://github.com/freekh)! - Images no longer show a validation warning in the editor when nothing is wrong
49
+ with them.
50
+
51
+ Every `s.image()` carrying width, height or a mime type used to be marked in VS
52
+ Code with "Found image metadata, but it could not be validated", whether or not
53
+ the metadata was correct — so the warning sat on every image in the project and
54
+ never went away, not even after applying its own quick fix.
55
+
56
+ That message was never a finding. `@valbuild/core` cannot read files, so it
57
+ cannot answer whether stored dimensions match the image, and it hands the
58
+ question on as an `image:check-metadata` fix instead. `val validate` has always
59
+ resolved that by reading the file and comparing; the language server now does
60
+ the same, and reports only what actually disagrees:
61
+
62
+ ```
63
+ Image width is incorrect! Found: 800. Expected: 944
64
+ ```
65
+
66
+ An image whose metadata is right gets nothing. A missing `width`, `height` or
67
+ `mimeType` is reported, as is a stale one, with the quick fix still offered. A
68
+ file that is not on disk is still reported as a missing file rather than as a
69
+ metadata problem.
70
+
71
+ The four messages involved say what they mean now, in the editor and in
72
+ `val validate` alike:
73
+
74
+ - "Image metadata has not been checked against the file." (was "Found image
75
+ metadata, but it could not be validated. An image must have a width (positive
76
+ number), a height (positive number) and a mime type." — which described a
77
+ check that never ran)
78
+ - "Image metadata is missing: width, height and mimeType." (was "Could not
79
+ validate Image metadata.")
80
+ - "File mimeType has not been checked against the file." (was "Found mimeType,
81
+ but it could not be validated.")
82
+ - "File metadata is missing: mimeType." (was "Missing File mimeType.")
83
+
84
+ Also fixes an `s.file()` whose `mimeType` is missing: it reported "Mime type and
85
+ file extension not matching. Mime type is 'undefined'" with no fix attached, so
86
+ no quick fix was offered and the `file:add-metadata` case was unreachable. It
87
+ now reports the missing mime type and offers to add it.
88
+
89
+ - [#579](https://github.com/valbuild/val/pull/579) [`b2812ae`](https://github.com/valbuild/val/commit/b2812ae4ee03e005ecead3365f49c625e536f94d) Thanks [@freekh](https://github.com/freekh)! - Every release now ships a changelog. Each package's `CHANGELOG.md` records what
90
+ changed under the version that shipped it — with a link to the pull request, the
91
+ commit and the author — and the same entry becomes the body of the GitHub
92
+ Release for the tag. The file is included in the npm tarball, so it is also
93
+ readable from an installed copy.
94
+
95
+ Up to now those changelogs were generated empty, and the GitHub Releases with
96
+ them, so there was no record of what any given version contained. Releases from
97
+ this one on have one; earlier versions stay blank.
@@ -31,7 +31,7 @@ import { ModulePath, SourcePath, getValPath, isVal } from "./val/index.js";
31
31
  import { createValPathOfItem } from "./selector/SelectorProxy.js";
32
32
  import { Operation } from "./patch/index.js";
33
33
  import { initSchema } from "./initSchema.js";
34
- import { getMimeType, mimeTypeToFileExt, filenameToMimeType } from "./mimeType/index.js";
34
+ import { getMimeType, mimeTypeToFileExt, filenameToMimeType, mimeTypeMatchesAccept } from "./mimeType/index.js";
35
35
  import { type ImageMetadata } from "./schema/image.js";
36
36
  import { type FileMetadata } from "./schema/file.js";
37
37
  import { isJson, getJsonImport, resolveJsonValues } from "./source/json.js";
@@ -114,6 +114,7 @@ declare const Internal: {
114
114
  getMimeType: typeof getMimeType;
115
115
  mimeTypeToFileExt: typeof mimeTypeToFileExt;
116
116
  filenameToMimeType: typeof filenameToMimeType;
117
+ mimeTypeMatchesAccept: typeof mimeTypeMatchesAccept;
117
118
  EXT_TO_MIME_TYPES: Record<string, string>;
118
119
  MIME_TYPES_TO_EXT: {
119
120
  [k: string]: string;
@@ -1,3 +1,17 @@
1
1
  export declare function getMimeType(base64Url: string): string | undefined;
2
2
  export declare function mimeTypeToFileExt(mimeType: string): string;
3
3
  export declare function filenameToMimeType(filename: string): string | undefined;
4
+ /**
5
+ * Whether `mimeType` satisfies an `accept` string.
6
+ *
7
+ * `accept` is the HTML file-input syntax: a comma-separated list of exact mime
8
+ * types (`image/png`), type wildcards (`image` followed by `/` and a star) or
9
+ * the catch-all star-slash-star.
10
+ *
11
+ * This lived in three places - `ImageSchema`, `FileSchema` and the media
12
+ * branch of `RecordSchema` - which is how the third copy grew a redundant
13
+ * `image` wildcard case that the general wildcard branch already covered.
14
+ * Anything that has to decide whether an `accept` is satisfied, validation and
15
+ * editor tooling alike, should call this.
16
+ */
17
+ export declare function mimeTypeMatchesAccept(mimeType: string, accept: string): boolean;
@@ -15,7 +15,7 @@ export type SerializedRichTextSchema = {
15
15
  /** Set when this schema declares a `preview`. The closure itself cannot serialize. */
16
16
  preview?: true;
17
17
  opt: boolean;
18
- options?: SerializedRichTextOptions & ValidationOptions;
18
+ options?: SerializedRichTextOptions;
19
19
  customValidate?: boolean;
20
20
  readonly?: boolean;
21
21
  hidden?: boolean;
@@ -3,71 +3,60 @@ import { RouteSchema, SerializedRouteSchema } from "../schema/route.js";
3
3
  import { StringSchema, SerializedStringSchema } from "../schema/string.js";
4
4
  import { ImageSource } from "./media.js";
5
5
  export type RichTextOptions = Partial<{
6
- style: Partial<{
7
- bold: boolean;
8
- italic: boolean;
9
- lineThrough: boolean;
10
- }>;
11
- block: Partial<{
12
- h1: boolean;
13
- h2: boolean;
14
- h3: boolean;
15
- h4: boolean;
16
- h5: boolean;
17
- h6: boolean;
18
- ul: boolean;
19
- ol: boolean;
20
- }>;
21
- inline: Partial<{
22
- a: boolean | RouteSchema<string> | StringSchema<string>;
23
- img: boolean | ImageSchema<ImageSource>;
24
- }>;
6
+ bold: boolean;
7
+ italic: boolean;
8
+ lineThrough: boolean;
9
+ h1: boolean;
10
+ h2: boolean;
11
+ h3: boolean;
12
+ h4: boolean;
13
+ h5: boolean;
14
+ h6: boolean;
15
+ ul: boolean;
16
+ ol: boolean;
17
+ a: boolean | RouteSchema<string> | StringSchema<string>;
18
+ img: boolean | ImageSchema<ImageSource>;
25
19
  }>;
26
20
  export type SerializedRichTextOptions = Partial<{
27
- style: Partial<{
28
- bold: boolean;
29
- italic: boolean;
30
- lineThrough: boolean;
31
- }>;
32
- block: Partial<{
33
- h1: boolean;
34
- h2: boolean;
35
- h3: boolean;
36
- h4: boolean;
37
- h5: boolean;
38
- h6: boolean;
39
- ul: boolean;
40
- ol: boolean;
41
- }>;
42
- inline: Partial<{
43
- a: boolean | SerializedRouteSchema | SerializedStringSchema;
44
- img: boolean | SerializedImageSchema;
45
- }>;
21
+ /**
22
+ * `.maxLength()` / `.minLength()` are not authored in the options argument,
23
+ * but they serialize into the same object - so the wire type has to name
24
+ * them, or a parser that strips unknown keys drops them in transit.
25
+ */
26
+ maxLength: number;
27
+ minLength: number;
28
+ bold: boolean;
29
+ italic: boolean;
30
+ lineThrough: boolean;
31
+ h1: boolean;
32
+ h2: boolean;
33
+ h3: boolean;
34
+ h4: boolean;
35
+ h5: boolean;
36
+ h6: boolean;
37
+ ul: boolean;
38
+ ol: boolean;
39
+ a: boolean | SerializedRouteSchema | SerializedStringSchema;
40
+ img: boolean | SerializedImageSchema;
46
41
  }>;
47
42
  export type AllRichTextOptions = {
48
- style: {
49
- bold: true;
50
- italic: true;
51
- lineThrough: true;
52
- };
53
- block: {
54
- h1: true;
55
- h2: true;
56
- h3: true;
57
- h4: true;
58
- h5: true;
59
- h6: true;
60
- ul: true;
61
- ol: true;
62
- };
63
- inline: {
64
- a: true;
65
- img: true;
66
- };
43
+ bold: true;
44
+ italic: true;
45
+ lineThrough: true;
46
+ h1: true;
47
+ h2: true;
48
+ h3: true;
49
+ h4: true;
50
+ h5: true;
51
+ h6: true;
52
+ ul: true;
53
+ ol: true;
54
+ a: true;
55
+ img: true;
67
56
  };
68
- export type LineThrough<O extends RichTextOptions> = NonNullable<O["style"]>["lineThrough"] extends true ? "line-through" : never;
69
- export type Italic<O extends RichTextOptions> = NonNullable<O["style"]>["italic"] extends true ? "italic" : never;
70
- export type Bold<O extends RichTextOptions> = NonNullable<O["style"]>["bold"] extends true ? "bold" : never;
57
+ export type LineThrough<O extends RichTextOptions> = O["lineThrough"] extends true ? "line-through" : never;
58
+ export type Italic<O extends RichTextOptions> = O["italic"] extends true ? "italic" : never;
59
+ export type Bold<O extends RichTextOptions> = O["bold"] extends true ? "bold" : never;
71
60
  export type Styles<O extends RichTextOptions> = LineThrough<O> | Italic<O> | Bold<O>;
72
61
  export type GenericRichTextSourceNode = {
73
62
  tag: string;
@@ -88,10 +77,10 @@ export type SpanNode<O extends RichTextOptions> = {
88
77
  styles: Styles<O>[];
89
78
  children: [string];
90
79
  };
91
- export type ImageNode<O extends RichTextOptions> = NonNullable<O["inline"]>["img"] extends true ? {
80
+ export type ImageNode<O extends RichTextOptions> = O["img"] extends true ? {
92
81
  tag: "img";
93
82
  src: ImageSource;
94
- } : NonNullable<O["inline"]>["img"] extends ImageSchema<infer Src> ? Src extends ImageSource ? {
83
+ } : O["img"] extends ImageSchema<infer Src> ? Src extends ImageSource ? {
95
84
  tag: "img";
96
85
  src: Src;
97
86
  } : never : never;
@@ -100,21 +89,22 @@ type LinkTagNode<O extends RichTextOptions> = {
100
89
  href: string;
101
90
  children: (string | SpanNode<O> | ImageNode<O> | CustomInlineNode<O>)[];
102
91
  };
103
- export type LinkNode<O extends RichTextOptions> = NonNullable<O["inline"]>["a"] extends true ? LinkTagNode<O> : NonNullable<O["inline"]>["a"] extends RouteSchema<string> | StringSchema<string> ? LinkTagNode<O> : never;
92
+ export type LinkNode<O extends RichTextOptions> = O["a"] extends true ? LinkTagNode<O> : O["a"] extends RouteSchema<string> | StringSchema<string> ? LinkTagNode<O> : never;
104
93
  type ListItemTagNode<O extends RichTextOptions> = {
105
94
  tag: "li";
106
95
  children: (ParagraphNode<O> | UnorderedListNode<O> | OrderedListNode<O>)[];
107
96
  };
108
- export type ListItemNode<O extends RichTextOptions> = NonNullable<O["block"]>["ul"] extends true ? ListItemTagNode<O> : never | NonNullable<O["block"]>["ol"] extends true ? ListItemTagNode<O> : never;
109
- export type UnorderedListNode<O extends RichTextOptions> = NonNullable<O["block"]>["ul"] extends true ? {
97
+ export type ListItemNode<O extends RichTextOptions> = O["ul"] extends true ? ListItemTagNode<O> : O["ol"] extends true ? ListItemTagNode<O> : never;
98
+ export type UnorderedListNode<O extends RichTextOptions> = O["ul"] extends true ? {
110
99
  tag: "ul";
111
100
  children: ListItemNode<O>[];
112
101
  } : never;
113
- export type OrderedListNode<O extends RichTextOptions> = NonNullable<O["block"]>["ol"] extends true ? {
102
+ export type OrderedListNode<O extends RichTextOptions> = O["ol"] extends true ? {
114
103
  tag: "ol";
115
104
  children: ListItemNode<O>[];
116
105
  } : never;
117
- export type HeadingTagOf<S extends keyof NonNullable<NonNullable<O["block"]>>, O extends RichTextOptions> = NonNullable<NonNullable<O["block"]>>[S] extends true ? {
106
+ export type HeadingTag = "h1" | "h2" | "h3" | "h4" | "h5" | "h6";
107
+ export type HeadingTagOf<S extends HeadingTag, O extends RichTextOptions> = O[S] extends true ? {
118
108
  tag: S;
119
109
  children: (string | SpanNode<O> | CustomInlineNode<O> | LinkNode<O> | BrNode | ImageNode<O>)[];
120
110
  } : never;