1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
use std::path::Path;
use anyhow::*;
use module_id::ModuleIdData;
use move_core_types::{identifier::Identifier, language_storage::ModuleId};
use move_idl::{IDLBuilder, IDLPackage};
use rustdoc_to_markdown::process_docs;
use serde::{Deserialize, Serialize};
use tera::Tera;
#[derive(Serialize)]
pub struct ReadmeContext {
pub title: String,
pub body: String,
pub address: String,
pub idl: IDLPackage,
pub license: Option<String>,
}
#[derive(Default, Serialize, Deserialize)]
pub struct ReadmeConfig {
pub title: Option<String>,
pub address: Option<String>,
pub main: Option<String>,
}
#[derive(Serialize, Deserialize)]
struct PackageMeta {
license: Option<String>,
}
#[derive(Serialize, Deserialize)]
struct ManifestWithReadme {
package: PackageMeta,
readme: Option<ReadmeConfig>,
}
struct ReadmeOptions {
title: String,
license: Option<String>,
module_id: ModuleIdData,
}
fn load_from_manifest_path(idl: &IDLPackage, manifest_path: &Path) -> Result<ReadmeOptions> {
let manifest_string: String = std::fs::read_to_string(manifest_path)?;
let manifest_with_readme: ManifestWithReadme = toml::from_str(&manifest_string)?;
let readme_cfg = manifest_with_readme.readme.unwrap_or_default();
let title = readme_cfg.title.unwrap_or_else(|| idl.name.clone());
let address_name = readme_cfg.address.unwrap_or_else(move || idl.name.clone());
let address = *idl.aliases.get(&address_name).expect("address not found");
let module_name = readme_cfg.main.unwrap_or_else(|| idl.name.clone());
Ok(ReadmeOptions {
title,
license: manifest_with_readme.package.license,
module_id: ModuleId::new(*address, Identifier::new(module_name)?).into(),
})
}
pub fn generate_readme(root_path: &Path) -> Result<String> {
let idl = IDLBuilder::load(root_path)?.gen()?;
let ReadmeOptions {
title,
license,
module_id,
} = load_from_manifest_path(&idl, &root_path.join("Move.toml"))?;
let module = idl
.modules
.get(&module_id)
.ok_or_else(|| anyhow!("module {} not found", &module_id))?;
let markdown_preamble = process_docs(
module
.doc
.clone()
.unwrap_or_default()
.lines()
.collect::<Vec<_>>(),
false,
)
.join("\n");
let mut tera = Tera::default();
tera.add_raw_template("default", include_str!("templates/default.tpl.md"))?;
let context = ReadmeContext {
title,
body: markdown_preamble,
address: module_id.address().to_hex_literal(),
idl,
license,
};
let result = tera.render("default", &tera::Context::from_serialize(context)?)?;
Ok(result)
}