1
0
mirror of https://github.com/Jermolene/TiddlyWiki5 synced 2024-06-27 15:53:14 +00:00

Merge branch 'master' into geospatial-plugin

This commit is contained in:
jeremy@jermolene.com 2023-06-11 12:22:42 +01:00
commit 9285470562
47 changed files with 392 additions and 192 deletions

View File

@ -2080,7 +2080,11 @@ $tw.loadPluginFolder = function(filepath,excludeRegExp) {
console.log("Warning: missing plugin.info file in " + filepath);
return null;
}
var pluginInfo = $tw.utils.parseJSONSafe(fs.readFileSync(infoPath,"utf8"));
var pluginInfo = $tw.utils.parseJSONSafe(fs.readFileSync(infoPath,"utf8"),function() {return null;});
if(!pluginInfo) {
console.log("warning: invalid JSON in plugin.info file at " + infoPath);
pluginInfo = {};
}
// Read the plugin files
var pluginFiles = $tw.loadTiddlersFromPath(filepath,excludeRegExp);
// Save the plugin tiddlers into the plugin info
@ -2197,7 +2201,11 @@ $tw.loadWikiTiddlers = function(wikiPath,options) {
pluginFields;
// Bail if we don't have a wiki info file
if(fs.existsSync(wikiInfoPath)) {
wikiInfo = $tw.utils.parseJSONSafe(fs.readFileSync(wikiInfoPath,"utf8"));
wikiInfo = $tw.utils.parseJSONSafe(fs.readFileSync(wikiInfoPath,"utf8"),function() {return null;});
if(!wikiInfo) {
console.log("warning: invalid JSON in tiddlywiki.info file at " + wikiInfoPath);
wikiInfo = {};
}
} else {
return null;
}

View File

@ -3,7 +3,7 @@ title: $:/Acknowledgements
TiddlyWiki incorporates code from these fine OpenSource projects:
* [[The Stanford Javascript Crypto Library|http://bitwiseshiftleft.github.io/sjcl/]]
* [[The Jasmine JavaScript Test Framework|http://pivotal.github.io/jasmine/]]
* [[The Jasmine JavaScript Test Framework|https://jasmine.github.io/]]
* [[Normalize.css by Nicolas Gallagher|http://necolas.github.io/normalize.css/]]
And media from these projects:

View File

@ -25,6 +25,8 @@ Encryption/RepeatPassword: Repeat password
Encryption/PasswordNoMatch: Passwords do not match
Encryption/SetPassword: Set password
Error/Caption: Error
Error/DeserializeOperator/MissingOperand: Filter Error: Missing operand for 'deserialize' operator
Error/DeserializeOperator/UnknownDeserializer: Filter Error: Unknown deserializer provided as operand for the 'deserialize' operator
Error/Filter: Filter error
Error/FilterSyntax: Syntax error in filter expression
Error/FilterRunPrefix: Filter Error: Unknown prefix for filter run

View File

@ -1,3 +1,3 @@
title: $:/SiteTitle
My ~TiddlyWiki
My TiddlyWiki

View File

@ -12,6 +12,8 @@ Adds tiddler filtering methods to the $tw.Wiki object.
/*global $tw: false */
"use strict";
var widgetClass = require("$:/core/modules/widgets/widget.js").widget;
/* Maximum permitted filter recursion depth */
var MAX_FILTER_DEPTH = 300;
@ -269,7 +271,7 @@ exports.compileFilter = function(filterString) {
operand.value = self.getTextReference(operand.text,"",currTiddlerTitle);
} else if(operand.variable) {
var varTree = $tw.utils.parseFilterVariable(operand.text);
operand.value = widget.evaluateVariable(varTree.name,{params: varTree.params, source: source})[0] || "";
operand.value = widgetClass.evaluateVariable(widget,varTree.name,{params: varTree.params, source: source})[0] || "";
} else {
operand.value = operand.text;
}

View File

@ -0,0 +1,39 @@
/*\
title: $:/core/modules/filters/deserialize.js
type: application/javascript
module-type: filteroperator
Filter operator for deserializing string data into JSON representing tiddlers
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports["deserialize"] = function(source,operator,options) {
var results = [],
deserializer;
if(operator.operand) {
// Get the deserializer identified by the operand
deserializer = $tw.Wiki.tiddlerDeserializerModules[operator.operand];
if(deserializer) {
source(function(tiddler,title) {
var tiddlers;
try {
tiddlers = deserializer(title);
} catch(e) {
// Return an empty array if we could not extract any tiddlers
tiddlers = [];
}
results.push(JSON.stringify(tiddlers));
});
} else {
return [$tw.language.getString("Error/DeserializeOperator/UnknownDeserializer")];
}
} else {
return [$tw.language.getString("Error/DeserializeOperator/MissingOperand")];
}
return results;
}
})();

View File

@ -17,9 +17,13 @@ Export our filter function
*/
exports.function = function(source,operator,options) {
var functionName = operator.operands[0],
variableInfo = options.widget && options.widget.getVariableInfo && options.widget.getVariableInfo(functionName);
params = [];
$tw.utils.each(operator.operands.slice(1),function(param) {
params.push({value: param});
});
var variableInfo = options.widget && options.widget.getVariableInfo && options.widget.getVariableInfo(functionName,{params: params, source: source});
if(variableInfo && variableInfo.srcVariable && variableInfo.srcVariable.isFunctionDefinition) {
return options.widget.evaluateVariable(functionName,{params: operator.operands.slice(1), source: source});
return variableInfo.resultList ? variableInfo.resultList : [variableInfo.text];
}
// Return the input list if the function wasn't found
var results = [];

View File

@ -21,10 +21,14 @@ Export our filter function
*/
exports["[unknown]"] = function(source,operator,options) {
// Check for a user defined filter operator
if(operator.operator.charAt(0) === ".") {
var variableInfo = options.widget && options.widget.getVariableInfo && options.widget.getVariableInfo(operator.operator);
if(variableInfo && variableInfo.srcVariable && variableInfo.srcVariable.isFunctionDefinition) {
var list = options.widget.evaluateVariable(operator.operator,{params: operator.operands, source: source});
if(operator.operator.indexOf(".") !== -1) {
var params = [];
$tw.utils.each(operator.operands,function(param) {
params.push({value: param});
});
var variableInfo = options.widget && options.widget.getVariableInfo && options.widget.getVariableInfo(operator.operator,{params: params, source: source});
if(variableInfo && variableInfo.srcVariable) {
var list = variableInfo.resultList ? variableInfo.resultList : [variableInfo.text];
if(operator.prefix === "!") {
var results = [];
source(function(tiddler,title) {

View File

@ -78,7 +78,7 @@ exports.parseTag = function(source,pos,options) {
orderedAttributes: []
};
// Define our regexps
var reTagName = /([a-zA-Z0-9\-\$]+)/g;
var reTagName = /([a-zA-Z0-9\-\$\.]+)/g;
// Skip whitespace
pos = $tw.utils.skipWhiteSpace(source,pos);
// Look for a less than sign
@ -138,7 +138,7 @@ exports.parseTag = function(source,pos,options) {
exports.findNextTag = function(source,pos,options) {
// A regexp for finding candidate HTML tags
var reLookahead = /<([a-zA-Z\-\$]+)/g;
var reLookahead = /<([a-zA-Z\-\$\.]+)/g;
// Find the next candidate
reLookahead.lastIndex = pos;
var match = reLookahead.exec(source);

View File

@ -0,0 +1,40 @@
/*\
title: $:/core/modules/parsers/wikiparser/rules/wikilinkprefix.js
type: application/javascript
module-type: wikirule
Wiki text inline rule for suppressed wiki links. For example:
```
~SuppressedLink
```
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.name = "wikilinkprefix";
exports.types = {inline: true};
exports.init = function(parser) {
this.parser = parser;
// Regexp to match
this.matchRegExp = new RegExp($tw.config.textPrimitives.unWikiLink + $tw.config.textPrimitives.wikiLink,"mg");
};
/*
Parse the most recent match
*/
exports.parse = function() {
// Get the details of the match
var linkText = this.match[0];
// Move past the wikilink
this.parser.pos = this.matchRegExp.lastIndex;
// Return the link without unwikilink character as plain text
return [{type: "text", text: linkText.substr(1)}];
};
})();

View File

@ -179,22 +179,7 @@ TranscludeWidget.prototype.getTransclusionTarget = function() {
if(variableInfo.text) {
if(srcVariable.isFunctionDefinition) {
// Function to return parameters by name or position
var fnGetParam = function(name,index) {
// Parameter names starting with dollar must be escaped to double dollars
if(name.charAt(0) === "$") {
name = "$" + name;
}
// Look for the parameter by name
if(self.hasAttribute(name)) {
return self.getAttribute(name);
// Look for the parameter by index
} else if(self.hasAttribute(index + "")) {
return self.getAttribute(index + "");
} else {
return undefined;
}
},
result = this.evaluateVariable(this.transcludeVariable,{params: fnGetParam})[0] || "";
var result = (variableInfo.resultList ? variableInfo.resultList[0] : variableInfo.text) || "";
parser = {
tree: [{
type: "text",

View File

@ -112,14 +112,18 @@ Get the prevailing value of a context variable
name: name of variable
options: see below
Options include
params: array of {name:, value:} for each parameter
defaultValue: default value if the variable is not defined
source: optional source iterator for evaluating function invocations
allowSelfAssigned: if true, includes the current widget in the context chain instead of just the parent
Returns an object with the following fields:
params: array of {name:,value:} of parameters passed to wikitext variables
params: array of {name:,value:} or {value:} of parameters to be applied
text: text of variable, with parameters properly substituted
resultList: result of variable evaluation as an array
srcVariable: reference to the object defining the variable
*/
Widget.prototype.getVariableInfo = function(name,options) {
options = options || {};
@ -135,7 +139,8 @@ Widget.prototype.getVariableInfo = function(name,options) {
if(variable) {
var originalValue = variable.value,
value = originalValue,
params = [];
params = [],
resultList = [value];
// Only substitute parameter and variable references if this variable was defined with the \define pragma
if(variable.isMacroDefinition) {
params = self.resolveVariableParameters(variable.params,actualParams);
@ -144,10 +149,28 @@ Widget.prototype.getVariableInfo = function(name,options) {
value = $tw.utils.replaceString(value,new RegExp("\\$" + $tw.utils.escapeRegExp(param.name) + "\\$","mg"),param.value);
});
value = self.substituteVariableReferences(value,options);
resultList = [value];
} else if(variable.isFunctionDefinition) {
// Function evaluations
params = self.resolveVariableParameters(variable.params,actualParams);
var variables = Object.create(null);
// Apply default parameter values
$tw.utils.each(variable.params,function(param,index) {
if(param["default"]) {
variables[param.name] = param["default"];
}
});
// Parameters are an array of {value:} or {name:, value:} pairs
$tw.utils.each(params,function(param) {
variables[param.name] = param.value;
});
resultList = this.wiki.filterTiddlers(value,this.makeFakeWidgetWithVariables(variables),options.source);
value = resultList[0] || "";
}
return {
text: value,
params: params,
resultList: resultList,
srcVariable: variable,
isCacheable: originalValue === value
};
@ -159,6 +182,7 @@ Widget.prototype.getVariableInfo = function(name,options) {
}
return {
text: text,
resultList: [text],
srcVariable: {}
};
};
@ -317,62 +341,11 @@ Widget.prototype.makeFakeWidgetWithVariables = function(variables) {
};
},
makeFakeWidgetWithVariables: self.makeFakeWidgetWithVariables,
evaluateVariable: self.evaluateVariable,
resolveVariableParameters: self.resolveVariableParameters,
wiki: self.wiki
};
};
/*
Evaluate a variable and associated actual parameters and return the resulting array.
The way that the variable is evaluated depends upon its type:
* Functions are evaluated as parameterised filter strings
* Macros are returned as plain text with substitution of parameters
* Procedures and widgets are returned as plain text
Options are:
params - the actual parameters may be one of:
* an array of values that may be an anonymous string value, or a {name:, value:} pair
* a hashmap of {name: value} pairs
* a function invoked with parameters (name,index) that returns a parameter value by name or position
source - iterator for source tiddlers
*/
Widget.prototype.evaluateVariable = function(name,options) {
options = options || {};
var params = options.params || [];
// Get the details of the variable (includes processing text substitution for macros
var variableInfo = this.getVariableInfo(name,{params: params,defaultValue: ""});
// Process function parameters
var variables = Object.create(null);
if(variableInfo.srcVariable && variableInfo.srcVariable.isFunctionDefinition) {
// Apply default parameter values
$tw.utils.each(variableInfo.srcVariable.params,function(param,index) {
if(param["default"]) {
variables[param.name] = param["default"];
}
});
if($tw.utils.isArray(params)) {
// Parameters are an array of values or {name:, value:} pairs
$tw.utils.each(this.resolveVariableParameters(variableInfo.srcVariable.params,params),function(param) {
variables[param.name] = param.value;
});
} else if(typeof params === "function") {
// Parameters are passed via a function
$tw.utils.each(variableInfo.srcVariable.params,function(param,index) {
variables[param.name] = params(param.name,index) || param["default"] || "";
});
} else {
// Parameters are a hashmap
$tw.utils.each(params,function(value,name) {
variables[name] = value;
});
}
return this.wiki.filterTiddlers(variableInfo.text,this.makeFakeWidgetWithVariables(variables),options.source);
} else {
return [variableInfo.text];
}
};
/*
Compute the current values of the attributes of the widget. Returns a hashmap of the names of the attributes that have changed.
Options include:
@ -406,13 +379,7 @@ Widget.prototype.computeAttribute = function(attribute) {
value = this.wiki.getTextReference(attribute.textReference,"",this.getVariable("currentTiddler")) || "";
} else if(attribute.type === "macro") {
var variableInfo = this.getVariableInfo(attribute.value.name,{params: attribute.value.params});
if(variableInfo.srcVariable && variableInfo.srcVariable.isFunctionDefinition) {
// It is a function definition. Go through each of the defined parameters, and make a variable with the value of the corresponding provided parameter
var paramArray = this.resolveVariableParameters(variableInfo.srcVariable.params,attribute.value.params);
value = this.evaluateVariable(attribute.value.name,{params: paramArray})[0] || "";
} else {
value = variableInfo.text;
}
value = variableInfo.text;
} else { // String attribute
value = attribute.value;
}
@ -546,8 +513,8 @@ Widget.prototype.makeChildWidget = function(parseTreeNode,options) {
var variableDefinitionName = "$" + parseTreeNode.type;
if(this.variables[variableDefinitionName]) {
var isOverrideable = function() {
// Widget is overrideable if it has a double dollar user defined name, or if it is an existing JS widget and we're not in safe mode
return parseTreeNode.type.charAt(0) === "$" || (!!self.widgetClasses[parseTreeNode.type] && !$tw.safeMode);
// Widget is overrideable if its name contains a period, or if it is an existing JS widget and we're not in safe mode
return parseTreeNode.type.indexOf(".") !== -1 || (!!self.widgetClasses[parseTreeNode.type] && !$tw.safeMode);
};
if(!parseTreeNode.isNotRemappable && isOverrideable()) {
var variableInfo = this.getVariableInfo(variableDefinitionName,{allowSelfAssigned: true});
@ -844,6 +811,20 @@ Widget.prototype.findChildrenDataWidgets = function(children,tag,callback) {
});
};
/*
Evaluate a variable with parameters. This is a static convenience method that attempts to evaluate a variable as a function, returning an array of strings
*/
Widget.evaluateVariable = function(widget,name,options) {
var result;
if(widget.getVariableInfo) {
var variableInfo = widget.getVariableInfo(name,options);
result = variableInfo.resultList || [variableInfo.text];
} else {
result = [widget.getVariable(name)];
}
return result;
};
exports.widget = Widget;
})();

View File

@ -2,18 +2,6 @@ title: $:/core/ui/ControlPanel/Settings
tags: $:/tags/ControlPanel
caption: {{$:/language/ControlPanel/Settings/Caption}}
\define lingo-base() $:/language/ControlPanel/Settings/
<<lingo Hint>>
<$list filter="[all[shadows+tiddlers]tag[$:/tags/ControlPanel/Settings]]">
<div style="border-top:1px solid #eee;">
!! <$link><$transclude field="caption"/></$link>
<$transclude/>
</div>
</$list>
<div class="tc-control-panel">
<$macrocall $name="tabs" tabsList="[all[shadows+tiddlers]tag[$:/tags/ControlPanel/SettingsTab]!has[draft.of]]" default="$:/core/ui/ControlPanel/Settings/TiddlyWiki" explicitState="$:/state/tab--697582678"/>
</div>

View File

@ -1,6 +1,7 @@
title: $:/core/ui/ControlPanel/Settings/TiddlyWiki
tags: $:/tags/ControlPanel/SettingsTab
caption: TiddlyWiki
list-before:
\define lingo-base() $:/language/ControlPanel/Settings/

View File

@ -14,8 +14,8 @@ color:$(foregroundColor)$;
\define tag-body-inner(colour,fallbackTarget,colourA,colourB,icon,tagField:"tags")
\whitespace trim
<$vars foregroundColor=<<contrastcolour target:"""$colour$""" fallbackTarget:"""$fallbackTarget$""" colourA:"""$colourA$""" colourB:"""$colourB$""">> backgroundColor="""$colour$""">
<span style=<<tag-styles>> class="tc-tag-label tc-tag-list-item tc-small-gap-right">
<$transclude tiddler="""$icon$"""/><$view field="title" format="text" />
<span style=<<tag-styles>> class="tc-tag-label tc-tag-list-item tc-small-gap-right" data-tag-title=<<currentTiddler>>>
<$transclude tiddler="""$icon$"""/><$view field="title" format="text"/>
<$button class="tc-btn-invisible tc-remove-tag-button" style=<<tag-styles>>><$action-listops $tiddler=<<saveTiddler>> $field=<<__tagField__>> $subfilter="-[{!!title}]"/>{{$:/core/images/close-button}}</$button>
</span>
</$vars>

View File

@ -15,7 +15,7 @@ title: $:/core/ui/TagPickerTagTemplate
<<actions>>
<$set name="backgroundColor" value={{{ [<currentTiddler>] :cascade[all[shadows+tiddlers]tag[$:/tags/TiddlerColourFilter]!is[draft]get[text]] }}}>
<$wikify name="foregroundColor" text="""<$macrocall $name="contrastcolour" target=<<backgroundColor>> fallbackTarget=<<fallbackTarget>> colourA=<<colourA>> colourB=<<colourB>>/>""">
<span class="tc-tag-label tc-btn-invisible" style=<<tag-pill-styles>>>
<span class="tc-tag-label tc-btn-invisible" style=<<tag-pill-styles>> data-tag-title=<<currentTiddler>> >
{{||$:/core/ui/TiddlerIcon}}<$view field="title" format="text"/>
</span>
</$wikify>

View File

@ -1,3 +1,3 @@
title: $:/config/WikiParserRules/Inline/wikilink
enable
disable

View File

@ -2,7 +2,7 @@ modified: 20141013085608911
tags: Mechanisms
title: TestingMechanism
TiddlyWiki5 incorporates the Jasmine JavaScript testing framework (see http://pivotal.github.io/jasmine/). It allows the same tests to be run both in the browser and under Node.js.
TiddlyWiki5 incorporates the Jasmine JavaScript testing framework (see https://jasmine.github.io/). It allows the same tests to be run both in the browser and under Node.js.
! TiddlyWiki5 Testing Components

View File

@ -0,0 +1,3 @@
title: $:/config/WikiParserRules/Inline/wikilink
enable

View File

@ -6,7 +6,7 @@ type: text/vnd.tiddlywiki
TiddlyWiki incorpora código de los siguientes proyectos OpenSource:
* [[The Stanford Javascript Crypto Library|http://bitwiseshiftleft.github.io/sjcl/]]
* [[The Jasmine JavaScript Test Framework|http://pivotal.github.io/jasmine/]]
* [[The Jasmine JavaScript Test Framework|https://jasmine.github.io/]]
* [[Normalize.css by Nicolas Gallagher|http://necolas.github.io/normalize.css/]]
...y materiales de estos otros proyectos:

View File

@ -6,7 +6,7 @@ type: text/vnd.tiddlywiki
TiddlyWiki intègre du code provenant de ces excellents projets OpenSource<<dp>>
* [[The Stanford Javascript Crypto Library|http://bitwiseshiftleft.github.io/sjcl/]]
* [[The Jasmine JavaScript Test Framework|http://pivotal.github.io/jasmine/]]
* [[The Jasmine JavaScript Test Framework|https://jasmine.github.io/]]
* [[Normalize.css by Nicolas Gallagher|http://necolas.github.io/normalize.css/]]
Et des contenus provenenant de ces sources<<dp>>

View File

@ -8,6 +8,6 @@ Tiddlers can contain formatted text:
Formatting is typed with special codes:
<$edit-text tiddler="FormattingDemoText" class="tc-edit-texteditor" minHeight="10px"/>
<$edit-text tiddler="FormattingDemoText" class="tc-edit-texteditor" minHeight="100px"/>
TiddlyWiki is not just for text. [[Images]] are first class citizens, too.

View File

@ -49,14 +49,6 @@
],
"build": {
"index": [
"--rendertiddler","$:/core/save/all","index.html","text/plain"],
"favicon": [
"--savetiddler","$:/favicon.ico","favicon.ico",
"--savetiddler","$:/green_favicon.ico","static/favicon.ico"],
"static": [
"--rendertiddler","$:/core/templates/static.template.html","static.html","text/plain",
"--rendertiddler","$:/core/templates/alltiddlers.template.html","alltiddlers.html","text/plain",
"--rendertiddlers","[!is[system]]","$:/core/templates/static.tiddler.html","static","text/plain",
"--rendertiddler","$:/core/templates/static.template.css","static/static.css","text/plain"]
"--rendertiddler","$:/core/save/all","index.html","text/plain"]
}
}

View File

@ -30,10 +30,15 @@ These changes lay the groundwork for macros and related features to be deprecate
The new transclusion architecture is not by itself sufficient to enable us to fully deprecate macros yet. To handle the remaining use cases we propose a new backtick quoted attribute format that allows for the substitution of variable values. See https://github.com/Jermolene/TiddlyWiki5/issues/6663 for details.
! Defaulting to Disabling CamelCase Links
<<.link-badge-updated "https://github.com/Jermolene/TiddlyWiki5/pull/7513">> CamelCase linking is now disabled by default. (Note that this wiki has CamelCase linking explicitly enabled)
! Plugin Improvements
* <<.link-badge-extended "https://github.com/Jermolene/TiddlyWiki5/pull/7260">> Dynannotate pugin to support three additional search modes
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/7365">> problem with [[BrowserStorage Plugin]] unnecessarily saving shadow tiddlers
* <<.link-badge-improved "https://github.com/Jermolene/TiddlyWiki5/pull/7493">> [[CodeMirror Plugin]] to add an option to make trailing spaces visible
! Translation improvement
@ -55,8 +60,10 @@ Improvements to the following translations:
! Filter improvements
* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/7511"> new [[deserialize Operator]] for converting various textual representations of tiddlers into JSON data
* <<.link-badge-extended "https://github.com/Jermolene/TiddlyWiki5/pull/7292">> [[format Operator]] to support converting Unix timestamps to TiddlyWiki's native date format
! Hackability Improvements
* <<.link-badge-extended "https://github.com/Jermolene/TiddlyWiki5/pull/7413">> [[Core Icons]] to allow the size to be controlled with a parameter
@ -73,6 +80,10 @@ Improvements to the following translations:
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/7401">> bug whereby scrolling occurs if the linkcatcher widget triggers an action-navigate and the $scroll attribute is set to "no"
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/7409">> problem switching between LTR and RTL text
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/7448">> bug when checkbox widget's listField attribute was given the name of a date field (like <<.field created>> or <<.field modified>>)
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/issues/7529">> size of buttons in dropdown for editor "link" toolbar button
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/commit/8e132948b6bec623d81d300fbe6dc3a0307bcc6d">> crash when transcluding a lazily loaded tiddler as an attribute value
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/issues/7462">> DiffTextWidget crash with missing or empty attributes
* <<.link-badge-improved "https://github.com/Jermolene/TiddlyWiki5/pull/7448">> CheckboxWidget to avoid writing to date fields
! Developer Improvements
@ -80,7 +91,9 @@ Improvements to the following translations:
! Node.js Improvements
* <<.link-badge-extended "https://github.com/Jermolene/TiddlyWiki5/pull/7471">> [[WebServer Parameter: authenticated-user-header]] to require URI encoding of authenticated username header, permitting non-ASCII characters in usernames
* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/7253">> support for `filepath` source attribute to [[tiddlywiki.files Files]]
* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/commit/48b22abdaab62c281c207127c66883b50898f9dd">> a warning message for JSON errors in [[tiddlywiki.info Files]] or [[plugin.info Files|PluginFolders]]
! Performance Improvements
@ -92,17 +105,22 @@ Improvements to the following translations:
<<.contributors """
Arlen22
BramChen
btheado
donmor
flibbles
GameDungeon
JoshuaFontany
kookma
linonetwo
Marxsal
mateuszwilczek
michsa
muzimuzhi
pmario
rmunn
saqimtiaz
tavin
twMat
yaisog
""">>

View File

@ -0,0 +1,3 @@
title: $:/config/WikiParserRules/Inline/wikilink
enable

View File

@ -0,0 +1,8 @@
title: dezerializer test data case 6
type: application/json
[
{"created":"20230601125557184","text":"Before you start storing important information in ~TiddlyWiki it is vital to make sure that you can reliably save changes. See https://tiddlywiki.com/#GettingStarted for details\n\n","title":"GettingStarted","modified":"20230601125601619"},
{"created":"20230601125507054","text":"Welcome to \"TiddlyWiki\".\n\nThis is a test tiddler.","tags":"","title":"Hello There \"Welcome\"","modified":"20230601125551144"},
{"title":"TiddlyWiki","created":"20130822170700000","modified":"20170127221451610","tags":"Concepts","type":"text/vnd.tiddlywiki","text":"~TiddlyWiki is a rich, interactive tool for manipulating complex data with structure that doesn't easily fit into conventional tools like spreadsheets or wordprocessors.\n\n~TiddlyWiki is designed to fit around your brain, helping you deal with the things that won't fit."}
]

View File

@ -12,15 +12,15 @@ title: Output
title: Actions
\whitespace trim
<!-- Define the <$$action-mywidget> widget by defining a transcludable variable with that name -->
\widget $$action-mywidget(one:'Jaguar')
<!-- Define the <$action.mywidget> widget by defining a transcludable variable with that name -->
\widget $action.mywidget(one:'Jaguar')
\whitespace trim
<$action-setfield $tiddler="Result" $field="text" $value=<<one>>/>
\end
<$$action-mywidget one="Dingo">
<$action.mywidget one="Dingo">
Crocodile
</$$action-mywidget>
</$action.mywidget>
+
title: ExpectedResult

View File

@ -12,21 +12,21 @@ title: Output
title: TiddlerOne
\whitespace trim
<!-- Define the <$$mywidget> widget by defining a transcludable variable with that name -->
\widget $$mywidget(one:'Jaguar')
<!-- Define the <$my.widget> widget by defining a transcludable variable with that name -->
\widget $my.widget(one:'Jaguar')
\whitespace trim
<$text text=<<one>>/>
<$slot $name="ts-raw">
Whale
</$slot>
\end
<$$mywidget one="Dingo">
<$my.widget one="Dingo">
Crocodile
</$$mywidget>
<$$mywidget one="BumbleBee">
</$my.widget>
<$my.widget one="BumbleBee">
Squirrel
</$$mywidget>
<$$mywidget/>
</$my.widget>
<$my.widget/>
+
title: ExpectedResult

View File

@ -6,13 +6,13 @@ tags: [[$:/tags/wiki-test-spec]]
title: Output
\whitespace trim
\widget $$mywidget()
\widget $my.widget()
<$slot $name=ts-raw>the body is empty</$slot>
\end
#<$$mywidget/>
#<$$mywidget></$$mywidget>
#<$$mywidget>the body is not empty</$$mywidget>
#<$my.widget/>
#<$my.widget></$my.widget>
#<$my.widget>the body is not empty</$my.widget>
+
title: ExpectedResult

View File

@ -6,21 +6,21 @@ tags: [[$:/tags/wiki-test-spec]]
title: Output
\whitespace trim
\widget $$mywidget(one:'Jaguar')
\widget $my.widget(one:'Jaguar')
\whitespace trim
<$text text=<<one>>/>
<$slot $name="ts-stuff">
Whale
</$slot>
\end
<$$mywidget one="Dingo">
<$my.widget one="Dingo">
<$fill $name="ts-stuff">
Crocodile
</$fill>
</$$mywidget>
<$$mywidget one="BumbleBee">
</$my.widget>
<$my.widget one="BumbleBee">
Squirrel
</$$mywidget>
</$my.widget>
+
title: ExpectedResult

View File

@ -12,17 +12,17 @@ title: Output
title: TiddlerOne
\whitespace trim
<!-- Redefine the <$$mywidget> widget by defining a transcludable variable with that name -->
\widget $$mywidget($variable:'Jaguar')
<!-- Redefine the <$my.widget> widget by defining a transcludable variable with that name -->
\widget $my.widget($variable:'Jaguar')
\whitespace trim
<$text text=<<$variable>>/>
<$slot $name="ts-raw">
Whale
</$slot>
\end
<$$mywidget $variable="Dingo">
<$my.widget $variable="Dingo">
Crocodile
</$$mywidget>
</$my.widget>
+
title: ExpectedResult

View File

@ -0,0 +1,44 @@
/*\
title: test-deserialize-operator.js
type: application/javascript
tags: [[$:/tags/test-spec]]
Tests deserialize[] filter operator with various core deserializers
\*/
(function(){
/* jslint node: true, browser: true */
/* eslint-env node, browser, jasmine */
/* eslint no-mixed-spaces-and-tabs: ["error", "smart-tabs"]*/
/* global $tw, require */
"use strict";
describe("deserialize operator tests", function() {
it("should support the deserialize[] operator", function() {
//Unknown deserializer as operand
expect($tw.wiki.filterTiddlers("[{dezerializer test data case 4}deserialize[unknown/deserializer]]")).toEqual([$tw.language.getString("Error/DeserializeOperator/UnknownDeserializer")]);
//Missing operand
expect($tw.wiki.filterTiddlers("[{dezerializer test data case 4}deserialize[]]")).toEqual([$tw.language.getString("Error/DeserializeOperator/MissingOperand")]);
//Deserialize TiddlyWiki file
expect($tw.wiki.filterTiddlers("[{dezerializer test data case 4}deserialize[text/html]]")).toEqual(['[{"type":"text/vnd.tiddlywiki","text":"Abacus","title":"Hello \\"There\\""},{"title":"Hello \\"There\\"","text":"Calculator"}]']);
expect($tw.wiki.filterTiddlers("[{dezerializer test data case 5}deserialize[text/html]]")).toEqual(['[{"type":"text/vnd.tiddlywiki","text":"Abacus","title":"Hello \\"There\\""},{"title":"Hello \\"There\\"","text":"Calculator"},{"title":"Hello \\"There\\"","text":"Protractor"}]']);
// Deserialize JSON payload containing tiddlers
expect($tw.wiki.filterTiddlers("[{dezerializer test data case 6}deserialize[application/json]]")).toEqual( [ `[{"created":"20230601125557184","text":"Before you start storing important information in ~TiddlyWiki it is vital to make sure that you can reliably save changes. See https://tiddlywiki.com/#GettingStarted for details\\n\\n","title":"GettingStarted","modified":"20230601125601619"},{"created":"20230601125507054","text":"Welcome to \\"TiddlyWiki\\".\\n\\nThis is a test tiddler.","tags":"","title":"Hello There \\"Welcome\\"","modified":"20230601125551144"},{"title":"TiddlyWiki","created":"20130822170700000","modified":"20170127221451610","tags":"Concepts","type":"text/vnd.tiddlywiki","text":"~TiddlyWiki is a rich, interactive tool for manipulating complex data with structure that doesn't easily fit into conventional tools like spreadsheets or wordprocessors.\\n\\n~TiddlyWiki is designed to fit around your brain, helping you deal with the things that won't fit."}]` ]);
expect($tw.wiki.filterTiddlers("[{dezerializer test data case 6}deserialize[application/json]jsonindexes[]] :map[{dezerializer test data case 6}jsonget<currentTiddler>,[title]]")).toEqual([ 'GettingStarted', 'Hello There "Welcome"', 'TiddlyWiki' ]);
//Deserialize TiddlyWiki file with an mismatched deserializer
expect($tw.wiki.filterTiddlers("[{dezerializer test data case 5}deserialize[application/json]]")).toEqual([jasmine.stringMatching('JSON error')]);
});
});
})();

View File

@ -99,14 +99,14 @@ Tests the filtering mechanism.
},
"TiddlerSix": {
title: "TiddlerSix",
text: "Missing inaction from TiddlerOne",
text: "Missing inaction from [[TiddlerOne]]",
filter: "[[one]] [[a a]] [subfilter{hasList!!list}]",
tags: []
},
"TiddlerSeventh": {
title: "TiddlerSeventh",
text: "",
list: "TiddlerOne [[Tiddler Three]] [[a fourth tiddler]] MissingTiddler",
list: "[[TiddlerOne]] [[Tiddler Three]] [[a fourth tiddler]] [[MissingTiddler]]",
tags: ["one"]
},
"Tiddler8": {
@ -144,7 +144,7 @@ Tests the filtering mechanism.
modified: "201304152211"
},{
title: "Tiddler Three",
text: "The speed of sound in light\n\nThere is no TiddlerZero but TiddlerSix",
text: "The speed of sound in light\n\nThere is no [[TiddlerZero]] but [[TiddlerSix]]",
tags: ["one","two"],
cost: "56",
value: "80",
@ -252,9 +252,9 @@ Tests the filtering mechanism.
});
it("should handle the lookup operator", function() {
expect(wiki.filterTiddlers("Six Seventh 8 +[lookup[Tiddler]]").join(",")).toBe("Missing inaction from TiddlerOne,,Tidd");
expect(wiki.filterTiddlers("Six Seventh 8 +[lookup:8[Tiddler]]").join(",")).toBe("Missing inaction from TiddlerOne,8,Tidd");
expect(wiki.filterTiddlers("Six Seventh 8 +[lookup:8[Tiddler],[text]]").join(",")).toBe("Missing inaction from TiddlerOne,8,Tidd");
expect(wiki.filterTiddlers("Six Seventh 8 +[lookup[Tiddler]]").join(",")).toBe("Missing inaction from [[TiddlerOne]],,Tidd");
expect(wiki.filterTiddlers("Six Seventh 8 +[lookup:8[Tiddler]]").join(",")).toBe("Missing inaction from [[TiddlerOne]],8,Tidd");
expect(wiki.filterTiddlers("Six Seventh 8 +[lookup:8[Tiddler],[text]]").join(",")).toBe("Missing inaction from [[TiddlerOne]],8,Tidd");
expect(wiki.filterTiddlers("Six Seventh 8 +[lookup[Tiddler],[tags]]").join(",")).toBe(",one,one");
});
@ -990,10 +990,10 @@ Tests the filtering mechanism.
expect(wiki.filterTiddlers("[!sortsub:number<sort1>]",anchorWidget).join(",")).toBe("filter regexp test,a fourth tiddler,$:/ShadowPlugin,$:/TiddlerTwo,Tiddler Three,has filter,TiddlerOne,hasList,one");
expect(wiki.filterTiddlers("[sortsub:string<sort1>]",anchorWidget).join(",")).toBe("has filter,TiddlerOne,$:/TiddlerTwo,Tiddler Three,$:/ShadowPlugin,a fourth tiddler,filter regexp test,one,hasList");
expect(wiki.filterTiddlers("[!sortsub:string<sort1>]",anchorWidget).join(",")).toBe("hasList,one,filter regexp test,a fourth tiddler,$:/ShadowPlugin,$:/TiddlerTwo,Tiddler Three,has filter,TiddlerOne");
expect(wiki.filterTiddlers("[sortsub:number<sort2>]",anchorWidget).join(",")).toBe("one,TiddlerOne,hasList,has filter,a fourth tiddler,Tiddler Three,$:/TiddlerTwo,filter regexp test,$:/ShadowPlugin");
expect(wiki.filterTiddlers("[!sortsub:number<sort2>]",anchorWidget).join(",")).toBe("$:/ShadowPlugin,filter regexp test,$:/TiddlerTwo,Tiddler Three,a fourth tiddler,has filter,hasList,TiddlerOne,one");
expect(wiki.filterTiddlers("[sortsub:string<sort2>]",anchorWidget).join(",")).toBe("one,TiddlerOne,hasList,has filter,$:/ShadowPlugin,a fourth tiddler,Tiddler Three,$:/TiddlerTwo,filter regexp test");
expect(wiki.filterTiddlers("[!sortsub:string<sort2>]",anchorWidget).join(",")).toBe("filter regexp test,$:/TiddlerTwo,Tiddler Three,a fourth tiddler,$:/ShadowPlugin,has filter,hasList,TiddlerOne,one");
expect(wiki.filterTiddlers("[sortsub:number<sort2>]",anchorWidget).join(",")).toBe("one,TiddlerOne,hasList,has filter,a fourth tiddler,$:/TiddlerTwo,Tiddler Three,filter regexp test,$:/ShadowPlugin");
expect(wiki.filterTiddlers("[!sortsub:number<sort2>]",anchorWidget).join(",")).toBe("$:/ShadowPlugin,filter regexp test,Tiddler Three,$:/TiddlerTwo,a fourth tiddler,has filter,hasList,TiddlerOne,one");
expect(wiki.filterTiddlers("[sortsub:string<sort2>]",anchorWidget).join(",")).toBe("one,TiddlerOne,hasList,has filter,$:/ShadowPlugin,a fourth tiddler,$:/TiddlerTwo,Tiddler Three,filter regexp test");
expect(wiki.filterTiddlers("[!sortsub:string<sort2>]",anchorWidget).join(",")).toBe("filter regexp test,Tiddler Three,$:/TiddlerTwo,a fourth tiddler,$:/ShadowPlugin,has filter,hasList,TiddlerOne,one");
expect(wiki.filterTiddlers("[[TiddlerOne]] [[$:/TiddlerTwo]] [[Tiddler Three]] [[a fourth tiddler]] +[!sortsub:number<sort3>]",anchorWidget).join(",")).toBe("$:/TiddlerTwo,Tiddler Three,TiddlerOne,a fourth tiddler");
expect(wiki.filterTiddlers("a1 a10 a2 a3 b10 b3 b1 c9 c11 c1 +[sortsub:alphanumeric<sort4>]",anchorWidget).join(",")).toBe("a1,a2,a3,a10,b1,b3,b10,c1,c9,c11");
// #7155. The order of the output is the same as the input when an undefined variable is used in the subfitler

View File

@ -45,16 +45,6 @@ describe("WikiText tests", function() {
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%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);
expect(wiki.renderText("text/html","text/vnd-tiddlywiki","One WikiLink here").indexOf("<a") !== -1).toBe(true);
expect(wiki.renderText("text/html","text/vnd-tiddlywiki","No Wiki-Link here").indexOf("<a") !== -1).toBe(false);
expect(wiki.renderText("text/html","text/vnd-tiddlywiki","No Wiki×Link here").indexOf("<a") !== -1).toBe(false);
expect(wiki.renderText("text/html","text/vnd-tiddlywiki","No Wiki÷Link here").indexOf("<a") !== -1).toBe(false);
expect(wiki.renderText("text/html","text/vnd-tiddlywiki","No xWikiLink here").indexOf("<a") !== -1).toBe(false);
expect(wiki.renderText("text/html","text/vnd-tiddlywiki","No -WikiLink here").indexOf("<a") !== -1).toBe(false);
expect(wiki.renderText("text/html","text/vnd-tiddlywiki","No _WikiLink here").indexOf("<a") !== -1).toBe(false);
});
it("handles style wikitext notation", function() {
expect(wiki.renderText("text/html","text/vnd-tiddlywiki","@@.myclass\n!header\n@@")).toBe("<h1 class=\"myclass\">header</h1>");
expect(wiki.renderText("text/html","text/vnd-tiddlywiki","@@.myclass\n<div>\n\nContent</div>\n@@")).toBe("<div class=\"myclass\"><p>Content</p></div>");

View File

@ -0,0 +1,26 @@
caption: deserialize
created: 20230601195749377
from-version: 5.3.0
modified: 20230602105513132
op-input: a selection of strings
op-output: JSON representations of tiddlers extracted from input titles.
op-parameter: the deserializer module to be used to extract tiddlers from the input
op-purpose: extract JSON representation of tiddlers from the input strings
tags: [[Filter Operators]] [[Special Operators]]
title: deserialize Operator
type: text/vnd.tiddlywiki
<<.tip "Deserializer modules parse text in various formats into their JSON representation as tiddlers. You can see the deserializers available in a wiki using the [[deserializers operator|deserializers Operator]].">>
|!Deserializer |!Description |
|(DOM)|Extracts tiddlers from a DOM node, should not be used with the <<.op deserialize[]>> operator |
|application/javascript|Parses a JavaScript module as a tiddler extracting fields from the header comment|
|application/json|Parses [[JSON|JSON in TiddlyWiki]] into tiddlers|
|application/x-tiddler|Parses the [[.tid file format|TiddlerFiles]] as a tiddler|
|application/x-tiddler-html-div|Parses the [[<DIV>.tiddler file format|TiddlerFiles]] as a tiddler|
|application/x-tiddlers|Parses the [[MultiTiddlerFile format|MultiTiddlerFiles]] as tiddlers|
|text/css|Parses CSS as a tiddler extracting fields from the header comment|
|text/html|Parses an HTML file into tiddlers. Supports ~TiddlyWiki Classic HTML files, ~TiddlyWiki5 HTML files and ordinary HTML files|
|text/plain|Parses plain text as a tiddler|
<<.operator-examples "deserialize">>

View File

@ -0,0 +1,29 @@
created: 20230601200356736
modified: 20230602105036887
tags: [[Operator Examples]] [[deserialize Operator]]
title: deserialize Operator (Examples)
type: text/vnd.tiddlywiki
\define html-data()
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Test Data</title>
</head>
<body>
<!--~~ Ordinary tiddlers ~~-->
<div id="storeArea" style="display:none;"><div title="Hello &quot;There&quot;" type="text/vnd.tiddlywiki">
<pre>Abacus</pre>
</div>
</div>
<script class="tiddlywiki-tiddler-store" type="application/json">[{"title":"Hello \"There\"","text":"Calculator"},{"title":"Hello \"There\"","text":"Protractor"}]</script>
</body>
</html>
\end
This example uses the predefined variable `html-data`:
<$codeblock code=<<html-data>> language="HTML"/>
<<.operator-example 1 "[<html-data>deserialize[text/html]]">>

View File

@ -21,7 +21,7 @@ Functions can be invoked in several ways:
* Directly transclude functions with the syntax `<<myfn param:"value">>`
* Assign functions to widget attributes with the syntax `<div class=<<myfn param:"value">>>`
* Invoke functions via the [[function Operator]] with the syntax `[function[myfn],[value],...]`
* Directly invoke functions whose names start with a period as custom filter operators with the syntax `[.myfn[value]]`
* Directly invoke functions whose names contain a period as custom filter operators with the syntax `[my.fn[value]]` or `[.myfn[value]]`
!! How Functions Work

View File

@ -0,0 +1,32 @@
created: 20230608121519758
modified: 20230608123444591
tags: [[How to apply custom styles]]
title: Custom tag pill styles
type: text/vnd.tiddlywiki
! Attribute: data-tag-title
<<.from-version "5.2.0">> The attribute <<.attr data-tag-title>> was added to tag pills visible in the tiddler view template.
<<.from-version "5.3.0">> The attribute was added to every tag pill visible in the standard ~TiddlyWiki UI. Especially the edit template tag list, the tag-picker dropdown, the Right sidebar -> More -> Tags tab and the $:/TagManager
The <<.attr data-tag-title>> HTML attribute only contains the tag-title visible in the tag pill. It can be used to style the tag-pill.
If you want to style the whole tiddler have a look at: [[Custom styles by data-tiddler-title]]
!! Examples
If you use the following CSS in a new tiddler tagged: `$:/tags/Stylesheet` every tag that starts with a `#` will have a new border radius. So those tags stand out in contrast to the default tags.
''You have to define both CSS rules'', due to the existing UI structure to catch all tag-pills in the existing TW UI.
```
[data-tag-title^="#"] .tc-tag-label,
[data-tag-title^="#"].tc-tag-label {
border-radius: 3px;
}
```
!! More Possibilities
{{Attribute Selectors}}

View File

@ -3,6 +3,7 @@ modified: 20220301180818011
tags: Messages
title: WidgetMessage: tm-close-all-windows
type: text/vnd.tiddlywiki
caption: tm-close-all-windows
<<.from-version 5.2.2>>
The `tm-close-all-windows` [[message|Messages]] closes all additional //browser// window that were opened with [[tm-open-window|WidgetMessage: tm-open-window]].

View File

@ -0,0 +1,3 @@
title: $:/config/WikiParserRules/Inline/wikilink
enable

View File

@ -1,6 +1,6 @@
created: 20150203173506000
list-before: $:/core/ui/ViewTemplate/body
modified: 20220316121232243
modified: 20230602181119360
tags: $:/tags/ViewTemplate
title: $:/editions/tw5.com/operator-template
@ -72,10 +72,10 @@ title: $:/editions/tw5.com/operator-template
<!-- -->
</table>
[[Learn more about how to use Filters|Filters]]
<p>[[Learn more about how to use Filters|Filters]]</p>
<$list filter="[all[current]has[from-version]]" variable="listItem">
<$macrocall $name=".from-version" version={{!!from-version}}/>
<p><$macrocall $name=".from-version" version={{!!from-version}}/></p>
</$list>
</$list>
</$set>

View File

@ -150,5 +150,5 @@ Below is an example macro, procedure and function definition. All three forms o
*''tiddler titles'' - tiddlers are uniquely identified by their title. The namespace for tiddler titles and variable names are completely separate.
*''variables'' - \define, <<.wlink SetWidget>>, <<.wlink LetWidget>>, <<.wlink VarsWidget>>, \procedure, \widget, \function all create variables. If the same name is used, then later define will overwrite earlier defined
*''<<.op function>> filter operator parameter'' - only variables defined using \function can be called using the <<.olink function>> operator
*''filter operators'' - only the [[javascript defined filter operators|Filter Operators]] and variables defined using \function with name starting with a dot can be called
*''filter operators'' - only the [[javascript defined filter operators|Filter Operators]] and variables defined using \function with name containing a dot can be called
*''widgets'' - variables defined using \widget can be invoked using `<$widget/>` syntax ONLY if the name starts a dollar sign (to override existing javascript defined widgets) or double dollar sign (to define [[custom widgets|Custom Widgets]]). Without the dollar sign prefix, defining variables using \widget is no different than using \procedure.

View File

@ -15,26 +15,21 @@ Custom widgets can also be used to override built-in JavaScript widgets to custo
Custom widgets are usually defined with the [[Pragma: \widget]]:
```
\widget $$my-widget(attribute:"Default value")
\widget $my.widget(attribute:"Default value")
This is the widget, and the attribute is <<attribute>>.
\end
```
The name of the widget must start with one or two dollar signs:
* A ''single dollar sign'' is used to override existing core widgets
** for example, `$text` or `$codeblock`
* ''Double dollar signs'' are used to define a custom widget
** for example, `$$mywidget` or `$$acme-logger`
The name of the widget must start with a dollar sign. If it is a user defined widget that does not override an existing widget then it must include at least one period (dot) within the name (for example `$my.widget` or `$acme.logger`).
!! Using Custom Widgets
Custom widgets are called in the same way as ordinary built-in widgets:
```
<$my-widget/>
<$my.widget/>
<$my-widget attribute="The parameter"/>
<$my.widget attribute="The parameter"/>
```
The attributes that are specified in the widget call are made available as parameter variables.
@ -45,18 +40,18 @@ Within the definition of a custom widget the content of the calling widget is av
For example:
<<wikitext-example-without-html """\widget $$mywidget(one:'Jaguar')
<<wikitext-example-without-html """\widget $my.widget(one:'Jaguar')
<$text text=<<one>>/>
<$slot $name="ts-raw">
Whale
</$slot>
\end
<$$mywidget one="Dingo">
<$my.widget one="Dingo">
Crocodile
</$$mywidget>
</$my.widget>
<$$mywidget/>""">>
<$my.widget/>""">>
!! How Custom Widgets Work

View File

@ -25,6 +25,8 @@ Encryption/RepeatPassword: 重复输入密码
Encryption/PasswordNoMatch: 密码不匹配
Encryption/SetPassword: 设定密码
Error/Caption: 错误
Error/DeserializeOperator/MissingOperand: 筛选器错误:'deserialize' 运算符缺少运算元
Error/DeserializeOperator/UnknownDeserializer: 筛选器错误:未知的解串器被提供为 'deserialize' 运算符的操作数
Error/Filter: 筛选器错误
Error/FilterRunPrefix: 筛选器错误:筛选器 run 的未知首码
Error/FilterSyntax: 筛选器运算式中的语法错误

View File

@ -25,6 +25,8 @@ Encryption/RepeatPassword: 重複輸入密碼
Encryption/PasswordNoMatch: 密碼不匹配
Encryption/SetPassword: 設定密碼
Error/Caption: 錯誤
Error/DeserializeOperator/MissingOperand: 篩選器錯誤:'deserialize' 運算子缺少運算元
Error/DeserializeOperator/UnknownDeserializer: 篩選器錯誤:未知的解串器被提供為 'deserialize' 運算子的運算元
Error/Filter: 篩選器錯誤
Error/FilterRunPrefix: 篩選器錯誤:篩選器 run 的未知首碼
Error/FilterSyntax: 篩選器運算式中的語法錯誤

View File

@ -1,7 +0,0 @@
title: $:/core/ui/ControlPanel/Settings
tags: $:/tags/ControlPanel
caption: {{$:/language/ControlPanel/Settings/Caption}}
<div class="tc-control-panel">
<$macrocall $name="tabs" tabsList="[all[shadows+tiddlers]tag[$:/tags/ControlPanel/SettingsTab]!has[draft.of]]" default="$:/core/ui/ControlPanel/Settings/TiddlyWiki" explicitState="$:/state/tab--697582678"/>
</div>

View File

@ -1388,6 +1388,11 @@ html body.tc-body.tc-single-tiddler-window {
height: 1.2em;
}
.tc-editor-toolbar .tc-drop-down a,
.tc-editor-toolbar .tc-drop-down button {
padding: 0;
}
.tc-editor-toolbar button:hover {
background-color: <<colour tiddler-controls-foreground-selected>>;
fill: <<colour background>>;