mirror of
https://github.com/Myriad-Dreamin/tinymist.git
synced 2025-07-07 13:05:02 +00:00
feat: export to tex by tasks (#1826)
* feat: export to tex by tasks * test: update snapshot
This commit is contained in:
parent
8e86a401ff
commit
7ee2e53189
19 changed files with 346 additions and 131 deletions
|
@ -1,6 +1,6 @@
|
|||
//! Project task models.
|
||||
|
||||
use std::hash::Hash;
|
||||
use std::{hash::Hash, path::PathBuf};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
|
@ -72,6 +72,8 @@ pub enum ProjectTask {
|
|||
ExportSvgHtml(ExportHtmlTask),
|
||||
/// An export Markdown task.
|
||||
ExportMd(ExportMarkdownTask),
|
||||
/// An export TeX task.
|
||||
ExportTeX(ExportTeXTask),
|
||||
/// An export Text task.
|
||||
ExportText(ExportTextTask),
|
||||
/// An query task.
|
||||
|
@ -92,6 +94,7 @@ impl ProjectTask {
|
|||
| Self::ExportHtml(..)
|
||||
| Self::ExportSvgHtml(..)
|
||||
| Self::ExportMd(..)
|
||||
| Self::ExportTeX(..)
|
||||
| Self::ExportText(..)
|
||||
| Self::Query(..) => self.as_export()?.when,
|
||||
})
|
||||
|
@ -106,6 +109,7 @@ impl ProjectTask {
|
|||
Self::ExportSvg(task) => &task.export,
|
||||
Self::ExportHtml(task) => &task.export,
|
||||
Self::ExportSvgHtml(task) => &task.export,
|
||||
Self::ExportTeX(task) => &task.export,
|
||||
Self::ExportMd(task) => &task.export,
|
||||
Self::ExportText(task) => &task.export,
|
||||
Self::Query(task) => &task.export,
|
||||
|
@ -118,6 +122,7 @@ impl ProjectTask {
|
|||
Self::ExportPdf { .. } => "pdf",
|
||||
Self::Preview(..) | Self::ExportSvgHtml { .. } | Self::ExportHtml { .. } => "html",
|
||||
Self::ExportMd { .. } => "md",
|
||||
Self::ExportTeX { .. } => "tex",
|
||||
Self::ExportText { .. } => "txt",
|
||||
Self::ExportSvg { .. } => "svg",
|
||||
Self::ExportPng { .. } => "png",
|
||||
|
@ -272,6 +277,23 @@ pub struct ExportHtmlTask {
|
|||
#[derive(Debug, Clone, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
pub struct ExportMarkdownTask {
|
||||
/// The processor to use for the markdown export.
|
||||
pub processor: Option<String>,
|
||||
/// The path of external assets directory.
|
||||
pub assets_path: Option<PathBuf>,
|
||||
/// The shared export arguments.
|
||||
#[serde(flatten)]
|
||||
pub export: ExportTask,
|
||||
}
|
||||
|
||||
/// An export TeX task specifier.
|
||||
#[derive(Debug, Clone, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
pub struct ExportTeXTask {
|
||||
/// The processor to use for the TeX export.
|
||||
pub processor: Option<String>,
|
||||
/// The path of external assets directory.
|
||||
pub assets_path: Option<PathBuf>,
|
||||
/// The shared export arguments.
|
||||
#[serde(flatten)]
|
||||
pub export: ExportTask,
|
||||
|
|
|
@ -10,12 +10,13 @@ use sync_ls::RequestId;
|
|||
use task::TraceParams;
|
||||
use tinymist_assets::TYPST_PREVIEW_HTML;
|
||||
use tinymist_project::{
|
||||
ExportHtmlTask, ExportMarkdownTask, ExportPdfTask, ExportPngTask, ExportSvgTask, ExportTask,
|
||||
ExportHtmlTask, ExportPdfTask, ExportPngTask, ExportSvgTask, ExportTask, ExportTeXTask,
|
||||
ExportTextTask, ExportTransform, PageSelection, Pages, ProjectTask, QueryTask,
|
||||
};
|
||||
use tinymist_query::package::PackageInfo;
|
||||
use tinymist_query::{LocalContextGuard, LspRange};
|
||||
use tinymist_std::error::prelude::*;
|
||||
use tinymist_task::ExportMarkdownTask;
|
||||
use typst::diag::{eco_format, EcoString, StrResult};
|
||||
use typst::syntax::package::{PackageSpec, VersionlessPackageSpec};
|
||||
use typst::syntax::{LinkedNode, Source};
|
||||
|
@ -35,12 +36,25 @@ struct ExportOpts {
|
|||
page: PageSelection,
|
||||
/// Whether to open the exported file(s) after the export is done.
|
||||
open: Option<bool>,
|
||||
// todo: we made a mistake that they will be snakecase, but they should be camelCase
|
||||
/// The creation timestamp for various outputs (in seconds).
|
||||
creation_timestamp: Option<String>,
|
||||
/// A PDF standard that Typst can enforce conformance with.
|
||||
pdf_standard: Option<Vec<PdfStandard>>,
|
||||
}
|
||||
|
||||
/// See [`ProjectTask`].
|
||||
#[derive(Debug, Clone, Default, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct ExportTypliteOpts {
|
||||
/// Whether to open the exported file(s) after the export is done.
|
||||
open: Option<bool>,
|
||||
/// The processor to use for the typlite export.
|
||||
processor: Option<String>,
|
||||
/// The path of external assets directory.
|
||||
assets_path: Option<PathBuf>,
|
||||
}
|
||||
|
||||
/// See [`ProjectTask`].
|
||||
#[derive(Debug, Clone, Default, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
|
@ -109,11 +123,31 @@ impl ServerState {
|
|||
req_id: RequestId,
|
||||
mut args: Vec<JsonValue>,
|
||||
) -> ScheduledResult {
|
||||
let opts = get_arg_or_default!(args[1] as ExportOpts);
|
||||
let opts = get_arg_or_default!(args[1] as ExportTypliteOpts);
|
||||
let export = self.config.export_task();
|
||||
self.export(
|
||||
req_id,
|
||||
ProjectTask::ExportMd(ExportMarkdownTask { export }),
|
||||
ProjectTask::ExportMd(ExportMarkdownTask {
|
||||
processor: opts.processor,
|
||||
assets_path: opts.assets_path,
|
||||
export,
|
||||
}),
|
||||
opts.open.unwrap_or_default(),
|
||||
args,
|
||||
)
|
||||
}
|
||||
|
||||
/// Export the current document as Tex file(s).
|
||||
pub fn export_tex(&mut self, req_id: RequestId, mut args: Vec<JsonValue>) -> ScheduledResult {
|
||||
let opts = get_arg_or_default!(args[1] as ExportTypliteOpts);
|
||||
let export = self.config.export_task();
|
||||
self.export(
|
||||
req_id,
|
||||
ProjectTask::ExportTeX(ExportTeXTask {
|
||||
processor: opts.processor,
|
||||
assets_path: opts.assets_path,
|
||||
export,
|
||||
}),
|
||||
opts.open.unwrap_or_default(),
|
||||
args,
|
||||
)
|
||||
|
|
|
@ -270,6 +270,7 @@ impl ServerState {
|
|||
.with_command_("tinymist.exportText", State::export_text)
|
||||
.with_command_("tinymist.exportHtml", State::export_html)
|
||||
.with_command_("tinymist.exportMarkdown", State::export_markdown)
|
||||
.with_command_("tinymist.exportTeX", State::export_tex)
|
||||
.with_command_("tinymist.exportQuery", State::export_query)
|
||||
.with_command("tinymist.exportAnsiHighlight", State::export_ansi_hl)
|
||||
.with_command("tinymist.exportAst", State::export_ast)
|
||||
|
|
|
@ -11,16 +11,16 @@ use tinymist_project::LspWorld;
|
|||
use tinymist_std::error::prelude::*;
|
||||
use tinymist_std::fs::paths::write_atomic;
|
||||
use tinymist_std::typst::TypstDocument;
|
||||
use tinymist_task::{get_page_selection, ExportTarget, PdfExport, TextExport};
|
||||
use tinymist_task::{get_page_selection, ExportMarkdownTask, ExportTarget, PdfExport, TextExport};
|
||||
use tokio::sync::mpsc;
|
||||
use typlite::Typlite;
|
||||
use typlite::{Format, Typlite};
|
||||
use typst::foundations::IntoValue;
|
||||
use typst::visualize::Color;
|
||||
|
||||
use super::{FutureFolder, SyncTaskFactory};
|
||||
use crate::project::{
|
||||
ApplyProjectTask, CompiledArtifact, EntryReader, ExportHtmlTask, ExportMarkdownTask,
|
||||
ExportPdfTask, ExportPngTask, ExportSvgTask, ExportTask as ProjectExportTask, ExportTextTask,
|
||||
ApplyProjectTask, CompiledArtifact, EntryReader, ExportHtmlTask, ExportPdfTask, ExportPngTask,
|
||||
ExportSvgTask, ExportTask as ProjectExportTask, ExportTeXTask, ExportTextTask,
|
||||
LspCompiledArtifact, ProjectTask, QueryTask, TaskWhen,
|
||||
};
|
||||
use crate::{actor::editor::EditorRequest, tool::word_count};
|
||||
|
@ -266,13 +266,42 @@ impl ExportTask {
|
|||
ExportText(ExportTextTask { export: _ }) => {
|
||||
Bytes::from_string(TextExport::run_on_doc(doc)?)
|
||||
}
|
||||
ExportMd(ExportMarkdownTask { export: _ }) => {
|
||||
ExportMd(ExportMarkdownTask {
|
||||
processor,
|
||||
assets_path,
|
||||
export: _,
|
||||
}) => {
|
||||
let conv = Typlite::new(Arc::new(graph.world().clone()))
|
||||
.with_format(Format::Md)
|
||||
.with_feature(typlite::TypliteFeat {
|
||||
processor,
|
||||
assets_path,
|
||||
..Default::default()
|
||||
})
|
||||
.convert()
|
||||
.map_err(|e| anyhow::anyhow!("failed to convert to markdown: {e}"))?;
|
||||
|
||||
Bytes::from_string(conv)
|
||||
}
|
||||
// todo: duplicated code with ExportMd
|
||||
ExportTeX(ExportTeXTask {
|
||||
processor,
|
||||
assets_path,
|
||||
export: _,
|
||||
}) => {
|
||||
log::info!("ExportTask({export_id}): exporting to TeX with processor {processor:?} and assets path {assets_path:?}");
|
||||
let conv = Typlite::new(Arc::new(graph.world().clone()))
|
||||
.with_format(Format::LaTeX)
|
||||
.with_feature(typlite::TypliteFeat {
|
||||
processor,
|
||||
assets_path,
|
||||
..Default::default()
|
||||
})
|
||||
.convert()
|
||||
.map_err(|e| anyhow::anyhow!("failed to convert to latex: {e}"))?;
|
||||
|
||||
Bytes::from_string(conv)
|
||||
}
|
||||
ExportSvg(ExportSvgTask { export }) => {
|
||||
let (is_first, merged_gap) = get_page_selection(&export)?;
|
||||
|
||||
|
|
|
@ -7,11 +7,10 @@ use reflexo_vec2svg::DefaultExportFeature;
|
|||
use tinymist_std::error::prelude::*;
|
||||
use tinymist_std::typst::TypstPagedDocument;
|
||||
use tinymist_task::{ExportTimings, TextExport};
|
||||
use typlite::Typlite;
|
||||
use typst::diag::SourceResult;
|
||||
use typlite::{Format, Typlite};
|
||||
|
||||
use crate::project::{
|
||||
ExportMarkdownTask, HtmlExport, LspCompilerFeat, PdfExport, PngExport, ProjectTask, SvgExport,
|
||||
ExportTeXTask, HtmlExport, LspCompilerFeat, PdfExport, PngExport, ProjectTask, SvgExport,
|
||||
TaskWhen,
|
||||
};
|
||||
use crate::world::base::{
|
||||
|
@ -45,7 +44,7 @@ impl ProjectCompilation {
|
|||
.transpose()?
|
||||
.map(|config| config.export.when);
|
||||
let md: Option<TaskWhen> = graph
|
||||
.get::<ConfigTask<ExportMarkdownTask>>()
|
||||
.get::<ConfigTask<ExportTeXTask>>()
|
||||
.transpose()?
|
||||
.map(|config| config.export.when);
|
||||
let text: Option<TaskWhen> = graph
|
||||
|
@ -146,7 +145,7 @@ impl WorldComputable<LspCompilerFeat> for ProjectExport {
|
|||
>(
|
||||
graph, when, &ExportWebSvgHtmlTask::default()
|
||||
),
|
||||
ExportMd(_config) => {
|
||||
ExportMd(..) => {
|
||||
let doc = graph.compute::<OptionDocumentTask<TypstPagedDocument>>()?;
|
||||
let doc = doc.as_ref();
|
||||
let n =
|
||||
|
@ -157,6 +156,17 @@ impl WorldComputable<LspCompilerFeat> for ProjectExport {
|
|||
|
||||
Ok(TypliteMdExport::run(graph)?.map(Bytes::from_string))
|
||||
}
|
||||
ExportTeX(..) => {
|
||||
let doc = graph.compute::<OptionDocumentTask<TypstPagedDocument>>()?;
|
||||
let doc = doc.as_ref();
|
||||
let n =
|
||||
ExportTimings::needs_run(&graph.snap, when, doc.as_deref()).unwrap_or(true);
|
||||
if !n {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
Ok(TypliteTeXExport::run(graph)?.map(Bytes::from_string))
|
||||
}
|
||||
ExportText(config) => Self::export_string::<_, TextExport>(graph, when, config),
|
||||
Query(..) => todo!(),
|
||||
}
|
||||
|
@ -174,22 +184,42 @@ impl WorldComputable<LspCompilerFeat> for ProjectExport {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct TypliteMdExport(pub Option<SourceResult<String>>);
|
||||
pub struct TypliteExport<const FORMAT: char>;
|
||||
|
||||
impl TypliteMdExport {
|
||||
const fn typlite_format(f: char) -> Format {
|
||||
match f {
|
||||
'm' => Format::Md,
|
||||
'x' => Format::LaTeX,
|
||||
_ => panic!("unsupported format for TypliteExport"),
|
||||
}
|
||||
}
|
||||
|
||||
const fn typlite_name(f: char) -> &'static str {
|
||||
match f {
|
||||
'm' => "Markdown",
|
||||
'x' => "LaTeX",
|
||||
_ => panic!("unsupported format for TypliteExport"),
|
||||
}
|
||||
}
|
||||
|
||||
impl<const F: char> TypliteExport<F> {
|
||||
fn run(graph: &Arc<WorldComputeGraph<LspCompilerFeat>>) -> Result<Option<String>> {
|
||||
let conv = Typlite::new(Arc::new(graph.snap.world.clone()))
|
||||
.with_format(typlite_format(F))
|
||||
.convert()
|
||||
.map_err(|e| anyhow::anyhow!("failed to convert to markdown: {e}"))?;
|
||||
.map_err(|e| anyhow::anyhow!("failed to convert to {}: {e}", typlite_name(F)))?;
|
||||
|
||||
Ok(Some(conv.to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
impl WorldComputable<LspCompilerFeat> for TypliteMdExport {
|
||||
impl<const F: char> WorldComputable<LspCompilerFeat> for TypliteExport<F> {
|
||||
type Output = Option<String>;
|
||||
|
||||
fn compute(graph: &Arc<WorldComputeGraph<LspCompilerFeat>>) -> Result<Self::Output> {
|
||||
Self::run(graph)
|
||||
}
|
||||
}
|
||||
|
||||
pub type TypliteMdExport = TypliteExport<'m'>;
|
||||
pub type TypliteTeXExport = TypliteExport<'x'>;
|
||||
|
|
|
@ -337,6 +337,9 @@ fn shell_build_script(shell: Shell) -> Result<String> {
|
|||
ProjectTask::ExportMd(..) => {
|
||||
cmd.push("--format=md");
|
||||
}
|
||||
ProjectTask::ExportTeX(..) => {
|
||||
cmd.push("--format=tex");
|
||||
}
|
||||
ProjectTask::ExportPng(..) => {
|
||||
cmd.push("--format=png");
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ use typst::html::HtmlDocument;
|
|||
use typst::World;
|
||||
use typst_syntax::VirtualPath;
|
||||
|
||||
use crate::common::Format;
|
||||
pub use crate::common::Format;
|
||||
use crate::parser::HtmlToAstParser;
|
||||
use crate::writer::WriterFactory;
|
||||
use typst_syntax::FileId;
|
||||
|
|
|
@ -35,18 +35,16 @@ pub struct CompileArgs {
|
|||
/// ## `article` function
|
||||
///
|
||||
/// The article function is used to wrap the typst content during
|
||||
/// compilation.
|
||||
/// compilation. It resembles the regular typst show rule function, like
|
||||
/// `#show: article`.
|
||||
///
|
||||
/// typlite exactly uses the `#article` function to process the content as
|
||||
/// follow:
|
||||
///
|
||||
/// ```typst
|
||||
/// #import "@local/processor": article
|
||||
/// #import "@local/ieee-tex:0.1.0": 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<String>,
|
||||
}
|
||||
|
|
|
@ -69,7 +69,6 @@ Enable or disable semantic tokens (LSP syntax highlighting)
|
|||
Enable or disable lint checks. Note: restarting the editor is required to change this setting.
|
||||
|
||||
- **Type**: `boolean`
|
||||
- **Default**: `false`
|
||||
|
||||
## `tinymist.lint.when`
|
||||
|
||||
|
@ -182,10 +181,9 @@ Sets the indent size (using space) for the formatter.
|
|||
|
||||
## `tinymist.formatterProseWrap`
|
||||
|
||||
Controls how the formatter handles prose line wrapping. Prose wrapping means inserting line breaks when a line exceeds the specified print width.
|
||||
Controls how the formatter handles prose line wrapping. If enabled, the formatter will insert hard line breaks at the specified print width. If disabled, the formatter keeps the original line breaks and spaces.
|
||||
|
||||
- **Type**: `boolean`
|
||||
- **Default**: `false`
|
||||
|
||||
## `tinymist.showExportFileIn`
|
||||
|
||||
|
|
1
editors/vscode/e2e-workspaces/ieee-paper/.gitignore
vendored
Normal file
1
editors/vscode/e2e-workspaces/ieee-paper/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
target
|
|
@ -6,11 +6,12 @@
|
|||
"type": "typst",
|
||||
"command": "export",
|
||||
"export": {
|
||||
"format": ["latex"],
|
||||
"format": ["tex"],
|
||||
// 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"
|
||||
"processor": "/ieee-tex.typ",
|
||||
"assetsPath": "${workspaceFolder}/target"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
|
@ -1,17 +1,20 @@
|
|||
|
||||
TODO: This is still in development. We have only integrated features to the server but not yet add exporter options to VSCode Tasks.
|
||||
|
||||
# Sample workspace to Make and Prepare for Submitting IEEE Papers
|
||||
|
||||
This workspace is designed to help you create and prepare IEEE papers using Typst. Hope this could help you get started with writing your paper in Typst until IEEE provides official support for Typst.
|
||||
|
||||
## Usage
|
||||
|
||||
Click and focus the document that you want to export, then run the following tasks in VSCode:
|
||||
|
||||
- "Export to LaTeX (IEEE)" - Exports the Typst document to LaTeX format.
|
||||
- "Export to Word (IEEE)" - Exports the Typst document to Word format.
|
||||
|
||||
## How does it work?
|
||||
|
||||
It converts typst main file to *unstyled* body markup and PDF Figures by HTML Export. The `main.tex` then glues official IEEE templates together with the body markup to produce a final PDF that is ready for submission.
|
||||
It converts typst main file to _unstyled_ body markup and PDF Figures by HTML Export. The [`ieee-tex.typ`](./ieee-tex.typ) then glues official IEEE templates together with the body markup to produce a final PDF that is ready for submission.
|
||||
|
||||
## Task Samples
|
||||
|
||||
See [Tasks](./.vscode/tasks.json) for a list of tasks that can be run in this workspace.
|
||||
|
||||
- "Export to LaTeX (IEEE)" - Exports the Typst document to LaTeX format.
|
||||
- "Export to Word (IEEE)" - Exports the Typst document to Word format.
|
||||
|
|
|
@ -1,10 +1,19 @@
|
|||
|
||||
// A xml element that writes raw content to output directly.
|
||||
#let verbatim(body) = {
|
||||
show raw.where(lang: "tex"): it => html.elem("m1verbatim", attrs: (src: it.text))
|
||||
body
|
||||
}
|
||||
|
||||
/// Shortcut for verbatim.
|
||||
///
|
||||
/// - body (string): The body of the verbatim block.
|
||||
#let tex(body) = verbatim(raw(lang: "tex", body))
|
||||
|
||||
#let prelude1 = verbatim(```tex
|
||||
%% Generated by typlite
|
||||
%% Please report to https://github.com/Myriad-Dreamin/tinymist if you find any bugs.
|
||||
|
||||
%% bare_conf_compsoc.tex
|
||||
%% V1.4b
|
||||
%% 2015/08/26
|
||||
|
@ -344,17 +353,13 @@
|
|||
```)
|
||||
#let paper-title = context {
|
||||
let title = state("tex:title", "").final()
|
||||
verbatim[
|
||||
```tex
|
||||
\title{
|
||||
```
|
||||
]
|
||||
verbatim(```tex
|
||||
\title{
|
||||
```)
|
||||
title
|
||||
verbatim[
|
||||
```tex
|
||||
}
|
||||
```
|
||||
]
|
||||
verbatim(```tex
|
||||
}
|
||||
```)
|
||||
}
|
||||
#let paper-authors = context {
|
||||
let to-text(author, field) = {
|
||||
|
@ -371,47 +376,38 @@
|
|||
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}"
|
||||
}
|
||||
},
|
||||
),
|
||||
)
|
||||
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"))
|
||||
let _and = tex("\n\and\n")
|
||||
|
||||
verbatim[
|
||||
```tex
|
||||
verbatim(```tex
|
||||
|
||||
% author names and affiliations
|
||||
% use a multiple column layout for up to three different
|
||||
% affiliations
|
||||
\author{
|
||||
```
|
||||
]
|
||||
% author names and affiliations
|
||||
% use a multiple column layout for up to three different
|
||||
% affiliations
|
||||
\author{
|
||||
```)
|
||||
authors.join(_and)
|
||||
verbatim[
|
||||
```tex
|
||||
}
|
||||
```
|
||||
]
|
||||
verbatim(```tex
|
||||
}
|
||||
```)
|
||||
}
|
||||
#let prelude2 = verbatim(```tex
|
||||
|
||||
|
@ -454,20 +450,15 @@
|
|||
```)
|
||||
#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}
|
||||
```
|
||||
]
|
||||
verbatim(```tex
|
||||
% As a general rule, do not put math, special symbols or citations
|
||||
% in the abstract
|
||||
\begin{abstract}
|
||||
```)
|
||||
abstract
|
||||
verbatim[
|
||||
|
||||
```tex
|
||||
\end{abstract}
|
||||
```
|
||||
]
|
||||
verbatim(```tex
|
||||
\end{abstract}
|
||||
```)
|
||||
}
|
||||
#let prelude3 = verbatim(```tex
|
||||
|
||||
|
@ -486,39 +477,32 @@
|
|||
```)
|
||||
#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}}
|
||||
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
|
||||
% 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
|
||||
"}"
|
||||
},
|
||||
),
|
||||
)
|
||||
% 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)
|
||||
```)
|
||||
tex(if bibliography-state == none {
|
||||
"%\bibliography{IEEEabrv,../bib/paper}"
|
||||
} else {
|
||||
"%\bibliography{IEEEabrv,"
|
||||
bibliography-state
|
||||
"}"
|
||||
})
|
||||
}
|
||||
#let postlude = verbatim(```tex
|
||||
|
||||
|
|
|
@ -105,7 +105,7 @@
|
|||
"description": "Arguments for `export` command.",
|
||||
"properties": {
|
||||
"format": {
|
||||
"description": "The format(s) to export the document to. Defaults to `pdf`.",
|
||||
"description": "The format(s) to export the document to.",
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string",
|
||||
|
@ -116,6 +116,7 @@
|
|||
"svg",
|
||||
"html",
|
||||
"markdown",
|
||||
"tex",
|
||||
"text",
|
||||
"query",
|
||||
"pdfpc"
|
||||
|
@ -126,6 +127,7 @@
|
|||
"SVG",
|
||||
"HTML",
|
||||
"Markdown",
|
||||
"TeX",
|
||||
"Plain Text",
|
||||
"Query Result",
|
||||
"Pdfpc (From Query)"
|
||||
|
@ -137,13 +139,14 @@
|
|||
"description": "The formats to export the document to.",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"description": "The format to export the document to. Defaults to `pdf`.",
|
||||
"description": "The format to export the document to.",
|
||||
"enum": [
|
||||
"pdf",
|
||||
"png",
|
||||
"svg",
|
||||
"html",
|
||||
"markdown",
|
||||
"tex",
|
||||
"text",
|
||||
"query",
|
||||
"pdfpc"
|
||||
|
@ -154,6 +157,7 @@
|
|||
"SVG",
|
||||
"HTML",
|
||||
"Markdown",
|
||||
"TeX",
|
||||
"Plain Text",
|
||||
"Query Result",
|
||||
"Pdfpc (From Query)"
|
||||
|
@ -268,6 +272,51 @@
|
|||
"query.one": {
|
||||
"type": "boolean",
|
||||
"description": "Whether to only return one result. Defaults to `false`."
|
||||
},
|
||||
"processor": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
],
|
||||
"description": "The processor to use for the markdown or TeX export.",
|
||||
"default": null
|
||||
},
|
||||
"tex.processor": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
],
|
||||
"description": "The processor to use for the TeX export.",
|
||||
"default": null
|
||||
},
|
||||
"markdown.processor": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
],
|
||||
"description": "The processor to use for the markdown export.",
|
||||
"default": null
|
||||
},
|
||||
"assetsPath": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
],
|
||||
"description": "The path to output assets to use for the markdown or TeX export.",
|
||||
"default": null
|
||||
},
|
||||
"tex.assetsPath": {
|
||||
"type": "string",
|
||||
"description": "The path to output assets to use for the TeX export.",
|
||||
"default": "target"
|
||||
},
|
||||
"markdown.assetsPath": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
],
|
||||
"description": "The path to output assets to use for the markdown export.",
|
||||
"default": null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ import { tinymist } from "../lsp";
|
|||
import { IContext } from "../context";
|
||||
import { commands } from "vscode";
|
||||
|
||||
export type ExportKind = "Pdf" | "Html" | "Svg" | "Png" | "Markdown" | "Text" | "Query";
|
||||
export type ExportKind = "Pdf" | "Html" | "Svg" | "Png" | "Markdown" | "TeX" | "Text" | "Query";
|
||||
|
||||
export function exportActivate(context: IContext) {
|
||||
context.subscriptions.push(
|
||||
|
@ -51,6 +51,11 @@ export const quickExports: QuickExportFormatMeta[] = [
|
|||
description: l10nMsg("Export as Markdown"),
|
||||
exportKind: "Markdown",
|
||||
},
|
||||
{
|
||||
label: "TeX",
|
||||
description: l10nMsg("Export as TeX"),
|
||||
exportKind: "TeX",
|
||||
},
|
||||
{
|
||||
label: "Text",
|
||||
description: l10nMsg("Export as Text"),
|
||||
|
@ -103,6 +108,23 @@ async function askAndRun<T>(
|
|||
return;
|
||||
}
|
||||
|
||||
if (picked.exportKind === "TeX") {
|
||||
picked.extraOpts = picked.extraOpts || {};
|
||||
const processor = await vscode.window.showInputBox({
|
||||
title: l10nMsg("TeX processor"),
|
||||
placeHolder: l10nMsg(
|
||||
"A typst file help export to TeX, e.g. `/ieee-tex.typ` or `@local/ieee-tex:0.1.0`",
|
||||
),
|
||||
prompt: l10nMsg(
|
||||
"Hint: you can create and find local packages in the sidebar. See https://github.com/Myriad-Dreamin/tinymist/tree/bc15eb55cee9f9b048aafd5f22472894961a1f51/editors/vscode/e2e-workspaces/ieee-paper for more information.",
|
||||
),
|
||||
});
|
||||
|
||||
if (processor) {
|
||||
picked.extraOpts.processor = processor;
|
||||
}
|
||||
}
|
||||
|
||||
return cb(picked);
|
||||
}
|
||||
|
||||
|
|
|
@ -9,16 +9,21 @@ interface ExportArgs {
|
|||
format: ExportFormat | ExportFormat[];
|
||||
inputPath: string;
|
||||
outputPath: string;
|
||||
|
||||
"pdf.creationTimestamp"?: string | null;
|
||||
"png.ppi"?: number;
|
||||
|
||||
fill?: string;
|
||||
"png.fill"?: string;
|
||||
|
||||
merged?: boolean;
|
||||
"svg.merged"?: boolean;
|
||||
"png.merged"?: boolean;
|
||||
|
||||
"merged.gap"?: string;
|
||||
"png.merged.gap"?: string;
|
||||
"svg.merged.gap"?: string;
|
||||
|
||||
"query.format"?: string;
|
||||
"query.outputExtension"?: string;
|
||||
"query.strict"?: boolean;
|
||||
|
@ -26,6 +31,13 @@ interface ExportArgs {
|
|||
"query.selector"?: string;
|
||||
"query.field"?: string;
|
||||
"query.one"?: boolean;
|
||||
|
||||
processor?: string;
|
||||
"markdown.processor"?: string;
|
||||
"tex.processor"?: string;
|
||||
assetsPath?: string;
|
||||
"markdown.assetsPath"?: string;
|
||||
"tex.assetsPath"?: string;
|
||||
}
|
||||
|
||||
export const runExport = (def: vscode.TaskDefinition) => {
|
||||
|
@ -140,10 +152,22 @@ const provideFormats = (exportArgs: ExportArgs, ops = exportOps(exportArgs)) =>
|
|||
},
|
||||
markdown: {
|
||||
opts() {
|
||||
return {};
|
||||
return {
|
||||
processor: exportArgs["markdown.processor"] || exportArgs["processor"],
|
||||
assetsPath: exportArgs["markdown.assetsPath"] || exportArgs["assetsPath"],
|
||||
};
|
||||
},
|
||||
export: tinymist.exportMarkdown,
|
||||
},
|
||||
tex: {
|
||||
opts() {
|
||||
return {
|
||||
processor: exportArgs["tex.processor"] || exportArgs["processor"],
|
||||
assetsPath: exportArgs["tex.assetsPath"] || exportArgs["assetsPath"],
|
||||
};
|
||||
},
|
||||
export: tinymist.exportTeX,
|
||||
},
|
||||
text: {
|
||||
opts() {
|
||||
return {};
|
||||
|
|
|
@ -325,6 +325,7 @@ export class LanguageState {
|
|||
exportPng = exportCommand("tinymist.exportPng");
|
||||
exportHtml = exportCommand("tinymist.exportHtml");
|
||||
exportMarkdown = exportCommand("tinymist.exportMarkdown");
|
||||
exportTeX = exportCommand("tinymist.exportTeX");
|
||||
exportText = exportCommand("tinymist.exportText");
|
||||
exportQuery = exportCommand("tinymist.exportQuery");
|
||||
exportAnsiHighlight = exportCommand("tinymist.exportAnsiHighlight");
|
||||
|
|
|
@ -5,6 +5,10 @@
|
|||
en = " (Preview)"
|
||||
zh = " (预览)"
|
||||
|
||||
["A typst file help export to TeX, e.g. `/ieee-tex.typ` or `@local/ieee-tex:0.1.0`"]
|
||||
en = "A typst file help export to TeX, e.g. `/ieee-tex.typ` or `@local/ieee-tex:0.1.0`"
|
||||
zh = "提供一个帮助导出为 TeX 的 typst 文件,例如 `/ieee-tex.typ` 或 `@local/ieee-tex:0.1.0`"
|
||||
|
||||
["Export as HTML"]
|
||||
en = "Export as HTML"
|
||||
zh = "导出为 HTML"
|
||||
|
@ -25,6 +29,9 @@ zh = "导出为 PNG (并更新 tasks.json)"
|
|||
en = "Export as SVG (and update tasks.json)"
|
||||
zh = "导出为 SVG (并更新 tasks.json)"
|
||||
|
||||
["Export as TeX"]
|
||||
en = "Export as TeX"
|
||||
|
||||
["Export as Text"]
|
||||
en = "Export as Text"
|
||||
zh = "导出为纯文本文件"
|
||||
|
@ -45,6 +52,10 @@ zh = "导出首页为单个 PNG"
|
|||
en = "Export the first page as a single SVG"
|
||||
zh = "导出首页为单个 SVG"
|
||||
|
||||
["Hint: you can create and find local packages in the sidebar. See https://github.com/Myriad-Dreamin/tinymist/tree/bc15eb55cee9f9b048aafd5f22472894961a1f51/editors/vscode/e2e-workspaces/ieee-paper for more information."]
|
||||
en = "Hint: you can create and find local packages in the sidebar. See https://github.com/Myriad-Dreamin/tinymist/tree/bc15eb55cee9f9b048aafd5f22472894961a1f51/editors/vscode/e2e-workspaces/ieee-paper for more information."
|
||||
zh = "提示:您可以在侧边栏中创建和查找本地包。有关更多信息,请参见 https://github.com/Myriad-Dreamin/tinymist/tree/bc15eb55cee9f9b048aafd5f22472894961a1f51/editors/vscode/e2e-workspaces/ieee-paper。"
|
||||
|
||||
["PNG (First Page)"]
|
||||
en = "PNG (First Page)"
|
||||
zh = "PNG (首页)"
|
||||
|
@ -87,3 +98,7 @@ zh = "SVG (合并)"
|
|||
["SVG (Task)"]
|
||||
en = "SVG (Task)"
|
||||
zh = "SVG (任务)"
|
||||
|
||||
["TeX processor"]
|
||||
en = "TeX processor"
|
||||
zh = "TeX 导出的处理脚本"
|
||||
|
|
|
@ -377,7 +377,7 @@ fn e2e() {
|
|||
});
|
||||
|
||||
let hash = replay_log(&tinymist_binary, &root.join("neovim"));
|
||||
insta::assert_snapshot!(hash, @"siphash128_13:3c4096d8e71eddb2b5a832f0918bdafa");
|
||||
insta::assert_snapshot!(hash, @"siphash128_13:7e4a9cdceda2bf7409ec907108d0f927");
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -388,7 +388,7 @@ fn e2e() {
|
|||
});
|
||||
|
||||
let hash = replay_log(&tinymist_binary, &root.join("vscode"));
|
||||
insta::assert_snapshot!(hash, @"siphash128_13:4a6d0b2d59178ca4e600985e4cef545");
|
||||
insta::assert_snapshot!(hash, @"siphash128_13:b18199e96fd07287ead7caa2b33f777");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue