@valbuild/core 0.18.0 → 0.20.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.
Files changed (41) hide show
  1. package/dist/declarations/src/index.d.ts +4 -1
  2. package/dist/declarations/src/initSchema.d.ts +2 -2
  3. package/dist/declarations/src/patch/deref.d.ts +2 -1
  4. package/dist/declarations/src/patch/operation.d.ts +8 -0
  5. package/dist/declarations/src/schema/richtext.d.ts +7 -6
  6. package/dist/declarations/src/schema/string.d.ts +6 -3
  7. package/dist/declarations/src/selector/future/index.d.ts +3 -3
  8. package/dist/declarations/src/selector/index.d.ts +3 -3
  9. package/dist/declarations/src/source/future/remote.d.ts +2 -2
  10. package/dist/declarations/src/source/index.d.ts +3 -3
  11. package/dist/declarations/src/source/richtext.d.ts +70 -54
  12. package/dist/{index-4abf3a1f.esm.js → index-5d1ab97c.esm.js} +1 -1
  13. package/dist/{index-a9235737.esm.js → index-bccf1907.esm.js} +1 -1
  14. package/dist/{ops-a2a295f8.esm.js → ops-22b624eb.esm.js} +107 -35
  15. package/dist/{ops-f3015423.cjs.dev.js → ops-b0a33248.cjs.dev.js} +106 -33
  16. package/dist/{ops-0d09f8ee.cjs.prod.js → ops-def81fc3.cjs.prod.js} +106 -33
  17. package/dist/valbuild-core.cjs.dev.js +202 -104
  18. package/dist/valbuild-core.cjs.prod.js +202 -104
  19. package/dist/valbuild-core.esm.js +184 -106
  20. package/expr/dist/valbuild-core-expr.esm.js +2 -2
  21. package/package.json +4 -1
  22. package/patch/dist/valbuild-core-patch.cjs.dev.js +6 -1
  23. package/patch/dist/valbuild-core-patch.cjs.prod.js +6 -1
  24. package/patch/dist/valbuild-core-patch.esm.js +8 -3
  25. package/src/getSha256.ts +8 -0
  26. package/src/index.ts +21 -5
  27. package/src/module.ts +33 -2
  28. package/src/patch/deref.ts +14 -1
  29. package/src/patch/operation.ts +10 -0
  30. package/src/patch/parse.ts +1 -0
  31. package/src/patch/patch.ts +3 -0
  32. package/src/schema/richtext.ts +19 -73
  33. package/src/schema/string.ts +14 -4
  34. package/src/schema/validation.test.ts +2 -2
  35. package/src/selector/future/index.ts +8 -4
  36. package/src/selector/index.ts +4 -4
  37. package/src/source/future/remote.ts +2 -2
  38. package/src/source/index.ts +2 -2
  39. package/src/source/richtext.test.ts +178 -0
  40. package/src/source/richtext.ts +295 -89
  41. package/tsconfig.json +2 -1
@@ -1,98 +1,44 @@
1
1
  /* eslint-disable @typescript-eslint/no-unused-vars */
2
2
  import { Schema, SerializedSchema } from ".";
3
- import { VAL_EXTENSION } from "../source";
4
- import { RichTextSource } from "../source/richtext";
3
+ import { RichTextSource, RichTextOptions } from "../source/richtext";
5
4
  import { SourcePath } from "../val";
6
- import {
7
- ValidationError,
8
- ValidationErrors,
9
- } from "./validation/ValidationError";
5
+ import { ValidationErrors } from "./validation/ValidationError";
10
6
 
11
- export type SerializedRichTextSchema = {
7
+ export type SerializedRichTextSchema = RichTextOptions & {
12
8
  type: "richtext";
13
9
  opt: boolean;
14
10
  };
15
11
 
16
12
  export class RichTextSchema<
17
- Src extends RichTextSource | null
13
+ O extends RichTextOptions,
14
+ Src extends RichTextSource<O> | null
18
15
  > extends Schema<Src> {
19
- validate(path: SourcePath, src: Src): ValidationErrors {
20
- if (this.opt && (src === null || src === undefined)) {
21
- return false;
22
- }
23
- if (src === null || src === undefined) {
24
- return {
25
- [path]: [
26
- { message: `Expected non-nullable got '${src}'` } as ValidationError,
27
- ],
28
- } as ValidationErrors;
29
- }
30
-
31
- if (typeof src !== "object" && !Array.isArray(src)) {
32
- return {
33
- [path]: [
34
- {
35
- message: `Expected 'object' (that is not of an array) or 'string', got '${typeof src}'`,
36
- value: src,
37
- } as ValidationError,
38
- ],
39
- } as ValidationErrors;
40
- }
41
-
42
- if (src[VAL_EXTENSION] !== "richtext") {
43
- return {
44
- [path]: [
45
- {
46
- message: `Expected _type key with value 'richtext' got '${src[VAL_EXTENSION]}'`,
47
- value: src,
48
- } as ValidationError,
49
- ],
50
- } as ValidationErrors;
51
- }
52
-
53
- if (src.type !== "root") {
54
- return {
55
- [path]: [
56
- {
57
- message: `Expected type key with value 'root' got '${src.type}'`,
58
- value: src,
59
- } as ValidationError,
60
- ],
61
- } as ValidationErrors;
62
- }
63
-
64
- if (typeof src.children !== "object" && !Array.isArray(src.children)) {
65
- return {
66
- [path]: [
67
- {
68
- message: `Expected children to be an array, but got '${src.type}'`,
69
- value: src,
70
- } as ValidationError,
71
- ],
72
- } as ValidationErrors;
73
- }
16
+ constructor(readonly options: O, readonly opt: boolean = false) {
17
+ super();
18
+ }
74
19
 
75
- return false;
20
+ validate(path: SourcePath, src: Src): ValidationErrors {
21
+ return false; //TODO
76
22
  }
23
+
77
24
  assert(src: Src): boolean {
78
- // TODO:
79
- return true;
25
+ return true; // TODO
80
26
  }
81
27
 
82
- optional(): Schema<RichTextSource | null> {
83
- return new RichTextSchema(true);
28
+ optional(): Schema<RichTextSource<O> | null> {
29
+ return new RichTextSchema(this.options, true);
84
30
  }
31
+
85
32
  serialize(): SerializedSchema {
86
33
  return {
87
34
  type: "richtext",
88
35
  opt: this.opt,
89
36
  };
90
37
  }
91
- constructor(readonly opt: boolean = false) {
92
- super();
93
- }
94
38
  }
95
39
 
96
- export const richtext = (): Schema<RichTextSource> => {
97
- return new RichTextSchema();
40
+ export const richtext = <O extends RichTextOptions>(
41
+ options?: O
42
+ ): Schema<RichTextSource<O>> => {
43
+ return new RichTextSchema<O, RichTextSource<O>>(options ?? ({} as O));
98
44
  };
@@ -12,10 +12,15 @@ export type SerializedStringSchema = {
12
12
  type: "string";
13
13
  options?: StringOptions;
14
14
  opt: boolean;
15
+ raw: boolean;
15
16
  };
16
17
 
17
18
  export class StringSchema<Src extends string | null> extends Schema<Src> {
18
- constructor(readonly options?: StringOptions, readonly opt: boolean = false) {
19
+ constructor(
20
+ readonly options?: StringOptions,
21
+ readonly opt: boolean = false,
22
+ private readonly isRaw: boolean = false
23
+ ) {
19
24
  super();
20
25
  }
21
26
 
@@ -40,8 +45,12 @@ export class StringSchema<Src extends string | null> extends Schema<Src> {
40
45
  return typeof src === "string";
41
46
  }
42
47
 
43
- optional(): Schema<Src | null> {
44
- return new StringSchema<Src | null>(this.options, true);
48
+ optional(): StringSchema<Src | null> {
49
+ return new StringSchema<Src | null>(this.options, true, this.isRaw);
50
+ }
51
+
52
+ raw(): StringSchema<Src> {
53
+ return new StringSchema<Src>(this.options, this.opt, true);
45
54
  }
46
55
 
47
56
  serialize(): SerializedSchema {
@@ -49,12 +58,13 @@ export class StringSchema<Src extends string | null> extends Schema<Src> {
49
58
  type: "string",
50
59
  options: this.options,
51
60
  opt: this.opt,
61
+ raw: this.isRaw,
52
62
  };
53
63
  }
54
64
  }
55
65
 
56
66
  export const string = <T extends string>(
57
67
  options?: StringOptions
58
- ): Schema<T> => {
68
+ ): StringSchema<T> => {
59
69
  return new StringSchema(options);
60
70
  };
@@ -254,9 +254,9 @@ const ValidationTestCases: {
254
254
  // richtext
255
255
  {
256
256
  description: "basic richtext",
257
- input: richtextVal("test"),
257
+ input: richtextVal`test`,
258
258
  expected: false,
259
- schema: richtext(),
259
+ schema: richtext({ bold: true }),
260
260
  },
261
261
  // TODO: more richtext cases
262
262
  // TODO: union
@@ -24,7 +24,11 @@ import {
24
24
  RemoteSource,
25
25
  } from "../../source/future/remote";
26
26
  import { FileSource } from "../../source/file";
27
- import { RichText, RichTextSource } from "../../source/richtext";
27
+ import {
28
+ AnyRichTextOptions,
29
+ RichText,
30
+ RichTextSource,
31
+ } from "../../source/richtext";
28
32
 
29
33
  /**
30
34
  * Selectors can be used to select parts of a Val module.
@@ -57,8 +61,8 @@ export type Selector<T extends Source> = Source extends T
57
61
  : GenericSelector<Source, "Could not determine remote source">
58
62
  : T extends FileSource
59
63
  ? FileSelector
60
- : T extends RichTextSource
61
- ? RichText
64
+ : T extends RichTextSource<infer O>
65
+ ? RichText<O>
62
66
  : T extends SourceObject
63
67
  ? ObjectSelector<T>
64
68
  : T extends SourceArray
@@ -83,7 +87,7 @@ export type SelectorSource =
83
87
  | I18nSource<readonly string[], I18nCompatibleSource>
84
88
  | RemoteSource<RemoteCompatibleSource>
85
89
  | FileSource
86
- | RichTextSource
90
+ | RichTextSource<AnyRichTextOptions>
87
91
  | GenericSelector<Source>;
88
92
 
89
93
  /**
@@ -10,14 +10,14 @@ import { Source, SourceArray, SourceObject, SourcePrimitive } from "../source";
10
10
  import { Schema } from "../schema";
11
11
  import type { A } from "ts-toolbelt";
12
12
  import { FileSource } from "../source/file";
13
- import { RichText, RichTextSource } from "../source/richtext";
13
+ import { RichText, RichTextOptions, RichTextSource } from "../source/richtext";
14
14
 
15
15
  export type Selector<T extends Source> = Source extends T
16
16
  ? GenericSelector<T>
17
17
  : T extends FileSource
18
18
  ? FileSelector
19
- : T extends RichTextSource
20
- ? RichText
19
+ : T extends RichTextSource<infer O>
20
+ ? RichText<O>
21
21
  : T extends SourceObject
22
22
  ? ObjectSelector<T>
23
23
  : T extends SourceArray
@@ -40,7 +40,7 @@ export type SelectorSource =
40
40
  [key: string]: SelectorSource;
41
41
  }
42
42
  | FileSource
43
- | RichTextSource
43
+ | RichTextSource<RichTextOptions>
44
44
  | GenericSelector<Source>;
45
45
 
46
46
  /**
@@ -1,7 +1,7 @@
1
1
  import { SourcePrimitive, VAL_EXTENSION, PhantomType } from "..";
2
2
  import { FileSource } from "../file";
3
3
  import { I18nCompatibleSource, I18nSource } from "./i18n";
4
- import { RichTextSource } from "../richtext";
4
+ import { AnyRichTextOptions, RichTextSource } from "../richtext";
5
5
 
6
6
  /**
7
7
  * Remote sources cannot include other remote sources.
@@ -10,7 +10,7 @@ export type RemoteCompatibleSource =
10
10
  | SourcePrimitive
11
11
  | RemoteObject
12
12
  | RemoteArray
13
- | RichTextSource
13
+ | RichTextSource<AnyRichTextOptions>
14
14
  | FileSource
15
15
  | I18nSource<string[], I18nCompatibleSource>;
16
16
  export type RemoteObject = { [key in string]: RemoteCompatibleSource };
@@ -1,7 +1,7 @@
1
1
  import { FileSource } from "./file";
2
2
  import { I18nSource, I18nCompatibleSource } from "./future/i18n";
3
3
  import { RemoteSource, RemoteCompatibleSource } from "./future/remote";
4
- import { RichTextSource } from "./richtext";
4
+ import { RichTextOptions, RichTextSource } from "./richtext";
5
5
 
6
6
  export type Source =
7
7
  | SourcePrimitive
@@ -10,7 +10,7 @@ export type Source =
10
10
  | I18nSource<string[], I18nCompatibleSource>
11
11
  | RemoteSource<RemoteCompatibleSource>
12
12
  | FileSource
13
- | RichTextSource;
13
+ | RichTextSource<RichTextOptions>;
14
14
 
15
15
  export type SourceObject = { [key in string]: Source } & {
16
16
  // TODO: update these restricted parameters:
@@ -0,0 +1,178 @@
1
+ import { file } from "../source/file";
2
+ import { richtext } from "./richtext";
3
+
4
+ //MD to HTML
5
+ describe("richtext", () => {
6
+ test("basic h1", () => {
7
+ const r = richtext`# Title 1`;
8
+ expect(r.children).toStrictEqual([{ tag: "h1", children: ["Title 1"] }]);
9
+ });
10
+
11
+ test("basic complete", () => {
12
+ const r = richtext`# Title 1
13
+ ## Title 2
14
+
15
+ Paragraph 1 2 3 4 5. Words *italic* **bold**
16
+ `;
17
+ expect(r.children).toStrictEqual([
18
+ { tag: "h1", children: ["Title 1"] },
19
+ { tag: "h2", children: ["Title 2"] },
20
+ {
21
+ tag: "p",
22
+ children: [
23
+ "Paragraph 1 2 3 4 5. Words ",
24
+ { tag: "span", classes: ["italic"], children: ["italic"] },
25
+ " ",
26
+ { tag: "span", classes: ["bold"], children: ["bold"] },
27
+ ],
28
+ },
29
+ ]);
30
+ });
31
+
32
+ test.skip("strong and emphasis merged spans", () => {
33
+ // TODO: currently we do not merge
34
+ const r = richtext`Which classes?
35
+ ***All of them!***
36
+ `;
37
+ expect(r.children).toStrictEqual([
38
+ {
39
+ tag: "p",
40
+ children: [
41
+ "Which classes?\n",
42
+ {
43
+ tag: "span",
44
+ classes: ["italic", "bold"],
45
+ children: ["All of them!"],
46
+ },
47
+ ],
48
+ },
49
+ ]);
50
+ });
51
+
52
+ test("line through", () => {
53
+ // TODO: currently we do not merge
54
+ const r = richtext`~~line through~~`;
55
+ expect(r.children).toStrictEqual([
56
+ {
57
+ tag: "p",
58
+ children: [
59
+ {
60
+ tag: "span",
61
+ classes: ["line-through"],
62
+ children: ["line through"],
63
+ },
64
+ ],
65
+ },
66
+ ]);
67
+ });
68
+
69
+ test("2 paragraphs", () => {
70
+ const r = richtext`# Title 1
71
+
72
+ First paragraph
73
+
74
+ Second paragraph
75
+ `;
76
+ expect(r.children).toStrictEqual([
77
+ { tag: "h1", children: ["Title 1"] },
78
+ { tag: "p", children: ["First paragraph"] },
79
+ { tag: "p", children: ["Second paragraph"] },
80
+ ]);
81
+ });
82
+
83
+ test("lists", () => {
84
+ const r = richtext`# Title 1
85
+
86
+ A paragraph
87
+
88
+ A bullet list:
89
+ - bullet 1
90
+ - bullet 2
91
+
92
+ A numbered list:
93
+ 1. number 1
94
+ 2. number 2
95
+
96
+ A nested list:
97
+ - bullet 1:
98
+ 1. number 1.1
99
+ 2. number 1.2
100
+ - bullet 2:
101
+ - bullet 2.1
102
+ - bullet 2.2
103
+ `;
104
+ expect(r.children).toStrictEqual([
105
+ { tag: "h1", children: ["Title 1"] },
106
+ { tag: "p", children: ["A paragraph"] },
107
+ { tag: "p", children: ["A bullet list:"] },
108
+ {
109
+ tag: "ul",
110
+ children: [
111
+ { tag: "li", children: ["bullet 1"] },
112
+ { tag: "li", children: ["bullet 2"] },
113
+ ],
114
+ },
115
+ { tag: "p", children: ["A numbered list:"] },
116
+ {
117
+ tag: "ol",
118
+ children: [
119
+ { tag: "li", children: ["number 1"] },
120
+ { tag: "li", children: ["number 2"] },
121
+ ],
122
+ },
123
+ { tag: "p", children: ["A nested list:"] },
124
+ {
125
+ tag: "ul",
126
+ children: [
127
+ {
128
+ tag: "li",
129
+ children: [
130
+ "bullet 1:",
131
+ {
132
+ tag: "ol",
133
+ children: [
134
+ { tag: "li", children: ["number 1.1"] },
135
+ { tag: "li", children: ["number 1.2"] },
136
+ ],
137
+ },
138
+ ],
139
+ },
140
+ {
141
+ tag: "li",
142
+ children: [
143
+ "bullet 2:",
144
+ {
145
+ tag: "ul",
146
+ children: [
147
+ { tag: "li", children: ["bullet 2.1"] },
148
+ { tag: "li", children: ["bullet 2.2"] },
149
+ ],
150
+ },
151
+ ],
152
+ },
153
+ ],
154
+ },
155
+ ]);
156
+ });
157
+
158
+ test("image", () => {
159
+ const r = richtext`# Title 1
160
+
161
+ Below we have an image block:
162
+
163
+ ${file("/public/foo.png", {
164
+ width: 100,
165
+ height: 100,
166
+ sha256: "123",
167
+ })}`;
168
+ expect(r.children).toStrictEqual([
169
+ { tag: "h1", children: ["Title 1"] },
170
+ { tag: "p", children: ["Below we have an image block:"] },
171
+ {
172
+ _ref: "/public/foo.png",
173
+ _type: "file",
174
+ metadata: { width: 100, height: 100, sha256: "123" },
175
+ },
176
+ ]);
177
+ });
178
+ });