1
0
mirror of https://github.com/Jermolene/TiddlyWiki5 synced 2024-11-07 18:39:57 +00:00

Merge branch 'master' into confetti-plugin

This commit is contained in:
jeremy@jermolene.com 2023-01-24 12:40:52 +00:00
commit 75af83174b
70 changed files with 732 additions and 619 deletions

View File

@ -359,14 +359,14 @@ node $TW5_BUILD_TIDDLYWIKI \
# Delete any existing static content
rm $TW5_BUILD_OUTPUT/languages/de-AT/static/*
rm $TW5_BUILD_OUTPUT/languages/de-DE/static/*
rm $TW5_BUILD_OUTPUT/languages/es-ES/static/*
rm $TW5_BUILD_OUTPUT/languages/fr-FR/static/*
rm $TW5_BUILD_OUTPUT/languages/ja-JP/static/*
rm $TW5_BUILD_OUTPUT/languages/ko-KR/static/*
rm $TW5_BUILD_OUTPUT/languages/zh-Hans/static/*
rm $TW5_BUILD_OUTPUT/languages/zh-Hant/static/*
rm -rf $TW5_BUILD_OUTPUT/languages/de-AT/static/*
rm -rf $TW5_BUILD_OUTPUT/languages/de-DE/static/*
rm -rf $TW5_BUILD_OUTPUT/languages/es-ES/static/*
rm -rf $TW5_BUILD_OUTPUT/languages/fr-FR/static/*
rm -rf $TW5_BUILD_OUTPUT/languages/ja-JP/static/*
rm -rf $TW5_BUILD_OUTPUT/languages/ko-KR/static/*
rm -rf $TW5_BUILD_OUTPUT/languages/zh-Hans/static/*
rm -rf $TW5_BUILD_OUTPUT/languages/zh-Hant/static/*
# /languages/de-AT/index.html Demo wiki with de-AT language
# /languages/de-AT/empty.html Empty wiki with de-AT language

View File

@ -313,7 +313,7 @@ $tw.utils.getLocationHash = function() {
var idx = href.indexOf('#');
if(idx === -1) {
return "#";
} else if(idx < href.length-1 && href[idx+1] === '#') {
} else if(href.substr(idx + 1,1) === "#" || href.substr(idx + 1,3) === "%23") {
// Special case: ignore location hash if it itself starts with a #
return "#";
} else {
@ -375,7 +375,7 @@ $tw.utils.stringifyList = function(value) {
var result = new Array(value.length);
for(var t=0, l=value.length; t<l; t++) {
var entry = value[t] || "";
if(entry.indexOf(" ") !== -1) {
if(entry.match(/[^\S\xA0]/mg)) {
result[t] = "[[" + entry + "]]";
} else {
result[t] = entry;

View File

@ -57,7 +57,7 @@ Command.prototype.execute = function() {
exportPath = path.resolve(outputPath,macroPath + extension);
}
}
var finalPath = exportPath || path.resolve(pathname,encodeURIComponent(title) + extension);
var finalPath = exportPath || path.resolve(pathname,$tw.utils.encodeURIComponentExtended(title) + extension);
$tw.utils.createFileDirectories(finalPath);
fs.writeFileSync(finalPath,text,"utf8");
});

View File

@ -65,7 +65,7 @@ Command.prototype.execute = function() {
$tw.utils.each(filteredPluginList,function(title) {
var tiddler = containerData.tiddlers[title];
// Save each JSON file and collect the skinny data
var pathname = path.resolve(self.commander.outputPath,basepath + encodeURIComponent(title) + ".json");
var pathname = path.resolve(self.commander.outputPath,basepath + $tw.utils.encodeURIComponentExtended(title) + ".json");
$tw.utils.createFileDirectories(pathname);
fs.writeFileSync(pathname,JSON.stringify(tiddler),"utf8");
// Collect the skinny list data

View File

@ -45,7 +45,7 @@ Command.prototype.execute = function() {
var tiddler = self.commander.wiki.getTiddler(title),
type = tiddler.fields.type || "text/vnd.tiddlywiki",
contentTypeInfo = $tw.config.contentTypeInfo[type] || {encoding: "utf8"},
filename = path.resolve(pathname,encodeURIComponent(title));
filename = path.resolve(pathname,$tw.utils.encodeURIComponentExtended(title));
fs.writeFileSync(filename,tiddler.fields.text,contentTypeInfo.encoding);
});
return null;

View File

@ -27,7 +27,7 @@ exports.decodeuricomponent = function(source,operator,options) {
exports.encodeuricomponent = function(source,operator,options) {
var results = [];
source(function(tiddler,title) {
results.push(encodeURIComponent(title));
results.push($tw.utils.encodeURIComponentExtended(title));
});
return results;
};

View File

@ -15,7 +15,7 @@ The PDF parser embeds a PDF viewer
var ImageParser = function(type,text,options) {
var element = {
type: "element",
tag: "embed",
tag: "iframe",
attributes: {}
},
src;

View File

@ -1,64 +0,0 @@
/*\
title: $:/core/modules/savers/beaker.js
type: application/javascript
module-type: saver
Saves files using the Beaker browser's (https://beakerbrowser.com) Dat protocol (https://datproject.org/)
Compatible with beaker >= V0.7.2
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
/*
Set up the saver
*/
var BeakerSaver = function(wiki) {
this.wiki = wiki;
};
BeakerSaver.prototype.save = function(text,method,callback) {
var dat = new DatArchive("" + window.location),
pathname = ("" + window.location.pathname).split("#")[0];
dat.stat(pathname).then(function(value) {
if(value.isDirectory()) {
pathname = pathname + "/index.html";
}
dat.writeFile(pathname,text,"utf8").then(function(value) {
callback(null);
},function(reason) {
callback("Beaker Saver Write Error: " + reason);
});
},function(reason) {
callback("Beaker Saver Stat Error: " + reason);
});
return true;
};
/*
Information about this saver
*/
BeakerSaver.prototype.info = {
name: "beaker",
priority: 3000,
capabilities: ["save", "autosave"]
};
/*
Static method that returns true if this saver is capable of working
*/
exports.canSave = function(wiki) {
return !!window.DatArchive && location.protocol==="dat:";
};
/*
Create an instance of this saver
*/
exports.create = function(wiki) {
return new BeakerSaver(wiki);
};
})();

View File

@ -1,64 +0,0 @@
/*\
title: $:/core/modules/savers/hyperdrive.js
type: application/javascript
module-type: saver
Saves files using the Hyperdrive Protocol (https://hypercore-protocol.org/#hyperdrive) Beaker browser beta-1.0 and later (https://beakerbrowser.com)
Compatible with beaker >= V1.0.0
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
/*
Set up the saver
*/
var HyperdriveSaver = function(wiki) {
this.wiki = wiki;
};
HyperdriveSaver.prototype.save = function(text,method,callback) {
var dat = beaker.hyperdrive.drive("" + window.location),
pathname = ("" + window.location.pathname).split("#")[0];
dat.stat(pathname).then(function(value) {
if(value.isDirectory()) {
pathname = pathname + "/index.html";
}
dat.writeFile(pathname,text,"utf8").then(function(value) {
callback(null);
},function(reason) {
callback("Hyperdrive Saver Write Error: " + reason);
});
},function(reason) {
callback("Hyperdrive Saver Stat Error: " + reason);
});
return true;
};
/*
Information about this saver
*/
HyperdriveSaver.prototype.info = {
name: "beaker-1.x",
priority: 3000,
capabilities: ["save", "autosave"]
};
/*
Static method that returns true if this saver is capable of working
*/
exports.canSave = function(wiki) {
return !!window.beaker && !!beaker.hyperdrive && location.protocol==="hyper:";
};
/*
Create an instance of this saver
*/
exports.create = function(wiki) {
return new HyperdriveSaver(wiki);
};
})();

View File

@ -228,7 +228,7 @@ exports.generateTiddlerFileInfo = function(tiddler,options) {
hasUnsafeFields = hasUnsafeFields || /[\x00-\x1F]/mg.test(value);
hasUnsafeFields = hasUnsafeFields || ($tw.utils.trim(value) !== value);
}
hasUnsafeFields = hasUnsafeFields || /:/mg.test(fieldName);
hasUnsafeFields = hasUnsafeFields || /:|#/mg.test(fieldName);
});
// Check for field values
if(hasUnsafeFields) {
@ -393,7 +393,7 @@ exports.generateTiddlerFilepath = function(title,options) {
} while(fs.existsSync(fullPath));
// If the last write failed with an error, or if path does not start with:
// the resolved options.directory, the resolved wikiPath directory, the wikiTiddlersPath directory,
// or the 'originalpath' directory, then encodeURIComponent() and resolve to tiddler directory.
// or the 'originalpath' directory, then $tw.utils.encodeURIComponentExtended() and resolve to tiddler directory.
var writePath = $tw.hooks.invokeHook("th-make-tiddler-path",fullPath,fullPath),
encode = (options.fileInfo || {writeError: false}).writeError == true;
if(!encode) {
@ -403,7 +403,7 @@ exports.generateTiddlerFilepath = function(title,options) {
writePath.indexOf(path.resolve($tw.boot.wikiTiddlersPath,originalpath)) == 0 );
}
if(encode) {
writePath = path.resolve(directory,encodeURIComponent(fullPath));
writePath = path.resolve(directory,$tw.utils.encodeURIComponentExtended(fullPath));
}
// Return the full path to the file
return writePath;

View File

@ -685,6 +685,16 @@ exports.escapeRegExp = function(s) {
return s.replace(/[\-\/\\\^\$\*\+\?\.\(\)\|\[\]\{\}]/g, '\\$&');
};
/*
Extended version of encodeURIComponent that encodes additional characters including
those that are illegal within filepaths on various platforms including Windows
*/
exports.encodeURIComponentExtended = function(s) {
return encodeURIComponent(s).replace(/[!'()*]/g,function(c) {
return "%" + c.charCodeAt(0).toString(16).toUpperCase();
});
};
// Checks whether a link target is external, i.e. not a tiddler title
exports.isLinkExternal = function(to) {
var externalRegExp = /^(?:file|http|https|mailto|ftp|irc|news|obsidian|data|skype):[^\s<>{}\[\]`|"\\^]+(?:\/|\b)/i;

View File

@ -232,10 +232,32 @@ DropZoneWidget.prototype.handleDropEvent = function(event) {
};
DropZoneWidget.prototype.handlePasteEvent = function(event) {
var self = this,
readFileCallback = function(tiddlerFieldsArray) {
var self = this;
var readFileCallback = function(tiddlerFieldsArray) {
self.readFileCallback(tiddlerFieldsArray);
};
var getItem = function(type) {
type = type || "text/plain";
return function(str) {
// Use the deserializer specified if any
if(self.dropzoneDeserializer) {
tiddlerFields = self.wiki.deserializeTiddlers(null,str,{title: self.wiki.generateNewTitle("Untitled " + type)},{deserializer:self.dropzoneDeserializer});
if(tiddlerFields && tiddlerFields.length) {
readFileCallback(tiddlerFields);
}
} else {
tiddlerFields = {
title: self.wiki.generateNewTitle("Untitled " + type),
text: str,
type: type
};
if($tw.log.IMPORT) {
console.log("Importing string '" + str + "', type: '" + type + "'");
}
readFileCallback([tiddlerFields]);
}
}
};
// Let the browser handle it if we're in a textarea or input box
if(["TEXTAREA","INPUT"].indexOf(event.target.tagName) == -1 && !event.target.isContentEditable) {
var self = this,
@ -251,27 +273,10 @@ DropZoneWidget.prototype.handlePasteEvent = function(event) {
});
} else if(item.kind === "string") {
// Create tiddlers from string items
var tiddlerFields,
type = item.type;
item.getAsString(function(str) {
// Use the deserializer specified if any
if(self.dropzoneDeserializer) {
tiddlerFields = self.wiki.deserializeTiddlers(null,str,{title: self.wiki.generateNewTitle("Untitled")},{deserializer:self.dropzoneDeserializer});
if(tiddlerFields && tiddlerFields.length) {
readFileCallback(tiddlerFields);
}
} else {
tiddlerFields = {
title: self.wiki.generateNewTitle("Untitled"),
text: str,
type: type
};
if($tw.log.IMPORT) {
console.log("Importing string '" + str + "', type: '" + type + "'");
}
readFileCallback([tiddlerFields]);
}
});
var tiddlerFields;
// It's important to give getAsString a closure with the right type
// So it can be added to the import queue
item.getAsString(getItem(item.type));
}
}
// Tell the browser that we've handled the paste

View File

@ -97,8 +97,8 @@ LinkWidget.prototype.renderLink = function(parent,nextSibling) {
// Expand the tv-wikilink-template variable to construct the href
var wikiLinkTemplateMacro = this.getVariable("tv-wikilink-template"),
wikiLinkTemplate = wikiLinkTemplateMacro ? wikiLinkTemplateMacro.trim() : "#$uri_encoded$";
wikiLinkText = $tw.utils.replaceString(wikiLinkTemplate,"$uri_encoded$",encodeURIComponent(this.to));
wikiLinkText = $tw.utils.replaceString(wikiLinkText,"$uri_doubleencoded$",encodeURIComponent(encodeURIComponent(this.to)));
wikiLinkText = $tw.utils.replaceString(wikiLinkTemplate,"$uri_encoded$",$tw.utils.encodeURIComponentExtended(this.to));
wikiLinkText = $tw.utils.replaceString(wikiLinkText,"$uri_doubleencoded$",$tw.utils.encodeURIComponentExtended($tw.utils.encodeURIComponentExtended(this.to)));
}
// Override with the value of tv-get-export-link if defined
wikiLinkText = this.getVariable("tv-get-export-link",{params: [{name: "to",value: this.to}],defaultValue: wikiLinkText});

View File

@ -82,7 +82,7 @@ MessageCatcherWidget.prototype.render = function(parent,nextSibling) {
}
});
// Render children
this.renderChildren(parent,null);
this.renderChildren(parent,nextSibling);
};
/*

View File

@ -227,10 +227,7 @@ NavigatorWidget.prototype.handleDeleteTiddlerEvent = function(event) {
originalTitle = tiddler ? tiddler.fields["draft.of"] : "",
originalTiddler = originalTitle ? this.wiki.getTiddler(originalTitle) : undefined,
confirmationTitle,
win = event.event && event.event.view ? event.event.view : window;
if(!tiddler) {
return false;
}
win = event.event && event.event.view ? event.event.view : window;
// Check if the tiddler we're deleting is in draft mode
if(originalTitle) {
// If so, we'll prompt for confirmation referencing the original tiddler
@ -240,7 +237,7 @@ NavigatorWidget.prototype.handleDeleteTiddlerEvent = function(event) {
confirmationTitle = title;
}
// Seek confirmation
if((this.wiki.getTiddler(originalTitle) || (tiddler.fields.text || "") !== "") && !win.confirm($tw.language.getString(
if(((originalTitle && this.wiki.getTiddler(originalTitle)) || (tiddler && ((tiddler.fields.text || "") !== ""))) && !win.confirm($tw.language.getString(
"ConfirmDeleteTiddler",
{variables:
{title: confirmationTitle}
@ -257,8 +254,10 @@ NavigatorWidget.prototype.handleDeleteTiddlerEvent = function(event) {
this.removeTitleFromStory(storyList,originalTitle);
}
// Invoke the hook function and delete this tiddler
$tw.hooks.invokeHook("th-deleting-tiddler",tiddler);
this.wiki.deleteTiddler(title);
if(tiddler) {
$tw.hooks.invokeHook("th-deleting-tiddler",tiddler);
this.wiki.deleteTiddler(title);
}
// Remove the closed tiddler from the story
this.removeTitleFromStory(storyList,title);
this.saveStoryList(storyList);

View File

@ -168,11 +168,11 @@ ViewWidget.prototype.getValueAsHtmlTextEncoded = function() {
};
ViewWidget.prototype.getValueAsUrlEncoded = function() {
return encodeURIComponent(this.getValueAsText());
return $tw.utils.encodeURIComponentExtended(this.getValueAsText());
};
ViewWidget.prototype.getValueAsDoubleUrlEncoded = function() {
return encodeURIComponent(encodeURIComponent(this.getValueAsText()));
return $tw.utils.encodeURIComponentExtended($tw.utils.encodeURIComponentExtended(this.getValueAsText()));
};
ViewWidget.prototype.getValueAsDate = function(format) {

View File

@ -1,5 +1,6 @@
title: $:/core/save/all-external-js
\whitespace trim
\import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]
\define saveTiddlerFilter()
[is[tiddler]] -[prefix[$:/state/popup/]] -[prefix[$:/temp/]] -[prefix[$:/HistoryList]] -[status[pending]plugin-type[import]] -[[$:/core]] -[[$:/boot/boot.css]] -[type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] +[sort[title]] $(publishFilter)$

View File

@ -1,5 +1,6 @@
title: $:/core/save/offline-external-js
\whitespace trim
\import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]
\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]] -[type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] +[sort[title]] $(publishFilter)$

View File

@ -0,0 +1,3 @@
title: $:/core/templates/tiddlywiki.js/load-tiddler
_load(window,<$macrocall $name="jsontiddler" $output="text/raw"/>);

View File

@ -1,15 +1,48 @@
title: $:/core/templates/tiddlywiki5.js
\rules only filteredtranscludeinline transcludeinline codeinline
/*
{{ $:/core/copyright.txt ||$:/core/templates/plain-text-tiddler}}
`*/
`<!--~~ Library modules ~~-->
{{{ [is[system]type[application/javascript]library[yes]] ||$:/core/templates/plain-text-tiddler}}}
<!--~~ Boot prefix ~~-->
{{ $:/boot/bootprefix.js ||$:/core/templates/plain-text-tiddler}}
<!--~~ Core plugin ~~-->
{{$:/core/templates/tiddlywiki5.js/tiddlers}}
<!--~~ Boot kernel ~~-->
{{ $:/boot/boot.js ||$:/core/templates/plain-text-tiddler}}
`/*
`{{ $:/core/copyright.txt ||$:/core/templates/plain-text-tiddler}}`
*/
$tw = (typeof $tw === 'undefined') ? Object.create(null) : $tw;
$tw.preloadTiddlers = $tw.preloadTiddlers || [];
_load = function(window,tiddler) {
"use strict";
var f;
$tw.preloadTiddlers.push(tiddler);
if(tiddler.library === "yes") {
var module = { exports:{} };
var moduleName = function moduleName(path) {
var word = path.split("/").pop();
word = word.substring(0,word.indexOf(".")) || word;
return word;
}
f = new Function("module",tiddler.text);
f(module);
window[moduleName(tiddler.title)] = module.exports;
} else {
f = new Function("window",tiddler.text);
f(window);
}
}
/* ~~ Library modules ~~ */
`{{{ [is[system]type[application/javascript]library[yes]] ||$:/core/templates/tiddlywiki.js/load-tiddler}}}`
/* ~~ Boot kernel prologue ~~ */
`{{ $:/boot/bootprefix.js ||$:/core/templates/tiddlywiki.js/load-tiddler}}`
/* ~~ Core tiddlers ~~ */
`{{$:/core/templates/tiddlywiki5.js/tiddlers}}`
/* ~~ Boot kernel ~~ */
`{{ $:/boot/boot.js ||$:/core/templates/tiddlywiki.js/load-tiddler}}`

View File

@ -1,48 +1,50 @@
title: $:/core/templates/tiddlywiki5-external-js.html
\rules only filteredtranscludeinline transcludeinline
<!doctype html>
{{$:/core/templates/MOTW.html}}<html lang="{{{ [{$:/language}get[name]] }}}">
<$set name="saveTiddlerAndShadowsFilter" filter="[subfilter<saveTiddlerFilter>] [subfilter<saveTiddlerFilter>plugintiddlers[]]">
`<!doctype html>
`{{$:/core/templates/MOTW.html}}`<html lang="`<$text text={{{ [{$:/language}get[name]] }}}/>`">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<!--~~ Raw markup for the top of the head section ~~-->
{{{ [all[shadows+tiddlers]tag[$:/tags/RawMarkupWikified/TopHead]] ||$:/core/templates/raw-static-tiddler}}}
`{{{ [enlist<saveTiddlerAndShadowsFilter>tag[$:/tags/RawMarkupWikified/TopHead]] ||$:/core/templates/raw-static-tiddler}}}`
<meta http-equiv="X-UA-Compatible" content="IE=Edge"/>
<meta name="application-name" content="TiddlyWiki" />
<meta name="generator" content="TiddlyWiki" />
<meta name="tiddlywiki-version" content="{{$:/core/templates/version}}" />
<meta name="tiddlywiki-version" content="`{{$:/core/templates/version}}`" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
<meta name="mobile-web-app-capable" content="yes"/>
<meta name="format-detection" content="telephone=no" />
<meta name="copyright" content="{{$:/core/copyright.txt}}" />
<meta name="copyright" content="`{{$:/core/copyright.txt}}`" />
<link id="faviconLink" rel="shortcut icon" href="favicon.ico">
<title>{{$:/core/wiki/title}}</title>
<title>`{{$:/core/wiki/title}}`</title>
<!--~~ This is a Tiddlywiki file. The points of interest in the file are marked with this pattern ~~-->
<!--~~ Raw markup ~~-->
{{{ [all[shadows+tiddlers]tag[$:/core/wiki/rawmarkup]] [all[shadows+tiddlers]tag[$:/tags/RawMarkup]] ||$:/core/templates/plain-text-tiddler}}}
{{{ [all[shadows+tiddlers]tag[$:/tags/RawMarkupWikified]] ||$:/core/templates/raw-static-tiddler}}}
`{{{ [enlist<saveTiddlerAndShadowsFilter>tag[$:/core/wiki/rawmarkup]] ||$:/core/templates/plain-text-tiddler}}}`
`{{{ [enlist<saveTiddlerAndShadowsFilter>tag[$:/tags/RawMarkup]] ||$:/core/templates/plain-text-tiddler}}}`
`{{{ [enlist<saveTiddlerAndShadowsFilter>tag[$:/tags/RawMarkupWikified]] ||$:/core/templates/raw-static-tiddler}}}`
</head>
<body class="tc-body">
<!--~~ Raw markup for the top of the body section ~~-->
{{{ [all[shadows+tiddlers]tag[$:/tags/RawMarkupWikified/TopBody]] ||$:/core/templates/raw-static-tiddler}}}
`{{{ [enlist<saveTiddlerAndShadowsFilter>tag[$:/tags/RawMarkupWikified/TopBody]] ||$:/core/templates/raw-static-tiddler}}}`
<!--~~ Static styles ~~-->
<div id="styleArea">
{{$:/boot/boot.css||$:/core/templates/css-tiddler}}
`{{$:/boot/boot.css||$:/core/templates/css-tiddler}}`
</div>
<!--~~ Static content for Google and browsers without JavaScript ~~-->
<noscript>
<div id="splashArea">
{{$:/core/templates/static.area}}
`{{$:/core/templates/static.area}}`
</div>
</noscript>
<!--~~ Ordinary tiddlers ~~-->
{{$:/core/templates/store.area.template.html}}
`{{$:/core/templates/store.area.template.html}}`
<!--~~ Raw markup for the bottom of the body section ~~-->
{{{ [all[shadows+tiddlers]tag[$:/tags/RawMarkupWikified/BottomBody]] ||$:/core/templates/raw-static-tiddler}}}
`{{{ [enlist<saveTiddlerAndShadowsFilter>tag[$:/tags/RawMarkupWikified/BottomBody]] ||$:/core/templates/raw-static-tiddler}}}`
<!--~~ Load external JavaScripts ~~-->
<script src="`{{{ [<coreURL>] }}}`" onerror="alert('Error: Cannot load `{{{ [<coreURL>] }}}`');"></script>
</body>
<!--~~ Load external JS ~~-->
<script src="{{{ [<coreURL>] }}}" onerror="alert('Error: Cannot load {{{ [<coreURL>] }}}');"></script>
</html>
</html>`
</$set>

View File

@ -12,7 +12,7 @@ field="text"
checked="enable"
unchecked="disable"
default="enable">
<<rule>>
<span class="tc-small-gap-left"><<rule>></span>
</$checkbox>
\end

View File

@ -0,0 +1,18 @@
title: $:/core/ui/DownloadFullWiki
\whitespace trim
\rules except wikilink
To download the standard single-file version of your wiki:
<$wikify name="site-title" text={{$:/config/SaveWikiButton/Filename}}>
<$let publishFilter="""-[[$:/config/SaveWikiButton/Template]] -[[$:/plugins/tiddlywiki/filesystem]] -[[$:/plugins/tiddlywiki/tiddlyweb]]""">
<$button tooltip="Download fully standalone wiki" aria-label="download full wiki" class="tc-btn-big-green">
<$action-sendmessage $message="tm-download-file" $param="$:/core/save/all" publishFilter=<<publishFilter>> filename=<<site-title>>/>
{{$:/core/images/download-button}}
<span class="tc-tiny-gap-left">
Download full wiki
</span>
</$button>
</$let>
</$wikify>

View File

@ -3,16 +3,23 @@ tags: $:/tags/EditToolbar
caption: {{$:/core/images/done-button}} {{$:/language/Buttons/Save/Caption}}
description: {{$:/language/Buttons/Save/Hint}}
\whitespace trim
\define save-tiddler-button()
\whitespace trim
<$fieldmangler><$button tooltip={{$:/language/Buttons/Save/Hint}} aria-label={{$:/language/Buttons/Save/Caption}} class=<<tv-config-toolbar-class>>>
<<save-tiddler-actions>>
<$list filter="[<tv-config-toolbar-icons>match[yes]]">
{{$:/core/images/done-button}}
</$list>
<$list filter="[<tv-config-toolbar-text>match[yes]]">
<span class="tc-btn-text"><$text text={{$:/language/Buttons/Save/Caption}}/></span>
</$list>
</$button></$fieldmangler>
<$fieldmangler>
<$button
tooltip={{$:/language/Buttons/Save/Hint}}
aria-label={{$:/language/Buttons/Save/Caption}}
class=<<tv-config-toolbar-class>>
>
<<save-tiddler-actions>>
<$list filter="[<tv-config-toolbar-icons>match[yes]]">
{{$:/core/images/done-button}}
</$list>
<$list filter="[<tv-config-toolbar-text>match[yes]]">
<span class="tc-btn-text"><$text text={{$:/language/Buttons/Save/Caption}}/></span>
</$list>
</$button>
</$fieldmangler>
\end
<<save-tiddler-button>>

View File

@ -1,11 +1,6 @@
title: $:/core/ui/ExportTiddlyWikiCore
\define jsFileName() tiddlywikicore-$(version)$.js
\define noExportMsg()
It appears that you have a wiki with an external ~TiddlyWiki core. The export action cannot be performed.
<p>You will need to view the page source in your browser. Then go to the very bottom the the source, find the last `<script>`
element, and right-click its `src` URI. Save the link as ''$(jsFileName)$''</p>
\end
\rules except wikilink
\whitespace trim
@ -17,16 +12,11 @@ Export the TiddlyWiki core JavaScript code for running with external JavaScript:
tooltip="Export the TiddlyWiki core code for running with external JavaScript"
aria-label="export TiddlyWiki core"
class="tc-btn-big-green">
<$list
filter="[[$:/boot/boot.js]is[missing]]"
variable="ignore"
emptyMessage="<$action-sendmessage $message='tm-download-file' $param='$:/core/templates/tiddlywiki5.js' filename=<<jsFileName>>/>" >
<$action-setfield $tiddler=<<qualify "$:/temp/alert">> text=<<noExportMsg>> subtitle="Export ~TiddllyWiki Core"/>
<$action-sendmessage $message="tm-modal" $param=<<qualify "$:/temp/alert">>/>
</$list>
<$action-sendmessage $message='tm-download-file' $param='$:/core/templates/tiddlywiki5.js' filename=<<jsFileName>>/>
{{$:/core/images/download-button}}
&#32;
<span class="tc-tiny-gap-left">
Download TiddlyWiki core
</span>
</$button>
[[Further information|https://tiddlywiki.com/#Using%20the%20external%20JavaScript%20template]]

View File

@ -13,13 +13,13 @@ caption: {{$:/language/ControlPanel/LayoutSwitcher/Caption}}
<$set name="cls" filter="[all[current]field:title{$:/layout}]" value="tc-chooser-item tc-chosen" emptyValue="tc-chooser-item">
<div class=<<cls>>>
<$link to={{!!title}}>
''<$transclude field="name"/>''&#32;-&#32;<$transclude field="description"/>
''<$transclude tiddler={{{ [<currentTiddler>get[icon]] }}}/><$transclude field="name"/>''&#32;-&#32;<$transclude field="description"/>
</$link></div></$set>
""">
<$set name="cls" filter="[all[current]field:title[$:/core/ui/PageTemplate]]" value="tc-chooser-item tc-chosen" emptyValue="tc-chooser-item">
<div class=<<cls>>>
<$link to={{!!title}}>
''<$transclude field="name"/>''&#32;-&#32;<$transclude field="description"/>
''<$transclude tiddler={{{ [<currentTiddler>get[icon]] }}}/><$transclude field="name"/>''&#32;-&#32;<$transclude field="description"/>
</$link>
</div>
</$set>

View File

@ -2,26 +2,17 @@ title: $:/core/ui/MoreSideBar/Tags
tags: $:/tags/MoreSideBar
caption: {{$:/language/SideBar/Tags/Caption}}
<$set name="tv-config-toolbar-icons" value="yes">
<$set name="tv-config-toolbar-text" value="yes">
<$set name="tv-config-toolbar-class" value="">
{{$:/core/ui/Buttons/tag-manager}}
</$set>
</$set>
</$set>
\whitespace trim
<$let tv-config-toolbar-icons="yes" tv-config-toolbar-text="yes" tv-config-toolbar-class="">
<div class="tc-tiny-v-gap-bottom">
{{$:/core/ui/Buttons/tag-manager}}
</div>
</$let>
<$list filter={{$:/core/Filters/AllTags!!filter}}>
<$transclude tiddler="$:/core/ui/TagTemplate"/>
<div class="tc-tiny-v-gap-bottom">
<$transclude tiddler="$:/core/ui/TagTemplate"/>
</div>
</$list>
<hr class="tc-untagged-separator">
{{$:/core/ui/UntaggedTemplate}}

View File

@ -1,6 +1,7 @@
title: $:/core/ui/PageTemplate
name: {{$:/language/PageTemplate/Name}}
description: {{$:/language/PageTemplate/Description}}
icon: $:/core/images/layout-button
\whitespace trim
\import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]

View File

@ -3,10 +3,8 @@ title: $:/core/ui/UntaggedTemplate
\define lingo-base() $:/language/SideBar/
\whitespace trim
<$button popup=<<qualify "$:/state/popup/tag">> class="tc-btn-invisible tc-untagged-label tc-tag-label">
<<lingo Tags/Untagged/Caption>>
<<lingo Tags/Untagged/Caption>>
</$button>
<$reveal state=<<qualify "$:/state/popup/tag">> type="popup" position="below">
<div class="tc-drop-down">
<$list filter="[untagged[]!is[system]] -[tags[]] +[sort[title]]" template="$:/core/ui/ListItemTemplate"/>
</div>
<$reveal class="tc-drop-down" tag="div" state=<<qualify "$:/state/popup/tag">> type="popup" position="below">
<$list filter="[untagged[]!is[system]] -[tags[]] +[sort[title]]" template="$:/core/ui/ListItemTemplate"/>
</$reveal>

View File

@ -4,76 +4,85 @@ tags: $:/tags/Macro
\define change-input-tab(stateTitle,tag,beforeafter,defaultState,actions)
\whitespace trim
<$set name="tabsList" filter="[all[shadows+tiddlers]tag<__tag__>!has[draft.of]]">
<$let
currentState={{{ [<__stateTitle__>!is[missing]get[text]] ~[<__defaultState__>] }}}
firstTab={{{ [enlist<tabsList>nth[1]] }}}
lastTab={{{ [enlist<tabsList>last[]] }}}
nextTab={{{ [all[shadows+tiddlers]tag<__tag__>!has[draft.of]$beforeafter$<currentState>] ~[[$beforeafter$]removeprefix[after]suffix[]addprefix<firstTab>] ~[[$beforeafter$]removeprefix[before]suffix[]addprefix<lastTab>] }}}>
<$action-setfield $tiddler=<<__stateTitle__>> text=<<nextTab>>/>
$actions$
</$let>
<$let
currentState={{{ [<__stateTitle__>!is[missing]get[text]] ~[<__defaultState__>] }}}
firstTab={{{ [enlist<tabsList>nth[1]] }}}
lastTab={{{ [enlist<tabsList>last[]] }}}
nextTab={{{ [all[shadows+tiddlers]tag<__tag__>!has[draft.of]$beforeafter$<currentState>] ~[[$beforeafter$]removeprefix[after]suffix[]addprefix<firstTab>] ~[[$beforeafter$]removeprefix[before]suffix[]addprefix<lastTab>] }}}
>
<$action-setfield $tiddler=<<__stateTitle__>> text=<<nextTab>>/>
$actions$
</$let>
</$set>
\end
\define keyboard-input-actions()
\whitespace trim
<$list filter="[<__index__>match[]]">
<$action-setfield $tiddler=<<__storeTitle__>> text={{{ [<__tiddler__>get<__field__>] }}}/>
<$action-setfield $tiddler=<<__storeTitle__>> text={{{ [<__tiddler__>get<__field__>] }}}/>
</$list>
<$list filter="[<__index__>!match[]]">
<$action-setfield $tiddler=<<__storeTitle__>> text={{{ [<__tiddler__>getindex<__index__>] }}}/>
<$action-setfield $tiddler=<<__storeTitle__>> text={{{ [<__tiddler__>getindex<__index__>] }}}/>
</$list>
\end
\define input-next-actions-inner()
\whitespace trim
<$list filter="[<nextItem>minlength[1]]" variable="ignore">
<$action-setfield $tiddler=<<__selectionStateTitle__>> text=<<nextItem>>/>
<$list filter="[<__index__>match[]]">
<$action-setfield $tiddler=<<__tiddler__>> $field=<<__field__>> $value={{{ [<nextItem>] +[splitregexp[(?:.(?!-))+$]] }}}/>
</$list>
<$list filter="[<__index__>!match[]]">
<$action-setfield $tiddler=<<__tiddler__>> $index=<<__index__>> $value={{{ [<nextItem>] +[splitregexp[(?:.(?!-))+$]] }}}/>
</$list>
<$action-setfield $tiddler=<<__refreshTitle__>> text="yes"/>
<$action-setfield $tiddler=<<__selectionStateTitle__>> text=<<nextItem>>/>
<$list filter="[<__index__>match[]]">
<$action-setfield $tiddler=<<__tiddler__>> $field=<<__field__>> $value={{{ [<nextItem>] +[splitregexp[(?:.(?!-))+$]] }}}/>
</$list>
<$list filter="[<__index__>!match[]]">
<$action-setfield $tiddler=<<__tiddler__>> $index=<<__index__>> $value={{{ [<nextItem>] +[splitregexp[(?:.(?!-))+$]] }}}/>
</$list>
<$action-setfield $tiddler=<<__refreshTitle__>> text="yes"/>
</$list>
\end
\define input-next-actions(afterOrBefore:"after",reverse:"")
\whitespace trim
<$list filter="[<__storeTitle__>get[text]minlength<__filterMinLength__>] [<__filterMinLength__>match[0]] +[limit[1]]" variable="ignore">
<$let
userInput={{{ [<__storeTitle__>get[text]] }}}
selectedItem={{{ [<__selectionStateTitle__>get[text]] }}}
configTiddler={{{ [subfilter<__configTiddlerFilter__>] }}}
primaryListFilter={{{ [<configTiddler>get<__firstSearchFilterField__>] }}}
secondaryListFilter={{{ [<configTiddler>get<__secondSearchFilterField__>] }}}>
<$set name="filteredList" filter="[subfilter<primaryListFilter>addsuffix[-primaryList]] =[subfilter<secondaryListFilter>addsuffix[-secondaryList]]">
<$let
nextItem={{{ [enlist<filteredList>$afterOrBefore$<selectedItem>] ~[enlist<filteredList>$reverse$nth[1]] }}}
firstItem={{{ [enlist<filteredList>nth[1]] }}}
lastItem={{{ [enlist<filteredList>last[]] }}}>
<$list filter="[<selectedItem>match<firstItem>!match<lastItem>]" variable="ignore">
<$set name="nextItem" value={{{ [[$afterOrBefore$]match[before]then<userInput>addsuffix[-userInput]] ~[<nextItem>] }}}>
<<input-next-actions-inner>>
</$set>
</$list>
<$list filter="[<selectedItem>match<lastItem>!match<firstItem>]" variable="ignore">
<$set name="nextItem" value={{{ [[$afterOrBefore$]match[after]then<userInput>addsuffix[-userInput]] ~[<nextItem>] }}}>
<<input-next-actions-inner>>
</$set>
</$list>
<$list filter="[<selectedItem>match<firstItem>match<lastItem>]" variable="ignore">
<$set name="nextItem" value={{{ [<userInput>addsuffix[-userInput]] }}}>
<<input-next-actions-inner>>
</$set>
</$list>
<$list filter="[<selectedItem>!match<firstItem>!match<lastItem>]" variable="ignore">
<<input-next-actions-inner>>
</$list>
</$let>
</$set>
</$let>
<$list
filter="[<__storeTitle__>get[text]minlength<__filterMinLength__>] [<__filterMinLength__>match[0]] +[limit[1]]"
variable="ignore"
>
<$let
userInput={{{ [<__storeTitle__>get[text]] }}}
selectedItem={{{ [<__selectionStateTitle__>get[text]] }}}
configTiddler={{{ [subfilter<__configTiddlerFilter__>] }}}
primaryListFilter={{{ [<configTiddler>get<__firstSearchFilterField__>] }}}
secondaryListFilter={{{ [<configTiddler>get<__secondSearchFilterField__>] }}}
>
<$set
name="filteredList"
filter="[subfilter<primaryListFilter>addsuffix[-primaryList]] =[subfilter<secondaryListFilter>addsuffix[-secondaryList]]"
>
<$let
nextItem={{{ [enlist<filteredList>$afterOrBefore$<selectedItem>] ~[enlist<filteredList>$reverse$nth[1]] }}}
firstItem={{{ [enlist<filteredList>nth[1]] }}}
lastItem={{{ [enlist<filteredList>last[]] }}}
>
<$list filter="[<selectedItem>match<firstItem>!match<lastItem>]" variable="ignore">
<$set name="nextItem" value={{{ [[$afterOrBefore$]match[before]then<userInput>addsuffix[-userInput]] ~[<nextItem>] }}}>
<<input-next-actions-inner>>
</$set>
</$list>
<$list filter="[<selectedItem>match<lastItem>!match<firstItem>]" variable="ignore">
<$set name="nextItem" value={{{ [[$afterOrBefore$]match[after]then<userInput>addsuffix[-userInput]] ~[<nextItem>] }}}>
<<input-next-actions-inner>>
</$set>
</$list>
<$list filter="[<selectedItem>match<firstItem>match<lastItem>]" variable="ignore">
<$set name="nextItem" value={{{ [<userInput>addsuffix[-userInput]] }}}>
<<input-next-actions-inner>>
</$set>
</$list>
<$list filter="[<selectedItem>!match<firstItem>!match<lastItem>]" variable="ignore">
<<input-next-actions-inner>>
</$list>
</$let>
</$set>
</$let>
</$list>
\end
@ -84,12 +93,14 @@ $actions$
<$keyboard key="((input-up))" actions=<<input-next-actions "before" "reverse[]">>>
<$keyboard key="((input-down))" actions=<<input-next-actions>>>
<$keyboard key="((input-cancel))" actions=<<__inputCancelActions__>>>
<$edit-text tiddler=<<__tiddler__>> field=<<__field__>> index=<<__index__>>
inputActions=<<keyboard-input-actions>> tag=<<__tag__>> class=<<__class__>>
placeholder=<<__placeholder__>> default=<<__default__>> focusPopup=<<__focusPopup__>>
focus=<<__focus__>> type=<<__type__>> rows=<<__rows__>> minHeight=<<__minHeight__>>
tabindex=<<__tabindex__>> size=<<__size__>> autoHeight=<<__autoHeight__>>
refreshTitle=<<__refreshTitle__>> cancelPopups=<<__cancelPopups__>>/>
<$edit-text
tiddler=<<__tiddler__>> field=<<__field__>> index=<<__index__>>
inputActions=<<keyboard-input-actions>> tag=<<__tag__>> class=<<__class__>>
placeholder=<<__placeholder__>> default=<<__default__>> focusPopup=<<__focusPopup__>>
focus=<<__focus__>> type=<<__type__>> rows=<<__rows__>> minHeight=<<__minHeight__>>
tabindex=<<__tabindex__>> size=<<__size__>> autoHeight=<<__autoHeight__>>
refreshTitle=<<__refreshTitle__>> cancelPopups=<<__cancelPopups__>>
/>
</$keyboard>
</$keyboard>
</$keyboard>

View File

@ -26,7 +26,7 @@ tags: $:/tags/Macro
\whitespace trim
<span class="tc-links-draggable-list">
<$vars targetTiddler="""$tiddler$""" targetField="""$field$""">
<$type$ class="$class$">
<$genesis $type=<<__type__>> class="$class$">
<$list filter="[list[$tiddler$!!$field$]]" emptyMessage=<<__emptyMessage__>>>
<$droppable actions=<<list-links-draggable-drop-actions>> tag="""$subtype$""" enable=<<tv-enable-drag-and-drop>>>
<div class="tc-droppable-placeholder"/>
@ -51,7 +51,7 @@ tags: $:/tags/Macro
<div style="height:0.5em;"/>
</$droppable>
</$tiddler>
</$type$>
</$genesis>
</$vars>
</span>
\end
@ -84,24 +84,24 @@ tags: $:/tags/Macro
<span class="tc-tagged-draggable-list">
<$set name="tag" value=<<__tag__>>>
<$list filter="[<__tag__>tagging[]$subFilter$]" emptyMessage=<<__emptyMessage__>> storyview=<<__storyview__>>>
<$elementTag$ class="tc-menu-list-item">
<$genesis $type=<<__elementTag__>> class="tc-menu-list-item">
<$droppable actions="""<$macrocall $name="list-tagged-draggable-drop-actions" tag=<<__tag__>>/>""" enable=<<tv-enable-drag-and-drop>>>
<$elementTag$ class="tc-droppable-placeholder"/>
<$elementTag$>
<$genesis $type=<<__elementTag__>> class="tc-droppable-placeholder"/>
<$genesis $type=<<__elementTag__>>>
<$transclude tiddler="""$itemTemplate$""">
<$link to={{!!title}}>
<$view field="title"/>
</$link>
</$transclude>
</$elementTag$>
</$genesis>
</$droppable>
</$elementTag$>
</$genesis>
</$list>
<$tiddler tiddler="">
<$droppable actions="""<$macrocall $name="list-tagged-draggable-drop-actions" tag=<<__tag__>>/>""" enable=<<tv-enable-drag-and-drop>>>
<$elementTag$ class="tc-droppable-placeholder"/>
<$elementTag$ style="height:0.5em;">
</$elementTag$>
<$genesis $type=<<__elementTag__>> class="tc-droppable-placeholder"/>
<$genesis $type=<<__elementTag__>> style="height:0.5em;">
</$genesis>
</$droppable>
</$tiddler>
</$set>

View File

@ -10,10 +10,14 @@ second-search-filter: [tags[]is[system]search:title<userInput>sort[]]
\define add-tag-actions(actions,tagField:"tags")
\whitespace trim
<$set name="tag" value={{{ [<__tiddler__>get[text]] }}}>
<$list filter="[<saveTiddler>!contains:$tagField$<tag>!match[]]" variable="ignore" emptyMessage="<$action-listops $tiddler=<<saveTiddler>> $field=<<__tagField__>> $subfilter='-[<tag>]'/>">
<$action-listops $tiddler=<<saveTiddler>> $field=<<__tagField__>> $subfilter="[<tag>trim[]]"/>
$actions$
</$list>
<$list
filter="[<saveTiddler>!contains:$tagField$<tag>!match[]]"
variable="ignore"
emptyMessage="<$action-listops $tiddler=<<saveTiddler>> $field=<<__tagField__>> $subfilter='-[<tag>]'/>"
>
<$action-listops $tiddler=<<saveTiddler>> $field=<<__tagField__>> $subfilter="[<tag>trim[]]"/>
$actions$
</$list>
</$set>
<<delete-tag-state-tiddlers>>
<$action-setfield $tiddler=<<refreshTitle>> text="yes"/>
@ -21,80 +25,153 @@ $actions$
\define clear-tags-actions-inner()
\whitespace trim
<$list filter="[<storeTitle>has[text]] [<newTagNameTiddler>has[text]]" variable="ignore" emptyMessage="<<cancel-delete-tiddler-actions 'cancel'>>">
<<delete-tag-state-tiddlers>>
<$list
filter="[<storeTitle>has[text]] [<newTagNameTiddler>has[text]]"
variable="ignore"
emptyMessage="<<cancel-delete-tiddler-actions 'cancel'>>"
>
<<delete-tag-state-tiddlers>>
</$list>
\end
\define clear-tags-actions()
\whitespace trim
<$set name="userInput" value={{{ [<storeTitle>get[text]] }}}>
<$list filter="[<newTagNameTiddler>get[text]!match<userInput>]" emptyMessage="<<clear-tags-actions-inner>>">
<$action-setfield $tiddler=<<newTagNameTiddler>> text=<<userInput>>/><$action-setfield $tiddler=<<refreshTitle>> text="yes"/>
</$list>
<$list filter="[<newTagNameTiddler>get[text]!match<userInput>]" emptyMessage="<<clear-tags-actions-inner>>">
<$action-setfield $tiddler=<<newTagNameTiddler>> text=<<userInput>>/><$action-setfield $tiddler=<<refreshTitle>> text="yes"/>
</$list>
</$set>
\end
\define tag-picker-inner(actions,tagField:"tags")
\whitespace trim
<$vars newTagNameInputTiddlerQualified=<<qualify "$:/temp/NewTagName/input">> newTagNameSelectionTiddlerQualified=<<qualify "$:/temp/NewTagName/selected-item">> fallbackTarget={{$(palette)$##tag-background}} colourA={{$(palette)$##foreground}} colourB={{$(palette)$##background}}>
<$vars storeTitle={{{ [<newTagNameInputTiddler>!match[]] ~[<newTagNameInputTiddlerQualified>] }}} tagSelectionState={{{ [<newTagNameSelectionTiddler>!match[]] ~[<newTagNameSelectionTiddlerQualified>] }}}>
<$vars refreshTitle=<<qualify "$:/temp/NewTagName/refresh">> nonSystemTagsFilter="[tags[]!is[system]search:title<userInput>sort[]]" systemTagsFilter="[tags[]is[system]search:title<userInput>sort[]]">
<div class="tc-edit-add-tag">
<div>
<span class="tc-add-tag-name tc-small-gap-right">
<$macrocall $name="keyboard-driven-input" tiddler=<<newTagNameTiddler>> storeTitle=<<storeTitle>> refreshTitle=<<refreshTitle>>
selectionStateTitle=<<tagSelectionState>> inputAcceptActions="<$macrocall $name='add-tag-actions' actions=<<__actions__>> tagField=<<__tagField__>>/>"
inputCancelActions=<<clear-tags-actions>> tag="input" placeholder={{$:/language/EditTemplate/Tags/Add/Placeholder}}
focusPopup=<<qualify "$:/state/popup/tags-auto-complete">> class="tc-edit-texteditor tc-popup-handle" tabindex=<<tabIndex>>
focus={{{ [{$:/config/AutoFocus}match[tags]then[true]] ~[[false]] }}} filterMinLength={{$:/config/Tags/MinLength}}
cancelPopups=<<cancelPopups>> configTiddlerFilter="[[$:/core/macros/tag-picker]]"/>
</span><$button popup=<<qualify "$:/state/popup/tags-auto-complete">> class="tc-btn-invisible tc-btn-dropdown" tooltip={{$:/language/EditTemplate/Tags/Dropdown/Hint}} aria-label={{$:/language/EditTemplate/Tags/Dropdown/Caption}}>{{$:/core/images/down-arrow}}</$button><$reveal state=<<storeTitle>> type="nomatch" text=""><$button class="tc-btn-invisible tc-small-gap tc-btn-dropdown" tooltip={{$:/language/EditTemplate/Tags/ClearInput/Hint}} aria-label={{$:/language/EditTemplate/Tags/ClearInput/Caption}}>{{$:/core/images/close-button}}<<delete-tag-state-tiddlers>></$button></$reveal><span class="tc-add-tag-button tc-small-gap-left">
<$set name="tag" value={{{ [<newTagNameTiddler>get[text]] }}}>
<$button set=<<newTagNameTiddler>> setTo="" class="">
<$action-listops $tiddler=<<saveTiddler>> $field=<<__tagField__>> $subfilter="[<tag>trim[]]"/>
$actions$
<$set name="currentTiddlerCSSEscaped" value={{{ [<saveTiddler>escapecss[]] }}}>
<<delete-tag-state-tiddlers>><$action-sendmessage $message="tm-focus-selector" $param=<<get-tagpicker-focus-selector>>/>
</$set>
{{$:/language/EditTemplate/Tags/Add/Button}}
</$button>
</$set>
</span>
</div>
<div class="tc-block-dropdown-wrapper">
<$reveal state=<<qualify "$:/state/popup/tags-auto-complete">> type="nomatch" text="" default="">
<div class="tc-block-dropdown tc-block-tags-dropdown">
<$set name="userInput" value={{{ [<storeTitle>get[text]] }}}>
<$list filter="[<userInput>minlength{$:/config/Tags/MinLength}limit[1]]" emptyMessage="<div class='tc-search-results'>{{$:/language/Search/Search/TooShort}}</div>" variable="listItem">
<$list filter=<<nonSystemTagsFilter>> variable="tag">
<$list filter="[<tag>addsuffix[-primaryList]] -[<tagSelectionState>get[text]]" emptyMessage="<$vars button-classes='tc-btn-invisible tc-tag-button-selected' actions=<<__actions__>> tagField=<<__tagField__>> currentTiddler=<<tag>>>{{||$:/core/ui/TagPickerTagTemplate}}</$vars>">
<$vars button-classes="tc-btn-invisible" actions=<<__actions__>> tagField=<<__tagField__>> currentTiddler=<<tag>>>{{||$:/core/ui/TagPickerTagTemplate}}</$vars>
</$list>
</$list></$list>
<hr>
<$list filter="[<userInput>minlength{$:/config/Tags/MinLength}limit[1]]" emptyMessage="<div class='tc-search-results'>{{$:/language/Search/Search/TooShort}}</div>" variable="listItem">
<$list filter=<<systemTagsFilter>> variable="tag">
<$list filter="[<tag>addsuffix[-secondaryList]] -[<tagSelectionState>get[text]]" emptyMessage="<$vars button-classes='tc-btn-invisible tc-tag-button-selected' actions=<<__actions__>> tagField=<<__tagField__>> currentTiddler=<<tag>>>{{||$:/core/ui/TagPickerTagTemplate}}</$vars>">
<$vars button-classes="tc-btn-invisible" actions=<<__actions__>> tagField=<<__tagField__>> currentTiddler=<<tag>>>{{||$:/core/ui/TagPickerTagTemplate}}</$vars>
</$list>
</$list></$list>
</$set>
</div>
</$reveal>
</div>
</div>
</$vars>
</$vars>
<$vars
newTagNameInputTiddlerQualified=<<qualify "$:/temp/NewTagName/input">>
newTagNameSelectionTiddlerQualified=<<qualify "$:/temp/NewTagName/selected-item">>
fallbackTarget={{$(palette)$##tag-background}}
colourA={{$(palette)$##foreground}}
colourB={{$(palette)$##background}}
>
<$vars
storeTitle={{{ [<newTagNameInputTiddler>!match[]] ~[<newTagNameInputTiddlerQualified>] }}}
tagSelectionState={{{ [<newTagNameSelectionTiddler>!match[]] ~[<newTagNameSelectionTiddlerQualified>] }}}
>
<$vars
refreshTitle=<<qualify "$:/temp/NewTagName/refresh">>
nonSystemTagsFilter="[tags[]!is[system]search:title<userInput>sort[]]"
systemTagsFilter="[tags[]is[system]search:title<userInput>sort[]]"
>
<div class="tc-edit-add-tag">
<div>
<span class="tc-add-tag-name tc-small-gap-right">
<$macrocall
$name="keyboard-driven-input"
tiddler=<<newTagNameTiddler>>
storeTitle=<<storeTitle>>
refreshTitle=<<refreshTitle>>
selectionStateTitle=<<tagSelectionState>>
inputAcceptActions="<$macrocall $name='add-tag-actions' actions=<<__actions__>> tagField=<<__tagField__>>/>"
inputCancelActions=<<clear-tags-actions>>
tag="input"
placeholder={{$:/language/EditTemplate/Tags/Add/Placeholder}}
focusPopup=<<qualify "$:/state/popup/tags-auto-complete">>
class="tc-edit-texteditor tc-popup-handle"
tabindex=<<tabIndex>>
focus={{{ [{$:/config/AutoFocus}match[tags]then[true]] ~[[false]] }}}
filterMinLength={{$:/config/Tags/MinLength}}
cancelPopups=<<cancelPopups>>
configTiddlerFilter="[[$:/core/macros/tag-picker]]"
/>
</span>
<$button popup=<<qualify "$:/state/popup/tags-auto-complete">>
class="tc-btn-invisible tc-btn-dropdown"
tooltip={{$:/language/EditTemplate/Tags/Dropdown/Hint}}
aria-label={{$:/language/EditTemplate/Tags/Dropdown/Caption}}
>
{{$:/core/images/down-arrow}}
</$button>
<$reveal state=<<storeTitle>> type="nomatch" text="">
<$button class="tc-btn-invisible tc-small-gap tc-btn-dropdown"
tooltip={{$:/language/EditTemplate/Tags/ClearInput/Hint}}
aria-label={{$:/language/EditTemplate/Tags/ClearInput/Caption}}
>
{{$:/core/images/close-button}}<<delete-tag-state-tiddlers>>
</$button>
</$reveal>
<span class="tc-add-tag-button tc-small-gap-left">
<$set name="tag" value={{{ [<newTagNameTiddler>get[text]] }}}>
<$button set=<<newTagNameTiddler>> setTo="" class="">
<$action-listops $tiddler=<<saveTiddler>> $field=<<__tagField__>> $subfilter="[<tag>trim[]]"/>
$actions$
<$set name="currentTiddlerCSSEscaped" value={{{ [<saveTiddler>escapecss[]] }}}>
<<delete-tag-state-tiddlers>><$action-sendmessage $message="tm-focus-selector" $param=<<get-tagpicker-focus-selector>>/>
</$set>
{{$:/language/EditTemplate/Tags/Add/Button}}
</$button>
</$set>
</span>
</div>
<div class="tc-block-dropdown-wrapper">
<$reveal state=<<qualify "$:/state/popup/tags-auto-complete">> type="nomatch" text="" default="">
<div class="tc-block-dropdown tc-block-tags-dropdown">
<$set name="userInput" value={{{ [<storeTitle>get[text]] }}}>
<$list
filter="[<userInput>minlength{$:/config/Tags/MinLength}limit[1]]"
emptyMessage="<div class='tc-search-results'
>
{{$:/language/Search/Search/TooShort}}</div>" variable="listItem">
<$list filter=<<nonSystemTagsFilter>> variable="tag">
<$list
filter="[<tag>addsuffix[-primaryList]] -[<tagSelectionState>get[text]]"
emptyMessage="<$vars button-classes='tc-btn-invisible tc-tag-button-selected' actions=<<__actions__>> tagField=<<__tagField__>> currentTiddler=<<tag>>>{{||$:/core/ui/TagPickerTagTemplate}}</$vars>"
>
<$vars button-classes="tc-btn-invisible"
actions=<<__actions__>>
tagField=<<__tagField__>>
currentTiddler=<<tag>>
>
{{||$:/core/ui/TagPickerTagTemplate}}
</$vars>
</$list>
</$list>
</$list>
<hr>
<$list filter="[<userInput>minlength{$:/config/Tags/MinLength}limit[1]]" emptyMessage="<div class='tc-search-results'>
{{$:/language/Search/Search/TooShort}}</div>" variable="listItem">
<$list filter=<<systemTagsFilter>> variable="tag">
<$list filter="[<tag>addsuffix[-secondaryList]] -[<tagSelectionState>get[text]]"
emptyMessage="<$vars button-classes='tc-btn-invisible tc-tag-button-selected' actions=<<__actions__>> tagField=<<__tagField__>> currentTiddler=<<tag>>>{{||$:/core/ui/TagPickerTagTemplate}}</$vars>"
>
<$vars button-classes="tc-btn-invisible"
actions=<<__actions__>>
tagField=<<__tagField__>>
currentTiddler=<<tag>>
>
{{||$:/core/ui/TagPickerTagTemplate}}
</$vars>
</$list>
</$list>
</$list>
</$set>
</div>
</$reveal>
</div>
</div>
</$vars>
</$vars>
</$vars>
\end
\define tag-picker(actions,tagField:"tags")
\whitespace trim
<$vars saveTiddler=<<currentTiddler>> palette={{$:/palette}}>
<$list filter="[<newTagNameTiddler>match[]]" emptyMessage="<$macrocall $name='tag-picker-inner' actions=<<__actions__>> tagField=<<__tagField__>>/>">
<$set name="newTagNameTiddler" value=<<qualify "$:/temp/NewTagName">>>
<$macrocall $name="tag-picker-inner" actions=<<__actions__>> tagField=<<__tagField__>>/>
</$set>
</$list>
<$list
filter="[<newTagNameTiddler>match[]]"
emptyMessage="<$macrocall $name='tag-picker-inner' actions=<<__actions__>> tagField=<<__tagField__>>/>"
>
<$set name="newTagNameTiddler" value=<<qualify "$:/temp/NewTagName">>>
<$macrocall $name="tag-picker-inner" actions=<<__actions__>> tagField=<<__tagField__>>/>
</$set>
</$list>
</$vars>
\end

View File

@ -7,7 +7,7 @@ tags: $:/tags/Macro
\define toc-caption()
\whitespace trim
<span class="tc-toc-caption tc-tiny-gap-left">
<span class="tc-toc-caption">
<$set name="tv-wikilinks" value="no">
<$transclude field="caption">
<$view field="title"/>
@ -24,7 +24,7 @@ tags: $:/tags/Macro
<$set name="excluded" filter="""[enlist<__exclude__>] [<__tag__>]""">
<$set name="toc-item-class" filter=<<__itemClassFilter__>> emptyValue="toc-item-selected" value="toc-item">
<li class=<<toc-item-class>>>
<$list filter="[all[current]toc-link[no]]" emptyMessage="<$link to={{{ [<currentTiddler>get[target]else<currentTiddler>] }}}><$view field='caption'><$view field='title'/></$view></$link>">
<$list filter="[all[current]toc-link[no]]" emptyMessage="<$link to={{{ [<currentTiddler>get[target]else<currentTiddler>] }}}><<toc-caption>></$link>">
<<toc-caption>>
</$list>
<$macrocall $name="toc-body" tag=<<item>> sort=<<__sort__>> itemClassFilter=<<__itemClassFilter__>> exclude=<<excluded>> path=<<path>>/>

View File

@ -1,7 +1,9 @@
{
"description": "Deutsche Basis Edition",
"plugins": [
"tiddlywiki/browser-sniff"],
"tiddlywiki/browser-sniff",
"tiddlywiki/internals"
],
"themes": [
"tiddlywiki/vanilla",
"tiddlywiki/snowwhite",
@ -9,8 +11,7 @@
"tiddlywiki/seamless",
"tiddlywiki/centralised",
"tiddlywiki/tight",
"tiddlywiki/readonly",
"tiddlywiki/internals"
"tiddlywiki/readonly"
],
"languages": [
"de-AT",

View File

@ -1,6 +1,7 @@
{
"description": "Spanish (Spain) edition",
"plugins": [
"tiddlywiki/internals"
],
"themes": [
"tiddlywiki/vanilla",
@ -9,8 +10,7 @@
"tiddlywiki/seamless",
"tiddlywiki/centralised",
"tiddlywiki/tight",
"tiddlywiki/readonly",
"tiddlywiki/internals"
"tiddlywiki/readonly"
],
"languages": [
"es-ES"

View File

@ -1,35 +0,0 @@
caption: Beaker Browser
color: #FF8A65
created: 20161229121316912
delivery: App
description: Nouveau navigateur puissant pour Mac, Windows et Linux
fr-title: Enregistrer avec Beaker Browser
method: save
modified: 20220402105820520
tags: Saving Windows Linux Mac
title: Saving on Beaker Browser
type: text/vnd.tiddlywiki
<<.from-version "5.1.14">> <<tw>> intègre un module qui lui permet d'enregistrer les modifications directement avec [[Beaker Browser]], un navigateur internet en peer-to-peer expérimental.
! Instructions
# Téléchargez et installez Beaker Browser depuis https://beakerbrowser.com/
# Lancez Beaker et si nécessaire ouvrez un onglet vers l'adresse `beaker:start`
# Cliquez sur le bouton <<gf "New site">> en haut à gauche de la page
# Saisissez les détails sur votre site
# Cliquez sur le lien <<gf "Add files">> et sélectionnez le fichier `index.html` de votre <<tw>>
# Naviguez sur votre site en cliquant sur le lien vers `index.html`<<;>> il devrait s'ouvrir dans un nouvel onglet
# Essayez de créer des tiddlers et d'enregistrer les modifications
Jusque là, le wiki est entièrement privé et les autres utilisateurs ne peuvent pas en voir le contenu, même en connaissant l'URL. Pour le partager avec d'autres utilisateurs<<:>>
# Publiez vos modifications
## Visitez la page <<gf Library>> à l'aide du menu <<gf System>> de Beaker Browser
## Sélectionnez votre site dans la liste
## Recherchez un encart <<gf "Unpublished changes">>. S'il n'est pas présent, passez au point suivant
## Cliquez sur le bouton <<gf "Review changes">>
## Cliquez sur le bouton <<gf "Publish">>
# Partagez l'URL `dat:`
## Copiez l'URL de votre site à partir de la barre d'adresse et partagez-la avec d'autres utilisateurs
## Les autres utilisateurs devraient pouvoir accéder à votre site mais ils ne pourront pas le modifier avant d'en avoir fait leur propre clone

View File

@ -1,6 +1,7 @@
{
"description": "French (France) edition",
"plugins": [
"tiddlywiki/internals"
],
"themes": [
"tiddlywiki/vanilla",
@ -9,8 +10,7 @@
"tiddlywiki/seamless",
"tiddlywiki/centralised",
"tiddlywiki/tight",
"tiddlywiki/readonly",
"tiddlywiki/internals"
"tiddlywiki/readonly"
],
"languages": [
"fr-FR"

View File

@ -49,9 +49,6 @@
],
"build": {
"index": [
"--savetiddlers","[tag[external-image]]","images",
"--setfield","[tag[external-image]]","_canonical_uri","$:/core/templates/canonical-uri-external-image","text/plain",
"--setfield","[tag[external-image]]","text","","text/plain",
"--rendertiddler","$:/core/save/all","index.html","text/plain"],
"favicon": [
"--savetiddler","$:/favicon.ico","favicon.ico",

View File

@ -1,6 +1,7 @@
{
"description": "Japanese (Japan) edition",
"plugins": [
"tiddlywiki/internals"
],
"themes": [
"tiddlywiki/vanilla",
@ -9,8 +10,7 @@
"tiddlywiki/seamless",
"tiddlywiki/centralised",
"tiddlywiki/tight",
"tiddlywiki/readonly",
"tiddlywiki/internals"
"tiddlywiki/readonly"
],
"languages": [
"ja-JP"

View File

@ -1,23 +1,31 @@
caption: 5.2.6
created: 20221219172444961
modified: 20221219172444961
created: 20230119221001957
modified: 20230119221001957
tags: ReleaseNotes
title: Release 5.2.6
type: text/vnd.tiddlywiki
//[[See GitHub for detailed change history of this release|https://github.com/Jermolene/TiddlyWiki5/compare/v5.2.5...master]]//
! Major Improvements
! Translation Improvements
Improvements to the following translations:
*
* Chinese
* Italian
! Plugin Improvements
* <<.link-badge-updated "https://github.com/Jermolene/TiddlyWiki5/pull/6528">> the [[Markdown Plugin]] to use the newer and better maintained [[markdown-it|https://github.com/markdown-it/markdown-it]] library. The previous Markdown plugin remains available as "markdown-legacy"
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/7176">> [[Innerwiki Plugin]] to allow the `<$data>` widget to override existing tiddler fields
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/7207">>, <<.link-badge-here "https://github.com/Jermolene/TiddlyWiki5/commit/c39ef398bffae12c0ed7324d9b6d9d29f0f2f9ff">> and <<.link-badge-here "https://github.com/Jermolene/TiddlyWiki5/commit/8f7441f296351a4dd0852c3c782f8874d398e052">> problem preventing [[Share Plugin]] from working properly
! Usability Improvements
*
* <<.link-badge-improved "https://github.com/Jermolene/TiddlyWiki5/pull/7217">> consistency of tiddler deletion by allowing missing tiddlers to be 'deleted', which just results in them being closed
* <<.link-badge-improved "https://github.com/Jermolene/TiddlyWiki5/commit/34643a42790777f1b235f57b5093bb29bd0b3a14">> layout switcher to include an optional icon for each layout
* <<.link-badge-removed "https://github.com/Jermolene/TiddlyWiki5/commit/c0615e20ecf7d5d5e66d8a2acd28b80e8d59688d">> [[improvements to table layout|https://github.com/Jermolene/TiddlyWiki5/pull/7010]] from v5.2.5 that have proved to not be backwards compatible
! Widget Improvements
@ -25,19 +33,35 @@ Improvements to the following translations:
! Filter improvements
*
* <<.link-badge-extended "https://github.com/Jermolene/TiddlyWiki5/pull/7121">> [[encodeuricomponent Operator]] to encode characters such as `*` that are illegal in Windows filenames
! Hackability Improvements
*
* <<.link-badge-extended "https://github.com/Jermolene/TiddlyWiki5/pull/7185">> the [[pragma|Pragma]] syntax to allow them to be indented with whitespace
* <<.link-badge-improved "https://github.com/Jermolene/TiddlyWiki5/pull/7118">> readability of [[tag-picker Macro]] and [[keyboard-driven-input Macro]]
* <<.link-badge-improved "https://github.com/Jermolene/TiddlyWiki5/pull/7129">> reliability of [[list-links-draggable Macro]] and [[list-tagged-draggable Macro]] by using the new GenesisWidget instead of textual substitution
* <<.link-badge-improved "https://github.com/Jermolene/TiddlyWiki5/pull/7210">> [[external JavaScript core support|Using the external JavaScript template]] to make it possible to save an external JS wiki as a standard single file wiki
! Bug Fixes
*
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/6622">> bug with the DropzoneWidget that prevented all the available formats being pasted
* <<.link-badge-updated "https://github.com/Jermolene/TiddlyWiki5/pull/7102">> PDF rendering to use an `<iframe>` instead of the older `<embed>`
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/commit/8ef6d78beffb6496fe5daa2c81a529a79046ba3c">> issue with `.tid` files with fieldnames containing hash characters by saving such tiddlers in `.json` format
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/7121">> (and <<.link-badge-here "https://github.com/Jermolene/TiddlyWiki5/pull/7219">>) overriding `toc-caption` macro for [[Table-of-Contents Macros]]
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/7212">> rendering of $:/core/ui/MoreSideBar/Tags when viewed within the story river
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/7156">> undefined variable crash in [[reduce Operator]], [[filter Operator]] and [[sortsub Operator]]
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/issues/7153">> GenesisWidget not to create anything if the `$type` attribute is blank or missing
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/issues/7160">> crash using [[jsonget Operator]] with "fixed" as key name
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/commit/0b39e47ce88c7620b7a66c1553a71efaff06edb9">> importing of MP3 files to match current browser implementations
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/7122">> crash when attempting to create an element with a blank tag name
! Node.js Improvements
*
* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/7169">> integration between the [[BrowserStorage Plugin]] and the client-server configuration to allow changes to be made while offline and then later resynchronised with the server
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/7130">> duplicate fields in internal templates used in client-server configuration
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/issues/7138">> lazy loading not triggering a sync from the server
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/commit/bf8e1ca5b0587787bf80692b0213bb7b038c7868">> crash on creating a new tiddler if anonymous users manage to create syncable tiddlers in a read only wiki
* <<.link-badge-improved "https://github.com/Jermolene/TiddlyWiki5/commit/95e61688397ff1bc9be04193bc4ce2e3c8c48dce">> handling of logout in the client-server configuration to avoid 404 errors
! Performance Improvements
@ -48,4 +72,26 @@ Improvements to the following translations:
[[@Jermolene|https://github.com/Jermolene]] would like to thank the contributors to this release who have generously given their time to help improve TiddlyWiki:
<<.contributors """
AnthonyMuscio
BramChen
btheado
cdruan
CrossEye
cs8425
fkmiec
flibbles
GameDungeon
jeffrey4l
joebordes
kookma
m42e
Marxsal
newmedicine
pippep
pmario
saqimtiaz
Telumire
twMat
wincentbalin
yaisog
""">>

View File

@ -1107,6 +1107,10 @@ Tests the filtering mechanism.
{ name: '', params: [] }
);
});
it("should handle the encodeuricomponent and decodeuricomponent operators", function() {
expect(wiki.filterTiddlers("[[<>:\"/\\|?*]encodeuricomponent[]]").join(",")).toBe("%3C%3E%3A%22%2F%5C%7C%3F%2A");
});
}

View File

@ -43,7 +43,7 @@ describe("WikiText tests", function() {
expect(wiki.renderTiddler("text/html","TiddlerThree")).toBe("<p>The speed of sound</p><p>The light of speed</p>");
});
it("should support attributes specified as macro invocations", function() {
expect(wiki.renderTiddler("text/html","TiddlerFour")).toBe("<p><a class=\"tc-tiddlylink tc-tiddlylink-missing\" href=\"#This%20is%20my%20''amazingly''%20groovy%20macro!\">This is a link</a></p>");
expect(wiki.renderTiddler("text/html","TiddlerFour")).toBe("<p><a class=\"tc-tiddlylink tc-tiddlylink-missing\" href=\"#This%20is%20my%20%27%27amazingly%27%27%20groovy%20macro%21\">This is a link</a></p>");
});
it("should identify wikiwords to automatically link", function() {
expect(wiki.renderText("text/html","text/vnd-tiddlywiki","No wikilinks here").indexOf("<a") !== -1).toBe(false);

View File

@ -1,5 +1,5 @@
created: 20150219175930000
modified: 20230107165037493
modified: 20230117112239663
tags: Concepts [[WikiText Parser Modes]]
title: Pragma
type: text/vnd.tiddlywiki
@ -19,4 +19,6 @@ The following pragmas are available:
;`\whitespace trim` or `\whitespace notrim`
: <<.from-version "5.1.15">> Control whether whitespace is trimmed from the start and end of text runs (the default is ''notrim''). This setting can be useful when the whitespace generated by linebreaks disturbs formatting
;`\import <filter-expression>`
: <<.from-version "5.1.18">> for importing macro definitions from tiddlers identified by a filter expression
: <<.from-version "5.1.18">> Import macro definitions from tiddlers identified by a filter expression
;`\parsermode block` or `\parsermode inline`
: <<.from-version "5.2.4">> Adjust whether the remaining text is parsed in block mode or inline mode.

View File

@ -1,6 +1,6 @@
caption: encodeuricomponent
created: 20161017152747386
modified: 20161017152809900
modified: 20230119174350062
op-input: a [[selection of titles|Title Selection]]
op-output: the input with URI component encoding applied
op-parameter:
@ -13,4 +13,6 @@ from-version: 5.1.14
See Mozilla Developer Network for details of the [[encodeURIComponent|https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent]] operation.
<<.from-version "5.2.6">> In addition to the characters mentioned in the article above, the following additional characters are also percent encoded: `!'()*`
<<.operator-examples "encodeuricomponent">>

View File

@ -11,7 +11,7 @@ op-output: all the property names or indices contained in the input data tiddler
Each input title is processed in turn, and is ignored if it does not denote a [[data tiddler|DataTiddlers]]. The sorted list of property names is retrieved from the data tiddler and then [[dominantly appended|Dominant Append]] to the operator's output.
Note that behind the scenes, the name/value pairs in a dictionary tiddler are represented as a [[JSON object|JSONTiddlers]]. JSON objects do not maintain a guaranteed ordering and so we cant reliably retain the ordering of the data in the file.
Note that behind the scenes, the name/value pairs in a dictionary tiddler are represented as a [[JSON object|JSONTiddlers]]. JSON objects do not maintain a guaranteed ordering and so we cannot reliably retain the ordering of the data in the file.
Where the content of a tiddler is in JSON format with an array as its root, the <<.op indexes>> operator retrieves a selection of integer indices instead.

View File

@ -33,6 +33,8 @@ If <<.place C>> is anything else an error message is returned. <<.from-version "
When <<.op is[missing]>> is the first operator in a [[run|Filter Run]], its output is always empty. And when <<.op is[shadow]>> comes first, it outputs only those shadow tiddlers that have been overridden. This is because the [[initial input to a run|Filter Expression]] contains only <<.em non>>-shadow tiddlers.
The <<.olink all>> operator is similar, but its scope is the whole wiki.
<<.tip "Use `has[title]` to match any tiddler title that is either a tiddler //or// a shadow tiddler.">>
<<.operator-examples "is">>
The <<.olink all>> operator is similar to <<.olink is>>, but its scope is the whole wiki.
<<.operator-examples "is">>

View File

@ -32,7 +32,7 @@ Unlike conventional online services, TiddlyWiki lets you choose where to keep yo
{{$:/core/images/twitter}} Twitter
</a>
<a rel="me" href="https://fosstodon.org/@TiddlyWiki" class="tc-btn-big-green" style="border-radius:4px;background-color:#2b90d9;" target="_blank" rel="noopener noreferrer">
{{$:/core/images/globe}} Mastodon
{{$:/core/images/mastodon}} Mastodon
</a>
<a href="https://github.com/Jermolene/TiddlyWiki5" class="tc-btn-big-green" style="border-radius:4px;background-color:#444;" target="_blank" rel="noopener noreferrer">
{{$:/core/images/github}} ~GitHub

View File

@ -1,21 +0,0 @@
created: 20161229113910984
modified: 20171113110222980
title: Beaker Browser
type: text/vnd.tiddlywiki
From [[Beaker Browser website|https://beakerbrowser.com/]]:
> Beaker is a Peer-to-Peer Web Browser, made for users to run applications independently of hosts. Using P2P Hypermedia, Beaker separates frontend apps from backend services, so that users are completely in control of their software and data. Read more.
Beaker is a fork of the open source Chromium browser (which is the core engine powering Google's Chrome browser).
Beaker adds the ability to host sites within the browser, and browse to those sites via the `dat://` protocol. The extraordinary thing is that if you are running Beaker then you can also browse to sites hosted by other users, without needing any server in between.
Further, you can opt to host a site belonging to somebody else, forming part of a Bittorrent-like swarm of peers serving the content to other browsers. You can also //fork// a site, making your own copy that you can change as you need.
The main disadvantage is that mainstream browsers cannot use `dat://` sites.
Most of the magic is accomplished by the underlying [[Dat protocol|https://datproject.org/]].
<<.from-version "5.1.14">> TiddlyWiki incorporates a special saver module permitting changes to be saved directly from Beaker browser. See [[Saving on Beaker Browser]] for instructions.

View File

@ -1,17 +1,13 @@
created: 20221123223127425
modified: 20221123223127425
tags: Pragmas
modified: 20230117112244779
tags: Pragma
title: Pragma: \parsermode
type: text/vnd.tiddlywiki
The ''\parsermode'' [[pragma|Pragmas]] adjusts whether the remaining text is parsed in block mode or inline mode. See [[WikiText Parser Modes]] for details of parser modes.
<<.from-version "5.2.4">>
```
\parsermode block|inline
```
The ''\parsermode'' [[pragma|Pragma]] adjusts whether the remaining text is parsed in block mode or inline mode. See [[WikiText Parser Modes]] for details of parser modes.
For example:
As with all pragmas, setting the parser mode this way can only be done at the start of text, not within the main body of the text.
```
\parsermode inline
```
;`\parsermode block` or `\parsermode inline`

View File

@ -1,34 +0,0 @@
caption: Beaker Browser
color: #FF8A65
created: 20161229121316912
delivery: App
description: Powerful new browser for Mac, Windows and Linux
method: save
modified: 20200507104016915
tags: Saving Windows Linux Mac
title: Saving on Beaker Browser
type: text/vnd.tiddlywiki
<<.from-version "5.1.14">> TiddlyWiki incorporates a saver module that allows it to save changes directly with the [[Beaker Browser]], an experimental peer-to-peer browser.
! Instructions
# Download and install the Beaker Browser from https://beakerbrowser.com/
# Run Beaker, and if necessary open a tab to beaker:start
# Click the "New site" button at the top left of the page
# Enter the details of your site
# Click the link “Add files” and upload your TiddlyWiki index.html file
# View the site by clicking on the link to index.html; it should open in a new tab
# Try out creating tiddlers, and saving changes
At this point, the wiki is entirely private, and other users cannot see the content even if they have the URL. To share the wiki with other users:
# Publish your changes
## Visit the "Library" page in Beaker Browser via the system menu
## Select your site in the list
## Look for a box mentioning "n unpublished changes". If not present, skip to the next step
## Click the "Review changes" button
## Click the "Publish" button
# Share the dat: URL
## Copy the URL of your site from the address bar and share it with other users
## Other users should be able to access your site but they won't be able to make changes unless they fork their own copy

View File

@ -34,7 +34,7 @@ Lightweight, portable and easy to use solutions
* ~SharePoint / ~OneDrive for Windows
** Save your ~TiddlyWiki file with an `.aspx` extension
** Copy it to a ~SharePoint/~OneDrive for Business sync'd library
** As long as ~WebDAV hasnt been disabled, renaming single-file wiki from .html to .aspx “just works” when stored in one of these folders
** As long as ~WebDAV has not been disabled, renaming single-file wiki from .html to .aspx “just works” when stored in one of these folders
** This //might// work with Mac also.
!! OSX

View File

@ -1,6 +1,6 @@
created: 20200131142401129
modified: 20211113230406823
tags: ActionCreateTiddlerWidget Widgets
tags: ActionCreateTiddlerWidget
title: ActionCreateTiddlerWidget Example 1
type: text/vnd.tiddlywiki

View File

@ -1,6 +1,6 @@
created: 20200131144828713
modified: 20211113011036840
tags: ActionCreateTiddlerWidget Widgets
tags: ActionCreateTiddlerWidget
title: ActionCreateTiddlerWidget Example 2
type: text/vnd.tiddlywiki

View File

@ -1,6 +1,6 @@
created: 20200131145355658
modified: 20211113011111052
tags: ActionCreateTiddlerWidget Widgets
tags: ActionCreateTiddlerWidget
title: ActionCreateTiddlerWidget Example 3
type: text/vnd.tiddlywiki

View File

@ -1,6 +1,6 @@
created: 20200131150229551
modified: 20211113011129601
tags: ActionCreateTiddlerWidget Widgets
tags: ActionCreateTiddlerWidget
title: ActionCreateTiddlerWidget Example 4
type: text/vnd.tiddlywiki

View File

@ -0,0 +1,32 @@
created: 20200131144828713
modified: 20230111220933412
tags: ActionCreateTiddlerWidget
title: ActionCreateTiddlerWidget Example 5
type: text/vnd.tiddlywiki
\define testCreate()
<$action-createtiddler $basetitle="base" $template="ActionCreateTiddlerWidget Template">
<$action-sendmessage $message="tm-edit-tiddler" $param=<<createTiddler-title>>/>
</$action-createtiddler>
\end
This example will use the base title defined in [[ActionCreateTiddlerWidget Template]].
It will create: "base", "base 1", "base 2" and so on, and navigate to this tiddler in draft mode.
```
\define testCreate()
<$action-createtiddler $basetitle="base" $template="ActionCreateTiddlerWidget Template">
<$action-sendmessage $message="tm-edit-tiddler" $param=<<createTiddler-title>>/>
</$action-createtiddler>
\end
<$button actions=<<testCreate>> >
Create Tiddler
</$button>
```
<$button actions=<<testCreate>> >
<$action-setfield $tiddler="$:/state/tab/sidebar--595412856" text="$:/core/ui/SideBar/Recent"/>
Create Tiddler
</$button> - Clicking this button, will also open the Right sidebar: Recent tab

View File

@ -1,35 +1,39 @@
caption: action-createtiddler
created: 20161020152745942
modified: 20210601092956998
modified: 20230115084716196
tags: Widgets ActionWidgets
title: ActionCreateTiddlerWidget
type: text/vnd.tiddlywiki
! Introduction
The ''action-createtiddler'' widget is an [[action widget|ActionWidgets]] that creates new tiddlers. ActionWidgets are used within triggering widgets such as the ButtonWidget.
The <<.wid "action-createtiddler">> widget is an [[action widget|ActionWidgets]] that creates new tiddlers. Action widgets are used within triggering widgets such as the ButtonWidget.
There are several differences from the [[tm-new-tiddler message|WidgetMessage: tm-new-tiddler]]:
There are several //differences// from the [[tm-new-tiddler message|WidgetMessage: tm-new-tiddler]]:
* The new tiddler is not automatically displayed in the [[story river|StoryRiver]]
* The new tiddler is not automatically displayed in the [[story river|Story River]]
* The title of the new tiddler is made available for subsequent operations
! Content and Attributes
The ''action-createtiddler'' widget is invisible.
<<.from-version "5.2.0">> The action widgets contained within the ''action-createtiddler'' widget are executed after the new tiddler has been created with the title of the tiddler in the variable `createTiddler-title` and `createTiddler-draftTitle`.
|!Attribute |!Description |
|$basetitle |The initial title that will be attempted. If a tiddler with that title already exists, then a numerical counter is added to the title and incremented until it is unique|
|$savetitle |//(deprecated see below)// A text reference identifying a field or index into which the title of the newly created tiddler will be stored after it is created |
|$savedrafttitle |//(deprecated see below)// <<.from-version "5.1.20">> A text reference identifying a field or index into which the draft title associated with the newly created tiddler will be stored after it is created. This is useful when using a sequence of action widgets to create a new tiddler, put it into edit mode, and position it within the list of its parent tag |
|$savetitle |<<.deprecated-since "5.1.20" "ActionCreateTiddlerWidget Example 5">> A text reference identifying a field or index into which the title of the newly created tiddler will be stored after it is created |
|$savedrafttitle |<<.deprecated-since "5.1.20" "ActionCreateTiddlerWidget Example 5">> A text reference identifying a field or index into which the draft title associated with the newly created tiddler will be stored after it is created. This is useful when using a sequence of action widgets to create a new tiddler, put it into edit mode, and position it within the list of its parent tag |
|$timestamp |Specifies whether the timestamp(s) of the target tiddler will be updated (''modified'' and ''modifier'', plus ''created'' and ''creator'' for newly created tiddlers). Can be "yes" (the default) or "no" |
|$template |<<.from-version "5.1.22">> The title of a template tiddler, that will be used to create a new tiddler |
|$overwrite |<<.from-version "5.1.22">> If set to "yes", it will overwrite existing tiddlers. ''Be careful!'' |
|//{any attributes not starting with $}// |Each attribute name specifies a field to be created in the new tiddler |
<<.from-version "5.2.0">> Note that the attributes `$savetitle` and `$savedrafttitle` are no longer needed. Instead, any action widgets that need to use the title of the newly created tiddler should be contained within the ''action-createtiddler'' widget, and reference the variables `createTiddler-title` and `createTiddler-draftTitle` to obtain the title.
! Variables
<<.from-version "5.2.0">> The content of the <<.wid "action-createtiddler">> widget is executed after the new tiddler has been created. The title of the newly created tiddler is stored in the variable <<.var "createTiddler-title">>.
|!Variables |!Description |
|`createTiddler-title` |The tittle of the tiddler that has been created. See [[ActionCreateTiddlerWidget Example 5]] |
|`createTiddler-draftTitle` |This variable only exists to have feature parity with the deprecated parameters. It contains the title of a "draft tiddler" |
! Examples
@ -61,4 +65,9 @@ The ''action-createtiddler'' widget is invisible.
{{ActionCreateTiddlerWidget Example 4}}
<<<
---
<<<
{{ActionCreateTiddlerWidget Example 5}}
<<<

View File

@ -1,6 +1,6 @@
created: 20161020153426686
modified: 20211113011019510
tags: ActionCreateTiddlerWidget Widgets
tags: ActionCreateTiddlerWidget
title: ActionCreateTiddlerWidget Example
type: text/vnd.tiddlywiki

View File

@ -1,22 +1,22 @@
caption: genesis
created: 20221101100729587
modified: 20221230213912929
modified: 20230115101800345
tags: Widgets
title: GenesisWidget
type: text/vnd.tiddlywiki
! Introduction
<<.from-version "5.2.4">> The <<.wlink GenesisWidget>> widget allows the dynamic construction of another widget, where the name and attributes of the new widget can be dynamically determined, without needing to be known in advance.
<<.from-version "5.2.4">> The <<.wid genesis>> widget allows the dynamic construction of another widget, where the name and attributes of the new widget can be dynamically determined, without needing to be known in advance.
! Content and Attributes
The content of the <<.wlink GenesisWidget>> widget is used as the content of the dynamically created widget.
The content of the <<.wid genesis>> widget is used as the content of the dynamically created widget.
|!Attribute |!Description |
|$type |The type of widget or element to create (an initial `$` indicates a widget, otherwise an HTML element will be created) |
|$names |An optional filter evaluating to the names of a list of attributes to be applied to the widget |
|$values |An optional filter evaluating to the values corresponding to the list of names specified in `$names` |
|$values |An optional filter evaluating to the values corresponding to the list of names specified in <<.attr $names>> |
|//{other attributes starting with $}// |Other attributes starting with a single dollar sign are reserved for future use |
|//{attributes starting with $$}// |Attributes starting with two dollar signs are applied as attributes to the output widget, but with the attribute name changed to use a single dollar sign |
|//{attributes not starting with $}// |Any other attributes that do not start with a dollar are applied as attributes to the output widget |
@ -27,10 +27,10 @@ Note that attributes explicitly specified take precedence over attributes with t
! Examples
<$macrocall $name='wikitext-example-without-html'
src='<$genesis $type="div" class="tc-thing" label="Squeak">Mouse</$genesis>'/>
<$macrocall $name="wikitext-example"
src="""<$genesis $type="div" class="tc-thing" label="Squeak">Mouse</$genesis>"""/>
<$macrocall $name='wikitext-example-without-html'
<$macrocall $name="wikitext-example"
src="""\define my-banner(mode:"inline",caption)
<$genesis $type={{{ [<__mode__>match[inline]then[span]else[div]] }}} class="tc-mybanner">
<<__caption__>>
@ -41,3 +41,10 @@ src="""\define my-banner(mode:"inline",caption)
<<my-banner mode:"block" caption:"I'm in a DIV">>
"""/>
! Important
<$macrocall $name=".warning" _="""
In the following example the widget attribute named `one` is not present in the HTML output. This is because HTML attributes starting with the prefix `on` are removed for security reasons. See [[HTML in WikiText]] "Security" for more details. This restriction only affects generated HTML elements, and does not prevent the use of attributes prefixed `on` with other widgets"""/>
<<wikitext-example '<$genesis $type="my-element" $names="one two" $values="1 2">Test Genesis Widget</$genesis>'>>

View File

@ -1,6 +1,6 @@
caption: HTML
created: 20131205160816081
modified: 20220123174919252
modified: 20230115100934146
tags: WikiText
title: HTML in WikiText
type: text/vnd.tiddlywiki
@ -31,7 +31,14 @@ some text <!-- inline comment -->
! Important
<<.tip """[[Widgets share the same syntax as HTML tags|Widgets in WikiText]], and so the following information applies to them, too.""">>
!! Security
<<.warning """Note that any HTML attributes prefixed with `on` are removed from the rendered HTML content. This is done to prevent event handlers (such as "onclick") being used as a clandestine way to execute untrusted JavaScript. A design goal of TiddlyWiki is to ensure that executable JavaScript can only enter the system through explicit JavaScript module tiddlers or raw markup tiddlers. This makes it possible to filter unsafe content in multiuser environments, and also makes it safer to copy untrusted wikitext examples.""">>
!! Widgets
<<.tip """[[Widgets share the same syntax as HTML tags|Widgets in WikiText]]<br>and so the following information applies to them, too.""">>
! Block mode versus Inline mode
@ -47,7 +54,7 @@ The following tags are treated as 'void'. This means that `<tag>` is treated as
* `<area>`, `<base>`, `<br>`, `<col>`, `<command>`, `<embed>`, `<hr>`, `<img>`, `<input>`, `<keygen>`, `<link>`, `<meta>`, `<param>`, `<source>`, `<track>`, `<wbr>`
If you dont close any other tag then it will behave as if the missing closing tag were at the end of the tiddler.
If you do not close any other tag then it will behave as if the missing closing tag were at the end of the tiddler.
! Attributes
@ -114,7 +121,7 @@ attr={{tiddler}}
attr={{!!field}}
attr={{tiddler!!field}}
```
<<.warning "The attribute's value will be the exact text retrieved from the TextReference. Any wiki syntax in that text will be left as-is.">>
<<.warning "The value of the attribute value will be the exact text retrieved from the TextReference. Any wiki syntax in that text will be left as-is.">>
!! Variable Attribute Values
@ -125,7 +132,7 @@ Variable attribute values are indicated with double angle brackets around a [[ma
...
</div>
```
<<.warning "The text from the macro's definition will be retrieved and text substitution will be performed (i.e. <<.param $param$>> and <<.param &#36;(...)&#36;>> syntax). The attribute's value will be the resulting text. Any wiki syntax in that text (including further macro calls and variable references) will be left as-is.">>
<<.warning "The text from the definition of the macro will be retrieved and text substitution will be performed (i.e. <<.param $param$>> and <<.param &#36;(...)&#36;>> syntax). The value of the attribute value will be the resulting text. Any wiki syntax in that text (including further macro calls and variable references) will be left as-is.">>
!! Filtered Attribute Values
@ -138,4 +145,4 @@ This example shows how to add a prefix to a value:
```
<$text text={{{ [<currentTiddler>addprefix[$:/myprefix/]] }}} />
```
<<.warning "The attribute's value will be the exact text from the first item in the resulting list. Any wiki syntax in that text will be left as-is.">>
<<.warning "The value of the attribute will be the exact text from the first item in the resulting list. Any wiki syntax in that text will be left as-is.">>

View File

@ -104,5 +104,3 @@ TagManager/Tag/Heading: タグ
Tiddler/DateFormat: YYYY年MM月DD日(ddd) 0hh:0mm
UnsavedChangesWarning: 保存していない編集内容があります。
Yes: はい
$:/SiteSubtitle: 非線形パーソナルウェブノートブック
$:/SiteTitle: 私の ~TiddlyWiki

View File

@ -8,8 +8,6 @@ Basics/AnimDuration/Prompt: Długość animacji
Basics/AutoFocus/Prompt: Domyślne wybrane pole do edycji przy tworzeniu nowego tiddlera
Basics/Caption: Podstawowe
Basics/DefaultTiddlers/BottomHint: Tiddlery, które mają spację w nazie otocz &#91;&#91;podwójnymi nawiasami kwadratowymi&#93;&#93;. Możesz też ustawić, by zawsze widzieć {{ostatnio otwarte tiddlery||$:/snippets/retain-story-ordering-button}}
Basics/DefaultTiddlers/BottomHint: Use &#91;&#91;double square brackets&#93;&#93; for titles with spaces. Or you can choose to <$button set="$:/DefaultTiddlers" setTo="[list[$:/StoryList]]">retain story ordering</$button>
Basics/DefaultTiddlers/BottomHint: Use &#91;&#91;double square brackets&#93;&#93; for titles with spaces. Or you can choose to {{retain story ordering||$:/snippets/retain-story-ordering-button}}
Basics/DefaultTiddlers/Prompt: Domyślnie otwarte tiddlery
Basics/DefaultTiddlers/TopHint: Wybierz które tiddlery mają być widoczne przy uruchomieniu
Basics/Language/Prompt: Cześć! Wybrany język to:

View File

@ -517,3 +517,5 @@ Pippo Peppo, @pippep, 2023-01-03
Scott Sauye, @CrossEye, 2023-01-04
Marcus Winter, @yaisog, 2023-01-07
Ethan Weller, @gamedungeon, 2023-01-17

View File

@ -14,7 +14,6 @@ $tw = window.$tw || Object.create(null);
$tw.hooks = $tw.hooks || { names: {}};
$tw.boot = $tw.boot || {};
$tw.boot.preloadDirty = $tw.boot.preloadDirty || [];
// Hook the point in the startup process when the tiddlers have been loaded but plugins not unpacked
var hookName = "th-boot-tiddlers-loaded";
if(Object.prototype.hasOwnProperty.call($tw.hooks.names,hookName)) {

View File

@ -19,19 +19,29 @@ exports.after = ["startup"];
exports.synchronous = true;
var ENABLED_TITLE = "$:/config/BrowserStorage/Enabled",
SAVE_FILTER_TITLE = "$:/config/BrowserStorage/SaveFilter",
QUOTA_EXCEEDED_ALERT_TITLE = "$:/config/BrowserStorage/QuotaExceededAlert",
DEFAULT_QUOTA_EXCEEDED_ALERT_PREFIX = "Quota exceeded attempting to store `",
DEFAULT_QUOTA_EXCEEDED_ALERT_SUFFIX = "` in browser local storage";
SAVE_FILTER_TITLE = "$:/config/BrowserStorage/SaveFilter";
var BrowserStorageUtil = require("$:/plugins/tiddlywiki/browser-storage/util.js").BrowserStorageUtil;
exports.startup = function() {
var self = this;
// If not exists, add ENABLED tiddler with default value "yes"
if(!$tw.wiki.getTiddler(ENABLED_TITLE)) {
$tw.wiki.addTiddler({title: ENABLED_TITLE, text: "yes"});
}
// Compute our prefix for local storage keys
var prefix = "tw5#" + window.location.pathname + "#";
// Make a logger
var logger = new $tw.utils.Logger("browser-storage",{
colour: "cyan"
});
// Add browserStorage object to $tw
$tw.browserStorage = new BrowserStorageUtil($tw.wiki,{
enabledTitle: ENABLED_TITLE,
prefix: prefix,
logger: logger
});
// Function to compile the filter
var filterFn,
compileFilter = function() {
@ -41,7 +51,7 @@ exports.startup = function() {
// Listen for tm-clear-browser-storage messages
$tw.rootWidget.addEventListener("tm-clear-browser-storage",function(event) {
$tw.wiki.addTiddler({title: ENABLED_TITLE, text: "no"});
clearLocalStorage();
$tw.browserStorage.clearLocalStorage();
});
// Track tiddler changes
$tw.wiki.addEventListener("change",function(changes) {
@ -67,65 +77,9 @@ exports.startup = function() {
return;
}
// Save the tiddler
saveTiddlerToLocalStorage(title,{
logger: logger,
prefix: prefix
});
$tw.browserStorage.saveTiddlerToLocalStorage(title);
});
});
};
function saveTiddlerToLocalStorage(title,options) {
options = options || {};
// Get the tiddler
var tiddler = $tw.wiki.getTiddler(title);
if(tiddler) {
console.log("browser-storage: Saving",title);
// Get the JSON of the tiddler
var json = JSON.stringify(tiddler.getFieldStrings());
// Try to save it to local storage
try {
window.localStorage.setItem(options.prefix + title,json);
} catch(e) {
if(e.name === "QuotaExceededError") {
// Complain if we failed
var msg = $tw.wiki.getTiddlerText(QUOTA_EXCEEDED_ALERT_TITLE,DEFAULT_QUOTA_EXCEEDED_ALERT_PREFIX + title + DEFAULT_QUOTA_EXCEEDED_ALERT_SUFFIX);
if(options.logger) {
options.logger.alert(msg);
}
// No point in keeping old values around for this tiddler
window.localStorage.removeItem(options.prefix + title);
} else {
console.log("Browser-storage error:",e);
}
}
} else {
// In local storage, use the special value of empty string to mark the tiddler as deleted
// On future page loads, if the tiddler is already gone from startup then the blank entry
// will be removed from localstorage. Otherwise, the tiddler will be deleted.
console.log("browser-storage: Blanking",title);
try {
window.localStorage.setItem(options.prefix + title, "");
} catch(e) {
console.log("Browser-storage error:",e);
}
}
}
function clearLocalStorage() {
var url = window.location.pathname,
log = [];
// Step through each browser storage item
if(window.localStorage) {
for(var index=window.localStorage.length - 1; index>=0; index--) {
var key = window.localStorage.key(index),
parts = key.split("#");
// Delete it if it is ours
if(parts[0] === "tw5" && parts[1] === url) {
window.localStorage.removeItem(key);
}
}
}
}
})();

View File

@ -0,0 +1,106 @@
/*\
title: $:/plugins/tiddlywiki/browser-storage/util.js
type: application/javascript
module-type: library
Utility methods for browser-storage plugin
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
function BrowserStorageUtil(wiki,options) {
this.options = options || {};
this.wiki = wiki;
this.cachedTiddlers = [];
this.QUOTA_EXCEEDED_ALERT_TITLE = "$:/config/BrowserStorage/QuotaExceededAlert";
this.DEFAULT_QUOTA_EXCEEDED_ALERT_PREFIX = "Quota exceeded attempting to store `";
this.DEFAULT_QUOTA_EXCEEDED_ALERT_SUFFIX = "` in browser local storage";
}
BrowserStorageUtil.prototype.isEnabled = function() {
return $tw.wiki.getTiddlerText(this.options.enabledTitle) === "yes";
};
BrowserStorageUtil.prototype.cachePreloadTiddlers = function() {
var self = this;
$tw.utils.each($tw.boot.preloadDirty, function(item){
var tiddler = $tw.wiki.getTiddler(item);
self.cachedTiddlers.push(tiddler);
});
};
BrowserStorageUtil.prototype.addCachedTiddlers = function() {
var self = this;
if(this.cachedTiddlers.length > 0) {
$tw.utils.each(this.cachedTiddlers, function(item){
$tw.wiki.addTiddler(item);
});
this.cachedTiddlers.length = 0;
}
};
BrowserStorageUtil.prototype.removeTiddlerFromLocalStorage = function(title) {
console.log("browser-storage: Removing", title);
window.localStorage.removeItem(this.options.prefix + title);
};
BrowserStorageUtil.prototype.saveTiddlerToLocalStorage = function(title) {
// Get the tiddler
var tiddler = $tw.wiki.getTiddler(title);
if(tiddler) {
console.log("browser-storage: Saving",title);
// Get the JSON of the tiddler
var json = JSON.stringify(tiddler.getFieldStrings());
// Try to save it to local storage
try {
window.localStorage.setItem(this.options.prefix + title,json);
} catch(e) {
if(e.name === "QuotaExceededError") {
// Complain if we failed
var msg = $tw.wiki.getTiddlerText(this.QUOTA_EXCEEDED_ALERT_TITLE,this.DEFAULT_QUOTA_EXCEEDED_ALERT_PREFIX + title + this.DEFAULT_QUOTA_EXCEEDED_ALERT_SUFFIX);
if(this.options.logger) {
this.options.logger.alert(msg);
}
// No point in keeping old values around for this tiddler
window.localStorage.removeItem(this.options.prefix + title);
} else {
console.log("Browser-storage error:",e);
}
}
} else {
// In local storage, use the special value of empty string to mark the tiddler as deleted
// On future page loads, if the tiddler is already gone from startup then the blank entry
// will be removed from localstorage. Otherwise, the tiddler will be deleted.
console.log("browser-storage: Blanking",title);
try {
window.localStorage.setItem(this.options.prefix + title, "");
} catch(e) {
console.log("Browser-storage error:",e);
}
}
};
BrowserStorageUtil.prototype.clearLocalStorage = function() {
var url = window.location.pathname,
log = [];
// Step through each browser storage item
if(window.localStorage) {
for(var index=window.localStorage.length - 1; index>=0; index--) {
var key = window.localStorage.key(index),
parts = key.split("#");
// Delete it if it is ours
if(parts[0] === "tw5" && parts[1] === url) {
window.localStorage.removeItem(key);
}
}
}
};
exports.BrowserStorageUtil = BrowserStorageUtil;
})();

View File

@ -4,4 +4,4 @@ title: $:/core/templates/css-tiddler
This template is used for saving CSS tiddlers as a style tag with data attributes representing the tiddler fields. This version includes the tiddler changecount as the field `revision`.
-->`<style`<$fields template=' data-tiddler-$name$="$encoded_value$"'></$fields>` data-tiddler-revision="`<<changecount>>`" data-tiddler-bag="default" type="text/css">`<$view field="text" format="text" />`</style>`
-->`<style`<$fields exclude='text revision bag' template=' data-tiddler-$name$="$encoded_value$"'></$fields>` data-tiddler-revision="`<<changecount>>`" data-tiddler-bag="default" type="text/css">`<$view field="text" format="text" />`</style>`

View File

@ -4,4 +4,4 @@ title: $:/core/templates/javascript-tiddler
This template is used for saving JavaScript tiddlers as a script tag with data attributes representing the tiddler fields. This version includes the tiddler changecount as the field `revision`.
-->`<script`<$fields template=' data-tiddler-$name$="$encoded_value$"'></$fields>` data-tiddler-revision="`<<changecount>>`" data-tiddler-bag="default" type="text/javascript">`<$view field="text" format="text" />`</script>`
-->`<script`<$fields exclude='text revision bag' template=' data-tiddler-$name$="$encoded_value$"'></$fields>` data-tiddler-revision="`<<changecount>>`" data-tiddler-bag="default" type="text/javascript">`<$view field="text" format="text" />`</script>`

View File

@ -76,6 +76,10 @@ TiddlyWebAdaptor.prototype.getStatus = function(callback) {
if(err) {
return callback(err);
}
//If Browser-Storage plugin is present, cache pre-loaded tiddlers and add back after sync from server completes
if($tw.browserStorage && $tw.browserStorage.isEnabled()) {
$tw.browserStorage.cachePreloadTiddlers();
}
// Decode the status JSON
var json = null;
try {
@ -188,6 +192,10 @@ TiddlyWebAdaptor.prototype.getSkinnyTiddlers = function(callback) {
}
// Invoke the callback with the skinny tiddlers
callback(null,tiddlers);
// If Browswer Storage tiddlers were cached on reloading the wiki, add them after sync from server completes in the above callback.
if($tw.browserStorage && $tw.browserStorage.isEnabled()) {
$tw.browserStorage.addCachedTiddlers();
}
}
});
};
@ -211,6 +219,10 @@ TiddlyWebAdaptor.prototype.saveTiddler = function(tiddler,callback,options) {
if(err) {
return callback(err);
}
//If Browser-Storage plugin is present, remove tiddler from local storage after successful sync to the server
if($tw.browserStorage && $tw.browserStorage.isEnabled()) {
$tw.browserStorage.removeTiddlerFromLocalStorage(tiddler.fields.title)
}
// Save the details of the new revision of the tiddler
var etag = request.getResponseHeader("Etag");
if(!etag) {

View File

@ -814,9 +814,6 @@ button.tc-tag-label, span.tc-tag-label {
}
.tc-untagged-separator {
width: 10em;
left: 0;
margin-left: 0;
border: 0;
height: 1px;
background: <<colour tab-divider>>;
@ -2777,6 +2774,11 @@ input.tc-palette-manager-colour-input {
color: <<colour sidebar-foreground>>;
}
button + .tc-toc-caption,
button > .tc-toc-caption{
margin-left: .25em;
}
.tc-table-of-contents svg {
width: 0.7em;
height: 0.7em;
@ -3137,6 +3139,8 @@ select {
** Other utility classes
*/
/* Horizontal gaps */
.tc-tiny-gap {
margin-left: .25em;
margin-right: .25em;
@ -3179,3 +3183,9 @@ select {
.tc-word-break {
word-break: break-all;
}
/* Vertical gaps */
.tc-tiny-v-gap-bottom {
margin-bottom: 3px;
}