Revert "revert html changes"

This reverts commit b82662e441.
This commit is contained in:
Myriad-Dreamin 2025-02-08 22:07:07 +08:00
parent b82662e441
commit b42643399c
10 changed files with 119 additions and 69 deletions

1
Cargo.lock generated
View file

@ -4238,7 +4238,6 @@ dependencies = [
"typst-assets",
"typst-pdf",
"typst-render",
"typst-shim",
"typst-svg",
]

View file

@ -90,7 +90,7 @@ impl<F: CompilerFeat> CompiledArtifact<F> {
/// Runs the compiler and returns the compiled document.
pub fn from_snapshot(mut snap: CompileSnapshot<F>) -> CompiledArtifact<F> {
snap.world.set_is_compiling(true);
let res = ::typst::compile(&snap.world);
let res = ::typst::compile::<tinymist_std::typst::TypstPagedDocument>(&snap.world);
let warned = match res.output {
Ok(doc) => Ok(Warned {
output: Arc::new(doc),

View file

@ -35,9 +35,10 @@ toml.workspace = true
typst.workspace = true
typst-assets.workspace = true
typst-pdf.workspace = true
typst-shim.workspace = true
typst-html.workspace = true
typst-svg.workspace = true
typst-render.workspace = true
typst-eval.workspace = true
notify.workspace = true
[features]

View file

@ -6,7 +6,7 @@ use std::sync::Arc;
use comemo::Track;
use ecow::EcoString;
use tinymist_std::error::prelude::*;
use tinymist_std::typst::TypstPagedDocument;
use tinymist_std::typst::{TypstHtmlDocument, TypstPagedDocument};
use tinymist_world::{
args::convert_source_date_epoch, CompileSnapshot, CompilerFeat, ExportComputation,
WorldComputeGraph,
@ -14,13 +14,14 @@ use tinymist_world::{
use typst::diag::{SourceResult, StrResult};
use typst::foundations::{Bytes, Content, Datetime, IntoValue, LocatableSelector, Scope, Value};
use typst::layout::Abs;
use typst::routines::EvalMode;
use typst::syntax::{ast, Span, SyntaxNode};
use typst::visualize::Color;
use typst::World;
use typst_pdf::PdfOptions;
use typst_shim::eval::EvalMode;
use typst_eval::eval_string;
use typst_pdf::{PdfOptions, Timestamp};
use crate::model::{ExportPdfTask, ExportPngTask, ExportSvgTask};
use crate::model::{ExportHtmlTask, ExportPdfTask, ExportPngTask, ExportSvgTask};
use crate::primitives::TaskWhen;
use crate::{ExportTransform, Pages, QueryTask};
@ -40,10 +41,10 @@ pub struct HtmlFlag;
pub struct ExportTimings;
impl ExportTimings {
pub fn needs_run<F: CompilerFeat>(
pub fn needs_run<F: CompilerFeat, D: typst::Document>(
snap: &CompileSnapshot<F>,
timing: Option<TaskWhen>,
docs: Option<&TypstPagedDocument>,
docs: Option<&D>,
) -> Option<bool> {
let s = snap.signal;
let when = timing.unwrap_or(TaskWhen::Never);
@ -56,7 +57,7 @@ impl ExportTimings {
TaskWhen::OnType => Some(s.by_mem_events),
TaskWhen::OnSave => Some(s.by_fs_events),
TaskWhen::OnDocumentHasTitle if s.by_fs_events => {
docs.map(|doc| doc.info.title.is_some())
docs.map(|doc| doc.info().title.is_some())
}
TaskWhen::OnDocumentHasTitle => Some(false),
}
@ -135,7 +136,7 @@ impl<F: CompilerFeat> ExportComputation<F, TypstPagedDocument> for PngExport {
pixmap
.encode_png()
.map(Bytes::from)
.map(Bytes::new)
.context_ut("failed to encode PNG")
}
}
@ -148,6 +149,21 @@ impl<F: CompilerFeat> ExportComputation<F, TypstPagedDocument> for PngExport {
// }
// }
pub struct HtmlExport;
impl<F: CompilerFeat> ExportComputation<F, TypstHtmlDocument> for HtmlExport {
type Output = String;
type Config = ExportHtmlTask;
fn run(
_graph: &Arc<WorldComputeGraph<F>>,
doc: &Arc<TypstHtmlDocument>,
_config: &ExportHtmlTask,
) -> Result<String> {
Ok(typst_html::html(doc)?)
}
}
// impl<F: CompilerFeat> WorldComputable<F> for HtmlExport {
// type Output = Option<String>;
@ -161,12 +177,13 @@ pub struct DocumentQuery;
impl DocumentQuery {
// todo: query exporter
/// Retrieve the matches for the selector.
pub fn retrieve(
pub fn retrieve<D: typst::Document>(
world: &dyn World,
selector: &str,
document: &TypstPagedDocument,
document: &D,
) -> StrResult<Vec<Content>> {
let selector = typst_shim::eval::eval_string(
let selector = eval_string(
&typst::ROUTINES,
world.track(),
selector,
Span::detached(),
@ -185,15 +202,15 @@ impl DocumentQuery {
.map_err(|e| EcoString::from(format!("failed to cast: {}", e.message())))?;
Ok(document
.introspector
.introspector()
.query(&selector.0)
.into_iter()
.collect::<Vec<_>>())
}
fn run_inner<F: CompilerFeat>(
fn run_inner<F: CompilerFeat, D: typst::Document>(
g: &Arc<WorldComputeGraph<F>>,
doc: &Arc<TypstPagedDocument>,
doc: &Arc<D>,
config: &QueryTask,
) -> Result<Vec<Value>> {
let selector = &config.selector;
@ -212,9 +229,9 @@ impl DocumentQuery {
.collect())
}
pub fn get_as_value<F: CompilerFeat>(
pub fn get_as_value<F: CompilerFeat, D: typst::Document>(
g: &Arc<WorldComputeGraph<F>>,
doc: &Arc<TypstPagedDocument>,
doc: &Arc<D>,
config: &QueryTask,
) -> Result<serde_json::Value> {
let mapped = Self::run_inner(g, doc, config)?;
@ -232,13 +249,13 @@ impl DocumentQuery {
}
}
impl<F: CompilerFeat> ExportComputation<F, TypstPagedDocument> for DocumentQuery {
impl<F: CompilerFeat, D: typst::Document> ExportComputation<F, D> for DocumentQuery {
type Output = SourceResult<String>;
type Config = QueryTask;
fn run(
g: &Arc<WorldComputeGraph<F>>,
doc: &Arc<TypstPagedDocument>,
doc: &Arc<D>,
config: &QueryTask,
) -> Result<SourceResult<String>> {
let pretty = false;
@ -356,17 +373,19 @@ fn parse_color(fill: String) -> anyhow::Result<Color> {
}
}
/// Convert [`chrono::DateTime`] to [`Datetime`]
fn convert_datetime(date_time: chrono::DateTime<chrono::Utc>) -> Option<Datetime> {
/// Convert [`chrono::DateTime`] to [`Timestamp`]
fn convert_datetime(date_time: chrono::DateTime<chrono::Utc>) -> Option<Timestamp> {
use chrono::{Datelike, Timelike};
Datetime::from_ymd_hms(
let datetime = Datetime::from_ymd_hms(
date_time.year(),
date_time.month().try_into().ok()?,
date_time.day().try_into().ok()?,
date_time.hour().try_into().ok()?,
date_time.minute().try_into().ok()?,
date_time.second().try_into().ok()?,
)
);
Some(Timestamp::new_utc(datetime.unwrap()))
}
#[cfg(test)]

View file

@ -2,6 +2,7 @@ use super::*;
pub use typst_pdf::pdf;
pub use typst_pdf::PdfStandard as TypstPdfStandard;
pub use typst_pdf::Timestamp as TypstTimestamp;
pub struct PdfExport;
impl<F: CompilerFeat> ExportComputation<F, TypstPagedDocument> for PdfExport {
@ -23,7 +24,7 @@ impl<F: CompilerFeat> ExportComputation<F, TypstPagedDocument> for PdfExport {
// todo: Some(pdf_uri.as_str())
Ok(Bytes::from(typst_pdf::pdf(
Ok(Bytes::new(typst_pdf::pdf(
doc,
&PdfOptions {
timestamp: convert_datetime(creation_timestamp),

View file

@ -66,6 +66,7 @@ impl fmt::Display for FullTextDigest {
}
Ok(())
}
_ => Err(fmt::Error),
}
}
}

View file

@ -3,11 +3,11 @@
use std::any::TypeId;
use std::sync::{Arc, OnceLock};
use ecow::EcoVec;
use parking_lot::Mutex;
use tinymist_std::error::prelude::*;
use tinymist_std::typst::TypstPagedDocument;
use tinymist_std::typst::{TypstHtmlDocument, TypstPagedDocument};
use typst::diag::{At, SourceResult, Warned};
use typst::ecow::EcoVec;
use typst::syntax::Span;
use crate::snapshot::CompileSnapshot;
@ -147,9 +147,6 @@ impl<F: CompilerFeat> WorldComputeGraph<F> {
}
}
pub trait Document {}
impl Document for TypstPagedDocument {}
pub trait ExportDetection<F: CompilerFeat, D> {
type Config: Send + Sync + 'static;
@ -203,19 +200,21 @@ impl<T> FlagTask<T> {
}
pub type PagedCompilationTask = CompilationTask<TypstPagedDocument>;
pub type HtmlCompilationTask = CompilationTask<TypstHtmlDocument>;
pub struct CompilationTask<D>(std::marker::PhantomData<D>);
impl<F: CompilerFeat> WorldComputable<F> for CompilationTask<TypstPagedDocument> {
type Output = Option<Warned<SourceResult<Arc<TypstPagedDocument>>>>;
impl<F: CompilerFeat, D> WorldComputable<F> for CompilationTask<D>
where
D: typst::Document + Send + Sync + 'static,
{
type Output = Option<Warned<SourceResult<Arc<D>>>>;
fn compute(graph: &Arc<WorldComputeGraph<F>>) -> Result<Self::Output> {
let enabled = graph
.must_get::<FlagTask<CompilationTask<TypstPagedDocument>>>()?
.enabled;
let enabled = graph.must_get::<FlagTask<CompilationTask<D>>>()?.enabled;
Ok(enabled.then(|| {
let compiled = typst::compile(&graph.snap.world);
let compiled = typst::compile::<D>(&graph.snap.world);
Warned {
output: compiled.output.map(Arc::new),
warnings: compiled.warnings,
@ -226,18 +225,25 @@ impl<F: CompilerFeat> WorldComputable<F> for CompilationTask<TypstPagedDocument>
pub struct OptionDocumentTask<D>(std::marker::PhantomData<D>);
impl<F: CompilerFeat> WorldComputable<F> for OptionDocumentTask<TypstPagedDocument> {
type Output = Option<Arc<TypstPagedDocument>>;
impl<F: CompilerFeat, D> WorldComputable<F> for OptionDocumentTask<D>
where
D: typst::Document + Send + Sync + 'static,
{
type Output = Option<Arc<D>>;
fn compute(graph: &Arc<WorldComputeGraph<F>>) -> Result<Self::Output> {
let doc = graph.compute::<CompilationTask<TypstPagedDocument>>()?;
let doc = doc.as_ref().as_ref();
let compiled = doc.and_then(|warned| warned.output.clone().ok());
let doc = graph.compute::<CompilationTask<D>>()?;
let compiled = doc
.as_ref()
.as_ref()
.and_then(|warned| warned.output.clone().ok());
Ok(compiled)
}
}
impl<D> OptionDocumentTask<D> where D: typst::Document + Send + Sync + 'static {}
struct CompilationDiagnostics {
errors: Option<EcoVec<typst::diag::SourceDiagnostic>>,
warnings: Option<EcoVec<typst::diag::SourceDiagnostic>>,
@ -256,6 +262,7 @@ impl CompilationDiagnostics {
pub struct DiagnosticsTask {
paged: CompilationDiagnostics,
html: CompilationDiagnostics,
}
impl<F: CompilerFeat> WorldComputable<F> for DiagnosticsTask {
@ -263,9 +270,11 @@ impl<F: CompilerFeat> WorldComputable<F> for DiagnosticsTask {
fn compute(graph: &Arc<WorldComputeGraph<F>>) -> Result<Self> {
let paged = graph.compute::<PagedCompilationTask>()?.clone();
let html = graph.compute::<HtmlCompilationTask>()?.clone();
Ok(Self {
paged: CompilationDiagnostics::from_result(paged.as_ref()),
paged: CompilationDiagnostics::from_result(&paged),
html: CompilationDiagnostics::from_result(&html),
})
}
}
@ -276,6 +285,8 @@ impl DiagnosticsTask {
.errors
.iter()
.chain(self.paged.warnings.iter())
.chain(self.html.errors.iter())
.chain(self.html.warnings.iter())
.flatten()
}
}
@ -342,8 +353,8 @@ impl<F: CompilerFeat> WorldComputeGraph<F> {
}
/// Compile once from scratch.
pub fn pure_compile(&self) -> Warned<SourceResult<Arc<TypstPagedDocument>>> {
let res = ::typst::compile(&self.snap.world);
pub fn pure_compile<D: ::typst::Document>(&self) -> Warned<SourceResult<Arc<D>>> {
let res = ::typst::compile::<D>(&self.snap.world);
// compile document
Warned {
output: res.output.map(Arc::new),
@ -355,4 +366,14 @@ impl<F: CompilerFeat> WorldComputeGraph<F> {
pub fn compile(&self) -> Warned<SourceResult<Arc<TypstPagedDocument>>> {
self.pure_compile()
}
/// Compile to html once from scratch.
pub fn compile_html(&self) -> Warned<SourceResult<Arc<::typst::html::HtmlDocument>>> {
self.pure_compile()
}
// With **the compilation state**, query the matches for the selector.
// fn query(&mut self, selector: String, document: &TypstDocument) ->
// SourceResult<Vec<Content>> { self.pure_query(world, selector,
// document) }
}

View file

@ -118,13 +118,15 @@ mod tests {
#[test]
fn test_args() {
use tinymist_std::typst::TypstPagedDocument;
let args = CompileOnceArgs::parse_from(["tinymist", "main.typ"]);
let verse = args
.resolve_system()
.expect("failed to resolve system universe");
let world = verse.snapshot();
let _res = typst::compile(&world);
let _res = typst::compile::<TypstPagedDocument>(&world);
}
static FONT_COMPUTED: AtomicBool = AtomicBool::new(false);

View file

@ -102,7 +102,6 @@ embed-fonts = ["tinymist-project/fonts"]
# This requires modifying typst.
no-content-hint = [
"tinymist-query/no-content-hint",
"tinymist-task/no-content-hint",
"reflexo-typst/no-content-hint",
"reflexo-vec2svg/no-content-hint",
]

View file

@ -2,8 +2,8 @@
use std::sync::Arc;
use reflexo_typst::Bytes;
use tinymist_project::{EntryReader, LspCompilerFeat, PdfExport, PngExport, SvgExport, TaskWhen};
use reflexo_typst::{Bytes, CompilerFeat, EntryReader};
use tinymist_project::{HtmlExport, LspCompilerFeat, PdfExport, PngExport, SvgExport, TaskWhen};
use tinymist_std::error::prelude::*;
use tinymist_std::typst::{TypstDocument, TypstPagedDocument};
use tinymist_task::ExportTimings;
@ -13,8 +13,8 @@ use typst::diag::SourceResult;
use crate::project::{ExportMarkdownTask, ExportTextTask, ProjectTask};
use crate::tool::text::FullTextDigest;
use crate::world::base::{
CompilerFeat, ConfigTask, DiagnosticsTask, ExportComputation, FlagTask, OptionDocumentTask,
PagedCompilationTask, WorldComputable, WorldComputeGraph,
ConfigTask, DiagnosticsTask, ExportComputation, FlagTask, HtmlCompilationTask,
OptionDocumentTask, PagedCompilationTask, WorldComputable, WorldComputeGraph,
};
#[derive(Clone, Copy, Default)]
@ -24,6 +24,7 @@ impl ProjectCompilation {
pub fn preconfig_timings<F: CompilerFeat>(graph: &Arc<WorldComputeGraph<F>>) -> Result<bool> {
// todo: configure run_diagnostics!
let paged_diag = Some(TaskWhen::OnType);
let html_diag = Some(TaskWhen::Never);
let pdf: Option<TaskWhen> = graph
.get::<ConfigTask<<PdfExport as ExportComputation<LspCompilerFeat, _>>::Config>>()
@ -37,6 +38,10 @@ impl ProjectCompilation {
.get::<ConfigTask<<PngExport as ExportComputation<LspCompilerFeat, _>>::Config>>()
.transpose()?
.map(|config| config.export.when);
let html: Option<TaskWhen> = graph
.get::<ConfigTask<<HtmlExport as ExportComputation<LspCompilerFeat, _>>::Config>>()
.transpose()?
.map(|config| config.export.when);
let md: Option<TaskWhen> = graph
.get::<ConfigTask<ExportMarkdownTask>>()
.transpose()?
@ -50,10 +55,12 @@ impl ProjectCompilation {
let check = |timing| ExportTimings::needs_run(&graph.snap, timing, doc).unwrap_or(true);
let compile_paged = [paged_diag, pdf, svg, png, text, md].into_iter().any(check);
let compile_html = [html_diag, html].into_iter().any(check);
let _ = graph.provide::<FlagTask<PagedCompilationTask>>(Ok(FlagTask::flag(compile_paged)));
let _ = graph.provide::<FlagTask<HtmlCompilationTask>>(Ok(FlagTask::flag(compile_html)));
Ok(compile_paged)
Ok(compile_paged || compile_html)
}
}
@ -70,12 +77,15 @@ impl<F: CompilerFeat> WorldComputable<F> for ProjectCompilation {
pub struct ProjectExport;
impl ProjectExport {
fn export_bytes<T: ExportComputation<LspCompilerFeat, TypstPagedDocument, Output = Bytes>>(
fn export_bytes<
D: typst::Document + Send + Sync + 'static,
T: ExportComputation<LspCompilerFeat, D, Output = Bytes>,
>(
graph: &Arc<WorldComputeGraph<LspCompilerFeat>>,
when: Option<TaskWhen>,
config: &T::Config,
) -> Result<Option<Bytes>> {
let doc = graph.compute::<OptionDocumentTask<TypstPagedDocument>>()?;
let doc = graph.compute::<OptionDocumentTask<D>>()?;
let doc = doc.as_ref();
let n = ExportTimings::needs_run(&graph.snap, when, doc.as_deref()).unwrap_or(true);
if !n {
@ -86,12 +96,15 @@ impl ProjectExport {
res.transpose()
}
fn export_string<T: ExportComputation<LspCompilerFeat, TypstPagedDocument, Output = String>>(
fn export_string<
D: typst::Document + Send + Sync + 'static,
T: ExportComputation<LspCompilerFeat, D, Output = String>,
>(
graph: &Arc<WorldComputeGraph<LspCompilerFeat>>,
when: Option<TaskWhen>,
config: &T::Config,
) -> Result<Option<Bytes>> {
let doc = graph.compute::<OptionDocumentTask<TypstPagedDocument>>()?;
let doc = graph.compute::<OptionDocumentTask<D>>()?;
let doc = doc.as_ref();
let n = ExportTimings::needs_run(&graph.snap, when, doc.as_deref()).unwrap_or(true);
if !n {
@ -99,11 +112,7 @@ impl ProjectExport {
}
let doc = doc.as_ref();
let res = doc.map(|doc| {
T::run(graph, doc, config)
.map(String::into_bytes)
.map(Bytes::from)
});
let res = doc.map(|doc| T::run(graph, doc, config).map(Bytes::from_string));
res.transpose()
}
}
@ -124,10 +133,10 @@ impl WorldComputable<LspCompilerFeat> for ProjectExport {
use ProjectTask::*;
match config.as_ref() {
Preview(..) => todo!(),
ExportPdf(config) => Self::export_bytes::<PdfExport>(graph, when, config),
ExportPng(config) => Self::export_bytes::<PngExport>(graph, when, config),
ExportSvg(config) => Self::export_string::<SvgExport>(graph, when, config),
ExportHtml(_config) => todo!(),
ExportPdf(config) => Self::export_bytes::<_, PdfExport>(graph, when, config),
ExportPng(config) => Self::export_bytes::<_, PngExport>(graph, when, config),
ExportSvg(config) => Self::export_string::<_, SvgExport>(graph, when, config),
ExportHtml(config) => Self::export_string::<_, HtmlExport>(graph, when, config),
ExportMd(_config) => {
let doc = graph.compute::<OptionDocumentTask<TypstPagedDocument>>()?;
let doc = doc.as_ref();
@ -137,11 +146,9 @@ impl WorldComputable<LspCompilerFeat> for ProjectExport {
return Ok(None);
}
Ok(TypliteMdExport::run(graph)?
.map(String::into_bytes)
.map(Bytes::from))
Ok(TypliteMdExport::run(graph)?.map(Bytes::from_string))
}
ExportText(config) => Self::export_string::<TextExport>(graph, when, config),
ExportText(config) => Self::export_string::<_, TextExport>(graph, when, config),
Query(..) => todo!(),
}
};