From 9c527f890fad0860e079b51a1419c0950c4c6557 Mon Sep 17 00:00:00 2001 From: Luke Boswell Date: Wed, 8 Jan 2025 13:43:42 +1100 Subject: [PATCH] enable --root-dir for roc docs --- crates/cli/src/lib.rs | 8 ++++++++ crates/cli/src/main.rs | 28 +++++++++++++++++++++----- crates/docs/src/lib.rs | 39 ++++++++++++++++++++++++------------- crates/docs_cli/src/main.rs | 2 +- 4 files changed, 57 insertions(+), 20 deletions(-) diff --git a/crates/cli/src/lib.rs b/crates/cli/src/lib.rs index a345faad89..9f8e31ba2c 100644 --- a/crates/cli/src/lib.rs +++ b/crates/cli/src/lib.rs @@ -89,6 +89,7 @@ pub const FLAG_PP_HOST: &str = "host"; pub const FLAG_PP_PLATFORM: &str = "platform"; pub const FLAG_PP_DYLIB: &str = "lib"; pub const FLAG_MIGRATE: &str = "migrate"; +pub const FLAG_DOCS_ROOT: &str = "root-dir"; pub const VERSION: &str = env!("ROC_VERSION"); const DEFAULT_GENERATED_DOCS_DIR: &str = "generated-docs"; @@ -184,6 +185,12 @@ pub fn build_app() -> Command { .num_args(0..) .allow_hyphen_values(true); + let flag_docs_root_dir = Arg::new(FLAG_DOCS_ROOT) + .long(FLAG_DOCS_ROOT) + .help("Set a root directory path to be used as a prefix for URL links in the generated documentation files.") + .value_parser(value_parser!(Option)) + .required(false); + let build_target_values_parser = PossibleValuesParser::new(Target::iter().map(Into::<&'static str>::into)); @@ -405,6 +412,7 @@ pub fn build_app() -> Command { .required(false) .default_value(DEFAULT_ROC_FILENAME), ) + .arg(flag_docs_root_dir) ) .subcommand(Command::new(CMD_GLUE) .about("Generate glue code between a platform's Roc API and its host language") diff --git a/crates/cli/src/main.rs b/crates/cli/src/main.rs index d746970ce6..3822222856 100644 --- a/crates/cli/src/main.rs +++ b/crates/cli/src/main.rs @@ -5,10 +5,10 @@ use roc_build::program::{check_file, CodeGenBackend}; use roc_cli::{ build_app, default_linking_strategy, format_files, format_src, test, BuildConfig, FormatMode, CMD_BUILD, CMD_CHECK, CMD_DEV, CMD_DOCS, CMD_FORMAT, CMD_GLUE, CMD_PREPROCESS_HOST, CMD_REPL, - CMD_RUN, CMD_TEST, CMD_VERSION, DIRECTORY_OR_FILES, FLAG_CHECK, FLAG_DEV, FLAG_LIB, FLAG_MAIN, - FLAG_MIGRATE, FLAG_NO_COLOR, FLAG_NO_HEADER, FLAG_NO_LINK, FLAG_OUTPUT, FLAG_PP_DYLIB, - FLAG_PP_HOST, FLAG_PP_PLATFORM, FLAG_STDIN, FLAG_STDOUT, FLAG_TARGET, FLAG_TIME, FLAG_VERBOSE, - GLUE_DIR, GLUE_SPEC, ROC_FILE, VERSION, + CMD_RUN, CMD_TEST, CMD_VERSION, DIRECTORY_OR_FILES, FLAG_CHECK, FLAG_DEV, FLAG_DOCS_ROOT, + FLAG_LIB, FLAG_MAIN, FLAG_MIGRATE, FLAG_NO_COLOR, FLAG_NO_HEADER, FLAG_NO_LINK, FLAG_OUTPUT, + FLAG_PP_DYLIB, FLAG_PP_HOST, FLAG_PP_PLATFORM, FLAG_STDIN, FLAG_STDOUT, FLAG_TARGET, FLAG_TIME, + FLAG_VERBOSE, GLUE_DIR, GLUE_SPEC, ROC_FILE, VERSION, }; use roc_docs::generate_docs_html; use roc_error_macros::user_error; @@ -324,7 +324,25 @@ fn main() -> io::Result<()> { let root_path = matches.get_one::(ROC_FILE).unwrap(); let out_dir = matches.get_one::(FLAG_OUTPUT).unwrap(); - generate_docs_html(root_path.to_owned(), out_dir.as_ref()); + let maybe_root_dir: Option = { + if let Ok(root_dir) = std::env::var("ROC_DOCS_URL_ROOT") { + // if the env var is set, it should override the flag for now + // TODO -- confirm we no longer need this and remove + // once docs are migrated to individual repositories and not roc website + Some(root_dir) + } else { + matches + .get_one::>(FLAG_DOCS_ROOT) + .unwrap() + .clone() + } + }; + + generate_docs_html( + root_path.to_owned(), + out_dir.as_ref(), + maybe_root_dir.clone(), + ); Ok(0) } diff --git a/crates/docs/src/lib.rs b/crates/docs/src/lib.rs index 779113ae0a..12cc699057 100644 --- a/crates/docs/src/lib.rs +++ b/crates/docs/src/lib.rs @@ -22,7 +22,7 @@ use std::path::{Path, PathBuf}; const LINK_SVG: &str = include_str!("./static/link.svg"); -pub fn generate_docs_html(root_file: PathBuf, build_dir: &Path) { +pub fn generate_docs_html(root_file: PathBuf, build_dir: &Path, maybe_root_dir: Option) { let mut loaded_module = load_module_for_docs(root_file); let exposed_module_docs = get_exposed_module_docs(&mut loaded_module); @@ -117,7 +117,7 @@ pub fn generate_docs_html(root_file: PathBuf, build_dir: &Path) { .join("\n ") .as_str(), ) - .replace("", &base_url()) + .replace("", &base_url(maybe_root_dir.as_deref())) .replace( "", render_sidebar(exposed_module_docs.iter().map(|(_, docs)| docs)).as_str(), @@ -156,7 +156,7 @@ pub fn generate_docs_html(root_file: PathBuf, build_dir: &Path) { ) .replace( "", - render_name_link(package_name.as_str()).as_str(), + render_name_link(package_name.as_str(), maybe_root_dir.as_deref()).as_str(), ) .replace("", package_name.as_str()) .replace( @@ -184,7 +184,7 @@ pub fn generate_docs_html(root_file: PathBuf, build_dir: &Path) { ) .replace( "", - render_name_link(package_name.as_str()).as_str(), + render_name_link(package_name.as_str(), maybe_root_dir.as_deref()).as_str(), ) .replace("", package_name.as_str()) .replace( @@ -194,6 +194,7 @@ pub fn generate_docs_html(root_file: PathBuf, build_dir: &Path) { module_docs, &loaded_module, &all_exposed_symbols, + maybe_root_dir.as_deref(), ) .as_str(), ); @@ -294,6 +295,7 @@ fn render_module_documentation( module: &ModuleDocumentation, root_module: &LoadedModule, all_exposed_symbols: &VecSet, + maybe_root_dir: Option<&str>, ) -> String { let mut buf = String::new(); let module_name = module.name.as_str(); @@ -356,6 +358,7 @@ fn render_module_documentation( &module.scope, docs, root_module, + maybe_root_dir, ); } @@ -370,6 +373,7 @@ fn render_module_documentation( &module.scope, docs, root_module, + maybe_root_dir, ); } DocEntry::DetachedDoc(docs) => { @@ -380,6 +384,7 @@ fn render_module_documentation( &module.scope, docs, root_module, + maybe_root_dir, ); } }; @@ -413,19 +418,16 @@ where buf.push('>'); } -fn base_url() -> String { - // e.g. "builtins/" in "https://roc-lang.org/builtins/Str" - // - // TODO make this a CLI flag to the `docs` subcommand instead of an env var - match std::env::var("ROC_DOCS_URL_ROOT") { - Ok(root_builtins_path) => { +fn base_url(maybe_root_dir: Option<&str>) -> String { + match maybe_root_dir { + Some(root_builtins_path) => { let mut url_str = String::with_capacity(root_builtins_path.len() + 64); if !root_builtins_path.starts_with('/') { url_str.push('/'); } - url_str.push_str(&root_builtins_path); + url_str.push_str(root_builtins_path); if !root_builtins_path.ends_with('/') { url_str.push('/'); @@ -444,14 +446,19 @@ fn base_url() -> String { } // TODO render version as well -fn render_name_link(name: &str) -> String { +fn render_name_link(name: &str, maybe_root_dir: Option<&str>) -> String { let mut buf = String::new(); push_html(&mut buf, "h1", [("class", "pkg-full-name")], { let mut link_buf = String::new(); // link to root (= docs overview page) - push_html(&mut link_buf, "a", [("href", base_url().as_str())], name); + push_html( + &mut link_buf, + "a", + [("href", base_url(maybe_root_dir).as_str())], + name, + ); link_buf }); @@ -1141,6 +1148,7 @@ fn doc_url<'a>( interns: &'a Interns, mut module_name: &'a str, ident: &str, + maybe_root_dir: Option<&str>, ) -> Result { if module_name.is_empty() { // This is an unqualified lookup, so look for the ident @@ -1194,7 +1202,7 @@ fn doc_url<'a>( } } - let mut url = base_url(); + let mut url = base_url(maybe_root_dir); // Example: // @@ -1216,6 +1224,7 @@ fn markdown_to_html( scope: &Scope, markdown: &str, loaded_module: &LoadedModule, + maybe_root_dir: Option<&str>, ) { use pulldown_cmark::{BrokenLink, CodeBlockKind, CowStr, Event, LinkType, Tag::*}; @@ -1253,6 +1262,7 @@ fn markdown_to_html( &loaded_module.interns, module_name, symbol_name, + maybe_root_dir, ) { Ok(DocUrl { url, title }) => Some((url.into(), title.into())), Err((link_markdown, problem)) => { @@ -1287,6 +1297,7 @@ fn markdown_to_html( &loaded_module.interns, "", type_name, + maybe_root_dir, ) { Ok(DocUrl { url, title }) => Some((url.into(), title.into())), Err((link_markdown, problem)) => { diff --git a/crates/docs_cli/src/main.rs b/crates/docs_cli/src/main.rs index d7f8a931d7..9c0c7f2bfd 100644 --- a/crates/docs_cli/src/main.rs +++ b/crates/docs_cli/src/main.rs @@ -19,10 +19,10 @@ fn main() -> io::Result<()> { ) .get_matches(); - // Populate roc_files generate_docs_html( matches.get_one::(ROC_FILE).unwrap().to_owned(), &PathBuf::from("./generated-docs"), + std::env::var("ROC_DOCS_URL_ROOT").ok(), ); Ok(())