summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2024-12-05 16:25:18 +0100
committerGitHub <noreply@github.com>2024-12-05 15:25:18 +0000
commitcaa72f4ec2401c275ddd3d8794dcf0bfdf9697a8 (patch)
tree490fcf0e7d7e3deb947d377109d886ecb579081a
parent8e4f5f21e0e52fb4ac88ab769e585af811d9b56e (diff)
Put HTTP server behind on-by-default feature flag (#5532)
-rw-r--r--.github/workflows/ci.yml1
-rw-r--r--crates/typst-cli/Cargo.toml7
-rw-r--r--crates/typst-cli/src/args.rs40
-rw-r--r--crates/typst-cli/src/compile.rs72
-rw-r--r--crates/typst-cli/src/main.rs1
-rw-r--r--crates/typst-cli/src/server.rs7
-rw-r--r--crates/typst-cli/src/watch.rs1
7 files changed, 79 insertions, 50 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 9ddb309b..268fd93c 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -64,6 +64,7 @@ jobs:
components: clippy, rustfmt
- uses: Swatinem/rust-cache@v2
- run: cargo clippy --workspace --all-targets --all-features
+ - run: cargo clippy --workspace --all-targets --no-default-features
- run: cargo fmt --check --all
- run: cargo doc --workspace --no-deps
diff --git a/crates/typst-cli/Cargo.toml b/crates/typst-cli/Cargo.toml
index c859f043..7e9b93f9 100644
--- a/crates/typst-cli/Cargo.toml
+++ b/crates/typst-cli/Cargo.toml
@@ -50,7 +50,7 @@ shell-escape = { workspace = true }
sigpipe = { workspace = true }
tar = { workspace = true }
tempfile = { workspace = true }
-tiny_http = { workspace = true }
+tiny_http = { workspace = true, optional = true }
toml = { workspace = true }
ureq = { workspace = true }
xz2 = { workspace = true, optional = true }
@@ -65,11 +65,14 @@ color-print = { workspace = true }
semver = { workspace = true }
[features]
-default = ["embed-fonts"]
+default = ["embed-fonts", "http-server"]
# Embeds some fonts into the binary, see typst-kit
embed-fonts = ["typst-kit/embed-fonts"]
+# Enables the built-in HTTP server for `typst watch` and HTML export.
+http-server = ["dep:tiny_http"]
+
# Permits the CLI to update itself without a package manager.
self-update = ["dep:self-replace", "dep:xz2", "dep:zip"]
diff --git a/crates/typst-cli/src/args.rs b/crates/typst-cli/src/args.rs
index ead93236..83c4c8f9 100644
--- a/crates/typst-cli/src/args.rs
+++ b/crates/typst-cli/src/args.rs
@@ -98,20 +98,10 @@ pub struct WatchCommand {
#[clap(flatten)]
pub args: CompileArgs,
- /// Disables the built-in HTTP server for HTML export.
- #[clap(long)]
- pub no_serve: bool,
-
- /// Disables the injected live reload script for HTML export. The HTML that
- /// is written to disk isn't affected either way.
- #[clap(long)]
- pub no_reload: bool,
-
- /// The port where HTML is served.
- ///
- /// Defaults to the first free port in the range 3000-3005.
- #[clap(long)]
- pub port: Option<u16>,
+ /// Arguments for the HTTP server.
+ #[cfg(feature = "http-server")]
+ #[clap(flatten)]
+ pub server: ServerArgs,
}
/// Initializes a new project from a template.
@@ -354,7 +344,7 @@ pub struct PackageArgs {
pub package_cache_path: Option<PathBuf>,
}
-/// Common arguments to customize available fonts
+/// Common arguments to customize available fonts.
#[derive(Debug, Clone, Parser)]
pub struct FontArgs {
/// Adds additional directories that are recursively searched for fonts.
@@ -375,6 +365,26 @@ pub struct FontArgs {
pub ignore_system_fonts: bool,
}
+/// Arguments for the HTTP server.
+#[cfg(feature = "http-server")]
+#[derive(Debug, Clone, Parser)]
+pub struct ServerArgs {
+ /// Disables the built-in HTTP server for HTML export.
+ #[clap(long)]
+ pub no_serve: bool,
+
+ /// Disables the injected live reload script for HTML export. The HTML that
+ /// is written to disk isn't affected either way.
+ #[clap(long)]
+ pub no_reload: bool,
+
+ /// The port where HTML is served.
+ ///
+ /// Defaults to the first free port in the range 3000-3005.
+ #[clap(long)]
+ pub port: Option<u16>,
+}
+
macro_rules! display_possible_values {
($ty:ty) => {
impl Display for $ty {
diff --git a/crates/typst-cli/src/compile.rs b/crates/typst-cli/src/compile.rs
index 01a6de1b..3aa3aa3b 100644
--- a/crates/typst-cli/src/compile.rs
+++ b/crates/typst-cli/src/compile.rs
@@ -1,4 +1,4 @@
-use std::ffi::OsString;
+use std::ffi::OsStr;
use std::fs::{self, File};
use std::io::{self, Write};
use std::path::{Path, PathBuf};
@@ -23,6 +23,7 @@ use crate::args::{
CompileArgs, CompileCommand, DiagnosticFormat, Input, Output, OutputFormat,
PdfStandard, WatchCommand,
};
+#[cfg(feature = "http-server")]
use crate::server::HtmlServer;
use crate::timings::Timer;
@@ -72,6 +73,7 @@ pub struct CompileConfig {
/// watch` sessions with images.
pub export_cache: ExportCache,
/// Server for `typst watch` to HTML.
+ #[cfg(feature = "http-server")]
pub server: Option<HtmlServer>,
}
@@ -139,17 +141,18 @@ impl CompileConfig {
PdfStandards::new(&list)?
};
- let mut server = None;
- let mut watching = false;
- if let Some(command) = watch {
- watching = true;
- if output_format == OutputFormat::Html && !command.no_serve {
- server = Some(HtmlServer::new(&input, command.port, !command.no_reload)?);
+ #[cfg(feature = "http-server")]
+ let server = match watch {
+ Some(command)
+ if output_format == OutputFormat::Html && !command.server.no_serve =>
+ {
+ Some(HtmlServer::new(&input, &command.server)?)
}
- }
+ _ => None,
+ };
Ok(Self {
- watching,
+ watching: watch.is_some(),
input,
output,
output_format,
@@ -161,6 +164,7 @@ impl CompileConfig {
diagnostic_format: args.process.diagnostic_format,
open: args.open.clone(),
export_cache: ExportCache::new(),
+ #[cfg(feature = "http-server")]
server,
})
}
@@ -241,6 +245,7 @@ fn export_html(document: &HtmlDocument, config: &CompileConfig) -> SourceResult<
let html = typst_html::html(document)?;
let result = config.output.write(html.as_bytes());
+ #[cfg(feature = "http-server")]
if let Some(server) = &config.server {
server.update(html);
}
@@ -556,30 +561,37 @@ fn write_make_deps(world: &mut SystemWorld, config: &CompileConfig) -> StrResult
})
}
-/// Opens the output if desired, with:
-/// - The default file viewer if `open` is `None`.
-/// - The given viewer provided by `open` if it is `Some`.
-///
-/// If the file could not be opened, an error is returned.
+/// Opens the output if desired.
fn open_output(config: &mut CompileConfig) -> StrResult<()> {
- let Some(open) = config.open.take() else { return Ok(()) };
-
- let path = if let Some(server) = &config.server {
- OsString::from(format!("http://{}", server.addr()))
- } else if let Output::Path(path) = &config.output {
- // Some resource openers require the path to be canonicalized.
- path.canonicalize()
- .map_err(|err| eco_format!("failed to canonicalize path ({err})"))?
- .into_os_string()
- } else {
- return Ok(());
- };
+ let Some(viewer) = config.open.take() else { return Ok(()) };
- if let Some(app) = &open {
- open::with_detached(&path, app)
- .map_err(|err| eco_format!("failed to open file with {} ({})", app, err))
+ #[cfg(feature = "http-server")]
+ if let Some(server) = &config.server {
+ let url = format!("http://{}", server.addr());
+ return open_path(OsStr::new(&url), viewer.as_deref());
+ }
+
+ // Can't open stdout.
+ let Output::Path(path) = &config.output else { return Ok(()) };
+
+ // Some resource openers require the path to be canonicalized.
+ let path = path
+ .canonicalize()
+ .map_err(|err| eco_format!("failed to canonicalize path ({err})"))?;
+
+ open_path(path.as_os_str(), viewer.as_deref())
+}
+
+/// Opens the given file using:
+///
+/// - The default file viewer if `app` is `None`.
+/// - The given viewer provided by `app` if it is `Some`.
+fn open_path(path: &OsStr, viewer: Option<&str>) -> StrResult<()> {
+ if let Some(viewer) = viewer {
+ open::with_detached(path, viewer)
+ .map_err(|err| eco_format!("failed to open file with {} ({})", viewer, err))
} else {
- open::that_detached(&path).map_err(|err| {
+ open::that_detached(path).map_err(|err| {
let openers = open::commands(path)
.iter()
.map(|command| command.get_program().to_string_lossy())
diff --git a/crates/typst-cli/src/main.rs b/crates/typst-cli/src/main.rs
index 610f89c0..14f8a665 100644
--- a/crates/typst-cli/src/main.rs
+++ b/crates/typst-cli/src/main.rs
@@ -6,6 +6,7 @@ mod greet;
mod init;
mod package;
mod query;
+#[cfg(feature = "http-server")]
mod server;
mod terminal;
mod timings;
diff --git a/crates/typst-cli/src/server.rs b/crates/typst-cli/src/server.rs
index b3ce83f8..8910e032 100644
--- a/crates/typst-cli/src/server.rs
+++ b/crates/typst-cli/src/server.rs
@@ -7,7 +7,7 @@ use parking_lot::{Condvar, Mutex, MutexGuard};
use tiny_http::{Header, Request, Response, StatusCode};
use typst::diag::{bail, StrResult};
-use crate::args::Input;
+use crate::args::{Input, ServerArgs};
/// Serves HTML with live reload.
pub struct HtmlServer {
@@ -17,8 +17,9 @@ pub struct HtmlServer {
impl HtmlServer {
/// Create a new HTTP server that serves live HTML.
- pub fn new(input: &Input, port: Option<u16>, reload: bool) -> StrResult<Self> {
- let (addr, server) = start_server(port)?;
+ pub fn new(input: &Input, args: &ServerArgs) -> StrResult<Self> {
+ let reload = !args.no_reload;
+ let (addr, server) = start_server(args.port)?;
let placeholder = PLACEHOLDER_HTML.replace("{INPUT}", &input.to_string());
let bucket = Arc::new(Bucket::new(placeholder));
diff --git a/crates/typst-cli/src/watch.rs b/crates/typst-cli/src/watch.rs
index e62746df..91132fc3 100644
--- a/crates/typst-cli/src/watch.rs
+++ b/crates/typst-cli/src/watch.rs
@@ -293,6 +293,7 @@ impl Status {
out.reset()?;
writeln!(out, " {}", config.output)?;
+ #[cfg(feature = "http-server")]
if let Some(server) = &config.server {
out.set_color(&color)?;
write!(out, "serving at")?;