Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Template improvements #3760

Open
wants to merge 10 commits into
base: master
Choose a base branch
from

Conversation

aknrdureegaesr
Copy link
Contributor

@aknrdureegaesr aknrdureegaesr commented Feb 20, 2024

Pull Request Checklist

  • I’ve read the guidelines for contributing.
  • I updated AUTHORS.txt and CHANGES.txt (if the change is non-trivial) and documentation (if applicable).
  • I tested my changes.

Description

New features:

  • Trace template usage if env variable NIKOLA_TEMPLATES_TRACE is set.
  • Enable raw template engine control via opitonal conf.py factory method.
  • Clarify template documentation: A parent template is not strictly needed.

Additional code improvements
helpful for those developing templates who actually read the code:

  • Added several typing hints and improved others.
  • A few code comments were added or improved.

Details

The commit message of the first commit can be used as the commit message of this entire PR.

docs/theming.rst Outdated
@@ -130,8 +134,9 @@ The following keys are currently supported:

The parent is so you don’t have to create a full theme each time: just
create an empty theme, set the parent, and add the bits you want modified.
You **must** define a parent, otherwise many features won’t work due to
missing templates, messages, and assets.
It is strongly recommended you define a parent. If you don't, many features
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope. Every theme must inherit from at least base/base-jinja, we explicitly refuse to support any other scenario (even if the code does not prevent this, we would prefer not to admit that it is a possibility, and we reserve the right to break it at any time.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a humble nice little blog in mind. For that, I absolutely want my HTML generated without any <div> in it. I want to prove that semantic HTML can be done. I also think that my little web site should work nicely without any Javascript (ROCA-style). This is not theory, this has really been my intention when I came to Nikola in the first place. If something in the templating changes, I'm willing to accept that my site will break on Nikola update and I'll have to fix.

I am willing to accept that I'll have to do a lot of theme customization to get that. As a platform as it stands now, Nikola would technically let me do this.

You are saying that Nikola strategically does not support my use case and I should go look elsewhere?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See https://www.famsik.de/opinions for background. In my opinion, Nikola could serve nicely for people who want to do experiments with stuff like that. But accepting that as a valid Nikola use case is a project-political decision.

Copy link
Contributor Author

@aknrdureegaesr aknrdureegaesr Feb 23, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thinking about it a bit further: From my point of view, it would be useful if Nikola would simply officially state that

  • it is possible to go without a parent template
  • things might break on any Nikola version update, as new template files become required from the code.

As for support, that would mean for Nokia a new template requirement needs to be announced in the change file.

Would that be something you'd be willing to do if asked nicely?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here’s some example wording that might work:

While it is possible to create a theme without a parent, it is strongly discouraged and not officially supported. The base and base-jinja themes provide assets, messages, and generic templates that Nikola expects to be able to use in all sites. That said, if you are making something very custom, Nikola will not prevent the creation of a theme without base, but you will need to manually determine which templates and messages are required in your theme.

It’s unlikely we’ll ever introduce a new template, but I guess it might be mentioned in the changelog if that happens.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as the changelog is concerned: Anything in the templates can be user-changed. So I think Nikola has to mention any change in the template arena in the changelog anyway. I see that as independent of the question "with base or not".

Copy link
Contributor Author

@aknrdureegaesr aknrdureegaesr Feb 24, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some stance like the one you suggest would answer my concerns. Thanks!

For some detail fine-tuning: I would prefer to warn people of consequences, yes, but otherwise treat them as adults who are able to make grown-up decisions. So I would think it nicer if we left out the "strongly discouraged" part. Maybe warn people that growing their own theme is harder than they might think at first sight.

As for the "not officially supported": Before people file a bug, we should require them to add the pertinent parent. If that makes the bug go away, it must not be filed.

Anything else the "not officially supported" entails?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

“Strongly discouraged” and “not officially supported” are meant to suggest “don’t do this unless you really know what you’re doing”. For user-facing software, phrases like this are a good idea IMO to clearly show the limitations.

“Not officially supported” means basically what you said, i.e. we won’t help with issues caused by a parentless theme, and we don’t guarantee it will always work.

Copy link
Contributor Author

@aknrdureegaesr aknrdureegaesr Mar 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Via the polyfill discussion, a solid reason surfaced why Nikola might rethink its policy of not officially supporting templates without parent.

Where GDPR rules, one needs a certain written agreement with any company before sending web traffic their way. This is a consequence of GDPR art 28, in particular section 2.. (I've personally been one of many developers who ported all references to Google fonts from external to locally hosted, in the web presence of a big Germany company (some 300.000+ employed).)

I believe small, private web sites are inside the target group of Nikola. People responsible for such web sites might not have the time and legal power to establish any such agreements legally needed. So they may choose to use no external resources whatsoever, but self-host everything their web site needs.

Nikola makes not promises regarding self-hosting presently. Indeed, build-in Nikola templates freely use external resources. Any Nikola version update might conceivably introduce or change external references in the HTML produced. Wanting to play it safe is a very solid reason to use a template without parent.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally there's the option use_cdn, but as #3763 shows this isn't always respected, like for polyfill.io.

I'm personally also using a template without a parent for my sites. (More precisely I have my own base template, and some templates deriving from my base.)

docs/theming.rst Outdated Show resolved Hide resolved
@@ -184,8 +196,16 @@ so ``post.tmpl`` only define the content, and the layout is inherited from ``bas

Another concept is theme inheritance. You do not need to duplicate all the
default templates in your theme — you can just override the ones you want
changed, and the rest will come from the parent theme. (Every theme needs a
parent.)
changed, and the rest will come from the parent theme. If your theme does not
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, unsupported and should not be documented.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think about the compromise "we document that this is unsupported", which is what I'm trying to do here?

nikola/__init__.py Outdated Show resolved Hide resolved
Comment on lines +38 to +43
# When this flag is set, fewer exceptions are handled internally;
# instead they are left unhandled for the run time system to deal with them,
# which typically leads to the stack traces being exposed.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# When this flag is set, fewer exceptions are handled internally;
# instead they are left unhandled for the run time system to deal with them,
# which typically leads to the stack traces being exposed.
# A flag to show tracebacks of unhandled exceptions.
# An alternative to the DEBUG flag with less noise.

(NIKOLA_DEBUG used to be very spammy with yapsy, it’s still not great to have it always on; export NIKOLA_SHOW_TRACEBACKS=1 is in my .zshrc though.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The wording "of unhandled exceptions" suggests whether the exceptions is handled or not is independent of this setting. As far as I remember, this is not the case.

nikola/plugins/template/jinja.py Outdated Show resolved Hide resolved
Comment on lines +49 to +52
if jinja2 is None:
lookup = None
else:
lookup: Optional[jinja2.Environment] = None
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider using a string annotation:

Suggested change
if jinja2 is None:
lookup = None
else:
lookup: Optional[jinja2.Environment] = None
lookup: 'Optional[jinja2.Environment]' = None

Copy link
Contributor Author

@aknrdureegaesr aknrdureegaesr Dec 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could be done and would technically work. But hides the concern and leaves the reader puzzling why the string has been used, as opposed to the plain Optional[jinja2.Environment]. By putting it into the else part, the concern is clear and explicit.

nikola/utils.py Outdated
if isinstance(string_or_iterable, (str, bytes)):
return string_or_iterable
elif isinstance(string_or_iterable, Iterable):
if isinstance(string_or_iterable, Iterable):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This won’t work, please undo:

>>> isinstance("a", typing.Iterable)
True

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, thanks!

But what we had previously also doesn't work, as bytes isn't a str.

How about calling str( ) for both str (where it is a no-op) and bytes (where you can be lucky, so it might work)?

nikola/utils.py Outdated

>>> smartjoin('; ', 'foo, bar')
'foo, bar'
>>> smartjoin('; ', ['foo', 'bar'])
'foo; bar'
>>> smartjoin(' to ', ['count', 42])
'count to 42'

The treatment of bytes (calling str(string_or_iterable)) is somewhat dubious. Is this needed?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be worth checking if bytes is ever passed here.

Copy link
Contributor Author

@aknrdureegaesr aknrdureegaesr Dec 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes!

But there's a lot in this PR already, so some other day (and maybe some other person). I'm content with leaving the mess as it is, just improving the type hints.

nikola/__init__.py Show resolved Hide resolved
nikola/log.py Outdated Show resolved Hide resolved
@aknrdureegaesr aknrdureegaesr marked this pull request as draft February 25, 2024 10:29
@aknrdureegaesr aknrdureegaesr marked this pull request as ready for review December 5, 2024 11:55
New features:

- Trace template usage if env variable NIKOLA_TEMPLATES_TRACE is set.
- Enable Jinja2 extensions via theme configuration.
- Clarify template documentation: A parent template is not strictly needed.

Additional code improvements
helpful for those developing templates who actually read the code:

- Added several typing hints and improved others.
- A few code comments were added or improved.
…te engine.

Also: Various type hint improvements.
Also some improvements to make the template handling code
better and more readable; mostly type hints.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants