summaryrefslogtreecommitdiff
path: root/cli
diff options
context:
space:
mode:
Diffstat (limited to 'cli')
-rw-r--r--cli/Cargo.toml2
-rw-r--r--cli/args/flags.rs60
-rw-r--r--cli/tools/doc.rs188
3 files changed, 243 insertions, 7 deletions
diff --git a/cli/Cargo.toml b/cli/Cargo.toml
index 9b318a22c..ff82fc3cc 100644
--- a/cli/Cargo.toml
+++ b/cli/Cargo.toml
@@ -67,7 +67,7 @@ deno_ast = { workspace = true, features = ["bundler", "cjs", "codegen", "proposa
deno_cache_dir = { workspace = true }
deno_config = { workspace = true, features = ["deno_json", "package_json"] }
deno_core = { workspace = true, features = ["include_js_files_for_snapshotting"] }
-deno_doc = { version = "=0.140.0", features = ["html", "syntect"] }
+deno_doc = { version = "=0.141.0", features = ["html", "syntect"] }
deno_emit = "=0.43.0"
deno_graph = { version = "=0.79.0", features = ["tokio_executor"] }
deno_lint = { version = "=0.60.0", features = ["docs"] }
diff --git a/cli/args/flags.rs b/cli/args/flags.rs
index 711ec4c61..1743d58c6 100644
--- a/cli/args/flags.rs
+++ b/cli/args/flags.rs
@@ -133,6 +133,10 @@ impl Default for DocSourceFileFlag {
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct DocHtmlFlag {
pub name: Option<String>,
+ pub category_docs_path: Option<String>,
+ pub symbol_redirect_map_path: Option<String>,
+ pub default_symbol_map_path: Option<String>,
+ pub strip_trailing_html: bool,
pub output: String,
}
@@ -1795,6 +1799,37 @@ Show documentation for runtime built-ins:
.require_equals(true)
)
.arg(
+ Arg::new("category-docs")
+ .long("category-docs")
+ .help("Path to a JSON file keyed by category and an optional value of a markdown doc")
+ .requires("html")
+ .action(ArgAction::Set)
+ .require_equals(true)
+ )
+ .arg(
+ Arg::new("symbol-redirect-map")
+ .long("symbol-redirect-map")
+ .help("Path to a JSON file keyed by file, with an inner map of symbol to an external link")
+ .requires("html")
+ .action(ArgAction::Set)
+ .require_equals(true)
+ )
+ .arg(
+ Arg::new("strip-trailing-html")
+ .long("strip-trailing-html")
+ .help("Remove trailing .html from various links. Will still generate files with a .html extension.")
+ .requires("html")
+ .action(ArgAction::SetTrue)
+ )
+ .arg(
+ Arg::new("default-symbol-map")
+ .long("default-symbol-map")
+ .help("Uses the provided mapping of default name to wanted name for usage blocks.")
+ .requires("html")
+ .action(ArgAction::Set)
+ .require_equals(true)
+ )
+ .arg(
Arg::new("output")
.long("output")
.help("Directory for HTML documentation output")
@@ -2635,7 +2670,7 @@ Directory arguments are expanded to all contained files matching the glob
Arg::new("clean")
.long("clean")
.help("Empty the temporary coverage profile data directory before running tests.
-
+
Note: running multiple `deno test --clean` calls in series or parallel for the same coverage directory may cause race conditions.")
.action(ArgAction::SetTrue),
)
@@ -3879,10 +3914,23 @@ fn doc_parse(flags: &mut Flags, matches: &mut ArgMatches) {
let filter = matches.remove_one::<String>("filter");
let html = if matches.get_flag("html") {
let name = matches.remove_one::<String>("name");
+ let category_docs_path = matches.remove_one::<String>("category-docs");
+ let symbol_redirect_map_path =
+ matches.remove_one::<String>("symbol-redirect-map");
+ let strip_trailing_html = matches.get_flag("strip-trailing-html");
+ let default_symbol_map_path =
+ matches.remove_one::<String>("default-symbol-map");
let output = matches
.remove_one::<String>("output")
.unwrap_or(String::from("./docs/"));
- Some(DocHtmlFlag { name, output })
+ Some(DocHtmlFlag {
+ name,
+ category_docs_path,
+ symbol_redirect_map_path,
+ default_symbol_map_path,
+ strip_trailing_html,
+ output,
+ })
} else {
None
};
@@ -8789,6 +8837,10 @@ mod tests {
lint: false,
html: Some(DocHtmlFlag {
name: Some("My library".to_string()),
+ category_docs_path: None,
+ symbol_redirect_map_path: None,
+ default_symbol_map_path: None,
+ strip_trailing_html: false,
output: String::from("./docs/"),
}),
source_files: DocSourceFileFlag::Paths(svec!["path/to/module.ts"]),
@@ -8815,6 +8867,10 @@ mod tests {
json: false,
html: Some(DocHtmlFlag {
name: Some("My library".to_string()),
+ category_docs_path: None,
+ symbol_redirect_map_path: None,
+ default_symbol_map_path: None,
+ strip_trailing_html: false,
output: String::from("./foo"),
}),
lint: true,
diff --git a/cli/tools/doc.rs b/cli/tools/doc.rs
index e96430b57..f123fc55a 100644
--- a/cli/tools/doc.rs
+++ b/cli/tools/doc.rs
@@ -179,6 +179,7 @@ pub async fn doc(flags: Flags, doc_flags: DocFlags) -> Result<(), AnyError> {
deno_doc::html::DocNodeKindWithDrilldown::Other(node.kind),
inner: std::sync::Arc::new(node),
drilldown_parent_kind: None,
+ parent: None,
})
.collect::<Vec<_>>(),
)
@@ -186,7 +187,38 @@ pub async fn doc(flags: Flags, doc_flags: DocFlags) -> Result<(), AnyError> {
Default::default()
};
- generate_docs_directory(doc_nodes_by_url, html_options, deno_ns)
+ let rewrite_map =
+ if let Some(config_file) = cli_options.maybe_config_file().clone() {
+ let config = config_file.to_exports_config()?;
+
+ let rewrite_map = config
+ .clone()
+ .into_map()
+ .into_keys()
+ .map(|key| {
+ Ok((
+ config.get_resolved(&key)?.unwrap(),
+ key
+ .strip_prefix('.')
+ .unwrap_or(&key)
+ .strip_prefix('/')
+ .unwrap_or(&key)
+ .to_owned(),
+ ))
+ })
+ .collect::<Result<IndexMap<_, _>, AnyError>>()?;
+
+ Some(rewrite_map)
+ } else {
+ None
+ };
+
+ generate_docs_directory(
+ doc_nodes_by_url,
+ html_options,
+ deno_ns,
+ rewrite_map,
+ )
} else {
let modules_len = doc_nodes_by_url.len();
let doc_nodes =
@@ -210,6 +242,7 @@ pub async fn doc(flags: Flags, doc_flags: DocFlags) -> Result<(), AnyError> {
struct DocResolver {
deno_ns: std::collections::HashSet<Vec<String>>,
+ strip_trailing_html: bool,
}
impl deno_doc::html::HrefResolver for DocResolver {
@@ -218,7 +251,17 @@ impl deno_doc::html::HrefResolver for DocResolver {
current: UrlResolveKind,
target: UrlResolveKind,
) -> String {
- deno_doc::html::href_path_resolve(current, target)
+ let path = deno_doc::html::href_path_resolve(current, target);
+ if self.strip_trailing_html {
+ if let Some(path) = path
+ .strip_suffix("index.html")
+ .or_else(|| path.strip_suffix(".html"))
+ {
+ return path.to_owned();
+ }
+ }
+
+ path
}
fn resolve_global_symbol(&self, symbol: &[String]) -> Option<String> {
@@ -257,21 +300,158 @@ impl deno_doc::html::HrefResolver for DocResolver {
}
}
+struct DenoDocResolver(bool);
+
+impl deno_doc::html::HrefResolver for DenoDocResolver {
+ fn resolve_path(
+ &self,
+ current: UrlResolveKind,
+ target: UrlResolveKind,
+ ) -> String {
+ let path = deno_doc::html::href_path_resolve(current, target);
+ if self.0 {
+ if let Some(path) = path
+ .strip_suffix("index.html")
+ .or_else(|| path.strip_suffix(".html"))
+ {
+ return path.to_owned();
+ }
+ }
+
+ path
+ }
+
+ fn resolve_global_symbol(&self, _symbol: &[String]) -> Option<String> {
+ None
+ }
+
+ fn resolve_import_href(
+ &self,
+ _symbol: &[String],
+ _src: &str,
+ ) -> Option<String> {
+ None
+ }
+
+ fn resolve_usage(&self, _current_resolve: UrlResolveKind) -> Option<String> {
+ None
+ }
+
+ fn resolve_source(&self, _location: &deno_doc::Location) -> Option<String> {
+ None
+ }
+}
+
+struct NodeDocResolver(bool);
+
+impl deno_doc::html::HrefResolver for NodeDocResolver {
+ fn resolve_path(
+ &self,
+ current: UrlResolveKind,
+ target: UrlResolveKind,
+ ) -> String {
+ let path = deno_doc::html::href_path_resolve(current, target);
+ if self.0 {
+ if let Some(path) = path
+ .strip_suffix("index.html")
+ .or_else(|| path.strip_suffix(".html"))
+ {
+ return path.to_owned();
+ }
+ }
+
+ path
+ }
+
+ fn resolve_global_symbol(&self, _symbol: &[String]) -> Option<String> {
+ None
+ }
+
+ fn resolve_import_href(
+ &self,
+ _symbol: &[String],
+ _src: &str,
+ ) -> Option<String> {
+ None
+ }
+
+ fn resolve_usage(&self, current_resolve: UrlResolveKind) -> Option<String> {
+ current_resolve
+ .get_file()
+ .map(|file| format!("node:{}", file.path))
+ }
+
+ fn resolve_source(&self, _location: &deno_doc::Location) -> Option<String> {
+ None
+ }
+}
+
fn generate_docs_directory(
doc_nodes_by_url: IndexMap<ModuleSpecifier, Vec<doc::DocNode>>,
html_options: &DocHtmlFlag,
deno_ns: std::collections::HashSet<Vec<String>>,
+ rewrite_map: Option<IndexMap<ModuleSpecifier, String>>,
) -> Result<(), AnyError> {
let cwd = std::env::current_dir().context("Failed to get CWD")?;
let output_dir_resolved = cwd.join(&html_options.output);
+ let internal_env = std::env::var("DENO_INTERNAL_HTML_DOCS").ok();
+
+ let href_resolver: Rc<dyn deno_doc::html::HrefResolver> = if internal_env
+ .as_ref()
+ .is_some_and(|internal_html_docs| internal_html_docs == "node")
+ {
+ Rc::new(NodeDocResolver(html_options.strip_trailing_html))
+ } else if internal_env
+ .as_ref()
+ .is_some_and(|internal_html_docs| internal_html_docs == "deno")
+ || deno_ns.is_empty()
+ {
+ Rc::new(DenoDocResolver(html_options.strip_trailing_html))
+ } else {
+ Rc::new(DocResolver {
+ deno_ns,
+ strip_trailing_html: html_options.strip_trailing_html,
+ })
+ };
+
+ let category_docs =
+ if let Some(category_docs_path) = &html_options.category_docs_path {
+ let content = std::fs::read(category_docs_path)?;
+ Some(deno_core::serde_json::from_slice(&content)?)
+ } else {
+ None
+ };
+
+ let symbol_redirect_map = if let Some(symbol_redirect_map_path) =
+ &html_options.symbol_redirect_map_path
+ {
+ let content = std::fs::read(symbol_redirect_map_path)?;
+ Some(deno_core::serde_json::from_slice(&content)?)
+ } else {
+ None
+ };
+
+ let default_symbol_map = if let Some(default_symbol_map_path) =
+ &html_options.default_symbol_map_path
+ {
+ let content = std::fs::read(default_symbol_map_path)?;
+ Some(deno_core::serde_json::from_slice(&content)?)
+ } else {
+ None
+ };
+
let options = deno_doc::html::GenerateOptions {
package_name: html_options.name.clone(),
main_entrypoint: None,
- rewrite_map: None,
- href_resolver: Rc::new(DocResolver { deno_ns }),
+ rewrite_map,
+ href_resolver,
usage_composer: None,
composable_output: false,
+ category_docs,
+ disable_search: internal_env.is_some(),
+ symbol_redirect_map,
+ default_symbol_map,
};
let files = deno_doc::html::generate(options, doc_nodes_by_url)