Skip to content

Commit

Permalink
jsdoc link referencing and fix issues
Browse files Browse the repository at this point in the history
  • Loading branch information
crowlKats committed Oct 27, 2023
1 parent 6728ee3 commit 5d11f70
Show file tree
Hide file tree
Showing 12 changed files with 154 additions and 36 deletions.
7 changes: 4 additions & 3 deletions src/html/class.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ pub fn render_class(doc_node: &crate::DocNode, ctx: &RenderContext) -> String {

format!(
r#"<div class="doc_block_items">{}{}{}{}</div>"#,
super::jsdoc::render_docs(&doc_node.js_doc, true, false),
render_constructors(&class_def.constructors, &doc_node.name),
super::jsdoc::render_docs(&doc_node.js_doc, true, false, ctx),
render_constructors(&class_def.constructors, &doc_node.name, ctx),
super::types::render_type_params(&class_def.type_params, ctx),
render_index_signatures(&class_def.index_signatures, ctx),
)
Expand All @@ -28,6 +28,7 @@ pub fn render_class(doc_node: &crate::DocNode, ctx: &RenderContext) -> String {
fn render_constructors(
constructors: &[crate::class::ClassConstructorDef],
name: &str,
ctx: &RenderContext,
) -> String {
if constructors.is_empty() {
return String::new();
Expand All @@ -40,7 +41,7 @@ fn render_constructors(
let id = name_to_id("constructor", &i.to_string());

// TODO: tags, render constructor params
doc_entry(&id, name, "()", constructor.js_doc.doc.as_deref())
doc_entry(&id, name, "()", constructor.js_doc.doc.as_deref(), ctx)
})
.collect::<String>();

Expand Down
3 changes: 2 additions & 1 deletion src/html/enum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,14 @@ pub fn render_enum(doc_node: &crate::DocNode, ctx: &RenderContext) -> String {
.map(|init| format!(" = {}", render_type_def(init, ctx)))
.unwrap_or_default(),
member.js_doc.doc.as_deref(),
ctx,
)
})
.collect::<String>();

format!(
r#"<div class="doc_block_items">{}{}</div>"#,
super::jsdoc::render_docs(&doc_node.js_doc, true, false),
super::jsdoc::render_docs(&doc_node.js_doc, true, false, ctx),
section("Members", &items),
)
}
14 changes: 10 additions & 4 deletions src/html/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ pub fn render_function(
let summary_doc = if !(function_def.has_body && i == 0) {
format!(
r#"<div style="width: 100%;">{}</div>"#,
super::jsdoc::render_docs(&doc_node.js_doc, false, true)
super::jsdoc::render_docs(&doc_node.js_doc, false, true, ctx)
)
} else {
String::new()
Expand Down Expand Up @@ -151,13 +151,13 @@ fn render_single_function(

// TODO: default_value, tags

doc_entry(&id, &name, &ts_type, param_docs.get(i).copied())
doc_entry(&id, &name, &ts_type, param_docs.get(i).copied(), ctx)
})
.collect::<String>();

format!(
r##"<div class="doc_block_items" id="{overload_id}_div">{}{}{}{}</div>"##,
super::jsdoc::render_docs(&doc_node.js_doc, true, false),
super::jsdoc::render_docs(&doc_node.js_doc, true, false, ctx),
render_type_params(&function_def.type_params, ctx),
section("Parameters", &params),
section(
Expand Down Expand Up @@ -192,5 +192,11 @@ fn render_function_return_type(
}
});

doc_entry(&id, "", &render_type_def(return_type, ctx), return_type_doc)
doc_entry(
&id,
"",
&render_type_def(return_type, ctx),
return_type_doc,
ctx,
)
}
5 changes: 4 additions & 1 deletion src/html/interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ pub fn render_interface(

format!(
r#"<div class="doc_block_items">{}{}{}{}{}{}</div>"#,
super::jsdoc::render_docs(&doc_node.js_doc, true, false),
super::jsdoc::render_docs(&doc_node.js_doc, true, false, ctx),
render_type_params(&interface_def.type_params, ctx),
render_index_signatures(&interface_def.index_signatures, ctx),
render_call_signatures(&interface_def.call_signatures, ctx),
Expand Down Expand Up @@ -101,6 +101,7 @@ fn render_call_signatures(
render_params(&call_signature.params, ctx),
),
call_signature.js_doc.doc.as_deref(),
ctx,
)
})
.collect::<String>();
Expand Down Expand Up @@ -155,6 +156,7 @@ fn render_properties(
},
&format!("{ts_type}{default_value}"),
property.js_doc.doc.as_deref(),
ctx,
)
})
.collect::<String>();
Expand Down Expand Up @@ -202,6 +204,7 @@ fn render_methods(
render_params(&method.params, ctx)
),
method.js_doc.doc.as_deref(),
ctx,
)
})
.collect::<String>();
Expand Down
79 changes: 71 additions & 8 deletions src/html/jsdoc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,68 @@ use super::util::*;
use crate::js_doc::JsDoc;
use crate::js_doc::JsDocTag;

pub fn markdown_to_html(md: &str, summary: bool) -> String {
lazy_static! {
static ref JSDOC_LINK_RE: regex::Regex = regex::Regex::new(
r"(?m)\{\s*@link(?<modifier>code|plain)?\s+(?<value>[^}]+)}"
)
.unwrap();
static ref LINK_RE: regex::Regex =
regex::Regex::new(r"(^\.{0,2}\/)|(^[A-Za-z]+:\S)").unwrap();
}

fn parse_links<'a>(
md: &'a str,
ctx: &RenderContext,
) -> std::borrow::Cow<'a, str> {
JSDOC_LINK_RE.replace_all(md, |captures: &regex::Captures| {
let code = captures
.name("modifier")
.map_or("plain", |modifier_match| modifier_match.as_str())
== "code";
let value = captures.name("value").unwrap().as_str();

let (title, link) =
if let Some(index) = value.find('|').or_else(|| value.find(' ')) {
value.split_at(index)
} else {
("", value)
};

let (title, link) = if let Some(href) = ctx.lookup_symbol_href(&link) {
let title = if title.is_empty() { link } else { title };

(title, href)
} else {
(title, link.to_string())
};

if LINK_RE.is_match(&link) {
if code {
format!("[`{title}`]({link})")
} else {
format!("[{title}]({link})")
}
} else {
let title = if !title.is_empty() {
format!(" | {title}")
} else {
String::new()
};

if code {
format!("`{link}`{title}")
} else {
format!("{link}{title}")
}
}
})
}

pub fn markdown_to_html(
md: &str,
summary: bool,
ctx: &RenderContext,
) -> String {
let mut extension_options = comrak::ExtensionOptions::default();
extension_options.autolink = true;
extension_options.description_lists = true;
Expand All @@ -12,7 +73,7 @@ pub fn markdown_to_html(md: &str, summary: bool) -> String {
extension_options.tagfilter = true;
extension_options.tasklist = true;

// TODO(@crowlKats): codeblock highlighting, link parsing
// TODO(@crowlKats): codeblock highlighting

let md = if summary {
let (title, body) = split_markdown_title(md);
Expand All @@ -22,7 +83,7 @@ pub fn markdown_to_html(md: &str, summary: bool) -> String {
};

let html = comrak::markdown_to_html(
md,
&parse_links(md, ctx),
&comrak::Options {
extension: extension_options,
parse: Default::default(),
Expand All @@ -43,9 +104,10 @@ pub fn render_docs(
js_doc: &JsDoc,
render_examples: bool,
summary: bool,
ctx: &RenderContext,
) -> String {
let mut doc = if let Some(doc) = js_doc.doc.as_deref() {
markdown_to_html(doc, summary)
markdown_to_html(doc, summary, ctx)
} else {
"".to_string()
};
Expand All @@ -59,7 +121,7 @@ pub fn render_docs(
.filter_map(|tag| {
if let JsDocTag::Example { doc } = tag {
doc.as_ref().map(|doc| {
let example = render_example(doc, i);
let example = render_example(doc, i, ctx);
i += 1;
example
})
Expand All @@ -77,7 +139,7 @@ pub fn render_docs(
doc
}

fn render_example(example: &str, i: usize) -> String {
fn render_example(example: &str, i: usize, ctx: &RenderContext) -> String {
let id = name_to_id("example", &i.to_string());

let (title, body) = split_markdown_title(example);
Expand All @@ -92,8 +154,9 @@ fn render_example(example: &str, i: usize) -> String {
|| format!("Example {}", i + 1),
|summary| summary.to_string()
),
true
true,
ctx,
),
markdown_to_html(body, false),
markdown_to_html(body, false, ctx),
)
}
27 changes: 20 additions & 7 deletions src/html/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use std::collections::{HashMap, HashSet};
use std::rc::Rc;
use tinytemplate::TinyTemplate;

use crate::html::util::RenderContext;
use crate::DocNodeKind;

mod class;
Expand Down Expand Up @@ -120,14 +121,15 @@ pub fn generate(

let mut files = HashMap::new();

let current_symbols = get_current_symbols(doc_nodes, vec![]);
let current_symbols = Rc::new(get_current_symbols(doc_nodes, vec![]));

// FIXME(bartlomieju): functions can have duplicates because of overloads
let partitions = namespace::partition_nodes_by_kind(doc_nodes);
let name_partitions = partition_nodes_by_name(doc_nodes);

let sidepanel = render_sidepanel(&ctx, &partitions);
let index_content = render_index(&ctx, &sidepanel, partitions);
let index_content =
render_index(&ctx, &sidepanel, partitions, current_symbols.clone());
files.insert(
"index".to_string(),
tt.render(
Expand All @@ -144,7 +146,7 @@ pub fn generate(
&ctx,
&sidepanel,
None,
Rc::new(current_symbols),
current_symbols,
);

Ok(files)
Expand Down Expand Up @@ -205,9 +207,10 @@ fn generate_pages(
}

fn render_index(
ctx: &GenerateCtx,
gen_ctx: &GenerateCtx,
sidepanel: &str,
partitions: IndexMap<DocNodeKind, Vec<crate::DocNode>>,
current_symbols: Rc<HashSet<Vec<String>>>,
) -> String {
let mut content = String::with_capacity(32 * 1024);

Expand All @@ -223,9 +226,19 @@ fn render_index(
for doc_node in doc_nodes {
content.push_str(&format!(
r##"<li><a href="{}.html">{}</a>{}</li>"##,
ctx.url(doc_node.name.to_string()),
gen_ctx.url(doc_node.name.to_string()),
doc_node.name,
jsdoc::render_docs(&doc_node.js_doc, false, false),
jsdoc::render_docs(
&doc_node.js_doc,
false,
false,
&RenderContext {
additional_css: Rc::new(RefCell::new("".to_string())),
namespace: None,
current_symbols: current_symbols.clone(),
current_type_params: Default::default(),
}
),
));
}

Expand Down Expand Up @@ -282,7 +295,7 @@ fn render_page(
doc_nodes: &[crate::DocNode],
current_symbols: Rc<HashSet<Vec<String>>>,
) -> String {
let context = util::RenderContext {
let context = RenderContext {
additional_css: Rc::new(RefCell::new("".to_string())),
namespace: name
.rsplit_once('.')
Expand Down
16 changes: 8 additions & 8 deletions src/html/namespace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,16 @@ use std::fmt::Write;

pub fn render_namespace(
doc_node: &crate::DocNode,
context: &RenderContext,
ctx: &RenderContext,
) -> String {
let namespace_def = doc_node.namespace_def.as_ref().unwrap();

let partitions = partition_nodes_by_kind(&namespace_def.elements);

format!(
r#"<div class="doc_block_items">{}{}</div>"#,
super::jsdoc::render_docs(&doc_node.js_doc, true, false),
doc_node_kind_sections(partitions, context)
super::jsdoc::render_docs(&doc_node.js_doc, true, false, ctx),
doc_node_kind_sections(partitions, ctx)
)
}

Expand All @@ -39,7 +39,7 @@ pub fn partition_nodes_by_kind(

fn doc_node_kind_sections(
partitions: IndexMap<DocNodeKind, Vec<crate::DocNode>>,
context: &RenderContext,
ctx: &RenderContext,
) -> String {
let mut content = String::new();

Expand All @@ -55,7 +55,7 @@ fn doc_node_kind_sections(
DocNodeKind::ModuleDoc | DocNodeKind::Import => unimplemented!(),
};

content.push_str(&symbol_section(title, doc_nodes, context))
content.push_str(&symbol_section(title, doc_nodes, ctx))
}

content
Expand All @@ -64,15 +64,15 @@ fn doc_node_kind_sections(
fn symbol_section(
title: &str,
doc_nodes: Vec<crate::DocNode>,
context: &RenderContext,
ctx: &RenderContext,
) -> String {
let content =
doc_nodes
.into_iter()
.fold(String::new(), |mut output, doc_node| {
// TODO: linking, tags

let (name, path) = context.namespace.as_ref().map_or_else(
let (name, path) = ctx.namespace.as_ref().map_or_else(
|| (doc_node.name.clone(), doc_node.name.clone()),
|namespace| {
(
Expand Down Expand Up @@ -102,7 +102,7 @@ fn symbol_section(
</td>
</tr>"#,
doc_node_kind_icon(doc_node.kind),
super::jsdoc::render_docs(&doc_node.js_doc, false, true),
super::jsdoc::render_docs(&doc_node.js_doc, false, true, ctx),
)
.unwrap();
output
Expand Down
Loading

0 comments on commit 5d11f70

Please sign in to comment.