Fix book links (#1227)
This commit is contained in:
parent
2710df4207
commit
c710d5a685
10
.github/workflows/ci.yaml
vendored
10
.github/workflows/ci.yaml
vendored
@ -80,6 +80,16 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
mdbook-version: latest
|
mdbook-version: latest
|
||||||
|
|
||||||
|
- name: Install `mdbook-linkcheck`
|
||||||
|
if: ${{ matrix.os == 'ubuntu-latest' }}
|
||||||
|
run: |
|
||||||
|
mkdir -p mdbook-linkcheck
|
||||||
|
cd mdbook-linkcheck
|
||||||
|
wget https://github.com/Michael-F-Bryan/mdbook-linkcheck/releases/latest/download/mdbook-linkcheck.x86_64-unknown-linux-gnu.zip
|
||||||
|
unzip mdbook-linkcheck.x86_64-unknown-linux-gnu.zip
|
||||||
|
chmod +x mdbook-linkcheck
|
||||||
|
pwd >> $GITHUB_PATH
|
||||||
|
|
||||||
- name: Build book
|
- name: Build book
|
||||||
if: ${{ matrix.os == 'ubuntu-latest' }}
|
if: ${{ matrix.os == 'ubuntu-latest' }}
|
||||||
run: |
|
run: |
|
||||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,6 +1,8 @@
|
|||||||
/.vagrant
|
/.vagrant
|
||||||
/README.html
|
/README.html
|
||||||
|
/book/en/build
|
||||||
/book/en/src
|
/book/en/src
|
||||||
|
/book/zh/build
|
||||||
/book/zh/src
|
/book/zh/src
|
||||||
/fuzz/artifacts
|
/fuzz/artifacts
|
||||||
/fuzz/corpus
|
/fuzz/corpus
|
||||||
@ -9,4 +11,3 @@
|
|||||||
/test-utilities/Cargo.lock
|
/test-utilities/Cargo.lock
|
||||||
/test-utilities/target
|
/test-utilities/target
|
||||||
/tmp
|
/tmp
|
||||||
/www/man
|
|
||||||
|
12
README.md
12
README.md
@ -313,7 +313,7 @@ Kakoune supports `justfile` syntax highlighting out of the box, thanks to TeddyD
|
|||||||
|
|
||||||
### Sublime Text
|
### Sublime Text
|
||||||
|
|
||||||
A syntax file for Sublime Text written by TonioGela is available in [extras/just.sublime-syntax](extras/just.sublime-syntax).
|
A syntax file for Sublime Text written by TonioGela is available in [extras/just.sublime-syntax](https://github.com/casey/just/blob/master/extras/just.sublime-syntax).
|
||||||
|
|
||||||
### Other Editors
|
### Other Editors
|
||||||
|
|
||||||
@ -940,7 +940,7 @@ $ just system-info
|
|||||||
This is an x86_64 machine
|
This is an x86_64 machine
|
||||||
```
|
```
|
||||||
|
|
||||||
The `os_family()` function can be used to create cross-platform `justfile`s that work on various operating systems. For an example, see [cross-platform.just](examples/cross-platform.just) file.
|
The `os_family()` function can be used to create cross-platform `justfile`s that work on various operating systems. For an example, see [cross-platform.just](https://github.com/casey/just/blob/master/examples/cross-platform.just) file.
|
||||||
|
|
||||||
#### Environment Variables
|
#### Environment Variables
|
||||||
|
|
||||||
@ -1946,7 +1946,7 @@ complete -F _just -o bashdefault -o default j
|
|||||||
|
|
||||||
### Shell Completion Scripts
|
### Shell Completion Scripts
|
||||||
|
|
||||||
Shell completion scripts for Bash, Zsh, Fish, PowerShell, and Elvish are available in the [completions](completions) directory. Please refer to your shell's documentation for how to install them.
|
Shell completion scripts for Bash, Zsh, Fish, PowerShell, and Elvish are available in the [completions](https://github.com/casey/just/tree/master/completions) directory. Please refer to your shell's documentation for how to install them.
|
||||||
|
|
||||||
The `just` binary can also generate the same completion scripts at runtime, using the `--completions` command:
|
The `just` binary can also generate the same completion scripts at runtime, using the `--completions` command:
|
||||||
|
|
||||||
@ -1956,11 +1956,11 @@ $ just --completions zsh > just.zsh
|
|||||||
|
|
||||||
### Grammar
|
### Grammar
|
||||||
|
|
||||||
A non-normative grammar of `justfile`s can be found in [GRAMMAR.md](GRAMMAR.md).
|
A non-normative grammar of `justfile`s can be found in [GRAMMAR.md](https://github.com/casey/just/blob/master/GRAMMAR.md).
|
||||||
|
|
||||||
### just.sh
|
### just.sh
|
||||||
|
|
||||||
Before `just` was a fancy Rust program it was a tiny shell script that called `make`. You can find the old version in [extras/just.sh](extras/just.sh).
|
Before `just` was a fancy Rust program it was a tiny shell script that called `make`. You can find the old version in [extras/just.sh](https://github.com/casey/just/blob/master/extras/just.sh).
|
||||||
|
|
||||||
### User `justfile`s
|
### User `justfile`s
|
||||||
|
|
||||||
@ -2099,7 +2099,7 @@ Some ideas for recipes:
|
|||||||
|
|
||||||
Even for small, personal projects it's nice to be able to remember commands by name instead of ^Reverse searching your shell history, and it's a huge boon to be able to go into an old project written in a random language with a mysterious build system and know that all the commands you need to do whatever you need to do are in the `justfile`, and that if you type `just` something useful (or at least interesting!) will probably happen.
|
Even for small, personal projects it's nice to be able to remember commands by name instead of ^Reverse searching your shell history, and it's a huge boon to be able to go into an old project written in a random language with a mysterious build system and know that all the commands you need to do whatever you need to do are in the `justfile`, and that if you type `just` something useful (or at least interesting!) will probably happen.
|
||||||
|
|
||||||
For ideas for recipes, check out [this project's `justfile`](justfile), or some of the `justfile`s [out in the wild](https://github.com/search?o=desc&q=filename%3Ajustfile&s=indexed&type=Code).
|
For ideas for recipes, check out [this project's `justfile`](https://github.com/casey/just/blob/master/justfile), or some of the `justfile`s [out in the wild](https://github.com/search?o=desc&q=filename%3Ajustfile&s=indexed&type=Code).
|
||||||
|
|
||||||
Anyways, I think that's about it for this incredibly long-winded README.
|
Anyways, I think that's about it for this incredibly long-winded README.
|
||||||
|
|
||||||
|
12
README.中文.md
12
README.中文.md
@ -309,7 +309,7 @@ Kakoune 已经内置支持 `justfile` 语法高亮,这要感谢 TeddyDD。
|
|||||||
|
|
||||||
### Sublime Text
|
### Sublime Text
|
||||||
|
|
||||||
由 TonioGela 编写的 Sublime Text 的语法高亮文件在 [extras/just.sublim-syntax](extras/just.sublim-syntax) 中提供。
|
由 TonioGela 编写的 Sublime Text 的语法高亮文件在 [extras/just.sublim-syntax](https://github.com/casey/just/blob/master/extras/just.sublime-syntax) 中提供。
|
||||||
|
|
||||||
### 其它编辑器
|
### 其它编辑器
|
||||||
|
|
||||||
@ -936,7 +936,7 @@ $ just system-info
|
|||||||
This is an x86_64 machine
|
This is an x86_64 machine
|
||||||
```
|
```
|
||||||
|
|
||||||
`os_family()` 函数可以用来创建跨平台的 `justfile`,使其可以在不同的操作系统上工作。一个例子,见 [cross-platform.just](examples/cross-platform.just) 文件。
|
`os_family()` 函数可以用来创建跨平台的 `justfile`,使其可以在不同的操作系统上工作。一个例子,见 [cross-platform.just](https://github.com/casey/just/blob/master/examples/cross-platform.just) 文件。
|
||||||
|
|
||||||
#### 环境变量
|
#### 环境变量
|
||||||
|
|
||||||
@ -1941,7 +1941,7 @@ complete -F _just -o bashdefault -o default j
|
|||||||
|
|
||||||
### Shell 自动补全脚本
|
### Shell 自动补全脚本
|
||||||
|
|
||||||
Bash、Zsh、Fish、PowerShell 和 Elvish 的 Shell 自动补全脚本可以在 [自动补全](completions) 目录下找到。关于如何安装它们,请参考你的 Shell 文档。
|
Bash、Zsh、Fish、PowerShell 和 Elvish 的 Shell 自动补全脚本可以在 [自动补全](https://github.com/casey/just/tree/master/completions) 目录下找到。关于如何安装它们,请参考你的 Shell 文档。
|
||||||
|
|
||||||
`just` 二进制文件也可以在运行时生成相同的自动补全脚本,使用 `--completions` 命令即可,如下:
|
`just` 二进制文件也可以在运行时生成相同的自动补全脚本,使用 `--completions` 命令即可,如下:
|
||||||
|
|
||||||
@ -1951,11 +1951,11 @@ $ just --completions zsh > just.zsh
|
|||||||
|
|
||||||
### 语法
|
### 语法
|
||||||
|
|
||||||
在 [GRAMMAR.md](GRAMMAR.md) 中可以找到一个非正式的 `justfile` 语法说明。
|
在 [GRAMMAR.md](https://github.com/casey/just/blob/master/GRAMMAR.md) 中可以找到一个非正式的 `justfile` 语法说明。
|
||||||
|
|
||||||
### just.sh
|
### just.sh
|
||||||
|
|
||||||
在 `just` 成为一个精致的 Rust 程序之前,它是一个很小的 Shell 脚本,叫 `make`。你可以在 [extras/just.sh](extras/just.sh) 中找到旧版本。
|
在 `just` 成为一个精致的 Rust 程序之前,它是一个很小的 Shell 脚本,叫 `make`。你可以在 [extras/just.sh](https://github.com/casey/just/blob/master/extras/just.sh) 中找到旧版本。
|
||||||
|
|
||||||
### 用户 `justfile`
|
### 用户 `justfile`
|
||||||
|
|
||||||
@ -2094,7 +2094,7 @@ make: `test' is up to date.
|
|||||||
|
|
||||||
即使是小型的个人项目,能够通过名字记住命令,而不是通过 ^Reverse 搜索你的 Shell 历史,这也是一个巨大的福音,能够进入一个用任意语言编写的旧项目,并知道你需要用到的所有命令都在 `justfile` 中,如果你输入 `just`,就可能会输出一些有用的(或至少是有趣的!)信息。
|
即使是小型的个人项目,能够通过名字记住命令,而不是通过 ^Reverse 搜索你的 Shell 历史,这也是一个巨大的福音,能够进入一个用任意语言编写的旧项目,并知道你需要用到的所有命令都在 `justfile` 中,如果你输入 `just`,就可能会输出一些有用的(或至少是有趣的!)信息。
|
||||||
|
|
||||||
关于配方的想法,请查看 [这个项目的 `justfile`](justfile),或一些 [在其他项目里](https://github.com/search?o=desc&q=filename%3Ajustfile&s=indexed&type=Code) 的 `justfile`。
|
关于配方的想法,请查看 [这个项目的 `justfile`](https://github.com/casey/just/blob/master/justfile),或一些 [在其他项目里](https://github.com/search?o=desc&q=filename%3Ajustfile&s=indexed&type=Code) 的 `justfile`。
|
||||||
|
|
||||||
总之,我想这个令人难以置信地啰嗦的 README 就到此为止了。
|
总之,我想这个令人难以置信地啰嗦的 README 就到此为止了。
|
||||||
|
|
||||||
|
@ -1,13 +1,12 @@
|
|||||||
use {
|
use {
|
||||||
pulldown_cmark::{
|
pulldown_cmark::{CowStr, Event, HeadingLevel, Options, Parser, Tag},
|
||||||
Event,
|
|
||||||
HeadingLevel::{H2, H3},
|
|
||||||
Options, Parser, Tag,
|
|
||||||
},
|
|
||||||
pulldown_cmark_to_cmark::cmark,
|
pulldown_cmark_to_cmark::cmark,
|
||||||
std::{error::Error, fs},
|
std::{collections::BTreeMap, error::Error, fs, ops::Deref},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type Result<T = ()> = std::result::Result<T, Box<dyn Error>>;
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug)]
|
||||||
enum Language {
|
enum Language {
|
||||||
English,
|
English,
|
||||||
Chinese,
|
Chinese,
|
||||||
@ -36,7 +35,61 @@ impl Language {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn Error>> {
|
#[derive(Debug)]
|
||||||
|
struct Chapter<'a> {
|
||||||
|
level: HeadingLevel,
|
||||||
|
events: Vec<Event<'a>>,
|
||||||
|
index: usize,
|
||||||
|
language: Language,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Chapter<'a> {
|
||||||
|
fn title(&self) -> String {
|
||||||
|
if self.index == 0 {
|
||||||
|
return self.language.introduction().into();
|
||||||
|
}
|
||||||
|
|
||||||
|
self
|
||||||
|
.events
|
||||||
|
.iter()
|
||||||
|
.skip_while(|event| !matches!(event, Event::Start(Tag::Heading(..))))
|
||||||
|
.skip(1)
|
||||||
|
.take_while(|event| !matches!(event, Event::End(Tag::Heading(..))))
|
||||||
|
.filter_map(|event| match event {
|
||||||
|
Event::Code(content) | Event::Text(content) => Some(content.deref()),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn number(&self) -> usize {
|
||||||
|
self.index + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
fn markdown(&self) -> Result<String> {
|
||||||
|
let mut markdown = String::new();
|
||||||
|
cmark(self.events.iter(), &mut markdown)?;
|
||||||
|
if self.index == 0 {
|
||||||
|
markdown = markdown.split_inclusive('\n').skip(1).collect::<String>();
|
||||||
|
}
|
||||||
|
Ok(markdown)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn slug(s: &str) -> String {
|
||||||
|
let mut slug = String::new();
|
||||||
|
for c in s.chars() {
|
||||||
|
match c {
|
||||||
|
'A'..='Z' => slug.extend(c.to_lowercase()),
|
||||||
|
' ' => slug.push('-'),
|
||||||
|
'?' | '.' | '?' => {}
|
||||||
|
_ => slug.push(c),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
slug
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() -> Result {
|
||||||
for language in [Language::English, Language::Chinese] {
|
for language in [Language::English, Language::Chinese] {
|
||||||
let src = format!("book/{}/src", language.code());
|
let src = format!("book/{}/src", language.code());
|
||||||
fs::remove_dir_all(&src).ok();
|
fs::remove_dir_all(&src).ok();
|
||||||
@ -44,34 +97,88 @@ fn main() -> Result<(), Box<dyn Error>> {
|
|||||||
|
|
||||||
let txt = fs::read_to_string(format!("README{}.md", language.suffix()))?;
|
let txt = fs::read_to_string(format!("README{}.md", language.suffix()))?;
|
||||||
|
|
||||||
let mut chapters = vec![(1usize, Vec::new())];
|
let mut chapters = vec![Chapter {
|
||||||
|
level: HeadingLevel::H1,
|
||||||
|
events: Vec::new(),
|
||||||
|
index: 0,
|
||||||
|
language,
|
||||||
|
}];
|
||||||
|
|
||||||
for event in Parser::new_ext(&txt, Options::all()) {
|
for event in Parser::new_ext(&txt, Options::all()) {
|
||||||
if let Event::Start(Tag::Heading(level @ (H2 | H3), ..)) = event {
|
if let Event::Start(Tag::Heading(level @ (HeadingLevel::H2 | HeadingLevel::H3), ..)) = event {
|
||||||
chapters.push((if level == H2 { 2 } else { 3 }, Vec::new()));
|
let index = chapters.last().unwrap().index + 1;
|
||||||
|
chapters.push(Chapter {
|
||||||
|
level,
|
||||||
|
events: Vec::new(),
|
||||||
|
index,
|
||||||
|
language,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
chapters.last_mut().unwrap().events.push(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut links = BTreeMap::new();
|
||||||
|
|
||||||
|
for chapter in &chapters {
|
||||||
|
let mut current = None;
|
||||||
|
for event in &chapter.events {
|
||||||
|
match event {
|
||||||
|
Event::Start(Tag::Heading(..)) => current = Some(Vec::new()),
|
||||||
|
Event::End(Tag::Heading(level, ..)) => {
|
||||||
|
let events = current.unwrap();
|
||||||
|
let title = events
|
||||||
|
.iter()
|
||||||
|
.filter_map(|event| match event {
|
||||||
|
Event::Code(content) | Event::Text(content) => Some(content.deref()),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
.collect::<String>();
|
||||||
|
let slug = slug(&title);
|
||||||
|
let link = if let HeadingLevel::H1 | HeadingLevel::H2 | HeadingLevel::H3 = level {
|
||||||
|
format!("chapter_{}.html", chapter.number())
|
||||||
|
} else {
|
||||||
|
format!("chapter_{}.html#{}", chapter.number(), slug)
|
||||||
|
};
|
||||||
|
links.insert(slug, link);
|
||||||
|
current = None;
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
if let Some(events) = &mut current {
|
||||||
|
events.push(event.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for chapter in &mut chapters {
|
||||||
|
for event in &mut chapter.events {
|
||||||
|
if let Event::Start(Tag::Link(_, dest, _)) | Event::End(Tag::Link(_, dest, _)) = event {
|
||||||
|
if let Some(anchor) = dest.clone().strip_prefix('#') {
|
||||||
|
*dest = CowStr::Borrowed(&links[anchor]);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
chapters.last_mut().unwrap().1.push(event);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut summary = String::new();
|
let mut summary = String::new();
|
||||||
|
|
||||||
for (i, (level, chapter)) in chapters.into_iter().enumerate() {
|
for chapter in chapters {
|
||||||
let mut txt = String::new();
|
let path = format!("{}/chapter_{}.md", src, chapter.number());
|
||||||
cmark(chapter.iter(), &mut txt)?;
|
fs::write(&path, &chapter.markdown()?)?;
|
||||||
let title = if i == 0 {
|
let indent = match chapter.level {
|
||||||
txt = txt.split_inclusive('\n').skip(1).collect::<String>();
|
HeadingLevel::H1 => 0,
|
||||||
language.introduction()
|
HeadingLevel::H2 => 1,
|
||||||
} else {
|
HeadingLevel::H3 => 2,
|
||||||
txt.lines().next().unwrap().split_once(' ').unwrap().1
|
HeadingLevel::H4 => 3,
|
||||||
|
HeadingLevel::H5 => 4,
|
||||||
|
HeadingLevel::H6 => 5,
|
||||||
};
|
};
|
||||||
|
|
||||||
let path = format!("{}/chapter_{}.md", src, i + 1);
|
|
||||||
fs::write(&path, &txt)?;
|
|
||||||
summary.push_str(&format!(
|
summary.push_str(&format!(
|
||||||
"{}- [{}](chapter_{}.md)\n",
|
"{}- [{}](chapter_{}.md)\n",
|
||||||
" ".repeat((level.saturating_sub(1)) * 4),
|
" ".repeat(indent * 4),
|
||||||
title,
|
chapter.title(),
|
||||||
i + 1
|
chapter.number()
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,4 +5,8 @@ src = "src"
|
|||||||
title = "Just Programmer's Manual"
|
title = "Just Programmer's Manual"
|
||||||
|
|
||||||
[build]
|
[build]
|
||||||
build-dir = "../../www/man/en"
|
build-dir = "build"
|
||||||
|
|
||||||
|
[output.html]
|
||||||
|
|
||||||
|
[output.linkcheck]
|
||||||
|
@ -5,4 +5,8 @@ src = "src"
|
|||||||
title = "Just 用户指南"
|
title = "Just 用户指南"
|
||||||
|
|
||||||
[build]
|
[build]
|
||||||
build-dir = "../../www/man/zh"
|
build-dir = "build"
|
||||||
|
|
||||||
|
[output.html]
|
||||||
|
|
||||||
|
[output.linkcheck]
|
||||||
|
5
justfile
5
justfile
@ -165,6 +165,11 @@ watch-readme:
|
|||||||
generate-completions:
|
generate-completions:
|
||||||
./bin/generate-completions
|
./bin/generate-completions
|
||||||
|
|
||||||
|
build-book:
|
||||||
|
cargo run --package generate-book
|
||||||
|
mdbook build book/en
|
||||||
|
mdbook build book/zh
|
||||||
|
|
||||||
# run all polyglot recipes
|
# run all polyglot recipes
|
||||||
polyglot: _python _js _perl _sh _ruby
|
polyglot: _python _js _perl _sh _ruby
|
||||||
# (recipes that start with `_` are hidden from --list)
|
# (recipes that start with `_` are hidden from --list)
|
||||||
|
1
www/man/en
Symbolic link
1
www/man/en
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../book/en/build/html/
|
1
www/man/zh
Symbolic link
1
www/man/zh
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../book/zh/build/html/
|
Loading…
Reference in New Issue
Block a user