mirror of
https://github.com/Myriad-Dreamin/tinymist.git
synced 2025-08-02 17:32:16 +00:00
feat: export to format regardless of export target (#1549)
* feat: export to format regardless of export target * chore: move todo comment
This commit is contained in:
parent
fadf85e68a
commit
d4f00b86b0
2 changed files with 77 additions and 45 deletions
|
@ -12,7 +12,7 @@ use typst::ecow::EcoVec;
|
|||
use typst::syntax::Span;
|
||||
|
||||
use crate::snapshot::CompileSnapshot;
|
||||
use crate::{CompilerFeat, EntryReader};
|
||||
use crate::{CompilerFeat, CompilerWorld, EntryReader};
|
||||
|
||||
type AnyArc = Arc<dyn std::any::Any + Send + Sync>;
|
||||
|
||||
|
@ -218,6 +218,43 @@ pub type HtmlCompilationTask = CompilationTask<TypstHtmlDocument>;
|
|||
|
||||
pub struct CompilationTask<D>(std::marker::PhantomData<D>);
|
||||
|
||||
impl<D: typst::Document + Send + Sync + 'static> CompilationTask<D> {
|
||||
pub fn execute<F: CompilerFeat>(world: &CompilerWorld<F>) -> Warned<SourceResult<Arc<D>>> {
|
||||
let is_paged_compilation = TypeId::of::<D>() == TypeId::of::<TypstPagedDocument>();
|
||||
let is_html_compilation = TypeId::of::<D>() == TypeId::of::<TypstHtmlDocument>();
|
||||
|
||||
let mut world = if is_paged_compilation {
|
||||
world.paged_task()
|
||||
} else if is_html_compilation {
|
||||
// todo: create html world once
|
||||
world.html_task()
|
||||
} else {
|
||||
Cow::Borrowed(world)
|
||||
};
|
||||
|
||||
world.to_mut().set_is_compiling(true);
|
||||
let compiled = typst::compile::<D>(world.as_ref());
|
||||
world.to_mut().set_is_compiling(false);
|
||||
|
||||
let exclude_html_warnings = if !is_html_compilation {
|
||||
compiled.warnings
|
||||
} else if compiled.warnings.len() == 1
|
||||
&& compiled.warnings[0]
|
||||
.message
|
||||
.starts_with("html export is under active development")
|
||||
{
|
||||
EcoVec::new()
|
||||
} else {
|
||||
compiled.warnings
|
||||
};
|
||||
|
||||
Warned {
|
||||
output: compiled.output.map(Arc::new),
|
||||
warnings: exclude_html_warnings,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: CompilerFeat, D> WorldComputable<F> for CompilationTask<D>
|
||||
where
|
||||
D: typst::Document + Send + Sync + 'static,
|
||||
|
@ -227,40 +264,7 @@ where
|
|||
fn compute(graph: &Arc<WorldComputeGraph<F>>) -> Result<Self::Output> {
|
||||
let enabled = graph.must_get::<FlagTask<CompilationTask<D>>>()?.enabled;
|
||||
|
||||
Ok(enabled.then(|| {
|
||||
// todo: create html world once
|
||||
let is_paged_compilation = TypeId::of::<D>() == TypeId::of::<TypstPagedDocument>();
|
||||
let is_html_compilation = TypeId::of::<D>() == TypeId::of::<TypstHtmlDocument>();
|
||||
|
||||
let mut world = if is_paged_compilation {
|
||||
graph.snap.world.paged_task()
|
||||
} else if is_html_compilation {
|
||||
graph.snap.world.html_task()
|
||||
} else {
|
||||
Cow::Borrowed(&graph.snap.world)
|
||||
};
|
||||
|
||||
world.to_mut().set_is_compiling(true);
|
||||
let compiled = typst::compile::<D>(world.as_ref());
|
||||
world.to_mut().set_is_compiling(false);
|
||||
|
||||
let exclude_html_warnings = if !is_html_compilation {
|
||||
compiled.warnings
|
||||
} else if compiled.warnings.len() == 1
|
||||
&& compiled.warnings[0]
|
||||
.message
|
||||
.starts_with("html export is under active development")
|
||||
{
|
||||
EcoVec::new()
|
||||
} else {
|
||||
compiled.warnings
|
||||
};
|
||||
|
||||
Warned {
|
||||
output: compiled.output.map(Arc::new),
|
||||
warnings: exclude_html_warnings,
|
||||
}
|
||||
}))
|
||||
Ok(enabled.then(|| CompilationTask::<D>::execute(&graph.snap.world)))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
//! The actor that handles various document export, like PDF and SVG export.
|
||||
|
||||
use std::path::PathBuf;
|
||||
use std::str::FromStr;
|
||||
use std::sync::atomic::AtomicUsize;
|
||||
use std::{path::PathBuf, sync::Arc};
|
||||
use std::sync::{Arc, OnceLock};
|
||||
|
||||
use reflexo::ImmutPath;
|
||||
use reflexo_typst::CompilationTask;
|
||||
use tinymist_project::LspWorld;
|
||||
use tinymist_std::error::prelude::*;
|
||||
use tinymist_std::typst::TypstDocument;
|
||||
use tinymist_task::{convert_datetime, get_page_selection, ExportTarget, TextExport};
|
||||
|
@ -186,17 +189,30 @@ impl ExportTask {
|
|||
let doc = &doc;
|
||||
|
||||
// static BLANK: Lazy<Page> = Lazy::new(Page::default);
|
||||
let html_doc = || {
|
||||
Ok(match &doc {
|
||||
TypstDocument::Html(html_doc) => html_doc,
|
||||
TypstDocument::Paged(_) => bail!("expected html document, found Paged"),
|
||||
})
|
||||
// todo: check warnings and errors inside
|
||||
let html_once = OnceLock::new();
|
||||
let html_doc = || -> Result<_> {
|
||||
html_once
|
||||
.get_or_init(|| -> Result<_> {
|
||||
Ok(match &doc {
|
||||
TypstDocument::Html(html_doc) => html_doc.clone(),
|
||||
TypstDocument::Paged(_) => extra_compile_for_export(&snap.world)?,
|
||||
})
|
||||
})
|
||||
.as_ref()
|
||||
.map_err(|e| e.clone())
|
||||
};
|
||||
let page_once = OnceLock::new();
|
||||
let paged_doc = || {
|
||||
Ok(match &doc {
|
||||
TypstDocument::Paged(paged_doc) => paged_doc,
|
||||
TypstDocument::Html(_) => bail!("expected paged document, found HTML"),
|
||||
})
|
||||
page_once
|
||||
.get_or_init(|| -> Result<_> {
|
||||
Ok(match &doc {
|
||||
TypstDocument::Paged(paged_doc) => paged_doc.clone(),
|
||||
TypstDocument::Html(_) => extra_compile_for_export(&snap.world)?,
|
||||
})
|
||||
})
|
||||
.as_ref()
|
||||
.map_err(|e| e.clone())
|
||||
};
|
||||
let first_page = || {
|
||||
paged_doc()?
|
||||
|
@ -373,6 +389,18 @@ fn log_err<T>(artifact: Result<T>) -> Option<T> {
|
|||
}
|
||||
}
|
||||
|
||||
fn extra_compile_for_export<D: typst::Document + Send + Sync + 'static>(
|
||||
world: &LspWorld,
|
||||
) -> Result<Arc<D>> {
|
||||
let res = tokio::task::block_in_place(|| CompilationTask::<D>::execute(world));
|
||||
|
||||
match res.output {
|
||||
Ok(v) => Ok(v),
|
||||
Err(e) if e.is_empty() => bail!("failed to compile: internal error"),
|
||||
Err(e) => bail!("failed to compile: {}", e[0].message),
|
||||
}
|
||||
}
|
||||
|
||||
/// Serialize data to the output format.
|
||||
fn serialize(data: &impl serde::Serialize, format: &str, pretty: bool) -> Result<String> {
|
||||
Ok(match format {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue