Skip to content

Commit c5f9f15

Browse files
authored
feat: node references (#674)
1 parent 9cf98e2 commit c5f9f15

File tree

84 files changed

+6400
-1875
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

84 files changed

+6400
-1875
lines changed

benches/doc_parser.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,9 @@ use deno_graph::CapturingModuleAnalyzer;
1515
use deno_graph::GraphKind;
1616
use deno_graph::ModuleGraph;
1717
use deno_graph::ModuleSpecifier;
18+
use indexmap::IndexMap;
1819

19-
async fn parse_with_reexports() -> Vec<DocNode> {
20+
async fn parse() -> IndexMap<ModuleSpecifier, Vec<DocNode>> {
2021
let source = std::fs::read_to_string("./benches/fixtures/deno.d.ts").unwrap();
2122
let sources = vec![(
2223
"file:///test/fixtures/deno.d.ts",
@@ -41,16 +42,15 @@ async fn parse_with_reexports() -> Vec<DocNode> {
4142
},
4243
)
4344
.await;
44-
DocParser::new(&graph, &analyzer, DocParserOptions::default())
45+
DocParser::new(&graph, &analyzer, &[root], DocParserOptions::default())
4546
.unwrap()
46-
.parse_with_reexports(&root)
47+
.parse()
4748
.unwrap()
4849
}
4950

5051
fn doc_parser(c: &mut Criterion) {
51-
c.bench_function("parse_with_rexports large", |b| {
52-
b.to_async(FuturesExecutor)
53-
.iter_with_large_drop(parse_with_reexports)
52+
c.bench_function("parse large", |b| {
53+
b.to_async(FuturesExecutor).iter_with_large_drop(parse)
5454
});
5555
}
5656

deno.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"test": "deno test -A",
55
"tailwind": "deno run -A build_css.ts",
66
"gen_html": "cargo run --example ddoc -- --name=gen_html --output generated_docs/ --html",
7-
"debug": "deno task tailwind && deno task doc ./tests/testdata/multiple/*",
7+
"debug": "deno task tailwind && deno task gen_html ./tests/testdata/multiple/[!_]*",
88
"test:update": "UPDATE=1 cargo test --locked --all-targets && cargo insta test --accept"
99
},
1010
"workspace": ["js"],

examples/ddoc/main.rs

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@
33
use clap::App;
44
use clap::Arg;
55
use deno_doc::find_nodes_by_name_recursively;
6-
use deno_doc::html::HrefResolver;
76
use deno_doc::html::UrlResolveKind;
87
use deno_doc::html::UsageComposer;
98
use deno_doc::html::UsageComposerEntry;
9+
use deno_doc::html::{GenerateCtx, HrefResolver};
1010
use deno_doc::DocNodeKind;
1111
use deno_doc::DocParser;
1212
use deno_doc::DocParserOptions;
@@ -59,6 +59,7 @@ async fn run() -> anyhow::Result<()> {
5959
.requires_all(&["output"]),
6060
)
6161
.arg(Arg::with_name("name").long("name").takes_value(true))
62+
.arg(Arg::with_name("json").long("json").conflicts_with("html"))
6263
.arg(
6364
Arg::with_name("main_entrypoint")
6465
.long("main_entrypoint")
@@ -75,6 +76,7 @@ async fn run() -> anyhow::Result<()> {
7576
.get_matches();
7677
let source_files = matches.values_of("source_files").unwrap();
7778
let html = matches.is_present("html");
79+
let json = matches.is_present("json");
7880
let name = if html {
7981
matches.value_of("name").map(|name| name.to_string())
8082
} else {
@@ -120,23 +122,21 @@ async fn run() -> anyhow::Result<()> {
120122
)
121123
.await;
122124

125+
let mut source_files = source_files.clone();
126+
source_files.sort();
127+
123128
let parser = DocParser::new(
124129
&graph,
125130
&analyzer,
131+
&source_files,
126132
DocParserOptions {
127133
diagnostics: false,
128134
private,
129135
},
130136
)?;
137+
let doc_nodes_by_url = parser.parse()?;
131138

132139
if html {
133-
let mut source_files = source_files.clone();
134-
source_files.sort();
135-
let mut doc_nodes_by_url = IndexMap::with_capacity(source_files.len());
136-
for source_file in source_files {
137-
let nodes = parser.parse_with_reexports(&source_file)?;
138-
doc_nodes_by_url.insert(source_file, nodes);
139-
}
140140
generate_docs_directory(
141141
name,
142142
output_dir,
@@ -146,19 +146,22 @@ async fn run() -> anyhow::Result<()> {
146146
return Ok(());
147147
}
148148

149-
let mut doc_nodes = Vec::with_capacity(1024);
150-
for source_file in source_files {
151-
let nodes = parser.parse_with_reexports(&source_file)?;
152-
doc_nodes.extend(nodes);
153-
}
149+
let mut doc_nodes =
150+
parser.parse()?.into_values().flatten().collect::<Vec<_>>();
154151

155152
doc_nodes.retain(|doc_node| doc_node.kind() != DocNodeKind::Import);
156153
if let Some(filter) = maybe_filter {
157154
doc_nodes = find_nodes_by_name_recursively(doc_nodes, filter);
158155
}
159156

160-
let result = DocPrinter::new(&doc_nodes, true, false);
161-
println!("{}", result);
157+
if json {
158+
serde_json::to_writer_pretty(std::io::stdout(), &doc_nodes)?;
159+
println!();
160+
} else {
161+
let result = DocPrinter::new(&doc_nodes, true, false);
162+
println!("{}", result);
163+
}
164+
162165
Ok(())
163166
}
164167

@@ -269,7 +272,8 @@ fn generate_docs_directory(
269272
)
270273
})),
271274
};
272-
let html = deno_doc::html::generate(options, doc_nodes_by_url)?;
275+
let ctx = GenerateCtx::create_basic(options, doc_nodes_by_url)?;
276+
let html = deno_doc::html::generate(ctx)?;
273277

274278
let path = &output_dir_resolved;
275279
let _ = std::fs::remove_dir_all(path);

js/allow_leak_test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ Deno.test({
1010
async fn() {
1111
await assertRejects(
1212
async () => {
13-
await doc("https://deno.land/x/bad.ts");
13+
await doc(["https://deno.land/x/bad.ts"]);
1414
},
1515
Error,
1616
`Module not found "https://deno.land/x/bad.ts".`,

js/mod.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -70,21 +70,21 @@ export interface DocOptions {
7070
* ```ts
7171
* import { doc } from "https://deno.land/x/deno_doc/mod.ts";
7272
*
73-
* const entries = await doc("https://deno.land/std/fmt/colors.ts");
73+
* const entries = await doc(["https://deno.land/std/fmt/colors.ts"]);
7474
*
7575
* for (const entry of entries) {
7676
* console.log(`name: ${entry.name} kind: ${entry.kind}`);
7777
* }
7878
* ```
7979
*
80-
* @param specifier The URL string of the specifier to document
80+
* @param specifiers List of the URL strings of the specifiers to document
8181
* @param options A set of options for generating the documentation
8282
* @returns A promise that resolves with an array of documentation nodes
8383
*/
8484
export async function doc(
85-
specifier: string,
85+
specifiers: string[],
8686
options: DocOptions = {},
87-
): Promise<Array<DocNode>> {
87+
): Promise<Record<string, Array<DocNode>>> {
8888
const {
8989
load = createCache().load,
9090
includeAll = false,
@@ -95,7 +95,7 @@ export async function doc(
9595

9696
const wasm = await instantiate();
9797
return wasm.doc(
98-
specifier,
98+
specifiers,
9999
includeAll,
100100
(specifier: string, options: {
101101
isDynamic: boolean;

js/test.ts

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@ import { doc, generateHtml } from "./mod.ts";
66
Deno.test({
77
name: "doc()",
88
async fn() {
9-
const entries = await doc(
10-
"https://deno.land/std@0.104.0/fmt/colors.ts",
9+
const records = await doc(
10+
["https://deno.land/std@0.104.0/fmt/colors.ts"],
1111
);
12+
const entries = Object.values(records)[0];
1213
assertEquals(entries.length, 49);
1314
const fnStripColor = entries.find((n) =>
1415
n.kind === "function" && n.name === "stripColor"
@@ -32,8 +33,8 @@ Deno.test({
3233
Deno.test({
3334
name: "doc() - timings",
3435
async fn() {
35-
const fixture = new URL("../benches/fixtures/deno.d.ts", import.meta.url)
36-
.toString();
36+
const fixture = [new URL("../benches/fixtures/deno.d.ts", import.meta.url)
37+
.toString()];
3738

3839
const start = Date.now();
3940
await doc(fixture);
@@ -58,7 +59,7 @@ Deno.test({
5859
Deno.test({
5960
name: "doc() - with headers",
6061
async fn() {
61-
const entries = await doc("https://example.com/a", {
62+
const entries = await doc(["https://example.com/a"], {
6263
load(specifier) {
6364
return Promise.resolve({
6465
kind: "module",
@@ -72,7 +73,7 @@ Deno.test({
7273
});
7374
},
7475
});
75-
assertEquals(entries.length, 1);
76+
assertEquals(Object.values(entries)[0].length, 1);
7677
},
7778
});
7879

@@ -81,7 +82,7 @@ Deno.test({
8182
async fn() {
8283
await assertRejects(
8384
async () => {
84-
await doc("./bad.ts");
85+
await doc(["./bad.ts"]);
8586
},
8687
Error,
8788
"relative URL without a base",
@@ -92,7 +93,7 @@ Deno.test({
9293
Deno.test({
9394
name: "doc() - with import map",
9495
async fn() {
95-
const entries = await doc("https://example.com/a.ts", {
96+
const records = await doc(["https://example.com/a.ts"], {
9697
importMap: "https://example.com/import_map.json",
9798
load(specifier) {
9899
let content = "";
@@ -118,6 +119,7 @@ Deno.test({
118119
});
119120
},
120121
});
122+
const entries = Object.values(records)[0];
121123
assertEquals(entries.length, 1);
122124
assertEquals(entries[0].kind, "class");
123125
assertEquals(entries[0].name, "B");
@@ -128,10 +130,12 @@ Deno.test({
128130
name: "generateHtml()",
129131
async fn() {
130132
const entries = await doc(
131-
"https://deno.land/std@0.104.0/fmt/colors.ts",
133+
["https://deno.land/std@0.104.0/fmt/colors.ts"],
132134
);
133135

134-
const files = await generateHtml({ ["file:///colors.ts"]: entries }, {
136+
const files = await generateHtml({
137+
["file:///colors.ts"]: Object.values(entries)[0],
138+
}, {
135139
markdownRenderer(
136140
md,
137141
_titleOnly,

lib/lib.rs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ impl Resolver for JsResolver {
148148

149149
#[wasm_bindgen]
150150
pub async fn doc(
151-
root_specifier: String,
151+
root_specifiers: Vec<String>,
152152
include_all: bool,
153153
load: js_sys::Function,
154154
maybe_resolve: Option<js_sys::Function>,
@@ -157,7 +157,7 @@ pub async fn doc(
157157
) -> anyhow::Result<JsValue, JsValue> {
158158
console_error_panic_hook::set_once();
159159
inner_doc(
160-
root_specifier,
160+
root_specifiers,
161161
include_all,
162162
load,
163163
maybe_resolve,
@@ -169,14 +169,17 @@ pub async fn doc(
169169
}
170170

171171
async fn inner_doc(
172-
root_specifier: String,
172+
root_specifiers: Vec<String>,
173173
include_all: bool,
174174
load: js_sys::Function,
175175
maybe_resolve: Option<js_sys::Function>,
176176
maybe_import_map: Option<String>,
177177
print_import_map_diagnostics: bool,
178178
) -> Result<JsValue, anyhow::Error> {
179-
let root_specifier = ModuleSpecifier::parse(&root_specifier)?;
179+
let root_specifiers = root_specifiers
180+
.into_iter()
181+
.map(|root_specifier| ModuleSpecifier::parse(&root_specifier))
182+
.collect::<Result<Vec<_>, _>>()?;
180183
let mut loader = JsLoader::new(load);
181184
let maybe_resolver: Option<Box<dyn Resolver>> = if let Some(import_map) =
182185
maybe_import_map
@@ -232,7 +235,7 @@ async fn inner_doc(
232235
let mut graph = ModuleGraph::new(GraphKind::TypesOnly);
233236
graph
234237
.build(
235-
vec![root_specifier.clone()],
238+
root_specifiers.clone(),
236239
&mut loader,
237240
BuildOptions {
238241
module_analyzer: &analyzer,
@@ -244,12 +247,13 @@ async fn inner_doc(
244247
let entries = DocParser::new(
245248
&graph,
246249
&analyzer,
250+
&root_specifiers,
247251
deno_doc::DocParserOptions {
248252
diagnostics: false,
249253
private: include_all,
250254
},
251255
)?
252-
.parse_with_reexports(&root_specifier)?;
256+
.parse()?;
253257
let serializer =
254258
serde_wasm_bindgen::Serializer::new().serialize_maps_as_objects(true);
255259
Ok(entries.serialize(&serializer).unwrap())
@@ -601,7 +605,7 @@ fn generate_html_inner(
601605
None
602606
};
603607

604-
let files = deno_doc::html::generate(
608+
let ctx = deno_doc::html::GenerateCtx::create_basic(
605609
deno_doc::html::GenerateOptions {
606610
package_name,
607611
main_entrypoint,
@@ -627,6 +631,7 @@ fn generate_html_inner(
627631
},
628632
doc_nodes_by_url,
629633
)?;
634+
let files = deno_doc::html::generate(ctx)?;
630635

631636
let serializer =
632637
serde_wasm_bindgen::Serializer::new().serialize_maps_as_objects(true);

src/diagnostics.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -403,7 +403,9 @@ impl<'a, 'b> DiagnosticDocNodeVisitor<'a, 'b> {
403403
| DocNodeKind::Namespace
404404
| DocNodeKind::TypeAlias
405405
| DocNodeKind::Variable => true,
406-
DocNodeKind::Import | DocNodeKind::ModuleDoc => false,
406+
DocNodeKind::Import
407+
| DocNodeKind::ModuleDoc
408+
| DocNodeKind::Reference => false,
407409
}
408410
}
409411

src/html/jsdoc.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,7 @@ impl ModuleDocCtx {
357357

358358
if !short_path.is_main {
359359
let partitions_by_kind = super::partition::partition_nodes_by_kind(
360+
render_ctx.ctx,
360361
module_doc_nodes.iter().map(Cow::Borrowed),
361362
true,
362363
);

0 commit comments

Comments
 (0)