mirror of
https://github.com/Myriad-Dreamin/tinymist.git
synced 2025-11-22 12:34:39 +00:00
feat: compile tinymist-query for wasm32 target (#1947)
- #2025 - #2026 --------- Co-authored-by: Momijiichigo <ichigomomiji436@gmail.com>
This commit is contained in:
parent
b102b42d2c
commit
79f68dc94d
12 changed files with 191 additions and 88 deletions
3
Cargo.lock
generated
3
Cargo.lock
generated
|
|
@ -4250,7 +4250,8 @@ dependencies = [
|
||||||
"console_error_panic_hook",
|
"console_error_panic_hook",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"reflexo-typst",
|
"reflexo-typst",
|
||||||
"tinymist-world",
|
"tinymist-project",
|
||||||
|
"tinymist-query",
|
||||||
"vergen",
|
"vergen",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ web = [
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"console_error_panic_hook",
|
"console_error_panic_hook",
|
||||||
"no-content-hint",
|
"no-content-hint",
|
||||||
"tinymist-world/web",
|
"tinymist-project/web",
|
||||||
"reflexo-typst/web",
|
"reflexo-typst/web",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -31,7 +31,8 @@ no-content-hint = ["reflexo-typst/no-content-hint"]
|
||||||
[dependencies]
|
[dependencies]
|
||||||
wasm-bindgen = { version = "0.2.100", optional = true }
|
wasm-bindgen = { version = "0.2.100", optional = true }
|
||||||
js-sys = { version = "0.3.77", optional = true }
|
js-sys = { version = "0.3.77", optional = true }
|
||||||
tinymist-world.workspace = true
|
tinymist-project.workspace = true
|
||||||
|
tinymist-query.workspace = true
|
||||||
reflexo-typst.workspace = true
|
reflexo-typst.workspace = true
|
||||||
|
|
||||||
console_error_panic_hook = { version = "0.1.2", optional = true }
|
console_error_panic_hook = { version = "0.1.2", optional = true }
|
||||||
|
|
|
||||||
|
|
@ -40,9 +40,11 @@ notify.workspace = true
|
||||||
|
|
||||||
fonts = ["typst-assets/fonts"]
|
fonts = ["typst-assets/fonts"]
|
||||||
no-content-hint = ["tinymist-task/no-content-hint"]
|
no-content-hint = ["tinymist-task/no-content-hint"]
|
||||||
lsp = ["system", "toml"]
|
lsp = ["toml"]
|
||||||
|
# "system",
|
||||||
|
|
||||||
system = ["tinymist-std/system", "tinymist-world/system"]
|
system = ["tinymist-std/system", "tinymist-world/system"]
|
||||||
|
web = ["tinymist-std/web", "tinymist-world/web"]
|
||||||
|
|
||||||
[lints]
|
[lints]
|
||||||
workspace = true
|
workspace = true
|
||||||
|
|
|
||||||
|
|
@ -11,22 +11,20 @@ mod lock;
|
||||||
mod lsp;
|
mod lsp;
|
||||||
#[cfg(feature = "system")]
|
#[cfg(feature = "system")]
|
||||||
mod watch;
|
mod watch;
|
||||||
#[cfg(feature = "system")]
|
|
||||||
pub mod world;
|
pub mod world;
|
||||||
|
|
||||||
pub use args::*;
|
pub use args::*;
|
||||||
pub use compiler::*;
|
pub use compiler::*;
|
||||||
pub use entry::*;
|
pub use entry::*;
|
||||||
pub use model::*;
|
|
||||||
|
|
||||||
#[cfg(feature = "lsp")]
|
|
||||||
pub use lock::*;
|
pub use lock::*;
|
||||||
|
pub use model::*;
|
||||||
|
pub use world::*;
|
||||||
|
|
||||||
#[cfg(feature = "lsp")]
|
#[cfg(feature = "lsp")]
|
||||||
pub use lsp::*;
|
pub use lsp::*;
|
||||||
#[cfg(feature = "system")]
|
#[cfg(feature = "system")]
|
||||||
pub use watch::*;
|
pub use watch::*;
|
||||||
#[cfg(feature = "system")]
|
|
||||||
pub use world::*;
|
|
||||||
|
|
||||||
pub use tinymist_world::{CompileSignal, CompileSnapshot, ProjectInsId};
|
pub use tinymist_world::{CompileSignal, CompileSnapshot, ProjectInsId};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,24 +1,20 @@
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::{borrow::Cow, sync::Arc};
|
use std::sync::Arc;
|
||||||
|
|
||||||
use tinymist_std::error::prelude::*;
|
use tinymist_std::error::prelude::*;
|
||||||
use tinymist_std::{bail, ImmutPath};
|
use tinymist_std::ImmutPath;
|
||||||
use tinymist_task::ExportTarget;
|
use tinymist_task::ExportTarget;
|
||||||
use tinymist_world::config::CompileFontOpts;
|
use tinymist_world::package::RegistryPathMapper;
|
||||||
use tinymist_world::font::system::SystemFontSearcher;
|
use tinymist_world::vfs::Vfs;
|
||||||
use tinymist_world::package::{registry::HttpRegistry, RegistryPathMapper};
|
|
||||||
use tinymist_world::vfs::{system::SystemAccessModel, Vfs};
|
|
||||||
use tinymist_world::{args::*, WorldComputeGraph};
|
use tinymist_world::{args::*, WorldComputeGraph};
|
||||||
use tinymist_world::{
|
use tinymist_world::{
|
||||||
CompileSnapshot, CompilerFeat, CompilerUniverse, CompilerWorld, EntryOpts, EntryState,
|
CompileSnapshot, CompilerFeat, CompilerUniverse, CompilerWorld, EntryOpts, EntryState,
|
||||||
};
|
};
|
||||||
use typst::diag::FileResult;
|
use typst::diag::FileResult;
|
||||||
use typst::foundations::{Bytes, Dict, Str, Value};
|
use typst::foundations::{Bytes, Dict};
|
||||||
use typst::utils::LazyHash;
|
use typst::utils::LazyHash;
|
||||||
use typst::Features;
|
use typst::Features;
|
||||||
|
|
||||||
use crate::ProjectInput;
|
|
||||||
|
|
||||||
use crate::world::font::FontResolverImpl;
|
use crate::world::font::FontResolverImpl;
|
||||||
use crate::{CompiledArtifact, Interrupt};
|
use crate::{CompiledArtifact, Interrupt};
|
||||||
|
|
||||||
|
|
@ -33,7 +29,11 @@ impl CompilerFeat for LspCompilerFeat {
|
||||||
/// It accesses a physical file system.
|
/// It accesses a physical file system.
|
||||||
type AccessModel = DynAccessModel;
|
type AccessModel = DynAccessModel;
|
||||||
/// It performs native HTTP requests for fetching package data.
|
/// It performs native HTTP requests for fetching package data.
|
||||||
type Registry = HttpRegistry;
|
#[cfg(feature = "system")]
|
||||||
|
type Registry = tinymist_world::package::registry::HttpRegistry;
|
||||||
|
// todo: registry in browser
|
||||||
|
#[cfg(not(feature = "system"))]
|
||||||
|
type Registry = tinymist_world::package::registry::DummyRegistry;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// LSP universe that spawns LSP worlds.
|
/// LSP universe that spawns LSP worlds.
|
||||||
|
|
@ -59,6 +59,7 @@ pub trait WorldProvider {
|
||||||
fn resolve(&self) -> Result<LspUniverse>;
|
fn resolve(&self) -> Result<LspUniverse>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "system")]
|
||||||
impl WorldProvider for CompileOnceArgs {
|
impl WorldProvider for CompileOnceArgs {
|
||||||
fn resolve(&self) -> Result<LspUniverse> {
|
fn resolve(&self) -> Result<LspUniverse> {
|
||||||
let entry = self.entry()?.try_into()?;
|
let entry = self.entry()?.try_into()?;
|
||||||
|
|
@ -78,7 +79,7 @@ impl WorldProvider for CompileOnceArgs {
|
||||||
packages,
|
packages,
|
||||||
fonts,
|
fonts,
|
||||||
self.creation_timestamp,
|
self.creation_timestamp,
|
||||||
DynAccessModel(Arc::new(SystemAccessModel {})),
|
DynAccessModel(Arc::new(tinymist_world::vfs::system::SystemAccessModel {})),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -129,8 +130,11 @@ impl WorldProvider for CompileOnceArgs {
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo: merge me with the above impl
|
// todo: merge me with the above impl
|
||||||
impl WorldProvider for (ProjectInput, ImmutPath) {
|
#[cfg(feature = "system")]
|
||||||
|
impl WorldProvider for (crate::ProjectInput, ImmutPath) {
|
||||||
fn resolve(&self) -> Result<LspUniverse> {
|
fn resolve(&self) -> Result<LspUniverse> {
|
||||||
|
use typst::foundations::{Str, Value};
|
||||||
|
|
||||||
let (proj, lock_dir) = self;
|
let (proj, lock_dir) = self;
|
||||||
let entry = self.entry()?.try_into()?;
|
let entry = self.entry()?.try_into()?;
|
||||||
let inputs = proj
|
let inputs = proj
|
||||||
|
|
@ -172,7 +176,7 @@ impl WorldProvider for (ProjectInput, ImmutPath) {
|
||||||
packages,
|
packages,
|
||||||
Arc::new(fonts),
|
Arc::new(fonts),
|
||||||
None, // creation_timestamp - not available in project file context
|
None, // creation_timestamp - not available in project file context
|
||||||
DynAccessModel(Arc::new(SystemAccessModel {})),
|
DynAccessModel(Arc::new(tinymist_world::vfs::system::SystemAccessModel {})),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -207,6 +211,11 @@ impl WorldProvider for (ProjectInput, ImmutPath) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "system"))]
|
||||||
|
type LspRegistry = tinymist_world::package::registry::DummyRegistry;
|
||||||
|
#[cfg(feature = "system")]
|
||||||
|
type LspRegistry = tinymist_world::package::registry::HttpRegistry;
|
||||||
|
|
||||||
/// Builder for LSP universe.
|
/// Builder for LSP universe.
|
||||||
pub struct LspUniverseBuilder;
|
pub struct LspUniverseBuilder;
|
||||||
|
|
||||||
|
|
@ -219,7 +228,7 @@ impl LspUniverseBuilder {
|
||||||
export_target: ExportTarget,
|
export_target: ExportTarget,
|
||||||
features: Features,
|
features: Features,
|
||||||
inputs: ImmutDict,
|
inputs: ImmutDict,
|
||||||
package_registry: HttpRegistry,
|
package_registry: LspRegistry,
|
||||||
font_resolver: Arc<FontResolverImpl>,
|
font_resolver: Arc<FontResolverImpl>,
|
||||||
creation_timestamp: Option<i64>,
|
creation_timestamp: Option<i64>,
|
||||||
access_model: DynAccessModel,
|
access_model: DynAccessModel,
|
||||||
|
|
@ -246,38 +255,54 @@ impl LspUniverseBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Resolve fonts from given options.
|
/// Resolve fonts from given options.
|
||||||
|
#[cfg(feature = "system")]
|
||||||
pub fn only_embedded_fonts() -> Result<FontResolverImpl> {
|
pub fn only_embedded_fonts() -> Result<FontResolverImpl> {
|
||||||
let mut searcher = SystemFontSearcher::new();
|
let mut searcher = tinymist_world::font::system::SystemFontSearcher::new();
|
||||||
searcher.resolve_opts(CompileFontOpts {
|
searcher.resolve_opts(tinymist_world::config::CompileFontOpts {
|
||||||
font_paths: vec![],
|
font_paths: vec![],
|
||||||
no_system_fonts: true,
|
no_system_fonts: true,
|
||||||
with_embedded_fonts: typst_assets::fonts().map(Cow::Borrowed).collect(),
|
with_embedded_fonts: typst_assets::fonts()
|
||||||
|
.map(std::borrow::Cow::Borrowed)
|
||||||
|
.collect(),
|
||||||
})?;
|
})?;
|
||||||
Ok(searcher.build())
|
Ok(searcher.build())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Resolve fonts from given options.
|
/// Resolve fonts from given options.
|
||||||
|
#[cfg(feature = "system")]
|
||||||
pub fn resolve_fonts(args: CompileFontArgs) -> Result<FontResolverImpl> {
|
pub fn resolve_fonts(args: CompileFontArgs) -> Result<FontResolverImpl> {
|
||||||
let mut searcher = SystemFontSearcher::new();
|
let mut searcher = tinymist_world::font::system::SystemFontSearcher::new();
|
||||||
searcher.resolve_opts(CompileFontOpts {
|
searcher.resolve_opts(tinymist_world::config::CompileFontOpts {
|
||||||
font_paths: args.font_paths,
|
font_paths: args.font_paths,
|
||||||
no_system_fonts: args.ignore_system_fonts,
|
no_system_fonts: args.ignore_system_fonts,
|
||||||
with_embedded_fonts: typst_assets::fonts().map(Cow::Borrowed).collect(),
|
with_embedded_fonts: typst_assets::fonts()
|
||||||
|
.map(std::borrow::Cow::Borrowed)
|
||||||
|
.collect(),
|
||||||
})?;
|
})?;
|
||||||
Ok(searcher.build())
|
Ok(searcher.build())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Resolve package registry from given options.
|
/// Resolves package registry from given options.
|
||||||
|
#[cfg(feature = "system")]
|
||||||
pub fn resolve_package(
|
pub fn resolve_package(
|
||||||
cert_path: Option<ImmutPath>,
|
cert_path: Option<ImmutPath>,
|
||||||
args: Option<&CompilePackageArgs>,
|
args: Option<&CompilePackageArgs>,
|
||||||
) -> HttpRegistry {
|
) -> tinymist_world::package::registry::HttpRegistry {
|
||||||
HttpRegistry::new(
|
tinymist_world::package::registry::HttpRegistry::new(
|
||||||
cert_path,
|
cert_path,
|
||||||
args.and_then(|args| Some(args.package_path.clone()?.into())),
|
args.and_then(|args| Some(args.package_path.clone()?.into())),
|
||||||
args.and_then(|args| Some(args.package_cache_path.clone()?.into())),
|
args.and_then(|args| Some(args.package_cache_path.clone()?.into())),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Resolves package registry from given options.
|
||||||
|
#[cfg(not(feature = "system"))]
|
||||||
|
pub fn resolve_package(
|
||||||
|
_cert_path: Option<ImmutPath>,
|
||||||
|
_args: Option<&CompilePackageArgs>,
|
||||||
|
) -> tinymist_world::package::registry::DummyRegistry {
|
||||||
|
tinymist_world::package::registry::DummyRegistry
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Access model for LSP universe and worlds.
|
/// Access model for LSP universe and worlds.
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,11 @@ pub use tinymist_world as base;
|
||||||
pub use tinymist_world::args::*;
|
pub use tinymist_world::args::*;
|
||||||
pub use tinymist_world::config::CompileFontOpts;
|
pub use tinymist_world::config::CompileFontOpts;
|
||||||
pub use tinymist_world::entry::*;
|
pub use tinymist_world::entry::*;
|
||||||
pub use tinymist_world::{diag, font, package, system, vfs};
|
pub use tinymist_world::{diag, font, package, vfs};
|
||||||
pub use tinymist_world::{
|
pub use tinymist_world::{
|
||||||
with_main, CompilerUniverse, CompilerWorld, DiagnosticFormat, EntryOpts, EntryState,
|
with_main, CompilerUniverse, CompilerWorld, DiagnosticFormat, EntryOpts, EntryState,
|
||||||
RevisingUniverse, SourceWorld, TaskInputs,
|
RevisingUniverse, SourceWorld, TaskInputs,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[cfg(feature = "system")]
|
||||||
|
pub use tinymist_world::system;
|
||||||
|
|
|
||||||
|
|
@ -209,26 +209,28 @@ impl TypeCompletionWorker<'_, '_, '_, '_> {
|
||||||
BuiltinTy::TextSize => return None,
|
BuiltinTy::TextSize => return None,
|
||||||
BuiltinTy::TextLang => {
|
BuiltinTy::TextLang => {
|
||||||
for (&key, desc) in rust_iso639::ALL_MAP.entries() {
|
for (&key, desc) in rust_iso639::ALL_MAP.entries() {
|
||||||
let detail = eco_format!("An ISO 639-1/2/3 language code, {}.", desc.name);
|
let detail =
|
||||||
|
eco_format!("An ISO 639-1/2/3 language code, {}.", desc.get_name());
|
||||||
self.base.push_completion(Completion {
|
self.base.push_completion(Completion {
|
||||||
kind: CompletionKind::Syntax,
|
kind: CompletionKind::Syntax,
|
||||||
label: key.to_lowercase().into(),
|
label: key.to_lowercase().into(),
|
||||||
apply: Some(eco_format!("\"{}\"", key.to_lowercase())),
|
apply: Some(eco_format!("\"{}\"", key.to_lowercase())),
|
||||||
detail: Some(detail),
|
detail: Some(detail),
|
||||||
label_details: Some(desc.name.into()),
|
label_details: Some(desc.get_name()),
|
||||||
..Completion::default()
|
..Completion::default()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BuiltinTy::TextRegion => {
|
BuiltinTy::TextRegion => {
|
||||||
for (&key, desc) in rust_iso3166::ALPHA2_MAP.entries() {
|
for (&key, desc) in rust_iso3166::ALPHA2_MAP.entries() {
|
||||||
let detail = eco_format!("An ISO 3166-1 alpha-2 region code, {}.", desc.name);
|
let detail =
|
||||||
|
eco_format!("An ISO 3166-1 alpha-2 region code, {}.", desc.get_name());
|
||||||
self.base.push_completion(Completion {
|
self.base.push_completion(Completion {
|
||||||
kind: CompletionKind::Syntax,
|
kind: CompletionKind::Syntax,
|
||||||
label: key.to_lowercase().into(),
|
label: key.to_lowercase().into(),
|
||||||
apply: Some(eco_format!("\"{}\"", key.to_lowercase())),
|
apply: Some(eco_format!("\"{}\"", key.to_lowercase())),
|
||||||
detail: Some(detail),
|
detail: Some(detail),
|
||||||
label_details: Some(desc.name.into()),
|
label_details: Some(desc.get_name()),
|
||||||
..Completion::default()
|
..Completion::default()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -346,3 +348,37 @@ impl TypeCompletionWorker<'_, '_, '_, '_> {
|
||||||
Some(())
|
Some(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// desc.name()
|
||||||
|
|
||||||
|
trait GetName {
|
||||||
|
fn get_name(&self) -> EcoString;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
impl GetName for rust_iso639::LanguageCode<'_> {
|
||||||
|
fn get_name(&self) -> EcoString {
|
||||||
|
self.name.into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(all(direct_wasm, target_arch = "wasm32")))]
|
||||||
|
impl GetName for rust_iso3166::CountryCode {
|
||||||
|
fn get_name(&self) -> EcoString {
|
||||||
|
self.name.into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
impl GetName for rust_iso639::LanguageCode {
|
||||||
|
fn get_name(&self) -> EcoString {
|
||||||
|
self.name().into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(all(direct_wasm, target_arch = "wasm32"))]
|
||||||
|
impl GetName for rust_iso3166::CountryCode {
|
||||||
|
fn get_name(&self) -> EcoString {
|
||||||
|
self.name().into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,9 +20,7 @@ use tinymist_std::typst::TypstDocument;
|
||||||
use tinymist_world::debug_loc::DataSource;
|
use tinymist_world::debug_loc::DataSource;
|
||||||
use tinymist_world::vfs::{PathResolution, WorkspaceResolver};
|
use tinymist_world::vfs::{PathResolution, WorkspaceResolver};
|
||||||
use tinymist_world::{EntryReader, DETACHED_ENTRY};
|
use tinymist_world::{EntryReader, DETACHED_ENTRY};
|
||||||
use typst::diag::{
|
use typst::diag::{At, FileError, FileResult, SourceDiagnostic, SourceResult, StrResult};
|
||||||
eco_format, At, FileError, FileResult, SourceDiagnostic, SourceResult, StrResult,
|
|
||||||
};
|
|
||||||
use typst::foundations::{Bytes, IntoValue, Module, StyleChain, Styles};
|
use typst::foundations::{Bytes, IntoValue, Module, StyleChain, Styles};
|
||||||
use typst::introspection::Introspector;
|
use typst::introspection::Introspector;
|
||||||
use typst::layout::Position;
|
use typst::layout::Position;
|
||||||
|
|
@ -674,6 +672,7 @@ impl SharedContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the local packages and their descriptions.
|
/// Get the local packages and their descriptions.
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
pub fn local_packages(&self) -> EcoVec<PackageSpec> {
|
pub fn local_packages(&self) -> EcoVec<PackageSpec> {
|
||||||
crate::package::list_package_by_namespace(&self.world.registry, eco_format!("local"))
|
crate::package::list_package_by_namespace(&self.world.registry, eco_format!("local"))
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
|
@ -681,6 +680,12 @@ impl SharedContext {
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the local packages and their descriptions.
|
||||||
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
pub fn local_packages(&self) -> EcoVec<PackageSpec> {
|
||||||
|
eco_vec![]
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn const_eval(rr: ast::Expr<'_>) -> Option<Value> {
|
pub(crate) fn const_eval(rr: ast::Expr<'_>) -> Option<Value> {
|
||||||
Some(match rr {
|
Some(match rr {
|
||||||
ast::Expr::None(_) => Value::None,
|
ast::Expr::None(_) => Value::None,
|
||||||
|
|
|
||||||
|
|
@ -31,11 +31,7 @@ pub fn path_to_url(path: &Path) -> anyhow::Result<Url> {
|
||||||
return untitled_url(untitled);
|
return untitled_url(untitled);
|
||||||
}
|
}
|
||||||
|
|
||||||
Url::from_file_path(path).or_else(|never| {
|
url_from_file_path(path)
|
||||||
let _: () = never;
|
|
||||||
|
|
||||||
anyhow::bail!("could not convert path to URI: path: {path:?}",)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert a path resolution to a URL.
|
/// Convert a path resolution to a URL.
|
||||||
|
|
@ -54,9 +50,7 @@ pub fn url_to_path(uri: Url) -> PathBuf {
|
||||||
return PathBuf::from("/untitled/nEoViM-BuG");
|
return PathBuf::from("/untitled/nEoViM-BuG");
|
||||||
}
|
}
|
||||||
|
|
||||||
return uri
|
return url_to_file_path(&uri);
|
||||||
.to_file_path()
|
|
||||||
.unwrap_or_else(|_| panic!("could not convert URI to path: URI: {uri:?}",));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if uri.scheme() == "untitled" {
|
if uri.scheme() == "untitled" {
|
||||||
|
|
@ -73,7 +67,40 @@ pub fn url_to_path(uri: Url) -> PathBuf {
|
||||||
return Path::new(String::from_utf8_lossy(&bytes).as_ref()).clean();
|
return Path::new(String::from_utf8_lossy(&bytes).as_ref()).clean();
|
||||||
}
|
}
|
||||||
|
|
||||||
uri.to_file_path().unwrap()
|
url_to_file_path(&uri)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
fn url_from_file_path(path: &Path) -> anyhow::Result<Url> {
|
||||||
|
Url::from_file_path(path).or_else(|never| {
|
||||||
|
let _: () = never;
|
||||||
|
|
||||||
|
anyhow::bail!("could not convert path to URI: path: {path:?}",)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
fn url_from_file_path(path: &Path) -> anyhow::Result<Url> {
|
||||||
|
// In WASM, create a simple file:// URL
|
||||||
|
let path_str = path.to_string_lossy();
|
||||||
|
let url_str = if path_str.starts_with('/') {
|
||||||
|
format!("file://{}", path_str)
|
||||||
|
} else {
|
||||||
|
format!("file:///{}", path_str)
|
||||||
|
};
|
||||||
|
Url::parse(&url_str).map_err(|e| anyhow::anyhow!("could not convert path to URI: {}", e))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
fn url_to_file_path(uri: &Url) -> PathBuf {
|
||||||
|
uri.to_file_path()
|
||||||
|
.unwrap_or_else(|_| panic!("could not convert URI to path: URI: {uri:?}",))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
fn url_to_file_path(uri: &Url) -> PathBuf {
|
||||||
|
// In WASM, manually parse the URL path
|
||||||
|
PathBuf::from(uri.path())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,10 @@
|
||||||
//! Package management tools.
|
//! Package management tools.
|
||||||
|
|
||||||
use std::collections::HashSet;
|
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::sync::OnceLock;
|
|
||||||
|
|
||||||
use ecow::{eco_format, eco_vec, EcoVec};
|
use ecow::eco_format;
|
||||||
use parking_lot::Mutex;
|
|
||||||
// use reflexo_typst::typst::prelude::*;
|
// use reflexo_typst::typst::prelude::*;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tinymist_world::package::registry::HttpRegistry;
|
|
||||||
use tinymist_world::package::PackageSpec;
|
use tinymist_world::package::PackageSpec;
|
||||||
use typst::diag::{EcoString, StrResult};
|
use typst::diag::{EcoString, StrResult};
|
||||||
use typst::syntax::package::PackageManifest;
|
use typst::syntax::package::PackageManifest;
|
||||||
|
|
@ -77,11 +73,47 @@ pub fn check_package(ctx: &mut LocalContext, spec: &PackageInfo) -> StrResult<()
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
/// Get the packages in namespaces and their descriptions.
|
/// Get the packages in namespaces and their descriptions.
|
||||||
pub fn list_package_by_namespace(
|
pub fn list_package_by_namespace(
|
||||||
registry: &HttpRegistry,
|
registry: &tinymist_world::package::registry::HttpRegistry,
|
||||||
ns: EcoString,
|
ns: EcoString,
|
||||||
) -> EcoVec<(PathBuf, PackageSpec)> {
|
) -> ecow::EcoVec<(PathBuf, PackageSpec)> {
|
||||||
|
use std::collections::HashSet;
|
||||||
|
use std::sync::OnceLock;
|
||||||
|
|
||||||
|
use ecow::eco_vec;
|
||||||
|
use parking_lot::Mutex;
|
||||||
|
|
||||||
|
trait IsDirFollowLinks {
|
||||||
|
fn is_dir_follow_links(&self) -> bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IsDirFollowLinks for PathBuf {
|
||||||
|
fn is_dir_follow_links(&self) -> bool {
|
||||||
|
// Although `canonicalize` is heavy, we must use it because `symlink_metadata`
|
||||||
|
// is not reliable.
|
||||||
|
self.canonicalize()
|
||||||
|
.map(|meta| meta.is_dir())
|
||||||
|
.unwrap_or(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn once_log<T, E: std::fmt::Display>(result: Result<T, E>, site: &'static str) -> Option<T> {
|
||||||
|
let err = match result {
|
||||||
|
Ok(value) => return Some(value),
|
||||||
|
Err(err) => err,
|
||||||
|
};
|
||||||
|
|
||||||
|
static ONCE: OnceLock<Mutex<HashSet<&'static str>>> = OnceLock::new();
|
||||||
|
let mut once = ONCE.get_or_init(Default::default).lock();
|
||||||
|
if once.insert(site) {
|
||||||
|
log::error!("failed to perform {site}: {err}");
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
// search packages locally. We only search in the data
|
// search packages locally. We only search in the data
|
||||||
// directory and not the cache directory, because the latter is not
|
// directory and not the cache directory, because the latter is not
|
||||||
// intended for storage of local packages.
|
// intended for storage of local packages.
|
||||||
|
|
@ -148,32 +180,3 @@ pub fn list_package_by_namespace(
|
||||||
|
|
||||||
packages
|
packages
|
||||||
}
|
}
|
||||||
|
|
||||||
trait IsDirFollowLinks {
|
|
||||||
fn is_dir_follow_links(&self) -> bool;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl IsDirFollowLinks for PathBuf {
|
|
||||||
fn is_dir_follow_links(&self) -> bool {
|
|
||||||
// Although `canonicalize` is heavy, we must use it because `symlink_metadata`
|
|
||||||
// is not reliable.
|
|
||||||
self.canonicalize()
|
|
||||||
.map(|meta| meta.is_dir())
|
|
||||||
.unwrap_or(false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn once_log<T, E: std::fmt::Display>(result: Result<T, E>, site: &'static str) -> Option<T> {
|
|
||||||
let err = match result {
|
|
||||||
Ok(value) => return Some(value),
|
|
||||||
Err(err) => err,
|
|
||||||
};
|
|
||||||
|
|
||||||
static ONCE: OnceLock<Mutex<HashSet<&'static str>>> = OnceLock::new();
|
|
||||||
let mut once = ONCE.get_or_init(Default::default).lock();
|
|
||||||
if once.insert(site) {
|
|
||||||
log::error!("failed to perform {site}: {err}");
|
|
||||||
}
|
|
||||||
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -814,7 +814,6 @@ impl<F: CompilerFeat> World for CompilerWorld<F> {
|
||||||
if let Some(timestamp) = self.creation_timestamp {
|
if let Some(timestamp) = self.creation_timestamp {
|
||||||
tinymist_std::time::UtcDateTime::from_unix_timestamp(timestamp)
|
tinymist_std::time::UtcDateTime::from_unix_timestamp(timestamp)
|
||||||
.unwrap_or_else(|_| now().into())
|
.unwrap_or_else(|_| now().into())
|
||||||
.into()
|
|
||||||
} else {
|
} else {
|
||||||
now().into()
|
now().into()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -51,10 +51,13 @@ clap = ["dep:clap"]
|
||||||
# Note: this is the feature for typlite as a CLI, not for others.
|
# Note: this is the feature for typlite as a CLI, not for others.
|
||||||
# `docx` is enabled in CLI mode, but not in library mode.
|
# `docx` is enabled in CLI mode, but not in library mode.
|
||||||
# `fonts` is enabled in CLI mode.
|
# `fonts` is enabled in CLI mode.
|
||||||
cli = ["clap", "clap/wrap_help", "docx", "fonts"]
|
cli = ["clap", "clap/wrap_help", "docx", "fonts", "system"]
|
||||||
no-content-hint = ["tinymist-project/no-content-hint"]
|
no-content-hint = ["tinymist-project/no-content-hint"]
|
||||||
docx = ["docx-rs", "image", "resvg"]
|
docx = ["docx-rs", "image", "resvg"]
|
||||||
|
|
||||||
|
system = ["tinymist-project/system"]
|
||||||
|
web = ["tinymist-project/web"]
|
||||||
|
|
||||||
# Embeds Typst's default fonts for
|
# Embeds Typst's default fonts for
|
||||||
# - text (Linux Libertine),
|
# - text (Linux Libertine),
|
||||||
# - math (New Computer Modern Math), and
|
# - math (New Computer Modern Math), and
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue