diff options
| author | Laurenz <laurmaedje@gmail.com> | 2023-06-26 13:57:21 +0200 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2023-06-27 18:40:17 +0200 |
| commit | 7b92bd7c340d9f9c094ed2fa57912049317d9b20 (patch) | |
| tree | b91399526ba94d87309d09d864df2935dd7a4d0a /library | |
| parent | 9c7f31870b4e1bf37df79ebbe1df9a56df83d878 (diff) | |
Basic package management
Diffstat (limited to 'library')
| -rw-r--r-- | library/src/compute/data.rs | 24 | ||||
| -rw-r--r-- | library/src/meta/bibliography.rs | 60 | ||||
| -rw-r--r-- | library/src/meta/reference.rs | 2 | ||||
| -rw-r--r-- | library/src/prelude.rs | 2 | ||||
| -rw-r--r-- | library/src/visualize/image.rs | 59 |
5 files changed, 81 insertions, 66 deletions
diff --git a/library/src/compute/data.rs b/library/src/compute/data.rs index 1d6bec60..6e3a298e 100644 --- a/library/src/compute/data.rs +++ b/library/src/compute/data.rs @@ -25,8 +25,8 @@ pub fn read( vm: &mut Vm, ) -> SourceResult<Str> { let Spanned { v: path, span } = path; - let path = vm.locate(&path).at(span)?; - let data = vm.world().file(&path).at(span)?; + let id = vm.location().join(&path).at(span)?; + let data = vm.world().file(id).at(span)?; let text = std::str::from_utf8(&data) .map_err(|_| "file is not valid utf-8") .at(span)?; @@ -66,8 +66,8 @@ pub fn csv( vm: &mut Vm, ) -> SourceResult<Array> { let Spanned { v: path, span } = path; - let path = vm.locate(&path).at(span)?; - let data = vm.world().file(&path).at(span)?; + let id = vm.location().join(&path).at(span)?; + let data = vm.world().file(id).at(span)?; let mut builder = csv::ReaderBuilder::new(); builder.has_headers(false); @@ -177,8 +177,8 @@ pub fn json( vm: &mut Vm, ) -> SourceResult<Value> { let Spanned { v: path, span } = path; - let path = vm.locate(&path).at(span)?; - let data = vm.world().file(&path).at(span)?; + let id = vm.location().join(&path).at(span)?; + let data = vm.world().file(id).at(span)?; let value: serde_json::Value = serde_json::from_slice(&data).map_err(format_json_error).at(span)?; Ok(convert_json(value)) @@ -243,8 +243,8 @@ pub fn toml( vm: &mut Vm, ) -> SourceResult<Value> { let Spanned { v: path, span } = path; - let path = vm.locate(&path).at(span)?; - let data = vm.world().file(&path).at(span)?; + let id = vm.location().join(&path).at(span)?; + let data = vm.world().file(id).at(span)?; let raw = std::str::from_utf8(&data) .map_err(|_| "file is not valid utf-8") @@ -352,8 +352,8 @@ pub fn yaml( vm: &mut Vm, ) -> SourceResult<Value> { let Spanned { v: path, span } = path; - let path = vm.locate(&path).at(span)?; - let data = vm.world().file(&path).at(span)?; + let id = vm.location().join(&path).at(span)?; + let data = vm.world().file(id).at(span)?; let value: serde_yaml::Value = serde_yaml::from_slice(&data).map_err(format_yaml_error).at(span)?; Ok(convert_yaml(value)) @@ -455,8 +455,8 @@ pub fn xml( vm: &mut Vm, ) -> SourceResult<Value> { let Spanned { v: path, span } = path; - let path = vm.locate(&path).at(span)?; - let data = vm.world().file(&path).at(span)?; + let id = vm.location().join(&path).at(span)?; + let data = vm.world().file(id).at(span)?; let text = std::str::from_utf8(&data).map_err(FileError::from).at(span)?; let document = roxmltree::Document::parse(text).map_err(format_xml_error).at(span)?; Ok(convert_xml(document.root())) diff --git a/library/src/meta/bibliography.rs b/library/src/meta/bibliography.rs index 0abcf5bb..0531997d 100644 --- a/library/src/meta/bibliography.rs +++ b/library/src/meta/bibliography.rs @@ -7,7 +7,8 @@ use ecow::{eco_vec, EcoVec}; use hayagriva::io::{BibLaTeXError, YamlBibliographyError}; use hayagriva::style::{self, Brackets, Citation, Database, DisplayString, Formatting}; use hayagriva::Entry; -use typst::util::option_eq; +use typst::diag::FileError; +use typst::util::{option_eq, Bytes}; use super::{LinkElem, LocalName, RefElem}; use crate::layout::{BlockElem, GridElem, ParElem, Sizing, TrackSizings, VElem}; @@ -49,18 +50,31 @@ pub struct BibliographyElem { /// Path to a Hayagriva `.yml` or BibLaTeX `.bib` file. #[required] #[parse( - let Spanned { v: mut paths, span } = + let Spanned { v: paths, span } = args.expect::<Spanned<BibPaths>>("path to bibliography file")?; - for path in &mut paths.0 { - // resolve paths - *path = vm.locate(path).at(span)?.to_string_lossy().into(); - } - // check that parsing works - let _ = load(vm.world(), &paths).at(span)?; + + // Load bibliography files. + let data = paths.0 + .iter() + .map(|path| { + let id = vm.location().join(path).at(span)?; + vm.world().file(id).at(span) + }) + .collect::<SourceResult<Vec<Bytes>>>()?; + + // Check that parsing works. + let _ = load(&paths, &data).at(span)?; + paths )] pub path: BibPaths, + /// The raw file buffers. + #[internal] + #[required] + #[parse(data)] + pub data: Vec<Bytes>, + /// The title of the bibliography. /// /// - When set to `{auto}`, an appropriate title for the [text @@ -80,7 +94,7 @@ pub struct BibliographyElem { pub style: BibliographyStyle, } -/// A list of bib file paths. +/// A list of bibliography file paths. #[derive(Debug, Default, Clone, Hash)] pub struct BibPaths(Vec<EcoString>); @@ -111,18 +125,20 @@ impl BibliographyElem { vt.introspector .query(&Self::func().select()) .into_iter() - .flat_map(|elem| load(vt.world, &elem.to::<Self>().unwrap().path())) + .flat_map(|elem| { + let elem = elem.to::<Self>().unwrap(); + load(&elem.path(), &elem.data()) + }) .flatten() .any(|entry| entry.key() == key) } /// Find all bibliography keys. pub fn keys( - world: Tracked<dyn World + '_>, introspector: Tracked<Introspector>, ) -> Vec<(EcoString, Option<EcoString>)> { Self::find(introspector) - .and_then(|elem| load(world, &elem.path())) + .and_then(|elem| load(&elem.path(), &elem.data())) .into_iter() .flatten() .map(|entry| { @@ -425,19 +441,15 @@ impl Works { _ => elem.to::<CiteElem>().unwrap().clone(), }) .collect(); - Ok(create(vt.world, bibliography, citations)) + Ok(create(bibliography, citations)) } } /// Generate all citations and the whole bibliography. #[comemo::memoize] -fn create( - world: Tracked<dyn World + '_>, - bibliography: BibliographyElem, - citations: Vec<CiteElem>, -) -> Arc<Works> { +fn create(bibliography: BibliographyElem, citations: Vec<CiteElem>) -> Arc<Works> { let span = bibliography.span(); - let entries = load(world, &bibliography.path()).unwrap(); + let entries = load(&bibliography.path(), &bibliography.data()).unwrap(); let style = bibliography.style(StyleChain::default()); let bib_location = bibliography.0.location().unwrap(); let ref_location = |target: &Entry| { @@ -587,16 +599,12 @@ fn create( /// Load bibliography entries from a path. #[comemo::memoize] -fn load( - world: Tracked<dyn World + '_>, - paths: &BibPaths, -) -> StrResult<EcoVec<hayagriva::Entry>> { +fn load(paths: &BibPaths, data: &[Bytes]) -> StrResult<EcoVec<hayagriva::Entry>> { let mut result = EcoVec::new(); // We might have multiple bib/yaml files - for path in &paths.0 { - let buffer = world.file(Path::new(path.as_str()))?; - let src = std::str::from_utf8(&buffer).map_err(|_| "file is not valid utf-8")?; + for (path, bytes) in paths.0.iter().zip(data) { + let src = std::str::from_utf8(bytes).map_err(|_| FileError::InvalidUtf8)?; let entries = parse_bib(path, src)?; result.extend(entries); } diff --git a/library/src/meta/reference.rs b/library/src/meta/reference.rs index 90823871..c39f8ca0 100644 --- a/library/src/meta/reference.rs +++ b/library/src/meta/reference.rs @@ -189,7 +189,7 @@ impl Show for RefElem { ) }) .hint(eco_format!( - "did you mean to use `#set {}(numbering: \"1.\")`?", + "you can enable heading numbering with `#set {}(numbering: \"1.\")`?", elem.func().name() )) .at(span)?; diff --git a/library/src/prelude.rs b/library/src/prelude.rs index 1a51b2a3..c720e770 100644 --- a/library/src/prelude.rs +++ b/library/src/prelude.rs @@ -19,6 +19,8 @@ pub use typst::eval::{ Func, IntoValue, Never, NoneValue, Scope, Str, Symbol, Type, Value, Vm, }; #[doc(no_inline)] +pub use typst::file::FileId; +#[doc(no_inline)] pub use typst::geom::*; #[doc(no_inline)] pub use typst::model::{ diff --git a/library/src/visualize/image.rs b/library/src/visualize/image.rs index 71f57269..b169cc4d 100644 --- a/library/src/visualize/image.rs +++ b/library/src/visualize/image.rs @@ -2,6 +2,7 @@ use std::ffi::OsStr; use std::path::Path; use typst::image::{Image, ImageFormat, RasterFormat, VectorFormat}; +use typst::util::Bytes; use crate::meta::{Figurable, LocalName}; use crate::prelude::*; @@ -37,12 +38,18 @@ pub struct ImageElem { #[parse( let Spanned { v: path, span } = args.expect::<Spanned<EcoString>>("path to image file")?; - let path: EcoString = vm.locate(&path).at(span)?.to_string_lossy().into(); - let _ = load(vm.world(), &path, None, None).at(span)?; + let id = vm.location().join(&path).at(span)?; + let data = vm.world().file(id).at(span)?; path )] pub path: EcoString, + /// The raw file data. + #[internal] + #[required] + #[parse(data)] + pub data: Bytes, + /// The width of the image. pub width: Smart<Rel<Length>>, @@ -65,10 +72,29 @@ impl Layout for ImageElem { styles: StyleChain, regions: Regions, ) -> SourceResult<Fragment> { - let first = families(styles).next(); - let fallback_family = first.as_ref().map(|f| f.as_str()); - let image = - load(vt.world, &self.path(), fallback_family, self.alt(styles)).unwrap(); + let ext = Path::new(self.path().as_str()) + .extension() + .and_then(OsStr::to_str) + .unwrap_or_default() + .to_lowercase(); + + let format = match ext.as_str() { + "png" => ImageFormat::Raster(RasterFormat::Png), + "jpg" | "jpeg" => ImageFormat::Raster(RasterFormat::Jpg), + "gif" => ImageFormat::Raster(RasterFormat::Gif), + "svg" | "svgz" => ImageFormat::Vector(VectorFormat::Svg), + _ => bail!(self.span(), "unknown image format"), + }; + + let image = Image::with_fonts( + self.data(), + format, + vt.world, + families(styles).next().as_ref().map(|f| f.as_str()), + self.alt(styles), + ) + .at(self.span())?; + let sizing = Axes::new(self.width(styles), self.height(styles)); let region = sizing .zip(regions.base()) @@ -169,24 +195,3 @@ pub enum ImageFit { /// this means that the image will be distorted. Stretch, } - -/// Load an image from a path. -#[comemo::memoize] -fn load( - world: Tracked<dyn World + '_>, - full: &str, - fallback_family: Option<&str>, - alt: Option<EcoString>, -) -> StrResult<Image> { - let full = Path::new(full); - let buffer = world.file(full)?; - let ext = full.extension().and_then(OsStr::to_str).unwrap_or_default(); - let format = match ext.to_lowercase().as_str() { - "png" => ImageFormat::Raster(RasterFormat::Png), - "jpg" | "jpeg" => ImageFormat::Raster(RasterFormat::Jpg), - "gif" => ImageFormat::Raster(RasterFormat::Gif), - "svg" | "svgz" => ImageFormat::Vector(VectorFormat::Svg), - _ => bail!("unknown image format"), - }; - Image::with_fonts(buffer, format, world, fallback_family, alt) -} |
