From bc15eb55cee9f9b048aafd5f22472894961a1f51 Mon Sep 17 00:00:00 2001 From: Myriad-Dreamin <35292584+Myriad-Dreamin@users.noreply.github.com> Date: Thu, 19 Jun 2025 09:57:11 +0800 Subject: [PATCH] feat: add processor flag and finish sample to convert into tex paper (#1824) * feat: add processor flag and finish sample to convert into tex paper * test: update snapshot remove tex {document} env wrapping --- _typos.toml | 5 +- crates/typlite/src/common.rs | 15 + .../snaps/convert_tex@base.typ.snap | 5 - .../snaps/convert_tex@enum.typ.snap | 5 - .../snaps/convert_tex@enum2.typ.snap | 5 - .../snaps/convert_tex@figure_caption.typ.snap | 5 - .../snaps/convert_tex@figure_image.typ.snap | 5 - .../convert_tex@figure_image_alt.typ.snap | 5 - .../snaps/convert_tex@highlight.typ.snap | 6 - .../snaps/convert_tex@ieee.typ.snap | 6 - .../snaps/convert_tex@image.typ.snap | 7 - .../snaps/convert_tex@image_alt.typ.snap | 7 - .../snaps/convert_tex@linebreak.typ.snap | 6 - .../snaps/convert_tex@link.typ.snap | 5 - .../snaps/convert_tex@link2.typ.snap | 5 - .../snaps/convert_tex@link3.typ.snap | 5 - .../snaps/convert_tex@list.typ.snap | 5 - .../snaps/convert_tex@math_block.typ.snap | 5 - .../snaps/convert_tex@math_block2.typ.snap | 5 - .../snaps/convert_tex@math_inline.typ.snap | 6 - .../snaps/convert_tex@outline.typ.snap | 5 - .../snaps/convert_tex@raw_inline.typ.snap | 5 - .../snaps/convert_tex@table.typ.snap | 4 - crates/typlite/src/lib.rs | 57 +- crates/typlite/src/main.rs | 77 +-- crates/typlite/src/parser/core.rs | 17 +- crates/typlite/src/tags.rs | 1 + crates/typlite/src/tests.rs | 2 +- crates/typlite/src/writer/docx/writer.rs | 8 +- crates/typlite/src/writer/latex.rs | 37 +- .../ieee-paper/.vscode/tasks.json | 6 +- .../ieee-paper/ieee-template.typ | 12 +- .../e2e-workspaces/ieee-paper/ieee-tex.typ | 553 ++++++++++++++++++ 33 files changed, 705 insertions(+), 197 deletions(-) create mode 100644 editors/vscode/e2e-workspaces/ieee-paper/ieee-tex.typ diff --git a/_typos.toml b/_typos.toml index 5a10fe31..00a71a34 100644 --- a/_typos.toml +++ b/_typos.toml @@ -1 +1,4 @@ -files.extend-exclude = ["locales/**/*"] +files.extend-exclude = [ + "locales/**/*", + "editors/vscode/e2e-workspaces/ieee-paper/ieee-tex.typ", +] diff --git a/crates/typlite/src/common.rs b/crates/typlite/src/common.rs index a5fc73a9..cc5ade7d 100644 --- a/crates/typlite/src/common.rs +++ b/crates/typlite/src/common.rs @@ -213,6 +213,21 @@ impl InlineNode { } } +/// Verbatim node for raw text output +#[derive(Debug, PartialEq, Clone)] +#[custom_node(block = true, html_impl = false)] +pub struct VerbatimNode { + /// The content to directly output + pub content: EcoString, +} + +impl VerbatimNode { + fn write_custom(&self, writer: &mut CommonMarkWriter) -> WriteResult<()> { + writer.write_str(&self.content)?; + Ok(()) + } +} + /// Alert node for alert messages #[derive(Debug, PartialEq, Clone)] #[custom_node(block = true, html_impl = false)] diff --git a/crates/typlite/src/fixtures/integration/snaps/convert_tex@base.typ.snap b/crates/typlite/src/fixtures/integration/snaps/convert_tex@base.typ.snap index 89aab68e..218e28dd 100644 --- a/crates/typlite/src/fixtures/integration/snaps/convert_tex@base.typ.snap +++ b/crates/typlite/src/fixtures/integration/snaps/convert_tex@base.typ.snap @@ -13,11 +13,6 @@ input_file: crates/typlite/src/fixtures/integration/base.typ ===== -\begin{document} - \section{Hello, World!} This is a typst document. - - -\end{document} diff --git a/crates/typlite/src/fixtures/integration/snaps/convert_tex@enum.typ.snap b/crates/typlite/src/fixtures/integration/snaps/convert_tex@enum.typ.snap index 4ecee0dc..bc1cfd4a 100644 --- a/crates/typlite/src/fixtures/integration/snaps/convert_tex@enum.typ.snap +++ b/crates/typlite/src/fixtures/integration/snaps/convert_tex@enum.typ.snap @@ -13,12 +13,7 @@ input_file: crates/typlite/src/fixtures/integration/enum.typ ===== -\begin{document} - \begin{enumerate} \item A \item B \end{enumerate} - - -\end{document} diff --git a/crates/typlite/src/fixtures/integration/snaps/convert_tex@enum2.typ.snap b/crates/typlite/src/fixtures/integration/snaps/convert_tex@enum2.typ.snap index 2d66eebc..951220d5 100644 --- a/crates/typlite/src/fixtures/integration/snaps/convert_tex@enum2.typ.snap +++ b/crates/typlite/src/fixtures/integration/snaps/convert_tex@enum2.typ.snap @@ -13,12 +13,7 @@ input_file: crates/typlite/src/fixtures/integration/enum2.typ ===== -\begin{document} - \begin{enumerate} \item A \item B \end{enumerate} - - -\end{document} diff --git a/crates/typlite/src/fixtures/integration/snaps/convert_tex@figure_caption.typ.snap b/crates/typlite/src/fixtures/integration/snaps/convert_tex@figure_caption.typ.snap index e0f6d8ec..c500d8ef 100644 --- a/crates/typlite/src/fixtures/integration/snaps/convert_tex@figure_caption.typ.snap +++ b/crates/typlite/src/fixtures/integration/snaps/convert_tex@figure_caption.typ.snap @@ -13,8 +13,6 @@ input_file: crates/typlite/src/fixtures/integration/figure_caption.typ ===== -\begin{document} - \begin{center} \begin{figure}[htbp] \centering @@ -23,6 +21,3 @@ input_file: crates/typlite/src/fixtures/integration/figure_caption.typ \end{figure} \end{center} - - -\end{document} diff --git a/crates/typlite/src/fixtures/integration/snaps/convert_tex@figure_image.typ.snap b/crates/typlite/src/fixtures/integration/snaps/convert_tex@figure_image.typ.snap index 0b08ddee..729d5133 100644 --- a/crates/typlite/src/fixtures/integration/snaps/convert_tex@figure_image.typ.snap +++ b/crates/typlite/src/fixtures/integration/snaps/convert_tex@figure_image.typ.snap @@ -13,8 +13,6 @@ input_file: crates/typlite/src/fixtures/integration/figure_image.typ ===== -\begin{document} - \begin{center} \begin{figure}[htbp] \centering @@ -22,6 +20,3 @@ input_file: crates/typlite/src/fixtures/integration/figure_image.typ \end{figure} \end{center} - - -\end{document} diff --git a/crates/typlite/src/fixtures/integration/snaps/convert_tex@figure_image_alt.typ.snap b/crates/typlite/src/fixtures/integration/snaps/convert_tex@figure_image_alt.typ.snap index 7563630f..d557fd56 100644 --- a/crates/typlite/src/fixtures/integration/snaps/convert_tex@figure_image_alt.typ.snap +++ b/crates/typlite/src/fixtures/integration/snaps/convert_tex@figure_image_alt.typ.snap @@ -13,8 +13,6 @@ input_file: crates/typlite/src/fixtures/integration/figure_image_alt.typ ===== -\begin{document} - \begin{center} \begin{figure}[htbp] \centering @@ -22,6 +20,3 @@ input_file: crates/typlite/src/fixtures/integration/figure_image_alt.typ \end{figure} \end{center} - - -\end{document} diff --git a/crates/typlite/src/fixtures/integration/snaps/convert_tex@highlight.typ.snap b/crates/typlite/src/fixtures/integration/snaps/convert_tex@highlight.typ.snap index b3d88b49..52b905be 100644 --- a/crates/typlite/src/fixtures/integration/snaps/convert_tex@highlight.typ.snap +++ b/crates/typlite/src/fixtures/integration/snaps/convert_tex@highlight.typ.snap @@ -2,7 +2,6 @@ source: crates/typlite/src/tests.rs expression: "conv(world, ConvKind::LaTeX)" input_file: crates/typlite/src/fixtures/integration/highlight.typ -snapshot_kind: text --- @@ -14,9 +13,4 @@ snapshot_kind: text ===== -\begin{document} - \colorbox{yellow}{highlight} - - -\end{document} diff --git a/crates/typlite/src/fixtures/integration/snaps/convert_tex@ieee.typ.snap b/crates/typlite/src/fixtures/integration/snaps/convert_tex@ieee.typ.snap index 730caa9b..706aeb0d 100644 --- a/crates/typlite/src/fixtures/integration/snaps/convert_tex@ieee.typ.snap +++ b/crates/typlite/src/fixtures/integration/snaps/convert_tex@ieee.typ.snap @@ -2,7 +2,6 @@ source: crates/typlite/src/tests.rs expression: "conv(world, ConvKind::LaTeX)" input_file: crates/typlite/src/fixtures/integration/ieee.typ -snapshot_kind: text --- @@ -14,8 +13,6 @@ snapshot_kind: text ===== -\begin{document} - \section{Introduction} Scientific writing is a crucial part of the research process, allowing researchers to share their findings with the wider scientific community. However, the process of typesetting scientific documents can often be a frustrating and time-consuming affair, particularly when using outdated tools such as LaTeX. Despite being over 30 years old, it remains a popular choice for scientific writing due to its power and flexibility. However, it also comes with a steep learning curve, complex syntax, and long compile times, leading to frustration and despair for many researchers [1] [2]. @@ -95,6 +92,3 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor i \hline \end{tabular} \end{table} - - -\end{document} diff --git a/crates/typlite/src/fixtures/integration/snaps/convert_tex@image.typ.snap b/crates/typlite/src/fixtures/integration/snaps/convert_tex@image.typ.snap index 62788311..d029a5d7 100644 --- a/crates/typlite/src/fixtures/integration/snaps/convert_tex@image.typ.snap +++ b/crates/typlite/src/fixtures/integration/snaps/convert_tex@image.typ.snap @@ -13,14 +13,7 @@ input_file: crates/typlite/src/fixtures/integration/image.typ ===== -\begin{document} - \begin{figure} \centering \includegraphics[width=0.8\textwidth]{fig.svg} \end{figure} - - - - -\end{document} diff --git a/crates/typlite/src/fixtures/integration/snaps/convert_tex@image_alt.typ.snap b/crates/typlite/src/fixtures/integration/snaps/convert_tex@image_alt.typ.snap index d1be648c..3c2075ed 100644 --- a/crates/typlite/src/fixtures/integration/snaps/convert_tex@image_alt.typ.snap +++ b/crates/typlite/src/fixtures/integration/snaps/convert_tex@image_alt.typ.snap @@ -13,15 +13,8 @@ input_file: crates/typlite/src/fixtures/integration/image_alt.typ ===== -\begin{document} - \begin{figure} \centering \includegraphics[width=0.8\textwidth]{fig.svg} \caption{Content} \end{figure} - - - - -\end{document} diff --git a/crates/typlite/src/fixtures/integration/snaps/convert_tex@linebreak.typ.snap b/crates/typlite/src/fixtures/integration/snaps/convert_tex@linebreak.typ.snap index cc3e3fb1..fcc7b9cd 100644 --- a/crates/typlite/src/fixtures/integration/snaps/convert_tex@linebreak.typ.snap +++ b/crates/typlite/src/fixtures/integration/snaps/convert_tex@linebreak.typ.snap @@ -2,7 +2,6 @@ source: crates/typlite/src/tests.rs expression: "conv(world, ConvKind::LaTeX)" input_file: crates/typlite/src/fixtures/integration/linebreak.typ -snapshot_kind: text --- @@ -14,13 +13,8 @@ snapshot_kind: text ===== -\begin{document} - Text2\\ Text1\\ \subsection{H1} - - -\end{document} diff --git a/crates/typlite/src/fixtures/integration/snaps/convert_tex@link.typ.snap b/crates/typlite/src/fixtures/integration/snaps/convert_tex@link.typ.snap index 1e2984ab..fa15da36 100644 --- a/crates/typlite/src/fixtures/integration/snaps/convert_tex@link.typ.snap +++ b/crates/typlite/src/fixtures/integration/snaps/convert_tex@link.typ.snap @@ -13,9 +13,4 @@ input_file: crates/typlite/src/fixtures/integration/link.typ ===== -\begin{document} - \href{https://example.com}{https://example.com} - - -\end{document} diff --git a/crates/typlite/src/fixtures/integration/snaps/convert_tex@link2.typ.snap b/crates/typlite/src/fixtures/integration/snaps/convert_tex@link2.typ.snap index 846474c6..a0b85998 100644 --- a/crates/typlite/src/fixtures/integration/snaps/convert_tex@link2.typ.snap +++ b/crates/typlite/src/fixtures/integration/snaps/convert_tex@link2.typ.snap @@ -13,9 +13,4 @@ input_file: crates/typlite/src/fixtures/integration/link2.typ ===== -\begin{document} - \href{https://example.com}{Content} - - -\end{document} diff --git a/crates/typlite/src/fixtures/integration/snaps/convert_tex@link3.typ.snap b/crates/typlite/src/fixtures/integration/snaps/convert_tex@link3.typ.snap index 6d458ff4..8b718180 100644 --- a/crates/typlite/src/fixtures/integration/snaps/convert_tex@link3.typ.snap +++ b/crates/typlite/src/fixtures/integration/snaps/convert_tex@link3.typ.snap @@ -13,9 +13,4 @@ input_file: crates/typlite/src/fixtures/integration/link3.typ ===== -\begin{document} - \href{https://example.com}{Reverse \textbf{the World}} - - -\end{document} diff --git a/crates/typlite/src/fixtures/integration/snaps/convert_tex@list.typ.snap b/crates/typlite/src/fixtures/integration/snaps/convert_tex@list.typ.snap index 134646b2..5a397978 100644 --- a/crates/typlite/src/fixtures/integration/snaps/convert_tex@list.typ.snap +++ b/crates/typlite/src/fixtures/integration/snaps/convert_tex@list.typ.snap @@ -13,12 +13,7 @@ input_file: crates/typlite/src/fixtures/integration/list.typ ===== -\begin{document} - \begin{itemize} \item Some \textbf{item} \item Another \textit{item} \end{itemize} - - -\end{document} diff --git a/crates/typlite/src/fixtures/integration/snaps/convert_tex@math_block.typ.snap b/crates/typlite/src/fixtures/integration/snaps/convert_tex@math_block.typ.snap index f5d2a011..af89c911 100644 --- a/crates/typlite/src/fixtures/integration/snaps/convert_tex@math_block.typ.snap +++ b/crates/typlite/src/fixtures/integration/snaps/convert_tex@math_block.typ.snap @@ -13,10 +13,5 @@ input_file: crates/typlite/src/fixtures/integration/math_block.typ ===== -\begin{document} - \begin{center} \end{center} - - -\end{document} diff --git a/crates/typlite/src/fixtures/integration/snaps/convert_tex@math_block2.typ.snap b/crates/typlite/src/fixtures/integration/snaps/convert_tex@math_block2.typ.snap index b91b2b77..63cb0ff9 100644 --- a/crates/typlite/src/fixtures/integration/snaps/convert_tex@math_block2.typ.snap +++ b/crates/typlite/src/fixtures/integration/snaps/convert_tex@math_block2.typ.snap @@ -13,10 +13,5 @@ input_file: crates/typlite/src/fixtures/integration/math_block2.typ ===== -\begin{document} - \begin{center} \end{center} - - -\end{document} diff --git a/crates/typlite/src/fixtures/integration/snaps/convert_tex@math_inline.typ.snap b/crates/typlite/src/fixtures/integration/snaps/convert_tex@math_inline.typ.snap index 9ca7c380..ad31d742 100644 --- a/crates/typlite/src/fixtures/integration/snaps/convert_tex@math_inline.typ.snap +++ b/crates/typlite/src/fixtures/integration/snaps/convert_tex@math_inline.typ.snap @@ -13,9 +13,3 @@ input_file: crates/typlite/src/fixtures/integration/math_inline.typ ===== -\begin{document} - - - - -\end{document} diff --git a/crates/typlite/src/fixtures/integration/snaps/convert_tex@outline.typ.snap b/crates/typlite/src/fixtures/integration/snaps/convert_tex@outline.typ.snap index 46fbb193..4b28c6b3 100644 --- a/crates/typlite/src/fixtures/integration/snaps/convert_tex@outline.typ.snap +++ b/crates/typlite/src/fixtures/integration/snaps/convert_tex@outline.typ.snap @@ -28,8 +28,6 @@ namespace MyApplication ===== -\begin{document} - \section{Contents} \subsection{Heading 1} @@ -97,6 +95,3 @@ First termFirst definition \hline \end{tabular} \end{table} - - -\end{document} diff --git a/crates/typlite/src/fixtures/integration/snaps/convert_tex@raw_inline.typ.snap b/crates/typlite/src/fixtures/integration/snaps/convert_tex@raw_inline.typ.snap index 8058ed71..4c7b6756 100644 --- a/crates/typlite/src/fixtures/integration/snaps/convert_tex@raw_inline.typ.snap +++ b/crates/typlite/src/fixtures/integration/snaps/convert_tex@raw_inline.typ.snap @@ -13,9 +13,4 @@ input_file: crates/typlite/src/fixtures/integration/raw_inline.typ ===== -\begin{document} - Some inlined raw \texttt{a}, \texttt{b} - - -\end{document} diff --git a/crates/typlite/src/fixtures/integration/snaps/convert_tex@table.typ.snap b/crates/typlite/src/fixtures/integration/snaps/convert_tex@table.typ.snap index c2165ebc..715947c5 100644 --- a/crates/typlite/src/fixtures/integration/snaps/convert_tex@table.typ.snap +++ b/crates/typlite/src/fixtures/integration/snaps/convert_tex@table.typ.snap @@ -2,7 +2,6 @@ source: crates/typlite/src/tests.rs expression: "conv(world, ConvKind::LaTeX)" input_file: crates/typlite/src/fixtures/integration/table.typ -snapshot_kind: text --- @@ -14,8 +13,6 @@ snapshot_kind: text ===== -\begin{document} - \begin{table}[htbp] \centering \begin{tabular}{cccccccccccccccccccc} @@ -40,4 +37,3 @@ snapshot_kind: text \end{table} 012345678910111213141516171819012345678910111213141516171819 -\end{document} diff --git a/crates/typlite/src/lib.rs b/crates/typlite/src/lib.rs index 6f5f86e5..80c21eef 100644 --- a/crates/typlite/src/lib.rs +++ b/crates/typlite/src/lib.rs @@ -23,7 +23,6 @@ use typst::foundations::Bytes; use typst::html::HtmlDocument; use typst::World; use typst_syntax::VirtualPath; -use writer::LaTeXWriter; use crate::common::Format; use crate::parser::HtmlToAstParser; @@ -110,14 +109,11 @@ impl MarkdownDocument { } /// Convert the content to a LaTeX string. - pub fn to_tex_string(&self, prelude: bool) -> tinymist_std::Result { + pub fn to_tex_string(&self) -> tinymist_std::Result { let mut output = ecow::EcoString::new(); let ast = self.parse()?; let mut writer = WriterFactory::create(Format::LaTeX); - if prelude { - LaTeXWriter::default_prelude(&mut output); - } writer .write_eco(&ast, &mut output) .context_ut("failed to write")?; @@ -159,8 +155,27 @@ pub struct TypliteFeat { pub remove_html: bool, /// The target to convert pub target: Format, - /// Import context for code examples (e.g., "#import \"/path/to/file.typ\": *") + /// Import context for code examples (e.g., "#import \"/path/to/file.typ\": + /// *") pub import_context: Option, + /// Specifies the package to process markup. + /// + /// ## `article` function + /// + /// The article function is used to wrap the typst content during + /// compilation. + /// + /// typlite exactly uses the `#article` function to process the content as + /// follow: + /// + /// ```typst + /// #import "@local/processor": article + /// #article(include "the-processed-content.typ") + /// ``` + /// + /// It resembles the regular typst show rule function, like `#show: + /// article`. + pub processor: Option, } /// Task builder for converting a typst document to Markdown. @@ -198,7 +213,7 @@ impl Typlite { pub fn convert(self) -> tinymist_std::Result { match self.format { Format::Md => self.convert_doc(Format::Md)?.to_md_string(), - Format::LaTeX => self.convert_doc(Format::LaTeX)?.to_tex_string(true), + Format::LaTeX => self.convert_doc(Format::LaTeX)?.to_tex_string(), Format::Text => self.convert_doc(Format::Text)?.to_text_string(), #[cfg(feature = "docx")] Format::Docx => bail!("docx format is not supported"), @@ -227,9 +242,19 @@ impl Typlite { } let wrap_main_id = current.join("__wrap_md_main.typ"); - let wrap_main_path = world - .path_for_id(wrap_main_id) - .context_ut("getting source for main file")?; + + 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())); @@ -238,7 +263,7 @@ impl Typlite { } let task_inputs = TaskInputs { - entry: Some(entry.select_in_workspace(wrap_main_id.vpath().as_rooted_path())), + entry: Some(entry.select_in_workspace(main_id.vpath().as_rooted_path())), inputs: Some(Arc::new(LazyHash::new(dict))), }; @@ -266,8 +291,8 @@ impl Typlite { .context_ut("cannot map markdown.typ")?; world - .map_shadow( - wrap_main_path.as_path(), + .map_shadow_by_id( + wrap_main_id, Bytes::from_string(format!( r#"#import "@local/markdown:0.1.0": md-doc, example #show: md-doc @@ -280,6 +305,12 @@ impl Typlite { ) .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")?; + } + // todo: ignoring warnings let base = typst::compile(&world).output?; let mut feat = self.feat; diff --git a/crates/typlite/src/main.rs b/crates/typlite/src/main.rs index 125f096b..d77df0f6 100644 --- a/crates/typlite/src/main.rs +++ b/crates/typlite/src/main.rs @@ -11,7 +11,7 @@ use clap::Parser; use tinymist_project::{ base::print_diagnostics, DiagnosticFormat, LspWorld, SourceWorld, WorldProvider, }; -use tinymist_std::error::prelude::*; +use tinymist_std::{error::prelude::*, Result}; use typlite::{common::Format, TypliteFeat}; use typlite::{CompileOnceArgs, Typlite}; use typst::foundations::Bytes; @@ -28,62 +28,76 @@ pub struct CompileArgs { /// Configures the path of assets directory #[clap(long, default_value = None, value_name = "ASSETS_PATH")] - pub assets_path: Option, + pub assets_path: Option, + + /// Specifies the package to process markup. + /// + /// ## `article` function + /// + /// The article function is used to wrap the typst content during + /// compilation. + /// + /// typlite exactly uses the `#article` function to process the content as + /// follow: + /// + /// ```typst + /// #import "@local/processor": article + /// #article(include "the-processed-content.typ") + /// ``` + /// + /// It resembles the regular typst show rule function, like `#show: + /// article`. + #[clap(long = "processor", default_value = None, value_name = "PACKAGE_SPEC")] + pub processor: Option, } -fn main() -> tinymist_std::Result<()> { +fn main() -> Result<()> { // Parse command line arguments let args = CompileArgs::parse(); - let universe = args.compile.resolve()?; - let world = Arc::new(universe.snapshot()); + let verse = args.compile.resolve()?; + let world = Arc::new(verse.snapshot()); print_diag_or_error(world.as_ref(), run(args, world.clone())) } -fn run(args: CompileArgs, world: Arc) -> tinymist_std::Result<()> { +fn run(args: CompileArgs, world: Arc) -> Result<()> { let input = args .compile .input - .as_ref() .context("Missing required argument: INPUT")?; let is_stdout = args.output.as_deref() == Some("-"); let output_path = args .output .map(PathBuf::from) - .unwrap_or_else(|| Path::new(input).with_extension("md")); + .unwrap_or_else(|| Path::new(&input).with_extension("md")); - let output_format = match output_path.extension() { - Some(ext) if ext == std::ffi::OsStr::new("tex") => Format::LaTeX, - Some(ext) if ext == std::ffi::OsStr::new("txt") => Format::Text, + let output_format = match output_path.extension().and_then(std::ffi::OsStr::to_str) { + Some("tex") => Format::LaTeX, + Some("txt") => Format::Text, #[cfg(feature = "docx")] - Some(ext) if ext == std::ffi::OsStr::new("docx") => Format::Docx, + Some("docx") => Format::Docx, _ => Format::Md, }; - let assets_path = match args.assets_path { - Some(assets_path) => { - let path = PathBuf::from(assets_path); - if !path.exists() { - if let Err(e) = std::fs::create_dir_all(&path) { - bail!("failed to create assets directory: {e}"); - } - } - Some(path) + if let Some(assets_path) = args.assets_path.as_ref() { + if !assets_path.exists() { + std::fs::create_dir_all(assets_path).context("failed to create assets directory")?; } - None => None, - }; + } - let converter = Typlite::new(world.clone()).with_feature(TypliteFeat { - assets_path: assets_path.clone(), - ..Default::default() - }); - let doc = converter.convert_doc(output_format)?; + let doc = Typlite::new(world.clone()) + .with_feature(TypliteFeat { + assets_path: args.assets_path, + processor: args.processor, + ..Default::default() + }) + .convert_doc(output_format)?; let result = match output_format { Format::Md => Bytes::from_string(doc.to_md_string()?), - Format::LaTeX => Bytes::from_string(doc.to_tex_string(true)?), + Format::LaTeX => Bytes::from_string(doc.to_tex_string()?), Format::Text => Bytes::from_string(doc.to_text_string()?), #[cfg(feature = "docx")] Format::Docx => Bytes::new(doc.to_docx()?), @@ -100,10 +114,7 @@ fn run(args: CompileArgs, world: Arc) -> tinymist_std::Result<()> { Ok(()) } -fn print_diag_or_error( - world: &impl SourceWorld, - result: tinymist_std::Result, -) -> tinymist_std::Result { +fn print_diag_or_error(world: &impl SourceWorld, result: Result) -> Result { match result { Ok(v) => Ok(v), Err(err) => { diff --git a/crates/typlite/src/parser/core.rs b/crates/typlite/src/parser/core.rs index fe861d92..c1cb7298 100644 --- a/crates/typlite/src/parser/core.rs +++ b/crates/typlite/src/parser/core.rs @@ -8,8 +8,8 @@ use ecow::EcoString; use tinymist_project::LspWorld; use typst::html::{tag, HtmlElement, HtmlNode}; -use crate::attributes::{AlertsAttr, HeadingAttr, RawAttr, TypliteAttrsParser}; -use crate::common::{AlertNode, CenterNode, ListState}; +use crate::attributes::{md_attr, AlertsAttr, HeadingAttr, RawAttr, TypliteAttrsParser}; +use crate::common::{AlertNode, CenterNode, ListState, VerbatimNode}; use crate::tags::md_tag; use crate::Result; use crate::TypliteFeat; @@ -181,6 +181,19 @@ impl HtmlToAstParser { Ok(()) } + md_tag::verbatim => { + self.inline_buffer.push(Node::Custom(Box::new(VerbatimNode { + content: element + .attrs + .0 + .iter() + .find(|(name, _)| *name == md_attr::src) + .map(|(_, value)| value.clone()) + .unwrap_or_default(), + }))); + Ok(()) + } + _ => { let tag_name = element.tag.resolve().to_string(); diff --git a/crates/typlite/src/tags.rs b/crates/typlite/src/tags.rs index 5be72852..e80e6293 100644 --- a/crates/typlite/src/tags.rs +++ b/crates/typlite/src/tags.rs @@ -22,6 +22,7 @@ pub mod md_tag { highlight -> m1highlight strike -> m1strike raw -> m1raw + verbatim -> m1verbatim label -> m1label reference -> m1ref heading -> m1heading diff --git a/crates/typlite/src/tests.rs b/crates/typlite/src/tests.rs index b9f0b22b..4259a971 100644 --- a/crates/typlite/src/tests.rs +++ b/crates/typlite/src/tests.rs @@ -104,7 +104,7 @@ fn conv(world: LspWorld, kind: ConvKind) -> String { let repr = typst_html::html(&redact(doc.base.clone())).unwrap(); let res = match kind { ConvKind::Md { .. } => doc.to_md_string().unwrap(), - ConvKind::LaTeX => doc.to_tex_string(false).unwrap(), + ConvKind::LaTeX => doc.to_tex_string().unwrap(), }; static REG: OnceLock = OnceLock::new(); diff --git a/crates/typlite/src/writer/docx/writer.rs b/crates/typlite/src/writer/docx/writer.rs index 7375c27a..709215a8 100644 --- a/crates/typlite/src/writer/docx/writer.rs +++ b/crates/typlite/src/writer/docx/writer.rs @@ -7,7 +7,9 @@ use ecow::EcoString; use std::fs; use std::io::Cursor; -use crate::common::{CenterNode, FigureNode, FormatWriter, HighlightNode, InlineNode}; +use crate::common::{ + CenterNode, FigureNode, FormatWriter, HighlightNode, InlineNode, VerbatimNode, +}; use crate::Result; use super::image_processor::DocxImageProcessor; @@ -248,6 +250,10 @@ impl DocxWriter { run = self.process_inline_to_run(run, child)?; } } + node if node.is_custom_type::() => { + let node = node.as_custom_type::().unwrap(); + eprintln!("Warning: `m1verbatim` is ignored {:?}.", node.content); + } // Other inline element types _ => { println!("other inline element: {:?}", node); diff --git a/crates/typlite/src/writer/latex.rs b/crates/typlite/src/writer/latex.rs index 646ded63..c6aa1a7d 100644 --- a/crates/typlite/src/writer/latex.rs +++ b/crates/typlite/src/writer/latex.rs @@ -8,6 +8,7 @@ use tinymist_std::path::unix_slash; use crate::common::{ CenterNode, ExternalFrameNode, FigureNode, FormatWriter, HighlightNode, InlineNode, ListState, + VerbatimNode, }; use crate::Result; @@ -27,32 +28,6 @@ impl LaTeXWriter { Self { list_state: None } } - pub fn default_prelude(output: &mut EcoString) { - // Write LaTeX document preamble using the new method - output.push_str("\\documentclass[12pt,a4paper]{article}\n"); - output.push_str("\\usepackage[utf8]{inputenc}\n"); - output.push_str("\\usepackage{hyperref}\n"); // For links - output.push_str("\\usepackage{graphicx}\n"); // For images - output.push_str("\\usepackage{ulem}\n"); // For strikethrough \sout - output.push_str("\\usepackage{listings}\n"); // For code blocks - output.push_str("\\usepackage{xcolor}\n"); // For colored text and backgrounds - output.push_str("\\usepackage{amsmath}\n"); // Math formula support - output.push_str("\\usepackage{amssymb}\n"); // Additional math symbols - output.push_str("\\usepackage{array}\n"); // Enhanced table functionality - - // Set code highlighting style - output.push_str("\\lstset{\n"); - output.push_str(" basicstyle=\\ttfamily\\small,\n"); - output.push_str(" breaklines=true,\n"); - output.push_str(" frame=single,\n"); - output.push_str(" numbers=left,\n"); - output.push_str(" numberstyle=\\tiny,\n"); - output.push_str(" keywordstyle=\\color{blue},\n"); - output.push_str(" commentstyle=\\color{green!60!black},\n"); - output.push_str(" stringstyle=\\color{red}\n"); - output.push_str("}\n\n"); - } - fn write_inline_nodes(&mut self, nodes: &[Node], output: &mut EcoString) -> Result<()> { for node in nodes { self.write_node(node, output)?; @@ -314,6 +289,10 @@ impl LaTeXWriter { self.write_node(child, output)?; } } + node if node.is_custom_type::() => { + let inline_node = node.as_custom_type::().unwrap(); + output.push_str(&inline_node.content); + } Node::Text(text) => { output.push_str(&escape_latex(text)); } @@ -410,14 +389,8 @@ fn escape_latex(text: &str) -> String { impl FormatWriter for LaTeXWriter { fn write_eco(&mut self, document: &Node, output: &mut EcoString) -> Result<()> { - output.push_str("\\begin{document}\n\n"); - // Write the document content self.write_node(document, output)?; - - // Add document ending - output.push_str("\n\\end{document}\n"); - Ok(()) } diff --git a/editors/vscode/e2e-workspaces/ieee-paper/.vscode/tasks.json b/editors/vscode/e2e-workspaces/ieee-paper/.vscode/tasks.json index 8e8b550f..1892aa2e 100644 --- a/editors/vscode/e2e-workspaces/ieee-paper/.vscode/tasks.json +++ b/editors/vscode/e2e-workspaces/ieee-paper/.vscode/tasks.json @@ -6,7 +6,11 @@ "type": "typst", "command": "export", "export": { - "format": ["latex"] + "format": ["latex"], + // It is totally legal to use the processor in the current workspace, + // but we suggest make a local package and use the package spec instead. + // like: "package": "@local/ieee-tex:0.1.0" + "processor": "/ieee-tex.typ" } }, { diff --git a/editors/vscode/e2e-workspaces/ieee-paper/ieee-template.typ b/editors/vscode/e2e-workspaces/ieee-paper/ieee-template.typ index 82af2102..e1fb2f92 100644 --- a/editors/vscode/e2e-workspaces/ieee-paper/ieee-template.typ +++ b/editors/vscode/e2e-workspaces/ieee-paper/ieee-template.typ @@ -2,6 +2,11 @@ /// `ieee` will not style the document if `is-html-target` is true. #let is-html-target = ("target" in dictionary(std)) +#let title-state = state("tex:title", "") +#let authors-state = state("tex:authors", ()) +#let abstract-state = state("tex:abstract", "") +#let bibliography-state = state("tex:bibliography", "") + // This function gets your whole document as its `body` and formats // it as an article in the style of the IEEE. #let ieee( @@ -27,10 +32,15 @@ ) = if is-html-target { set heading(numbering: "I.A.a)") set math.equation(numbering: "(1)") + title-state.update(_ => title) + authors-state.update(_ => authors) + abstract-state.update(_ => abstract) + if bibliography != none { + bibliography-state.update(_ => bibliography.sources.at(0)) + } body - // Display bibliography. bibliography } else { // Set document metadata. diff --git a/editors/vscode/e2e-workspaces/ieee-paper/ieee-tex.typ b/editors/vscode/e2e-workspaces/ieee-paper/ieee-tex.typ new file mode 100644 index 00000000..dd8a3bb2 --- /dev/null +++ b/editors/vscode/e2e-workspaces/ieee-paper/ieee-tex.typ @@ -0,0 +1,553 @@ + +#let verbatim(body) = { + show raw.where(lang: "tex"): it => html.elem("m1verbatim", attrs: (src: it.text)) + body +} + +#let prelude1 = verbatim(```tex +%% bare_conf_compsoc.tex +%% V1.4b +%% 2015/08/26 +%% by Michael Shell +%% See: +%% http://www.michaelshell.org/ +%% for current contact information. +%% +%% This is a skeleton file demonstrating the use of IEEEtran.cls +%% (requires IEEEtran.cls version 1.8b or later) with an IEEE Computer +%% Society conference paper. +%% +%% Support sites: +%% http://www.michaelshell.org/tex/ieeetran/ +%% http://www.ctan.org/pkg/ieeetran +%% and +%% http://www.ieee.org/ + +%%************************************************************************* +%% Legal Notice: +%% This code is offered as-is without any warranty either expressed or +%% implied; without even the implied warranty of MERCHANTABILITY or +%% FITNESS FOR A PARTICULAR PURPOSE! +%% User assumes all risk. +%% In no event shall the IEEE or any contributor to this code be liable for +%% any damages or losses, including, but not limited to, incidental, +%% consequential, or any other damages, resulting from the use or misuse +%% of any information contained here. +%% +%% All comments are the opinions of their respective authors and are not +%% necessarily endorsed by the IEEE. +%% +%% This work is distributed under the LaTeX Project Public License (LPPL) +%% ( http://www.latex-project.org/ ) version 1.3, and may be freely used, +%% distributed and modified. A copy of the LPPL, version 1.3, is included +%% in the base LaTeX documentation of all distributions of LaTeX released +%% 2003/12/01 or later. +%% Retain all contribution notices and credits. +%% ** Modified files should be clearly indicated as such, including ** +%% ** renaming them and changing author support contact information. ** +%%************************************************************************* + + +% *** Authors should verify (and, if needed, correct) their LaTeX system *** +% *** with the testflow diagnostic prior to trusting their LaTeX platform *** +% *** with production work. The IEEE's font choices and paper sizes can *** +% *** trigger bugs that do not appear when using other class files. *** *** +% The testflow support page is at: +% http://www.michaelshell.org/tex/testflow/ + + + +\documentclass[conference,compsoc]{IEEEtran} +% Some/most Computer Society conferences require the compsoc mode option, +% but others may want the standard conference format. +% +% If IEEEtran.cls has not been installed into the LaTeX system files, +% manually specify the path to it like: +% \documentclass[conference,compsoc]{../sty/IEEEtran} + + + + + +% Some very useful LaTeX packages include: +% (uncomment the ones you want to load) + + +% *** MISC UTILITY PACKAGES *** +% +%\usepackage{ifpdf} +% Heiko Oberdiek's ifpdf.sty is very useful if you need conditional +% compilation based on whether the output is pdf or dvi. +% usage: +% \ifpdf +% % pdf code +% \else +% % dvi code +% \fi +% The latest version of ifpdf.sty can be obtained from: +% http://www.ctan.org/pkg/ifpdf +% Also, note that IEEEtran.cls V1.7 and later provides a builtin +% \ifCLASSINFOpdf conditional that works the same way. +% When switching from latex to pdflatex and vice-versa, the compiler may +% have to be run twice to clear warning/error messages. + + + + + + +% *** CITATION PACKAGES *** +% +\ifCLASSOPTIONcompsoc + % IEEE Computer Society needs nocompress option + % requires cite.sty v4.0 or later (November 2003) + \usepackage[nocompress]{cite} +\else + % normal IEEE + \usepackage{cite} +\fi +% cite.sty was written by Donald Arseneau +% V1.6 and later of IEEEtran pre-defines the format of the cite.sty package +% \cite{} output to follow that of the IEEE. Loading the cite package will +% result in citation numbers being automatically sorted and properly +% "compressed/ranged". e.g., [1], [9], [2], [7], [5], [6] without using +% cite.sty will become [1], [2], [5]--[7], [9] using cite.sty. cite.sty's +% \cite will automatically add leading space, if needed. Use cite.sty's +% noadjust option (cite.sty V3.8 and later) if you want to turn this off +% such as if a citation ever needs to be enclosed in parenthesis. +% cite.sty is already installed on most LaTeX systems. Be sure and use +% version 5.0 (2009-03-20) and later if using hyperref.sty. +% The latest version can be obtained at: +% http://www.ctan.org/pkg/cite +% The documentation is contained in the cite.sty file itself. +% +% Note that some packages require special options to format as the Computer +% Society requires. In particular, Computer Society papers do not use +% compressed citation ranges as is done in typical IEEE papers +% (e.g., [1]-[4]). Instead, they list every citation separately in order +% (e.g., [1], [2], [3], [4]). To get the latter we need to load the cite +% package with the nocompress option which is supported by cite.sty v4.0 +% and later. + + + + + +% *** GRAPHICS RELATED PACKAGES *** +% +\ifCLASSINFOpdf + % \usepackage[pdftex]{graphicx} + % declare the path(s) where your graphic files are + % \graphicspath{{../pdf/}{../jpeg/}} + % and their extensions so you won't have to specify these with + % every instance of \includegraphics + % \DeclareGraphicsExtensions{.pdf,.jpeg,.png} +\else + % or other class option (dvipsone, dvipdf, if not using dvips). graphicx + % will default to the driver specified in the system graphics.cfg if no + % driver is specified. + % \usepackage[dvips]{graphicx} + % declare the path(s) where your graphic files are + % \graphicspath{{../eps/}} + % and their extensions so you won't have to specify these with + % every instance of \includegraphics + % \DeclareGraphicsExtensions{.eps} +\fi +% graphicx was written by David Carlisle and Sebastian Rahtz. It is +% required if you want graphics, photos, etc. graphicx.sty is already +% installed on most LaTeX systems. The latest version and documentation +% can be obtained at: +% http://www.ctan.org/pkg/graphicx +% Another good source of documentation is "Using Imported Graphics in +% LaTeX2e" by Keith Reckdahl which can be found at: +% http://www.ctan.org/pkg/epslatex +% +% latex, and pdflatex in dvi mode, support graphics in encapsulated +% postscript (.eps) format. pdflatex in pdf mode supports graphics +% in .pdf, .jpeg, .png and .mps (metapost) formats. Users should ensure +% that all non-photo figures use a vector format (.eps, .pdf, .mps) and +% not a bitmapped formats (.jpeg, .png). The IEEE frowns on bitmapped formats +% which can result in "jaggedy"/blurry rendering of lines and letters as +% well as large increases in file sizes. +% +% You can find documentation about the pdfTeX application at: +% http://www.tug.org/applications/pdftex + + + + + +% *** MATH PACKAGES *** +% +%\usepackage{amsmath} +% A popular package from the American Mathematical Society that provides +% many useful and powerful commands for dealing with mathematics. +% +% Note that the amsmath package sets \interdisplaylinepenalty to 10000 +% thus preventing page breaks from occurring within multiline equations. Use: +%\interdisplaylinepenalty=2500 +% after loading amsmath to restore such page breaks as IEEEtran.cls normally +% does. amsmath.sty is already installed on most LaTeX systems. The latest +% version and documentation can be obtained at: +% http://www.ctan.org/pkg/amsmath + + + + + +% *** SPECIALIZED LIST PACKAGES *** +% +%\usepackage{algorithmic} +% algorithmic.sty was written by Peter Williams and Rogerio Brito. +% This package provides an algorithmic environment for describing algorithms. +% You can use the algorithmic environment in-text or within a figure +% environment to provide for a floating algorithm. Do NOT use the algorithm +% floating environment provided by algorithm.sty (by the same authors) or +% algorithm2e.sty (by Christophe Fiorio) as the IEEE does not use dedicated +% algorithm float types and packages that provide these will not provide +% correct IEEE style captions. The latest version and documentation of +% algorithmic.sty can be obtained at: +% http://www.ctan.org/pkg/algorithms +% Also of interest may be the (relatively newer and more customizable) +% algorithmicx.sty package by Szasz Janos: +% http://www.ctan.org/pkg/algorithmicx + + + + +% *** ALIGNMENT PACKAGES *** +% +%\usepackage{array} +% Frank Mittelbach's and David Carlisle's array.sty patches and improves +% the standard LaTeX2e array and tabular environments to provide better +% appearance and additional user controls. As the default LaTeX2e table +% generation code is lacking to the point of almost being broken with +% respect to the quality of the end results, all users are strongly +% advised to use an enhanced (at the very least that provided by array.sty) +% set of table tools. array.sty is already installed on most systems. The +% latest version and documentation can be obtained at: +% http://www.ctan.org/pkg/array + + +% IEEEtran contains the IEEEeqnarray family of commands that can be used to +% generate multiline equations as well as matrices, tables, etc., of high +% quality. + + + + +% *** SUBFIGURE PACKAGES *** +%\ifCLASSOPTIONcompsoc +% \usepackage[caption=false,font=footnotesize,labelfont=sf,textfont=sf]{subfig} +%\else +% \usepackage[caption=false,font=footnotesize]{subfig} +%\fi +% subfig.sty, written by Steven Douglas Cochran, is the modern replacement +% for subfigure.sty, the latter of which is no longer maintained and is +% incompatible with some LaTeX packages including fixltx2e. However, +% subfig.sty requires and automatically loads Axel Sommerfeldt's caption.sty +% which will override IEEEtran.cls' handling of captions and this will result +% in non-IEEE style figure/table captions. To prevent this problem, be sure +% and invoke subfig.sty's "caption=false" package option (available since +% subfig.sty version 1.3, 2005/06/28) as this is will preserve IEEEtran.cls +% handling of captions. +% Note that the Computer Society format requires a sans serif font rather +% than the serif font used in traditional IEEE formatting and thus the need +% to invoke different subfig.sty package options depending on whether +% compsoc mode has been enabled. +% +% The latest version and documentation of subfig.sty can be obtained at: +% http://www.ctan.org/pkg/subfig + + + + +% *** FLOAT PACKAGES *** +% +%\usepackage{fixltx2e} +% fixltx2e, the successor to the earlier fix2col.sty, was written by +% Frank Mittelbach and David Carlisle. This package corrects a few problems +% in the LaTeX2e kernel, the most notable of which is that in current +% LaTeX2e releases, the ordering of single and double column floats is not +% guaranteed to be preserved. Thus, an unpatched LaTeX2e can allow a +% single column figure to be placed prior to an earlier double column +% figure. +% Be aware that LaTeX2e kernels dated 2015 and later have fixltx2e.sty's +% corrections already built into the system in which case a warning will +% be issued if an attempt is made to load fixltx2e.sty as it is no longer +% needed. +% The latest version and documentation can be found at: +% http://www.ctan.org/pkg/fixltx2e + + +%\usepackage{stfloats} +% stfloats.sty was written by Sigitas Tolusis. This package gives LaTeX2e +% the ability to do double column floats at the bottom of the page as well +% as the top. (e.g., "\begin{figure*}[!b]" is not normally possible in +% LaTeX2e). It also provides a command: +%\fnbelowfloat +% to enable the placement of footnotes below bottom floats (the standard +% LaTeX2e kernel puts them above bottom floats). This is an invasive package +% which rewrites many portions of the LaTeX2e float routines. It may not work +% with other packages that modify the LaTeX2e float routines. The latest +% version and documentation can be obtained at: +% http://www.ctan.org/pkg/stfloats +% Do not use the stfloats baselinefloat ability as the IEEE does not allow +% \baselineskip to stretch. Authors submitting work to the IEEE should note +% that the IEEE rarely uses double column equations and that authors should try +% to avoid such use. Do not be tempted to use the cuted.sty or midfloat.sty +% packages (also by Sigitas Tolusis) as the IEEE does not format its papers in +% such ways. +% Do not attempt to use stfloats with fixltx2e as they are incompatible. +% Instead, use Morten Hogholm'a dblfloatfix which combines the features +% of both fixltx2e and stfloats: +% +% \usepackage{dblfloatfix} +% The latest version can be found at: +% http://www.ctan.org/pkg/dblfloatfix + + + + +% *** PDF, URL AND HYPERLINK PACKAGES *** +% +%\usepackage{url} +% url.sty was written by Donald Arseneau. It provides better support for +% handling and breaking URLs. url.sty is already installed on most LaTeX +% systems. The latest version and documentation can be obtained at: +% http://www.ctan.org/pkg/url +% Basically, \url{my_url_here}. + + + + +% *** Do not adjust lengths that control margins, column widths, etc. *** +% *** Do not use packages that alter fonts (such as pslatex). *** +% There should be no need to do such things with IEEEtran.cls V1.6 and later. +% (Unless specifically asked to do so by the journal or conference you plan +% to submit to, of course. ) + + +% correct bad hyphenation here +\hyphenation{op-tical net-works semi-conduc-tor} + + +\begin{document} +% +% paper title +% Titles are generally capitalized except for words such as a, an, and, as, +% at, but, by, for, in, nor, of, on, or, the, to and up, which are usually +% not capitalized unless they are the first or last word of the title. +% Linebreaks \\ can be used within to get better formatting as desired. +% Do not put math or special symbols in the title. + +```) +#let paper-title = context { + let title = state("tex:title", "").final() + verbatim[ + ```tex + \title{ + ``` + ] + title + verbatim[ + ```tex + } + ``` + ] +} +#let paper-authors = context { + let to-text(author, field) = { + let value = author.at(field) + if type(value) == str { + value + } else if type(value) == content and value.has("text") { + value.text + } else { + panic("Expected a string or content with `text` in field: " + field) + } + } + + let authors = state("tex:authors", ()) + .final() + .map(author => { + verbatim( + raw( + lang: "tex", + { + "\n\\IEEEauthorblockN{" + to-text(author, "name") + "}" + if ("department" in author) or ("organization" in author) or ("location" in author) { + "\n\\IEEEauthorblockA{" + if "department" in author { + "\n" + to-text(author, "department") + "\\" + } + if "organization" in author { + "\n" + to-text(author, "organization") + "\\" + } + if "location" in author { + "\n" + to-text(author, "location") + "\\" + } + "\n}" + } + }, + ), + ) + }) + let _and = verbatim(raw(lang: "tex", "\n\and\n")) + + verbatim[ + ```tex + + % author names and affiliations + % use a multiple column layout for up to three different + % affiliations + \author{ + ``` + ] + authors.join(_and) + verbatim[ + ```tex + } + ``` + ] +} +#let prelude2 = verbatim(```tex + +% conference papers do not typically use \thanks and this command +% is locked out in conference mode. If really needed, such as for +% the acknowledgment of grants, issue a \IEEEoverridecommandlockouts +% after \documentclass + +% for over three affiliations, or if they all won't fit within the width +% of the page (and note that there is less available width in this regard for +% compsoc conferences compared to traditional conferences), use this +% alternative format: +% +%\author{\IEEEauthorblockN{Michael Shell\IEEEauthorrefmark{1}, +%Homer Simpson\IEEEauthorrefmark{2}, +%James Kirk\IEEEauthorrefmark{3}, +%Montgomery Scott\IEEEauthorrefmark{3} and +%Eldon Tyrell\IEEEauthorrefmark{4}} +%\IEEEauthorblockA{\IEEEauthorrefmark{1}School of Electrical and Computer Engineering\\ +%Georgia Institute of Technology, +%Atlanta, Georgia 30332--0250\\ Email: see http://www.michaelshell.org/contact.html} +%\IEEEauthorblockA{\IEEEauthorrefmark{2}Twentieth Century Fox, Springfield, USA\\ +%Email: homer@thesimpsons.com} +%\IEEEauthorblockA{\IEEEauthorrefmark{3}Starfleet Academy, San Francisco, California 96678-2391\\ +%Telephone: (800) 555--1212, Fax: (888) 555--1212} +%\IEEEauthorblockA{\IEEEauthorrefmark{4}Tyrell Inc., 123 Replicant Street, Los Angeles, California 90210--4321}} + + + + +% use for special paper notices +%\IEEEspecialpapernotice{(Invited Paper)} + + + + +% make the title area +\maketitle + +```) +#let abstract = context { + let abstract = state("tex:abstract", "").final() + verbatim[ + ```tex + % As a general rule, do not put math, special symbols or citations + % in the abstract + \begin{abstract} + ``` + ] + abstract + verbatim[ + + ```tex + \end{abstract} + ``` + ] +} +#let prelude3 = verbatim(```tex + +% no keywords + +% For peer review papers, you can put extra information on the cover +% page as needed: +% \ifCLASSOPTIONpeerreview +% \begin{center} \bfseries EDICS Category: 3-BBND \end{center} +% \fi +% +% For peerreview papers, this IEEEtran command inserts a page break and +% creates the second title. It will be ignored for other modes. +\IEEEpeerreviewmaketitle + +```) +#let bibliography-section = context { + let bibliography-state = state("tex:bibliography", "").final() + verbatim[ + ```tex + % trigger a \newpage just before the given reference + % number - used to balance the columns on the last page + % adjust value as needed - may need to be readjusted if + % the document is modified later + %\IEEEtriggeratref{8} + % The "triggered" command can be changed if desired: + %\IEEEtriggercmd{\enlargethispage{-5in}} + + % references section + + % can use a bibliography generated by BibTeX as a .bbl file + % BibTeX documentation can be easily obtained at: + % http://mirror.ctan.org/biblio/bibtex/contrib/doc/ + % The IEEEtran BibTeX style support page is at: + % http://www.michaelshell.org/tex/ieeetran/bibtex/ + %\bibliographystyle{IEEEtran} + % argument is your BibTeX string definitions and bibliography database(s) + ``` + ] + verbatim( + raw( + lang: "tex", + if bibliography-state == none { + "%\bibliography{IEEEabrv,../bib/paper}" + } else { + "%\bibliography{IEEEabrv," + bibliography-state + "}" + }, + ), + ) +} +#let postlude = verbatim(```tex + +% that's all folks +\end{document} +```) + +#let article(body) = { + // make bibliography available but not visible in the document + show bibliography: it => { + verbatim(```tex + + \iffalse + ```) + it + verbatim(```tex + + \fi + + ```) + } + + prelude1 + paper-title + paper-authors + prelude2 + abstract + prelude3 + body + bibliography-section + postlude +}