From c8585161875a30bb8a88571e9a9b2febf35fb340 Mon Sep 17 00:00:00 2001 From: Myriad-Dreamin Date: Wed, 13 Dec 2023 14:22:53 +0800 Subject: [PATCH] dev: decouple hyper --- src/args.rs | 30 +++++++++++++------------- src/lib.rs | 54 ++--------------------------------------------- src/main.rs | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 76 insertions(+), 69 deletions(-) diff --git a/src/args.rs b/src/args.rs index 204d5f90..f63c8de5 100644 --- a/src/args.rs +++ b/src/args.rs @@ -19,10 +19,6 @@ const ENV_PATH_SEP: char = if cfg!(windows) { ';' } else { ':' }; #[derive(Debug, Clone, Parser)] pub struct PreviewArgs { - /// Preview mode - #[clap(long = "preview-mode", default_value = "document", value_name = "MODE")] - pub preview_mode: PreviewMode, - /// Data plane server will bind to this address #[clap( long = "data-plane-host", @@ -41,6 +37,21 @@ pub struct PreviewArgs { )] pub control_plane_host: String, + /// Only render visible part of the document. This can improve performance but still being experimental. + #[clap(long = "partial-rendering")] + pub enable_partial_rendering: bool, +} + +#[derive(Debug, Clone, Parser)] +#[clap(name = "typst-preview", author, version, about, long_version(LONG_VERSION.as_str()))] +pub struct CliArguments { + #[clap(flatten)] + pub preview: PreviewArgs, + + /// Preview mode + #[clap(long = "preview-mode", default_value = "document", value_name = "MODE")] + pub preview_mode: PreviewMode, + /// Host for the preview server #[clap( long = "host", @@ -54,17 +65,6 @@ pub struct PreviewArgs { #[clap(long = "no-open")] pub dont_open_in_browser: bool, - /// Only render visible part of the document. This can improve performance but still being experimental. - #[clap(long = "partial-rendering")] - pub enable_partial_rendering: bool, -} - -#[derive(Debug, Clone, Parser)] -#[clap(name = "typst-preview", author, version, about, long_version(LONG_VERSION.as_str()))] -pub struct CliArguments { - #[clap(flatten)] - pub preview: PreviewArgs, - /// Add additional directories to search for fonts #[clap(long = "font-path", value_name = "DIR", action = ArgAction::Append, env = "TYPST_FONT_PATHS", value_delimiter = ENV_PATH_SEP)] pub font_paths: Vec, diff --git a/src/lib.rs b/src/lib.rs index 53ff9947..68434fa2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,11 +6,7 @@ mod outline; use std::{collections::HashMap, path::PathBuf, sync::Arc}; use futures::SinkExt; -use hyper::{ - service::{make_service_fn, service_fn}, - Error, -}; -use log::{error, info}; +use log::info; use serde::Deserialize; use tokio::net::{TcpListener, TcpStream}; use tokio_tungstenite::tungstenite::Message; @@ -71,20 +67,14 @@ pub struct MemoryFilesShort { const HTML: &str = include_str!("../addons/vscode/out/frontend/index.html"); pub struct Previewer { - frontend_html: ImmutStr, frontend_html_factory: Box ImmutStr>, data_plane_handle: tokio::task::JoinHandle<()>, control_plane_handle: tokio::task::JoinHandle<()>, } impl Previewer { - /// Get the HTML for the frontend (with set preview mode) - pub fn frontend_html(&self) -> ImmutStr { - self.frontend_html.clone() - } - /// Get the HTML for the frontend by a given preview mode - pub fn frontend_html_in_mode(&self, mode: PreviewMode) -> ImmutStr { + pub fn frontend_html(&self, mode: PreviewMode) -> ImmutStr { (self.frontend_html_factory)(mode) } @@ -230,48 +220,8 @@ pub async fn preview(arguments: PreviewArgs, compiler_driver: CompileDriver) -> ) .into() }); - let mode = arguments.preview_mode; - let frontend_html = frontend_html_factory(mode); - let make_service = make_service_fn(|_| { - let html = frontend_html.clone(); - async move { - Ok::<_, hyper::http::Error>(service_fn(move |req| { - // todo: clone may not be necessary - let html = html.as_ref().to_owned(); - async move { - if req.uri().path() == "/" { - log::info!("Serve frontend: {:?}", mode); - Ok::<_, Error>(hyper::Response::new(hyper::Body::from(html))) - } else { - // jump to / - let mut res = hyper::Response::new(hyper::Body::empty()); - *res.status_mut() = hyper::StatusCode::FOUND; - res.headers_mut().insert( - hyper::header::LOCATION, - hyper::header::HeaderValue::from_static("/"), - ); - Ok(res) - } - } - })) - } - }); - let static_file_addr = arguments.static_file_host; - if !static_file_addr.is_empty() { - let server = hyper::Server::bind(&static_file_addr.parse().unwrap()).serve(make_service); - if !arguments.dont_open_in_browser { - if let Err(e) = open::that_detached(format!("http://{}", server.local_addr())) { - error!("failed to open browser: {}", e); - }; - } - info!("Static file server listening on: {}", server.local_addr()); - if let Err(e) = server.await { - error!("Static file server error: {}", e); - } - } Previewer { - frontend_html, frontend_html_factory, data_plane_handle, control_plane_handle, diff --git a/src/main.rs b/src/main.rs index 27788d48..5d6f4c4e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,7 +5,52 @@ use typst_ts_compiler::service::CompileDriver; use typst_ts_compiler::TypstSystemWorld; use typst_ts_core::config::CompileOpts; -use typst_preview::{preview, CliArguments}; +use hyper::{ + service::{make_service_fn, service_fn}, + Error, +}; + +use typst_preview::{preview, CliArguments, PreviewMode, Previewer}; + +pub async fn make_static_host( + previewer: &Previewer, + static_file_addr: String, + mode: PreviewMode, +) -> SocketAddr { + let frontend_html = previewer.frontend_html(mode); + let make_service = make_service_fn(|_| { + let html = frontend_html.clone(); + async move { + Ok::<_, hyper::http::Error>(service_fn(move |req| { + // todo: clone may not be necessary + let html = html.as_ref().to_owned(); + async move { + if req.uri().path() == "/" { + log::info!("Serve frontend: {:?}", mode); + Ok::<_, Error>(hyper::Response::new(hyper::Body::from(html))) + } else { + // jump to / + let mut res = hyper::Response::new(hyper::Body::empty()); + *res.status_mut() = hyper::StatusCode::FOUND; + res.headers_mut().insert( + hyper::header::LOCATION, + hyper::header::HeaderValue::from_static("/"), + ); + Ok(res) + } + } + })) + } + }); + let server = hyper::Server::bind(&static_file_addr.parse().unwrap()).serve(make_service); + + let addr = server.local_addr(); + if let Err(e) = server.await { + error!("Static file server error: {}", e); + } + + addr +} /// Entry point. #[tokio::main] @@ -62,10 +107,22 @@ async fn main() { let previewer = preview(arguments.preview, compiler_driver).await; + let static_file_addr = arguments.static_file_host; + let mode = arguments.preview_mode; + if !static_file_addr.is_empty() { + let addr = make_static_host(&previewer, static_file_addr, mode).await; + info!("Static file server listening on: {}", addr); + if !arguments.dont_open_in_browser { + if let Err(e) = open::that_detached(format!("http://{}", addr)) { + error!("failed to open browser: {}", e); + }; + } + } + previewer.join().await; } -use std::borrow::Cow; +use std::{borrow::Cow, net::SocketAddr}; pub static EMBEDDED_FONT: &[Cow<'_, [u8]>] = &[ // Embed default fonts.