TiddlyWiki / TiddlyWiki5

A self-contained JavaScript wiki for the browser, Node.js, AWS Lambda etc.
https://tiddlywiki.com/
Other
8.02k stars 1.19k forks source link

[BUG] Exporting mutilates some css selectors #8380

Closed twMat closed 2 months ago

twMat commented 3 months ago

Describe the bug

Try out this Demo. Note that there are two style definitions within a style block in the tiddler.

But the exporting converts the > selector into >. (Also & selectors becomes &) This kills the styling selector.

Expected behavior

Within a stylesheet or a styleblock, no such conversion should take place.

To Reproduce

  1. Go to the demo
  2. Click on Export as Static HTML
  3. See error
  4. Check the inspector to see how > has become > in one of the style defs.

Screenshots

No response

TiddlyWiki Configuration

Additional context

No response

Jermolene commented 3 months ago

Hi @twMat I am afraid that this is just one of several pitfalls with using embedded stylesheets in wikitext tiddlers. The core does not use this technique, and I strongly recommend that TiddlyWiki users avoid it. While it seems beguilingly simple, it is brittle in subtle and hard-to-debug ways that make it a minefield.

The pitfalls mostly stem from accidentally using wikitext syntax within a stylesheet, causing it to be interpreted differently. For example, referencing a URL with https://... within a stylesheet will be interpreted as the start of a run of italics. Other examples include # signs at the start of a line being interpreted as a numbered list.

The problem you've run into is slightly more subtle, and stems from the fact that the HTML specification requires that > be encoded as > and so text within wikitext tiddlers are automatically encoded. CSS does not require escaping, and does not understand the > notation.

The fundamental problem is that CSS and wikitext are different languages, and need to be handled differently in TiddlyWiki.

That's the current situation but it is worth thinking whether we can improve things. The obvious approach would be for the wikitext parser to have special handling for <style> elements that would not recursively parse the content of the element, and instead take all the text up the closing </style> as the plain text of the stylesheet.

That simple approach would not support macros and wikitext within the stylesheet block. Sometimes it is useful to be able to reference the <<colour>> macro for example. Fixing that would require that we do recursively parse the content of the stylesheet block, but with the same restricted set of "safe" parsing rules that we use for stylesheets.

So, the end result would be that the content of embedded stylesheets would be parsed with a restricted set of rules, avoiding the accidental wikitext problem referred to above.

However, we would still be left with the problem of < in stylesheets being encoded. The encoding is done later, as part of the processing done by the view widget which has no knowledge of the distinction between an embeded stylesheet block and the surrounding wikitext.

It is worth exploring further but I am not hopeful that these issues can be ironed out, and so for the moment by recommendation would continue to be to avoid embedded stylesheet blocks.

twMat commented 3 months ago

Thank you @Jermolene - that is a very informative reply, much appreciated.

for the moment by recommendation would continue to be to avoid embedded stylesheet blocks.

but if the stylesheet is not embedded, how could it then reference currentTiddler and other contextual variables? This is the main, possibly even the only, reason why I need to use these styleblocks. I can't think of any other solution.

CodaCodr commented 3 months ago

but if the stylesheet is not embedded, how could it then reference currentTiddler and other contextual variables?

Probably not the best place to get into that here. Post on the forum?

I went to look at the site, did you take it down?

Jermolene commented 3 months ago

but if the stylesheet is not embedded, how could it then reference currentTiddler and other contextual variables? This is the main, possibly even the only, reason why I need to use these styleblocks. I can't think of any other solution.

As @CodaCodr suggests it would be well worth bringing up an example on the forum to see if we can figure out a better approach.

twMat commented 3 months ago

Thanks everyone for the replies. I'll post over at the chicken yard.

@CodaCodr - there's no problem accessing the demo site with the given links, afaict. Here it is again:

https://issue-8380.tiddlyhost.com/

twMat commented 2 months ago

Of possible relevance, I found this stackoverflow post which asks "Why are the < turned into &lt ;?". Essentially, the reply is:

[in javascript] .text() always converts HTML special characters to entities so they won't be treated as markup, because it expects text, not HTML.

...i.e that individual had used the wrong js function for that context. Might TW have a similar bug or is > converted into &gt; deliberately because that conversion is usually the right thing? @Jermolene

Thanks!

Jermolene commented 2 months ago

Hi @twMat the Stack Overflow answer is not wrong: no encoding is needed when creating text nodes in the DOM. That is the technique that TiddlyWiki uses. The encoding of < is actually done by the browser (or the "fakedom" implementation of the browser APIs that TW uses on the server).

twMat commented 2 months ago

Thanks @Jermolene - so I then also understand from your reply that my problem, then, is a consequence not of any bug but simply becuse TW is currently not quite built for my use case. Fair enough.

twMat commented 2 months ago

@Jermolene

It is worth exploring further but I am not hopeful that these issues can be ironed out, and so for the moment by recommendation would continue to be to avoid embedded stylesheet blocks.

For the record:

While I've managed to circumvent the issue directly described in the OP (the mutilation of some css selectors), the question about embedding stylesheets for the sake of accessing e.g currentTiddler remains. My real example that promplted the question is the static plugin. In it's core tiddler, there is a prominent section of embedded styles that rely heavily on variables from the environment. I don't know how to achieve the end result without this and would welcome solutions.

Definitely drifting from OP - and I realize I'm naive in asking - but: Couldn't stylesheets just be tagged with $:/tags/Global and we ditch the stylesheet tag (but perhaps keep the type) and just like macros be addressable with params? C'mon how hard can it be? ;-) Hackability dude!

Jermolene commented 2 months ago

there is a prominent section of embedded styles that rely heavily on variables from the environment. I don't know how to achieve the end result without this and would welcome solutions.

There's a bit too much code for me to trace through it exhaustively, but the general principle would be to have separate tiddlers for the wikitext content and the stylesheets, sharing the same set of global definitions. Then, if you're say generating stylesheets in a loop with the names of elements depending on the loop, you would have to duplicate the logic in both the wikitext tiddler and the stylesheet, so that the same variables are available.

Would you be able to extract a minimal test case?

twMat commented 2 months ago

duplicate the logic in both the wikitext tiddler and the stylesheet, so that the same variables are available.

Ahaaa, but of course! This should solve it! Thank you @Jermolene !