diff --git a/.github/workflows/build-pkg.yml b/.github/workflows/build-pkg.yml index c2da711..ef6d866 100644 --- a/.github/workflows/build-pkg.yml +++ b/.github/workflows/build-pkg.yml @@ -2,8 +2,8 @@ name: "build pkg" on: push: - tags: - - "v*" + -branches: + - release jobs: publish-tauri: diff --git a/README.md b/README.md index db40407..f969d22 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -![typster](./public/imgs/app-icon.png) +![typster](./app-icon.png) # [WIP] typster diff --git a/app-icon.png b/app-icon.png index 283a137..cc2a5f8 100644 Binary files a/app-icon.png and b/app-icon.png differ diff --git a/src-tauri/icons/128x128.png b/src-tauri/icons/128x128.png index 734d229..5b7aaf3 100644 Binary files a/src-tauri/icons/128x128.png and b/src-tauri/icons/128x128.png differ diff --git a/src-tauri/icons/128x128@2x.png b/src-tauri/icons/128x128@2x.png index 4ec7d02..1eb6c1f 100644 Binary files a/src-tauri/icons/128x128@2x.png and b/src-tauri/icons/128x128@2x.png differ diff --git a/src-tauri/icons/32x32.png b/src-tauri/icons/32x32.png index 8cab1b3..836ece5 100644 Binary files a/src-tauri/icons/32x32.png and b/src-tauri/icons/32x32.png differ diff --git a/src-tauri/icons/Square107x107Logo.png b/src-tauri/icons/Square107x107Logo.png index 588f2ce..9a38536 100644 Binary files a/src-tauri/icons/Square107x107Logo.png and b/src-tauri/icons/Square107x107Logo.png differ diff --git a/src-tauri/icons/Square142x142Logo.png b/src-tauri/icons/Square142x142Logo.png index ec518df..8f746b8 100644 Binary files a/src-tauri/icons/Square142x142Logo.png and b/src-tauri/icons/Square142x142Logo.png differ diff --git a/src-tauri/icons/Square150x150Logo.png b/src-tauri/icons/Square150x150Logo.png index db06233..5c9a742 100644 Binary files a/src-tauri/icons/Square150x150Logo.png and b/src-tauri/icons/Square150x150Logo.png differ diff --git a/src-tauri/icons/Square284x284Logo.png b/src-tauri/icons/Square284x284Logo.png index 6221e05..51eae2b 100644 Binary files a/src-tauri/icons/Square284x284Logo.png and b/src-tauri/icons/Square284x284Logo.png differ diff --git a/src-tauri/icons/Square30x30Logo.png b/src-tauri/icons/Square30x30Logo.png index 4246565..7153f13 100644 Binary files a/src-tauri/icons/Square30x30Logo.png and b/src-tauri/icons/Square30x30Logo.png differ diff --git a/src-tauri/icons/Square310x310Logo.png b/src-tauri/icons/Square310x310Logo.png index 6d8d643..cdab616 100644 Binary files a/src-tauri/icons/Square310x310Logo.png and b/src-tauri/icons/Square310x310Logo.png differ diff --git a/src-tauri/icons/Square44x44Logo.png b/src-tauri/icons/Square44x44Logo.png index 796c693..160001d 100644 Binary files a/src-tauri/icons/Square44x44Logo.png and b/src-tauri/icons/Square44x44Logo.png differ diff --git a/src-tauri/icons/Square71x71Logo.png b/src-tauri/icons/Square71x71Logo.png index 7b00e3d..983ed68 100644 Binary files a/src-tauri/icons/Square71x71Logo.png and b/src-tauri/icons/Square71x71Logo.png differ diff --git a/src-tauri/icons/Square89x89Logo.png b/src-tauri/icons/Square89x89Logo.png index 018a655..0aabb18 100644 Binary files a/src-tauri/icons/Square89x89Logo.png and b/src-tauri/icons/Square89x89Logo.png differ diff --git a/src-tauri/icons/StoreLogo.png b/src-tauri/icons/StoreLogo.png index 85e3b2c..74b9a9b 100644 Binary files a/src-tauri/icons/StoreLogo.png and b/src-tauri/icons/StoreLogo.png differ diff --git a/src-tauri/icons/icon.icns b/src-tauri/icons/icon.icns index b659eef..36aee5f 100644 Binary files a/src-tauri/icons/icon.icns and b/src-tauri/icons/icon.icns differ diff --git a/src-tauri/icons/icon.ico b/src-tauri/icons/icon.ico index 82a292c..5c456dc 100644 Binary files a/src-tauri/icons/icon.ico and b/src-tauri/icons/icon.ico differ diff --git a/src-tauri/icons/icon.png b/src-tauri/icons/icon.png index 4d91b16..13b5304 100644 Binary files a/src-tauri/icons/icon.png and b/src-tauri/icons/icon.png differ diff --git a/src-tauri/src/ipc/commands/typst.rs b/src-tauri/src/ipc/commands/typst.rs index 1c1f173..ae51f56 100644 --- a/src-tauri/src/ipc/commands/typst.rs +++ b/src-tauri/src/ipc/commands/typst.rs @@ -2,7 +2,7 @@ use super::{Error, Result}; use crate::ipc::commands::project; use crate::ipc::model::TypstRenderResponse; use crate::ipc::{ - TypstCompileEvent, TypstDiagnosticSeverity, TypstDocument, TypstPage, TypstSourceDiagnostic + TypstCompileEvent, TypstDiagnosticSeverity, TypstDocument, TypstPage, TypstSourceDiagnostic, }; use crate::project::ProjectManager; use base64::Engine; @@ -11,6 +11,7 @@ use serde::Serialize; use serde_repr::Serialize_repr; use siphasher::sip128::{Hasher128, SipHasher}; use std::hash::Hash; +use std::ops::Range; use std::path::PathBuf; use std::sync::Arc; use std::time::Instant; @@ -72,7 +73,7 @@ pub async fn typst_slot_update( content: String, ) -> Result<()> { let project = project(&window, &project_manager)?; - + let mut world = project.world.lock().unwrap(); let _ = world .slot_update(&path, Some(content)) @@ -86,7 +87,7 @@ pub async fn typst_compile_doc( project_manager: tauri::State<'_, Arc>>, path: PathBuf, content: String, -) -> Result> { +) -> Result<(Vec, Vec)> { let project = project(&window, &project_manager)?; let mut world = project.world.lock().unwrap(); @@ -105,7 +106,8 @@ pub async fn typst_compile_doc( debug!("compiling {:?}: {:?}", path, project); let now = Instant::now(); let mut tracer = Tracer::new(); - let mut res: Vec = Vec::new(); + let mut pages: Vec = Vec::new(); + let mut diags: Vec = Vec::new(); match typst::compile(&*world, &mut tracer) { Ok(doc) => { let elapsed = now.elapsed(); @@ -114,31 +116,27 @@ pub async fn typst_compile_doc( project, elapsed.as_millis() ); - let mut idx:u32 = 0; + let mut idx: u32 = 0; for page in &doc.pages { let mut hasher = SipHasher::new(); page.frame.hash(&mut hasher); let hash = hex::encode(hasher.finish128().as_bytes()); - let width = page.frame.width().to_pt(); + let width = page.frame.width().to_pt(); let height = page.frame.height().to_pt(); - idx +=1; - let pag = TypstPage { + idx += 1; + let pag = TypstPage { num: idx, width, height, - hash: hash.clone() + hash: hash.clone(), }; - res.push(pag); + pages.push(pag); } project.cache.write().unwrap().document = Some(doc); - } Err(diagnostics) => { - debug!( - "compilation failed with {:?} diagnostics", - &diagnostics - ); + debug!("compilation failed with {:?} diagnostics", &diagnostics); let source = world.source(source_id); let diagnostics: Vec = match source { @@ -148,13 +146,11 @@ pub async fn typst_compile_doc( .filter_map(|d| { let span = source.find(d.span)?; let range = span.range(); - let start = content[..range.start].chars().count(); - let size = content[range.start..range.end].chars().count(); let message = d.message.to_string(); - info!("############## {}", &message); Some(TypstSourceDiagnostic { - range: start..start + size, + pos: get_range_position(&content, range.clone()), + range, severity: match d.severity { Severity::Error => TypstDiagnosticSeverity::Error, Severity::Warning => TypstDiagnosticSeverity::Warning, @@ -167,123 +163,32 @@ pub async fn typst_compile_doc( Err(_) => vec![], }; - info!("############## {:?}", &diagnostics); - + diags = diagnostics.clone(); - - + info!("############## {:?}", &diags); } } - Ok(res) + Ok((pages, diags)) } -#[tauri::command] -pub async fn typst_compile( - window: tauri::Window, - project_manager: tauri::State<'_, Arc>>, - path: PathBuf, - content: String, -) -> Result<()> { - let project = project(&window, &project_manager)?; - - let mut world = project.world.lock().unwrap(); - let source_id = world - .slot_update(&path, Some(content.clone())) - .map_err(Into::::into)?; - - if !world.is_main_set() { - let config = project.config.read().unwrap(); - if config.apply_main(&project, &mut world).is_err() { - debug!("skipped compilation for {:?} (main not set)", project); - return Ok(()); - } - } - - debug!("compiling {:?}: {:?}", path, project); - let now = Instant::now(); - let mut tracer = Tracer::new(); - match typst::compile(&*world, &mut tracer) { - Ok(doc) => { - let elapsed = now.elapsed(); - debug!( - "compilation succeeded for {:?} in {:?} ms", - project, - elapsed.as_millis() - ); - - let pages = doc.pages.len(); - - let mut hasher = SipHasher::new(); - for page in &doc.pages { - page.frame.hash(&mut hasher); - } - let hash = hex::encode(hasher.finish128().as_bytes()); - - // Assume all pages have the same size - // TODO: Improve this? - let first_page = &doc.pages[0]; - let width = first_page.frame.width(); - let height = first_page.frame.height(); - - project.cache.write().unwrap().document = Some(doc); - - let _ = window.emit( - "typst_compile", - TypstCompileEvent { - document: Some(TypstDocument { - pages, - hash, - width: width.to_pt(), - height: height.to_pt(), - }), - diagnostics: None, - }, - ); +pub fn get_range_position(text: &str, rang: Range) -> (usize, usize) { + let mut ln = 0; + let mut cn = 0; + let mut total: usize = 0; + for line in text.lines() { + + ln += 1; + let row = line.chars().count() + 1; + + if total <= rang.start && rang.start <= total + row { + cn = rang.start - total; + break; } - Err(diagnostics) => { - debug!( - "compilation failed with {:?} diagnostics", - diagnostics.len() - ); - - let source = world.source(source_id); - let diagnostics: Vec = match source { - Ok(source) => diagnostics - .iter() - .filter(|d| d.span.id() == Some(source_id)) - .filter_map(|d| { - let span = source.find(d.span)?; - let range = span.range(); - let start = content[..range.start].chars().count(); - let size = content[range.start..range.end].chars().count(); - - let message = d.message.to_string(); - Some(TypstSourceDiagnostic { - range: start..start + size, - severity: match d.severity { - Severity::Error => TypstDiagnosticSeverity::Error, - Severity::Warning => TypstDiagnosticSeverity::Warning, - }, - message, - hints: d.hints.iter().map(|hint| hint.to_string()).collect(), - }) - }) - .collect(), - Err(_) => vec![], - }; - let _ = window.emit( - "typst_compile", - TypstCompileEvent { - document: None, - diagnostics: Some(diagnostics), - }, - ); - } + total += row; } - - Ok(()) + return (ln, cn); } #[tauri::command] @@ -294,17 +199,23 @@ pub async fn typst_render( scale: f32, nonce: u32, ) -> Result { - - info!("typst_render page:{} scale: {} nonce: {}", page, scale, nonce); + info!( + "typst_render page:{} scale: {} nonce: {}", + page, scale, nonce + ); let project = project_manager .get_project(&window) .ok_or(Error::UnknownProject)?; - + let cache = project.cache.read().unwrap(); - - if let Some(p) = cache.document.as_ref().and_then(|doc| doc.pages.get(page-1)) { + + if let Some(p) = cache + .document + .as_ref() + .and_then(|doc| doc.pages.get(page - 1)) + { let now = Instant::now(); - + let bmp = typst_render::render(&p.frame, scale, Color::WHITE); if let Ok(image) = bmp.encode_png() { let elapsed = now.elapsed(); diff --git a/src-tauri/src/ipc/model.rs b/src-tauri/src/ipc/model.rs index 4f78b77..8788fb4 100644 --- a/src-tauri/src/ipc/model.rs +++ b/src-tauri/src/ipc/model.rs @@ -39,6 +39,7 @@ pub struct TypstSourceDiagnostic { pub severity: TypstDiagnosticSeverity, pub message: String, pub hints: Vec, + pub pos:(usize, usize) } #[derive(Serialize, Clone, Debug)] diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index bb899d8..1806f01 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -42,7 +42,6 @@ async fn main() { ipc::commands::fs_write_file_binary, ipc::commands::fs_write_file_text, ipc::commands::load_project_from_path, - ipc::commands::typst_compile, ipc::commands::typst_compile_doc, ipc::commands::typst_render, ipc::commands::typst_autocomplete, diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 9b5db94..5a0b7f5 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -86,11 +86,14 @@ "fullscreen": false, "resizable": true, "title": "typster", + "center": true, "hiddenTitle": true, - "titleBarStyle": "Overlay", + "titleBarStyle": "Transparent", "theme": "Light", "width": 1200, - "height": 900 + "height": 900, + "minWidth": 800, + "minHeight": 400 } ] } diff --git a/src-tauri/tauri.macos.conf.json b/src-tauri/tauri.macos.conf.json new file mode 100644 index 0000000..a285a0d --- /dev/null +++ b/src-tauri/tauri.macos.conf.json @@ -0,0 +1,19 @@ +{ + "tauri": { + "windows": [ + { + "fullscreen": false, + "resizable": true, + "title": "", + "center": true, + "hiddenTitle": false, + "titleBarStyle": "Overlay", + "theme": "Light", + "width": 1200, + "height": 900, + "minWidth": 800, + "minHeight": 400 + } + ] + } +} \ No newline at end of file diff --git a/src/components/MonacoEditor.vue b/src/components/MonacoEditor.vue index 101220e..7eb29fb 100644 --- a/src/components/MonacoEditor.vue +++ b/src/components/MonacoEditor.vue @@ -5,7 +5,7 @@ + + \ No newline at end of file diff --git a/src/pages/typst/PreviewPage.vue b/src/pages/typst/PreviewPage.vue index 6c2c72b..615e068 100644 --- a/src/pages/typst/PreviewPage.vue +++ b/src/pages/typst/PreviewPage.vue @@ -9,7 +9,7 @@ import { computed, onMounted, reactive, ref, watch } from 'vue'; import { invoke } from '@tauri-apps/api'; import defaultUrl from './../../assets/rendering.svg' -import type { TypstCompileEvent, TypstRenderResponse } from './interface'; +import type { TypstRenderResponse } from './interface'; const props = defineProps({ num: Number, diff --git a/src/pages/typst/TypstEditor.vue b/src/pages/typst/TypstEditor.vue index 4789097..70c5ef9 100644 --- a/src/pages/typst/TypstEditor.vue +++ b/src/pages/typst/TypstEditor.vue @@ -1,6 +1,8 @@