Skip to content

Commit 0fadb4a

Browse files
Add optional slug field to chapter sections to allow for slug overriding (#2617)
* Add optional `slug` field to chapter sections to allow for slug overriding. Useful for including special chars in slug. * Add tests for optional slug field of chapter sections * Update docs to include optional slug field of chapter sections * Improve documentation for slug field of chapter sections
1 parent 49beb9e commit 0fadb4a

File tree

12 files changed

+109
-2
lines changed

12 files changed

+109
-2
lines changed

csfieldguide/chapters/content/structure/human-computer-interaction/sections/sections.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@ interface-usability:
1010
usability-heuristics:
1111
section-number: 4
1212

13-
mātāpono-māori:
13+
maataapono-maaori:
1414
section-number: 5
15+
slug: mātāpono-māori
1516

1617
accessibility:
1718
section-number: 6

csfieldguide/chapters/management/commands/_ChapterSectionsLoader.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ def load(self):
3434
"""
3535
chapter_sections_structure = self.load_yaml_file(self.structure_file_path)
3636
next_section_number = 1
37+
used_slugs = set()
3738

3839
for (section_slug, section_structure) in chapter_sections_structure.items():
3940
if section_structure is None:
@@ -74,6 +75,24 @@ def load(self):
7475
chapter_section_translations[language]["content"] = content.html_string
7576
chapter_section_translations[language]["name"] = content.title
7677

78+
# Override slug. Useful when macrons or other special chars wanted in slug.
79+
new_slug = section_structure.get("slug", None)
80+
if new_slug:
81+
if new_slug == section_slug:
82+
raise InvalidYAMLValueError(
83+
self.structure_file_path,
84+
f"slug - value {new_slug} is invalid.",
85+
f"Must be different from default slug {section_slug}."
86+
)
87+
if new_slug in used_slugs:
88+
raise InvalidYAMLValueError(
89+
self.structure_file_path,
90+
f"slug - value {new_slug} is invalid.",
91+
f"Must be unique, {new_slug} has already been used."
92+
)
93+
section_slug = new_slug
94+
used_slugs.add(section_slug)
95+
7796
chapter_section, created = self.chapter.chapter_sections.update_or_create(
7897
number=section_number,
7998
defaults={
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# This is the first section
2+
3+
## This is a second level heading
4+
5+
This is the content for the first section.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# This is the second section
2+
3+
## This is a second level heading
4+
5+
## This is another second level heading
6+
7+
This is the content for the second section.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# This is the section heading
2+
3+
This is the content for the section.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# This is the section heading
2+
3+
This is the content for the section.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
multiple-sections-duplicate-slug-1:
2+
section-number: 1
3+
slug: new-slug
4+
5+
multiple-sections-duplicate-slug-2:
6+
section-number: 2
7+
slug: new-slug
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
single-section-invalid-slug:
2+
section-number: 1
3+
slug: single-section-invalid-slug
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
single-section-slug:
2+
section-number: 1
3+
slug: new-slug

csfieldguide/tests/chapters/loaders/test_chapter_sections_loader.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,58 @@ def test_chapters_chapter_section_loader_single_section(self):
3838
transform=repr
3939
)
4040

41+
def test_chapters_chapter_section_loader_single_section_with_slug(self):
42+
test_slug = "single-section-slug"
43+
chapter = self.test_data.create_chapter("1")
44+
factory = mock.Mock()
45+
chapter_section_loader = ChapterSectionsLoader(
46+
factory,
47+
chapter,
48+
base_path=self.base_path,
49+
content_path=test_slug,
50+
structure_filename="{}.yaml".format(test_slug),
51+
)
52+
chapter_section_loader.load()
53+
querryset = ChapterSection.objects.all()
54+
self.assertQuerysetEqual(
55+
querryset,
56+
["<ChapterSection: This is the section heading>"],
57+
transform=repr
58+
)
59+
self.assertEqual(querryset[0].slug, 'new-slug')
60+
61+
def test_chapters_chapter_section_loader_single_section_with_invalid_slug(self):
62+
test_slug = "single-section-invalid-slug"
63+
chapter = self.test_data.create_chapter("1")
64+
factory = mock.Mock()
65+
chapter_section_loader = ChapterSectionsLoader(
66+
factory,
67+
chapter,
68+
base_path=self.base_path,
69+
content_path=test_slug,
70+
structure_filename="{}.yaml".format(test_slug),
71+
)
72+
self.assertRaises(
73+
InvalidYAMLValueError,
74+
chapter_section_loader.load
75+
)
76+
77+
def test_chapters_chapter_section_loader_multiple_sections_with_duplicate_slug(self):
78+
test_slug = "multiple-sections-duplicate-slug"
79+
chapter = self.test_data.create_chapter("1")
80+
factory = mock.Mock()
81+
chapter_section_loader = ChapterSectionsLoader(
82+
factory,
83+
chapter,
84+
base_path=self.base_path,
85+
content_path=test_slug,
86+
structure_filename="{}.yaml".format(test_slug),
87+
)
88+
self.assertRaises(
89+
InvalidYAMLValueError,
90+
chapter_section_loader.load
91+
)
92+
4193
def test_chapters_chapter_section_loader_multiple_sections(self):
4294
test_slug = "multiple-sections"
4395
chapter = self.test_data.create_chapter("1")

docs/author/chapters.rst

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,11 +149,15 @@ Chapter Sections Configuration File
149149

150150
- **Required Fields:**
151151

152-
- ``<section-slug>:`` Key for the section.
152+
- ``<section-slug>:`` Key for the section. Cannot contain macrons.
153153

154154
- **Required Fields:**
155155

156156
- ``section-number:`` Number order for the section in the chapter.
157+
158+
- **Optional fields:**
159+
160+
- ``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.)
157161

158162
A complete chapter application structure file with multiple chapters may look like the following:
159163

0 commit comments

Comments
 (0)