summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoel Klinghed <the_jk@spawned.biz>2025-06-06 22:34:40 +0200
committerJoel Klinghed <the_jk@spawned.biz>2025-06-06 22:36:01 +0200
commitf58f6b91e851897444186e9291804fc9b58bbd60 (patch)
treebd461eed0c0f8dd2f9eb7d436356bca64411a2f9
parenta7a5ec7b626b72c0156d6f6edc8b8d2b62bf321d (diff)
grit: Add support for expanding grit-part in grit
-rw-r--r--server/common/src/grit.rs58
-rw-r--r--server/common/src/tests.rs147
2 files changed, 205 insertions, 0 deletions
diff --git a/server/common/src/grit.rs b/server/common/src/grit.rs
index fab1130..dbf4f89 100644
--- a/server/common/src/grit.rs
+++ b/server/common/src/grit.rs
@@ -1098,3 +1098,61 @@ pub async fn parse_grit_part(path: impl AsRef<Path>) -> anyhow::Result<GritPart>
.await
.unwrap()
}
+
+fn if_message_to_if_message_part(messages: Vec<IfMessage>) -> Vec<IfMessagePart> {
+ messages
+ .into_iter()
+ .map(|x| match x {
+ IfMessage::Message(message) => IfMessagePart::Message(message),
+ IfMessage::If { expr, message } => IfMessagePart::If {
+ expr,
+ message: if_message_to_if_message_part(message),
+ },
+ })
+ .collect()
+}
+
+async fn maybe_expand_message(
+ message: &mut IfMessagePart,
+ basepath: &Path,
+) -> anyhow::Result<Vec<IfMessagePart>> {
+ match message {
+ IfMessagePart::Message(_) => Ok(Vec::new()),
+ IfMessagePart::Part(part) => {
+ let file_path = Path::new(part.file.as_str());
+ let part_path = if let Some(parent) = basepath.parent() {
+ parent.join(file_path)
+ } else {
+ file_path.to_path_buf()
+ };
+ let grit_part = parse_grit_part(part_path).await?;
+ Ok(if_message_to_if_message_part(grit_part.messages))
+ }
+ IfMessagePart::If { expr: _, message } => {
+ Box::pin(expand_messages(message, basepath)).await?;
+ Ok(Vec::new())
+ }
+ }
+}
+
+async fn expand_messages(messages: &mut Vec<IfMessagePart>, basepath: &Path) -> anyhow::Result<()> {
+ let mut i = 0;
+ while i < messages.len() {
+ let new_messages = maybe_expand_message(&mut messages[i], basepath).await?;
+ if new_messages.is_empty() {
+ i += 1;
+ } else {
+ let j = new_messages.len();
+ messages.splice(i..i + 1, new_messages);
+ i += j;
+ }
+ }
+ Ok(())
+}
+
+pub async fn parse_grit_with_parts(path: impl AsRef<Path>) -> anyhow::Result<Grit> {
+ let path = path.as_ref();
+ let mut grit = parse_grit(path).await?;
+ expand_messages(&mut grit.release.messages.messages, path).await?;
+ Ok(grit)
+}
diff --git a/server/common/src/tests.rs b/server/common/src/tests.rs
index c275c70..2b6aae5 100644
--- a/server/common/src/tests.rs
+++ b/server/common/src/tests.rs
@@ -541,3 +541,150 @@ async fn test_grit_parse_extra() {
},
)
}
+
+#[tokio::test]
+async fn test_grit_parse_include_parts() {
+ let path = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("src/testdata/grit/base.grd");
+ let grit = grit::parse_grit_with_parts(path).await.unwrap();
+ assert_eq!(
+ grit.release.messages,
+ grit::Messages {
+ fallback_to_english: true,
+ messages: vec![
+ grit::IfMessagePart::If {
+ expr: "pp_ifdef('include_extra')".to_string(),
+ message: vec![
+ grit::IfMessagePart::Message(
+ grit::Message {
+ desc: "Extra title".to_string(),
+ name: "IDS_EXTRA".to_string(),
+ internal_comment: None,
+ meaning: None,
+ content: vec![
+ grit::TextPlaceholder::Text("Extra title".to_string()),
+ ],
+ },
+ ),
+ ],
+ },
+ grit::IfMessagePart::Message(
+ grit::Message {
+ desc: "Title which is shown on the main bookmarks view.".to_string(),
+ name: "IDS_BOOKMARKS_FRAGMENT_TITLE".to_string(),
+ internal_comment: Some("section(bookmarks)".to_string()),
+ meaning: None,
+ content: vec![
+ grit::TextPlaceholder::Text("Bookmarks".to_string()),
+ ],
+ },
+ ),
+ grit::IfMessagePart::Message(
+ grit::Message {
+ desc: "Generic welcome string.".to_string(),
+ name: "IDS_GENERIC_WELCOME".to_string(),
+ internal_comment: Some("section(eula)".to_string()),
+ meaning: None,
+ content: vec![
+ grit::TextPlaceholder::Text("Welcome to ".to_string()),
+ grit::TextPlaceholder::Placeholder {
+ name: "STRING".to_string(),
+ content: "%1$s".to_string(),
+ example: Some("Opera".to_string()),
+ },
+ ],
+ },
+ ),
+ grit::IfMessagePart::Message(
+ grit::Message {
+ desc: "First startup information about the license and privacy terms.".to_string(),
+ name: "IDS_START_TERMS".to_string(),
+ internal_comment: None,
+ meaning: None,
+ content: vec![
+ grit::TextPlaceholder::Text(
+ "By using this application you are agreeing to Opera's ".to_string(),
+ ),
+ grit::TextPlaceholder::Placeholder {
+ name: "TOS_BEGIN".to_string(),
+ content: "<tos>".to_string(),
+ example: None,
+ },
+ grit::TextPlaceholder::Text(
+ "Terms of Service".to_string(),
+ ),
+ grit::TextPlaceholder::Placeholder {
+ name: "TOS_END".to_string(),
+ content: "</tos>".to_string(),
+ example: None,
+ },
+ grit::TextPlaceholder::Text(
+ ". Also, you can learn how Opera handles and protects your data in our ".to_string(),
+ ),
+ grit::TextPlaceholder::Placeholder {
+ name: "PRIVACY_BEGIN".to_string(),
+ content: "<privacy>".to_string(),
+ example: None,
+ },
+ grit::TextPlaceholder::Text(
+ "Privacy Statement".to_string(),
+ ),
+ grit::TextPlaceholder::Placeholder {
+ name: "PRIVACY_END".to_string(),
+ content: "</privacy>".to_string(),
+ example: None,
+ },
+ grit::TextPlaceholder::Text(
+ ".".to_string(),
+ ),
+ ],
+ },
+ ),
+ grit::IfMessagePart::Message(
+ grit::Message {
+ desc: "Message which is shown when one or more folders have been deleted from the bookmark list.".to_string(),
+ name: "IDS_BOOKMARKS_FOLDERS_DELETED".to_string(),
+ internal_comment: None,
+ meaning: None,
+ content: vec![
+ grit::TextPlaceholder::Text(
+ "{BOOKMARKS, plural,\n one {".to_string(),
+ ),
+ grit::TextPlaceholder::Placeholder {
+ name: "COUNT".to_string(),
+ content: "%1$d".to_string(),
+ example: Some("1".to_string()),
+ },
+ grit::TextPlaceholder::Text(
+ " folder deleted}\n few {".to_string(),
+ ),
+ grit::TextPlaceholder::Placeholder {
+ name: "COUNT".to_string(),
+ content: "%1$d".to_string(),
+ example: Some("15".to_string()),
+ },
+ grit::TextPlaceholder::Text(
+ " folders deleted}\n many {".to_string(),
+ ),
+ grit::TextPlaceholder::Placeholder {
+ name: "COUNT".to_string(),
+ content: "%1$d".to_string(),
+ example: Some("100".to_string()),
+ },
+ grit::TextPlaceholder::Text(
+ " folders deleted}\n other {".to_string(),
+ ),
+ grit::TextPlaceholder::Placeholder {
+ name: "COUNT".to_string(),
+ content: "%1$d".to_string(),
+ example: Some("42".to_string()),
+ },
+ grit::TextPlaceholder::Text(
+ " folders deleted}}".to_string(),
+ ),
+ ],
+ },
+ ),
+ ],
+ },
+ )
+}