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