This commit is contained in:
Laurenz Stampfl 2025-03-10 10:29:37 +01:00
parent 33199e1c00
commit c14eeae249
3 changed files with 106 additions and 45 deletions

View File

@ -241,6 +241,10 @@ pub struct CompileArgs {
#[arg(long = "pages", value_delimiter = ',')]
pub pages: Option<Vec<Pages>>,
/// The version of the produced PDF.
#[arg(long = "pdf-version")]
pub pdf_version: Option<PdfVersion>,
/// One (or multiple comma-separated) PDF standards that Typst will enforce
/// conformance with.
#[arg(long = "pdf-standard", value_delimiter = ',')]
@ -463,23 +467,59 @@ pub enum Feature {
display_possible_values!(Feature);
/// A PDF version.
#[derive(Debug, Copy, Clone, Eq, PartialEq, ValueEnum)]
#[allow(non_camel_case_types)]
pub enum PdfVersion {
/// PDF 1.4.
#[value(name = "1.4")]
V_1_4,
/// PDF 1.5.
#[value(name = "1.5")]
V_1_5,
/// PDF 1.5.
#[value(name = "1.6")]
V_1_6,
/// PDF 1.7.
#[value(name = "1.7")]
V_1_7,
/// PDF 2.0.
#[value(name = "2.0")]
V_2_0,
}
display_possible_values!(PdfVersion);
/// A PDF standard that Typst can enforce conformance with.
#[derive(Debug, Copy, Clone, Eq, PartialEq, ValueEnum)]
#[allow(non_camel_case_types)]
pub enum PdfStandard {
/// PDF 1.7.
#[value(name = "1.7")]
V_1_7,
/// PDF/A-1b.
#[value(name = "a-1b")]
A_1b,
/// PDF/A-2b.
#[value(name = "a-2b")]
A_2b,
/// PDF/A-3b.
/// PDF/A-2u.
#[value(name = "a-2u")]
A_2u,
/// PDF/A-3u.
#[value(name = "a-3b")]
A_3b,
/// PDF/A-3u.
#[value(name = "a-3u")]
A_3u,
/// PDF/A-4.
#[value(name = "a-4")]
A_4,
/// PDF/A-4f.
#[value(name = "a-4f")]
A_4f,
/// PDF/A-4e.
#[value(name = "a-4e")]
A_4e,
}
display_possible_values!(PdfStandard);
// Output file format for query command
#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, ValueEnum)]
pub enum SerializationFormat {

View File

@ -18,12 +18,9 @@ use typst::html::HtmlDocument;
use typst::layout::{Frame, Page, PageRanges, PagedDocument};
use typst::syntax::{FileId, Source, Span};
use typst::WorldExt;
use typst_pdf::{PdfOptions, Timestamp};
use typst_pdf::{PdfOptions, Timestamp, Validator};
use crate::args::{
CompileArgs, CompileCommand, DiagnosticFormat, Input, Output, OutputFormat,
PdfStandard, WatchCommand,
};
use crate::args::{CompileArgs, CompileCommand, DiagnosticFormat, Input, Output, OutputFormat, PdfStandard, PdfVersion, WatchCommand};
#[cfg(feature = "http-server")]
use crate::server::HtmlServer;
use crate::timings::Timer;
@ -63,9 +60,10 @@ pub struct CompileConfig {
/// Opens the output file with the default viewer or a specific program after
/// compilation.
pub open: Option<Option<String>>,
/// One (or multiple comma-separated) PDF standards that Typst will enforce
/// conformance with.
pub pdf_standards: PdfStandards,
/// The version that should be used to export the PDF.
pub pdf_version: Option<PdfVersion>,
/// A list of standards the PDF should conform to.
pub pdf_standard: Vec<PdfStandard>,
/// A path to write a Makefile rule describing the current compilation.
pub make_deps: Option<PathBuf>,
/// The PPI (pixels per inch) to use for PNG export.
@ -130,19 +128,6 @@ impl CompileConfig {
PageRanges::new(export_ranges.iter().map(|r| r.0.clone()).collect())
});
let pdf_standards = {
let list = args
.pdf_standard
.iter()
.map(|standard| match standard {
PdfStandard::V_1_7 => typst_pdf::PdfStandard::V_1_7,
PdfStandard::A_2b => typst_pdf::PdfStandard::A_2b,
PdfStandard::A_3b => typst_pdf::PdfStandard::A_3b,
})
.collect::<Vec<_>>();
PdfStandards::new(&list)?
};
#[cfg(feature = "http-server")]
let server = match watch {
Some(command)
@ -159,7 +144,8 @@ impl CompileConfig {
output,
output_format,
pages,
pdf_standards,
pdf_version: args.pdf_version,
pdf_standard: args.pdf_standard.clone(),
creation_timestamp: args.world.creation_timestamp,
make_deps: args.make_deps.clone(),
ppi: args.ppi,
@ -295,11 +281,45 @@ fn export_pdf(document: &PagedDocument, config: &CompileConfig) -> SourceResult<
})
}
};
let validator = match config.pdf_standard.first() {
None => None,
Some(s) => {
let validator = if config.pdf_standard.len() > 1 {
bail!(Span::detached(), "cannot export using more than one PDF standard";
hint: "typst currently only supports export using \
one standard at the same time");
} else {
match s {
PdfStandard::A_1b => Validator::A_1b,
PdfStandard::A_2b => Validator::A_2b,
PdfStandard::A_2u => Validator::A_2u,
PdfStandard::A_3b => Validator::A_3b,
PdfStandard::A_3u => Validator::A_3u,
PdfStandard::A_4 => Validator::A_4,
PdfStandard::A_4f => Validator::A_4f,
PdfStandard::A_4e => Validator::A_4e
}
};
Some(validator)
}
};
let pdf_version = config.pdf_version.map(|v| match v {
PdfVersion::V_1_4 => typst_pdf::PdfVersion::Pdf14,
PdfVersion::V_1_5 => typst_pdf::PdfVersion::Pdf15,
PdfVersion::V_1_6 => typst_pdf::PdfVersion::Pdf16,
PdfVersion::V_1_7 => typst_pdf::PdfVersion::Pdf17,
PdfVersion::V_2_0 => typst_pdf::PdfVersion::Pdf20,
});
let options = PdfOptions {
ident: Smart::Auto,
timestamp,
page_ranges: config.pages.clone(),
standards: config.pdf_standards.clone(),
validator,
pdf_version
};
let buffer = typst_pdf::pdf(document, &options)?;
config

View File

@ -52,39 +52,40 @@ impl From<PdfVersion> for krilla::configure::PdfVersion {
/// A validator for exporting PDF documents to a specific subset of PDF.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[allow(non_camel_case_types)]
pub enum Validator {
/// The validator for the PDF/A1-A standard.
A1_A,
/// The validator for the PDF/A1-B standard.
A1_B,
A_1b,
/// The validator for the PDF/A2-B standard.
A2_B,
A_2b,
/// The validator for the PDF/A2-U standard.
A2_U,
A_2u,
/// The validator for the PDF/A3-B standard.
A3_B,
A_3b,
/// The validator for the PDF/A3-U standard.
A3_U,
A_3u,
/// The validator for the PDF/A4 standard.
A4,
A_4,
/// The validator for the PDF/A4f standard.
A4F,
A_4f,
/// The validator for the PDF/A4e standard.
A4E,
A_4e,
}
impl From<Validator> for krilla::configure::Validator {
fn from(value: Validator) -> Self {
match value {
Validator::A1_A => krilla::configure::Validator::A1_A,
Validator::A1_B => krilla::configure::Validator::A1_B,
Validator::A2_B => krilla::configure::Validator::A2_B,
Validator::A2_U => krilla::configure::Validator::A2_U,
Validator::A3_B => krilla::configure::Validator::A3_B,
Validator::A3_U => krilla::configure::Validator::A3_U,
Validator::A4 => krilla::configure::Validator::A4,
Validator::A4F => krilla::configure::Validator::A4F,
Validator::A4E => krilla::configure::Validator::A4E,
Validator::A_1b => krilla::configure::Validator::A1_B,
Validator::A_2b => krilla::configure::Validator::A2_B,
Validator::A_2u => krilla::configure::Validator::A2_U,
Validator::A_3b => krilla::configure::Validator::A3_B,
Validator::A_3u => krilla::configure::Validator::A3_U,
Validator::A_4 => krilla::configure::Validator::A4,
Validator::A_4f => krilla::configure::Validator::A4F,
Validator::A_4e => krilla::configure::Validator::A4E,
}
}
}