mirror of
https://github.com/Myriad-Dreamin/tinymist.git
synced 2025-07-19 18:55:01 +00:00
feat: render examples in docs (#772)
* feat: render examples in docs * fix: create `hover-images` on `startHover` * dev: update snapshot
This commit is contained in:
parent
d02fa18617
commit
d75fd7e74e
17 changed files with 334 additions and 74 deletions
|
@ -36,7 +36,7 @@ use crate::syntax::{
|
|||
};
|
||||
use crate::upstream::{tooltip_, Tooltip};
|
||||
use crate::{
|
||||
lsp_to_typst, path_to_url, typst_to_lsp, LspPosition, LspRange, PositionEncoding,
|
||||
lsp_to_typst, path_to_url, typst_to_lsp, ColorTheme, LspPosition, LspRange, PositionEncoding,
|
||||
SemanticTokenContext, TypstRange, VersionedDocument,
|
||||
};
|
||||
|
||||
|
@ -45,6 +45,8 @@ use crate::{
|
|||
pub struct Analysis {
|
||||
/// The position encoding for the workspace.
|
||||
pub position_encoding: PositionEncoding,
|
||||
/// The editor's color theme.
|
||||
pub color_theme: ColorTheme,
|
||||
/// The periscope provider.
|
||||
pub periscope: Option<Arc<dyn PeriscopeProvider + Send + Sync>>,
|
||||
/// The semantic token context.
|
||||
|
|
|
@ -3,28 +3,30 @@ use std::sync::{Arc, LazyLock};
|
|||
use ecow::{eco_format, EcoString};
|
||||
use parking_lot::Mutex;
|
||||
use tinymist_world::base::{EntryState, ShadowApi, TaskInputs};
|
||||
use tinymist_world::LspWorld;
|
||||
use typlite::scopes::Scopes;
|
||||
use typlite::value::{Value, *};
|
||||
use typlite::value::Value;
|
||||
use typst::foundations::Bytes;
|
||||
use typst::{
|
||||
diag::StrResult,
|
||||
syntax::{FileId, VirtualPath},
|
||||
};
|
||||
|
||||
use crate::analysis::SharedContext;
|
||||
|
||||
// Unfortunately, we have only 65536 possible file ids and we cannot revoke
|
||||
// them. So we share a global file id for all docs conversion.
|
||||
static DOCS_CONVERT_ID: LazyLock<Mutex<FileId>> =
|
||||
LazyLock::new(|| Mutex::new(FileId::new(None, VirtualPath::new("__tinymist_docs__.typ"))));
|
||||
|
||||
pub(crate) fn convert_docs(world: &LspWorld, content: &str) -> StrResult<EcoString> {
|
||||
static DOCS_LIB: LazyLock<Arc<Scopes<Value>>> = LazyLock::new(lib);
|
||||
pub(crate) fn convert_docs(ctx: &SharedContext, content: &str) -> StrResult<EcoString> {
|
||||
static DOCS_LIB: LazyLock<Arc<Scopes<Value>>> =
|
||||
LazyLock::new(|| Arc::new(typlite::library::docstring_lib()));
|
||||
|
||||
let conv_id = DOCS_CONVERT_ID.lock();
|
||||
let entry = EntryState::new_rootless(conv_id.vpath().as_rooted_path().into()).unwrap();
|
||||
let entry = entry.select_in_workspace(*conv_id);
|
||||
|
||||
let mut w = world.task(TaskInputs {
|
||||
let mut w = ctx.world.task(TaskInputs {
|
||||
entry: Some(entry),
|
||||
inputs: None,
|
||||
});
|
||||
|
@ -34,29 +36,10 @@ pub(crate) fn convert_docs(world: &LspWorld, content: &str) -> StrResult<EcoStri
|
|||
|
||||
let conv = typlite::Typlite::new(Arc::new(w))
|
||||
.with_library(DOCS_LIB.clone())
|
||||
.with_color_theme(ctx.analysis.color_theme)
|
||||
.annotate_elements(true)
|
||||
.convert()
|
||||
.map_err(|e| eco_format!("failed to convert to markdown: {e}"))?;
|
||||
|
||||
Ok(conv.replace("```example", "```typ"))
|
||||
}
|
||||
|
||||
pub(super) fn lib() -> Arc<Scopes<Value>> {
|
||||
let mut scopes = typlite::library::library();
|
||||
|
||||
// todo: how to import this function correctly?
|
||||
scopes.define("example", example as RawFunc);
|
||||
|
||||
Arc::new(scopes)
|
||||
}
|
||||
|
||||
/// Evaluate a `example`.
|
||||
pub fn example(mut args: Args) -> typlite::Result<Value> {
|
||||
let body = get_pos_named!(args, body: Content).0;
|
||||
let body = body.trim();
|
||||
let ticks = body.chars().take_while(|t| *t == '`').collect::<String>();
|
||||
let body = &body[ticks.len()..];
|
||||
let body = eco_format!("{ticks}typ{body}");
|
||||
|
||||
Ok(Value::Content(body))
|
||||
}
|
||||
|
|
|
@ -91,6 +91,8 @@ use typst::{model::Document as TypstDocument, syntax::Source};
|
|||
/// The physical position in a document.
|
||||
pub type FramePosition = typst::layout::Position;
|
||||
|
||||
pub use typlite::ColorTheme;
|
||||
|
||||
/// A compiled document with an self-incremented logical version.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct VersionedDocument {
|
||||
|
|
|
@ -107,7 +107,7 @@ struct DocsChecker<'a> {
|
|||
|
||||
impl<'a> DocsChecker<'a> {
|
||||
pub fn check_func_docs(mut self, docs: String) -> Option<DocString> {
|
||||
let converted = convert_docs(&self.ctx.world, &docs).ok()?;
|
||||
let converted = convert_docs(self.ctx, &docs).ok()?;
|
||||
let converted = identify_func_docs(&converted).ok()?;
|
||||
let module = self.ctx.module_by_str(docs)?;
|
||||
|
||||
|
@ -135,7 +135,7 @@ impl<'a> DocsChecker<'a> {
|
|||
}
|
||||
|
||||
pub fn check_var_docs(mut self, docs: String) -> Option<DocString> {
|
||||
let converted = convert_docs(&self.ctx.world, &docs).ok()?;
|
||||
let converted = convert_docs(self.ctx, &docs).ok()?;
|
||||
let converted = identify_var_docs(converted).ok()?;
|
||||
let module = self.ctx.module_by_str(docs)?;
|
||||
|
||||
|
@ -152,7 +152,7 @@ impl<'a> DocsChecker<'a> {
|
|||
}
|
||||
|
||||
pub fn check_module_docs(self, docs: String) -> Option<DocString> {
|
||||
let converted = convert_docs(&self.ctx.world, &docs).ok()?;
|
||||
let converted = convert_docs(self.ctx, &docs).ok()?;
|
||||
let converted = identify_tidy_module_docs(converted).ok()?;
|
||||
|
||||
Some(DocString {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue