Skip to content

Commit f8053bb

Browse files
committed
Wrestle slug system to work with modern and legacy; rename all practice IDs to kebab case
1 parent e7683d4 commit f8053bb

File tree

40 files changed

+292
-253
lines changed

40 files changed

+292
-253
lines changed

CourseIndexPaths.gd

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,32 @@
11
class_name CourseIndexPaths
22
extends RefCounted
33

4+
const DEFAULT_COURSE_INDEX := "learn-gdscript"
45

56
const COURSES := {
6-
"learn_gdscript": "res://course/CourseLearnGDScriptIndex.gd"
7+
"learn-gdscript": "res://course/CourseLearnGDScriptIndex.gd"
78
}
89

910
const COURSE_SLUG_ALIASES := {
10-
"course": "learn_gdscript"
11+
"course": "learn-gdscript"
1112
}
1213

1314
static var _course_index_cache := {}
1415

1516

16-
static func get_course_index_instance(course_id: String) -> CourseIndex:
17+
static func build_all_practice_slugs() -> void:
18+
for course_index: String in COURSES:
19+
var index := get_course_index_instance(course_index)
20+
for i in index.get_lessons_count():
21+
var lesson := NavigationManager.get_navigation_resource(index.get_lesson_path(i))
22+
var lesson_slug: String = index.get_lesson_slug(i)
23+
for l in BBCodeUtils.get_lesson_practice_count(lesson):
24+
var practice := BBCodeUtils.get_lesson_practice(lesson, l)
25+
var id := BBCodeUtils.get_practice_id(practice)
26+
index.set_practice_slug(lesson_slug, id, practice)
27+
28+
29+
static func get_course_index_instance(course_id: String = DEFAULT_COURSE_INDEX) -> CourseIndex:
1730
var effective_id := course_id
1831
if not COURSES.has(course_id) and COURSE_SLUG_ALIASES.has(course_id):
1932
effective_id = COURSE_SLUG_ALIASES[course_id]

autoload/NavigationManager.gd

Lines changed: 61 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -19,20 +19,24 @@ var arguments := { }
1919

2020
var _current_unload_type := -1
2121
var _url_normalization_regex := RegExpGroup.compile(
22-
r"^(?<prefix>user:\/\/|res:\/\/|\.*?\/+)#?(?<course>.*?)\/(?<lesson>.*)\.(?<extension>t?res|bbcode)(?<practice>#P[0-9]+)?",
22+
r"^(?<prefix>user:\/\/|res:\/\/|\.*?\/+)#?(?<course>[^\/]+)\/(?<lesson>[^\/]+)\/?(?<lesson_file>[^\.]+\.[^\/]+)?\/?(?<practice>\$.*)?",
23+
)
24+
var _slug_normalization_regex := RegExpGroup.compile(
25+
r"^#?(?<course>[^\/]+)\/(?<lesson>[^\$]+)\/?(?<practice>\$.*)?",
2326
)
24-
var _practice_regex := RegEx.create_from_string("#P[0-9]+")
2527
var _lesson_cache := { }
2628

2729

2830
func _init() -> void:
31+
CourseIndexPaths.build_all_practice_slugs.call_deferred()
32+
2933
_parse_arguments()
3034
if _js_available:
31-
_on_init_setup_js()
35+
_on_init_setup_js.call_deferred()
3236
else:
3337
var initial_url: String = arguments.get("file", "")
3438
if initial_url != "":
35-
navigate_to(initial_url)
39+
navigate_to.call_deferred(initial_url)
3640

3741

3842
func _parse_arguments() -> void:
@@ -135,7 +139,10 @@ func navigate_to_welcome_screen() -> void:
135139
func navigate_to(metadata: String) -> void:
136140
var regex_result := _url_normalization_regex.search(metadata)
137141
if not regex_result:
138-
push_error("`%s` is not a valid resource or bbcode path" % [metadata])
142+
regex_result = _slug_normalization_regex.search(metadata)
143+
144+
if not regex_result:
145+
push_error("`%s` is not a valid bbcode or slug path" % [metadata])
139146
return
140147

141148
var normalized := NormalizedUrl.new(regex_result)
@@ -145,47 +152,49 @@ func navigate_to(metadata: String) -> void:
145152
push_error("'%s' is not a valid course" % [normalized.course_path])
146153
return
147154

148-
# legacy practices support
149-
var full_lesson_path := "%s.%s" % [normalized.lesson_path, normalized.extension]
150-
var alias := course_index.get_real_slug_from_slug(full_lesson_path)
151-
if alias != full_lesson_path:
152-
var new_path := "%s%s/%s" % [normalized.protocol, normalized.course_path, alias]
153-
regex_result = _url_normalization_regex.search(new_path)
155+
# legacy slugs support
156+
var legacy_path := normalized.lesson_path
157+
var lesson_slug := course_index.get_real_slug_from_slug(legacy_path)
158+
if lesson_slug != legacy_path:
159+
regex_result = _slug_normalization_regex.search("%s/%s" % [course_index.get_course_id(), lesson_slug])
154160
normalized = NormalizedUrl.new(regex_result)
155161

156-
if not normalized.lesson_path:
157-
push_error("`%s` is not a valid path" % metadata)
158-
return
159-
160-
var lesson_path := course_index.get_lesson_path_from_slug("%s.%s" % [normalized.lesson_path, normalized.extension])
162+
var lesson_path := course_index.get_lesson_path_from_slug(normalized.lesson_path)
161163

162164
var lesson := get_navigation_resource(lesson_path)
163165
if not (lesson is BBCodeParser.ParseNode):
164166
push_error("`%s` is not a lesson" % lesson_path)
165167
return
166168

167-
var effective_path := lesson_path
168-
if normalized.practice_index > -1:
169-
var practice := BBCodeUtils.get_lesson_practice(lesson, normalized.practice_index)
169+
var effective_path := "%s/%s" % [course_index.get_course_id(), normalized.lesson_path]
170+
if normalized.practice_path != "":
171+
var practice := course_index.get_practice_from_slug("%s/$%s" % [normalized.lesson_path, normalized.practice_path])
170172
if not practice is BBCodeParser.ParseNode:
171-
push_error("'%s' does not have a practice at index '%s'" % [lesson_path, normalized.practice_index])
173+
push_error("'%s' does not have a practice at slug '%s'" % [lesson_path, normalized.practice_path])
172174
return
173-
effective_path += "#P%s" % [normalized.practice_index]
175+
effective_path += "/$%s" % [normalized.practice_path]
174176

175177
history.push_back(effective_path)
176-
_push_javascript_state(normalized.get_web_url())
178+
_push_javascript_state(effective_path)
177179

178-
emit_signal("navigation_requested")
180+
navigation_requested.emit()
179181

180182

181183
func get_navigation_resource(resource_id: String) -> BBCodeParser.ParseNode:
182-
var practice_index_match := _practice_regex.search(resource_id)
183-
var is_practice := practice_index_match != null
184+
var normalized_url_groups := _url_normalization_regex.search(resource_id)
185+
var is_slug := false
186+
if not normalized_url_groups:
187+
is_slug = true
188+
normalized_url_groups = _slug_normalization_regex.search(resource_id)
189+
var is_practice := not normalized_url_groups.get_string("practice").is_empty()
184190

185191
var bbcode_path := resource_id
186192
if is_practice:
187-
bbcode_path = bbcode_path.left(-practice_index_match.strings[0].length())
188-
193+
bbcode_path = bbcode_path.left(-(normalized_url_groups.get_end("practice")-normalized_url_groups.get_start("practice")+1))
194+
if is_slug:
195+
var course_index := CourseIndexPaths.get_course_index_instance(normalized_url_groups.get_string("course"))
196+
bbcode_path = course_index.get_lesson_path_from_slug(normalized_url_groups.get_string("lesson").trim_suffix("/"))
197+
189198
var lesson_data: BBCodeParser.ParseNode = null
190199
if _lesson_cache.has(bbcode_path):
191200
lesson_data = _lesson_cache[bbcode_path]
@@ -210,9 +219,9 @@ func get_navigation_resource(resource_id: String) -> BBCodeParser.ParseNode:
210219
_lesson_cache[bbcode_path] = lesson_data
211220

212221
if is_practice:
213-
var practice_idx := int(practice_index_match.strings[0].substr(2))
214-
return BBCodeUtils.get_lesson_practice(lesson_data, practice_idx)
215-
222+
var course_index := CourseIndexPaths.get_course_index_instance(normalized_url_groups.get_string("course"))
223+
var lesson_slug := course_index.get_lesson_slug_from_path(bbcode_path)
224+
return course_index.get_practice_from_slug("%s/%s" % [lesson_slug, normalized_url_groups.get_string("practice")])
216225
return lesson_data
217226

218227

@@ -283,7 +292,7 @@ func _on_init_setup_js() -> void:
283292
else ""
284293
)
285294
if url:
286-
navigate_to("res://%s" % [url])
295+
navigate_to(url)
287296

288297

289298
# Handles user changing the url manually or pressing back
@@ -339,39 +348,43 @@ class NormalizedUrl:
339348
var protocol := ""
340349
var course_path := ""
341350
var lesson_path := ""
342-
var practice_index := -1
343-
var extension := ""
351+
var practice_path := ""
352+
var lesson_file := ""
344353

345354

346355
func _init(regex_result: RegExMatch) -> void:
347356
protocol = regex_result.get_string("prefix")
348357
course_path = regex_result.get_string("course")
349-
lesson_path = regex_result.get_string("lesson")
350-
extension = regex_result.get_string("extension")
358+
lesson_path = regex_result.get_string("lesson").trim_suffix("/")
359+
practice_path = regex_result.get_string("practice").substr(1)
360+
lesson_file = regex_result.get_string("lesson_file")
351361

352-
var practice_string := regex_result.get_string("practice")
353-
if practice_string:
354-
practice_index = int(practice_string.substr(2))
355362
if protocol in ["//", "/"]:
356363
protocol = "res://"
357364

358365

359-
func get_file_path() -> String:
360-
var file_path := "%s%s/%s.%s" % [protocol, course_path, lesson_path, extension]
361-
if practice_index > -1:
362-
file_path += "#P" % [practice_index]
366+
func get_file_path(with_practices: bool = false) -> String:
367+
var file_path := "%s%s/%s" % [protocol, course_path, lesson_path]
368+
if lesson_file != "":
369+
file_path += "/%s" % [lesson_file]
370+
if with_practices and practice_path != "":
371+
file_path += "/$%s" % [practice_path]
363372
return file_path
364373

365374

366375
func get_web_url() -> String:
367-
var url := "%s/%s.%s" % [course_path, lesson_path, extension]
368-
if practice_index > -1:
369-
url += "#P%s" % [practice_index]
376+
var url := "%s/%s" % [course_path, lesson_path]
377+
if lesson_file != "":
378+
url += "/%s" % [lesson_file]
379+
if practice_path != "":
380+
url += "/$%s" % [practice_path]
370381
return url
371382

372383

373384
func _to_string() -> String:
374-
var string := "%s%s/%s"
375-
if practice_index > -1:
376-
string += "#P%s" % [practice_index]
385+
var string := "%s%s/%s" % [protocol, course_path, lesson_path]
386+
if lesson_file != "":
387+
string += "/%s" % [lesson_file]
388+
if practice_path != "":
389+
string += "/$%s" % [practice_path]
377390
return string

0 commit comments

Comments
 (0)