To-Stuff is a collection of Typst functions for converting string values to native types. This is most useful when loading layout data from an external configuration source, such as a YAML file.
- Avoids any use of
eval(). - All conversion functions optionally accept a default value to return on failure.
- Where no default value is specified, a failed conversion panics with a sensible error message.
How to use
Import the package into the current scope, optionally renamed using the as keyword:
#import "@preview/to-stuff:1.0.0"
// Bindings available as to-stuff.alignment(), to-stuff.angle(), etc.
// …or…
#import "@preview/to-stuff:1.0.0" as to
// Bindings available as to.alignment(), to.angle(), etc.
The package’s let bindings have the same names as their return types, and rely on Typst’s import syntax to scope safely. It is not recommended to load the individual bindings into the current scope, as that may cause collisions with the types themselves.
#assert(type(42pt) == length) // Expected behaviour
#import "@preview/to-stuff:1.0.0": * // NOT RECOMMENDED
#assert(type(42pt) != length) // To-Stuff bindings collide with standard types
#assert(type(42pt) == std.length) // Workaround
Localisation
All conversions involving numeric values assume the number strings to be in a format understood by Typst code; specifically:
- All numeric digits must be ASCII characters 0-9 and/or A-F (case non-sensitive).
- Decimal separators must be a full stop/period; commas, apostrophes, etc. are not supported.
- Thousands separators are not supported.
General Purpose Function
stuff
Attempts to convert a value to the most appropriate data type, based on brute-force process of elimination. If no valid conversion can be found, the original value is returned unaltered.
Unlike the direct conversion functions, this function does not panic in the event of a failed conversion, and does not accept a default value.
#stuff(
value, // any
recursive: false, // bool
arguments-collapse: false, // bool
numbers-as: auto, // type
none-from: (), // array
) -> any
View arguments
value
str or array or dictionary or arguments or others (positional, required)
The value that should be converted to a native data type.
- A string with the value
"auto"is converted toauto. - A string representation of a native data type that is recognised by a direct conversion function is converted accordingly.
- A
dictionarythat conforms to a validalignment,relativeorstrokeis converted. - An
arraythat conforms to a validversionis converted. - Any other value is returned unchanged.
recursive
bool
Whether to recurse through the items of arguments and array values, and of dictionary values that could not otherwise be converted.
Note that recursing an array means that it will not be converted to a single version, even if otherwise suitable; version-like strings will still be converted as expected.
Default: false
arguments-collapse
bool
Whether to return an arguments value as an array or dictionary, where possible.
Has no effect when recursive is not true.
- A setting of
truereturns anargumentsvalue with no named arguments as anarray, or anargumentsvalue with no positional arguments as adictionary. Anargumentsvalue with both named and positional arguments will always be returned as anarguments. - A setting of
falsereturns anargumentsvalue as anarguments, regardless of its lack of named or positional arguments.
Default: false
numbers-as
type
The standard type to which to attempt to convert basic numbers.
- A setting of
std.intconvertsdecimals,floats and eligible strings tointtypes. - A setting of
std.floatconvertsints,decimals and eligible strings tofloattypes. - A setting of
std.decimalconvertsints and eligible strings todecimaltypes, but ignoresfloats. - A setting of
std.versionconvertsints and eligible strings toversiontypes, but ignoresfloats anddecimals. - A setting of
autoapplies thenumberdirect conversion function, which if successful returns either anintor afloatas appropriate.
Default: auto
none-from
array
Specify strings to convert to none. Case non-sensitive.
Default: ()
View examples
#import "@preview/to-stuff:1.0.0" as to
#let a = to.stuff("auto")
// -> auto
#let b = to.stuff("true")
// -> true
#let c = to.stuff("top + right")
// -> right + top
#let d = to.stuff((x: "right", y: "top"))
// -> right + top
#let e = to.stuff("45deg")
// -> 45deg
#let f = to.stuff("rgb(255, 65, 54)")
// -> rgb("#ff4136")
#let g = to.stuff("rtl")
// -> rtl
#let h = to.stuff("25e-1")
// -> 2.5
#let i = to.stuff("2.5fr")
// -> 2.5fr
#let j = to.stuff("0x2a")
// -> 42
#let k = to.stuff("45pt")
// -> 45pt
#let l = to.stuff("45%")
// -> 45%
#let m = to.stuff("45pt + 3%")
// -> 3% + 45pt
#let n = to.stuff((ratio: "3%", length: "45pt"))
// -> 3% + 45pt
#let o = to.stuff("2pt + red + densely-dashed")
// -> (paint: rgb("#ff4136"), thickness: 2pt, dash: (array: (3pt, 2pt), phase: 0pt))
#let p = to.stuff((paint: red, thickness: 2pt, dash: "densely-dashed"))
// -> (paint: rgb("#ff4136"), thickness: 2pt, dash: (array: (3pt, 2pt), phase: 0pt))
#let q = to.stuff(recursive: true, (
mixed: ("A", "2", "33.3%", "auto", "5pt", "horizon + center"),
origin: (x: "center", y: "horizon"),
line: (thickness: "0.5pt", paint: "blue", dash: "dotted"),
))
/* -> (
mixed: ("A", 2, 33.3%, auto, 5pt, center + horizon),
origin: center + horizon,
line: (paint: rgb("#0074d9"), thickness: 0.5pt, dash: (array: ("dot", 2pt), phase: 0pt)),
) */
#let r = to.stuff(recursive: true, arguments-collapse: false, arguments(paint: "black", thickness:
"0.9pt"))
// -> arguments(paint: luma(0%), thickness: 0.9pt)
#let s = to.stuff(recursive: true, arguments-collapse: true, arguments(paint: "black", thickness:
"0.9pt"))
// -> 0.9pt + luma(0%)
#let t = to.stuff(numbers-as: decimal, "2.5")
// -> decimal("2.5")
#let u = to.stuff(numbers-as: float, "2.5")
// -> 2.5
#let v = to.stuff(numbers-as: int, "2.5")
// -> 2
#let w = to.stuff("")
// -> ""
Direct Conversion Functions
alignment
Attempts to convert a value to an alignment.
#alignment(
value, // str | alignment | dictionary
default: auto, // auto | none | alignment
) -> none | alignment
View arguments
value
str or alignment or dictionary (positional, required)
The value that should be converted to an alignment.
- An
alignmentis returned unchanged. - A string representation of any of the eight
alignmentvalues is converted to that value.- The string must not contain any scoping prefix, e.g.
alignment.…, or the conversion will fail.
- The string must not contain any scoping prefix, e.g.
- A string consisting of two
alignmentrepresentations joined by a plus sign is converted to the corresponding 2D alignment.- The two alignments must be on different axes, or the conversion will fail.
- A
dictionarycontaining one or more of the keysxandy, and no other keys, is converted.- The value of
x, if present, must be either a horizontalalignmentor a value that would convert to one. - The value of
y, if present, must be either a verticalalignmentor a value that would convert to one.
- The value of
default
auto or none or alignment
What to return if value could not be converted. If auto, failed conversions cause a panic.
Default: auto
View examples
#import "@preview/to-stuff:1.0.0" as to
#let a = to.alignment("top + right")
// -> right + top
#let b = to.alignment(top + right)
// -> right + top
#let c = to.alignment((x: "right", y: "top"))
// -> right + top
#let d = to.alignment("turnwise")
// panics with: "could not convert to alignment: \"turnwise\""
#let e = to.alignment("top + bottom")
// panics with: "cannot add two vertical alignments: \"top + bottom\""
#let f = to.alignment(default: top + right, "top + bottom")
// -> right + top
#let g = to.alignment(default: none, "top + bottom")
// -> none
angle
Attempts to convert a value to an angle.
#angle(
value, // str | angle
default: auto, // auto | none | angle
) -> none | angle
View arguments
value
str or angle (positional, required)
The value that should be converted to an angle.
- An
angleis returned unchanged. - A string representation of a number followed by the letters
degorradis converted.- The number may be positive or negative, and may contain decimal places and/or an exponent.
default
auto or none or angle
What to return if value could not be converted. If auto, failed conversions cause a panic.
Default: auto
View examples
#import "@preview/to-stuff:1.0.0" as to
#let a = to.angle("45deg")
// -> 45deg
#let b = to.angle(45deg)
// -> 45deg
#let c = to.angle("42")
// panics with: "could not convert to angle: \"42\""
#let d = to.angle(default: 45deg, "42")
// -> 45deg
#let e = to.angle(default: none, "42")
// -> none
bool
Attempts to convert a value to a bool.
#bool(
value, // str | bool
default: auto, // auto | none | bool
) -> none | bool
View arguments
value
str or bool (positional, required)
The value that should be converted to a bool.
- A
boolis returned unchanged. - A string value of
"true"is converted totrue. Case non-sensitive. - A string value of
"false"is converted tofalse. Case non-sensitive.
default
auto or none or bool
What to return if value could not be converted. If auto, failed conversions cause a panic.
Default: auto
View examples
#import "@preview/to-stuff:1.0.0" as to
#let a = to.bool("true")
// -> true
#let b = to.bool(true)
// -> true
#let c = to.bool("auto")
// panics with: "could not convert to boolean: \"auto\""
#let d = to.bool(default: true, "auto")
// -> true
#let e = to.bool(default: none, "auto")
// -> none
color
Attempts to convert a value to a color.
#color(
value, // str | color
default: auto, // auto | none | color
) -> none | color
View arguments
value
str or color (positional, required)
The value that should be converted to a color.
- A
coloris returned unchanged. - A string representation of a predefined color value is converted to that built-in color.
- A string representation of a hash symbol followed by a 6- or 8-digit hexadecimal code is converted to the corresponding RGB or RGBA value.
- A string representation of a color space function followed by parentheses and arguments is converted.
- The string must not contain any scoping prefix, e.g.
color.…, or the conversion will fail. This includes thehsl,hsv, andlinear-rgbfunctions.
- The string must not contain any scoping prefix, e.g.
default
auto or none or color
What to return if value could not be converted. If auto, failed conversions cause a panic.
Default: auto
View examples
#import "@preview/to-stuff:1.0.0" as to
#let a = to.color("red")
// -> rgb("#ff4136")
#let b = to.color(red)
// -> rgb("#ff4136")
#let c = to.color("#FF4136FF")
// -> rgb("#ff4136")
#let d = to.color("rgb(255, 65, 54)")
// -> rgb("#ff4136")
#let e = to.color("hsv(135deg,75%,127,100)")
// -> color.hsv(135deg, 75%, 49.8%, 39.22%)
#let f = to.color("indigo")
// panics with: "could not convert to color: \"indigo\""
#let g = to.color(default: red, "indigo")
// -> rgb("#ff4136")
#let h = to.color(default: none, "indigo")
// -> none
decimal
Attempts to convert a value to a decimal.
While the standard decimal constructor throws an error on failure, this function panics instead, which may be suppressed if desired via the default argument.
#decimal(
value, // str | int | decimal
default: auto, // auto | none | int | decimal
) -> none | decimal
View arguments
value
str or int or decimal (positional, required)
The value that should be converted to a decimal.
- A
decimalis returned unchanged. - An
intis converted. - A string representation of a number is converted.
- The number may be positive or negative, and may contain decimal places, but not an exponent.
- Hexadecimal numbers, prefixed with
0x, are permitted. - Octal numbers, prefixed with
0o, are permitted. - Binary numbers, prefixed with
0b, are permitted.
default
auto or none or int or decimal
What to return if value could not be converted; int defaults are converted to decimal. If auto, failed conversions cause a panic.
Default: auto
View examples
#import "@preview/to-stuff:1.0.0" as to
#let a = to.decimal("42")
// -> decimal("42")
#let b = to.decimal(42)
// -> decimal("42")
#let c = to.decimal("0x2a")
// -> decimal("42")
#let d = to.decimal(0x2a)
// -> decimal("42")
#let e = to.decimal("2.5")
// -> decimal("2.5")
#let f = to.decimal(2.5)
// panics with: "could not convert to decimal: 2.5"
#let h = to.decimal("25e-1")
// panics with: "could not convert to decimal: \"25e-1\""
#let h = to.decimal(default: 42, "25e-1")
// -> decimal("42")
#let i = to.decimal(default: none, "25e-1")
// -> none
direction
Attempts to convert a value to a direction.
#direction(
value, // str | direction
default: auto, // auto | none | direction
) -> none | direction
View arguments
value
str or direction (positional, required)
The value that should be converted to a direction.
- A
directionis returned unchanged. - A string representation of any of the four
directionvalues is converted to that value.- The string must not contain any scoping prefix, e.g.
direction.…, or the conversion will fail.
- The string must not contain any scoping prefix, e.g.
default
auto or none or direction
What to return if value could not be converted. If auto, failed conversions cause a panic.
Default: auto
View examples
#import "@preview/to-stuff:1.0.0" as to
#let a = to.direction("rtl")
// -> rtl
#let b = to.direction(rtl)
// -> rtl
#let c = to.direction("btf")
// panics with: "could not convert to direction: \"btf\""
#let d = to.direction(default: rtl, "btf")
// -> rtl
#let e = to.direction(default: none, "btf")
// -> none
float
Attempts to convert a value to a float.
While the standard float constructor throws an error on failure, this function panics instead, which may be suppressed if desired via the default argument.
#float(
value, // str | int | float | decimal
default: auto, // auto | none | int | float | decimal
) -> none | float
View arguments
value
str or int or float or decimal (positional, required)
The value that should be converted to a float.
- A
floatis returned unchanged. - A
decimalorintis converted. - A string representation of a number is converted.
- The number may be positive or negative, and may contain decimal places and/or an exponent.
- Hexadecimal numbers, prefixed with
0x, are permitted. - Octal numbers, prefixed with
0o, are permitted. - Binary numbers, prefixed with
0b, are permitted.
default
auto or none or int or float or decimal
What to return if value could not be converted; decimal and int defaults are converted to float. If auto, failed conversions cause a panic.
Default: auto
View examples
#import "@preview/to-stuff:1.0.0" as to
#let a = to.float("42")
// -> 42.0
#let b = to.float(42)
// -> 42.0
#let c = to.float("2.5")
// -> 2.5
#let d = to.float(2.5)
// -> 2.5
#let e = to.float(25e-1)
// -> 2.5
#let f = to.float("25e-1")
// -> 2.5
#let g = to.float("0x2a")
// -> 42.0
#let h = to.float(0x2a)
// -> 42.0
#let i = to.float("42%")
// panics with: "could not convert to float: \"42%\""
#let j = to.float(default: 42, "42%")
// -> 42.0
#let k = to.float(default: none, "42%")
// -> none
fraction
Attempts to convert a value to a fraction.
#fraction(
value, // str | fraction
default: auto, // auto | none | fraction
) -> none | fraction
View arguments
value
str or fraction (positional, required)
The value that should be converted to a fraction.
- A
fractionis returned unchanged. - A string representation of a number followed by the letters
fris converted.- The number may be positive or negative, and may contain decimal places and/or an exponent.
default
auto or none or fraction
What to return if value could not be converted. If auto, failed conversions cause a panic.
Default: auto
View examples
#import "@preview/to-stuff:1.0.0" as to
#let a = to.fraction("2.5fr")
// -> 2.5fr
#let b = to.fraction(2.5fr)
// -> 2.5fr
#let c = to.fraction("42")
// panics with: "could not convert to fraction: \"42\""
#let d = to.fraction(default: 2.5fr, "42")
// -> 2.5fr
#let e = to.fraction(default: none, "42")
// -> none
int
Attempts to convert a value to an int.
While the standard int constructor throws an error on failure, this function panics instead, which may be suppressed if desired via the default argument.
This function can also parse correctly-prefixed strings in hexadecimal, octal and binary.
#int(
value, // str | int | float | decimal
default: auto, // auto | none | int
) -> none | int
View arguments
value
str or int or float or decimal (positional, required)
The value that should be converted to an int.
- An
intis returned unchanged. - A
decimalorfloatis rounded towards zero and converted. - A string representation of a number is converted.
- The number may be positive or negative, and may contain decimal places and/or an exponent.
- Hexadecimal numbers, prefixed with
0x, are permitted. - Octal numbers, prefixed with
0o, are permitted. - Binary numbers, prefixed with
0b, are permitted.
default
auto or none or int
What to return if value could not be converted. If auto, failed conversions cause a panic.
Default: auto
View examples
#import "@preview/to-stuff:1.0.0" as to
#let a = to.int("42")
// -> 42
#let b = to.int(42)
// -> 42
#let c = to.int("2.5")
// -> 2
#let d = to.int(2.5)
// -> 2
#let e = to.int(25e-1)
// -> 2
#let f = to.int("25e-1")
// -> 2
#let g = to.int("0x2a")
// -> 42
#let h = to.int(0x2a)
// -> 42
#let i = to.int("42%")
// panics with: "could not convert to int: \"42%\""
#let j = to.int(default: 42, "42%")
// -> 42
#let k = to.int(default: none, "42%")
// -> none
length
Attempts to convert a value to a length.
#length(
value, // str | length
default: auto, // auto | none | length
) -> none | length
View arguments
value
str or length (positional, required)
The value that should be converted to a length.
- A
lengthis returned unchanged. - A string representation of a number followed by the letters
pt,mm,cm,in, orem, is converted.- The number may be positive or negative, and may contain decimal places and/or an exponent.
default
auto or none or length
What to return if value could not be converted. If auto, failed conversions cause a panic.
Default: auto
View examples
#import "@preview/to-stuff:1.0.0" as to
#let a = to.length("45pt")
// -> 45pt
#let b = to.length(45pt)
// -> 45pt
#let c = to.length("42")
// panics with: "could not convert to length: \"42\""
#let d = to.length(default: 45pt, "42")
// -> 45pt
#let e = to.length(default: none, "42")
// -> none
number
Attempts to convert a value to an int or a float as appropriate.
#number(
value, // str | int | float | decimal
default: auto, // auto | none | int | float | decimal
) -> none | int | float | decimal
View arguments
value
str or int or float or decimal (positional, required)
The value that should be converted to a float or int.
- A
decimal,floatorintis returned unchanged. - A string representation of a number is converted.
- The number may be positive or negative.
- A number that contains decimal places and/or an exponent, is converted to a
float. - Hexadecimal numbers, prefixed with
0x, are converted to anint. - Octal numbers, prefixed with
0o, are converted to anint. - Binary numbers, prefixed with
0b, are converted to anint.
default
auto or none or int or float or decimal
What to return if value could not be converted. If auto, failed conversions cause a panic.
Default: auto
View examples
#import "@preview/to-stuff:1.0.0" as to
#let a = to.number("42")
// -> 42
#let b = to.number(42)
// -> 42
#let c = to.number("2.5")
// -> 2.5
#let d = to.number(2.5)
// -> 2.5
#let e = to.number(25e-1)
// -> 2.5
#let f = to.number("25e-1")
// -> 2.5
#let g = to.number("0x2a")
// -> 42
#let h = to.number(0x2a)
// -> 42
#let i = to.number("42%")
// panics with: "could not convert to int or float: \"45%\""
#let j = to.number(default: 42, "42%")
// -> 42
#let k = to.number(default: none, "42%")
// -> none
ratio
Attempts to convert a value to a ratio.
#ratio(
value, // str | ratio
default: auto, // auto | none | ratio
) -> none | ratio
View arguments
value
str or ratio (positional, required)
The value that should be converted to a ratio.
- A
ratiois returned unchanged. - A string representation of a number followed by a percent sign is converted.
- The number may be positive or negative, and may contain decimal places and/or an exponent.
default
auto or none or ratio
What to return if value could not be converted. If auto, failed conversions cause a panic.
Default: auto
View examples
#import "@preview/to-stuff:1.0.0" as to
#let a = to.ratio("45%")
// -> 45%
#let b = to.ratio(45%)
// -> 45%
#let c = to.ratio("42")
// panics with: "could not convert to ratio: \"42\""
#let d = to.ratio(default: 45%, "42")
// -> 45%
#let e = to.ratio(default: none, "42")
// -> none
relative
Attempts to convert a value to a relative.
#relative(
value, // str | relative | ratio | length | dictionary
default: auto, // auto | none | relative | ratio | length
) -> none | relative
View arguments
value
str or relative or ratio or length or dictionary (positional, required)
The value that should be converted to a relative.
- A
relativeis returned unchanged. - A
ratiois returned as arelativewith alengthof0pt. - A
lengthis returned as arelativewith aratioof0%. - A string representation of a
ratio(see above) is converted. - A string representation of a
length(see above) is converted. - A string consisting of multiple
ratios andlengths joined by plus signs or minus signs is converted to a singlerelativelength.- All
length-like substrings are added. - All
ratio-like substrings are added.
- All
- A
dictionarycontaining one or more of the keysratioandlength, and no other keys, is converted.- The value of
ratio, if present, must be either aratioor a value that would convert to one. - The value of
length, if present, must be either alengthor a value that would convert to one.
- The value of
default
auto or none or relative or ratio or length
What to return if value could not be converted. If auto, failed conversions cause a panic.
Default: auto
View examples
#import "@preview/to-stuff:1.0.0" as to
#let a = to.relative("45pt + 3%")
// -> 3% + 45pt
#let b = to.relative(45pt + 3%)
// -> 3% + 45pt
#let c = to.relative((ratio: "3%", length: "45pt"))
// -> 3% + 45pt
#let d = to.relative("42")
// panics with: "could not convert to relative: \"42\""
#let e = to.relative(default: 45pt + 3%, "42")
// -> 3% + 45pt
#let f = to.relative(default: none, "42")
// -> none
stroke
Attempts to convert a value to a stroke.
#stroke(
value, // str | stroke | color | length | array | dictionary
default: auto, // auto | none | stroke | color | length
) -> none | stroke
View arguments
value
str or stroke or color or length or array or dictionary (positional, required)
The value that should be converted to a stroke.
- A
stroke,colororlengthis returned unchanged. - A string representation of a
color(see above) is converted. - A string representation of a
length(see above) is converted. - A valid dash pattern is converted.
- A string representation of one or more valid
colors,lengths and/or predefined dash patterns joined by plus signs is converted.- All
color-like substrings are combined viacolor.mix(). - All
length-like substrings added.
- All
- A
dictionarythat would otherwise be accepted as a validstrokeis converted.
default
auto or none or stroke or color or length
What to return if value could not be converted. If auto, failed conversions cause a panic.
Default: auto
View examples
#import "@preview/to-stuff:1.0.0" as to
#let a = to.stroke("red")
// -> rgb("#ff4136")
#let b = to.stroke(45pt)
// -> 45pt
#let c = to.stroke("densely-dashed")
// -> (dash: (array(3pt, 2pt), phase: 0pt))
#let d = to.stroke((3pt, 2pt))
// -> (dash: (array(3pt, 2pt), phase: 0pt))
#let e = to.stroke((paint: red, thickness: 2pt, dash: "densely-dashed"))
// -> (paint: rgb("#ff4136"), thickness: 2pt, dash: (array: (3pt, 2pt), phase: 0pt))
#let f = to.stroke("2pt + red + densely-dashed + silver + 5pt")
// -> (paint: oklab(77.85%, 0.1, 0.054), thickness: 7pt, dash: (array: (3pt, 2pt), phase: 0pt))
#let g = to.stroke("deep-dish")
// panics with: "could not convert to stroke: \"deep-dish\""
#let h = to.stroke(default: red + 45pt, "deep-dish")
// -> 45pt + rgb("#ff4136")
#let i = to.stroke(default: none, "deep-dish")
// -> none
version
Attempts to convert a value to a version.
#version(
value, // str | version | int | array
default: auto, // auto | none | version
) -> none | version
View arguments
value
str or version or int or array (positional, required)
The value that should be converted to a version.
- A
versionis returned unchanged. - An
intis converted. - A string representation of positive integers separated by periods is converted.
- An array of any combination of the above is flattened and converted.
default
auto or none or version
What to return if value could not be converted. If auto, failed conversions cause a panic.
Default: auto
View examples
#import "@preview/to-stuff:1.0.0" as to
#let a = to.version("42")
// -> version(42)
#let b = to.version(42)
// -> version(42)
#let c = to.version("2.5")
// -> version(2, 5)
#let d = to.version(2.5)
// -> panics with: "expected integer, array or version, found float 2.5"
#let e = to.version("2.5.1")
// -> version(2, 5, 1)
#let f = to.version((2, 5, 1))
// -> version(2, 5, 1)
#let g = to.version((2, -5, 1))
// -> panics with "number must be greater than zero: -5"
#let h = to.version((2, (5, 1)))
// -> version(2, 5, 1)
#let i = to.version((2, std.version(5, 1)))
// -> version(2, 5, 1)
#let j = `to.version("42%")`
// -> panics with: "could not convert to version: \"42%\""
#let k = to.version(default: sys.version, "42%")
// -> version(0, 14, 2)
#let l = to.version(default: none, "42%")
// -> none
Changelog
1.0.0 - 2026-06-08
Changed
- Breaking: less strict, more natural handling of integers and floats.
- Integer and float conversions may accept integers, floats or decimals.
- Float and generic number conversions may default to an integer, float, or decimal.
- Integer conversions may only default to an integer (or
none).
Added
- New general-purpose function
stuffto guess most appropriate conversion. - Expose new conversions:
- bool
- decimal
- version
Removed
- Breaking: remove deprecated
quietargument from all direct conversion functions. - Breaking: remove deprecated
scalarfunction alias.
0.5.1 - 2026-01-16
Changed
- Invalid
defaultandquietvalues throw failed assertions instead of panicking.
Fixed
- Reject empty dictionaries when converting:
- alignment
- relative
- stroke
0.5.0 - 2025-12-20
Changed
- Rename scalar to number.
- Deprecate scalar (retained as alias of number for backward compatibility).
Added
- Add
defaultargument to every conversion (#2). - Deprecate the
quietargument (equivalent todefault: none).
Fixed
- Additional validation restraints for color constructors (#1).
0.4.0 - 2025-12-06
Changed
- Remove reliance on
eval()from:- color
- All use of
eval()now entirely eliminated.
Added
- Expose new conversions:
- float
- int
- scalar (returns either float or int as appropriate)
Fixed
- Color conversion via constructor now checks validity of all arguments.
- Stroke miter-limit now treated as scalar.
0.3.1 - 2025-10-30
Added
- Dictionary conversion to stroke now checks validity of cap, join and miter-limit.
0.3.0 - 2025-10-19
Changed
- Improve conversion logic and error checking for stroke.
0.2.1 - 2025-10-10
Changed
- Remove reliance on
eval()from:- alignment
0.2.0 - 2025-10-08
Changed
- Remove reliance on
eval()from:- angle
- fraction
- length
- ratio
- relative
Added
- Allow exponential notation in numeric conversions.
0.1.0 - 2025-09-30
Initial release.