TiddlyWiki / TiddlyWikiClassic

TiddlyWiki Classic (not to be confused with TiddlyWiki5: https://github.com/Jermolene/TiddlyWiki5)
https://classic.tiddlywiki.com/
492 stars 114 forks source link

Standard order of tiddler attributes storage (to prevent unwanted diffs) #306

Open PengjuYan opened 6 months ago

PengjuYan commented 6 months ago

This issue surfaces to me when I'm developing/testing a plugin SwitchPalettePlugin. You won't notice that if you are a normal user.

When I save a TWC file, and use git diff to check the difference, I found many unnecessary changes are made to the order of html attributes of some tiddlers, even if the content of these tiddlers (title, tags, text) are never changed by the user.

Here are some examples:

tiddler before save after save
ColorPalette title="ColorPalette" modifier="Pengju" created="202401260942" modified="202401271137" is.dark.mode="true" from.palette="ColorPalette (pengju dark)" server.type="file" server.page.revision="202401270237" changecount="2" title="ColorPalette" modifier="Pengju" created="202401260942" modified="202401271137" changecount="2" server.page.revision="202401270237" server.type="file" from.palette="ColorPalette (pengju dark)" is.dark.mode="true"
TiddlerInFilePlugin title="TiddlerInFilePlugin" modifier="Yakov Litvin" created="201808191403" modified="202212060812" tags="systemConfig" content-type="text/javascript" changecount="274" title="TiddlerInFilePlugin" modifier="Yakov Litvin" created="201808191403" modified="202212060812" tags="systemConfig" changecount="274" content-type="text/javascript"

You can see that the attributes values remain untouched but what have been changed are the orders only.

Interestingly, attribute order of some tiddler never change. Those tiddlers include DefaultTiddlers, ExternalTiddlersList, StyleSheet, etc.

Because all the intact tiddlers only have normal attributes including title, creator, modifier, created, modified,tags (changecount seems like a second-class-citizen, too) and contaminated ones have non-official second-class-citizen attributes like server.type, from.palette, my guess is that the order of keys of official attributes are kept while others aren't.

While this doesn't seem a big deal, it does have some negative effect in some situations. Imagine you like to use git to track the changes to your TWC html file, the trial change of attribute order will make your tracking much harder (you have to look for real changes hidden in many non-sense ones).

YakovL commented 6 months ago

Hi Pengju, thanks for creating this issue, I'm aware of it and even have a draft solution for it (in fact, it's included into SUP) which includes sorting of non-standard fields. I haven't included it into the core yet for 2 reasons:

  1. it won't be nice if this affects performance of saving big TWs, so this should be researched first before applying;
  2. the other complication is that this should be done in different savers, like site building with TW5 or granulated saving via MTS.

So I won't be changing this right away, but once I have time for the necessary research (or may be somebody else helps with that), this can be pushed forward.

markkerrigan commented 6 months ago

I've experienced this before when viewing other people's TiddlyWiki, then their cookie values make their way into my personal TiddlyWiki.

The easiest way to replicate this is to download Okido's nwSaver (TW version 2.9.4), then visit your own TiddlyWiki, make a quick edit and save. I tried this with a TW file using 2.9.2 and I did not have the issue, but with another TW file running 2.10.0 I did start seeing these attributes. Using standard download saving, no saver configured.

<div tiddler="Main Page" modifier="Okido" created="201009172231" modified="202402101622" tags="" server.page.revision="201909091628" changecount="3">

These are my default cookie options.

Screenshot 2024-02-10 at 08-29-13

then also my zzConfig

config.options.chkAutoSave = true;
config.options.chkSaveBackups = false;
config.options.chkHttpReadOnly = false;
config.messages.tiddlerLinkTooltip = "%0 - %1 - %2";
config.options.txtTiddlerLinkTooltipDate = "DD MMM YYYY";
config.options.txtMaxEditRows = "40";
YakovL commented 6 months ago

Hi @markkerrigan , I don't think it's useful to look for exact scenarios here: the thing is, the store.forEachField call uses the for..in loop to iterate custom fields and JS (EcmaScript) doesn't guarantee the order of such iteration (it may depend on browser, on the order of adding properties (fields in this case), on the context, etc). So yeah, to avoid inconsistencies, we need explicit sorting here; as for the standard fields, they are concatenated in a fixed order

markkerrigan commented 6 months ago

Right my issue is I don't understand why the server.page.revision attribute is added, only that it seems to be cookie related.

YakovL commented 6 months ago

Hi, @markkerrigan, as far as I can see, the core sets the server.page.revision field only on import (with the "Keep these tiddlers linked to this server so that you can synchronise subsequent changes" option) or on "loading missing tiddler", i.e. when trying to open a link from a tiddler that was imported (with the server.page.revision field saved in it). You can look through the code (a shortcut would be to look for adaptor.getTiddlerList and adaptor.getTiddler, but plugins may do their own stuff about the fields). If there's something requiring an investigation, I think that deserves a separate issue/thread