diff --git a/content/pages/a_page.md b/content/pages/a_page.md index 2c4339f..f37368f 100644 --- a/content/pages/a_page.md +++ b/content/pages/a_page.md @@ -11,4 +11,4 @@ template_engine jinja2

Page 1

-

Go to page 2

\ No newline at end of file +

Go to page 2

\ No newline at end of file diff --git a/content/pages/another_page.md b/content/pages/another_page.md index 281fd93..17f11b8 100644 --- a/content/pages/another_page.md +++ b/content/pages/another_page.md @@ -11,4 +11,4 @@ template_engine jinja2

Page 2

-

Go to page 1

+

Go to page 1

diff --git a/content/templates/jinja2/blocks/en/navbar.html b/content/templates/jinja2/blocks/en/navbar.html index d2ddb7b..80f83a1 100644 --- a/content/templates/jinja2/blocks/en/navbar.html +++ b/content/templates/jinja2/blocks/en/navbar.html @@ -4,7 +4,7 @@ CTA_LABEL="See pricing", CTA_TARGET="", CTA_URL="#pricing", - CHANGE_LANG_URL="fr-index", + CHANGE_LANG_URL="/fr-index.html", CHANGE_LANG_FLAG_URL="assets/img/lang-fr.svg", CHANGE_LANG_ALT="Version française" ) }} \ No newline at end of file diff --git a/content/templates/jinja2/blocks/fr/navbar.html b/content/templates/jinja2/blocks/fr/navbar.html index 29345f5..7f48327 100644 --- a/content/templates/jinja2/blocks/fr/navbar.html +++ b/content/templates/jinja2/blocks/fr/navbar.html @@ -4,7 +4,7 @@ CTA_LABEL="Découvrir les tarifs", CTA_TARGET="", CTA_URL="#pricing", - CHANGE_LANG_URL="en-index", + CHANGE_LANG_URL="/en-index.html", CHANGE_LANG_FLAG_URL="assets/img/lang-gb.svg", CHANGE_LANG_ALT="English version" ) }} \ No newline at end of file diff --git a/content/templates/jinja2/widgets/navbar.html b/content/templates/jinja2/widgets/navbar.html index 445d1dc..dada97a 100644 --- a/content/templates/jinja2/widgets/navbar.html +++ b/content/templates/jinja2/widgets/navbar.html @@ -19,7 +19,7 @@ diff --git a/jssg/jinja2.py b/jssg/jinja2.py index 3589a9b..f8ad0ca 100644 --- a/jssg/jinja2.py +++ b/jssg/jinja2.py @@ -5,38 +5,84 @@ from jssg.templatetags.filter_opengraph_metadata import filter_opengraph_metadata - from jssg.models import Page -def url_from_slug(slug) : +import re + +def url_for_slug(slug) : + """ + @param slug: the slug of the page to search + @return: the string of the url corresponding to the page + @error: raise an exception if the slug does not exist or it is not unique (eg same slug found in several folders) + + >>> url_for_slug('index') # the slug exists and is unique + /en/index.html + + >>> url_for_slug('index-duplicated') # the slug exists in several pages + Traceback (most recent call last): + ... + Exception: slug 'index-duplicated' is not unique, found in : [pages/fr-index.md, pages/en-index.md] ; use url_for_slug_path() + + >>> url_for_slug('index-removed') # the slug does not exists + Traceback (most recent call last): + ... + Exception: slug 'index-removed' not found + + """ + url = "" - pages_with_slug = "" + pages_with_slug = [] for page in Page.load_glob(all=True) : - if page.slug == slug : - if pages_with_slug == "" : - url = "/" + page.dir + "/" + page.slug + ".html" - else : + if page.slug == slug : # the page exists + if pages_with_slug == [] : # the slug has not been found yet + if page.rel_folder_path != '' : + url = "/" + page.rel_folder_path + "/" + page.slug + ".html" + else : + url = "/" + page.slug + ".html" + else : # the slug already exists url = "" - pages_with_slug += str(page.path.relative_to(page.page_dir.parent)) + ", " + pages_with_slug.append(str(page.path.relative_to(page.content_page_dir.parent))) - if url == "" and pages_with_slug != "" : - raise Exception("url_slug() : slug '%s' is not unique, found in : [%s] ; use url_abs()" % (slug, pages_with_slug[:-2])) + if url == "" and pages_with_slug != [] : + raise Exception("slug '%s' is not unique, found in : [%s] ; use url_for_slug_path()" % (slug, ", ".join(pages_with_slug))) elif url == "" : - raise Exception("url_slug() : slug '%s' not found" % slug) + raise Exception("slug '%s' not found" % slug) return url -def url_absolute(url_path) : - dir = '/'.join(url_path.split('/')[:-1]) - slug = ''.join((''.join(url_path.split('/')[-1])).split('.')[0]) +def url_for_slug_path(url_path) : + """ + @param url_path: the url of the page to search (absolute path) + @return: the string of the url corresponding to the page + @error: raise an exception if the url is a dead link + + >>> url_for_slug_path('/en/index.html') # the page exists + /en/index.html + + >>> url_for_slug_path('/en/index-removed.html') # the page does not exist + Traceback (most recent call last): + ... + Exception: page for '/en/index-removed.html' url not found (dead link) - for page in Page.get_pages() : - if page["slug"] == slug and dir == "" : - return "/" + slug + ".html" - elif page["slug"] == slug and "dir" in page.keys() and page["dir"] == dir : - return "/" + dir + "/" + slug + ".html" + >>> url_for_slug_path('folder/index') + Traceback (most recent call last): + ... + Exception: url 'folder/index' is not valid ; correct urls are //.html or / + + """ + # Valid url are //.html or /.html + # Example: if url_path is "/tmp/folder/subfolder/thefile.html", then slug will be "thefile" and the dir will be "tmp/folder/subfolder" + try : + _, dir, slug = re.findall(r"(^|^/([a-zA-Z0-9-/]+))/([a-zA-Z0-9-]+)\.html", url_path)[0] + except : + raise Exception("url '%s' is not valid ; correct urls are //.html or /.html" % url_path) + + # Verify that the page exists + for page in Page.load_glob(all=True) : + if page.slug == slug and page.rel_folder_path == dir : + return url_path - raise Exception("url_abs() : page for %s url not found" % url_path) + raise Exception("page for '%s' url not found (dead link)" % url_path) def environment(**options): env = Environment(**options) @@ -44,8 +90,8 @@ def environment(**options): { "static": static, "url": reverse, - "url_slug": url_from_slug, - "url_abs" : url_absolute + "url_for_slug": url_for_slug, + "url_for_slug_path" : url_for_slug_path } ) env.filters.update( diff --git a/jssg/models.py b/jssg/models.py index 4439424..de227f4 100644 --- a/jssg/models.py +++ b/jssg/models.py @@ -238,13 +238,14 @@ def __init__(self, content: str, **metadata) -> None: except KeyError: self.slug = slugify(self.title) - self.page_dir = self.path - while (self.page_dir not in self.BASE_DIR) : - self.page_dir = self.page_dir.parent + self.content_page_dir = self.path + while (self.content_page_dir not in self.BASE_DIR) : + self.content_page_dir = self.content_page_dir.parent - self.dir = str(self.path.relative_to(self.page_dir).parent) - if self.dir == '.' : - self.dir = '' + # page folder path relative to its content_page_dir + self.rel_folder_path = str(self.path.relative_to(self.content_page_dir).parent) + if self.rel_folder_path == '.' : + self.rel_folder_path = '' @classmethod def load_page_with_slug(cls, slug: str, dir : str) -> "Page": @@ -259,7 +260,7 @@ def load_glob( @classmethod def get_pages(cls) : - return ({"slug": p.slug} if p.dir == '' else {"dir": p.dir, "slug" : p.slug} for p in Page.load_glob(all = True)) + return ({"slug": p.slug} if p.rel_folder_path == '' else {"dir": p.rel_folder_path, "slug" : p.slug} for p in Page.load_glob(all = True)) class Post(Page): @@ -285,7 +286,7 @@ def load_glob( @classmethod def get_posts(cls) : - return ({"slug": p.slug} if p.dir == '' else {"dir": p.dir, "slug" : p.slug} for p in Post.load_glob(all = True)) + return ({"slug": p.slug} if p.rel_folder_path == '' else {"dir": p.rel_folder_path, "slug" : p.slug} for p in Post.load_glob(all = True)) class Sitemap : BASE_DIR = settings.JFME_PAGES_DIRS + settings.JFME_POSTS_DIRS