mirror of
https://github.com/Myriad-Dreamin/tinymist.git
synced 2025-11-26 22:04:56 +00:00
refactor: tidy up main and let converter know the target (#1729)
This commit is contained in:
parent
d85bd7428a
commit
e4ed9defb1
4 changed files with 48 additions and 111 deletions
|
|
@ -15,8 +15,9 @@ pub enum ListState {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Valid formats for the conversion.
|
/// Valid formats for the conversion.
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub enum Format {
|
pub enum Format {
|
||||||
|
#[default]
|
||||||
Md,
|
Md,
|
||||||
LaTeX,
|
LaTeX,
|
||||||
#[cfg(feature = "docx")]
|
#[cfg(feature = "docx")]
|
||||||
|
|
|
||||||
|
|
@ -127,6 +127,8 @@ pub struct TypliteFeat {
|
||||||
pub soft_error: bool,
|
pub soft_error: bool,
|
||||||
/// Remove HTML tags from the output.
|
/// Remove HTML tags from the output.
|
||||||
pub remove_html: bool,
|
pub remove_html: bool,
|
||||||
|
/// The target to convert
|
||||||
|
pub target: Format,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Task builder for converting a typst document to Markdown.
|
/// Task builder for converting a typst document to Markdown.
|
||||||
|
|
@ -166,8 +168,8 @@ impl Typlite {
|
||||||
/// Convert the content to a markdown string.
|
/// Convert the content to a markdown string.
|
||||||
pub fn convert(self) -> Result<ecow::EcoString> {
|
pub fn convert(self) -> Result<ecow::EcoString> {
|
||||||
match self.format {
|
match self.format {
|
||||||
Format::Md => self.convert_doc()?.to_md_string(),
|
Format::Md => self.convert_doc(Format::Md)?.to_md_string(),
|
||||||
Format::LaTeX => self.convert_doc()?.to_tex_string(true),
|
Format::LaTeX => self.convert_doc(Format::LaTeX)?.to_tex_string(true),
|
||||||
#[cfg(feature = "docx")]
|
#[cfg(feature = "docx")]
|
||||||
Format::Docx => Err("docx format is not supported".into()),
|
Format::Docx => Err("docx format is not supported".into()),
|
||||||
}
|
}
|
||||||
|
|
@ -179,11 +181,11 @@ impl Typlite {
|
||||||
if self.format != Format::Docx {
|
if self.format != Format::Docx {
|
||||||
return Err("format is not DOCX".into());
|
return Err("format is not DOCX".into());
|
||||||
}
|
}
|
||||||
self.convert_doc()?.to_docx()
|
self.convert_doc(Format::Docx)?.to_docx()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert the content to a markdown document.
|
/// Convert the content to a markdown document.
|
||||||
pub fn convert_doc(self) -> Result<MarkdownDocument> {
|
pub fn convert_doc(self, format: Format) -> Result<MarkdownDocument> {
|
||||||
let entry = self.world.entry_state();
|
let entry = self.world.entry_state();
|
||||||
let main = entry.main();
|
let main = entry.main();
|
||||||
let current = main.ok_or("no main file in workspace")?;
|
let current = main.ok_or("no main file in workspace")?;
|
||||||
|
|
@ -236,7 +238,9 @@ impl Typlite {
|
||||||
let base = typst::compile(&world)
|
let base = typst::compile(&world)
|
||||||
.output
|
.output
|
||||||
.map_err(|err| format!("convert source for main file: {err:?}"))?;
|
.map_err(|err| format!("convert source for main file: {err:?}"))?;
|
||||||
Ok(MarkdownDocument::new(base, self.feat))
|
let mut feat = self.feat;
|
||||||
|
feat.target = format;
|
||||||
|
Ok(MarkdownDocument::new(base, feat))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ use clap::Parser;
|
||||||
use tinymist_project::WorldProvider;
|
use tinymist_project::WorldProvider;
|
||||||
use typlite::{common::Format, TypliteFeat};
|
use typlite::{common::Format, TypliteFeat};
|
||||||
use typlite::{CompileOnceArgs, Typlite};
|
use typlite::{CompileOnceArgs, Typlite};
|
||||||
|
use typst::foundations::Bytes;
|
||||||
|
|
||||||
/// Common arguments of compile, watch, and query.
|
/// Common arguments of compile, watch, and query.
|
||||||
#[derive(Debug, Clone, Parser, Default)]
|
#[derive(Debug, Clone, Parser, Default)]
|
||||||
|
|
@ -17,9 +18,9 @@ pub struct CompileArgs {
|
||||||
#[clap(flatten)]
|
#[clap(flatten)]
|
||||||
pub compile: CompileOnceArgs,
|
pub compile: CompileOnceArgs,
|
||||||
|
|
||||||
/// Path to output file(s)
|
/// Path to output file
|
||||||
#[clap(value_name = "OUTPUT", action = clap::ArgAction::Append)]
|
#[clap(value_name = "OUTPUT", default_value = None)]
|
||||||
pub outputs: Vec<String>,
|
pub output: Option<String>,
|
||||||
|
|
||||||
/// Configures the path of assets directory
|
/// Configures the path of assets directory
|
||||||
#[clap(long, default_value = None, value_name = "ASSETS_PATH")]
|
#[clap(long, default_value = None, value_name = "ASSETS_PATH")]
|
||||||
|
|
@ -36,13 +37,17 @@ fn main() -> typlite::Result<()> {
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.ok_or("Missing required argument: INPUT")?;
|
.ok_or("Missing required argument: INPUT")?;
|
||||||
|
|
||||||
let outputs = if args.outputs.is_empty() {
|
let is_stdout = args.output.as_deref() == Some("-");
|
||||||
vec![Path::new(input)
|
let output_path = args
|
||||||
.with_extension("md")
|
.output
|
||||||
.to_string_lossy()
|
.map(PathBuf::from)
|
||||||
.to_string()]
|
.unwrap_or_else(|| Path::new(input).with_extension("md"));
|
||||||
} else {
|
|
||||||
args.outputs.clone()
|
let output_format = match output_path.extension() {
|
||||||
|
Some(ext) if ext == std::ffi::OsStr::new("tex") => Format::LaTeX,
|
||||||
|
#[cfg(feature = "docx")]
|
||||||
|
Some(ext) if ext == std::ffi::OsStr::new("docx") => Format::Docx,
|
||||||
|
_ => Format::Md,
|
||||||
};
|
};
|
||||||
|
|
||||||
let assets_path = match args.assets_path {
|
let assets_path = match args.assets_path {
|
||||||
|
|
@ -65,102 +70,22 @@ fn main() -> typlite::Result<()> {
|
||||||
assets_path: assets_path.clone(),
|
assets_path: assets_path.clone(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
});
|
||||||
let doc = match converter.convert_doc() {
|
let doc = converter.convert_doc(output_format)?;
|
||||||
Ok(doc) => doc,
|
|
||||||
Err(err) => return Err(format!("failed to convert document: {err}").into()),
|
|
||||||
};
|
|
||||||
|
|
||||||
for output_path in &outputs {
|
let result = match output_format {
|
||||||
let is_stdout = output_path == "-";
|
Format::Md => Bytes::from_string(doc.to_md_string()?),
|
||||||
let output = if is_stdout {
|
Format::LaTeX => Bytes::from_string(doc.to_tex_string(true)?),
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(PathBuf::from(output_path))
|
|
||||||
};
|
|
||||||
|
|
||||||
let format = match &output {
|
|
||||||
Some(output) if output.extension() == Some(std::ffi::OsStr::new("tex")) => {
|
|
||||||
Format::LaTeX
|
|
||||||
}
|
|
||||||
#[cfg(feature = "docx")]
|
#[cfg(feature = "docx")]
|
||||||
Some(output) if output.extension() == Some(std::ffi::OsStr::new("docx")) => {
|
Format::Docx => Bytes::new(doc.to_docx()?),
|
||||||
Format::Docx
|
|
||||||
}
|
|
||||||
_ => Format::Md,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
match format {
|
if is_stdout {
|
||||||
#[cfg(feature = "docx")]
|
std::io::stdout().write_all(result.as_slice()).unwrap();
|
||||||
Format::Docx => {
|
} else if let Err(err) = std::fs::write(&output_path, result.as_slice()) {
|
||||||
let docx_data = match doc.to_docx() {
|
Err(format!(
|
||||||
Ok(data) => data,
|
"failed to write file {}: {err}",
|
||||||
Err(err) => {
|
output_path.display()
|
||||||
eprintln!("Error generating DOCX for {}: {}", output_path, err);
|
))?;
|
||||||
continue;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
match output {
|
|
||||||
None => {
|
|
||||||
eprintln!("output file is required for DOCX format");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
Some(output) => {
|
|
||||||
if let Err(err) = std::fs::write(&output, docx_data) {
|
|
||||||
eprintln!("failed to write DOCX file {}: {}", output.display(), err);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
println!("Generated DOCX file: {}", output.display());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Format::LaTeX => {
|
|
||||||
let result = doc.to_tex_string(true);
|
|
||||||
match (result, output) {
|
|
||||||
(Ok(content), None) => {
|
|
||||||
std::io::stdout()
|
|
||||||
.write_all(content.as_str().as_bytes())
|
|
||||||
.unwrap();
|
|
||||||
}
|
|
||||||
(Ok(content), Some(output)) => {
|
|
||||||
if let Err(err) = std::fs::write(&output, content.as_str()) {
|
|
||||||
eprintln!("failed to write LaTeX file {}: {}", output.display(), err);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
println!("Generated LaTeX file: {}", output.display());
|
|
||||||
}
|
|
||||||
(Err(err), _) => {
|
|
||||||
eprintln!("Error converting to LaTeX for {}: {}", output_path, err);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Format::Md => {
|
|
||||||
let result = doc.to_md_string();
|
|
||||||
match (result, output) {
|
|
||||||
(Ok(content), None) => {
|
|
||||||
std::io::stdout()
|
|
||||||
.write_all(content.as_str().as_bytes())
|
|
||||||
.unwrap();
|
|
||||||
}
|
|
||||||
(Ok(content), Some(output)) => {
|
|
||||||
if let Err(err) = std::fs::write(&output, content.as_str()) {
|
|
||||||
eprintln!(
|
|
||||||
"failed to write Markdown file {}: {}",
|
|
||||||
output.display(),
|
|
||||||
err
|
|
||||||
);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
println!("Generated Markdown file: {}", output.display());
|
|
||||||
}
|
|
||||||
(Err(err), _) => {
|
|
||||||
eprintln!("Error converting to Markdown for {}: {}", output_path, err);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
||||||
|
|
@ -81,6 +81,13 @@ impl ConvKind {
|
||||||
ConvKind::LaTeX => false,
|
ConvKind::LaTeX => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn kind(&self) -> Format {
|
||||||
|
match self {
|
||||||
|
ConvKind::Md { .. } => Format::Md,
|
||||||
|
ConvKind::LaTeX => Format::LaTeX,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn conv(world: LspWorld, kind: ConvKind) -> String {
|
fn conv(world: LspWorld, kind: ConvKind) -> String {
|
||||||
|
|
@ -88,7 +95,7 @@ fn conv(world: LspWorld, kind: ConvKind) -> String {
|
||||||
annotate_elem: kind.for_docs(),
|
annotate_elem: kind.for_docs(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
});
|
||||||
let doc = match converter.convert_doc() {
|
let doc = match converter.convert_doc(kind.kind()) {
|
||||||
Ok(doc) => doc,
|
Ok(doc) => doc,
|
||||||
Err(err) => return format!("failed to convert to markdown: {err}"),
|
Err(err) => return format!("failed to convert to markdown: {err}"),
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue