Skip to content

Commit 6dbcfdf

Browse files
committed
feat(init): add an optional funding field
1 parent 4ab78ae commit 6dbcfdf

File tree

6 files changed

+60
-0
lines changed

6 files changed

+60
-0
lines changed

cli/loader/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,8 @@ pub struct Author {
217217
pub struct Links {
218218
pub repository: Url,
219219
#[serde(skip_serializing_if = "Option::is_none")]
220+
pub funding: Option<Url>,
221+
#[serde(skip_serializing_if = "Option::is_none")]
220222
pub homepage: Option<String>,
221223
}
222224

cli/src/init.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ const AUTHOR_BLOCK_GRAMMAR: &str = "\n * @author ";
5252
const AUTHOR_NAME_PLACEHOLDER_GRAMMAR: &str = "PARSER_AUTHOR_NAME";
5353
const AUTHOR_EMAIL_PLACEHOLDER_GRAMMAR: &str = " PARSER_AUTHOR_EMAIL";
5454

55+
const FUNDING_URL_PLACEHOLDER: &str = "FUNDING_URL";
56+
5557
const GRAMMAR_JS_TEMPLATE: &str = include_str!("./templates/grammar.js");
5658
const PACKAGE_JSON_TEMPLATE: &str = include_str!("./templates/package.json");
5759
const GITIGNORE_TEMPLATE: &str = include_str!("./templates/gitignore");
@@ -118,6 +120,8 @@ pub struct JsonConfigOpts {
118120
pub description: String,
119121
#[serde(skip_serializing_if = "Option::is_none")]
120122
pub repository: Option<Url>,
123+
#[serde(skip_serializing_if = "Option::is_none")]
124+
pub funding: Option<Url>,
121125
pub scope: String,
122126
pub file_types: Vec<String>,
123127
pub version: Version,
@@ -166,6 +170,7 @@ impl JsonConfigOpts {
166170
))
167171
.expect("Failed to parse default repository URL")
168172
}),
173+
funding: self.funding,
169174
homepage: None,
170175
}),
171176
namespace: None,
@@ -182,6 +187,7 @@ impl Default for JsonConfigOpts {
182187
camelcase: String::new(),
183188
description: String::new(),
184189
repository: None,
190+
funding: None,
185191
scope: String::new(),
186192
file_types: vec![],
187193
version: Version::from_str("0.1.0").unwrap(),
@@ -200,6 +206,7 @@ struct GenerateOpts<'a> {
200206
license: Option<&'a str>,
201207
description: Option<&'a str>,
202208
repository: Option<&'a str>,
209+
funding: Option<&'a str>,
203210
version: &'a Version,
204211
camel_parser_name: &'a str,
205212
}
@@ -261,6 +268,11 @@ pub fn generate_grammar_files(
261268
.links
262269
.as_ref()
263270
.map(|l| l.repository.as_str()),
271+
funding: tree_sitter_config
272+
.metadata
273+
.links
274+
.as_ref()
275+
.and_then(|l| l.funding.as_ref().map(|f| f.as_str())),
264276
version: &tree_sitter_config.metadata.version,
265277
camel_parser_name: &camel_name,
266278
};
@@ -848,6 +860,25 @@ fn generate_file(
848860
}
849861
}
850862

863+
if let Some(funding_url) = generate_opts.funding {
864+
match filename {
865+
"pyproject.toml" | "package.json" => {
866+
replacement = replacement.replace(FUNDING_URL_PLACEHOLDER, funding_url);
867+
}
868+
_ => {}
869+
}
870+
} else {
871+
match filename {
872+
"package.json" => {
873+
replacement = replacement.replace(" \"funding\": \"FUNDING_URL\",\n", "");
874+
}
875+
"pyproject.toml" => {
876+
replacement = replacement.replace("Funding = \"FUNDING_URL\"\n", "");
877+
}
878+
_ => {}
879+
}
880+
}
881+
851882
write_file(path, replacement)?;
852883
Ok(())
853884
}

cli/src/main.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -560,6 +560,24 @@ impl Init {
560560
.interact_text()
561561
};
562562

563+
let funding = || {
564+
Input::<String>::with_theme(&ColorfulTheme::default())
565+
.with_prompt("Funding URL")
566+
.allow_empty(true)
567+
.validate_with(|input: &String| {
568+
if input.trim().is_empty()
569+
|| Url::parse(input)
570+
.is_ok_and(|u| u.scheme() == "http" || u.scheme() == "https")
571+
{
572+
Ok(())
573+
} else {
574+
Err("The URL must start with 'http://' or 'https://'")
575+
}
576+
})
577+
.interact_text()
578+
.map(|e| (!e.trim().is_empty()).then(|| Url::parse(&e).unwrap()))
579+
};
580+
563581
let scope = |name: &str| {
564582
Input::<String>::with_theme(&ColorfulTheme::default())
565583
.with_prompt("TextMate scope")
@@ -640,6 +658,7 @@ impl Init {
640658
"camelcase",
641659
"description",
642660
"repository",
661+
"funding",
643662
"scope",
644663
"file_types",
645664
"version",
@@ -657,6 +676,7 @@ impl Init {
657676
"camelcase" => opts.camelcase = camelcase_name(&opts.name)?,
658677
"description" => opts.description = description(&opts.name)?,
659678
"repository" => opts.repository = Some(repository(&opts.name)?),
679+
"funding" => opts.funding = funding()?,
660680
"scope" => opts.scope = scope(&opts.name)?,
661681
"file_types" => opts.file_types = file_types(&opts.name)?,
662682
"version" => opts.version = initial_version()?,

cli/src/templates/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
"version": "PARSER_VERSION",
44
"description": "PARSER_DESCRIPTION",
55
"repository": "PARSER_URL",
6+
"funding": "FUNDING_URL",
67
"license": "PARSER_LICENSE",
78
"author": {
89
"name": "PARSER_AUTHOR_NAME",

cli/src/templates/pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ readme = "README.md"
2020

2121
[project.urls]
2222
Homepage = "PARSER_URL"
23+
Funding = "FUNDING_URL"
2324

2425
[project.optional-dependencies]
2526
core = ["tree-sitter~=0.24"]

docs/src/assets/schemas/config.schema.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,11 @@
172172
"format": "uri",
173173
"description": "The project's repository."
174174
},
175+
"funding": {
176+
"type": "string",
177+
"format": "uri",
178+
"description": "The project's funding link."
179+
},
175180
"homepage": {
176181
"type": "string",
177182
"format": "uri",

0 commit comments

Comments
 (0)