summaryrefslogtreecommitdiff
path: root/library
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2023-06-26 13:57:21 +0200
committerLaurenz <laurmaedje@gmail.com>2023-06-27 18:40:17 +0200
commit7b92bd7c340d9f9c094ed2fa57912049317d9b20 (patch)
treeb91399526ba94d87309d09d864df2935dd7a4d0a /library
parent9c7f31870b4e1bf37df79ebbe1df9a56df83d878 (diff)
Basic package management
Diffstat (limited to 'library')
-rw-r--r--library/src/compute/data.rs24
-rw-r--r--library/src/meta/bibliography.rs60
-rw-r--r--library/src/meta/reference.rs2
-rw-r--r--library/src/prelude.rs2
-rw-r--r--library/src/visualize/image.rs59
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)
-}