diff --git a/crates/typst-syntax/src/file.rs b/crates/typst-syntax/src/file.rs index f5fa493b2..8f07cc926 100644 --- a/crates/typst-syntax/src/file.rs +++ b/crates/typst-syntax/src/file.rs @@ -265,6 +265,17 @@ pub struct PackageVersion { pub patch: u32, } +impl PackageVersion { + /// The current compiler version. + pub fn compiler() -> Self { + Self { + major: env!("CARGO_PKG_VERSION_MAJOR").parse().unwrap(), + minor: env!("CARGO_PKG_VERSION_MINOR").parse().unwrap(), + patch: env!("CARGO_PKG_VERSION_PATCH").parse().unwrap(), + } + } +} + impl FromStr for PackageVersion { type Err = EcoString; diff --git a/crates/typst/src/eval/mod.rs b/crates/typst/src/eval/mod.rs index 3f0e4577d..fffedc9fa 100644 --- a/crates/typst/src/eval/mod.rs +++ b/crates/typst/src/eval/mod.rs @@ -1920,6 +1920,16 @@ impl PackageManifest { ); } + if let Some(compiler) = self.package.compiler { + let current = PackageVersion::compiler(); + if current < compiler { + bail!( + "package requires typst {compiler} or newer \ + (current version is {current})" + ); + } + } + Ok(()) } } @@ -1935,6 +1945,8 @@ struct PackageInfo { version: PackageVersion, /// The path of the entrypoint into the package. entrypoint: EcoString, + /// The minimum required compiler version for the package. + compiler: Option, } impl Eval for ast::LoopBreak<'_> { diff --git a/tests/packages/future-0.1.0/lib.typ b/tests/packages/future-0.1.0/lib.typ new file mode 100644 index 000000000..80406f620 --- /dev/null +++ b/tests/packages/future-0.1.0/lib.typ @@ -0,0 +1 @@ +#future diff --git a/tests/packages/future-0.1.0/typst.toml b/tests/packages/future-0.1.0/typst.toml new file mode 100644 index 000000000..f8da5406b --- /dev/null +++ b/tests/packages/future-0.1.0/typst.toml @@ -0,0 +1,5 @@ +[package] +name = "future" +version = "0.1.0" +entrypoint = "lib.typ" +compiler = "1.0.0" diff --git a/tests/src/tests.rs b/tests/src/tests.rs index 960aacd2e..fee6f2b7b 100644 --- a/tests/src/tests.rs +++ b/tests/src/tests.rs @@ -25,7 +25,7 @@ use typst::doc::{Document, Frame, FrameItem, Meta}; use typst::eval::{eco_format, func, Bytes, Datetime, Library, NoneValue, Tracer, Value}; use typst::font::{Font, FontBook}; use typst::geom::{Abs, Color, RgbaColor, Smart}; -use typst::syntax::{FileId, Source, Span, SyntaxNode, VirtualPath}; +use typst::syntax::{FileId, PackageVersion, Source, Span, SyntaxNode, VirtualPath}; use typst::{World, WorldExt}; use typst_library::layout::{Margin, PageElem}; use typst_library::text::{TextElem, TextSize}; @@ -719,7 +719,10 @@ fn parse_part_metadata(source: &Source) -> TestPartMetadata { let mut s = Scanner::new(expectation); let range = range(&mut s); let rest = if range.is_some() { s.after() } else { s.string() }; - let message = rest.trim().into(); + let message = rest + .trim() + .replace("VERSION", &PackageVersion::compiler().to_string()) + .into(); annotations.insert(Annotation { kind, range, message }); } } diff --git a/tests/typ/compiler/packages.typ b/tests/typ/compiler/packages.typ index 066a31deb..0d3fda581 100644 --- a/tests/typ/compiler/packages.typ +++ b/tests/typ/compiler/packages.typ @@ -11,6 +11,11 @@ #import "@test/adder:0.1.0": add #test(add(2, 8), 10) +--- +// Test too high required compiler version. +// Error: 9-29 package requires typst 1.0.0 or newer (current version is VERSION) +#import "@test/future:0.1.0": future + --- // Error: 9-13 `@` is not a valid package namespace #import "@@": *