mirror of
https://github.com/Myriad-Dreamin/tinymist.git
synced 2025-11-25 21:37:32 +00:00
feat: convert TypstDocument to enum (#1256)
* feat: convert `TypstDocument` to enum * fix: errors * build: update cargo.lock * fix: warnings * fix: error * html changes * Revert "html changes" This reverts commitf9fc0e4872. * Revert "Revert "html changes"" This reverts commit7dc554a9e4. * use std typst docs * span * paged * paged * html change * paged * html change * bytes * paged * paged * paged * html changes * paged * html changes * paged
This commit is contained in:
parent
30a08e79ab
commit
3bc5f19cf5
23 changed files with 237 additions and 123 deletions
3
Cargo.lock
generated
3
Cargo.lock
generated
|
|
@ -4165,9 +4165,11 @@ version = "0.12.18"
|
|||
dependencies = [
|
||||
"base64",
|
||||
"log",
|
||||
"reflexo-typst",
|
||||
"reflexo-vec2svg",
|
||||
"serde",
|
||||
"tinymist-query",
|
||||
"tinymist-std",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -4651,6 +4653,7 @@ dependencies = [
|
|||
"serde",
|
||||
"serde_json",
|
||||
"tinymist-assets 0.12.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tinymist-std",
|
||||
"tokio",
|
||||
"typst",
|
||||
"typst-assets",
|
||||
|
|
|
|||
|
|
@ -7,9 +7,9 @@ use std::sync::{Arc, OnceLock};
|
|||
|
||||
use ecow::{eco_vec, EcoString, EcoVec};
|
||||
use reflexo_typst::features::{CompileFeature, FeatureSet, WITH_COMPILING_STATUS_FEATURE};
|
||||
use reflexo_typst::{CompileEnv, CompileReport, Compiler, TypstDocument};
|
||||
use reflexo_typst::{CompileEnv, CompileReport, Compiler};
|
||||
use tinymist_std::error::prelude::Result;
|
||||
use tinymist_std::ImmutPath;
|
||||
use tinymist_std::{typst::TypstDocument, ImmutPath};
|
||||
use tinymist_world::vfs::notify::{
|
||||
FilesystemEvent, MemoryEvent, NotifyDeps, NotifyMessage, UpstreamUpdateEvent,
|
||||
};
|
||||
|
|
@ -70,7 +70,7 @@ pub struct CompileSnapshot<F: CompilerFeat> {
|
|||
/// Using world
|
||||
pub world: CompilerWorld<F>,
|
||||
/// The last successfully compiled document.
|
||||
pub success_doc: Option<Arc<TypstDocument>>,
|
||||
pub success_doc: Option<TypstDocument>,
|
||||
}
|
||||
|
||||
impl<F: CompilerFeat + 'static> CompileSnapshot<F> {
|
||||
|
|
@ -118,7 +118,7 @@ impl<F: CompilerFeat + 'static> CompileSnapshot<F> {
|
|||
let warned = std::marker::PhantomData.compile(&snap.world, &mut snap.env);
|
||||
snap.world.set_is_compiling(false);
|
||||
let (doc, warnings) = match warned {
|
||||
Ok(doc) => (Ok(doc.output), doc.warnings),
|
||||
Ok(doc) => (Ok(TypstDocument::Paged(doc.output)), doc.warnings),
|
||||
Err(err) => (Err(err), EcoVec::default()),
|
||||
};
|
||||
CompiledArtifact {
|
||||
|
|
@ -149,7 +149,7 @@ pub struct CompiledArtifact<F: CompilerFeat> {
|
|||
/// The diagnostics of the document.
|
||||
pub warnings: EcoVec<SourceDiagnostic>,
|
||||
/// The compiled document.
|
||||
pub doc: SourceResult<Arc<TypstDocument>>,
|
||||
pub doc: SourceResult<TypstDocument>,
|
||||
/// The depended files.
|
||||
pub deps: OnceLock<EcoVec<FileId>>,
|
||||
}
|
||||
|
|
@ -182,7 +182,7 @@ impl<F: CompilerFeat> Clone for CompiledArtifact<F> {
|
|||
|
||||
impl<F: CompilerFeat> CompiledArtifact<F> {
|
||||
/// Returns the last successfully compiled document.
|
||||
pub fn success_doc(&self) -> Option<Arc<TypstDocument>> {
|
||||
pub fn success_doc(&self) -> Option<TypstDocument> {
|
||||
self.doc
|
||||
.as_ref()
|
||||
.ok()
|
||||
|
|
@ -736,9 +736,9 @@ pub struct ProjectInsState<F: CompilerFeat, Ext> {
|
|||
deps: EcoVec<ImmutPath>,
|
||||
|
||||
/// The latest compiled document.
|
||||
pub(crate) latest_doc: Option<Arc<TypstDocument>>,
|
||||
pub(crate) latest_doc: Option<TypstDocument>,
|
||||
/// The latest successly compiled document.
|
||||
latest_success_doc: Option<Arc<TypstDocument>>,
|
||||
latest_success_doc: Option<TypstDocument>,
|
||||
/// feature set for compile_once mode.
|
||||
once_feature_set: Arc<FeatureSet>,
|
||||
/// Shared feature set for watch mode.
|
||||
|
|
|
|||
|
|
@ -13,11 +13,11 @@ use serde::{Deserialize, Serialize};
|
|||
use tinymist_derive::BindTyCtx;
|
||||
use tinymist_project::LspWorld;
|
||||
use tinymist_std::path::unix_slash;
|
||||
use tinymist_std::typst::TypstDocument;
|
||||
use typst::foundations::{
|
||||
fields_on, format_str, repr, AutoValue, Func, Label, NoneValue, Repr, Scope, StyleChain, Type,
|
||||
Value,
|
||||
};
|
||||
use typst::model::Document;
|
||||
use typst::syntax::ast::{self, AstNode, Param};
|
||||
use typst::syntax::{is_id_continue, is_id_start, is_ident};
|
||||
use typst::text::RawElem;
|
||||
|
|
@ -329,7 +329,7 @@ pub struct CompletionWorker<'a> {
|
|||
/// The analysis local context.
|
||||
ctx: &'a mut LocalContext,
|
||||
/// The compiled document.
|
||||
document: Option<&'a Document>,
|
||||
document: Option<&'a TypstDocument>,
|
||||
/// Whether the completion was explicitly requested.
|
||||
explicit: bool,
|
||||
/// The trigger character.
|
||||
|
|
@ -346,7 +346,7 @@ impl<'a> CompletionWorker<'a> {
|
|||
/// Create a completion worker.
|
||||
pub fn new(
|
||||
ctx: &'a mut LocalContext,
|
||||
document: Option<&'a Document>,
|
||||
document: Option<&'a TypstDocument>,
|
||||
explicit: bool,
|
||||
trigger_character: Option<char>,
|
||||
) -> Option<Self> {
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ pub fn definition(
|
|||
_ => return None,
|
||||
};
|
||||
|
||||
let introspector = &document?.document.introspector;
|
||||
let introspector = &document?.document.introspector();
|
||||
bib_definition(ctx, introspector, name)
|
||||
.or_else(|| ref_definition(introspector, name, ref_expr))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,11 +2,12 @@
|
|||
|
||||
use comemo::Track;
|
||||
use ecow::*;
|
||||
use tinymist_std::typst::TypstDocument;
|
||||
use typst::engine::{Engine, Route, Sink, Traced};
|
||||
use typst::eval::Vm;
|
||||
use typst::foundations::{Context, Label, Scopes, Styles, Value};
|
||||
use typst::introspection::Introspector;
|
||||
use typst::model::{BibliographyElem, Document};
|
||||
use typst::model::BibliographyElem;
|
||||
use typst::syntax::{ast, LinkedNode, Span, SyntaxKind, SyntaxNode};
|
||||
use typst::World;
|
||||
|
||||
|
|
@ -103,11 +104,11 @@ pub struct DynLabel {
|
|||
/// - All labels and descriptions for them, if available
|
||||
/// - A split offset: All labels before this offset belong to nodes, all after
|
||||
/// belong to a bibliography.
|
||||
pub fn analyze_labels(document: &Document) -> (Vec<DynLabel>, usize) {
|
||||
pub fn analyze_labels(document: &TypstDocument) -> (Vec<DynLabel>, usize) {
|
||||
let mut output = vec![];
|
||||
|
||||
// Labels in the document.
|
||||
for elem in document.introspector.all() {
|
||||
for elem in document.introspector().all() {
|
||||
let Some(label) = elem.label() else { continue };
|
||||
let (is_derived, details) = {
|
||||
let derived = elem
|
||||
|
|
@ -136,7 +137,7 @@ pub fn analyze_labels(document: &Document) -> (Vec<DynLabel>, usize) {
|
|||
let split = output.len();
|
||||
|
||||
// Bibliography keys.
|
||||
for (key, detail) in BibliographyElem::keys(document.introspector.track()) {
|
||||
for (key, detail) in BibliographyElem::keys(document.introspector().track()) {
|
||||
output.push(DynLabel {
|
||||
label: Label::new(key.as_str()),
|
||||
label_desc: detail.clone(),
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ impl StatefulRequest for CompletionRequest {
|
|||
// assume that the completion is not explicit.
|
||||
let explicit = false;
|
||||
|
||||
let document = doc.as_ref().map(|doc| doc.document.as_ref());
|
||||
let document = doc.as_ref().map(|doc| &doc.document);
|
||||
let source = ctx.source_by_path(&self.path).ok()?;
|
||||
let cursor = ctx.to_typst_pos_offset(&source, self.position, 0)?;
|
||||
let mut cursor = CompletionCursor::new(ctx.shared_(), &source, cursor)?;
|
||||
|
|
|
|||
|
|
@ -3,10 +3,10 @@ use std::{collections::HashMap, path::PathBuf};
|
|||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tinymist_std::debug_loc::DataSource;
|
||||
use tinymist_std::typst::TypstDocument;
|
||||
use typst::text::{Font, FontStretch, FontStyle, FontWeight};
|
||||
use typst::{
|
||||
layout::{Frame, FrameItem},
|
||||
model::Document,
|
||||
syntax::Span,
|
||||
text::TextItem,
|
||||
};
|
||||
|
|
@ -142,12 +142,16 @@ struct DocumentMetricsWorker<'a> {
|
|||
}
|
||||
|
||||
impl DocumentMetricsWorker<'_> {
|
||||
fn work(&mut self, doc: &Document) -> Option<()> {
|
||||
for page in &doc.pages {
|
||||
self.work_frame(&page.frame)?;
|
||||
}
|
||||
fn work(&mut self, doc: &TypstDocument) -> Option<()> {
|
||||
match doc {
|
||||
TypstDocument::Paged(paged_doc) => {
|
||||
for page in &paged_doc.pages {
|
||||
self.work_frame(&page.frame)?;
|
||||
}
|
||||
|
||||
Some(())
|
||||
Some(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn work_frame(&mut self, frame: &Frame) -> Option<()> {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
use std::num::NonZeroUsize;
|
||||
|
||||
use typst::model::Document;
|
||||
use tinymist_std::typst::TypstDocument;
|
||||
use typst::{
|
||||
layout::{Frame, FrameItem, Point, Position},
|
||||
syntax::{LinkedNode, Source, Span, SyntaxKind},
|
||||
|
|
@ -10,38 +10,46 @@ use typst::{
|
|||
use typst_shim::syntax::LinkedNodeExt;
|
||||
|
||||
/// Find the output location in the document for a cursor position.
|
||||
pub fn jump_from_cursor(document: &Document, source: &Source, cursor: usize) -> Option<Position> {
|
||||
let node = LinkedNode::new(source.root()).leaf_at_compat(cursor)?;
|
||||
if node.kind() != SyntaxKind::Text {
|
||||
return None;
|
||||
}
|
||||
pub fn jump_from_cursor(
|
||||
document: &TypstDocument,
|
||||
source: &Source,
|
||||
cursor: usize,
|
||||
) -> Option<Position> {
|
||||
match document {
|
||||
TypstDocument::Paged(paged_doc) => {
|
||||
let node = LinkedNode::new(source.root()).leaf_at_compat(cursor)?;
|
||||
if node.kind() != SyntaxKind::Text {
|
||||
return None;
|
||||
}
|
||||
|
||||
let mut min_dis = u64::MAX;
|
||||
let mut point = Point::default();
|
||||
let mut ppage = 0usize;
|
||||
let mut min_dis = u64::MAX;
|
||||
let mut point = Point::default();
|
||||
let mut ppage = 0usize;
|
||||
|
||||
let span = node.span();
|
||||
for (idx, page) in document.pages.iter().enumerate() {
|
||||
let t_dis = min_dis;
|
||||
if let Some(point) = find_in_frame(&page.frame, span, &mut min_dis, &mut point) {
|
||||
return Some(Position {
|
||||
page: NonZeroUsize::new(idx + 1)?,
|
||||
let span = node.span();
|
||||
for (idx, page) in paged_doc.pages.iter().enumerate() {
|
||||
let t_dis = min_dis;
|
||||
if let Some(point) = find_in_frame(&page.frame, span, &mut min_dis, &mut point) {
|
||||
return Some(Position {
|
||||
page: NonZeroUsize::new(idx + 1)?,
|
||||
point,
|
||||
});
|
||||
}
|
||||
if t_dis != min_dis {
|
||||
ppage = idx;
|
||||
}
|
||||
}
|
||||
|
||||
if min_dis == u64::MAX {
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(Position {
|
||||
page: NonZeroUsize::new(ppage + 1)?,
|
||||
point,
|
||||
});
|
||||
}
|
||||
if t_dis != min_dis {
|
||||
ppage = idx;
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if min_dis == u64::MAX {
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(Position {
|
||||
page: NonZeroUsize::new(ppage + 1)?,
|
||||
point,
|
||||
})
|
||||
}
|
||||
|
||||
/// Find the position of a span in a frame.
|
||||
|
|
|
|||
|
|
@ -81,9 +81,8 @@ pub use lsp_typst_boundary::*;
|
|||
|
||||
mod prelude;
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use typst::{model::Document as TypstDocument, syntax::Source};
|
||||
use tinymist_std::typst::TypstDocument;
|
||||
use typst::syntax::Source;
|
||||
|
||||
/// The physical position in a document.
|
||||
pub type FramePosition = typst::layout::Position;
|
||||
|
|
@ -96,7 +95,7 @@ pub struct VersionedDocument {
|
|||
/// The version of the document.
|
||||
pub version: usize,
|
||||
/// The compiled document.
|
||||
pub document: Arc<TypstDocument>,
|
||||
pub document: TypstDocument,
|
||||
}
|
||||
|
||||
/// A request handler with given syntax information.
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ use std::{
|
|||
use once_cell::sync::Lazy;
|
||||
use serde_json::{ser::PrettyFormatter, Serializer, Value};
|
||||
use tinymist_project::CompileFontArgs;
|
||||
use tinymist_std::typst::TypstDocument;
|
||||
use tinymist_world::package::PackageSpec;
|
||||
use tinymist_world::vfs::WorkspaceResolver;
|
||||
use tinymist_world::EntryState;
|
||||
|
|
@ -142,7 +143,7 @@ pub fn compile_doc_for_test(
|
|||
let doc = typst::compile(&world).output.unwrap();
|
||||
Some(VersionedDocument {
|
||||
version: 0,
|
||||
document: Arc::new(doc),
|
||||
document: TypstDocument::Paged(Arc::new(doc)),
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@ rust-version.workspace = true
|
|||
serde.workspace = true
|
||||
tinymist-query.workspace = true
|
||||
reflexo-vec2svg.workspace = true
|
||||
reflexo-typst.workspace = true
|
||||
tinymist-std.workspace = true
|
||||
base64.workspace = true
|
||||
log.workspace = true
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ use core::fmt;
|
|||
use base64::Engine;
|
||||
use reflexo_vec2svg::{ExportFeature, SvgExporter, SvgText};
|
||||
use tinymist_query::{FramePosition, LocalContext, VersionedDocument};
|
||||
use tinymist_std::typst::TypstDocument;
|
||||
|
||||
struct PeriscopeExportFeature {}
|
||||
|
||||
|
|
@ -97,32 +98,36 @@ impl PeriscopeRenderer {
|
|||
doc: VersionedDocument,
|
||||
pos: FramePosition,
|
||||
) -> Option<(String, f32, f32)> {
|
||||
// todo: svg viewer compatibility
|
||||
type UsingExporter = SvgExporter<PeriscopeExportFeature>;
|
||||
let mut doc = UsingExporter::svg_doc(&doc.document);
|
||||
doc.module.prepare_glyphs();
|
||||
let page0 = doc.pages.get(pos.page.get() - 1)?.clone();
|
||||
let mut svg_text = UsingExporter::render(&doc.module, &[page0.clone()], None);
|
||||
match &doc.document {
|
||||
TypstDocument::Paged(paged_doc) => {
|
||||
// todo: svg viewer compatibility
|
||||
type UsingExporter = SvgExporter<PeriscopeExportFeature>;
|
||||
let mut doc = UsingExporter::svg_doc(paged_doc);
|
||||
doc.module.prepare_glyphs();
|
||||
let page0 = doc.pages.get(pos.page.get() - 1)?.clone();
|
||||
let mut svg_text = UsingExporter::render(&doc.module, &[page0.clone()], None);
|
||||
|
||||
// todo: let typst.ts expose it
|
||||
let svg_header = svg_text.get_mut(0)?;
|
||||
// todo: let typst.ts expose it
|
||||
let svg_header = svg_text.get_mut(0)?;
|
||||
|
||||
let y_center = pos.point.y.to_pt() as f32;
|
||||
let y_lo = y_center - self.p.y_above;
|
||||
let y_hi = y_center + self.p.y_below;
|
||||
let y_center = pos.point.y.to_pt() as f32;
|
||||
let y_lo = y_center - self.p.y_above;
|
||||
let y_hi = y_center + self.p.y_below;
|
||||
|
||||
let width = page0.size.x.0;
|
||||
let height = y_hi - y_lo;
|
||||
let width = page0.size.x.0;
|
||||
let height = y_hi - y_lo;
|
||||
|
||||
*svg_header = SvgText::Plain(header_inner(
|
||||
page0.size.x.0,
|
||||
y_lo,
|
||||
y_hi,
|
||||
self.p.scale,
|
||||
self.p.invert_color == "always",
|
||||
));
|
||||
*svg_header = SvgText::Plain(header_inner(
|
||||
page0.size.x.0,
|
||||
y_lo,
|
||||
y_hi,
|
||||
self.p.scale,
|
||||
self.p.invert_color == "always",
|
||||
));
|
||||
|
||||
Some((SvgText::join(svg_text), width, height))
|
||||
Some((SvgText::join(svg_text), width, height))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,9 @@ pub use read::*;
|
|||
mod marker;
|
||||
pub use marker::*;
|
||||
|
||||
#[cfg(feature = "typst")]
|
||||
pub mod typst;
|
||||
|
||||
/// An immutable string.
|
||||
pub type ImmutStr = Arc<str>;
|
||||
/// An immutable byte slice.
|
||||
|
|
|
|||
58
crates/tinymist-std/src/concepts/typst.rs
Normal file
58
crates/tinymist-std/src/concepts/typst.rs
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
//! Re-export of the typst crate.
|
||||
pub(crate) mod well_known {
|
||||
pub use typst::foundations::Bytes;
|
||||
|
||||
pub use typst::utils::LazyHash;
|
||||
|
||||
/// Although this is not good to expose this, we make an alias here to
|
||||
/// let it as a part of typst-ts.
|
||||
pub use typst::syntax::FileId as TypstFileId;
|
||||
|
||||
pub use typst::World as TypstWorld;
|
||||
|
||||
pub use typst::layout::Abs as TypstAbs;
|
||||
|
||||
pub use typst::model::Document as TypstPagedDocument;
|
||||
|
||||
pub use typst::text::Font as TypstFont;
|
||||
|
||||
pub use typst::foundations::Dict as TypstDict;
|
||||
|
||||
pub use typst::foundations::Datetime as TypstDatetime;
|
||||
|
||||
pub use typst::{diag, foundations, syntax};
|
||||
}
|
||||
|
||||
/// The enum of all well-known Typst documents.
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum TypstDocument {
|
||||
/// The document compiled with `paged` target.
|
||||
Paged(Arc<well_known::TypstPagedDocument>),
|
||||
}
|
||||
|
||||
impl TypstDocument {
|
||||
/// Gets details about the document.
|
||||
pub fn info(&self) -> &typst::model::DocumentInfo {
|
||||
match self {
|
||||
Self::Paged(doc) => &doc.info,
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the introspector that can be queried for elements and their
|
||||
/// positions.
|
||||
pub fn introspector(&self) -> &typst::introspection::Introspector {
|
||||
match self {
|
||||
Self::Paged(doc) => &doc.introspector,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
pub use well_known::*;
|
||||
|
||||
/// The prelude of the Typst module.
|
||||
pub mod prelude {
|
||||
pub use comemo::Prehashed;
|
||||
pub use ecow::{eco_format, eco_vec, EcoString, EcoVec};
|
||||
}
|
||||
|
|
@ -1,8 +1,9 @@
|
|||
use std::{collections::BTreeMap, path::Path, sync::Arc};
|
||||
|
||||
use reflexo_typst::{vector::font::GlyphId, TypstDocument, TypstFont};
|
||||
use reflexo_typst::{vector::font::GlyphId, TypstFont};
|
||||
use sync_lsp::LspResult;
|
||||
use tinymist_project::LspCompileSnapshot;
|
||||
use tinymist_std::typst::TypstDocument;
|
||||
use typst::{syntax::VirtualPath, World};
|
||||
|
||||
use crate::world::{base::ShadowApi, EntryState, TaskInputs};
|
||||
|
|
@ -993,7 +994,10 @@ impl ServerState {
|
|||
.map_err(internal_error)?;
|
||||
|
||||
log::debug!("sym doc: {sym_doc:?}");
|
||||
Some(trait_symbol_fonts(&sym_doc.output, &symbols_ref))
|
||||
Some(trait_symbol_fonts(
|
||||
&TypstDocument::Paged(sym_doc.output),
|
||||
&symbols_ref,
|
||||
))
|
||||
};
|
||||
|
||||
let mut glyph_def = String::new();
|
||||
|
|
@ -1111,7 +1115,8 @@ fn trait_symbol_fonts(
|
|||
|
||||
impl Worker<'_> {
|
||||
fn work(&mut self, doc: &TypstDocument) {
|
||||
for (pg, s) in doc.pages.iter().zip(self.symbols.iter()) {
|
||||
let TypstDocument::Paged(paged_doc) = doc;
|
||||
for (pg, s) in paged_doc.pages.iter().zip(self.symbols.iter()) {
|
||||
self.active = s;
|
||||
self.work_frame(&pg.frame);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ use tinymist_project::{
|
|||
ExportTransform, LspCompiledArtifact, Pages, ProjectTask, QueryTask,
|
||||
};
|
||||
use tinymist_std::error::prelude::*;
|
||||
use tinymist_std::typst::TypstDocument;
|
||||
use tokio::sync::mpsc;
|
||||
use typlite::Typlite;
|
||||
use typst::foundations::IntoValue;
|
||||
|
|
@ -76,7 +77,7 @@ impl ExportTask {
|
|||
TaskWhen::Never => false,
|
||||
TaskWhen::OnType => s.by_mem_events,
|
||||
TaskWhen::OnSave => s.by_fs_events,
|
||||
TaskWhen::OnDocumentHasTitle => s.by_fs_events && doc.info.title.is_some(),
|
||||
TaskWhen::OnDocumentHasTitle => s.by_fs_events && doc.info().title.is_some(),
|
||||
};
|
||||
|
||||
if !need_export {
|
||||
|
|
@ -186,7 +187,8 @@ impl ExportTask {
|
|||
let doc = &doc;
|
||||
|
||||
// static BLANK: Lazy<Page> = Lazy::new(Page::default);
|
||||
let first_page = doc.pages.first().unwrap();
|
||||
let TypstDocument::Paged(paged_doc) = &doc;
|
||||
let first_page = paged_doc.pages.first().unwrap();
|
||||
Ok(match kind2 {
|
||||
Preview(..) => vec![],
|
||||
// todo: more pdf flags
|
||||
|
|
@ -202,7 +204,7 @@ impl ExportTask {
|
|||
|
||||
// todo: Some(pdf_uri.as_str())
|
||||
typst_pdf::pdf(
|
||||
doc,
|
||||
paged_doc,
|
||||
&PdfOptions {
|
||||
timestamp: convert_datetime(creation_timestamp),
|
||||
..Default::default()
|
||||
|
|
@ -219,8 +221,9 @@ impl ExportTask {
|
|||
one,
|
||||
}) => {
|
||||
let pretty = false;
|
||||
let elements = reflexo_typst::query::retrieve(&snap.world, &selector, doc)
|
||||
.map_err(|e| anyhow::anyhow!("failed to retrieve: {e}"))?;
|
||||
let elements =
|
||||
reflexo_typst::query::retrieve(&snap.world, &selector, paged_doc)
|
||||
.map_err(|e| anyhow::anyhow!("failed to retrieve: {e}"))?;
|
||||
if one && elements.len() != 1 {
|
||||
bail!("expected exactly one element, found {}", elements.len());
|
||||
}
|
||||
|
|
@ -243,7 +246,7 @@ impl ExportTask {
|
|||
}
|
||||
}
|
||||
ExportHtml(ExportHtmlTask { export: _ }) => {
|
||||
reflexo_vec2svg::render_svg_html::<DefaultExportFeature>(doc).into_bytes()
|
||||
reflexo_vec2svg::render_svg_html::<DefaultExportFeature>(paged_doc).into_bytes()
|
||||
}
|
||||
ExportText(ExportTextTask { export: _ }) => {
|
||||
format!("{}", FullTextDigest(doc.clone())).into_bytes()
|
||||
|
|
@ -261,7 +264,7 @@ impl ExportTask {
|
|||
if is_first {
|
||||
typst_svg::svg(first_page).into_bytes()
|
||||
} else {
|
||||
typst_svg::svg_merged(doc, merged_gap).into_bytes()
|
||||
typst_svg::svg_merged(paged_doc, merged_gap).into_bytes()
|
||||
}
|
||||
}
|
||||
ExportPng(ExportPngTask { export, ppi, fill }) => {
|
||||
|
|
@ -281,7 +284,7 @@ impl ExportTask {
|
|||
let pixmap = if is_first {
|
||||
typst_render::render(first_page, ppi / 72.)
|
||||
} else {
|
||||
typst_render::render_merged(doc, ppi / 72., merged_gap, Some(fill))
|
||||
typst_render::render_merged(paged_doc, ppi / 72., merged_gap, Some(fill))
|
||||
};
|
||||
|
||||
pixmap
|
||||
|
|
|
|||
|
|
@ -15,13 +15,14 @@ use hyper_util::server::graceful::GracefulShutdown;
|
|||
use lsp_types::notification::Notification;
|
||||
use parking_lot::Mutex;
|
||||
use reflexo_typst::debug_loc::SourceSpanOffset;
|
||||
use reflexo_typst::{error::prelude::*, Error, TypstDocument};
|
||||
use reflexo_typst::{error::prelude::*, Error};
|
||||
use serde::Serialize;
|
||||
use serde_json::Value as JsonValue;
|
||||
use sync_lsp::just_ok;
|
||||
use tinymist_assets::TYPST_PREVIEW_HTML;
|
||||
use tinymist_project::ProjectInsId;
|
||||
use tinymist_std::error::IgnoreLogging;
|
||||
use tinymist_std::typst::TypstDocument;
|
||||
use tokio::sync::{mpsc, oneshot};
|
||||
use typst::layout::{Frame, FrameItem, Point, Position};
|
||||
use typst::syntax::{LinkedNode, Source, Span, SyntaxKind};
|
||||
|
|
@ -50,9 +51,10 @@ pub struct PreviewCompileView {
|
|||
}
|
||||
|
||||
impl typst_preview::CompileView for PreviewCompileView {
|
||||
fn doc(&self) -> Option<Arc<TypstDocument>> {
|
||||
fn doc(&self) -> Option<TypstDocument> {
|
||||
self.snap.doc.clone().ok()
|
||||
}
|
||||
|
||||
fn status(&self) -> typst_preview::CompileStatus {
|
||||
match self.snap.doc {
|
||||
Ok(_) => typst_preview::CompileStatus::CompileSuccess,
|
||||
|
|
@ -95,7 +97,7 @@ impl typst_preview::CompileView for PreviewCompileView {
|
|||
let column = src_loc.pos.column;
|
||||
|
||||
let doc = self.snap.success_doc();
|
||||
let Some(doc) = doc.as_deref() else {
|
||||
let Some(doc) = doc.as_ref() else {
|
||||
return vec![];
|
||||
};
|
||||
|
||||
|
|
@ -799,19 +801,23 @@ fn jump_from_cursor(document: &TypstDocument, source: &Source, cursor: usize) ->
|
|||
let mut p = Point::default();
|
||||
|
||||
let span = node.span();
|
||||
let mut positions: Vec<Position> = vec![];
|
||||
for (i, page) in document.pages.iter().enumerate() {
|
||||
let mut min_dis = u64::MAX;
|
||||
if let Some(pos) = find_in_frame(&page.frame, span, &mut min_dis, &mut p) {
|
||||
if let Some(page) = NonZeroUsize::new(i + 1) {
|
||||
positions.push(Position { page, point: pos });
|
||||
match document {
|
||||
TypstDocument::Paged(paged_doc) => {
|
||||
let mut positions: Vec<Position> = vec![];
|
||||
for (i, page) in paged_doc.pages.iter().enumerate() {
|
||||
let mut min_dis = u64::MAX;
|
||||
if let Some(pos) = find_in_frame(&page.frame, span, &mut min_dis, &mut p) {
|
||||
if let Some(page) = NonZeroUsize::new(i + 1) {
|
||||
positions.push(Position { page, point: pos });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log::info!("jump_from_cursor: {positions:#?}");
|
||||
|
||||
positions
|
||||
}
|
||||
}
|
||||
|
||||
log::info!("jump_from_cursor: {positions:#?}");
|
||||
|
||||
positions
|
||||
}
|
||||
|
||||
/// Find the position of a span in a frame.
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
//! Text export utilities.
|
||||
|
||||
use core::fmt;
|
||||
use reflexo_typst::TypstDocument;
|
||||
use std::sync::Arc;
|
||||
use tinymist_std::typst::TypstDocument;
|
||||
|
||||
/// A full text digest of a document.
|
||||
pub struct FullTextDigest(pub Arc<TypstDocument>);
|
||||
pub struct FullTextDigest(pub TypstDocument);
|
||||
|
||||
impl FullTextDigest {
|
||||
fn export_frame(f: &mut fmt::Formatter<'_>, doc: &typst::layout::Frame) -> fmt::Result {
|
||||
|
|
@ -32,9 +31,13 @@ impl FullTextDigest {
|
|||
|
||||
impl fmt::Display for FullTextDigest {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
for page in self.0.pages.iter() {
|
||||
Self::export_frame(f, &page.frame)?;
|
||||
match &self.0 {
|
||||
TypstDocument::Paged(paged_doc) => {
|
||||
for page in paged_doc.pages.iter() {
|
||||
Self::export_frame(f, &page.frame)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,8 @@ use std::sync::Arc;
|
|||
|
||||
use reflexo_typst::{debug_loc::SourceSpanOffset, exporter_utils::map_err};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use typst::{model::Document, syntax::Span, text::TextItem};
|
||||
use tinymist_std::typst::TypstDocument;
|
||||
use typst::{syntax::Span, text::TextItem};
|
||||
use unicode_script::{Script, UnicodeScript};
|
||||
|
||||
/// Words count for a document.
|
||||
|
|
@ -25,7 +26,7 @@ pub struct WordsCount {
|
|||
}
|
||||
|
||||
/// Count words in a document.
|
||||
pub fn word_count(doc: &Document) -> WordsCount {
|
||||
pub fn word_count(doc: &TypstDocument) -> WordsCount {
|
||||
// the mapping is still not use, so we prevent the warning here
|
||||
let _ = TextContent::map_back_spans;
|
||||
|
||||
|
|
@ -97,7 +98,7 @@ pub struct TextExporter {}
|
|||
|
||||
impl TextExporter {
|
||||
/// Collect text content from a document.
|
||||
pub fn collect(&self, output: &Document) -> typst::diag::SourceResult<String> {
|
||||
pub fn collect(&self, output: &TypstDocument) -> typst::diag::SourceResult<String> {
|
||||
let w = std::io::BufWriter::new(Vec::new());
|
||||
|
||||
let mut d = TextExportWorker { w };
|
||||
|
|
@ -113,11 +114,15 @@ struct TextExportWorker {
|
|||
}
|
||||
|
||||
impl TextExportWorker {
|
||||
fn doc(&mut self, doc: &Document) -> io::Result<()> {
|
||||
for page in doc.pages.iter() {
|
||||
self.frame(&page.frame)?;
|
||||
fn doc(&mut self, doc: &TypstDocument) -> io::Result<()> {
|
||||
match doc {
|
||||
TypstDocument::Paged(paged_doc) => {
|
||||
for page in paged_doc.pages.iter() {
|
||||
self.frame(&page.frame)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn frame(&mut self, doc: &typst::layout::Frame) -> io::Result<()> {
|
||||
|
|
@ -159,7 +164,7 @@ pub struct TextContent {
|
|||
/// A string of the content for slicing.
|
||||
pub content: String,
|
||||
/// annotating document.
|
||||
pub doc: Arc<Document>,
|
||||
pub doc: Arc<TypstDocument>,
|
||||
}
|
||||
|
||||
impl TextContent {
|
||||
|
|
@ -197,9 +202,13 @@ struct SpanMapper {
|
|||
}
|
||||
|
||||
impl SpanMapper {
|
||||
fn doc(&mut self, doc: &Document) {
|
||||
for page in doc.pages.iter() {
|
||||
self.frame(&page.frame);
|
||||
fn doc(&mut self, doc: &TypstDocument) {
|
||||
match doc {
|
||||
TypstDocument::Paged(paged_doc) => {
|
||||
for page in paged_doc.pages.iter() {
|
||||
self.frame(&page.frame);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ rust-version.workspace = true
|
|||
[dependencies]
|
||||
typst.workspace = true
|
||||
tinymist-assets.workspace = true
|
||||
tinymist-std.workspace = true
|
||||
typst-assets.workspace = true
|
||||
comemo.workspace = true
|
||||
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ use std::sync::Arc;
|
|||
use reflexo_typst::debug_loc::{
|
||||
CharPosition, DocumentPosition, ElementPoint, SourceLocation, SourceSpanOffset,
|
||||
};
|
||||
use reflexo_typst::TypstDocument;
|
||||
use reflexo_vec2svg::IncrSvgDocServer;
|
||||
use tinymist_std::typst::TypstDocument;
|
||||
use tokio::sync::{broadcast, mpsc};
|
||||
|
||||
use super::{editor::EditorActorRequest, webview::WebviewActorRequest};
|
||||
|
|
@ -138,6 +138,9 @@ impl RenderActor {
|
|||
log::info!("RenderActor: document is not ready");
|
||||
continue;
|
||||
};
|
||||
|
||||
let TypstDocument::Paged(document) = document;
|
||||
|
||||
let data = if has_full_render {
|
||||
if let Some(data) = self.renderer.pack_current() {
|
||||
data
|
||||
|
|
|
|||
|
|
@ -15,8 +15,8 @@ use futures::sink::SinkExt;
|
|||
use once_cell::sync::OnceCell;
|
||||
use reflexo_typst::debug_loc::SourceSpanOffset;
|
||||
use reflexo_typst::Error;
|
||||
use reflexo_typst::TypstDocument as Document;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tinymist_std::typst::TypstDocument;
|
||||
use tokio::sync::{broadcast, mpsc};
|
||||
use typst::{layout::Position, syntax::Span};
|
||||
|
||||
|
|
@ -355,7 +355,7 @@ pub struct MemoryFilesShort {
|
|||
|
||||
pub trait CompileView: Send + Sync {
|
||||
/// Get the compiled document.
|
||||
fn doc(&self) -> Option<Arc<Document>>;
|
||||
fn doc(&self) -> Option<TypstDocument>;
|
||||
/// Get the compile status.
|
||||
fn status(&self) -> CompileStatus;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
use std::num::NonZeroUsize;
|
||||
|
||||
use reflexo_typst::debug_loc::DocumentPosition;
|
||||
use reflexo_typst::TypstDocument;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tinymist_std::typst::TypstDocument;
|
||||
use typst::foundations::{Content, NativeElement, Packed, StyleChain};
|
||||
use typst::introspection::Introspector;
|
||||
use typst::model::HeadingElem;
|
||||
|
|
@ -140,7 +140,7 @@ struct OutlineItem {
|
|||
}
|
||||
|
||||
pub fn outline(interner: &mut SpanInternerImpl, document: &TypstDocument) -> Outline {
|
||||
let outline = get_outline(&document.introspector);
|
||||
let outline = get_outline(document.introspector());
|
||||
let mut items = Vec::with_capacity(outline.as_ref().map_or(0, Vec::len));
|
||||
|
||||
for heading in outline.iter().flatten() {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue