Skip to content

Commit

Permalink
Merge pull request #24 from typst-community/next
Browse files Browse the repository at this point in the history
Merge `next` into `main`
  • Loading branch information
jamesrswift authored Jun 2, 2024
2 parents 1bc0aa7 + 2afdf9b commit 7d27ff9
Show file tree
Hide file tree
Showing 15 changed files with 325 additions and 49 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

## Changed
- Valkyrie is now distributed under the MIT license rather than GPL-3.0-only.
- Number schema generator now takes additional optional parameters `min` and `max` which a sugar for value assertions. These changes also apply to number specializations such as `float` and `integer`
- String schema generator now takes additional optional parameters `min` and `max` which a sugar for value length assertions. These changes also apply to number specializations such as `email` and `ip`
- Array schema generator now takes additional optional parameters `min` and `max` which a sugar for value length assertions.
- Added schema generator for argument sinks. Takes `positional` and `named` as optional parameters that take schema types. Absence of one of these parameters indicate that these must also be absent from the argument type being validated.


---

Expand Down
Binary file modified docs/manual.pdf
Binary file not shown.
62 changes: 42 additions & 20 deletions docs/manual.typ
Original file line number Diff line number Diff line change
Expand Up @@ -373,11 +373,11 @@ For the sake of brevity and owing to their consistency, the arguments that each
)[Positional arguments of validation schemes in order or preference that an input value should satisfy.]
]

#command("number", sarg[args], ret: "schema")[
#command("number", arg(min: none), arg(max: none), sarg[args], ret: "schema")[
Generates a schema that accepts only numbers as valid.
]

#command("string", sarg[args], ret: "schema")[
#command("string", arg(min: none), arg(max: none), sarg[args], ret: "schema")[
Generates a schema that accepts only strings as valid.
]

Expand All @@ -389,19 +389,36 @@ For the sake of brevity and owing to their consistency, the arguments that each
)[Positional arguments of validation schemes representing a tuple.]
]

#command(
"sink",
arg(positional: none),
arg(named: none),
sarg[args],
ret: "schema",
)[
#argument(
"positional",
types: ("schema", none),
)[Schema that `args.pos()` must satisfy. If `none`, no positional arguments may be present]
#argument(
"named",
types: ("schema", none),
)[Schema that `args.named()` must satisfy. If `none`, no named arguments may be present]
]

#command("choice", arg[choices], sarg[args], ret: "schema")[
#argument("choices", types: "array")[Array of valid inputs]
]

#pagebreak()

#import("@preview/tidy:0.2.0")
#import "@preview/tidy:0.2.0"

#let module-doc = tidy.parse-module(
read("/src/coercions.typ"),
name: "z.coerce",
label-prefix: "z.coerce",
scope: (:)
scope: (:),
)

#tidy.show-module(
Expand All @@ -411,29 +428,28 @@ For the sake of brevity and owing to their consistency, the arguments that each
show-outline: mty-tidy.show-outline,
show-parameter-list: mty-tidy.show-parameter-list,
show-parameter-block: mty-tidy.show-parameter-block,
show-function: mty-tidy.show-function.with(tidy: tidy, extract-headings: true),
show-function: mty-tidy.show-function.with(
tidy: tidy,
extract-headings: true,
),
show-variable: mty-tidy.show-variable.with(tidy: tidy),
show-example: mty-tidy.show-example,
show-reference: mty-tidy.show-reference
show-reference: mty-tidy.show-reference,
),
first-heading-level: 2,
show-module-name: true,
sort-functions: false,
show-outline: true
show-outline: true,
)

#tidy-module(read("/src/coercions.typ"), name: "coerce")
#pagebreak()



#let module-doc = tidy.parse-module(
read("/src/assertions.typ")
+ read("/src/assertions/comparative.typ")
+ read("/src/assertions/string.typ"),
read("/src/assertions.typ") + read("/src/assertions/comparative.typ") + read("/src/assertions/string.typ"),
name: "z.assert",
label-prefix: "z.assert",
scope: (:)
scope: (:),
)

#tidy.show-module(
Expand All @@ -443,22 +459,25 @@ For the sake of brevity and owing to their consistency, the arguments that each
show-outline: mty-tidy.show-outline,
show-parameter-list: mty-tidy.show-parameter-list,
show-parameter-block: mty-tidy.show-parameter-block,
show-function: mty-tidy.show-function.with(tidy: tidy, extract-headings: true),
show-function: mty-tidy.show-function.with(
tidy: tidy,
extract-headings: true,
),
show-variable: mty-tidy.show-variable.with(tidy: tidy),
show-example: mty-tidy.show-example,
show-reference: mty-tidy.show-reference
show-reference: mty-tidy.show-reference,
),
first-heading-level: 2,
show-module-name: true,
sort-functions: false,
show-outline: true
show-outline: true,
)

#let module-doc = tidy.parse-module(
read("/src/assertions/length.typ"),
name: "z.assert.length",
label-prefix: "z.assert.string.",
scope: (:)
scope: (:),
)

#tidy.show-module(
Expand All @@ -468,15 +487,18 @@ For the sake of brevity and owing to their consistency, the arguments that each
show-outline: mty-tidy.show-outline,
show-parameter-list: mty-tidy.show-parameter-list,
show-parameter-block: mty-tidy.show-parameter-block,
show-function: mty-tidy.show-function.with(tidy: tidy, extract-headings: true),
show-function: mty-tidy.show-function.with(
tidy: tidy,
extract-headings: true,
),
show-variable: mty-tidy.show-variable.with(tidy: tidy),
show-example: mty-tidy.show-example,
show-reference: mty-tidy.show-reference
show-reference: mty-tidy.show-reference,
),
first-heading-level: 2,
show-module-name: true,
sort-functions: false,
show-outline: true
show-outline: true,
)

#pagebreak()
Expand Down
2 changes: 1 addition & 1 deletion src/assertions-util.typ
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
)
}

#let assert-positive-type(var, name: "", types: (), default: none) = {
#let assert-positive-type(var, name: "", types: (float, int), default: none) = {
assert-types(var, types: types, default: default, name: name)
assert-positive(var, name: name)
}
Expand Down
5 changes: 2 additions & 3 deletions src/types.typ
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
#import "types/array.typ": array
#import "types/dictionary.typ": dictionary
#import "types/logical.typ": either
#import "types/number.typ": number, integer, floating-point
#import "types/sink.typ": sink
#import "types/string.typ": string, ip, email
#import "types/tuple.typ": tuple

Expand All @@ -11,9 +13,6 @@
#let color = base-type.with(name: "color", types: (color,))
#let content = base-type.with(name: "content", types: (content, str))
#let date = base-type.with(name: "date", types: (datetime,))
#let number = base-type.with(name: "number", types: (float, int))
#let integer = number.with(name: "integer", types: (int,))
#let floating-point = number.with(name: "float", types: (float,))

#let choice(list, assertions: (), ..args) = base-type(
name: "enum",
Expand Down
23 changes: 22 additions & 1 deletion src/types/array.typ
Original file line number Diff line number Diff line change
@@ -1,22 +1,43 @@
#import "../base-type.typ": base-type
#import "../assertions-util.typ": assert-base-type
#import "../assertions-util.typ": assert-base-type, assert-positive-type
#import "../ctx.typ": z-ctx

#let array-type = type(())

#let array(
name: "array",
assertions: (),
min: none,
max: none,
..args,
) = {
let descendents-schema = args.pos().at(0, default: base-type(name: "any"))

assert-base-type(descendents-schema, scope: ("arguments",))
assert-positive-type(min, types: (int,), name: "Minimum length")
assert-positive-type(max, types: (int,), name: "Maximum length")

base-type(
name: "array[" + (descendents-schema.name) + "]",
default: (),
types: (array-type,),
..args.named(),
) + (
min: min,
max: max,
assertions: (
(
precondition: "min",
condition: (self, it) => it.len() >= self.min,
message: (self, it) => "Length must be at least " + str(self.min),
),
(
precondition: "max",
condition: (self, it) => it.len() <= self.max,
message: (self, it) => "Length must be at most " + str(self.max),
),
..assertions,
),
descendents-schema: descendents-schema,
handle-descendents: (self, it, ctx: z-ctx(), scope: ()) => {
for (key, value) in it.enumerate() {
Expand Down
34 changes: 34 additions & 0 deletions src/types/number.typ
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#import "../base-type.typ": base-type
#import "../assertions-util.typ": *

#let number(
assertions: (),
min: none,
max: none,
..args,
) = {

assert-positive-type(min, types: (int,), name: "Minimum length")
assert-positive-type(max, types: (int,), name: "Maximum length")

base-type(name: "number", types: (float, int), ..args) + (
min: min,
max: max,
assertions: (
(
precondition: "min",
condition: (self, it) => it >= self.min,
message: (self, it) => "Value must be at least " + str(self.min),
),
(
precondition: "max",
condition: (self, it) => it <= self.max,
message: (self, it) => "Value must be at most " + str(self.max),
),
..assertions,
),
)
}

#let integer = number.with(name: "integer", types: (int,))
#let floating-point = number.with(name: "float", types: (float,))
73 changes: 73 additions & 0 deletions src/types/sink.typ
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#import "../base-type.typ": base-type
#import "../assertions-util.typ": assert-base-type
#import "../ctx.typ": z-ctx

#let to-args-type(..args) = args

#let sink(
positional: none,
named: none,
..args,
) = {

if positional != none {
assert-base-type(positional)
}
if named != none {
assert-base-type(named)
}

base-type(
name: "argument-sink",
types: (arguments,),
..args,
) + (
positional-schema: positional,
named-schema: named,
handle-descendents: (self, it, ctx: z-ctx(), scope: ()) => {

let positional = it.pos()
if self.positional-schema == none {
if positional.len() > 0 {
(self.fail-validation)(
self,
it,
scope: scope,
ctx: ctx,
message: "Unexpected positional arguments.",
)
}
} else {
positional = (self.positional-schema.validate)(
self.positional-schema,
it.pos(),
ctx: ctx,
scope: (..scope, "positional"),
)
}

let named = it.named()
if self.named-schema == none {
if named.len() > 0 {
(self.fail-validation)(
self,
it,
scope: scope,
ctx: ctx,
message: "Unexpected named arguments.",
)
}
} else {
named = (self.named-schema.validate)(
self.named-schema,
it.named(),
ctx: ctx,
scope: (..scope, "named"),
)
}

to-args-type(..positional, ..named)
},
)

}
29 changes: 29 additions & 0 deletions src/types/string.typ
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,35 @@
/// -> schema
#let string = base-type.with(name: "string", types: (str,))

#let string(
assertions: (),
min: none,
max: none,
..args,
) = {

assert-positive-type(min, types: (int,), name: "Minimum length")
assert-positive-type(max, types: (int,), name: "Maximum length")

base-type(name: "string", types: (str,), ..args) + (
min: min,
max: max,
assertions: (
(
precondition: "min",
condition: (self, it) => it.len() >= self.min,
message: (self, it) => "Length must be at least " + str(self.min),
),
(
precondition: "max",
condition: (self, it) => it.len() <= self.max,
message: (self, it) => "Length must be at most " + str(self.max),
),
..assertions,
),
)
}

#let email = string.with(
name: "email",
assertions: (
Expand Down
Loading

0 comments on commit 7d27ff9

Please sign in to comment.