Updating a single file tiddlywiki in-place

Edit: I updated the upgrader to make it possible to update any single file wiki in-place, by setting the path of the core plugin to the official tiddlywiki plugin hosted on github page

The recent releases of tiddlywiki now allow to easily update our wiki in-place, using the external core setup.

Try it on tiddlyhost: https://tiddlyhost.com/sites/new?clone=upgrade-tiddlywiki-external

Plugin: tiddlywiki-upgrader

Wikitext:

\procedure store-tw-versions-data()
  <$action-setfield $tiddler="$:/temp/store-tw-versions-data" status=<<status>> data=<<data>>/>
\end

\procedure get-tw-versions()
  <$action-sendmessage
    $message="tm-http-request"
    url="https://api.github.com/repos/TiddlyWiki/tiddlywiki.com-gh-pages/contents/prerelease"
    bind-status="$:/temp/store-tw-versions-data/status"
    oncompletion=<<store-tw-versions-data>>
  />
\end

\function is.pending()
[{$:/temp/store-tw-versions-data/status}match[pending]]
\end

\function tw.versions()
  [[$:/temp/store-tw-versions-data]get[data]jsonindexes[]] 
  :map[[$:/temp/store-tw-versions-data]get[data]jsonget<currentTiddler>,[name]removeprefix[tiddlywikicore-]removesuffix[.js]]
  :filter[!is[blank]]
\end

\function tw.latest.prerelease()
  [tw.versions[]suffix[-prerelease]last[]]
\end

\function tw.latest.stable()
  [tw.versions[]!suffix[-prerelease]last[]]
\end

\function target.version()
  [tw.latest.prerelease[]]
  :filter[[$:/temp/store-tw-versions-data]get[enable-prerelease]match[true]]
  :else[tw.latest.stable[]]
  :filter[compare:version:gt<version>]
  :else[<version>]
\end

\define defaultBasePath()
./
\end

\function base.path()
  [[$:/config/coreURL]get[base-path]else<defaultBasePath>]
\end

\function coreURL()
  [[$(base.path)$tiddlywikicore-$(target.version)$.js]substitute[]]
\end

\function is.backup.enabled()
  [[$:/temp/store-tw-versions-data]get[enable-backup]else[true]match[true]]
\end

\procedure update-version()
  <!-- trigger the save to apply the new version -->
  <$wikify name="site-title" text={{$:/config/SaveWikiButton/Filename}}>
    <$action-sendmessage
      $message="tm-save-wiki"
      $param="$:/core/save/offline-external-js"
      filename=<<site-title>>
      version=<<target.version>>
      coreURL=<<coreURL>>
    />
  </$wikify>
\end

\procedure confirm-version-change()
    <%if [is.backup.enabled[]] %>
      <!-- backup first to avoid data loss -->
      <$let 
        publishFilter="-[[$:/config/SaveWikiButton/Template]] -[[$:/plugins/tiddlywiki/filesystem]] -[[$:/plugins/tiddlywiki/tiddlyweb]]"
        filename=`${ [<site-title>] }$⏱${[get[modified]!sort[]first[]]}$`
      >
        <!-- Download wiki including the core -->
        <$action-sendmessage
            $message="tm-download-file"
            $param="$:/core/save/all"
            publishFilter=<<publishFilter>>
            filename=`$(filename)$-all`
        />
        <!-- Download wiki + core separately -->
        <$action-sendmessage
            $message="tm-download-file"
            $param="$:/core/save/offline-external-js"
            publishFilter=<<publishFilter>>
            filename=`$(filename)$-external`
        />
        <$action-sendmessage
            $message="tm-download-file"
            $param="$:/core/templates/tiddlywiki5.js"
            filename=`tiddlywikicore-$(version)$.js`
            type="application/javascript"
          />
      </$let>
      <%endif%>
      <<update-version>>
\end

\procedure refresh-page()
  <$action-sendmessage $message="tm-browser-refresh"/>
\end

<$tiddler tiddler="$:/temp/store-tw-versions-data">
<$button actions=<<get-tw-versions>> >{{$:/core/images/refresh-button}} Check for updates</$button>

<p><$checkbox field="enable-prerelease" checked="true"> enable prerelease</$checkbox></p>

<%if [is.pending[]] %>
<p>Loading..</p>
<%elseif [<tw.versions>is[blank]] %>
<%elseif [<target.version>match<version>] %>

<p>Tiddlywiki  v<<version>> is the latest version</p>

<%else%>

<$checkbox field="enable-backup" default="true" checked="true" unchecked="false"> Perform a backup before upgrading</$checkbox>

<$button actions=<<confirm-version-change>> class="tc-btn-invisible tc-install-plugin tc-reinstall-upgrade">
    {{$:/core/images/download-button}} Upgrade from v<<version>> → v<<target.version>>
</$button>

<p>
Please <$button actions=<<refresh-page>> >reload the page</$button> once the upgrade is complete.
</p>
<%endif%>

<hr>

Base path for the <a href=<<coreURL>> >core</a>: <$edit tiddler="$:/config/coreURL" field="base-path" default=<<defaultBasePath>> placeholder=<<defaultBasePath>>/>

<$button actions=<<update-version>>>update</$button>

<aside>Official base path: `https://tiddlywiki.com/prerelease/`</aside>

</$tiddler>
Explanation

This is how it works.

Tiddlywiki initialize the version number by looking at the meta tags ($:/core/modules/utils/utils.js) :

/*
Extract the version number from the meta tag or from the boot file
*/

// Browser version
exports.extractVersionInfo = function() {
	if($tw.packageInfo) {
		return $tw.packageInfo.version;
	} else {
		var metatags = document.getElementsByTagName("meta");
		for(var t=0; t<metatags.length; t++) {
			var m = metatags[t];
			if(m.name === "tiddlywiki-version") {
				return m.content;
			}
		}
	}
	return null;
};

It is then made available in the version macro ($:/core/modules/macros/version.js):

/*\
title: $:/core/modules/macros/version.js
type: application/javascript
module-type: macro

Macro to return the TiddlyWiki core version number

\*/

"use strict";

/*
Information about this macro
*/

exports.name = "version";

exports.params = [];

/*
Run the macro
*/
exports.run = function() {
	return $tw.version;
};

The version macro is used in $:/core/save/offline-external-js, which is used to handle the save when the wiki has an external core:

\whitespace trim
\import [subfilter{$:/core/config/GlobalImportFilter}]
\define saveTiddlerFilter()
[is[tiddler]] -[prefix[$:/state/popup/]] -[prefix[$:/temp/]] -[prefix[$:/HistoryList]] -[status[pending]plugin-type[import]] -[[$:/core]] -[[$:/plugins/tiddlywiki/filesystem]] -[[$:/plugins/tiddlywiki/tiddlyweb]] -[[$:/boot/boot.css]] -[is[system]type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] +[sort[title]] $(publishFilter)$
\end
\define defaultCoreURL() tiddlywikicore-$(version)$.js
<$let coreURL={{{ [[coreURL]is[variable]then<coreURL>else<defaultCoreURL>] }}}>
	{{$:/core/templates/tiddlywiki5-external-js.html}}
</$let>

All we need to do to change the core version is to override the version variable (which tiddlywiki derive from the meta tags) and trigger a save. That way, it will update the meta tag, update the version output by the version macro, and as long as the core javascript file follow the standard naming convention, the correct file will be used to load the core plugin.


Related: Upgrading external-core tiddlyhost files, How to reduce the size of your Tiddlywiki

1 Like

Sure looks like it works. If so, would be much easier than current 6 step process.

For “time-travel”, it’s a bit of a one-way trip. You can’t go back further than 5.3.2 and then return, because %if didn’t exist before 5.3.2.

Is there a way to make it easy to download a local copy of a particular version of the core? I think that’s what prevents me from using the external core version more often.

1 Like

Thanks for the feedback !

You can set the version then download the core with the tiddler “$:/core/ui/ExportTiddlyWikiCore”, or download a full version, core included using “$:/core/ui/ExportTiddlyWikiCore”. I updated the demo :slight_smile:

Nice!

Since the objective is to use the TW both with and without the core, it might help if there was an option to download the wiki without the core? And yes, I know I could do that from the TH control panel. Just thinking in terms of “one-stop shopping.”

Thanks!

1 Like

Personally I use something like this:

<$button>
Make a backup
<$action-sendmessage $message="tm-download-file" filename=`${ [{$:/SiteTitle}] [get[modified]!sort[]first[]] +[join[⏱]]}$`/>
</$button>

This approach is effective.

1 Like

I updated the demo to add a backup option that will download the core, the wiki+core and the wiki minus the core. It’s also now no longer limited to tiddlyhost and can be used locally. I removed the select widget to only show the latest version, to prevent “time travel” since downgrading a wiki could break things :sweat_smile:

I added it to my plugin library, to make future updates easier: tiddlywiki-upgrader

1 Like