Skip to content

Commit

Permalink
Validate content #5935
Browse files Browse the repository at this point in the history
  • Loading branch information
boryanagoncharenko committed Nov 25, 2024
1 parent ad6f5cc commit 57595d1
Show file tree
Hide file tree
Showing 6 changed files with 225 additions and 54 deletions.
12 changes: 11 additions & 1 deletion content/pages/el.yaml
Original file line number Diff line number Diff line change
@@ -1 +1,11 @@
{}
home-sections:
- title: This is Greek translation
text: |-
1. Here is an html link: <a #HREF_DISCORD_SERVER# href="https://tricket.io" target="_blank">Discord server</a>
2. There is a markdown link [Discord](#MD_DISCORD_SERVER#)
3. And here is an image: <img #SRC_CUSTOMIZE_ADVENTURE# width="1000">
- title: This is Greek translation
text: |-
1. Here is an html link: <a #HREF_DISCORD_SERVER# target="_blank">Discord server</a>
2. There is a markdown link [Discord](#MD_DISCORD_SERVER#)
3. And here is an image: <img #SRC_CUSTOMIZE_ADVENTURE# width="1000">
29 changes: 14 additions & 15 deletions content/pages/en.yaml
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
title: Hedy documentation
home-sections:
- title: Textual programming made easy!
- title: This is English translation
text: |-
Many schools and teachers around the world want to teach their students programming. Initially this is often done with playful tools, ranging from the Beebot robot to
Scratch Junior or Scratch. After using such tools, kids often want to move to more powerful, textual programming languages, like Python.
Python however is hard, because it is only available in English, and requires learners to learn complex programming concepts and syntax at once.
Hedy is the easy way to get started with textual programming languages! Hedy is free to use, open source, and unlike any other textual programming language in three ways.
1. Hedy is multi-lingual, you can use Hedy in your own language
2. Hedy is gradual, so you can learn one concept and its syntax a time
3. Hedy is built for the classroom, allowing teachers to fully customize their student's experience
- title: Multi-lingual programming
text: While almost all textual programming language have keywords in English, such as `for` or `repeat`, Hedy can be used in any language! We currently support 47 different languages, including Dutch, Spanish, Arabic, Turkish, Chinese and Hindi. If your language is not available you can always start a new translation.
This section is hijacked for exemplary purposes
1. Here is an html link: <a #HREF_DISCORD_SERVER# target="_blank">Discord server</a>
2. There is a markdown link [Discord](#MD_DISCORD_SERVER#)
3. And here is an image: <img #SRC_CUSTOMIZE_ADVENTURE# width="1000">
- title: This is English translation
text: |-
This section is hijacked for exemplary purposes too. However, it shows what happens if you have bad content:
1. An html link with a custom href: <a href="https://bad.url.com" target="_blank">Discord server</a>
2. An markdown link with a non-whitelisted link: [discord](https://bad.url.com)
3. An image with a non-whitelisted source: <img src="https://bad.url.com" width="1000">
- title: Step by step learning
text: Learning a programming language can be overwhelming, since learners have to learn concepts (for example if-else or loops) and syntax (like quotation marks or round brackets) at the same time. In Hedy, concepts are first introduced with little syntax and then refined. A scientifically proven way to learn!
- title: Built for the classroom
Expand Down Expand Up @@ -49,7 +48,7 @@ join-sections:
- title: Help teachers get started
text: |-
Hedy is designed to support teachers in providing programming lessons in class. We have specific teacher features like the option to create a class, customize it and see how your students are doing.
If you like Hedy, you can reach out to schools that you know to help teachers get started! We can help you find schools or teachers via <a href="https://discord.gg/8yY7dEme9r" target="_blank">Discord</a>.
If you like Hedy, you can reach out to schools that you know to help teachers get started! We can help you find schools or teachers via <a #HREF_DISCORD_SERVER# target="_blank">Discord</a> or via [Discord](#MD_DISCORD_SERVER#).
learn-more-sections:
- title: The Hedy foundation
text: |-
Expand Down Expand Up @@ -95,14 +94,14 @@ start-sections:
text: |-
Welcome to Hedy, we are happy to help you get started with Hedy.
Our [Teacher Manual](https://www.hedy.org/for-teachers/manual) has an overview of all features in detail, but this page has a brief overview so you know what it what before you dive in.
Our [Teacher Manual](#MD_TEACHERS_MANUAL#) has an overview of all features in detail, but this page has a brief overview so you know what it what before you dive in.
A few highlights that are important to know:
* Hedy is a tool designed to help manage a classroom of kids programming! You can create your own classes, lesson plans and follow how kids are doing.
* You do not need to know a lot of programming if you begin, Hedy works step by step, also for you!
* You can use Hedy in your native tongue because it has been translated into many other languages!
* Every kid can programme!! Hedy is especially helpful for kids who have vision problems because it can read material aloud to you without the need for a mouse.
* We are here to help, you can find us for example on [Discord](https://discord.gg/8yY7dEme9r) or you can [email-us]([email protected]).
* We are here to help, you can find us for example on [Discord](#MD_DISCORD_SERVER#) or you can [email-us](#MD_MAIL_TO_HELLO_HEDY#).
- title: Teachers about Hedy
text: |-
Various teachers worldwide have expressed their passion for Hedy, as some have shared with us:
Expand Down
82 changes: 65 additions & 17 deletions tests/tests_z_yamlfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,72 +45,120 @@ def test_load_yaml_equivalent(self):
# Merging of YAML content
# Key of type dict
def test_merge_dicts_prefers_source(self):
result = YamlFile.merge_yaml({"key1": "source"}, {"key1": "fallback"})
result = YamlFile.validate_and_merge_yaml({"key1": "source"}, {"key1": "fallback"})
self.assertEqual({"key1": "source"}, result)

def test_merge_dicts_uses_fallback_if_source_key_not_present(self):
result = YamlFile.merge_yaml({}, {"key1": "fallback"})
result = YamlFile.validate_and_merge_yaml({}, {"key1": "fallback"})
self.assertEqual({"key1": "fallback"}, result)

def test_merge_dicts_skips_key_if_not_present_in_fallback_empty(self):
result = YamlFile.merge_yaml({"key1": "source"}, {})
result = YamlFile.validate_and_merge_yaml({"key1": "source"}, {})
self.assertEqual({}, result)

def test_merge_dicts_skips_key_if_not_present_in_fallback(self):
result = YamlFile.merge_yaml({"key2": "source"}, {"key1": "fallback"})
result = YamlFile.validate_and_merge_yaml({"key2": "source"}, {"key1": "fallback"})
self.assertEqual({"key1": "fallback"}, result)

# Key of type list
def test_merge_lists_prefers_source(self):
result = YamlFile.merge_yaml({"key1": ["a", "b"]}, {"key1": ["c", "d"]})
result = YamlFile.validate_and_merge_yaml({"key1": ["a", "b"]}, {"key1": ["c", "d"]})
self.assertEqual({"key1": ["a", "b"]}, result)

def test_merge_lists_skips_key_if_not_present_in_fallback(self):
result = YamlFile.merge_yaml({"key1": ["a", "b"]}, {})
result = YamlFile.validate_and_merge_yaml({"key1": ["a", "b"]}, {})
self.assertEqual({}, result)

def test_merge_lists_uses_fallback_if_source_key_not_present_empty(self):
result = YamlFile.merge_yaml({}, {"key1": ["c", "d"]})
result = YamlFile.validate_and_merge_yaml({}, {"key1": ["c", "d"]})
self.assertEqual({"key1": ["c", "d"]}, result)

def test_merge_lists_uses_fallback_if_source_key_not_present(self):
result = YamlFile.merge_yaml({"key2": ["a", "b"]}, {"key1": ["c", "d"]})
result = YamlFile.validate_and_merge_yaml({"key2": ["a", "b"]}, {"key1": ["c", "d"]})
self.assertEqual({"key1": ["c", "d"]}, result)

# Elements in list
def test_merge_lists_values_prefers_source(self):
result = YamlFile.merge_yaml({"key1": [None, "b"]}, {"key1": ["c", "d"]})
result = YamlFile.validate_and_merge_yaml({"key1": [None, "b"]}, {"key1": ["c", "d"]})
self.assertEqual({"key1": ["c", "b"]}, result)

def test_merge_lists_values_uses_fallback_if_value_is_empty(self):
result = YamlFile.merge_yaml({"key1": ["", "b"]}, {"key1": ["c", "d"]})
result = YamlFile.validate_and_merge_yaml({"key1": ["", "b"]}, {"key1": ["c", "d"]})
self.assertEqual({"key1": ["c", "b"]}, result)

def test_merge_lists_values_prefers_len_of_fallback(self):
result = YamlFile.merge_yaml({"key1": ["a", "b", "e"]}, {"key1": ["c", "d"]})
result = YamlFile.validate_and_merge_yaml({"key1": ["a", "b", "e"]}, {"key1": ["c", "d"]})
self.assertEqual({"key1": ["a", "b"]}, result)

def test_merge_lists_values_prefers_source_values(self):
result = YamlFile.merge_yaml({"key1": ["a"]}, {"key1": ["c", "d"]})
result = YamlFile.validate_and_merge_yaml({"key1": ["a"]}, {"key1": ["c", "d"]})
self.assertEqual({"key1": ["a", "d"]}, result)

# Keys with mismatched types
def test_merge_dicts_prefers_fallback_type_dict(self):
result = YamlFile.merge_yaml({"key1": ["a", "b"]}, {"key1": {"a": "c", "b": "d"}})
result = YamlFile.validate_and_merge_yaml({"key1": ["a", "b"]}, {"key1": {"a": "c", "b": "d"}})
self.assertEqual({"key1": {"a": "c", "b": "d"}}, result)

def test_merge_dicts_prefers_fallback_type_str(self):
result = YamlFile.merge_yaml({"key1": ["a", "b"]}, {"key1": "string value"})
result = YamlFile.validate_and_merge_yaml({"key1": ["a", "b"]}, {"key1": "string value"})
self.assertEqual({"key1": "string value"}, result)

def test_merge_dicts_prefers_fallback_type_list(self):
result = YamlFile.merge_yaml({"key1": {"a": "c", "b": "d"}}, {"key1": ["a", "b"]})
result = YamlFile.validate_and_merge_yaml({"key1": {"a": "c", "b": "d"}}, {"key1": ["a", "b"]})
self.assertEqual({"key1": ["a", "b"]}, result)

def test_merge_dicts_prefers_fallback_type_string(self):
result = YamlFile.merge_yaml({"key1": {"a": "c", "b": "d"}}, {"key1": "string value"})
result = YamlFile.validate_and_merge_yaml({"key1": {"a": "c", "b": "d"}}, {"key1": "string value"})
self.assertEqual({"key1": "string value"}, result)

def test_merge_dicts_prefers_fallback_type_bool(self):
result = YamlFile.merge_yaml({"key1": True}, {"key1": "string value"})
result = YamlFile.validate_and_merge_yaml({"key1": True}, {"key1": "string value"})
self.assertEqual({"key1": True}, result)

def test_process_html_content_dict(self):
result = YamlFile.validate_and_merge_yaml({"key1": 'clean content'}, {"key1": 'fallback'})
self.assertEqual({"key1": 'clean content'}, result)

def test_process_html_content_dict_invalid(self):
result = YamlFile.validate_and_merge_yaml({"key1": '<a href="//bad.com"></a>'}, {"key1": 'fallback'})
self.assertEqual({"key1": 'fallback'}, result)

def test_process_html_content_nested_dict_invalid(self):
result = YamlFile.validate_and_merge_yaml({"key1": {"key2": '<a href="//bad.com"></a>'}}, {"key1": {"key2": 'fallback'}})
self.assertEqual({"key1": {"key2": 'fallback'}}, result)

def test_process_html_content_dict_partial_invalid(self):
result = YamlFile.validate_and_merge_yaml({"key1": '<a #HREF_DISCORD_SERVER#></a>', "key2": '<a href="//bad.com"></a>'}, {"key1": '<a #HREF_DISCORD_SERVER#></a>', "key2": 'fallback'})
self.assertEqual({"key1": '<a href="https://discord.gg/8yY7dEme9r"></a>', "key2": 'fallback'}, result)

def test_process_html_content_list_partial_invalid(self):
result = YamlFile.validate_and_merge_yaml(['<a #HREF_DISCORD_SERVER#></a>', '<a href="//bad.com"></a>'], ['<a #HREF_DISCORD_SERVER#></a>', 'fallback'])
self.assertEqual(['<a href="https://discord.gg/8yY7dEme9r"></a>', 'fallback'], result)

def test_process_html_content_bool(self):
result = YamlFile.validate_and_merge_yaml(True, False)
self.assertEqual(True, result)

# def test_process_html_content_bool(self):
# result = YamlFile.process_html_content({"key1": True})
# self.assertEqual({"key1": True}, result)
#
# def test_process_html_content_dict(self):
# result = YamlFile.process_html_content({"key1": {'key2': 'test'}})
# self.assertEqual({"key1": {'key2': 'test'}}, result)
#
# def test_process_html_content_list(self):
# result = YamlFile.process_html_content({"key1": ['one', 'two', 'three']})
# self.assertEqual({"key1": ['one', 'two', 'three']}, result)
#
# def test_process_html_content_string_with_anchor(self):
# result = YamlFile.process_html_content({"key1": 'this <a href="//test.com">video</a>'})
# self.assertEqual({"key1": 'this &lt;a href="//test.com"&gt;video&lt;/a&gt;'}, result)
#
# def test_process_html_content_string_with_script(self):
# result = YamlFile.process_html_content({"key1": 'this <script>hello</script>'})
# self.assertEqual({"key1": 'this &lt;script&gt;hello&lt;/script&gt;'}, result)

# def test_process_html_content_string_with_md_link(self):
# result = YamlFile.process_html_content({"key1": 'this [video](//test.com).'})
# self.assertEqual({"key1": r'this \[video]\(//test.com).'}, result)
18 changes: 9 additions & 9 deletions translations/en/LC_MESSAGES/messages.po
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ msgid "adventures_completed"
msgstr "Adventures completed: {number_of_adventures}"

msgid "adventures_info"
msgstr "Each Hedy level has built-in exercises for students, which we call adventures. You can create your own adventures and add them to your classes. With your own adventures you can create adventures that are relevant and interesting for your students. You can find more information about creating your own adventures <a href=\"https://hedy.org/for-teachers/manual/features\">here</a>."
msgstr "Each Hedy level has built-in exercises for students, which we call adventures. You can create your own adventures and add them to your classes. With your own adventures you can create adventures that are relevant and interesting for your students. You can find more information about creating your own adventures <a #HREF_TEACHERS_MANUAL_FEATURES#>here</a>."

msgid "adventures_restored"
msgstr "The default adventures have been restored."
Expand Down Expand Up @@ -349,7 +349,7 @@ msgid "classes"
msgstr "Classes"

msgid "classes_info"
msgstr "Create a class to follow the progress of each student in dashboard, and to customize the adventures your students see, and even adding your own! You can create as many classes as you like, and each class can have multiple teachers each one with different roles. You can also add as many students as you want, but mind that each student can only be in one class at a time. You can find more information about classes in the <a href=\"https://hedy.org/for-teachers/manual/preparations#for-teachers\">teacher manual</a>."
msgstr "Create a class to follow the progress of each student in dashboard, and to customize the adventures your students see, and even adding your own! You can create as many classes as you like, and each class can have multiple teachers each one with different roles. You can also add as many students as you want, but mind that each student can only be in one class at a time. You can find more information about classes in the <a #HREF_TEACHERS_MANUAL_FOR_TEACHERS#>teacher manual</a>."

msgid "clear"
msgstr "Clear"
Expand Down Expand Up @@ -925,7 +925,7 @@ msgid "logged_in_to_share"
msgstr "You must be logged in to save and share a program."

msgid "login"
msgstr "Log in"
msgstr "Log in <script></script>"

msgid "login_long"
msgstr "Log in to your account"
Expand Down Expand Up @@ -982,18 +982,18 @@ msgstr ""
"<strong>What teacher's accounts can do</strong>\n"
"There are a number of extra options unlocked for you now.\n"
"\n"
"1. Extra explanation is available in the <a href=\"https://hedy.org/for-teachers/manual\">teacher's manual</a>.\n"
"2. With your teacher account, you can create classes. Your students can than join your classes and you can see their progress. Classes are made and managed though the for <a href=\"https://hedycode.com/for-teachers\">teachers page</a>.\n"
"1. Extra explanation is available in the <a #HREF_TEACHERS_MANUAL_FEATURES#>teacher's manual</a>.\n"
"2. With your teacher account, you can create classes. Your students can than join your classes and you can see their progress. Classes are made and managed though the for <a #HREF_FOR_TEACHERS#>teachers page</a>.\n"
"3. You can fully customize your classes, for example you can open and close levels, enable or disable adventures and author your own adventures!\n"
"\n"
"<strong>Join our online community!</strong>\n"
"All Hedy teachers, programmers and other fans are welcome to join our <a href=\"https://discord.gg/8yY7dEme9r\">Discord server</a>. This is the ideal place to chat about Hedy: we have channels where you can show your cool projects and lessons, channels to report bugs, and channels to chat with other teachers and with the Hedy team.\n"
"All Hedy teachers, programmers and other fans are welcome to join our <a #HREF_DISCORD_SERVER#>Discord server</a>. This is the ideal place to chat about Hedy: we have channels where you can show your cool projects and lessons, channels to report bugs, and channels to chat with other teachers and with the Hedy team.\n"
"\n"
"<strong>How to ask for help </strong>\n"
"If anything is unclear, you can let us know on Discord, or <a href=\"mailto: [email protected]\">send us an email</a>.\n"
"If anything is unclear, you can let us know on Discord, or <a #HREF_MAIL_TO_HELLO_HEDY#>send us an email</a>.\n"
"\n"
"<strong>How to report bugs</strong>\n"
"In Discord, we have a channel for reporting bugs, called #bugs. That is the perfect place to let us know about issues you are running into. If you know how to use GitHub, you can create an <a href=\"https://github.com/hedyorg/hedy/issues/new?assignees=&labels=&template=bug_report.md&title=%5BBUG%5D\">issue</a> there.\n"
"In Discord, we have a channel for reporting bugs, called #bugs. That is the perfect place to let us know about issues you are running into. If you know how to use GitHub, you can create an <a #HREF_OPEN_BUG_REPORT#>issue</a> there.\n"

msgid "mail_welcome_teacher_subject"
msgstr "Your Hedy teacher account is ready"
Expand Down Expand Up @@ -1571,7 +1571,7 @@ msgid "slides_for_level"
msgstr "Slides for level"

msgid "slides_info"
msgstr "For each level of Hedy, we have created slides to help you teach. The slides contain explanations of each level, and Hedy examples that you can run inside the slides. Just click the link and get started! the Introduction slides are a general explanation of Hedy before level 1 The slides were created using <a href=\"https://slides.com\">slides.com</a>. If you want to adapt them yourself, you can download them, and then upload the resulting zip file to <a href=\"https://slides.com\">slides.com</a>. You can find more information about the slides in the <a href=\"https://hedy.org/for-teachers/manual/features\">teacher's manual</a>."
msgstr "For each level of Hedy, we have created slides to help you teach. The slides contain explanations of each level, and Hedy examples that you can run inside the slides. Just click the link and get started! the Introduction slides are a general explanation of Hedy before level 1 The slides were created using <a #HREF_SLIDES_COM#>slides.com</a>. If you want to adapt them yourself, you can download them, and then upload the resulting zip file to <a #URL_SLIDES#>slides.com</a>. You can find more information about the slides in the <a #HREF_TEACHERS_MANUAL_FEATURES#>teacher's manual</a>."

msgid "social_media"
msgstr "Social media"
Expand Down
Loading

0 comments on commit 57595d1

Please sign in to comment.