Skip to content

Commit e4ed9de

Browse files
refactor: tidy up main and let converter know the target (#1729)
1 parent d85bd74 commit e4ed9de

File tree

4 files changed

+48
-111
lines changed

4 files changed

+48
-111
lines changed

crates/typlite/src/common.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,9 @@ pub enum ListState {
1515
}
1616

1717
/// Valid formats for the conversion.
18-
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
18+
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
1919
pub enum Format {
20+
#[default]
2021
Md,
2122
LaTeX,
2223
#[cfg(feature = "docx")]

crates/typlite/src/lib.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,8 @@ pub struct TypliteFeat {
127127
pub soft_error: bool,
128128
/// Remove HTML tags from the output.
129129
pub remove_html: bool,
130+
/// The target to convert
131+
pub target: Format,
130132
}
131133

132134
/// Task builder for converting a typst document to Markdown.
@@ -166,8 +168,8 @@ impl Typlite {
166168
/// Convert the content to a markdown string.
167169
pub fn convert(self) -> Result<ecow::EcoString> {
168170
match self.format {
169-
Format::Md => self.convert_doc()?.to_md_string(),
170-
Format::LaTeX => self.convert_doc()?.to_tex_string(true),
171+
Format::Md => self.convert_doc(Format::Md)?.to_md_string(),
172+
Format::LaTeX => self.convert_doc(Format::LaTeX)?.to_tex_string(true),
171173
#[cfg(feature = "docx")]
172174
Format::Docx => Err("docx format is not supported".into()),
173175
}
@@ -179,11 +181,11 @@ impl Typlite {
179181
if self.format != Format::Docx {
180182
return Err("format is not DOCX".into());
181183
}
182-
self.convert_doc()?.to_docx()
184+
self.convert_doc(Format::Docx)?.to_docx()
183185
}
184186

185187
/// Convert the content to a markdown document.
186-
pub fn convert_doc(self) -> Result<MarkdownDocument> {
188+
pub fn convert_doc(self, format: Format) -> Result<MarkdownDocument> {
187189
let entry = self.world.entry_state();
188190
let main = entry.main();
189191
let current = main.ok_or("no main file in workspace")?;
@@ -236,7 +238,9 @@ impl Typlite {
236238
let base = typst::compile(&world)
237239
.output
238240
.map_err(|err| format!("convert source for main file: {err:?}"))?;
239-
Ok(MarkdownDocument::new(base, self.feat))
241+
let mut feat = self.feat;
242+
feat.target = format;
243+
Ok(MarkdownDocument::new(base, feat))
240244
}
241245
}
242246

crates/typlite/src/main.rs

Lines changed: 29 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,17 @@ use clap::Parser;
1010
use tinymist_project::WorldProvider;
1111
use typlite::{common::Format, TypliteFeat};
1212
use typlite::{CompileOnceArgs, Typlite};
13+
use typst::foundations::Bytes;
1314

1415
/// Common arguments of compile, watch, and query.
1516
#[derive(Debug, Clone, Parser, Default)]
1617
pub struct CompileArgs {
1718
#[clap(flatten)]
1819
pub compile: CompileOnceArgs,
1920

20-
/// Path to output file(s)
21-
#[clap(value_name = "OUTPUT", action = clap::ArgAction::Append)]
22-
pub outputs: Vec<String>,
21+
/// Path to output file
22+
#[clap(value_name = "OUTPUT", default_value = None)]
23+
pub output: Option<String>,
2324

2425
/// Configures the path of assets directory
2526
#[clap(long, default_value = None, value_name = "ASSETS_PATH")]
@@ -36,13 +37,17 @@ fn main() -> typlite::Result<()> {
3637
.as_ref()
3738
.ok_or("Missing required argument: INPUT")?;
3839

39-
let outputs = if args.outputs.is_empty() {
40-
vec![Path::new(input)
41-
.with_extension("md")
42-
.to_string_lossy()
43-
.to_string()]
44-
} else {
45-
args.outputs.clone()
40+
let is_stdout = args.output.as_deref() == Some("-");
41+
let output_path = args
42+
.output
43+
.map(PathBuf::from)
44+
.unwrap_or_else(|| Path::new(input).with_extension("md"));
45+
46+
let output_format = match output_path.extension() {
47+
Some(ext) if ext == std::ffi::OsStr::new("tex") => Format::LaTeX,
48+
#[cfg(feature = "docx")]
49+
Some(ext) if ext == std::ffi::OsStr::new("docx") => Format::Docx,
50+
_ => Format::Md,
4651
};
4752

4853
let assets_path = match args.assets_path {
@@ -65,102 +70,22 @@ fn main() -> typlite::Result<()> {
6570
assets_path: assets_path.clone(),
6671
..Default::default()
6772
});
68-
let doc = match converter.convert_doc() {
69-
Ok(doc) => doc,
70-
Err(err) => return Err(format!("failed to convert document: {err}").into()),
71-
};
72-
73-
for output_path in &outputs {
74-
let is_stdout = output_path == "-";
75-
let output = if is_stdout {
76-
None
77-
} else {
78-
Some(PathBuf::from(output_path))
79-
};
73+
let doc = converter.convert_doc(output_format)?;
8074

81-
let format = match &output {
82-
Some(output) if output.extension() == Some(std::ffi::OsStr::new("tex")) => {
83-
Format::LaTeX
84-
}
85-
#[cfg(feature = "docx")]
86-
Some(output) if output.extension() == Some(std::ffi::OsStr::new("docx")) => {
87-
Format::Docx
88-
}
89-
_ => Format::Md,
90-
};
91-
92-
match format {
93-
#[cfg(feature = "docx")]
94-
Format::Docx => {
95-
let docx_data = match doc.to_docx() {
96-
Ok(data) => data,
97-
Err(err) => {
98-
eprintln!("Error generating DOCX for {}: {}", output_path, err);
99-
continue;
100-
}
101-
};
75+
let result = match output_format {
76+
Format::Md => Bytes::from_string(doc.to_md_string()?),
77+
Format::LaTeX => Bytes::from_string(doc.to_tex_string(true)?),
78+
#[cfg(feature = "docx")]
79+
Format::Docx => Bytes::new(doc.to_docx()?),
80+
};
10281

103-
match output {
104-
None => {
105-
eprintln!("output file is required for DOCX format");
106-
continue;
107-
}
108-
Some(output) => {
109-
if let Err(err) = std::fs::write(&output, docx_data) {
110-
eprintln!("failed to write DOCX file {}: {}", output.display(), err);
111-
continue;
112-
}
113-
println!("Generated DOCX file: {}", output.display());
114-
}
115-
}
116-
}
117-
Format::LaTeX => {
118-
let result = doc.to_tex_string(true);
119-
match (result, output) {
120-
(Ok(content), None) => {
121-
std::io::stdout()
122-
.write_all(content.as_str().as_bytes())
123-
.unwrap();
124-
}
125-
(Ok(content), Some(output)) => {
126-
if let Err(err) = std::fs::write(&output, content.as_str()) {
127-
eprintln!("failed to write LaTeX file {}: {}", output.display(), err);
128-
continue;
129-
}
130-
println!("Generated LaTeX file: {}", output.display());
131-
}
132-
(Err(err), _) => {
133-
eprintln!("Error converting to LaTeX for {}: {}", output_path, err);
134-
continue;
135-
}
136-
}
137-
}
138-
Format::Md => {
139-
let result = doc.to_md_string();
140-
match (result, output) {
141-
(Ok(content), None) => {
142-
std::io::stdout()
143-
.write_all(content.as_str().as_bytes())
144-
.unwrap();
145-
}
146-
(Ok(content), Some(output)) => {
147-
if let Err(err) = std::fs::write(&output, content.as_str()) {
148-
eprintln!(
149-
"failed to write Markdown file {}: {}",
150-
output.display(),
151-
err
152-
);
153-
continue;
154-
}
155-
println!("Generated Markdown file: {}", output.display());
156-
}
157-
(Err(err), _) => {
158-
eprintln!("Error converting to Markdown for {}: {}", output_path, err);
159-
continue;
160-
}
161-
}
162-
}
163-
}
82+
if is_stdout {
83+
std::io::stdout().write_all(result.as_slice()).unwrap();
84+
} else if let Err(err) = std::fs::write(&output_path, result.as_slice()) {
85+
Err(format!(
86+
"failed to write file {}: {err}",
87+
output_path.display()
88+
))?;
16489
}
16590

16691
Ok(())

crates/typlite/src/tests.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,14 +81,21 @@ impl ConvKind {
8181
ConvKind::LaTeX => false,
8282
}
8383
}
84+
85+
fn kind(&self) -> Format {
86+
match self {
87+
ConvKind::Md { .. } => Format::Md,
88+
ConvKind::LaTeX => Format::LaTeX,
89+
}
90+
}
8491
}
8592

8693
fn conv(world: LspWorld, kind: ConvKind) -> String {
8794
let converter = Typlite::new(Arc::new(world)).with_feature(TypliteFeat {
8895
annotate_elem: kind.for_docs(),
8996
..Default::default()
9097
});
91-
let doc = match converter.convert_doc() {
98+
let doc = match converter.convert_doc(kind.kind()) {
9299
Ok(doc) => doc,
93100
Err(err) => return format!("failed to convert to markdown: {err}"),
94101
};

0 commit comments

Comments
 (0)