kcl std lib docs use handlebars now so making changes should be better (1st pass) (#4007)

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* start of types docs

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu-latest)

* add types files

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* add links

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* better

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* uodates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu-latest)

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
This commit is contained in:
Jess Frazelle
2024-09-27 07:37:46 -07:00
committed by GitHub
parent 47b1c1654a
commit 6303130e08
144 changed files with 3391 additions and 36723 deletions

View File

@ -314,207 +314,3 @@ pub struct FnAsArg<'a> {
pub expr: Box<FunctionExpression>,
pub memory: Box<ProgramMemory>,
}
#[cfg(test)]
mod tests {
use base64::Engine;
use convert_case::Casing;
use itertools::Itertools;
use crate::std::StdLib;
#[test]
fn test_generate_stdlib_markdown_docs() {
let stdlib = StdLib::new();
let combined = stdlib.combined();
let mut buf = String::new();
buf.push_str(
r#"---
title: "KCL Standard Library"
excerpt: "Documentation for the KCL standard library for the Zoo Modeling App."
layout: manual
---
"#,
);
// Generate a table of contents.
buf.push_str("## Table of Contents\n\n");
buf.push_str("* [Types](kcl/types)\n");
buf.push_str("* [Known Issues](kcl/KNOWN-ISSUES)\n");
for key in combined.keys().sorted() {
let internal_fn = combined.get(key).unwrap();
if internal_fn.unpublished() || internal_fn.deprecated() {
continue;
}
buf.push_str(&format!("* [`{}`](kcl/{})\n", internal_fn.name(), internal_fn.name()));
}
// Write the index.
expectorate::assert_contents("../../../docs/kcl/index.md", &buf);
for key in combined.keys().sorted() {
let mut buf = String::new();
let internal_fn = combined.get(key).unwrap();
if internal_fn.unpublished() {
continue;
}
let mut fn_docs = String::new();
fn_docs.push_str(&format!(
r#"---
title: "{}"
excerpt: "{}"
layout: manual
---
"#,
internal_fn.name(),
internal_fn.summary()
));
if internal_fn.deprecated() {
fn_docs.push_str("**WARNING:** This function is deprecated.\n\n");
}
fn_docs.push_str(&format!("{}\n\n", internal_fn.summary()));
fn_docs.push_str(&format!("{}\n\n", internal_fn.description()));
fn_docs.push_str("```js\n");
let signature = internal_fn.fn_signature();
fn_docs.push_str(&signature);
fn_docs.push_str("\n```\n\n");
// If the function has tags, we should add them to the docs.
let tags = internal_fn.tags().clone();
if !tags.is_empty() {
fn_docs.push_str("### Tags\n\n");
for tag in tags {
fn_docs.push_str(&format!("* `{}`\n", tag));
}
fn_docs.push('\n');
}
if !internal_fn.examples().is_empty() {
fn_docs.push_str("### Examples\n\n");
for (index, example) in internal_fn.examples().iter().enumerate() {
fn_docs.push_str("```js\n");
fn_docs.push_str(example);
fn_docs.push_str("\n```\n\n");
// If this is not a "utilities" function,
// we should add the image to the docs.
if !internal_fn.tags().contains(&"utilities".to_string()) {
// Get the path to this specific rust file.
let dir = env!("CARGO_MANIFEST_DIR");
// Convert from camel case to snake case.
let mut fn_name = internal_fn.name().to_case(convert_case::Case::Snake);
// Clean the fn name.
if fn_name.starts_with("last_seg_") {
fn_name = fn_name.replace("last_seg_", "last_segment_");
} else if fn_name.contains("_2_d") {
fn_name = fn_name.replace("_2_d", "_2d");
} else if fn_name.contains("_greater_than_or_eq") {
fn_name = fn_name.replace("_greater_than_or_eq", "_gte");
} else if fn_name.contains("_less_than_or_eq") {
fn_name = fn_name.replace("_less_than_or_eq", "_lte");
} else if fn_name.contains("_greater_than") {
fn_name = fn_name.replace("_greater_than", "_gt");
} else if fn_name.contains("_less_than") {
fn_name = fn_name.replace("_less_than", "_lt");
} else if fn_name.contains("_3_d") {
fn_name = fn_name.replace("_3_d", "_3d");
} else if fn_name == "seg_ang" {
fn_name = "segment_angle".to_string();
} else if fn_name == "seg_len" {
fn_name = "segment_length".to_string();
} else if fn_name.starts_with("seg_") {
fn_name = fn_name.replace("seg_", "segment_");
} else if fn_name.starts_with("log_") {
fn_name = fn_name.replace("log_", "log");
}
// Read the image file and encode as base64.
let image_path = format!("{}/tests/outputs/serial_test_example_{}{}.png", dir, fn_name, index);
let image_data = std::fs::read(&image_path)
.unwrap_or_else(|_| panic!("Failed to read image file: {}", image_path));
let encoded = base64::engine::general_purpose::STANDARD.encode(&image_data);
fn_docs.push_str(&format!(
r#"![Rendered example of {} {}](data:image/png;base64,{})
"#,
internal_fn.name(),
index,
encoded,
));
}
}
}
fn_docs.push_str("### Arguments\n\n");
for arg in internal_fn.args() {
let (format, should_be_indented) = arg.get_type_string().unwrap();
let optional_string = if arg.required { " (REQUIRED)" } else { " (OPTIONAL)" }.to_string();
if let Some(description) = arg.description() {
fn_docs.push_str(&format!(
"* `{}`: `{}` - {}{}\n",
arg.name, arg.type_, description, optional_string
));
} else {
fn_docs.push_str(&format!("* `{}`: `{}`{}\n", arg.name, arg.type_, optional_string));
}
if should_be_indented {
fn_docs.push_str(&format!("```js\n{}\n```\n", format));
}
}
if let Some(return_type) = internal_fn.return_value() {
fn_docs.push_str("\n### Returns\n\n");
if let Some(description) = return_type.description() {
fn_docs.push_str(&format!("`{}` - {}\n", return_type.type_, description));
} else {
fn_docs.push_str(&format!("`{}`\n", return_type.type_));
}
let (format, should_be_indented) = return_type.get_type_string().unwrap();
if should_be_indented {
fn_docs.push_str(&format!("```js\n{}\n```\n", format));
}
}
fn_docs.push_str("\n\n\n");
buf.push_str(&fn_docs);
// Write the file.
expectorate::assert_contents(format!("../../../docs/kcl/{}.md", internal_fn.name()), &buf);
}
}
#[test]
fn test_generate_stdlib_json_schema() {
let stdlib = StdLib::new();
let combined = stdlib.combined();
let mut json_data = vec![];
for key in combined.keys().sorted() {
let internal_fn = combined.get(key).unwrap();
json_data.push(internal_fn.to_json().unwrap());
}
expectorate::assert_contents(
"../../../docs/kcl/std.json",
&serde_json::to_string_pretty(&json_data).unwrap(),
);
}
}