Fork of daniellemaywood.uk/gleam — Wasm codegen work
2

Configure Feed

Select the types of activity you want to include in your feed.

gleam / compiler-cli / src / docs.rs
5.7 kB 184 lines
1use std::time::{Instant, SystemTime}; 2 3use camino::{Utf8Path, Utf8PathBuf}; 4use ecow::EcoString; 5 6use crate::{cli, fs::ProjectIO, http::HttpClient}; 7use gleam_core::{ 8 Result, 9 analyse::TargetSupport, 10 build::{Codegen, Compile, Mode, Options, Package, Target}, 11 config::{DocsPage, PackageConfig}, 12 docs::DocContext, 13 error::Error, 14 hex, 15 io::HttpClient as _, 16 paths::ProjectPaths, 17 type_, 18}; 19 20pub fn remove(package: String, version: String) -> Result<()> { 21 let runtime = tokio::runtime::Runtime::new().expect("Unable to start Tokio async runtime"); 22 let hex_config = hexpm::Config::new(); 23 let api_key = 24 crate::hex::HexAuthentication::new(&runtime, hex_config.clone()).get_or_create_api_key()?; 25 let http = HttpClient::new(); 26 27 // Remove docs from API 28 let request = hexpm::remove_docs_request(&package, &version, &api_key, &hex_config) 29 .map_err(Error::hex)?; 30 let response = runtime.block_on(http.send(request))?; 31 hexpm::remove_docs_response(response).map_err(Error::hex)?; 32 33 // Done! 34 println!("The docs for {package} {version} have been removed from HexDocs"); 35 Ok(()) 36} 37 38#[derive(Debug)] 39pub struct BuildOptions { 40 /// Whether to open the docs after building. 41 pub open: bool, 42 pub target: Option<Target>, 43} 44 45pub fn build(paths: &ProjectPaths, options: BuildOptions) -> Result<()> { 46 let config = crate::config::root_config(paths)?; 47 48 // Reset the build directory so we know the state of the project 49 crate::fs::delete_directory(&paths.build_directory_for_target(Mode::Prod, config.target))?; 50 51 let out = paths.build_documentation_directory(&config.name); 52 let mut built = crate::build::main( 53 paths, 54 Options { 55 mode: Mode::Prod, 56 target: options.target, 57 codegen: Codegen::All, 58 compile: Compile::All, 59 warnings_as_errors: false, 60 root_target_support: TargetSupport::Enforced, 61 no_print_progress: false, 62 }, 63 crate::build::download_dependencies(paths, cli::Reporter::new())?, 64 )?; 65 let outputs = build_documentation( 66 paths, 67 &config, 68 &mut built.root_package, 69 DocContext::Build, 70 &built.module_interfaces, 71 )?; 72 73 // Write 74 crate::fs::delete_directory(&out)?; 75 crate::fs::write_outputs_under(&outputs, &out)?; 76 77 let index_html = out.join("index.html"); 78 79 println!( 80 "\nThe documentation for {package} has been rendered to \n{index_html}", 81 package = config.name, 82 index_html = index_html 83 ); 84 85 if options.open { 86 open_docs(&index_html)?; 87 } 88 89 // We're done! 90 Ok(()) 91} 92 93/// Opens the indicated path in the default program configured by the system. 94/// 95/// For the docs this will generally be a browser (unless some other program is 96/// configured as the default for `.html` files). 97fn open_docs(path: &Utf8Path) -> Result<()> { 98 opener::open(path).map_err(|error| Error::FailedToOpenDocs { 99 path: path.to_path_buf(), 100 error: error.to_string(), 101 })?; 102 103 Ok(()) 104} 105 106pub(crate) fn build_documentation( 107 paths: &ProjectPaths, 108 config: &PackageConfig, 109 compiled: &mut Package, 110 is_hex_publish: DocContext, 111 cached_modules: &im::HashMap<EcoString, type_::ModuleInterface>, 112) -> Result<Vec<gleam_core::io::OutputFile>, Error> { 113 compiled.attach_doc_and_module_comments(); 114 cli::print_generating_documentation(); 115 let mut pages = vec![DocsPage { 116 title: "README".into(), 117 path: "index.html".into(), 118 source: paths.readme(), // TODO: support non markdown READMEs. Or a default if there is none. 119 }]; 120 pages.extend(config.documentation.pages.iter().cloned()); 121 let mut outputs = gleam_core::docs::generate_html( 122 paths, 123 config, 124 compiled.modules.as_slice(), 125 &pages, 126 ProjectIO::new(), 127 SystemTime::now(), 128 is_hex_publish, 129 ); 130 131 outputs.push(gleam_core::docs::generate_json_package_interface( 132 Utf8PathBuf::from("package-interface.json"), 133 compiled, 134 cached_modules, 135 )); 136 Ok(outputs) 137} 138 139pub fn publish(paths: &ProjectPaths) -> Result<()> { 140 let config = crate::config::root_config(paths)?; 141 142 let runtime = tokio::runtime::Runtime::new().expect("Unable to start Tokio async runtime"); 143 let hex_config = hexpm::Config::new(); 144 let api_key = 145 crate::hex::HexAuthentication::new(&runtime, hex_config.clone()).get_or_create_api_key()?; 146 147 // Reset the build directory so we know the state of the project 148 crate::fs::delete_directory(&paths.build_directory_for_target(Mode::Prod, config.target))?; 149 150 let mut built = crate::build::main( 151 paths, 152 Options { 153 root_target_support: TargetSupport::Enforced, 154 warnings_as_errors: false, 155 codegen: Codegen::All, 156 compile: Compile::All, 157 mode: Mode::Prod, 158 target: None, 159 no_print_progress: false, 160 }, 161 crate::build::download_dependencies(paths, cli::Reporter::new())?, 162 )?; 163 let outputs = build_documentation( 164 paths, 165 &config, 166 &mut built.root_package, 167 DocContext::HexPublish, 168 &built.module_interfaces, 169 )?; 170 let archive = crate::fs::create_tar_archive(outputs)?; 171 172 let start = Instant::now(); 173 cli::print_publishing_documentation(); 174 runtime.block_on(hex::publish_documentation( 175 &config.name, 176 &config.version, 177 archive, 178 &api_key, 179 &hex_config, 180 &HttpClient::new(), 181 ))?; 182 cli::print_published(start.elapsed()); 183 Ok(()) 184}