A simple solution would be to create a button allowing you to bulk edit recently imported tiddlers manually:
<$button>
Set imported timestamp
<$list filter="[[$:/Import]links[]]">
<$action-setfield imported=<<now [UTC]YYYY0MM0DD0hh0mm0ssXXX>> $timestamp="no"/>
</$list>
</$button>
You would need to remember to click the button right after importing the tiddlers while the $:/Import tiddler is up to date.
You could automate this by overriding the tiddler $:/core/ui/ViewTemplate/body/import, but modifying core tiddlers is generally discouraged because it prevents that file from receiving updates when you upgrade TiddlyWiki.
A cleaner approach is to create a small startup module to implement a new system tag $:/tags/ImportAction. Tiddlers with this tag will execute automatically immediately after an import.
Make a backup of your wiki before attempting this!
To achieve this, we need to create a small script to “hook” into the import process.
Create a new tiddler (e.g., $:/plugins/custom/import-hook.js) with the following fields:
-
Type:
application/javascript
-
Field:
module-type with value startup
Then paste this code into the body:
/*\
title: $:/plugins/custom/import-hook.js
type: application/javascript
module-type: startup
Runs actions tagged with $:/tags/ImportAction after an import is performed.
Only actions present before the import will be performed.
\*/
(function(){
"use strict";
exports.name = "import-actions-hook";
exports.platforms = ["browser"];
exports.after = ["startup"];
exports.synchronous = true;
exports.startup = function() {
var NavigatorWidget = require("$:/core/modules/widgets/navigator.js").navigator;
var originalHandlePerformImportEvent = NavigatorWidget.prototype.handlePerformImportEvent;
NavigatorWidget.prototype.handlePerformImportEvent = function(event) {
var importTiddlerTitle = event.param || "$:/Import";
var importTiddler = this.wiki.getTiddler(importTiddlerTitle);
var blockedTitles = [];
// --- PHASE 1: Identify targets BEFORE import ---
if(importTiddler) {
try {
var importData = JSON.parse(importTiddler.fields.text);
if(importData && importData.tiddlers) {
var incomingTitles = Object.keys(importData.tiddlers);
for(var k=0; k<incomingTitles.length; k++) {
var title = incomingTitles[k];
// Check 1: Is the tiddler actually selected for import?
// TiddlyWiki stores selection state in fields like "selection-TiddlerTitle"
var selectionState = importTiddler.fields["selection-" + title];
// If explicitly set to "no", it is NOT being imported. Skip blocking logic.
if(selectionState === "no") continue;
// Check 2: Content Comparison
// We compare the INCOMING text with the EXISTING text.
// If they are identical, it is a safe re-import (allow execution).
// If they are different (or new), it is a potential threat (block execution).
var incomingText = importData.tiddlers[title].text;
var existingTiddler = this.wiki.getTiddler(title);
var existingText = existingTiddler ? existingTiddler.fields.text : null;
if(incomingText !== existingText) {
blockedTitles.push(title);
}
}
}
} catch(e) {
console.error("Import Hook: Error analyzing import safety", e);
}
}
// --- PHASE 2: Perform the Import ---
// This writes the new/changed tiddlers to the wiki
var result = originalHandlePerformImportEvent.call(this, event);
// --- PHASE 3: Run Actions ---
var actionTiddlers = this.wiki.filterTiddlers("[all[tiddlers+shadows]tag[$:/tags/ImportAction]]");
for(var i=0; i<actionTiddlers.length; i++) {
var actionTitle = actionTiddlers[i];
// SECURITY CHECK:
if(blockedTitles.indexOf(actionTitle) !== -1) {
console.warn("SECURITY BLOCKED: Prevented execution of newly imported/modified action: " + actionTitle);
continue;
}
this.invokeActionString(this.wiki.getTiddlerText(actionTitle), this, event, {
importTiddler: importTiddlerTitle
});
}
return result;
};
};
})();
How this works
This script uses a technique called “monkey patching” to extend TiddlyWiki’s core Navigator widget:
-
Intercept: It listens for the
handlePerformImportEvent (which happens when you click “Import”).
-
Execute Core Logic: It runs the original TiddlyWiki import function first, ensuring the files are actually imported as usual.
-
Hook: Immediately after the import finishes, it searches for any tiddlers tagged with
$:/tags/ImportAction.
-
Execute Actions: It runs the text of those tiddlers as ActionWidgets, passing them a variable called
importTiddler.
Note: this solution uses the “Monkey Patch” approach instead of relying on the th-before-importing hook to let you use standard TiddlyWiki macros and widgets immediately after an import, which are easier to write and maintain.
Save and reload your wiki for the script to take effect.
Now you can create your timestamp action.
- Create a new tiddler (e.g.,
$:/config/AutoSetImportDate).
- Add the tag:
$:/tags/ImportAction
- Paste the following into the text field:
<$list filter="[<importTiddler>links[]]">
<$action-setfield imported=<<now "[UTC]YYYY0MM0DD0hh0mm0ssXXX">> $timestamp="no"/>
</$list>
This uses the variable <importTiddler> passed by our script to target the specific batch being processed, applying the timestamp instantly without requiring a manual button click.
Demo (with examples): https://import-action.tiddlyhost.com/
See also: Feature-request: action on import?