diff --git "a/csfieldguide/chapters/content/en/human-computer-interaction/sections/m\304\201t\304\201pono-m\304\201ori.md" b/csfieldguide/chapters/content/en/human-computer-interaction/sections/maataapono-maaori.md similarity index 100% rename from "csfieldguide/chapters/content/en/human-computer-interaction/sections/m\304\201t\304\201pono-m\304\201ori.md" rename to csfieldguide/chapters/content/en/human-computer-interaction/sections/maataapono-maaori.md diff --git a/csfieldguide/chapters/content/structure/human-computer-interaction/sections/sections.yaml b/csfieldguide/chapters/content/structure/human-computer-interaction/sections/sections.yaml index 8b10348cb..e3a39c598 100644 --- a/csfieldguide/chapters/content/structure/human-computer-interaction/sections/sections.yaml +++ b/csfieldguide/chapters/content/structure/human-computer-interaction/sections/sections.yaml @@ -10,8 +10,9 @@ interface-usability: usability-heuristics: section-number: 4 -mātāpono-māori: +maataapono-maaori: section-number: 5 + slug: mātāpono-māori accessibility: section-number: 6 diff --git a/csfieldguide/chapters/management/commands/_ChapterSectionsLoader.py b/csfieldguide/chapters/management/commands/_ChapterSectionsLoader.py index eb4998534..f659cd921 100644 --- a/csfieldguide/chapters/management/commands/_ChapterSectionsLoader.py +++ b/csfieldguide/chapters/management/commands/_ChapterSectionsLoader.py @@ -34,6 +34,7 @@ def load(self): """ chapter_sections_structure = self.load_yaml_file(self.structure_file_path) next_section_number = 1 + used_slugs = set() for (section_slug, section_structure) in chapter_sections_structure.items(): if section_structure is None: @@ -74,6 +75,24 @@ def load(self): chapter_section_translations[language]["content"] = content.html_string chapter_section_translations[language]["name"] = content.title + # Override slug. Useful when macrons or other special chars wanted in slug. + new_slug = section_structure.get("slug", None) + if new_slug: + if new_slug == section_slug: + raise InvalidYAMLValueError( + self.structure_file_path, + f"slug - value {new_slug} is invalid.", + f"Must be different from default slug {section_slug}." + ) + if new_slug in used_slugs: + raise InvalidYAMLValueError( + self.structure_file_path, + f"slug - value {new_slug} is invalid.", + f"Must be unique, {new_slug} has already been used." + ) + section_slug = new_slug + used_slugs.add(section_slug) + chapter_section, created = self.chapter.chapter_sections.update_or_create( number=section_number, defaults={ diff --git a/csfieldguide/tests/chapters/loaders/assets/chapter-sections/en/multiple-sections-duplicate-slug/multiple-sections-duplicate-slug-1.md b/csfieldguide/tests/chapters/loaders/assets/chapter-sections/en/multiple-sections-duplicate-slug/multiple-sections-duplicate-slug-1.md new file mode 100644 index 000000000..d8d0c4682 --- /dev/null +++ b/csfieldguide/tests/chapters/loaders/assets/chapter-sections/en/multiple-sections-duplicate-slug/multiple-sections-duplicate-slug-1.md @@ -0,0 +1,5 @@ +# This is the first section + +## This is a second level heading + +This is the content for the first section. diff --git a/csfieldguide/tests/chapters/loaders/assets/chapter-sections/en/multiple-sections-duplicate-slug/multiple-sections-duplicate-slug-2.md b/csfieldguide/tests/chapters/loaders/assets/chapter-sections/en/multiple-sections-duplicate-slug/multiple-sections-duplicate-slug-2.md new file mode 100644 index 000000000..1bbab9023 --- /dev/null +++ b/csfieldguide/tests/chapters/loaders/assets/chapter-sections/en/multiple-sections-duplicate-slug/multiple-sections-duplicate-slug-2.md @@ -0,0 +1,7 @@ +# This is the second section + +## This is a second level heading + +## This is another second level heading + +This is the content for the second section. diff --git a/csfieldguide/tests/chapters/loaders/assets/chapter-sections/en/single-section-invalid-slug/single-section-invalid-slug.md b/csfieldguide/tests/chapters/loaders/assets/chapter-sections/en/single-section-invalid-slug/single-section-invalid-slug.md new file mode 100644 index 000000000..524f6f2bc --- /dev/null +++ b/csfieldguide/tests/chapters/loaders/assets/chapter-sections/en/single-section-invalid-slug/single-section-invalid-slug.md @@ -0,0 +1,3 @@ +# This is the section heading + +This is the content for the section. diff --git a/csfieldguide/tests/chapters/loaders/assets/chapter-sections/en/single-section-slug/single-section-slug.md b/csfieldguide/tests/chapters/loaders/assets/chapter-sections/en/single-section-slug/single-section-slug.md new file mode 100644 index 000000000..524f6f2bc --- /dev/null +++ b/csfieldguide/tests/chapters/loaders/assets/chapter-sections/en/single-section-slug/single-section-slug.md @@ -0,0 +1,3 @@ +# This is the section heading + +This is the content for the section. diff --git a/csfieldguide/tests/chapters/loaders/assets/chapter-sections/structure/multiple-sections-duplicate-slug/multiple-sections-duplicate-slug.yaml b/csfieldguide/tests/chapters/loaders/assets/chapter-sections/structure/multiple-sections-duplicate-slug/multiple-sections-duplicate-slug.yaml new file mode 100644 index 000000000..6e8d2193d --- /dev/null +++ b/csfieldguide/tests/chapters/loaders/assets/chapter-sections/structure/multiple-sections-duplicate-slug/multiple-sections-duplicate-slug.yaml @@ -0,0 +1,7 @@ +multiple-sections-duplicate-slug-1: + section-number: 1 + slug: new-slug + +multiple-sections-duplicate-slug-2: + section-number: 2 + slug: new-slug diff --git a/csfieldguide/tests/chapters/loaders/assets/chapter-sections/structure/single-section-invalid-slug/single-section-invalid-slug.yaml b/csfieldguide/tests/chapters/loaders/assets/chapter-sections/structure/single-section-invalid-slug/single-section-invalid-slug.yaml new file mode 100644 index 000000000..e2c7ebec4 --- /dev/null +++ b/csfieldguide/tests/chapters/loaders/assets/chapter-sections/structure/single-section-invalid-slug/single-section-invalid-slug.yaml @@ -0,0 +1,3 @@ +single-section-invalid-slug: + section-number: 1 + slug: single-section-invalid-slug diff --git a/csfieldguide/tests/chapters/loaders/assets/chapter-sections/structure/single-section-slug/single-section-slug.yaml b/csfieldguide/tests/chapters/loaders/assets/chapter-sections/structure/single-section-slug/single-section-slug.yaml new file mode 100644 index 000000000..f14e1f70e --- /dev/null +++ b/csfieldguide/tests/chapters/loaders/assets/chapter-sections/structure/single-section-slug/single-section-slug.yaml @@ -0,0 +1,3 @@ +single-section-slug: + section-number: 1 + slug: new-slug diff --git a/csfieldguide/tests/chapters/loaders/test_chapter_sections_loader.py b/csfieldguide/tests/chapters/loaders/test_chapter_sections_loader.py index cff76b397..9daec0d29 100644 --- a/csfieldguide/tests/chapters/loaders/test_chapter_sections_loader.py +++ b/csfieldguide/tests/chapters/loaders/test_chapter_sections_loader.py @@ -38,6 +38,58 @@ def test_chapters_chapter_section_loader_single_section(self): transform=repr ) + def test_chapters_chapter_section_loader_single_section_with_slug(self): + test_slug = "single-section-slug" + chapter = self.test_data.create_chapter("1") + factory = mock.Mock() + chapter_section_loader = ChapterSectionsLoader( + factory, + chapter, + base_path=self.base_path, + content_path=test_slug, + structure_filename="{}.yaml".format(test_slug), + ) + chapter_section_loader.load() + querryset = ChapterSection.objects.all() + self.assertQuerysetEqual( + querryset, + [""], + transform=repr + ) + self.assertEqual(querryset[0].slug, 'new-slug') + + def test_chapters_chapter_section_loader_single_section_with_invalid_slug(self): + test_slug = "single-section-invalid-slug" + chapter = self.test_data.create_chapter("1") + factory = mock.Mock() + chapter_section_loader = ChapterSectionsLoader( + factory, + chapter, + base_path=self.base_path, + content_path=test_slug, + structure_filename="{}.yaml".format(test_slug), + ) + self.assertRaises( + InvalidYAMLValueError, + chapter_section_loader.load + ) + + def test_chapters_chapter_section_loader_multiple_sections_with_duplicate_slug(self): + test_slug = "multiple-sections-duplicate-slug" + chapter = self.test_data.create_chapter("1") + factory = mock.Mock() + chapter_section_loader = ChapterSectionsLoader( + factory, + chapter, + base_path=self.base_path, + content_path=test_slug, + structure_filename="{}.yaml".format(test_slug), + ) + self.assertRaises( + InvalidYAMLValueError, + chapter_section_loader.load + ) + def test_chapters_chapter_section_loader_multiple_sections(self): test_slug = "multiple-sections" chapter = self.test_data.create_chapter("1") diff --git a/docs/author/chapters.rst b/docs/author/chapters.rst index 0ee37e913..627461ff3 100644 --- a/docs/author/chapters.rst +++ b/docs/author/chapters.rst @@ -149,11 +149,15 @@ Chapter Sections Configuration File - **Required Fields:** - - ``:`` Key for the section. + - ``:`` Key for the section. Cannot contain macrons. - **Required Fields:** - ``section-number:`` Number order for the section in the chapter. + + - **Optional fields:** + + - ``slug:`` Override the chapter section's slug. Use this to include macrons in URL. (See mātāpono-māori chapter section for example use case.) A complete chapter application structure file with multiple chapters may look like the following: