diff --git a/crates/tinymist-query/src/docs/convert.rs b/crates/tinymist-query/src/docs/convert.rs index ae23eebb..35d85725 100644 --- a/crates/tinymist-query/src/docs/convert.rs +++ b/crates/tinymist-query/src/docs/convert.rs @@ -3,9 +3,12 @@ use std::sync::Arc; use ecow::{eco_format, EcoString}; use tinymist_std::path::unix_slash; +use tinymist_world::system::print_diagnostics_to_string; use tinymist_world::vfs::WorkspaceResolver; -use tinymist_world::{EntryReader, EntryState, ShadowApi, TaskInputs}; -use typlite::TypliteFeat; +use tinymist_world::{ + DiagnosticFormat, EntryReader, EntryState, ShadowApi, SourceWorld, TaskInputs, +}; +use typlite::{Format, TypliteFeat}; use typst::diag::StrResult; use typst::foundations::Bytes; use typst::syntax::FileId; @@ -19,7 +22,7 @@ pub(crate) fn convert_docs( source_fid: Option, ) -> StrResult { let mut entry = ctx.world.entry_state(); - let (contextual_content, import_context) = if let Some(fid) = source_fid { + let import_context = source_fid.map(|fid| { let root = ctx .world .vfs() @@ -42,16 +45,15 @@ pub(crate) fn convert_docs( "#import {:?}: *", unix_slash(fid.vpath().as_rooted_path()) )); - let imports = imports.join("\n"); - let content_with_import: String = if !imports.is_empty() { - format!("{imports}\n\n{content}") - } else { - content.to_owned() - }; - - (content_with_import, Some(imports)) - } else { - (content.to_owned(), None) + imports.join("; ") + }); + let feat = TypliteFeat { + color_theme: Some(ctx.analysis.color_theme), + annotate_elem: true, + soft_error: true, + remove_html: ctx.analysis.remove_html, + import_context, + ..Default::default() }; let entry = entry.select_in_workspace(Path::new("__tinymist_docs__.typ")); @@ -61,21 +63,39 @@ pub(crate) fn convert_docs( inputs: None, }); - w.map_shadow_by_id(w.main(), Bytes::from_string(contextual_content))?; + // todo: bad performance: content.to_owned() + w.map_shadow_by_id(w.main(), Bytes::from_string(content.to_owned()))?; // todo: bad performance w.take_db(); + let w = feat + .prepare_world(&w, Format::Md) + .map_err(|e| eco_format!("failed to prepare world: {e}"))?; - let conv = typlite::Typlite::new(Arc::new(w)) - .with_feature(TypliteFeat { - color_theme: Some(ctx.analysis.color_theme), - annotate_elem: true, - soft_error: true, - remove_html: ctx.analysis.remove_html, - import_context, - ..Default::default() - }) - .convert() - .map_err(|err| eco_format!("failed to convert to markdown: {err}"))?; + let w = Arc::new(w); + let res = typlite::Typlite::new(w.clone()) + .with_feature(feat) + .convert(); + let conv = print_diag_or_error(w.as_ref(), res)?; Ok(conv.replace("```example", "```typ")) } + +fn print_diag_or_error( + world: &impl SourceWorld, + result: tinymist_std::Result, +) -> StrResult { + match result { + Ok(v) => Ok(v), + Err(err) => { + if let Some(diagnostics) = err.diagnostics() { + return Err(print_diagnostics_to_string( + world, + diagnostics.iter(), + DiagnosticFormat::Human, + )?); + } + + Err(eco_format!("failed to convert docs: {err}")) + } + } +} diff --git a/crates/tinymist-query/src/fixtures/hover/error_in_doc.typ b/crates/tinymist-query/src/fixtures/hover/error_in_doc.typ new file mode 100644 index 00000000..57fdd78a --- /dev/null +++ b/crates/tinymist-query/src/fixtures/hover/error_in_doc.typ @@ -0,0 +1,6 @@ +/// * +#let my-fun(mode: "typ", setting: it => it, note) = { + touying-fn-wrapper(utils.my-fun, mode: mode, setting: setting, note) +} + +#(/* ident after */ my-fun); diff --git a/crates/tinymist-query/src/fixtures/hover/error_in_module.typ b/crates/tinymist-query/src/fixtures/hover/error_in_module.typ new file mode 100644 index 00000000..45109dcb --- /dev/null +++ b/crates/tinymist-query/src/fixtures/hover/error_in_module.typ @@ -0,0 +1,9 @@ +/// Good doc +#let my-fun(mode: "typ", setting: it => it, note) = { + touying-fn-wrapper(utils.my-fun, mode: mode, setting: setting, note) +} + +#(/* ident after */ my-fun); + + +#my-f diff --git a/crates/tinymist-query/src/fixtures/hover/error_in_module_example.typ b/crates/tinymist-query/src/fixtures/hover/error_in_module_example.typ new file mode 100644 index 00000000..95abd5a8 --- /dev/null +++ b/crates/tinymist-query/src/fixtures/hover/error_in_module_example.typ @@ -0,0 +1,14 @@ +/// Good doc +/// +/// #example(``` +/// my-fun() +/// ```) +/// +#let my-fun(mode: "typ", setting: it => it, note) = { + touying-fn-wrapper(utils.my-fun, mode: mode, setting: setting, note) +} + +#(/* ident after */ my-fun); + + +#my-f diff --git a/crates/tinymist-query/src/fixtures/hover/annotate_docs_error.typ b/crates/tinymist-query/src/fixtures/hover/example.typ similarity index 100% rename from crates/tinymist-query/src/fixtures/hover/annotate_docs_error.typ rename to crates/tinymist-query/src/fixtures/hover/example.typ diff --git a/crates/tinymist-query/src/fixtures/hover/snaps/test@error_in_doc.typ.snap b/crates/tinymist-query/src/fixtures/hover/snaps/test@error_in_doc.typ.snap new file mode 100644 index 00000000..a4eca742 --- /dev/null +++ b/crates/tinymist-query/src/fixtures/hover/snaps/test@error_in_doc.typ.snap @@ -0,0 +1,58 @@ +--- +source: crates/tinymist-query/src/hover.rs +expression: content +input_file: crates/tinymist-query/src/fixtures/hover/error_in_doc.typ +--- +Range: 5:20:5:26 + +```typc +let my-fun( + note: any, + mode: str = "typ", + setting: (any) => any = Closure(..), +) = none; +``` + + +====== + + +``` +failed to parse docs: error: unclosed delimiter + ┌─ /dummy-root/__wrap_md_main.typ:2:0 + │ +2 │ * + │ ^ + + +``` + +```typ +* +``` + +# Positional Parameters + +## note + +```typc +type: +``` + + + +# Named Parameters + +## mode + +```typc +type: "typ" +``` + + + +## setting (named) + +```typc +type: (any) => any +``` diff --git a/crates/tinymist-query/src/fixtures/hover/snaps/test@error_in_module.typ.snap b/crates/tinymist-query/src/fixtures/hover/snaps/test@error_in_module.typ.snap new file mode 100644 index 00000000..a1f1043d --- /dev/null +++ b/crates/tinymist-query/src/fixtures/hover/snaps/test@error_in_module.typ.snap @@ -0,0 +1,46 @@ +--- +source: crates/tinymist-query/src/hover.rs +expression: content +input_file: crates/tinymist-query/src/fixtures/hover/error_in_module.typ +--- +Range: 5:20:5:26 + +```typc +let my-fun( + note: any, + mode: str = "typ", + setting: (any) => any = Closure(..), +) = none; +``` + + +====== + + +Good doc + +# Positional Parameters + +## note + +```typc +type: +``` + + + +# Named Parameters + +## mode + +```typc +type: "typ" +``` + + + +## setting (named) + +```typc +type: (any) => any +``` diff --git a/crates/tinymist-query/src/fixtures/hover/snaps/test@error_in_module_example.typ.snap b/crates/tinymist-query/src/fixtures/hover/snaps/test@error_in_module_example.typ.snap new file mode 100644 index 00000000..d62f73a8 --- /dev/null +++ b/crates/tinymist-query/src/fixtures/hover/snaps/test@error_in_module_example.typ.snap @@ -0,0 +1,64 @@ +--- +source: crates/tinymist-query/src/hover.rs +expression: content +input_file: crates/tinymist-query/src/fixtures/hover/error_in_module_example.typ +--- +Range: 10:20:10:26 + +```typc +let my-fun( + note: any, + mode: str = "typ", + setting: (any) => any = Closure(..), +) = none; +``` + + +====== + + +Good doc + +```typ +my-fun() +``` + +Error compiling idoc: error: unknown variable: my-f + ┌─ /dummy-root/s0.typ:14:1 + │ +14 │ #my-f + │ ^^^^ + │ + = hint: if you meant to use subtraction, try adding spaces around the minus sign: \`my - f\` + +help: error occurred while importing this module + ┌─ /dummy-root/\_\_main\_\_.typ:1:8 + │ +1 │ #import "/s0.typ": \* + │ ^^^^^^^^^ + +# Positional Parameters + +## note + +```typc +type: +``` + + + +# Named Parameters + +## mode + +```typc +type: "typ" +``` + + + +## setting (named) + +```typc +type: (any) => any +``` diff --git a/crates/tinymist-query/src/fixtures/hover/snaps/test@annotate_docs_error.typ.snap b/crates/tinymist-query/src/fixtures/hover/snaps/test@example.typ.snap similarity index 89% rename from crates/tinymist-query/src/fixtures/hover/snaps/test@annotate_docs_error.typ.snap rename to crates/tinymist-query/src/fixtures/hover/snaps/test@example.typ.snap index 72406466..9bb214bc 100644 --- a/crates/tinymist-query/src/fixtures/hover/snaps/test@annotate_docs_error.typ.snap +++ b/crates/tinymist-query/src/fixtures/hover/snaps/test@example.typ.snap @@ -1,7 +1,7 @@ --- source: crates/tinymist-query/src/hover.rs expression: content -input_file: crates/tinymist-query/src/fixtures/hover/annotate_docs_error.typ +input_file: crates/tinymist-query/src/fixtures/hover/example.typ --- Range: 12:20:12:32 diff --git a/crates/tinymist-query/src/fixtures/playground/base.typ b/crates/tinymist-query/src/fixtures/playground/base.typ index 47353754..57fdd78a 100644 --- a/crates/tinymist-query/src/fixtures/playground/base.typ +++ b/crates/tinymist-query/src/fixtures/playground/base.typ @@ -1,2 +1,6 @@ -#let tmpl2(stroke) = text(stroke: stroke) -#tmpl2(/* position */) \ No newline at end of file +/// * +#let my-fun(mode: "typ", setting: it => it, note) = { + touying-fn-wrapper(utils.my-fun, mode: mode, setting: setting, note) +} + +#(/* ident after */ my-fun); diff --git a/crates/tinymist-query/src/fixtures/playground/snaps/test.snap b/crates/tinymist-query/src/fixtures/playground/snaps/test.snap new file mode 100644 index 00000000..fd2b4e05 --- /dev/null +++ b/crates/tinymist-query/src/fixtures/playground/snaps/test.snap @@ -0,0 +1,58 @@ +--- +source: crates/tinymist-query/src/hover.rs +expression: content +input_file: crates/tinymist-query/src/fixtures/playground/base.typ +--- +Range: 5:20:5:26 + +```typc +let my-fun( + note: any, + mode: str = "typ", + setting: (any) => any = Closure(..), +) = none; +``` + + +====== + + +``` +failed to parse docs: error: unclosed delimiter + ┌─ /dummy-root/__wrap_md_main.typ:2:0 + │ +2 │ * + │ ^ + + +``` + +```typ +* +``` + +# Positional Parameters + +## note + +```typc +type: +``` + + + +# Named Parameters + +## mode + +```typc +type: "typ" +``` + + + +## setting (named) + +```typc +type: (any) => any +``` diff --git a/crates/tinymist-query/src/tests.rs b/crates/tinymist-query/src/tests.rs index 10fc5dca..646a7bdb 100644 --- a/crates/tinymist-query/src/tests.rs +++ b/crates/tinymist-query/src/tests.rs @@ -8,6 +8,7 @@ use std::{ path::{Path, PathBuf}, }; +use regex::{Regex, Replacer}; use serde_json::{ser::PrettyFormatter, Serializer, Value}; use tinymist_project::{LspCompileSnapshot, LspComputeGraph}; use tinymist_std::path::unix_slash; @@ -333,13 +334,14 @@ impl JsonRepr { } pub fn md_content(v: &str) -> Cow<'_, str> { - static REG: LazyLock = - LazyLock::new(|| regex::Regex::new(r#"data:image/svg\+xml;base64,([^"]+)"#).unwrap()); + static REG: LazyLock = + LazyLock::new(|| Regex::new(r#"data:image/svg\+xml;base64,([^"]+)"#).unwrap()); + static REG2: LazyLock = + LazyLock::new(|| Regex::new(r#"C:\\?\\dummy-root\\?\\"#).unwrap()); let v = REG.replace_all(v, |_captures: ®ex::Captures| { "data:image-hash/svg+xml;base64,redacted" }); - - v + REG2.replace_all_cow(v, "/dummy-root/") } pub fn range(v: impl serde::Serialize) -> String { @@ -360,8 +362,7 @@ impl fmt::Display for JsonRepr { let res = String::from_utf8(ser.into_inner().into_inner().unwrap()).unwrap(); // replace Span(number) to Span(..) - static REG: LazyLock = - LazyLock::new(|| regex::Regex::new(r#"Span\((\d+)\)"#).unwrap()); + static REG: LazyLock = LazyLock::new(|| Regex::new(r#"Span\((\d+)\)"#).unwrap()); let res = REG.replace_all(&res, "Span(..)"); f.write_str(&res) } @@ -470,3 +471,18 @@ impl fmt::Display for HashRepr { write!(f, "sha256:{}", hex::encode(hash)) } } + +/// Extension methods for `Regex` that operate on `Cow` instead of `&str`. +pub trait RegexCowExt { + /// [`Regex::replace_all`], but taking text as `Cow` instead of `&str`. + fn replace_all_cow<'t, R: Replacer>(&self, text: Cow<'t, str>, rep: R) -> Cow<'t, str>; +} + +impl RegexCowExt for Regex { + fn replace_all_cow<'t, R: Replacer>(&self, text: Cow<'t, str>, rep: R) -> Cow<'t, str> { + match self.replace_all(&text, rep) { + Cow::Owned(result) => Cow::Owned(result), + Cow::Borrowed(_) => text, + } + } +} diff --git a/crates/tinymist-world/src/system/diag.rs b/crates/tinymist-world/src/system/diag.rs index 748a0c5b..8eeb974c 100644 --- a/crates/tinymist-world/src/system/diag.rs +++ b/crates/tinymist-world/src/system/diag.rs @@ -1,17 +1,17 @@ -use std::io::IsTerminal; +use ecow::EcoString; +use std::io::IsTerminal; +use std::str::FromStr; + +use codespan_reporting::term::termcolor::{ColorChoice, NoColor, StandardStream, WriteColor}; use codespan_reporting::{ diagnostic::{Diagnostic, Label}, - term::{ - self, - termcolor::{ColorChoice, StandardStream}, - }, + term, }; use tinymist_std::Result; use tinymist_vfs::FileId; -use typst::diag::{eco_format, Severity, SourceDiagnostic}; +use typst::diag::{eco_format, Severity, SourceDiagnostic, StrResult}; use typst::syntax::Span; -use typst::WorldExt; use crate::{CodeSpanReportWorld, DiagnosticFormat, SourceWorld}; @@ -30,13 +30,41 @@ pub fn print_diagnostics<'d, 'files>( errors: impl Iterator, diagnostic_format: DiagnosticFormat, ) -> Result<(), codespan_reporting::files::Error> { - let world = CodeSpanReportWorld::new(world); - let mut w = match diagnostic_format { DiagnosticFormat::Human => color_stream(), DiagnosticFormat::Short => StandardStream::stderr(ColorChoice::Never), }; + print_diagnostics_to(world, errors, &mut w, diagnostic_format) +} + +/// Print diagnostic messages to the terminal. +pub fn print_diagnostics_to_string<'d, 'files>( + world: &'files dyn SourceWorld, + errors: impl Iterator, + diagnostic_format: DiagnosticFormat, +) -> StrResult { + let mut w = NoColor::new(vec![]); + + print_diagnostics_to(world, errors, &mut w, diagnostic_format) + .map_err(|e| eco_format!("failed to print diagnostics to string: {e}"))?; + let output = EcoString::from_str( + std::str::from_utf8(&w.into_inner()) + .map_err(|e| eco_format!("failed to convert diagnostics to string: {e}"))?, + ) + .unwrap_or_default(); + Ok(output) +} + +/// Print diagnostic messages to the terminal. +pub fn print_diagnostics_to<'d, 'files>( + world: &'files dyn SourceWorld, + errors: impl Iterator, + w: &mut impl WriteColor, + diagnostic_format: DiagnosticFormat, +) -> Result<(), codespan_reporting::files::Error> { + let world = CodeSpanReportWorld::new(world); + let mut config = term::Config { tab_width: 2, ..Default::default() @@ -60,7 +88,7 @@ pub fn print_diagnostics<'d, 'files>( ) .with_labels(label(world.world, diagnostic.span).into_iter().collect()); - term::emit(&mut w, &config, &world, &diag)?; + term::emit(w, &config, &world, &diag)?; // Stacktrace-like helper diagnostics. for point in &diagnostic.trace { @@ -69,7 +97,7 @@ pub fn print_diagnostics<'d, 'files>( .with_message(message) .with_labels(label(world.world, point.span).into_iter().collect()); - term::emit(&mut w, &config, &world, &help)?; + term::emit(w, &config, &world, &help)?; } } @@ -78,5 +106,5 @@ pub fn print_diagnostics<'d, 'files>( /// Create a label for a span. fn label(world: &dyn SourceWorld, span: Span) -> Option> { - Some(Label::primary(span.id()?, world.range(span)?)) + Some(Label::primary(span.id()?, world.source_range(span)?)) } diff --git a/crates/tinymist-world/src/world.rs b/crates/tinymist-world/src/world.rs index 06e869cc..6eb8bdcf 100644 --- a/crates/tinymist-world/src/world.rs +++ b/crates/tinymist-world/src/world.rs @@ -17,7 +17,7 @@ use typst::{ syntax::{Source, Span, VirtualPath}, text::{Font, FontBook}, utils::LazyHash, - Features, Library, World, + Features, Library, World, WorldExt, }; use crate::{ @@ -858,6 +858,10 @@ pub trait SourceWorld: World { self.source(id) .expect("file id does not point to any source file") } + + fn source_range(&self, span: Span) -> Option> { + self.range(span) + } } impl SourceWorld for CompilerWorld { diff --git a/crates/typlite/src/lib.rs b/crates/typlite/src/lib.rs index cc76bde9..fe964eb2 100644 --- a/crates/typlite/src/lib.rs +++ b/crates/typlite/src/lib.rs @@ -178,6 +178,93 @@ pub struct TypliteFeat { pub processor: Option, } +impl TypliteFeat { + pub fn prepare_world( + &self, + world: &LspWorld, + format: Format, + ) -> tinymist_std::Result { + let entry = world.entry_state(); + let main = entry.main(); + let current = main.context("no main file in workspace")?; + + if WorkspaceResolver::is_package_file(current) { + bail!("package file is not supported"); + } + + let wrap_main_id = current.join("__wrap_md_main.typ"); + + let (main_id, main_content) = match self.processor.as_ref() { + None => (wrap_main_id, None), + Some(processor) => { + let main_id = current.join("__md_main.typ"); + let content = format!( + r#"#import {processor:?}: article +#article(include "__wrap_md_main.typ")"# + ); + + (main_id, Some(Bytes::from_string(content))) + } + }; + + let mut dict = TypstDict::new(); + dict.insert("x-target".into(), Str("md".into())); + if format == Format::Text || self.remove_html { + dict.insert("x-remove-html".into(), Str("true".into())); + } + + let task_inputs = TaskInputs { + entry: Some(entry.select_in_workspace(main_id.vpath().as_rooted_path())), + inputs: Some(Arc::new(LazyHash::new(dict))), + }; + + let mut world = world.task(task_inputs).html_task().into_owned(); + + let markdown_id = FileId::new( + Some( + typst_syntax::package::PackageSpec::from_str("@local/_markdown:0.1.0") + .context_ut("failed to import markdown package")?, + ), + VirtualPath::new("lib.typ"), + ); + + world + .map_shadow_by_id( + markdown_id.join("typst.toml"), + Bytes::from_string(include_str!("markdown-typst.toml")), + ) + .context_ut("cannot map markdown-typst.toml")?; + world + .map_shadow_by_id( + markdown_id, + Bytes::from_string(include_str!("markdown.typ")), + ) + .context_ut("cannot map markdown.typ")?; + + world + .map_shadow_by_id( + wrap_main_id, + Bytes::from_string(format!( + r#"#import "@local/_markdown:0.1.0": md-doc, example; #show: md-doc +{}"#, + world + .source(current) + .context_ut("failed to get main file content")? + .text() + )), + ) + .context_ut("cannot map source for main file")?; + + if let Some(main_content) = main_content { + world + .map_shadow_by_id(main_id, main_content) + .context_ut("cannot map source for main file")?; + } + + Ok(world) + } +} + /// Task builder for converting a typst document to Markdown. pub struct Typlite { /// The universe to use for the conversion. @@ -231,91 +318,22 @@ impl Typlite { /// Convert the content to a markdown document. pub fn convert_doc(self, format: Format) -> tinymist_std::Result { - let entry = self.world.entry_state(); - let main = entry.main(); - let current = main.context("no main file in workspace")?; - let world_origin = self.world.clone(); - let world = self.world; - - if WorkspaceResolver::is_package_file(current) { - bail!("package file is not supported"); - } - - let wrap_main_id = current.join("__wrap_md_main.typ"); - - let (main_id, main_content) = match self.feat.processor.as_ref() { - None => (wrap_main_id, None), - Some(processor) => { - let main_id = current.join("__md_main.typ"); - let content = format!( - r#"#import {processor:?}: article -#article(include "__wrap_md_main.typ")"# - ); - - (main_id, Some(Bytes::from_string(content))) - } - }; - - let mut dict = TypstDict::new(); - dict.insert("x-target".into(), Str("md".into())); - if format == Format::Text || self.feat.remove_html { - dict.insert("x-remove-html".into(), Str("true".into())); - } - - let task_inputs = TaskInputs { - entry: Some(entry.select_in_workspace(main_id.vpath().as_rooted_path())), - inputs: Some(Arc::new(LazyHash::new(dict))), - }; - - let mut world = world.task(task_inputs).html_task().into_owned(); - - let markdown_id = FileId::new( - Some( - typst_syntax::package::PackageSpec::from_str("@local/markdown:0.1.0") - .context_ut("failed to import markdown package")?, - ), - VirtualPath::new("lib.typ"), - ); - - world - .map_shadow_by_id( - markdown_id.join("typst.toml"), - Bytes::from_string(include_str!("markdown-typst.toml")), - ) - .context_ut("cannot map markdown-typst.toml")?; - world - .map_shadow_by_id( - markdown_id, - Bytes::from_string(include_str!("markdown.typ")), - ) - .context_ut("cannot map markdown.typ")?; - - world - .map_shadow_by_id( - wrap_main_id, - Bytes::from_string(format!( - r#"#import "@local/markdown:0.1.0": md-doc, example -#show: md-doc -{}"#, - world - .source(current) - .context_ut("failed to get main file content")? - .text() - )), - ) - .context_ut("cannot map source for main file")?; - - if let Some(main_content) = main_content { - world - .map_shadow_by_id(main_id, main_content) - .context_ut("cannot map source for main file")?; - } + let world = Arc::new(self.feat.prepare_world(&self.world, format)?); + let feat = self.feat.clone(); + Self::convert_doc_prepared(feat, format, world) + } + /// Convert the content to a markdown document. + pub fn convert_doc_prepared( + feat: TypliteFeat, + format: Format, + world: Arc, + ) -> tinymist_std::Result { // todo: ignoring warnings let base = typst::compile(&world).output?; - let mut feat = self.feat; + let mut feat = feat; feat.target = format; - Ok(MarkdownDocument::new(base, world_origin, feat)) + Ok(MarkdownDocument::new(base, world.clone(), feat)) } } diff --git a/crates/typlite/src/markdown-typst.toml b/crates/typlite/src/markdown-typst.toml index d82c0bb6..4befea04 100644 --- a/crates/typlite/src/markdown-typst.toml +++ b/crates/typlite/src/markdown-typst.toml @@ -1,5 +1,5 @@ [package] -name = "markdown" +name = "_markdown" version = "0.1.0" entrypoint = "lib.typ" description = "Markdown support for typst." diff --git a/crates/typlite/src/parser/media.rs b/crates/typlite/src/parser/media.rs index 212aa619..ce4fd94d 100644 --- a/crates/typlite/src/parser/media.rs +++ b/crates/typlite/src/parser/media.rs @@ -7,6 +7,7 @@ use std::sync::{Arc, LazyLock}; use base64::Engine; use cmark_writer::ast::{HtmlAttribute, HtmlElement as CmarkHtmlElement, Node}; use ecow::{eco_format, EcoString}; +use tinymist_project::system::print_diagnostics_to_string; use tinymist_project::{base::ShadowApi, EntryReader, TaskInputs, MEMORY_MAIN_ENTRY}; use typst::{ foundations::{Bytes, Dict, IntoValue}, @@ -277,12 +278,22 @@ impl HtmlToAstParser { ) .unwrap(); + //todo: ignoring warnings let doc = typst::compile(&world); let doc = match doc.output { Ok(doc) => doc, Err(e) => { + let diag = doc.warnings.iter().chain(e.iter()); + + let e = print_diagnostics_to_string( + &world, + diag, + tinymist_project::DiagnosticFormat::Human, + ) + .unwrap_or_else(|e| e); + if self.feat.soft_error { - return Node::Text(eco_format!("Error compiling idoc: {e:?}")); + return Node::Text(eco_format!("Error compiling idoc: {e}")); } else { // Construct error node return Node::HtmlElement(CmarkHtmlElement { @@ -291,7 +302,7 @@ impl HtmlToAstParser { name: EcoString::inline("class"), value: EcoString::inline("error"), }], - children: vec![Node::Text(eco_format!("Error compiling idoc: {e:?}"))], + children: vec![Node::Text(eco_format!("Error compiling idoc: {e}"))], self_closing: false, }); } diff --git a/crates/typlite/src/writer/docx/writer.rs b/crates/typlite/src/writer/docx/writer.rs index 709215a8..59a0491b 100644 --- a/crates/typlite/src/writer/docx/writer.rs +++ b/crates/typlite/src/writer/docx/writer.rs @@ -256,7 +256,7 @@ impl DocxWriter { } // Other inline element types _ => { - println!("other inline element: {:?}", node); + eprintln!("other inline element: {:?}", node); } }