Skip to content

allow linebreaks in brief, option to bundle js #9

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CONFIG.md
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please fix "Weather" -> "Whether"

Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ The configuration file is a TOML file named `cppdoc.toml` with the following sec
- `path`: Path to the output directory.
- `root_namespace` (optional): Namespace to use as the root, this is useful for libraries that only globally expose one namespace and want the index to be based on that namespace.
- `base_url`: Base URL to prepend all paths with.
- `enable_mermaid`: Weather to enable mermaid, default: `true`
- `bundle_mermaid`: Weather to bundle mermaid (`mermaid.mjs` in the static directory), otherwise it is fetched from a release online, default: `false`
- `bundle_minisearch`: Weather to bundle minisearch (`minisearch.js` in the static directory), otherwise it is fetched from a release online, default `false`

## `pages`
- `index` (optional): Markdown file to use as the index file, if an index page is not specified, the root namespace's comment will be used instead.
Expand Down
12 changes: 11 additions & 1 deletion USAGE.md
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what the point of this is, comments are using //<

Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,22 @@ Comments are written using `///` or `//<`, the latter being used for inline docu
```cpp
/// Documentation for 'MyEnum'
enum MyEnum {
A //< Documentation for 'A'
///< Documentation for 'A'
A
}
```

Comments content are parsed as cppdoc-flavored markdown, there is no support for `javadoc`/Doxygen-style comments.

### Hiding nodes

Nodes can be hidden by annotating them with `/// #[doc(hidden)]`

```cpp
/// #[doc(hidden)]
struct Hidden {}
```

## Markdown syntax
`cppdoc` introduces a few extensions to markdown.

Expand Down
23 changes: 18 additions & 5 deletions src/comment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,38 @@ fn remove_prefix_and_clean(string: &str, prefix: &str) -> String {
}
}

pub fn parse_comment(string: String) -> Comment {
pub fn parse_comment(string: String) -> Option<Comment> {
let mut ret = Comment {
brief: "".to_string(),
description: "".to_string(),
impl_: None,
};

let mut lines = string.lines();
if lines.clone().peekable().peek() == Some(&"/// #[doc(hidden)]") {
return None;
}

if let Some(line) = lines.next() {
let mut brief = String::new();
while let Some(line) = lines.next() {
let trimmed = line.trim();
if trimmed.is_empty() {
break;
}

if !brief.is_empty() {
brief.push(' ');
}

if trimmed.starts_with("///<") {
ret.brief = remove_prefix_and_clean(trimmed, "///<");
brief.push_str(&remove_prefix_and_clean(trimmed, "///<"));
} else {
ret.brief = remove_prefix_and_clean(trimmed, "///");
brief.push_str(&remove_prefix_and_clean(trimmed, "///"));
}
}

ret.brief = brief;

let description = lines.fold(String::new(), |mut acc, line| {
let cleaned_up = remove_prefix_and_clean(line.trim(), "///");

Expand All @@ -48,5 +61,5 @@ pub fn parse_comment(string: String) -> Comment {

ret.description = description.trim().to_string();

ret
Some(ret)
}
10 changes: 10 additions & 0 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,16 @@ pub struct Output {
pub path: String,
pub root_namespace: Option<String>,
pub base_url: String,
#[serde(default = "bool_true")]
pub enable_mermaid: bool,
#[serde(default)]
pub bundle_mermaid: bool,
#[serde(default)]
pub bundle_minisearch: bool,
}

fn bool_true() -> bool {
true
}

#[derive(Deserialize, Serialize, Clone, Debug)]
Expand Down
94 changes: 71 additions & 23 deletions src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ impl<'a> Parser<'a> {
}
}

fn parse_function(&self, node: clang::Entity) -> Function {
fn parse_function(&self, node: clang::Entity) -> Option<Function> {
let mut ret = Function {
name: node.get_name().unwrap(),
return_type: node.get_result_type().unwrap().get_display_name(),
Expand All @@ -170,7 +170,12 @@ impl<'a> Parser<'a> {
// Handle function names with quotes, like operator"", so that links don't fuck up
ret.name = ret.name.replace("\"", "&quot");

if let Some(c) = node.get_comment() { ret.comment = Some(comment::parse_comment(c)); }
if let Some(c) = node.get_comment() {
ret.comment = comment::parse_comment(c);
if ret.comment.is_none() {
return None;
}
}

for c in node
.get_children()
Expand All @@ -190,10 +195,10 @@ impl<'a> Parser<'a> {
ret.template = Some(self.parse_template(node));
}

ret
Some(ret)
}

fn parse_record(&self, node: clang::Entity) -> Record {
fn parse_record(&self, node: clang::Entity) -> Option<Record> {
let mut ret = Record {
name: node.get_name().unwrap(),
fields: Vec::new(),
Expand All @@ -215,7 +220,12 @@ impl<'a> Parser<'a> {
nested: None,
};

if let Some(c) = node.get_comment() { ret.comment = Some(comment::parse_comment(c)); }
if let Some(c) = node.get_comment() {
ret.comment = comment::parse_comment(c);
if ret.comment.is_none() {
return None;
}
}

if node.get_kind() == clang::EntityKind::ClassTemplate {
ret.template = Some(self.parse_template(node));
Expand All @@ -224,10 +234,16 @@ impl<'a> Parser<'a> {
for c in node.get_children().iter() {
match c.get_kind() {
clang::EntityKind::FieldDecl => if let Some(clang::Accessibility::Public) = c.get_accessibility() {
let comment = if let Some(comment) = node.get_comment() {
comment::parse_comment(comment)
} else {
None
};

let mut field = Field {
name: c.get_name().unwrap_or_default(),
type_: c.get_type().unwrap().get_display_name(),
comment: c.get_comment().map(comment::parse_comment),
comment,
struct_: None,
};

Expand All @@ -238,7 +254,7 @@ impl<'a> Parser<'a> {
.iter()
.find(|c| c.get_kind() == clang::EntityKind::StructDecl)
.unwrap(),
);
)?;

field.type_ = "struct".to_string();
field.struct_ = Some(NestedField::Record(ret_struct));
Expand All @@ -250,7 +266,7 @@ impl<'a> Parser<'a> {
.iter()
.find(|c| c.get_kind() == clang::EntityKind::UnionDecl)
.unwrap(),
);
)?;

field.type_ = "union".to_string();
field.struct_ = Some(NestedField::Record(ret_struct));
Expand All @@ -262,7 +278,7 @@ impl<'a> Parser<'a> {
.iter()
.find(|c| c.get_kind() == clang::EntityKind::EnumDecl)
.unwrap(),
);
)?;

field.type_ = "enum".to_string();
field.struct_ = Some(NestedField::Enum(ret_enum));
Expand All @@ -272,15 +288,15 @@ impl<'a> Parser<'a> {
},

clang::EntityKind::Constructor => {
let mut function = self.parse_function(*c);
let mut function = self.parse_function(*c)?;
function.return_type = "".to_string();

ret.ctor.push(function);
}

clang::EntityKind::Method | clang::EntityKind::FunctionTemplate => {
if let Some(clang::Accessibility::Public) = c.get_accessibility() {
let mut function = self.parse_function(*c);
let mut function = self.parse_function(*c)?;
function.namespace = Some(ret.name.clone());

ret.methods.push(function);
Expand All @@ -291,7 +307,7 @@ impl<'a> Parser<'a> {
| clang::EntityKind::ClassDecl
| clang::EntityKind::UnionDecl
| clang::EntityKind::ClassTemplate => {
let mut record = self.parse_record(*c);
let mut record = self.parse_record(*c)?;

if !record.name.starts_with("(anonymous")
&& !record.name.starts_with("(unnamed")
Expand All @@ -307,7 +323,7 @@ impl<'a> Parser<'a> {
}

clang::EntityKind::EnumDecl => {
let mut enum_ = self.parse_enum(*c);
let mut enum_ = self.parse_enum(*c)?;

if !enum_.name.starts_with("(anonymous") && !enum_.name.starts_with("(unnamed")
{
Expand All @@ -327,31 +343,42 @@ impl<'a> Parser<'a> {
}
}

ret
Some(ret)
}

fn parse_enum(&self, node: clang::Entity) -> Enum {
fn parse_enum(&self, node: clang::Entity) -> Option<Enum> {
let mut ret = Enum {
name: node.get_name().unwrap(),
comment: None,
namespace: None,
values: Vec::new(),
};

if let Some(c) = node.get_comment() { ret.comment = Some(comment::parse_comment(c)); }
if let Some(c) = node.get_comment() {
ret.comment = comment::parse_comment(c);
if ret.comment.is_none() {
return None;
}
}

for c in node.get_children().iter() {
if c.get_kind() == clang::EntityKind::EnumConstantDecl {
let comment = if let Some(comment) = node.get_comment() {
comment::parse_comment(comment)
} else {
None
};

let value = EnumValue {
name: c.get_name().unwrap_or_default(),
comment: c.get_comment().map(comment::parse_comment),
comment,
};

ret.values.push(value);
}
}

ret
Some(ret)
}

fn get_name_for_namespace(name: &str, namespace_name: &str, ns_name_full: &str) -> String {
Expand Down Expand Up @@ -381,7 +408,10 @@ impl<'a> Parser<'a> {

match node.get_kind() {
clang::EntityKind::FunctionDecl | clang::EntityKind::FunctionTemplate => {
let mut function = self.parse_function(node);
let Some(mut function) = self.parse_function(node) else {
return;
};

function.namespace = Some(current_namespace_name.to_string());

if let Some(existing) = ns.functions.iter_mut().find(|f| f.name == function.name) {
Expand All @@ -406,7 +436,10 @@ impl<'a> Parser<'a> {
| clang::EntityKind::ClassDecl
| clang::EntityKind::UnionDecl
| clang::EntityKind::ClassTemplate => {
let mut record = self.parse_record(node);
let Some(mut record) = self.parse_record(node) else {
return;
};

record.namespace = Some(current_namespace_name.to_string());

// If a record already exists, it must be some kind of template specialization/overloading,
Expand Down Expand Up @@ -464,7 +497,10 @@ impl<'a> Parser<'a> {
}

clang::EntityKind::EnumDecl => {
let mut enum_ = self.parse_enum(node);
let Some(mut enum_) = self.parse_enum(node) else {
return;
};

enum_.namespace = Some(current_namespace_name.to_string());

index.insert(absolute_name, "enum".to_string());
Expand All @@ -473,9 +509,15 @@ impl<'a> Parser<'a> {

clang::EntityKind::Namespace => {
let name = node.get_name().unwrap();
let comment = if let Some(comment) = node.get_comment() {
comment::parse_comment(comment)
} else {
None
};

let mut real_ns = Namespace {
name: node.get_name().unwrap(),
comment: node.get_comment().map(comment::parse_comment),
comment,
records: Vec::new(),
functions: Vec::new(),
namespaces: Vec::new(),
Expand Down Expand Up @@ -549,11 +591,17 @@ impl<'a> Parser<'a> {
type_ = "unknown".to_string();
}

let comment = if let Some(comment) = node.get_comment() {
comment::parse_comment(comment)
} else {
None
};

let alias = Alias {
namespace: Some(current_namespace_name.to_string()),
name: node.get_name().unwrap(),
type_,
comment: node.get_comment().map(comment::parse_comment),
comment,
};

index.insert(absolute_name, "alias".to_string());
Expand Down
8 changes: 7 additions & 1 deletion src/templates/page.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,15 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="{{ config.output.base_url }}/style.css" />
<title>{% block title %}{% endblock title %}</title>
{% if config.output.enable_mermaid %}
<script type="module">
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs';
{% if config.output.bundle_mermaid %}
import mermaid from '{{ config.output.base_url }}/mermaid.mjs';
{% else %}
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs';
{% endif %}
</script>
{% endif %}
{% endblock head %}

</head>
Expand Down
4 changes: 4 additions & 0 deletions src/templates/search.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="{{ config.output.base_url }}/style.css" />
<title>Search - {{ project.name }} </title>
{% if config.output.bundle_minisearch %}
<script src="{{ config.output.base_url }}/minisearch.js"></script>
{% else %}
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/index.min.js"></script>
{% endif %}
<script type="text/javascript">
// Read file /search_index.json
var url = window.location;
Expand Down