Skip to content

Commit

Permalink
images
Browse files Browse the repository at this point in the history
  • Loading branch information
Jazzpirate committed Nov 18, 2024
1 parent 2391186 commit 4f7f265
Show file tree
Hide file tree
Showing 17 changed files with 291 additions and 88 deletions.
4 changes: 4 additions & 0 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,8 @@ jobs:
with:
name: linux
path: ./linux
- name: Set executable
run: chmod +x ./linux/immt
- uses: actions/download-artifact@v4
with:
name: windows
Expand All @@ -121,6 +123,8 @@ jobs:
with:
name: mac_aarch64
path: ./mac
- name: Set executable
run: chmod +x ./mac/immt
- uses: actions/download-artifact@v4
with:
name: ts
Expand Down
5 changes: 4 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,9 @@ html5ever = "0.29.0"
async-lsp = {version="0.2",features=["tokio","async-io"]}
futures = {version="0.3"}

image = { version = "0.25"}
webp = { version= "0.3"}
dashmap = { version = "5" }

# leptos
leptos = { version = "=0.7.0-rc1", features=["nightly"]}
Expand Down Expand Up @@ -158,7 +161,7 @@ console_error_panic_hook = "0.1.7"
reqwasm = "0.5"
#reqwest = {version="0.12",features=["json"]}
gloo-storage = "0.3"
web-sys = { version = "0.3.70" }
web-sys = { version = "0.3" }
tsify-next = {version="0.5", features = ["js"]}
js-sys = "0.3"

Expand Down
23 changes: 13 additions & 10 deletions source/lsp/src/documents.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::path::Path;
use async_lsp::lsp_types::{Position, Range, Url};
use immt_ontology::uris::{ArchiveURI, DocumentURI, URIRefTrait};
use immt_stex::quickparse::stex::{STeXParseData, STeXParseDataI};
use immt_system::backend::{archives::Archive, AnyBackend, GlobalBackend};
use immt_system::backend::{archives::Archive, AnyBackend, Backend, GlobalBackend};
use immt_utils::time::measure;

use crate::LSPStore;
Expand All @@ -30,19 +30,22 @@ impl LSPDocument {
#[allow(clippy::borrowed_box)]
#[must_use]
pub fn new(text:String,lsp_uri:Url) -> Self {
let path = lsp_uri.to_file_path().ok().map(Into::into);
let path:Option<Box<Path>> = lsp_uri.to_file_path().ok().map(Into::into);
let default = || {
let path = path.as_ref()?.as_os_str().to_str()?.into();
Some((ArchiveURI::no_archive(),Some(path)))
};
let ap = path.as_ref().and_then(|path:&Box<Path>|
GlobalBackend::get().manager().all_archives().iter().find_map(|a|
if let Archive::Local(a) = a {
if path.starts_with(a.path()) {
let rel_path = path.display().to_string().strip_prefix(&a.source_dir().display().to_string()).map(Into::into);
Some((a.uri().owned(),rel_path))
} else {None}
} else {None}
));
GlobalBackend::get().archive_of(path,|a,rp| {
let uri = a.uri().owned();
let rp = rp.strip_prefix("/source/").map(|r| r.into());
(uri,rp)
})
).or_else(default);
let (archive,rel_path) = ap.map_or((None,None),|(a,p)| (Some(a),p));
let r = LSPText { text ,up_to_date:false, html_up_to_date: false };
let doc_uri = archive.as_ref().and_then(|a| rel_path.as_ref().map(|rp:&Box<str>| DocumentURI::from_archive_relpath(a.clone(), rp)));
//tracing::info!("Document: {lsp_uri}\n - {doc_uri:?}\n - [{archive:?}]{{{rel_path:?}}}");
let data = DocumentData {
lsp_uri,path,archive,rel_path,doc_uri
};
Expand Down
43 changes: 21 additions & 22 deletions source/lsp/src/implementation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,6 @@ impl<T:IMMTLSPServer> LanguageServer for ServerWrapper<T> {
};
let _ = client.publish_diagnostics(r);
}));
//d.with_text(|t| tracing::info!("new text:\n{}",t));
} else {
tracing::warn!("document not found: {}",document.uri);
}
Expand All @@ -179,7 +178,7 @@ impl<T:IMMTLSPServer> LanguageServer for ServerWrapper<T> {
#[allow(clippy::let_underscore_future)]
//impl_notification!(! did_save = DidSaveTextDocument);
fn did_save(&mut self,params:lsp::DidSaveTextDocumentParams) -> Self::NotifyResult {
tracing::info!("did_save: {}",params.text_document.uri);
tracing::trace!("did_save: {}",params.text_document.uri);
let state = self.inner.state().clone();
let client = self.inner.client().clone();
let uri = params.text_document.uri;
Expand Down Expand Up @@ -294,8 +293,8 @@ impl<T:IMMTLSPServer> LanguageServer for ServerWrapper<T> {
#[must_use]
// impl_request!(! hover = HoverRequest => (None));
fn hover(&mut self, params: lsp::HoverParams) -> Res<Option<lsp::Hover>> {
tracing::info_span!("hover").in_scope(move || {
tracing::info!("uri: {},work_done_progress_params: {:?}, position: {:?}",
tracing::trace_span!("hover").in_scope(move || {
tracing::trace!("uri: {},work_done_progress_params: {:?}, position: {:?}",
params.text_document_position_params.text_document.uri,
params.work_done_progress_params,
params.text_document_position_params.position
Expand Down Expand Up @@ -391,8 +390,8 @@ impl<T:IMMTLSPServer> LanguageServer for ServerWrapper<T> {
#[must_use]
// impl_request!(semantic_tokens_full = SemanticTokensFullRequest);
fn semantic_tokens_full(&mut self, params: lsp::SemanticTokensParams) -> Res<Option<lsp::SemanticTokensResult>> {
tracing::info_span!("semantic_tokens_full").in_scope(|| {
tracing::info!("work_done_progress_params: {:?}, partial_results: {:?}, uri: {}",
tracing::trace_span!("semantic_tokens_full").in_scope(|| {
tracing::trace!("work_done_progress_params: {:?}, partial_results: {:?}, uri: {}",
params.work_done_progress_params,
params.partial_result_params,
params.text_document.uri
Expand All @@ -407,25 +406,11 @@ impl<T:IMMTLSPServer> LanguageServer for ServerWrapper<T> {
})
}

#[must_use]
// impl_request!(semantic_tokens_full_delta = SemanticTokensFullDeltaRequest);
fn semantic_tokens_full_delta(&mut self, params: lsp::SemanticTokensDeltaParams) -> Res<Option<lsp::SemanticTokensFullDeltaResult>> {
tracing::info_span!("semantic_tokens_full_delta").in_scope(|| {
tracing::info!("work_done_progress_params: {:?}, partial_results: {:?}, previous_result_id: {:?}, uri:{}",
params.work_done_progress_params,
params.partial_result_params,
params.previous_result_id,
params.text_document.uri
);
Box::pin(std::future::ready(Ok(None)))
})
}

#[must_use]
// impl_request!(semantic_tokens_range = SemanticTokensRangeRequest);
fn semantic_tokens_range(&mut self, params: lsp::SemanticTokensRangeParams) -> Res<Option<lsp::SemanticTokensRangeResult>> {
tracing::info_span!("semantic_tokens_range").in_scope(|| {
tracing::info!("work_done_progress_params: {:?}, partial_results: {:?}, range: {:?}, uri:{}",
tracing::trace_span!("semantic_tokens_range").in_scope(|| {
tracing::trace!("work_done_progress_params: {:?}, partial_results: {:?}, range: {:?}, uri:{}",
params.work_done_progress_params,
params.partial_result_params,
params.range,
Expand All @@ -441,6 +426,20 @@ impl<T:IMMTLSPServer> LanguageServer for ServerWrapper<T> {
})
}

#[must_use]
// impl_request!(semantic_tokens_full_delta = SemanticTokensFullDeltaRequest);
fn semantic_tokens_full_delta(&mut self, params: lsp::SemanticTokensDeltaParams) -> Res<Option<lsp::SemanticTokensFullDeltaResult>> {
tracing::info_span!("semantic_tokens_full_delta").in_scope(|| {
tracing::info!("work_done_progress_params: {:?}, partial_results: {:?}, previous_result_id: {:?}, uri:{}",
params.work_done_progress_params,
params.partial_result_params,
params.previous_result_id,
params.text_document.uri
);
Box::pin(std::future::ready(Ok(None)))
})
}

// callHierarchy/
impl_request!(incoming_calls = CallHierarchyIncomingCalls);
impl_request!(outgoing_calls = CallHierarchyOutgoingCalls);
Expand Down
2 changes: 1 addition & 1 deletion source/lsp/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ impl LSPState {
_ => ()
}
}
tracing::info!("document links: {:?}",ret);
//tracing::info!("document links: {:?}",ret);
if let Some(p) = progress { p.finish() }
ret
}))
Expand Down
12 changes: 11 additions & 1 deletion source/main/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,11 @@ ssr = [
"dep:immt-lsp",
"dep:tracing-subscriber",
"dep:tokio-util",
"dep:rayon"
"dep:rayon",
"dep:tex_engine",
"dep:image",
"dep:webp",
"dep:dashmap"
]
hydrate = [
"dep:console_error_panic_hook",
Expand Down Expand Up @@ -87,6 +91,8 @@ immt-system = {workspace=true,features=["tokio"],optional=true}
immt-lsp = {workspace=true,optional=true, features=["ws"]}
immt-stex = {workspace=true,optional=true}
immt-shtml = {workspace=true,optional=true}
tex_engine = {workspace=true,optional=true}

tokio = {workspace=true,features = ["full","rt","rt-multi-thread"],optional=true}
toml = {workspace = true,optional=true}
color-eyre = {workspace = true,optional=true}
Expand All @@ -112,6 +118,10 @@ argon2 = {workspace=true,optional=true}
tokio-util = {workspace=true,optional=true}
tracing-subscriber = {workspace=true,optional=true}

image = {workspace=true,optional=true}
webp = {workspace=true,optional=true}
dashmap = {workspace=true,optional=true}

#hydrate
console_error_panic_hook = {workspace = true,optional=true}
wasm-bindgen = {workspace = true,optional=true}
Expand Down
97 changes: 97 additions & 0 deletions source/main/src/server/img.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
use std::{default, ops::Deref, path::PathBuf, sync::atomic::AtomicU64};

use axum::body::Body;
use http::Request;
use immt_ontology::uris::ArchiveId;
use immt_system::{backend::{Backend, GlobalBackend}, settings::Settings};
use immt_utils::time::Timestamp;
use leptos::svg::Image;
use tower::ServiceExt;
use tower_http::services::{fs::ServeFileSystemResponseBody, ServeFile};

use super::ServerState;

#[derive(Clone,Default)]
pub struct ImageStore(immt_utils::triomphe::Arc<ImageStoreI>);

#[derive(Default)]
struct ImageStoreI {
map:dashmap::DashMap<ImageSpec, ImageData>,
count:AtomicU64
}

#[derive(Clone,Debug,Hash,PartialEq,Eq)]
pub enum ImageSpec {
Kpse(Box<str>),
ARp(ArchiveId,Box<str>),
File(Box<str>)
}
impl ImageSpec {
pub fn path(&self) -> Option<PathBuf> {
match self {
Self::Kpse(p) => tex_engine::engine::filesystem::kpathsea::KPATHSEA.which(p),
Self::ARp(a,p) =>
GlobalBackend::get().with_local_archive(a, |a|
a.map(|a| a.path().join(&**p) )
),
Self::File(p) => Some(std::path::PathBuf::from(p.to_string()))
}
}
}

pub struct ImageData {
img: Box<[u8]>,
timestamp: AtomicU64
}
impl ImageData {
pub fn update(&self) {
let now = Timestamp::now();
self.timestamp.store(now.0.get() as _,std::sync::atomic::Ordering::SeqCst);
}
pub fn new(data: &[u8]) -> Self {
Self {
img: data.into(),
timestamp: AtomicU64::new(Timestamp::now().0.get())
}
}
}


pub async fn img_handler(
mut uri: http::Uri,
axum::extract::State(ServerState {images,..}): axum::extract::State<ServerState>,
//request: http::Request<axum::body::Body>,
) -> axum::response::Response<ServeFileSystemResponseBody> {

let default = || {
let mut resp = axum::response::Response::new(ServeFileSystemResponseBody::default());
*resp.status_mut() = http::StatusCode::NOT_FOUND;
resp
};

let Some(s) = uri.query() else { return default(); };

let spec = if let Some(s) = s.strip_prefix("kpse=") {
ImageSpec::Kpse(s.into())
} else if let Some(f) = s.strip_prefix("file=") {
if Settings::get().lsp {
ImageSpec::File(f.into())
} else { return default(); }
}
else if let Some(s) = s.strip_prefix("a=") {
let Some((a,rp)) = s.split_once("&rp=") else { return default(); };
let a = a.parse().unwrap_or_else(|_| unreachable!());
let rp = rp.into();
ImageSpec::ARp(a,rp)
} else { return default() };

//tracing::info!("HERE: {spec:?}");
if let Some(p) = spec.path() {
let req = Request::builder()
.uri(uri.clone())
.body(Body::empty())
.unwrap();
ServeFile::new(p).oneshot(req).await.unwrap_or_else(|_| default())
} else {default() }

}
8 changes: 6 additions & 2 deletions source/main/src/server/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
pub mod db;
pub mod settings;
pub mod lsp;
mod img;

use std::future::IntoFuture;

Expand Down Expand Up @@ -59,6 +60,7 @@ pub async fn run(port_channel:Option<tokio::sync::watch::Sender<Option<u16>>>) {
routes,
axum::routing::get(|a, b, c| routes_handler(a, b, c).in_current_span()),
)
.route("/img",axum::routing::get(img::img_handler))
.fallback(file_and_error_handler)
.layer(auth_layer)
.layer(
Expand Down Expand Up @@ -93,7 +95,7 @@ pub async fn run(port_channel:Option<tokio::sync::watch::Sender<Option<u16>>>) {

async fn routes_handler(
auth_session: axum_login::AuthSession<DBBackend>,
extract::State(ServerState { db, options }): extract::State<ServerState>,
extract::State(ServerState { db, options,.. }): extract::State<ServerState>,
request: http::Request<axum::body::Body>,
) -> impl IntoResponse {
let handler = leptos_axum::render_app_to_stream_with_context(
Expand All @@ -108,7 +110,7 @@ async fn routes_handler(

async fn server_fn_handle(
auth_session: axum_login::AuthSession<DBBackend>,
extract::State(ServerState { db, options }): extract::State<ServerState>,
extract::State(ServerState { db, options,.. }): extract::State<ServerState>,
request: http::Request<axum::body::Body>,
) -> impl IntoResponse {
leptos_axum::handle_server_fns_with_context(
Expand Down Expand Up @@ -154,6 +156,7 @@ impl<A> tower_http::trace::MakeSpan<A> for SpanLayer {
pub(crate) struct ServerState {
options: LeptosOptions,
db: DBBackend,
pub(crate) images: img::ImageStore,
}

impl ServerState {
Expand All @@ -163,6 +166,7 @@ impl ServerState {
Self {
options: leptos_cfg.leptos_options,
db,
images: img::ImageStore::default(),
}
}

Expand Down
8 changes: 8 additions & 0 deletions source/ontology/src/uris/archives.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ use triomphe::Arc;
lazy_static! {
static ref ARCHIVE_IDS: Arc<Mutex<TArcInterner<str, 4, 100>>> =
Arc::new(Mutex::new(TArcInterner::default()));

static ref NO_ARCHIVE_ID:ArchiveId = ArchiveId::new("no/archive");
static ref NO_ARCHIVE_URI:ArchiveURI = "http://unknown.source?a=no/archive".parse().unwrap_or_else(|_| unreachable!());
}

#[derive(Clone, PartialEq, Eq, Hash)]
Expand All @@ -27,6 +30,9 @@ impl ArchiveId {
s.rsplit_once('/').map_or(s, |(_, s)| s)
}

#[inline]#[must_use]
pub fn no_archive() -> Self { NO_ARCHIVE_ID.clone() }

#[must_use]
pub fn steps(&self) -> std::str::Split<char> {
self.as_ref().split('/')
Expand Down Expand Up @@ -108,6 +114,8 @@ impl Display for ArchiveURI {
debugdisplay!(ArchiveURI);

impl ArchiveURI {
#[must_use]
pub fn no_archive() -> Self { NO_ARCHIVE_URI.clone() }
#[must_use]
#[allow(clippy::missing_const_for_fn)]
pub fn new(base: BaseURI, archive: ArchiveId) -> Self {
Expand Down
Loading

0 comments on commit 4f7f265

Please sign in to comment.