Move docs generation code (#3519)

This commit is contained in:
Laurenz 2024-02-28 11:37:52 +01:00 committed by GitHub
parent e16d3f5a67
commit a518e2dd4d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 43 additions and 102 deletions

20
Cargo.lock generated
View File

@ -1050,25 +1050,6 @@ version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "029d73f573d8e8d63e6d5020011d3255b28c3ba85d6cf870a07184ed23de9284" checksum = "029d73f573d8e8d63e6d5020011d3255b28c3ba85d6cf870a07184ed23de9284"
[[package]]
name = "include_dir"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "18762faeff7122e89e0857b02f7ce6fcc0d101d5e9ad2ad7846cc01d61b7f19e"
dependencies = [
"include_dir_macros",
]
[[package]]
name = "include_dir_macros"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b139284b5cf57ecfa712bcc66950bb635b31aff41c188e8a4cfc758eca374a3f"
dependencies = [
"proc-macro2",
"quote",
]
[[package]] [[package]]
name = "indexmap" name = "indexmap"
version = "1.9.3" version = "1.9.3"
@ -2688,7 +2669,6 @@ dependencies = [
"comemo", "comemo",
"ecow", "ecow",
"heck", "heck",
"include_dir",
"once_cell", "once_cell",
"pulldown-cmark", "pulldown-cmark",
"serde", "serde",

View File

@ -1,5 +1,5 @@
[workspace] [workspace]
members = ["crates/*", "tests", "tests/fuzz"] members = ["crates/*", "docs", "tests", "tests/fuzz"]
default-members = ["crates/typst-cli"] default-members = ["crates/typst-cli"]
resolver = "2" resolver = "2"
@ -58,7 +58,6 @@ icu_provider_blob = "1.4"
icu_segmenter = { version = "1.4", features = ["serde"] } icu_segmenter = { version = "1.4", features = ["serde"] }
if_chain = "1" if_chain = "1"
image = { version = "0.24", default-features = false, features = ["png", "jpeg", "gif"] } image = { version = "0.24", default-features = false, features = ["png", "jpeg", "gif"] }
include_dir = "0.7"
indexmap = { version = "2", features = ["serde"] } indexmap = { version = "2", features = ["serde"] }
kamadak-exif = "0.5" kamadak-exif = "0.5"
kurbo = "0.9" # in sync with usvg kurbo = "0.9" # in sync with usvg

View File

@ -24,7 +24,6 @@ typst-dev-assets = { workspace = true }
comemo = { workspace = true } comemo = { workspace = true }
ecow = { workspace = true } ecow = { workspace = true }
heck = { workspace = true } heck = { workspace = true }
include_dir = { workspace = true }
once_cell = { workspace = true } once_cell = { workspace = true }
pulldown-cmark = { workspace = true } pulldown-cmark = { workspace = true }
serde = { workspace = true } serde = { workspace = true }

View File

@ -250,7 +250,7 @@ impl<'a> Handler<'a> {
} }
fn handle_image(&self, link: &str) -> String { fn handle_image(&self, link: &str) -> String {
if let Some(data) = typst_dev_assets::get(link) { if let Some(data) = typst_dev_assets::get_by_name(link) {
self.resolver.image(link, data) self.resolver.image(link, data)
} else if let Some(url) = self.resolver.link(link) { } else if let Some(url) = self.resolver.link(link) {
url url

View File

@ -9,14 +9,10 @@ pub use self::contribs::*;
pub use self::html::*; pub use self::html::*;
pub use self::model::*; pub use self::model::*;
use std::path::Path;
use comemo::Prehashed; use comemo::Prehashed;
use ecow::{eco_format, EcoString}; use ecow::{eco_format, EcoString};
use heck::ToTitleCase; use heck::ToTitleCase;
use include_dir::{include_dir, Dir};
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use serde::de::DeserializeOwned;
use serde::Deserialize; use serde::Deserialize;
use serde_yaml as yaml; use serde_yaml as yaml;
use typst::diag::{bail, StrResult}; use typst::diag::{bail, StrResult};
@ -36,10 +32,15 @@ use typst::text::{Font, FontBook, TEXT};
use typst::visualize::VISUALIZE; use typst::visualize::VISUALIZE;
use typst::Library; use typst::Library;
static DOCS_DIR: Dir<'_> = include_dir!("$CARGO_MANIFEST_DIR/../../docs"); macro_rules! load {
($path:literal) => {
include_str!(concat!("../", $path))
};
}
static GROUPS: Lazy<Vec<GroupData>> = Lazy::new(|| { static GROUPS: Lazy<Vec<GroupData>> = Lazy::new(|| {
let mut groups: Vec<GroupData> = yaml("reference/groups.yml"); let mut groups: Vec<GroupData> =
yaml::from_str(load!("reference/groups.yml")).unwrap();
for group in &mut groups { for group in &mut groups {
if group.filter.is_empty() { if group.filter.is_empty() {
group.filter = group group.filter = group
@ -76,16 +77,16 @@ static FONTS: Lazy<(Prehashed<FontBook>, Vec<Font>)> = Lazy::new(|| {
/// Build documentation pages. /// Build documentation pages.
pub fn provide(resolver: &dyn Resolver) -> Vec<PageModel> { pub fn provide(resolver: &dyn Resolver) -> Vec<PageModel> {
let base = resolver.base();
vec![ vec![
markdown_page(resolver, resolver.base(), "overview.md") md_page(resolver, base, load!("overview.md")).with_route(base),
.with_route(resolver.base()),
tutorial_pages(resolver), tutorial_pages(resolver),
reference_pages(resolver), reference_pages(resolver),
guide_pages(resolver), guide_pages(resolver),
packages_page(resolver), packages_page(resolver),
markdown_page(resolver, resolver.base(), "changelog.md"), md_page(resolver, base, load!("changelog.md")),
markdown_page(resolver, resolver.base(), "roadmap.md"), md_page(resolver, base, load!("roadmap.md")),
markdown_page(resolver, resolver.base(), "community.md"), md_page(resolver, base, load!("community.md")),
] ]
} }
@ -109,13 +110,8 @@ pub trait Resolver {
/// Create a page from a markdown file. /// Create a page from a markdown file.
#[track_caller] #[track_caller]
fn markdown_page( fn md_page(resolver: &dyn Resolver, parent: &str, md: &str) -> PageModel {
resolver: &dyn Resolver,
parent: &str,
path: impl AsRef<Path>,
) -> PageModel {
assert!(parent.starts_with('/') && parent.ends_with('/')); assert!(parent.starts_with('/') && parent.ends_with('/'));
let md = DOCS_DIR.get_file(path).unwrap().contents_utf8().unwrap();
let html = Html::markdown(resolver, md, Some(0)); let html = Html::markdown(resolver, md, Some(0));
let title: EcoString = html.title().expect("chapter lacks a title").into(); let title: EcoString = html.title().expect("chapter lacks a title").into();
PageModel { PageModel {
@ -131,44 +127,26 @@ fn markdown_page(
/// Build the tutorial. /// Build the tutorial.
fn tutorial_pages(resolver: &dyn Resolver) -> PageModel { fn tutorial_pages(resolver: &dyn Resolver) -> PageModel {
let mut page = markdown_page(resolver, resolver.base(), "tutorial/welcome.md"); let mut page = md_page(resolver, resolver.base(), load!("tutorial/welcome.md"));
page.children = DOCS_DIR let base = format!("{}tutorial/", resolver.base());
.get_dir("tutorial") page.children = vec![
.unwrap() md_page(resolver, &base, load!("tutorial/1-writing.md")),
.files() md_page(resolver, &base, load!("tutorial/2-formatting.md")),
.filter(|file| file.path() != Path::new("tutorial/welcome.md")) md_page(resolver, &base, load!("tutorial/3-advanced.md")),
.map(|file| { md_page(resolver, &base, load!("tutorial/4-template.md")),
markdown_page(resolver, &format!("{}tutorial/", resolver.base()), file.path()) ];
})
.collect();
page page
} }
/// Build the reference. /// Build the reference.
fn reference_pages(resolver: &dyn Resolver) -> PageModel { fn reference_pages(resolver: &dyn Resolver) -> PageModel {
let mut page = markdown_page(resolver, resolver.base(), "reference/welcome.md"); let mut page = md_page(resolver, resolver.base(), load!("reference/welcome.md"));
let base = format!("{}reference/", resolver.base());
page.children = vec![ page.children = vec![
markdown_page( md_page(resolver, &base, load!("reference/syntax.md")).with_part("Language"),
resolver, md_page(resolver, &base, load!("reference/styling.md")),
&format!("{}reference/", resolver.base()), md_page(resolver, &base, load!("reference/scripting.md")),
"reference/syntax.md", md_page(resolver, &base, load!("reference/context.md")),
)
.with_part("Language"),
markdown_page(
resolver,
&format!("{}reference/", resolver.base()),
"reference/styling.md",
),
markdown_page(
resolver,
&format!("{}reference/", resolver.base()),
"reference/scripting.md",
),
markdown_page(
resolver,
&format!("{}reference/", resolver.base()),
"reference/context.md",
),
category_page(resolver, FOUNDATIONS).with_part("Library"), category_page(resolver, FOUNDATIONS).with_part("Library"),
category_page(resolver, MODEL), category_page(resolver, MODEL),
category_page(resolver, TEXT), category_page(resolver, TEXT),
@ -184,36 +162,28 @@ fn reference_pages(resolver: &dyn Resolver) -> PageModel {
/// Build the guides section. /// Build the guides section.
fn guide_pages(resolver: &dyn Resolver) -> PageModel { fn guide_pages(resolver: &dyn Resolver) -> PageModel {
let mut page = markdown_page(resolver, resolver.base(), "guides/welcome.md"); let mut page = md_page(resolver, resolver.base(), load!("guides/welcome.md"));
let base = format!("{}guides/", resolver.base());
page.children = vec![ page.children = vec![
markdown_page( md_page(resolver, &base, load!("guides/guide-for-latex-users.md")),
resolver, md_page(resolver, &base, load!("guides/page-setup.md")),
&format!("{}guides/", resolver.base()),
"guides/guide-for-latex-users.md",
),
markdown_page(
resolver,
&format!("{}guides/", resolver.base()),
"guides/page-setup.md",
),
]; ];
page page
} }
/// Build the packages section. /// Build the packages section.
fn packages_page(resolver: &dyn Resolver) -> PageModel { fn packages_page(resolver: &dyn Resolver) -> PageModel {
let md = DOCS_DIR
.get_file("reference/packages.md")
.unwrap()
.contents_utf8()
.unwrap();
PageModel { PageModel {
route: eco_format!("{}packages/", resolver.base()), route: eco_format!("{}packages/", resolver.base()),
title: "Packages".into(), title: "Packages".into(),
description: "Packages for Typst.".into(), description: "Packages for Typst.".into(),
part: None, part: None,
outline: vec![], outline: vec![],
body: BodyModel::Packages(Html::markdown(resolver, md, Some(1))), body: BodyModel::Packages(Html::markdown(
resolver,
load!("reference/packages.md"),
Some(1),
)),
children: vec![], children: vec![],
} }
} }
@ -720,13 +690,6 @@ fn get_module<'a>(parent: &'a Module, name: &str) -> StrResult<&'a Module> {
} }
} }
/// Load YAML from a path.
#[track_caller]
fn yaml<T: DeserializeOwned>(path: &str) -> T {
let file = DOCS_DIR.get_file(path).unwrap();
yaml::from_slice(file.contents()).unwrap()
}
/// Turn a title into an URL fragment. /// Turn a title into an URL fragment.
pub fn urlify(title: &str) -> EcoString { pub fn urlify(title: &str) -> EcoString {
title title

View File

@ -9,7 +9,7 @@ you create a new project on the Typst app. You'll be taken to the editor where
you see two panels: A source panel where you compose your document and a you see two panels: A source panel where you compose your document and a
preview panel where you see the rendered document. preview panel where you see the rendered document.
![Typst app screenshot](screenshots/1-writing-app.png) ![Typst app screenshot](1-writing-app.png)
You already have a good angle for your report in mind. So let's start by writing You already have a good angle for your report in mind. So let's start by writing
the introduction. Enter some text in the editor panel. You'll notice that the the introduction. Enter some text in the editor panel. You'll notice that the
@ -77,7 +77,7 @@ click the button with the arrow in the top-right corner. This opens the upload
dialog, in which you can pick files to upload from your computer. Select an dialog, in which you can pick files to upload from your computer. Select an
image file for your report. image file for your report.
![Upload dialog](screenshots/1-writing-upload.png) ![Upload dialog](1-writing-upload.png)
We have seen before that specific symbols (called _markup_) have specific We have seen before that specific symbols (called _markup_) have specific
meaning in Typst. We can use `=`, `-`, `+`, and `_` to create headings, lists meaning in Typst. We can use `=`, `-`, `+`, and `_` to create headings, lists

View File

@ -82,7 +82,7 @@ hitting the Escape key and opened again by typing `#` or hitting
right arguments for functions. Most suggestions come with a small description of right arguments for functions. Most suggestions come with a small description of
what they do. what they do.
![Autocomplete panel](screenshots/2-formatting-autocomplete.png) ![Autocomplete panel](2-formatting-autocomplete.png)
## Set up the page { #page-setup } ## Set up the page { #page-setup }
Back to set rules: When writing a rule, you choose the function depending on Back to set rules: When writing a rule, you choose the function depending on

View File

@ -16,7 +16,7 @@ left toolbar and create a team. Finally, click on the new team and go to its
settings by clicking 'manage team' next to the team name. Now you can invite settings by clicking 'manage team' next to the team name. Now you can invite
your supervisor by email. your supervisor by email.
![The team settings](screenshots/3-advanced-team-settings.png) ![The team settings](3-advanced-team-settings.png)
Next, move your project into the team: Open it, going to its settings by Next, move your project into the team: Open it, going to its settings by
choosing the gear icon in the left toolbar and selecting your new team from the choosing the gear icon in the left toolbar and selecting your new team from the
@ -489,7 +489,7 @@ We are now in compliance with all of these styles and can submit the paper to
the conference! The finished paper looks like this: the conference! The finished paper looks like this:
<img <img
src="screenshots/3-advanced-paper.png" src="3-advanced-paper.png"
alt="The finished paper" alt="The finished paper"
style="box-shadow: 0 4px 12px rgb(89 85 101 / 20%); width: 500px; max-width: 100%; display: block; margin: 24px auto;" style="box-shadow: 0 4px 12px rgb(89 85 101 / 20%); width: 500px; max-width: 100%; display: block; margin: 24px auto;"
> >