Skip to content

Commit

Permalink
Render bevy error codes (#216)
Browse files Browse the repository at this point in the history
  • Loading branch information
NiklasEi authored Nov 13, 2021
1 parent 480c905 commit f0a243d
Show file tree
Hide file tree
Showing 11 changed files with 381 additions and 2 deletions.
5 changes: 4 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,13 @@ jobs:
- name: "Build Bevy Assets"
run: cd generate-assets && ./generate_assets.sh

- name: "Build Bevy Error Codes"
run: cd generate-errors && ./generate_errors.sh

- name: "Build website"
uses: shalzz/zola-deploy-action@master
env:
PAGES_BRANCH: gh-pages
BUILD_DIR: .
BUILD_ONLY: true
TOKEN: fake-secret
TOKEN: fake-secret
3 changes: 3 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ jobs:
- name: "Build Bevy Assets"
run: cd generate-assets && ./generate_assets.sh

- name: "Build Bevy Error Codes"
run: cd generate-errors && ./generate_errors.sh

- name: "Build and deploy website"
if: github.repository_owner == 'bevyengine'
uses: shalzz/zola-deploy-action@master
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ public
**/.DS_Store
.idea/
content/assets
content/learn/errors
2 changes: 2 additions & 0 deletions generate-errors/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
target/
bevy/
114 changes: 114 additions & 0 deletions generate-errors/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 14 additions & 0 deletions generate-errors/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[package]
name = "generate-errors"
version = "0.1.0"
authors = [
"Bevy Contributors <bevyengine@gmail.com>",
"Carter Anderson <mcanders1@gmail.com>",
]
license = "MIT"
edition = "2018"

[dependencies]
pulldown-cmark = { version = "0.8", default-features = false }
serde = { version = "1", features = [ "derive" ] }
toml = "0.5"
10 changes: 10 additions & 0 deletions generate-errors/generate_errors.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/bin/sh

git init bevy
cd bevy
git remote add origin https://github.com/bevyengine/bevy
git sparse-checkout set "errors"
git pull --depth=1 origin latest
cd ..

cargo run --bin generate -- bevy/errors ../content/learn
113 changes: 113 additions & 0 deletions generate-errors/src/bin/generate.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
use generate_errors::{parse_errors, ErrorCode, FrontMatterErrorCode, Section};
use serde::Serialize;
use std::fs::File;
use std::io::Write;
use std::path::Path;
use std::{fs, io};

fn main() -> io::Result<()> {
let errors_dir = std::env::args()
.nth(1)
.expect("First argument should specify the errors directory");
let content_dir = std::env::args()
.nth(2)
.expect("Second argument should specify the content directory");
let _ = fs::create_dir(content_dir.clone());
let errors_root_section = parse_errors(&errors_dir)?;

errors_root_section.write(Path::new(&content_dir), Path::new(""), 0)
}

trait FrontMatterWriter {
fn write(&self, root_path: &Path, current_path: &Path, weight: usize) -> io::Result<()>;
}

#[derive(Serialize)]
struct FrontMatterSection {
title: String,
sort_by: String,
template: Option<String>,
weight: usize,
extra: FrontMatterSectionExtra,
}

#[derive(Serialize)]
struct FrontMatterSectionExtra {
header_message: Option<String>,
sort_order_reversed: bool,
}

impl From<&Section> for FrontMatterSection {
fn from(section: &Section) -> Self {
FrontMatterSection {
title: section.name.clone(),
sort_by: "weight".to_string(),
template: section.template.clone(),
weight: section.order.unwrap_or(0),
extra: section.into(),
}
}
}

impl From<&Section> for FrontMatterSectionExtra {
fn from(section: &Section) -> Self {
FrontMatterSectionExtra {
header_message: section.header.clone(),
sort_order_reversed: section.sort_order_reversed,
}
}
}

impl FrontMatterWriter for Section {
fn write(&self, root_path: &Path, current_path: &Path, weight: usize) -> io::Result<()> {
let section_path = current_path.join(self.name.to_ascii_lowercase());
let path = root_path.join(&section_path);
fs::create_dir(path.clone())?;

let mut frontmatter = FrontMatterSection::from(self);
if self.order.is_none() {
frontmatter.weight = weight;
}

let mut file = File::create(path.join("_index.md"))?;
file.write_all(
format!(
r#"+++
{}
+++
"#,
toml::to_string(&frontmatter).unwrap(),
)
.as_bytes(),
)?;

for (i, content) in self.content.iter().enumerate() {
content.write(root_path, &section_path, i)?
}
Ok(())
}
}

impl FrontMatterWriter for ErrorCode {
fn write(&self, root_path: &Path, current_path: &Path, weight: usize) -> io::Result<()> {
let path = root_path.join(&current_path);

let mut frontmatter = FrontMatterErrorCode::from(self);
frontmatter.weight = weight;

let mut file = File::create(path.join(format!("{}.md", self.code)))?;
file.write_all(
format!(
r#"+++
{}
+++
{}"#,
toml::to_string(&frontmatter).unwrap(),
self.content
)
.as_bytes(),
)?;

Ok(())
}
}
102 changes: 102 additions & 0 deletions generate-errors/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
use serde::Serialize;
use std::fs::read_to_string;
use std::{fs, io, path::PathBuf, str::FromStr};

#[derive(Debug, Clone)]
pub struct Section {
pub name: String,
pub content: Vec<ErrorCode>,
pub template: Option<String>,
pub header: Option<String>,
pub order: Option<usize>,
pub sort_order_reversed: bool,
}

#[derive(Debug, Clone)]
pub struct ErrorCode {
pub code: String,
pub content: String,
}

#[derive(Serialize)]
pub struct FrontMatterErrorCode {
pub title: String,
pub weight: usize,
}

impl From<&ErrorCode> for FrontMatterErrorCode {
fn from(asset: &ErrorCode) -> Self {
FrontMatterErrorCode {
title: asset.code.clone(),
weight: 0,
}
}
}

fn visit_dirs(dir: PathBuf, section: &mut Section) -> io::Result<()> {
if !dir.is_dir() {
// Todo: after the 0.6 release, remove this if statement
// For now we will allow this to be able to point to the `latest` branch (0.5)
// which does not yet include error codes
return Ok(());
}
assert!(dir.is_dir(), "The path to the errors is not a directory");
for entry in fs::read_dir(dir)? {
let entry = entry?;
let path = entry.path();
if path.file_name().unwrap() == ".git" || path.file_name().unwrap() == ".github" {
continue;
}
if !path.is_dir() {
if path.extension().unwrap() != "md" {
continue;
}

let error_code = read_to_string(path.clone())?;

let code = path
.file_name()
.unwrap()
.to_os_string()
.into_string()
.unwrap()
.trim_end_matches(".md")
.to_owned();
section.content.push(ErrorCode {
content: error_code
.trim_start_matches(&format!("# {}", code.clone()))
.replace("```rust,*", "```rust")
.lines()
.map(|line| {
// throw away `should_panic` and `no_run` to fix code highlighting
if line.starts_with("```rust,") {
"```rust"
} else {
line
}
})
.collect::<Vec<&str>>()
.join("\n"),
code,
});
}
}

Ok(())
}

pub fn parse_errors(errors_dir: &str) -> io::Result<Section> {
let mut errors_root_section = Section {
name: "Errors".to_string(),
content: vec![],
template: Some("errors.html".to_string()),
header: Some("Errors".to_string()),
order: None,
sort_order_reversed: false,
};
visit_dirs(
PathBuf::from_str(&errors_dir).unwrap(),
&mut errors_root_section,
)?;
Ok(errors_root_section)
}
Loading

0 comments on commit f0a243d

Please sign in to comment.