feat: generate documentation in PDF format

This commit is contained in:
Myriad-Dreamin 2025-03-11 10:54:54 +08:00
parent 5a038c99ec
commit ce90489017
34 changed files with 166 additions and 50 deletions

View file

@ -49,9 +49,7 @@ jobs:
curl -L https://github.com/Myriad-Dreamin/shiroa/releases/download/v0.1.5/source-han-serif-font-assets.tar.gz | tar -xvz -C assets/fonts
- name: Download & install shiroa
run: |
curl -L https://github.com/Myriad-Dreamin/shiroa/releases/download/v0.2.0-nightly5/shiroa-x86_64-unknown-linux-gnu.tar.gz | tar -xvz
chmod +x shiroa-x86_64-unknown-linux-gnu/bin/shiroa
sudo cp shiroa-x86_64-unknown-linux-gnu/bin/shiroa /usr/bin/shiroa
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/Myriad-Dreamin/shiroa/releases/download/v0.3.0/shiroa-installer.sh | sh
- name: Install Node.js
uses: actions/setup-node@v4
with:

1
.gitignore vendored
View file

@ -10,4 +10,5 @@ editors/lapce/out/
/external/typst-preview
/dist
*.pdf
.vscode/*.code-workspace

View file

@ -186,7 +186,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2023 Myriad Dreamin, Nathan Varner
Copyright 2023-2025 Myriad Dreamin, Nathan Varner
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

View file

@ -186,7 +186,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2023 Myriad Dreamin, Nathan Varner
Copyright 2023-2025 Myriad Dreamin, Nathan Varner
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

View file

@ -1,5 +1,5 @@
#import "@preview/shiroa:0.1.2": *
#import "@preview/shiroa:0.2.0": *
#show: book
@ -22,8 +22,8 @@
- #chapter("frontend/zed.typ")[Zed]
= Features
- #chapter("feature/cli.typ")[Command line interface]
- #chapter("feature/docs.typ")[Documentation]
- #chapter("guide/completion.typ")[Completion]
- #chapter("feature/docs.typ")[Code Documentation]
- #chapter("guide/completion.typ")[Code Completion]
- #chapter("feature/export.typ")[Exporting Documents]
- #chapter("feature/preview.typ")[Document Preview]
- #chapter("feature/language.typ")[Other Features]

View file

@ -1,6 +1,6 @@
#import "mod.typ": *
#show: book-page.with(title: "Tinymist Command System")
#show: book-page.with(title: [Command System])
The extra features are exposed via LSP's #link("https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#workspace_executeCommand")[`workspace/executeCommand`] request, forming a command system. The commands in the system share a name convention.

View file

@ -1,7 +1,7 @@
#import "mod.typ": *
#import "@preview/cmarker:0.1.0": render as md
#show: book-page.with(title: "Tinymist Configurations")
#show: book-page.with(title: [Configurations])
#let packages = json("/editors/vscode/package.json")

View file

@ -2,4 +2,4 @@
#show: book-page.with(title: "Crate Docs")
#cross-link("/rs/tinymist/index.typ")[Tinymist Crate Docs (for Developers)]
#link("https://myriad-dreamin.github.io/tinymist/rs/tinymist/index.html")[Tinymist Crate Docs (for Developers)]

View file

@ -1,8 +1,10 @@
#import "@preview/shiroa:0.1.2": *
#import "@preview/shiroa:0.2.0": *
#import "/typ/templates/ebook.typ"
#show: ebook.project.with(title: "tinymist", spec: "book.typ")
#import "/typ/templates/tinymist-version.typ": tinymist-package
#show: ebook.project.with(title: [Tinymist Documentation (v#tinymist-package.version)], spec: "book.typ")
// set a resolver for inclusion
#ebook.resolve-inclusion(it => include it)

View file

@ -1,6 +1,6 @@
#import "mod.typ": *
#show: book-page.with(title: "Tinymist Command Line Interface (CLI)")
#show: book-page.with(title: [Command Line Interface (CLI)])
== Starting a Language Server

View file

@ -1,6 +1,6 @@
#import "mod.typ": *
#show: book-page.with(title: "Documentation")
#show: book-page.with(title: [Code Documentation])
Tinymist will read the documentation from the source code and display it in the editor. For example, you can hover over a identifier to see its documentation, usually the content of the comments above the identifier's definition. The format of the documentation follows #link("https://github.com/typst-community/guidelines/pull/8")[this guideline].

View file

@ -1,5 +1,5 @@
#import "mod.typ": *
#show: book-page.with(title: "Tinymist Language and Editor Features")
#show: book-page.with(title: [Language and Editor Features])
#include "language-content.typ"

View file

@ -1,6 +1,6 @@
#import "mod.typ": *
#show: book-page.with(title: "Tinymist Preview Feature")
#show: book-page.with(title: [Preview Feature])
Two ways of previewing a Typst document are provided:
- PDF Preview: let lsp export your PDF on typed, and open related PDF by your favorite PDF viewer.

View file

@ -1,6 +1,6 @@
#import "/docs/tinymist/frontend/mod.typ": *
#show: book-page.with(title: "Tinymist Emacs Extension")
#show: book-page.with(title: [Emacs])
Run and configure tinymist in Emacs for Typst.

View file

@ -1,6 +1,6 @@
#import "/docs/tinymist/frontend/mod.typ": *
#show: book-page.with(title: "Tinymist Helix Extension")
#show: book-page.with(title: [Helix])
Run and configure tinymist in helix for Typst.

View file

@ -1,6 +1,6 @@
#import "mod.typ": *
#show: book-page.with(title: "Tinymist Editor Frontends")
#show: book-page.with(title: [Editor Frontends])
Leveraging the interface of LSP, tinymist provides frontends to each editor, located in the #link("https://github.com/Myriad-Dreamin/tinymist/tree/main/editors")[editor folders]. They are minimal, meaning that LSP should finish its main LSP features as many as possible without help of editor frontends. The editor frontends just enhances your code experience. For example, the vscode frontend takes responsibility on providing some nice editor tools. It is recommended to install these editors frontend for your editors.

View file

@ -1,6 +1,6 @@
#import "/docs/tinymist/frontend/mod.typ": *
#show: book-page.with(title: "Tinymist Neovim Extension")
#show: book-page.with(title: [Neovim])
Run and configure `tinymist` in Neovim with support for all major distros and package managers.

View file

@ -1,7 +1,7 @@
#import "/docs/tinymist/frontend/mod.typ": *
#show: book-page.with(title: "Tinymist Sublime Support for Typst")
#show: book-page.with(title: [Sublime Support])
Follow the instructions in the #link("https://github.com/sublimelsp/LSP/blob/main/docs/src/language_servers.md#tinymist")[sublimelsp documentation] to make it work.

View file

@ -1,6 +1,6 @@
#import "/docs/tinymist/frontend/mod.typ": *
#show: book-page.with(title: "Tinymist VS Code Extension")
#show: book-page.with(title: [VS Cod(e,ium)])
A VS Code or VS Codium extension for Typst. You can find the extension on:

View file

@ -1,6 +1,6 @@
#import "/docs/tinymist/frontend/mod.typ": *
#show: book-page.with(title: "Tinymist Zed Extension")
#show: book-page.with(title: [Zed])
See #link("https://github.com/WeetHet/typst.zed")[typst.zed];.

View file

@ -1,6 +1,6 @@
#import "mod.typ": *
#show: book-page.with(title: "Guide: Completion")
#show: book-page.with(title: [Code Completion])
== Using LSP-Based Completion

View file

@ -1,6 +1,6 @@
#import "mod.typ": *
#show: book-page.with(title: "Tinymist LSP Inputs")
#show: book-page.with(title: [LSP Inputs])
== Prefer to Using LSP Configurations

View file

@ -1,7 +1,7 @@
#import "/docs/tinymist/book.typ": book-page, cross-link
#import "/typ/templates/page.typ": *
#import "@preview/fletcher:0.4.4" as fletcher: *
#import "@preview/fletcher:0.5.6" as fletcher: *
#import "@preview/numbly:0.1.0": numbly
/// This function is to render a text string in monospace style and function

View file

@ -1,6 +1,6 @@
#import "mod.typ": *
#show: book-page.with(title: "Tinymist LSP")
#show: book-page.with(title: [LSP])
== Architecture

View file

@ -1,6 +1,6 @@
#import "mod.typ": *
#show: book-page.with(title: "Tinymist Preview")
#show: book-page.with(title: [Preview])
Todo: rewrite this guide #link("https://enter-tainer.github.io/typst-preview/arch.html")[Developer Guide: Typst-Preview Architecture].

View file

@ -1,6 +1,6 @@
#import "mod.typ": *
#show: book-page.with(title: "Tinymist Language Queries")
#show: book-page.with(title: [Language Queries])
== Base Analyses
@ -47,11 +47,14 @@ There are seven basic analyzers:
edge(sig-n, call-n, "-|>"),
edge(type-n, call-n, "-|>"),
for i in range(9) {
let j = 1 + i * 0.25;
let j = 1 + i * 0.25
edge((j, 1.4), (j, 1.8), "-|>")
},
pg-node((2, 2.3), [`Extended`\
`Language Features`]),
pg-node(
(2, 2.3),
[`Extended`\
`Language Features`],
),
// for i in (1, 3, 5) {
// edge((i, 0), (i, -0.5), (5.5, -0.5), (5.6, 0), "-|>")
// },

View file

@ -1,6 +1,6 @@
#import "mod.typ": *
#show: book-page.with(title: "Tinymist Principles")
#show: book-page.with(title: [Principles])
Four principles are followed.

View file

@ -1,6 +1,6 @@
#import "mod.typ": *
#show: book-page.with(title: "Tinymist Type System")
#show: book-page.with(title: [Type System])
The underlying techniques are not easy to understand, but there are some links:
- bidirectional type checking: https://jaked.org/blog/2021-09-15-Reconstructing-TypeScript-part-1
@ -25,10 +25,10 @@ Second, the $sig$ and the $sans("argument")$ type are reused frequently.
- an optional rest argument, in $sans("arr")$ type.
- an *optional* body, in any type.
notated as $sig := sig(sans("tup")(tau_1,..,tau_n),sans("rec")(a_1=tau_(n+1),..,a_m=tau_(n+m)),..sans("arr")(tau_(n+m+1))) arrow psi$
notated as $sig := sig\(sans("tup")(tau_1,..,tau_n),sans("rec")(a_1=tau_(n+1),..,a_m=tau_(n+m)),\.\.sans("arr");(tau_(n+m+1))) arrow psi$
- the $sans("argument")$ is a $sans("signature")$ without rest and body.
$args := args(sig(..))$
$args := args\(sig\(..))$
With aboving constructors, we soonly get typst's type checker.

View file

@ -186,7 +186,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2023 Myriad Dreamin, Nathan Varner
Copyright 2023-2025 Myriad Dreamin, Nathan Varner
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

View file

@ -18,6 +18,7 @@
"build:preview": "cd tools/typst-preview-frontend && yarn run build && rimraf ../../crates/tinymist-assets/src/typst-preview.html && cpr ./dist/index.html ../../crates/tinymist-assets/src/typst-preview.html",
"maintainers": "typst query MAINTAINERS.typ \"<maintainer-meta>\" --pretty --one --field value --input=action=help",
"docs": "shiroa serve --font-path assets/fonts -w . docs/tinymist",
"docs:pdf": "cargo run --bin tinymist --release -- compile --font-path assets/fonts --root . docs/tinymist/ebook.typ",
"docs:typ": "node scripts/link-docs.mjs",
"docs:rs": "cargo doc --workspace --document-private-items --no-deps",
"lint": "eslint editors/vscode/src",

View file

@ -1,5 +1,6 @@
#import "@preview/shiroa:0.1.2": *
#import "/typ/templates/page.typ": project, part-style
#import "@preview/shiroa:0.2.0": *
#import "/typ/templates/page.typ": project, part-style, heading-sizes, main-color
#import "tinymist-version.typ": tinymist-package
#let _page-project = project
@ -18,20 +19,84 @@
show: _page-project
if title != "" {
heading(title)
set text(size: heading-sizes.at(1))
set text(weight: "bold")
// if kind == "page" and is-pdf-target and not is-main {
// [= #title]
// }
title
v(1em)
}
[
#tinymist-package.description
Visit tinymist repository: #link(tinymist-package.repository)[main branch, ] or #link({
tinymist-package.repository
"/tree/v"
tinymist-package.version
})[v#tinymist-package.version.]
]
{
// inherit from page setting
show: _page-project.with(title: none, kind: "preface")
include "/typ/templates/license.typ"
let outline-numbering-base = numbering.with("1.")
let outline-numbering(a0, ..args) = if a0 > 0 {
h(1em * args.pos().len())
outline-numbering-base(a0, ..args) + [ ]
}
locate(loc => {
let inc = _resolve-inclusion-state.final(loc)
let outline-counter = counter("outline-counter")
show outline.entry: it => {
let has-part = if it.body().func() != none and "children" in it.body().fields() {
for ch in it.body().children {
if "text" in ch.fields() and ch.text.contains("Part") {
ch.text
}
}
}
// set link(main-color)
show link: set text(fill: main-color)
if has-part == none {
outline-counter.step(level: it.level + 1)
layout(shape => {
context {
let lnk = link(it.element.location(), [#outline-counter.display(outline-numbering) #it.element.body])
let r = repeat([.])
let page-no = str(it.element.location().page())
let q = measure(lnk + page-no)
lnk
box(width: shape.width - q.width, inset: (x: 0.25em), r)
page-no
}
})
} else {
outline-counter.step(level: 1)
block(link(it.element.location(), it.element.body))
}
}
set outline.entry(fill: repeat[.])
outline(depth: 1)
}
context {
let inc = _resolve-inclusion-state.final()
external-book(spec: inc(spec))
let mt = book-meta-state.final(loc)
let mt = book-meta-state.final()
let styles = (inc: inc, part: part-style, chapter: it => it)
if mt != none {
mt.summary.map(it => visit-summary(it, styles)).sum()
}
})
}
content
}

16
typ/templates/license.typ Normal file
View file

@ -0,0 +1,16 @@
#page({
set text(size: 10.5pt)
set block(spacing: 1.5em)
show "TERMS AND CONDITIONS FOR USE": it => {
v(0.5em)
it
}
show "APPENDIX": it => {
v(1fr)
it
}
eval(read("/LICENSE"), mode: "markup")
v(5em)
})

View file

@ -1,13 +1,16 @@
// This is important for shiroa to produce a responsive layout
// and multiple targets.
#import "@preview/shiroa:0.1.2": get-page-width, target, is-web-target, is-pdf-target, plain-text, templates
#import "@preview/shiroa:0.2.0": get-page-width, target, is-web-target, is-pdf-target, plain-text, templates
#import templates: *
#import "@preview/numbly:0.1.0": numbly
// Metadata
#let page-width = get-page-width()
#let is-pdf-target = is-pdf-target()
#let is-web-target = is-web-target()
#let part-counter = counter("shiroa-part-counter")
// Theme (Colors)
#let (
style: theme-style,
@ -44,20 +47,23 @@
/// The project function defines how your document looks.
/// It takes your content and some metadata and formats it.
/// Go ahead and customize it to your liking!
#let project(title: "Typst Book", authors: (), kind: "page", body) = {
#let project(title: "Tinymist Documentation", authors: (), kind: "page", body) = {
// set basic document metadata
set document(
author: authors,
title: title,
) if not is-pdf-target
// todo dirty hack to check is main
let is-main = title == "Tinymist Documentation"
// set web/pdf page properties
set page(
numbering: none,
number-align: center,
width: page-width,
)
set page(numbering: "1") if is-pdf-target and not is-main and kind == "page"
// remove margins for web target
set page(
@ -113,6 +119,15 @@
it,
)
}
set heading(
numbering: (..numbers) => context {
if part-counter.get().at(0) > 0 {
numbering("1.", ..part-counter.get(), ..numbers)
} else {
h(-0.3em)
}
},
) if is-pdf-target
// link setting
show link: set text(fill: dash-color)
@ -145,10 +160,22 @@
it.lines.at(0).body.children.slice(0, -2).join()
}
if kind == "page" and is-pdf-target and not is-main {
[= #title]
}
// Main body.
set par(justify: true)
body
}
#let part-style = heading
#let part-style(it) = {
set text(size: heading-sizes.at(1))
set text(weight: "bold")
set text(fill: main-color)
part-counter.step()
context heading(numbering: none, [Part #part-counter.display(numbly("{1}. "))#it])
counter(heading).update(0)
}

View file

@ -0,0 +1,3 @@
#let cargo-toml = toml("/Cargo.toml")
#let tinymist-package = cargo-toml.workspace.package