mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2024-12-25 01:20:30 +00:00
Merge branch 'master' into confetti-plugin
This commit is contained in:
commit
40fd941394
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,5 +1,6 @@
|
||||
.DS_Store
|
||||
.c9/
|
||||
.vs/
|
||||
.vscode/
|
||||
tmp/
|
||||
output/
|
||||
|
28
boot/boot.js
28
boot/boot.js
@ -569,26 +569,17 @@ $tw.utils.getTypeEncoding = function(ext) {
|
||||
return typeInfo ? typeInfo.encoding : "utf8";
|
||||
};
|
||||
|
||||
var polyfill =[
|
||||
"// this polyfills the globalThis variable",
|
||||
"// using the this variable on a getter ",
|
||||
"// inserted into the prototype of globalThis",
|
||||
"(function() {",
|
||||
" if (typeof globalThis === 'object') return;",
|
||||
" // node.green says this is available since 0.10.48",
|
||||
" Object.prototype.__defineGetter__('__temp__', function() {",
|
||||
" return this;",
|
||||
" });",
|
||||
" __temp__.globalThis = __temp__;",
|
||||
" delete Object.prototype.__temp__;",
|
||||
"}());"
|
||||
].join("\n");
|
||||
|
||||
var globalCheck =[
|
||||
" if(Object.keys(globalThis).length){",
|
||||
" console.log(Object.keys(globalThis));",
|
||||
" Object.defineProperty(Object.prototype, '__temp__', {",
|
||||
" get: function () { return this; },",
|
||||
" configurable: true",
|
||||
" });",
|
||||
" if(Object.keys(__temp__).length){",
|
||||
" console.log(Object.keys(__temp__));",
|
||||
" delete Object.prototype.__temp__;",
|
||||
" throw \"Global assignment is not allowed within modules on node.\";",
|
||||
" }"
|
||||
" }",
|
||||
" delete Object.prototype.__temp__;",
|
||||
].join('\n');
|
||||
|
||||
/*
|
||||
@ -604,7 +595,6 @@ $tw.utils.evalGlobal = function(code,context,filename,sandbox,allowGlobals) {
|
||||
});
|
||||
// Add the code prologue and epilogue
|
||||
code = [
|
||||
(!$tw.browser ? polyfill : ""),
|
||||
"(function(" + contextNames.join(",") + ") {",
|
||||
" (function(){\n" + code + "\n;})();",
|
||||
(!$tw.browser && sandbox && !allowGlobals) ? globalCheck : "",
|
||||
|
@ -18,7 +18,7 @@ All parameters are optional with safe defaults, and can be specified in any orde
|
||||
* ''anon-username'' - the username for signing edits for anonymous users
|
||||
* ''username'' - optional username for basic authentication
|
||||
* ''password'' - optional password for basic authentication
|
||||
* ''authenticated-user-header'' - optional name of header to be used for trusted authentication
|
||||
* ''authenticated-user-header'' - optional name of request header to be used for trusted authentication.
|
||||
* ''readers'' - comma-separated list of principals allowed to read from this wiki
|
||||
* ''writers'' - comma-separated list of principals allowed to write to this wiki
|
||||
* ''csrf-disable'' - set to "yes" to disable CSRF checks (defaults to "no")
|
||||
|
@ -21,7 +21,7 @@ Export our filter function
|
||||
*/
|
||||
exports["[unknown]"] = function(source,operator,options) {
|
||||
// Check for a user defined filter operator
|
||||
if(operator.operator.charAt(0) === ".") {
|
||||
if(operator.operator.indexOf(".") !== -1) {
|
||||
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});
|
||||
|
@ -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);
|
||||
|
@ -26,7 +26,7 @@ Instantiate parse rule
|
||||
exports.init = function(parser) {
|
||||
this.parser = parser;
|
||||
// Regexp to match
|
||||
this.matchRegExp = /^\\parameters\s*\(([^)]*)\)\s*\r?\n/mg;
|
||||
this.matchRegExp = /^\\parameters\s*\(([^)]*)\)(\s*\r?\n)?/mg;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -37,7 +37,7 @@ HeaderAuthenticator.prototype.authenticateRequest = function(request,response,st
|
||||
return false;
|
||||
} else {
|
||||
// authenticatedUsername will be undefined for anonymous users
|
||||
state.authenticatedUsername = username;
|
||||
state.authenticatedUsername = $tw.utils.decodeURIComponentSafe(username);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
@ -80,7 +80,7 @@ ClassicStoryView.prototype.remove = function(widget) {
|
||||
if(duration) {
|
||||
var targetElement = widget.findFirstDomNode(),
|
||||
removeElement = function() {
|
||||
widget.destroy();
|
||||
widget.removeChildDomNodes();
|
||||
};
|
||||
// Abandon if the list entry isn't a DOM element (it might be a text node)
|
||||
if(!targetElement || targetElement.nodeType === Node.TEXT_NODE) {
|
||||
@ -112,7 +112,7 @@ ClassicStoryView.prototype.remove = function(widget) {
|
||||
{opacity: "0.0"}
|
||||
]);
|
||||
} else {
|
||||
widget.destroy();
|
||||
widget.removeChildDomNodes();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -73,7 +73,7 @@ PopStoryView.prototype.remove = function(widget) {
|
||||
duration = $tw.utils.getAnimationDuration(),
|
||||
removeElement = function() {
|
||||
if(targetElement && targetElement.parentNode) {
|
||||
widget.destroy();
|
||||
widget.removeChildDomNodes();
|
||||
}
|
||||
};
|
||||
// Abandon if the list entry isn't a DOM element (it might be a text node)
|
||||
|
@ -154,7 +154,7 @@ ZoominListView.prototype.remove = function(widget) {
|
||||
var targetElement = widget.findFirstDomNode(),
|
||||
duration = $tw.utils.getAnimationDuration(),
|
||||
removeElement = function() {
|
||||
widget.destroy();
|
||||
widget.removeChildDomNodes();
|
||||
};
|
||||
// Abandon if the list entry isn't a DOM element (it might be a text node)
|
||||
if(!targetElement || targetElement.nodeType === Node.TEXT_NODE) {
|
||||
|
@ -112,7 +112,7 @@ CheckboxWidget.prototype.getValue = function() {
|
||||
var list;
|
||||
if(this.checkboxListField) {
|
||||
if($tw.utils.hop(tiddler.fields,this.checkboxListField)) {
|
||||
list = tiddler.getFieldList(this.checkboxListField);
|
||||
list = tiddler.getFieldList(this.checkboxListField) || [];
|
||||
} else {
|
||||
list = $tw.utils.parseStringArray(this.checkboxDefault || "") || [];
|
||||
}
|
||||
@ -208,16 +208,20 @@ CheckboxWidget.prototype.handleChangeEvent = function(event) {
|
||||
if(this.checkboxListField || this.checkboxListIndex) {
|
||||
var fieldContents, listContents, oldPos, newPos;
|
||||
if(this.checkboxListField) {
|
||||
fieldContents = tiddler ? tiddler.fields[this.checkboxListField] : undefined;
|
||||
fieldContents = (tiddler ? tiddler.fields[this.checkboxListField] : undefined) || [];
|
||||
} else {
|
||||
fieldContents = this.wiki.extractTiddlerDataItem(this.checkboxTitle,this.checkboxListIndex);
|
||||
}
|
||||
if($tw.utils.isArray(fieldContents)) {
|
||||
// Make a copy so we can modify it without changing original that's refrenced elsewhere
|
||||
listContents = fieldContents.slice(0);
|
||||
} else {
|
||||
listContents = $tw.utils.parseStringArray(fieldContents) || [];
|
||||
} else if(typeof fieldContents === "string") {
|
||||
listContents = $tw.utils.parseStringArray(fieldContents);
|
||||
// No need to copy since parseStringArray returns a fresh array, not refrenced elsewhere
|
||||
} else {
|
||||
// Field was neither an array nor a string; it's probably something that shouldn't become
|
||||
// an array (such as a date field), so bail out *without* triggering actions
|
||||
return;
|
||||
}
|
||||
oldPos = notValue ? listContents.indexOf(notValue) : -1;
|
||||
newPos = value ? listContents.indexOf(value) : -1;
|
||||
|
@ -39,7 +39,7 @@ DiffTextWidget.prototype.render = function(parent,nextSibling) {
|
||||
this.execute();
|
||||
// Create the diff
|
||||
var dmpObject = new dmp.diff_match_patch(),
|
||||
diffs = dmpObject.diff_main(this.getAttribute("source"),this.getAttribute("dest"));
|
||||
diffs = dmpObject.diff_main(this.getAttribute("source",""),this.getAttribute("dest",""));
|
||||
// Apply required cleanup
|
||||
switch(this.getAttribute("cleanup","semantic")) {
|
||||
case "none":
|
||||
|
@ -122,7 +122,7 @@ ImportVariablesWidget.prototype.refresh = function(changedTiddlers) {
|
||||
}
|
||||
if(changedAttributes.filter || !$tw.utils.isArrayEqual(this.tiddlerList,tiddlerList) || haveListedTiddlersChanged()) {
|
||||
// Compute the filter
|
||||
this.destroy();
|
||||
this.removeChildDomNodes();
|
||||
this.execute(tiddlerList);
|
||||
this.renderChildren(this.parentDomNode,this.findNextSiblingDomNode());
|
||||
return true;
|
||||
|
@ -219,7 +219,7 @@ ListWidget.prototype.handleListChanges = function(changedTiddlers) {
|
||||
} else {
|
||||
// If the list was empty then we need to remove the empty message
|
||||
if(prevList.length === 0) {
|
||||
this.destroy();
|
||||
this.removeChildDomNodes();
|
||||
this.children = [];
|
||||
}
|
||||
// If we are providing an counter variable then we must refresh the items, otherwise we can rearrange them
|
||||
@ -312,7 +312,7 @@ ListWidget.prototype.removeListItem = function(index) {
|
||||
if(this.storyview && this.storyview.remove) {
|
||||
this.storyview.remove(widget);
|
||||
} else {
|
||||
widget.destroy();
|
||||
widget.removeChildDomNodes();
|
||||
}
|
||||
// Remove the child widget
|
||||
this.children.splice(index,1);
|
||||
|
@ -51,7 +51,8 @@ MacroCallWidget.prototype.execute = function() {
|
||||
var positionalName = 0,
|
||||
parseTreeNodes = [{
|
||||
type: "transclude",
|
||||
isBlock: this.parseTreeNode.isBlock
|
||||
isBlock: this.parseTreeNode.isBlock,
|
||||
children: this.parseTreeNode.children
|
||||
}];
|
||||
$tw.utils.addAttributeToParseTreeNode(parseTreeNodes[0],"$variable",this.macroName);
|
||||
$tw.utils.addAttributeToParseTreeNode(parseTreeNodes[0],"$type",this.parseType);
|
||||
|
@ -48,7 +48,7 @@ SlotWidget.prototype.execute = function() {
|
||||
var pointer = this.parentWidget,
|
||||
depth = this.slotDepth;
|
||||
while(pointer) {
|
||||
if(pointer instanceof TranscludeWidget) {
|
||||
if(pointer instanceof TranscludeWidget && pointer.hasVisibleSlots()) {
|
||||
depth--;
|
||||
if(depth <= 0) {
|
||||
break;
|
||||
|
@ -171,99 +171,101 @@ TranscludeWidget.prototype.getTransclusionTarget = function() {
|
||||
}
|
||||
var parser;
|
||||
// Get the parse tree
|
||||
if(this.transcludeVariable) {
|
||||
// Transcluding a variable
|
||||
var variableInfo = this.getVariableInfo(this.transcludeVariable,{params: this.getOrderedTransclusionParameters()}),
|
||||
srcVariable = variableInfo && variableInfo.srcVariable;
|
||||
if(srcVariable) {
|
||||
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] || "";
|
||||
parser = {
|
||||
tree: [{
|
||||
type: "text",
|
||||
text: result
|
||||
}],
|
||||
source: result,
|
||||
type: "text/vnd.tiddlywiki"
|
||||
};
|
||||
if(parseAsInline) {
|
||||
parser.tree[0] = {
|
||||
type: "text",
|
||||
text: result
|
||||
};
|
||||
} else {
|
||||
parser.tree[0] = {
|
||||
type: "element",
|
||||
tag: "p",
|
||||
children: [{
|
||||
if(this.hasAttribute("$variable")) {
|
||||
if(this.transcludeVariable) {
|
||||
// Transcluding a variable
|
||||
var variableInfo = this.getVariableInfo(this.transcludeVariable,{params: this.getOrderedTransclusionParameters()}),
|
||||
srcVariable = variableInfo && variableInfo.srcVariable;
|
||||
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] || "";
|
||||
parser = {
|
||||
tree: [{
|
||||
type: "text",
|
||||
text: result
|
||||
}]
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var cacheKey = (parseAsInline ? "inlineParser" : "blockParser") + (this.transcludeType || "");
|
||||
if(variableInfo.isCacheable && srcVariable[cacheKey]) {
|
||||
parser = srcVariable[cacheKey];
|
||||
} else {
|
||||
parser = this.wiki.parseText(this.transcludeType,variableInfo.text || "",{parseAsInline: parseAsInline, configTrimWhiteSpace: srcVariable.configTrimWhiteSpace});
|
||||
if(variableInfo.isCacheable) {
|
||||
srcVariable[cacheKey] = parser;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(parser) {
|
||||
// Add parameters widget for procedures and custom widgets
|
||||
if(srcVariable.isProcedureDefinition || srcVariable.isWidgetDefinition) {
|
||||
parser = {
|
||||
tree: [
|
||||
{
|
||||
type: "parameters",
|
||||
children: parser.tree
|
||||
}
|
||||
],
|
||||
source: parser.source,
|
||||
type: parser.type
|
||||
}
|
||||
$tw.utils.each(srcVariable.params,function(param) {
|
||||
var name = param.name;
|
||||
// Parameter names starting with dollar must be escaped to double dollars
|
||||
if(name.charAt(0) === "$") {
|
||||
name = "$" + name;
|
||||
}],
|
||||
source: result,
|
||||
type: "text/vnd.tiddlywiki"
|
||||
};
|
||||
if(parseAsInline) {
|
||||
parser.tree[0] = {
|
||||
type: "text",
|
||||
text: result
|
||||
};
|
||||
} else {
|
||||
parser.tree[0] = {
|
||||
type: "element",
|
||||
tag: "p",
|
||||
children: [{
|
||||
type: "text",
|
||||
text: result
|
||||
}]
|
||||
}
|
||||
$tw.utils.addAttributeToParseTreeNode(parser.tree[0],name,param["default"])
|
||||
});
|
||||
} else {
|
||||
// For macros and ordinary variables, wrap the parse tree in a vars widget assigning the parameters to variables named "__paramname__"
|
||||
parser = {
|
||||
tree: [
|
||||
{
|
||||
type: "vars",
|
||||
children: parser.tree
|
||||
}
|
||||
],
|
||||
source: parser.source,
|
||||
type: parser.type
|
||||
}
|
||||
$tw.utils.each(variableInfo.params,function(param) {
|
||||
$tw.utils.addAttributeToParseTreeNode(parser.tree[0],"__" + param.name + "__",param.value)
|
||||
});
|
||||
} else {
|
||||
var cacheKey = (parseAsInline ? "inlineParser" : "blockParser") + (this.transcludeType || "");
|
||||
if(variableInfo.isCacheable && srcVariable[cacheKey]) {
|
||||
parser = srcVariable[cacheKey];
|
||||
} else {
|
||||
parser = this.wiki.parseText(this.transcludeType,variableInfo.text || "",{parseAsInline: parseAsInline, configTrimWhiteSpace: srcVariable.configTrimWhiteSpace});
|
||||
if(variableInfo.isCacheable) {
|
||||
srcVariable[cacheKey] = parser;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(parser) {
|
||||
// Add parameters widget for procedures and custom widgets
|
||||
if(srcVariable.isProcedureDefinition || srcVariable.isWidgetDefinition) {
|
||||
parser = {
|
||||
tree: [
|
||||
{
|
||||
type: "parameters",
|
||||
children: parser.tree
|
||||
}
|
||||
],
|
||||
source: parser.source,
|
||||
type: parser.type
|
||||
}
|
||||
$tw.utils.each(srcVariable.params,function(param) {
|
||||
var name = param.name;
|
||||
// Parameter names starting with dollar must be escaped to double dollars
|
||||
if(name.charAt(0) === "$") {
|
||||
name = "$" + name;
|
||||
}
|
||||
$tw.utils.addAttributeToParseTreeNode(parser.tree[0],name,param["default"])
|
||||
});
|
||||
} else {
|
||||
// For macros and ordinary variables, wrap the parse tree in a vars widget assigning the parameters to variables named "__paramname__"
|
||||
parser = {
|
||||
tree: [
|
||||
{
|
||||
type: "vars",
|
||||
children: parser.tree
|
||||
}
|
||||
],
|
||||
source: parser.source,
|
||||
type: parser.type
|
||||
}
|
||||
$tw.utils.each(variableInfo.params,function(param) {
|
||||
$tw.utils.addAttributeToParseTreeNode(parser.tree[0],"__" + param.name + "__",param.value)
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -382,6 +384,13 @@ TranscludeWidget.prototype.getTransclusionSlotFill = function(name,defaultParseT
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
Return whether this transclusion should be visible to the slot widget
|
||||
*/
|
||||
TranscludeWidget.prototype.hasVisibleSlots = function() {
|
||||
return this.getAttribute("$fillignore","no") === "no";
|
||||
}
|
||||
|
||||
/*
|
||||
Compose a string comprising the title, field and/or index to identify this transclusion for recursion detection
|
||||
*/
|
||||
|
@ -403,7 +403,7 @@ Widget.prototype.computeAttribute = function(attribute) {
|
||||
if(attribute.type === "filtered") {
|
||||
value = this.wiki.filterTiddlers(attribute.filter,this)[0] || "";
|
||||
} else if(attribute.type === "indirect") {
|
||||
value = this.wiki.getTextReference(attribute.textReference,"",this.getVariable("currentTiddler"));
|
||||
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) {
|
||||
@ -546,8 +546,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});
|
||||
@ -688,7 +688,7 @@ Rebuild a previously rendered widget
|
||||
*/
|
||||
Widget.prototype.refreshSelf = function() {
|
||||
var nextSibling = this.findNextSiblingDomNode();
|
||||
this.removeChildDomNodes({ recursive: true });
|
||||
this.removeChildDomNodes();
|
||||
this.render(this.parentDomNode,nextSibling);
|
||||
};
|
||||
|
||||
@ -753,42 +753,19 @@ Widget.prototype.findFirstDomNode = function() {
|
||||
/*
|
||||
Remove any DOM nodes created by this widget or its children
|
||||
*/
|
||||
Widget.prototype.removeChildDomNodes = function(options) {
|
||||
var recursive = options && options.recursive;
|
||||
/**
|
||||
* If this widget has directly created DOM nodes, delete them and exit.
|
||||
* This assumes that any child widgets are contained within the created DOM nodes, which would normally be the case
|
||||
*/
|
||||
Widget.prototype.removeChildDomNodes = function() {
|
||||
// If this widget has directly created DOM nodes, delete them and exit. This assumes that any child widgets are contained within the created DOM nodes, which would normally be the case
|
||||
if(this.domNodes.length > 0) {
|
||||
$tw.utils.each(this.domNodes,function(domNode) {
|
||||
domNode.parentNode.removeChild(domNode);
|
||||
});
|
||||
this.domNodes = [];
|
||||
return true;
|
||||
} else if(recursive) {
|
||||
} else {
|
||||
// Otherwise, ask the child widgets to delete their DOM nodes
|
||||
$tw.utils.each(this.children,function(childWidget) {
|
||||
childWidget.removeChildDomNodes(options);
|
||||
childWidget.removeChildDomNodes();
|
||||
});
|
||||
}
|
||||
return false
|
||||
};
|
||||
|
||||
/*
|
||||
Inform widget subclass that extends this widget and children widgets of this widget. Let them know this widget tree is about to destroy, and dom nodes are being unmounted from the document.
|
||||
*/
|
||||
Widget.prototype.destroy = function(options) {
|
||||
// removeDom by default
|
||||
var removeDom = (options && options.removeDom) || true;
|
||||
if (removeDom) {
|
||||
// prepare options for children, if we have removed the dom, child don't need to remove their dom
|
||||
removeDom = !this.removeChildDomNodes();
|
||||
}
|
||||
// nothing need to do, as dom is already removed in the removeChildDomNodes
|
||||
// we just need to inform the children
|
||||
$tw.utils.each(this.children,function(childWidget) {
|
||||
childWidget.destroy({ removeDom: removeDom });
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -30,15 +30,15 @@ Block transclusions are shown in red, and inline transclusions are shown in gree
|
||||
<!-- Look for a parameter starting with $ to determine if we are in legacy mode -->
|
||||
<$list filter="[<@params>jsonindexes[]] :filter[<currentTiddler>prefix[$]] +[limit[1]]" variable="ignore" emptyMessage="""
|
||||
<!-- Legacy mode: we render the transclusion without a dollar sign for recursionMarker and mode -->
|
||||
<$genesis $type="$transclude" $remappable="no" $names="[<@params>jsonindexes[]]" $values="[<@params>jsonindexes[]] :map[<@params>jsonget<currentTiddler>]" recursionMarker="no" mode=<<mode>>>
|
||||
<$genesis $type="$transclude" $remappable="no" $names="[<@params>jsonindexes[]]" $values="[<@params>jsonindexes[]] :map[<@params>jsonget<currentTiddler>]" recursionMarker="no" mode=<<mode>> $$fillignore="yes">
|
||||
<!-- Reach back up to the grandparent transclusion to get the correct slot value -->
|
||||
<$slot $name="ts-raw" $depth="2"/>
|
||||
<$slot $name="ts-raw"/>
|
||||
</$genesis>
|
||||
""">
|
||||
<!-- Non-legacy mode: we use dollar signs for the recursionMarker and mode -->
|
||||
<$genesis $type="$transclude" $remappable="no" $names="[<@params>jsonindexes[]]" $values="[<@params>jsonindexes[]] :map[<@params>jsonget<currentTiddler>]" $$recursionMarker="no" $$mode=<<mode>>>
|
||||
<$genesis $type="$transclude" $remappable="no" $names="[<@params>jsonindexes[]]" $values="[<@params>jsonindexes[]] :map[<@params>jsonget<currentTiddler>]" $$recursionMarker="no" $$mode=<<mode>> $$fillignore="yes">
|
||||
<!-- Reach back up to the grandparent transclusion to get the correct slot fill value -->
|
||||
<$slot $name="ts-raw" $depth="2"/>
|
||||
<$slot $name="ts-raw"/>
|
||||
</$genesis>
|
||||
</$list>
|
||||
</$genesis>
|
||||
|
@ -26,7 +26,7 @@ $button$
|
||||
<div class="tc-sidebar-tab-open">
|
||||
<$list filter="[list<tv-story-list>]" history=<<tv-history-list>> storyview="pop">
|
||||
<div class="tc-sidebar-tab-open-item">
|
||||
<$macrocall $name="droppable-item" button="<$button message='tm-close-tiddler' tooltip={{$:/language/Buttons/Close/Hint}} aria-label={{$:/language/Buttons/Close/Caption}} class='tc-btn-invisible tc-btn-mini tc-small-gap-right'>{{$:/core/images/close-button}}</$button><$link to={{!!title}}><$view field='title'/></$link>"/>
|
||||
<$macrocall $name="droppable-item" button="<$button message='tm-close-tiddler' tooltip={{$:/language/Buttons/Close/Hint}} aria-label={{$:/language/Buttons/Close/Caption}} class='tc-btn-invisible tc-btn-mini tc-small-gap-right'>{{$:/core/images/close-button}}</$button><$link/>"/>
|
||||
</div>
|
||||
</$list>
|
||||
<$tiddler tiddler="">
|
||||
|
@ -3,14 +3,26 @@ tags: $:/tags/Macro
|
||||
|
||||
\define translink(title,mode:"block")
|
||||
\whitespace trim
|
||||
<div style="border:1px solid #ccc; padding: 0.5em; background: black; foreground; white;">
|
||||
<$list filter="[<__mode__>match[block]]">
|
||||
<div class="tc-translink">
|
||||
<div>
|
||||
<$link to="""$title$""">
|
||||
<$text text="""$title$"""/>
|
||||
<h1><$text text="""$title$"""/></h1>
|
||||
</$link>
|
||||
<div style="border:1px solid #ccc; padding: 0.5em; background: white; foreground; black;">
|
||||
<$transclude tiddler="""$title$""" mode="$mode$">
|
||||
"<$text text="""$title$"""/>" is missing
|
||||
<$transclude tiddler="""$title$""" mode="block">
|
||||
<$set name="currentTiddler" value="""$title$"""><$transclude tiddler="$:/language/MissingTiddler/Hint"/></$set>
|
||||
</$transclude>
|
||||
</div>
|
||||
</div>
|
||||
</$list>
|
||||
<$list filter="[<__mode__>match[inline]]">
|
||||
<span class="tc-translink">
|
||||
<$link to="""$title$""">
|
||||
<$text text="""$title$"""/>
|
||||
</$link>
|
||||
 (<$transclude tiddler="""$title$""" mode="inline">
|
||||
<$set name="currentTiddler" value="""$title$"""><$transclude tiddler="$:/language/MissingTiddler/Hint"/></$set>
|
||||
</$transclude>)
|
||||
</span>
|
||||
</$list>
|
||||
\end
|
||||
|
@ -72,10 +72,11 @@ Improvements to the following translations:
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/7380">> crashes when using an invalid CSS selector for [[WidgetMessage: tm-focus-selector]] and [[WidgetMessage: tm-scroll]]
|
||||
* <<.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>>)
|
||||
|
||||
! Developer Improvements
|
||||
|
||||
* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/6699">> support for a `destroy()` method for widgets, giving them a chance to dispose of any resources
|
||||
*
|
||||
|
||||
! Node.js Improvements
|
||||
|
||||
@ -101,6 +102,7 @@ Marxsal
|
||||
michsa
|
||||
muzimuzhi
|
||||
pmario
|
||||
rmunn
|
||||
saqimtiaz
|
||||
yaisog
|
||||
""">>
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -0,0 +1,40 @@
|
||||
title: Transclude/Macro/Missing
|
||||
description: Transcluding a missing or blank variable
|
||||
type: text/vnd.tiddlywiki-multiple
|
||||
tags: [[$:/tags/wiki-test-spec]]
|
||||
|
||||
title: Output
|
||||
|
||||
\whitespace trim
|
||||
<$macrocall $name="missingmacro">
|
||||
Fallback content
|
||||
</$macrocall>
|
||||
|
||||
<$transclude $variable="missingmacro">
|
||||
Fallback content
|
||||
</$transclude>
|
||||
|
||||
<$macrocall $name="">
|
||||
Fallback content
|
||||
</$macrocall>
|
||||
|
||||
<$transclude $variable="">
|
||||
Fallback content
|
||||
</$transclude>
|
||||
|
||||
<$let emptyVariable="">
|
||||
|
||||
<$macrocall $name="emptyVariable">
|
||||
Fallback content
|
||||
</$macrocall>
|
||||
|
||||
<$transclude $variable="emptyVariable">
|
||||
Fallback content
|
||||
</$transclude>
|
||||
|
||||
</$let>
|
||||
|
||||
+
|
||||
title: ExpectedResult
|
||||
|
||||
<p>Fallback content</p><p>Fallback content</p><p>Fallback content</p><p>Fallback content</p><p>Fallback content</p><p>Fallback content</p>
|
@ -56,7 +56,7 @@ Tests the checkbox widget thoroughly.
|
||||
* Test data for checkbox widget tests
|
||||
*/
|
||||
|
||||
const fieldModeTests = [
|
||||
var fieldModeTests = [
|
||||
{
|
||||
testName: "field mode checked",
|
||||
tiddlers: [{title: "TiddlerOne", text: "Jolly Old World", expand: "yes"}],
|
||||
@ -95,16 +95,16 @@ Tests the checkbox widget thoroughly.
|
||||
},
|
||||
];
|
||||
|
||||
const indexModeTests = fieldModeTests.map(data => {
|
||||
const newData = {...data};
|
||||
const newName = data.testName.replace('field mode', 'index mode');
|
||||
const newTiddlers = data.tiddlers.map(tiddler => {
|
||||
var indexModeTests = fieldModeTests.map(data => {
|
||||
var newData = {...data};
|
||||
var newName = data.testName.replace('field mode', 'index mode');
|
||||
var newTiddlers = data.tiddlers.map(tiddler => {
|
||||
return {title: tiddler.title, type: "application/x-tiddler-dictionary", text: `one: a\nexpand: ${tiddler.expand}\ntwo: b`}
|
||||
});
|
||||
const newWidgetText = data.widgetText.replace("field='expand'", "index='expand'");
|
||||
const newChange = {};
|
||||
for (const key of Object.keys(data.expectedChange)) {
|
||||
const oldChange = data.expectedChange[key];
|
||||
var newWidgetText = data.widgetText.replace("field='expand'", "index='expand'");
|
||||
var newChange = {};
|
||||
for (var key of Object.keys(data.expectedChange)) {
|
||||
var oldChange = data.expectedChange[key];
|
||||
if (oldChange.expand) {
|
||||
newChange[key] = { text: `one: a\nexpand: ${oldChange.expand}\ntwo: b` }
|
||||
} else {
|
||||
@ -119,7 +119,26 @@ Tests the checkbox widget thoroughly.
|
||||
return newData;
|
||||
});
|
||||
|
||||
const listModeTests = [
|
||||
var listModeTestsForDateFields = [
|
||||
{
|
||||
testName: "list mode created date field",
|
||||
tiddlers: [{title: "Colors", created: "201304152222", modified: "202301022222"}],
|
||||
widgetText: "<$checkbox tiddler='Colors' listField='created' checked='green' />",
|
||||
startsOutChecked: false,
|
||||
finalValue: false,
|
||||
expectedChange: { "Colors": { created: new Date("2013-04-15T22:22:00Z")}} // created field should *not* be touched by a listField checkbox
|
||||
},
|
||||
{
|
||||
testName: "list mode modified date field",
|
||||
tiddlers: [{title: "Colors", created: "201304152222", modified: "202301022222"}],
|
||||
widgetText: "<$checkbox tiddler='Colors' listField='modified' checked='green' />",
|
||||
startsOutChecked: false,
|
||||
finalValue: false,
|
||||
expectedChange: { "Colors": { modified: new Date("2023-01-02T22:22:00Z")}} // modified field should *not* be touched by a listField checkbox
|
||||
},
|
||||
]
|
||||
|
||||
var listModeTests = [
|
||||
{
|
||||
testName: "list mode add",
|
||||
tiddlers: [{title: "Colors", colors: "orange yellow"}],
|
||||
@ -235,11 +254,11 @@ Tests the checkbox widget thoroughly.
|
||||
];
|
||||
|
||||
// https://github.com/Jermolene/TiddlyWiki5/issues/6871
|
||||
const listModeTestsWithListField = (
|
||||
var listModeTestsWithListField = (
|
||||
listModeTests
|
||||
.filter(data => data.widgetText.includes("listField='colors'"))
|
||||
.map(data => {
|
||||
const newData = {
|
||||
var newData = {
|
||||
...data,
|
||||
tiddlers: data.tiddlers.map(tiddler => ({...tiddler, list: tiddler.colors, colors: undefined})),
|
||||
widgetText: data.widgetText.replace("listField='colors'", "listField='list'"),
|
||||
@ -250,11 +269,11 @@ Tests the checkbox widget thoroughly.
|
||||
return newData;
|
||||
})
|
||||
);
|
||||
const listModeTestsWithTagsField = (
|
||||
var listModeTestsWithTagsField = (
|
||||
listModeTests
|
||||
.filter(data => data.widgetText.includes("listField='colors'"))
|
||||
.map(data => {
|
||||
const newData = {
|
||||
var newData = {
|
||||
...data,
|
||||
tiddlers: data.tiddlers.map(tiddler => ({...tiddler, tags: tiddler.colors, colors: undefined})),
|
||||
widgetText: data.widgetText.replace("listField='colors'", "listField='tags'"),
|
||||
@ -266,20 +285,20 @@ Tests the checkbox widget thoroughly.
|
||||
})
|
||||
);
|
||||
|
||||
const indexListModeTests = listModeTests.map(data => {
|
||||
const newData = {...data};
|
||||
const newName = data.testName.replace('list mode', 'index list mode');
|
||||
const newTiddlers = data.tiddlers.map(tiddler => {
|
||||
var indexListModeTests = listModeTests.map(data => {
|
||||
var newData = {...data};
|
||||
var newName = data.testName.replace('list mode', 'index list mode');
|
||||
var newTiddlers = data.tiddlers.map(tiddler => {
|
||||
if (tiddler.hasOwnProperty('colors')) {
|
||||
return {title: tiddler.title, type: "application/x-tiddler-dictionary", text: `one: a\ncolors: ${tiddler.colors}\ntwo: b`}
|
||||
} else if (tiddler.hasOwnProperty('someField')) {
|
||||
return {title: tiddler.title, type: "application/x-tiddler-dictionary", text: `one: a\nsomeField: ${tiddler.someField}\ntwo: b`}
|
||||
}
|
||||
});
|
||||
const newWidgetText = data.widgetText.replace("listField='colors'", "listIndex='colors'").replace(/\$field/g, '$index').replace("listField='someField'", "listIndex='someField'");
|
||||
const newChange = {};
|
||||
for (const key of Object.keys(data.expectedChange)) {
|
||||
const oldChange = data.expectedChange[key];
|
||||
var newWidgetText = data.widgetText.replace("listField='colors'", "listIndex='colors'").replace(/\$field/g, '$index').replace("listField='someField'", "listIndex='someField'");
|
||||
var newChange = {};
|
||||
for (var key of Object.keys(data.expectedChange)) {
|
||||
var oldChange = data.expectedChange[key];
|
||||
if (oldChange.colors) {
|
||||
newChange[key] = { text: `one: a\ncolors: ${oldChange.colors}\ntwo: b` }
|
||||
} else if (oldChange.someField !== undefined) {
|
||||
@ -296,7 +315,7 @@ Tests the checkbox widget thoroughly.
|
||||
return newData;
|
||||
});
|
||||
|
||||
const filterModeTests = [
|
||||
var filterModeTests = [
|
||||
{
|
||||
testName: "filter mode false -> true",
|
||||
tiddlers: [{title: "Colors", colors: "red orange yellow"}],
|
||||
@ -482,9 +501,10 @@ Tests the checkbox widget thoroughly.
|
||||
},
|
||||
];
|
||||
|
||||
const checkboxTestData = fieldModeTests.concat(
|
||||
var checkboxTestData = fieldModeTests.concat(
|
||||
indexModeTests,
|
||||
listModeTests,
|
||||
listModeTestsForDateFields,
|
||||
listModeTestsWithListField,
|
||||
listModeTestsWithTagsField,
|
||||
indexListModeTests,
|
||||
@ -494,7 +514,7 @@ Tests the checkbox widget thoroughly.
|
||||
/*
|
||||
* Checkbox widget tests using the test data above
|
||||
*/
|
||||
for (const data of checkboxTestData) {
|
||||
for (var data of checkboxTestData) {
|
||||
it('checkbox widget test: ' + data.testName, function() {
|
||||
// Setup
|
||||
|
||||
@ -505,7 +525,7 @@ Tests the checkbox widget thoroughly.
|
||||
|
||||
// Check initial state
|
||||
|
||||
const widget = findNodeOfType('checkbox', widgetNode);
|
||||
var widget = findNodeOfType('checkbox', widgetNode);
|
||||
// Verify that the widget is or is not checked as expected
|
||||
expect(widget.getValue()).toBe(data.startsOutChecked);
|
||||
|
||||
@ -519,16 +539,16 @@ Tests the checkbox widget thoroughly.
|
||||
widget.handleChangeEvent(null);
|
||||
|
||||
// Check state again: in most tests, checkbox should be inverse of what it was
|
||||
const finalValue = data.hasOwnProperty('finalValue') ? data.finalValue : !data.startsOutChecked;
|
||||
var finalValue = data.hasOwnProperty('finalValue') ? data.finalValue : !data.startsOutChecked;
|
||||
expect(widget.getValue()).toBe(finalValue);
|
||||
|
||||
// Check that tiddler(s) has/have gone through expected change(s)
|
||||
for (const key of Object.keys(data.expectedChange)) {
|
||||
const tiddler = wiki.getTiddler(key);
|
||||
const change = data.expectedChange[key];
|
||||
for (const fieldName of Object.keys(change)) {
|
||||
const expectedValue = change[fieldName];
|
||||
const fieldValue = tiddler.fields[fieldName];
|
||||
for (var key of Object.keys(data.expectedChange)) {
|
||||
var tiddler = wiki.getTiddler(key);
|
||||
var change = data.expectedChange[key];
|
||||
for (var fieldName of Object.keys(change)) {
|
||||
var expectedValue = change[fieldName];
|
||||
var fieldValue = tiddler.fields[fieldName];
|
||||
expect(fieldValue).toEqual(expectedValue);
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,8 @@ type: text/vnd.tiddlywiki
|
||||
|
||||
The edit template body cascade is a [[cascade|Cascades]] used by the default edit template to choose the template for displaying the tiddler body.
|
||||
|
||||
The core edit template body cascade can be found in $:/core/ui/EditTemplate/body
|
||||
|
||||
The default edit template body cascade consists of:
|
||||
|
||||
# If the tiddler has the field ''_canonical_uri'' then use the template $:/core/ui/EditTemplate/body/canonical-uri to display the remote URL
|
||||
@ -13,4 +15,4 @@ The default edit template body cascade consists of:
|
||||
|
||||
You can see the current settings for the view template body cascade in $:/ControlPanel under the ''Info'' -> ''Advanced'' -> ''Cascades'' -> ''Edit Template Body'' tab.
|
||||
|
||||
<<list-links "[tag[Edit Template Body Cascade]]">>
|
||||
<<list-links "[tag[Edit Template Body Cascade]]">>
|
||||
|
@ -6,6 +6,8 @@ type: text/vnd.tiddlywiki
|
||||
|
||||
The field editor cascade is a [[cascade|Cascades]] used to choose a template for rendering the field editor within the [[EditTemplate|$:/core/ui/EditTemplate/fields]].
|
||||
|
||||
The core field editor cascade can be found in $:/core/ui/EditTemplate/fields
|
||||
|
||||
The default field editor cascade only contains one element:
|
||||
|
||||
# Use the tiddler $:/core/ui/EditTemplate/fieldEditor/default to render the field
|
||||
@ -14,4 +16,4 @@ See [[Customizing EditTemplate field rendering]] for more details.
|
||||
|
||||
You can see the current settings for the field editor cascade in $:/ControlPanel under the ''Info'' -> ''Advanced'' -> ''Cascades'' -> ''Field Editor'' tab.
|
||||
|
||||
<<list-links "[tag[Tiddler Field Editor Cascade]]">>
|
||||
<<list-links "[tag[Tiddler Field Editor Cascade]]">>
|
||||
|
@ -6,6 +6,8 @@ type: text/vnd.tiddlywiki
|
||||
|
||||
"Story tiddler template" refers to the template used to display a tiddler within the story river.
|
||||
|
||||
The core story tiddler template can be found in $:/core/ui/StoryTiddlerTemplate
|
||||
|
||||
The [[Story Tiddler Template Cascade]] is used to choose the template to be used for a particular tiddler. By default, the edit template is used for tiddlers in draft mode, and the view template used otherwise.
|
||||
|
||||
See also:
|
||||
|
@ -6,6 +6,8 @@ type: text/vnd.tiddlywiki
|
||||
|
||||
The tiddler colour cascade is a [[cascade|Cascades]] used to choose which colour should be used for a particular tiddler.
|
||||
|
||||
Core tiddler colour cascades can be found in $:/core/macros/tag, $:/core/ui/Components/tag-link, $:/core/ui/EditTemplate/tags, $:/core/ui/TagPickerTagTemplate, $:/core/ui/TagTemplate and $:/core/ui/ViewTemplate/title
|
||||
|
||||
The default tiddler colour cascade consists of:
|
||||
|
||||
# If the tiddler has a ''color'' field, use the value as the colour
|
||||
@ -13,4 +15,4 @@ The default tiddler colour cascade consists of:
|
||||
|
||||
You can see the current settings for the tiddler colour cascade in $:/ControlPanel under the ''Info'' -> ''Advanced'' -> ''Cascades'' -> ''Tiddler Colour'' tab.
|
||||
|
||||
<<list-links "[tag[Tiddler Colour Cascade]]">>
|
||||
<<list-links "[tag[Tiddler Colour Cascade]]">>
|
||||
|
@ -6,6 +6,8 @@ type: text/vnd.tiddlywiki
|
||||
|
||||
The tiddler icon cascade is a [[cascade|Cascades]] used to choose which icon should be used for a particular tiddler.
|
||||
|
||||
The core tiddler icon cascade can be found in $:/core/ui/TiddlerIcon
|
||||
|
||||
The default tiddler icon cascade consists of:
|
||||
|
||||
# If the tiddler has an ''icon'' field, use the value as the title of the icon tiddler
|
||||
@ -13,4 +15,4 @@ The default tiddler icon cascade consists of:
|
||||
|
||||
You can see the current settings for the tiddler icon cascade in $:/ControlPanel under the ''Info'' -> ''Advanced'' -> ''Cascades'' -> ''Tiddler Icon'' tab.
|
||||
|
||||
<<list-links "[tag[Tiddler Icon Cascade]]">>
|
||||
<<list-links "[tag[Tiddler Icon Cascade]]">>
|
||||
|
@ -6,6 +6,8 @@ type: text/vnd.tiddlywiki
|
||||
|
||||
The view template title cascade is a [[cascade|Cascades]] used by the default view template to choose the template for displaying the tiddler title.
|
||||
|
||||
The core view template title cascade can be found in $:/core/ui/ViewTemplate/title
|
||||
|
||||
The default view template title cascade consists of:
|
||||
|
||||
# If the tiddler title starts with `$:/` then use the template $:/core/ui/ViewTemplate/title/system which causes the `$:/` prefix to be displayed in pale text
|
||||
@ -13,4 +15,4 @@ The default view template title cascade consists of:
|
||||
|
||||
You can see the current settings for the view template title cascade in $:/ControlPanel under the ''Info'' -> ''Advanced'' -> ''Cascades'' -> ''View Template Title'' tab.
|
||||
|
||||
<<list-links "[tag[View Template Title Cascade]]">>
|
||||
<<list-links "[tag[View Template Title Cascade]]">>
|
||||
|
@ -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
|
||||
|
||||
|
@ -1,22 +1,18 @@
|
||||
created: 20160810122928198
|
||||
modified: 20160810122934291
|
||||
modified: 20230505104214168
|
||||
tags: [[Editor toolbar]]
|
||||
title: Using Excise
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
|
||||
! Excise text
|
||||
From the EditorToolbar you can export selected text to a new tiddler and insert a [[link|Linking in WikiText]] [[Transclusion]] or [[macro|Macros]] in its place. Click ''Excise text'' (<<.icon $:/core/images/excise>>), input name of the new tiddler, and choose excise method.
|
||||
|
||||
!! How to excise text
|
||||
# Highlight the relevant piece of text
|
||||
#Click ''Excise text'' (<<.icon $:/core/images/excise>>)
|
||||
# Click ''Excise text'' (<<.icon $:/core/images/excise>>)
|
||||
# Give the new tiddler a title.
|
||||
# Chosse if the new tiddler will be tagged with the title of the current tiddler''*''.
|
||||
# Choose replacing method. [[link|Linking in WikiText]] [[Transclusion]] or [[macro|Macros]].
|
||||
|
||||
# Chosse if the new tiddler will be tagged with the title of the current tiddler (see note below).
|
||||
# Choose replacing method: [[link|Linking in WikiText]], [[transclusion|Transclusion]], or [[macro|Macros]].
|
||||
# Click the ''{{$:/language/Buttons/Excise/Caption/Excise}}'' button
|
||||
|
||||
|
||||
|
||||
''*NOTE:'' If you choose tic the option to `Tag new tiddler with the title of this tiddler`. The tag will be the'' draft title''. If you create a new tiddler (or clone an existing one), the draft title and the tag, will be `New Tiddler`. __You have to save the tiddler and re-edit it to get the new title as tag.__
|
||||
<<.strong Note!>> If you choose the option to `Tag new tiddler with the title of this tiddler`, the new tiddler will be tagged with the name of the current tiddler before it has been edited. If you have changed the title of the current tiddler, save it first and edit it again to perform excision with this option.
|
||||
|
21
editions/tw5.com/tiddlers/macros/TranslinkMacro.tid
Normal file
21
editions/tw5.com/tiddlers/macros/TranslinkMacro.tid
Normal file
@ -0,0 +1,21 @@
|
||||
created: 20230505090333510
|
||||
modified: 20230505090333510
|
||||
tags: Macros [[Core Macros]]
|
||||
title: translink Macro
|
||||
type: text/vnd.tiddlywiki
|
||||
caption: translink
|
||||
|
||||
The <<.def translink>> [[macro|Macros]] returns a frame with the title and [[transcluded|Transclusion]] text of a chosen tiddler. The title links to the transcluded tiddler.
|
||||
|
||||
If the chosen tiddler is missing, an appropriate message will be shown instead of the transcluded text.
|
||||
|
||||
This is the default macro used when [[excising|Using Excise]] text and replacing it with a macro.
|
||||
|
||||
!! Parameters
|
||||
|
||||
; title
|
||||
: The title of the tiddler to be transcluded
|
||||
; mode
|
||||
: The mode of the [[transclude widget|TranscludeWidget]] used inside the macro, defaults to `block`
|
||||
|
||||
<<.macro-examples "translink">>
|
9
editions/tw5.com/tiddlers/macros/examples/translink.tid
Normal file
9
editions/tw5.com/tiddlers/macros/examples/translink.tid
Normal file
@ -0,0 +1,9 @@
|
||||
created: 20230505092952569
|
||||
modified: 20230505092952569
|
||||
tags: [[translink Macro]] [[Macro Examples]]
|
||||
title: translink Macro (Examples)
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
<$macrocall $name=".example" n="1" eg="""<<translink "Philosophy of Tiddlers">>"""/>
|
||||
<$macrocall $name=".example" n="2" eg="""<<translink "Philosophy of Tiddlers" inline>>"""/>
|
||||
<$macrocall $name=".example" n="3" eg="""<<translink Foo>>"""/>
|
@ -13,7 +13,7 @@ Excises the currently selected text into a new tiddler and replaces it with a li
|
||||
|!Name |!Description |
|
||||
|title |Title of the new tiddler the selected content is excised to|
|
||||
|type |Type of the replacement to be inserted: Can be one of <<.value "transclude">>, <<.value "link">> or <<.value "macro">>|
|
||||
|macro |In case //type=<<.value "macro">>//, specifies the name of the macro to be inserted. The title of the new tiddler is provided as the first parameter to the macro. Defaults to the ''translink'' macro|
|
||||
|macro |In case //type=<<.value "macro">>//, specifies the name of the macro to be inserted. The title of the new tiddler is provided as the first parameter to the macro. Defaults to the [[translink macro|translink Macro]]|
|
||||
|tagnew |If '<<.value "yes">>', will tag the new tiddler with the title of the tiddler currently being edited |
|
||||
|
||||
</div>
|
||||
|
@ -1,10 +1,10 @@
|
||||
created: 20220917113154900
|
||||
modified: 20230419103154329
|
||||
modified: 20230518143557045
|
||||
tags: Pragmas
|
||||
title: Pragma: \parameters
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
<<.from-version "5.3.0">> The ''\parameters'' [[pragma|Pragmas]] is used within [[procedure|Procedure Definitions]] and [[widget|Widget Definitions]] definitions to declare the parameters that are expected, and their default values. It is a shortcut syntax for the ParametersWidget.
|
||||
<<.from-version "5.3.0">> The ''\parameters'' [[pragma|Pragmas]] is used within [[procedure|Procedure Definitions]] and [[widget|Custom Widgets]] definitions to declare the parameters that are expected, and their default values. It is a shortcut syntax for the ParametersWidget.
|
||||
|
||||
```
|
||||
\parameters (<name>[:<default-value>],<name>[:<default-value>]...)
|
||||
@ -16,3 +16,11 @@ For example:
|
||||
\parameters (firstname:"Joe",lastname:"Blogs")
|
||||
```
|
||||
|
||||
To illustrate the use of ''\parameters'' pragma, see [[Core Icons]] which are parameterised. The first parameter `size` specified the size at which the icon should be rendered. For example see the text of [[$:/core/images/print-button]] tiddler. The first line defines the size parameter as `\parameters (size:"22pt")`
|
||||
|
||||
<<wikitext-example-without-html """{{$:/core/images/print-button|16px}}
|
||||
<$transclude $tiddler="$:/core/images/print-button" size="32px"/>
|
||||
""">>
|
||||
|
||||
In the above example, the first line shows a simple transclusion of [[$:/core/images/print-button]] icon with `size` parameter passed by position and is set to 16px. The second line is a transclusion of image with `size` parameter passed by name and is set to 32px.
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
created: 20221007132845007
|
||||
modified: 20230419103154329
|
||||
modified: 20230518152756112
|
||||
tags: Pragmas
|
||||
title: Pragma: \procedure
|
||||
type: text/vnd.tiddlywiki
|
||||
@ -52,4 +52,59 @@ Procedure definitions can be nested by specifying the name of the procedure in t
|
||||
\end special-button
|
||||
|
||||
<<special-button>>
|
||||
""">>
|
||||
|
||||
! Use of Parameters Inside Procedures
|
||||
The parameters can be declared inside procedures. The parameters widget is necessary in a procedure if you want to use computed default values. For example:
|
||||
|
||||
<<wikitext-example-without-html
|
||||
src:"""\procedure myproc()
|
||||
<$parameters name={{$:/SiteTitle}} desc={{$:/SiteSubtitle}}>
|
||||
This is <<name>> demonstrates <<desc>>.
|
||||
</$parameters>
|
||||
\end
|
||||
|
||||
<<myproc>>
|
||||
""">>
|
||||
|
||||
!! Caution in Using Positional Parameters
|
||||
Procedures are a shortcut syntax for the SetVariableWidget with an implicit ParametersWidget, so generally there is no reason to have multiple parameters widgets within a definition. In the below example when passing `x` to `myproc`, it will also be set to `a`:
|
||||
|
||||
<<wikitext-example-without-html
|
||||
src:"""\procedure myproc(x:10)
|
||||
\parameters (a:100, b:200)
|
||||
|
||||
x=<<x>>, a=<<a>>, b=<<b>>
|
||||
\end
|
||||
|
||||
<<myproc 50>>
|
||||
""">>
|
||||
|
||||
The reason for that result is clearer if we consider an equivalent with explicit parameters widgets.
|
||||
|
||||
<$macrocall $name=wikitext-example-without-html
|
||||
src='<$let myprog="""
|
||||
\parameters (x:10)
|
||||
\parameters (a:100, b:200)
|
||||
|
||||
x=<<x>>, a=<<a>>, b=<<b>>
|
||||
""">
|
||||
<<myprog 50>>
|
||||
</$let>'
|
||||
/>
|
||||
|
||||
This is because those two parameters widgets are entirely independent. They are both processed as if the other parameter widget is not there.
|
||||
|
||||
<<.tip "The positional parameters are only required when using the parameterised transclusion shortcut syntax, and that in other cases it is generally clearer to use named parameters.">>
|
||||
|
||||
To prevent such situation of above example, pass parameters by name as below.
|
||||
|
||||
<<wikitext-example-without-html
|
||||
src:"""\procedure myproc(x:10)
|
||||
\parameters (a:100, b:200)
|
||||
|
||||
x=<<x>>, a=<<a>>, b=<<b>>
|
||||
\end
|
||||
|
||||
<<myproc x:50>>
|
||||
""">>
|
@ -6,15 +6,15 @@ type: text/vnd.tiddlywiki
|
||||
|
||||
!! Introduction
|
||||
|
||||
This tiddler describes the different ways in which [[macros|Procedures]] can be defined.
|
||||
This tiddler describes the different ways in which [[Procedures|Procedures]] can be defined.
|
||||
|
||||
!! Procedure Definition Pragma
|
||||
|
||||
Macros are created using the [[Pragma: \procedure]] at the start of a tiddler. The definitions are available in the rest of the tiddler that defines them, plus any tiddlers that it transcludes.
|
||||
Procedures are created using the [[Pragma: \procedure]] at the start of a tiddler. The definitions are available in the rest of the tiddler that defines them, plus any tiddlers that it transcludes.
|
||||
|
||||
```
|
||||
\define my-procedure(param)
|
||||
This is the macro text (param=<<param>>)
|
||||
This is the procedure text (param=<<param>>)
|
||||
\end
|
||||
```
|
||||
|
||||
|
@ -17,14 +17,6 @@ It looks like this browser doesn't run JavaScript. You can use one of these stat
|
||||
|
||||
---
|
||||
|
||||
{{HelloThere}}
|
||||
|
||||
{{TiddlyWiki}}
|
||||
|
||||
{{Features}}
|
||||
|
||||
{{Community}}
|
||||
|
||||
{{HelpingTiddlyWiki}}
|
||||
|
||||
</$reveal>
|
||||
|
@ -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.
|
||||
|
@ -1,4 +1,4 @@
|
||||
caption: currentTiddler
|
||||
caption: thisTiddler
|
||||
created: 20230304122810114
|
||||
modified: 20230505200086200
|
||||
tags: Variables [[Core Variables]]
|
||||
|
@ -4,6 +4,10 @@ tags: [[WebServer Authentication]]
|
||||
title: WebServer Header Authentication
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
Header authentication is a web integration technique enabling external entities to securely pass details of the authenticated user to an application. It is commonly used for "single sign on" in corporate environments.
|
||||
Header authentication is a web integration technique enabling external entities to securely pass details of the authenticated user to an application.
|
||||
|
||||
Header authentication is activated if is configured via the [[authenticated-user-header|WebServer Parameter: authenticated-user-header]]
|
||||
|
||||
!! Usage in SSO
|
||||
|
||||
Header authentication is commonly used for "single sign on" in corporate environments. When doing header authentication, the user is not prompted for a username and password on TiddlyWiki. Instead, the user is required to login at a SSO proxy server. When the user authenticates themselves to the SSO proxy server, the proxy server redirects the user request to the TiddlyWiki server with this additional request header containing the username. Then TiddlyWiki server is able to use the value of this request header to identify the user.
|
@ -1,8 +1,16 @@
|
||||
caption: authenticated-user-header
|
||||
created: 20180630180213047
|
||||
modified: 20180702140416583
|
||||
modified: 20230522184416583
|
||||
tags: [[WebServer Parameters]]
|
||||
title: WebServer Parameter: authenticated-user-header
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
The [[web server configuration parameter|WebServer Parameters]] ''authenticated-user-header'' activates [[header authentication|WebServer Header Authentication]] by specifying the name of the HTTP header that will be used to pass the username to TiddlyWiki.
|
||||
The [[web server configuration parameter|WebServer Parameters]] ''authenticated-user-header'' activates [[header authentication|WebServer Header Authentication]] by specifying the name of the HTTP header field that will be used to pass the username to TiddlyWiki.
|
||||
|
||||
For example, if the ''authenticated-user-header'' is set to ''X-Authenticated-User'', then the HTTP request must include a header field ''X-Authenticated-User'' with a value that is the username:
|
||||
|
||||
```http
|
||||
X-Authenticated-User: JeremyRuston
|
||||
```
|
||||
|
||||
<<.from-version "5.3.0">> Value of this header field should be URI-encoded before transit on the client (using `encodeURIComponent` JS function or [[encodeuricomponent Operator]]), and will be URI-decoded by the server.
|
@ -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
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
caption: fill
|
||||
created: 20220909111836951
|
||||
modified: 20230419103154328
|
||||
modified: 20230511123456782
|
||||
tags: Widgets
|
||||
title: FillWidget
|
||||
type: text/vnd.tiddlywiki
|
||||
@ -9,7 +9,7 @@ type: text/vnd.tiddlywiki
|
||||
|
||||
<<.from-version "5.3.0">> The <<.wlink FillWidget>> widget is used within a <<.wlink TranscludeWidget>> widget to specify the content that should be copied to the named "slot". Slots are defined by the <<.wlink SlotWidget>> widget within the transcluded content.
|
||||
|
||||
See the <<.wlink TranscludeWidget>> widget for details.
|
||||
See the <<.wlink TranscludeWidget>> widget for details and an example. More examples can be found in the <<.wlink SlotWidget>> widget documentation.
|
||||
|
||||
! Attributes
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
caption: parameters
|
||||
created: 20220909111836951
|
||||
modified: 20230419103154328
|
||||
modified: 20230518134032228
|
||||
tags: Widgets
|
||||
title: ParametersWidget
|
||||
type: text/vnd.tiddlywiki
|
||||
@ -48,14 +48,5 @@ These attributes provide low level access to the contents of the transcluding wi
|
||||
* The `$slotFillParseTreeNodes` attribute provides access to the raw parse tree nodes corresponding to the filled slots within the contents of the transcluding widget. Represented in JSON as an object with keys of the slot name and values being an array of parse tree nodes
|
||||
|
||||
! Examples
|
||||
{{ParametersWidget (Examples)}}
|
||||
|
||||
Here the <<.wlink ParametersWidget>> widget is used to declare a parameter whose default value is transcluded from another tiddler.
|
||||
|
||||
<$macrocall $name='wikitext-example-without-html'
|
||||
src="""\procedure mymacro()
|
||||
<$parameters name={{$:/SiteTitle}} age="21">
|
||||
My name is <<name>> and my age is <<age>>.
|
||||
</$parameters>
|
||||
\end
|
||||
|
||||
<$transclude $variable="mymacro" age="19"/>"""/>
|
||||
|
@ -1,6 +1,6 @@
|
||||
caption: slot
|
||||
created: 20220909111836951
|
||||
modified: 20230419103154329
|
||||
modified: 20230511123922283
|
||||
tags: Widgets
|
||||
title: SlotWidget
|
||||
type: text/vnd.tiddlywiki
|
||||
@ -17,3 +17,59 @@ The content of the <<.wlink SlotWidget>> widget is used as a fallback for the sl
|
||||
|
||||
|!Attribute |!Description |
|
||||
|$name |The name of the slot being defined |
|
||||
|$depth |Optional number indicating how deep the <<.wlink SlotWidget>> widget is compared to the matching <<.wlink FillWidget>> widget as measured by the number of nested transclude widgets (defaults to 1). Transclude widgets whose <<.attr $fillignore>> attribute is set to ''yes'' are ignored, and do not affect the depth count |
|
||||
|
||||
! Examples
|
||||
|
||||
!! Quoted content
|
||||
When content contains quotes, passing it through attributes and parameters can be challenging. However, passing the content using the <<.wlink FillWidget>> widget content eliminates the need to wrap it in quotes, making the process easier.
|
||||
|
||||
<$let bold_slot='<b>
|
||||
<$slot $name="body"/>
|
||||
</b>
|
||||
'>
|
||||
|
||||
If a variable named <<.var bold_slot>> contains the following <<.wlink SlotWidget>> definition:
|
||||
<$codeblock code={{{[[bold_slot]getvariable[]]}}}/>
|
||||
|
||||
then the slot can be filled using this variable transclusion:
|
||||
|
||||
<<wikitext-example-without-html src:'<$transclude $variable=bold_slot>
|
||||
<$fill $name=body>
|
||||
|
||||
"""
|
||||
some text
|
||||
using [[Hard Linebreaks in WikiText]]
|
||||
syntax
|
||||
"""
|
||||
</$fill>
|
||||
</$transclude>
|
||||
'>>
|
||||
</$let>
|
||||
|
||||
!! Depth
|
||||
|
||||
<$let table_slot="|!depth|!slot1|!slot2|
|
||||
|1|<$slot $name=slot1/>|<$slot $name=slot2/>|
|
||||
|2|<$slot $name=slot1 $depth=2>missing</$slot>|<$slot $name=slot2 $depth=2>missing</$slot>|
|
||||
"
|
||||
table_fill="""<$transclude $variable=table_slot $mode=block>
|
||||
<$fill $name=slot1>outer1</$fill>
|
||||
<$fill $name=slot2>outer2
|
||||
<$transclude $variable=table_slot $mode=block>
|
||||
<$fill $name=slot1>inner1</$fill>
|
||||
<$fill $name=slot2>inner2</$fill>
|
||||
</$transclude>
|
||||
</$fill>
|
||||
</$transclude>
|
||||
""">
|
||||
|
||||
If a variable named <<.var table_slot>> contains the following <<.wlink SlotWidget>> definition:
|
||||
|
||||
<$codeblock code={{{[[table_slot]getvariable[]]}}}/>
|
||||
|
||||
then the slot values can be filled at different transclusion depths:
|
||||
|
||||
<$transclude $variable="wikitext-example-without-html" src=<<table_fill>>/>
|
||||
|
||||
The <<.var slot1>> slot is filled at both depths with a simple string (outer1 and outer2). For <<.var slot2>>, the outer instance is a simple string but the inner instance recursively transcludes the same <<.var table_slot>> variable again. The recursion ends at the third transclusion call since both "inner" slots are filled with simple strings.
|
@ -1,6 +1,6 @@
|
||||
caption: transclude
|
||||
created: 20130824142500000
|
||||
modified: 20230419103154329
|
||||
modified: 20230511022612458
|
||||
tags: Widgets
|
||||
title: TranscludeWidget
|
||||
type: text/vnd.tiddlywiki
|
||||
@ -51,6 +51,7 @@ Modern mode is recommended for use in new applications.
|
||||
|$type |– |Optional ContentType used when transcluding variables, indexes or fields other than the ''text'' field|
|
||||
|$output |- |ContentType for the output rendering (defaults to `text/html`, can also be `text/plain` or `text/raw`) |
|
||||
|$recursionMarker |recursionMarker |Set to ''no'' to prevent creation of [[Legacy Transclusion Recursion Marker]] (defaults to ''yes'') |
|
||||
|$fillignore |- |Set to ''yes'' to make this transclusion invisible to the <<.attr $depth>> attribute of the <<.wlink SlotWidget>> widget (defaults to ''no'') |
|
||||
|//{attributes not starting with $}// |– |Any other attributes that do not start with a dollar are used as parameters to the transclusion |
|
||||
|//{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 used as parameters to the transclusion, but with the name changed to use a single dollar sign |
|
||||
@ -145,7 +146,7 @@ The output will be equivalent to:
|
||||
</li>
|
||||
</ol>
|
||||
```
|
||||
|
||||
See <<.wlink SlotWidget>> for more examples.
|
||||
|
||||
! Missing Transclusion Targets
|
||||
|
||||
|
@ -0,0 +1,39 @@
|
||||
created: 20230518124403282
|
||||
modified: 20230518135109977
|
||||
tags: ParametersWidget
|
||||
title: ParametersWidget (Examples)
|
||||
|
||||
''Example i'': Shows transclusion of [[Sample Tiddler Template]]. The template tiddler has two parameters `name` and `age` and here their default values are used.
|
||||
|
||||
<$macrocall $name=".example" n="1" eg="""<$transclude $tiddler="Sample Tiddler Template" />"""/>
|
||||
|
||||
''Example ii'': Shows, another transclusion of [[Sample Tiddler Template]], here the value of `age` is passed, but `name` uses its default value.
|
||||
|
||||
<$macrocall $name=".example" n="2" eg="""<$transclude $tiddler="Sample Tiddler Template" age=33/>"""/>
|
||||
|
||||
''Example iii'': Shows, another transclusion of [[Sample Tiddler Template]], here the value of both `name` and `age` are passed.
|
||||
|
||||
<$macrocall $name=".example" n="3" eg="""<$transclude $tiddler="Sample Tiddler Template" age=45 name="Jeremy Ruston" />"""/>
|
||||
|
||||
In the simple form the above transclusion is equivalent to
|
||||
|
||||
<$macrocall $name=".example" n="3.1" eg="""{{Sample Tiddler Template|Jeremy Ruston|45}}"""/>
|
||||
|
||||
In this simple form, parameters passed by position not by name. So the first value is passed to the first parameter, here `name` and the second value is passed to the second parameter, here `age`.
|
||||
|
||||
''Remarks''
|
||||
|
||||
# Passing parameter by name is good practice and is recommended for clarity. So for parameterized transclusions, the use of <<.wid transclude>> is recommended over simple form transclusion.
|
||||
# When passing parameters value by position, you cannot pass the second parameter while the first one has not been passed.
|
||||
|
||||
|
||||
''Example iv'': Here the <<.wlink ParametersWidget>> widget is used to declare a parameter whose default value is transcluded from another tiddler.
|
||||
|
||||
<$macrocall $name=".example" n="4" eg="""\procedure myproc()
|
||||
<$parameters name={{$:/SiteTitle}} age="21">
|
||||
My name is <<name>> and my age is <<age>>.
|
||||
</$parameters>
|
||||
\end
|
||||
|
||||
<$transclude $variable="myproc" age="19"/>
|
||||
"""/>
|
@ -0,0 +1,9 @@
|
||||
created: 20230518124140604
|
||||
description: This example tiddler is used to illustrate some of the new features in Parameterized Transclusions
|
||||
modified: 20230518125337219
|
||||
tags: [[ParametersWidget Examples]] Demonstrations
|
||||
title: Sample Tiddler Template
|
||||
|
||||
<$parameters name=Jeremy age="21">
|
||||
My name is <<name>> and my age is <<age>>.
|
||||
</$parameters>
|
@ -18,7 +18,7 @@ listen 命令使用[[命名的命令参数|NamedCommandParameters]]:
|
||||
* ''anon-username'' - 匿名用户的编辑署名
|
||||
* ''username'' - 可选的基础验证用户名称
|
||||
* ''password'' - 可选的基础验证密码
|
||||
* ''authenticated-user-header'' - 可选的标头名称,用于受信任身份验证
|
||||
* ''authenticated-user-header'' - 可选的请求标头名称,用于受信任身份验证
|
||||
* ''readers'' - 允许读取此维基,以逗号分隔的用户名称的清单
|
||||
* ''writers'' - 允许写入此维基,以逗号分隔的用户名称的清单
|
||||
* ''csrf-disable'' - 设置为 "yes" 以禁用 CSRF 检查 (默认为 "no")
|
||||
|
@ -18,7 +18,7 @@ listen 命令使用[[命名的命令參數|NamedCommandParameters]]:
|
||||
* ''anon-username'' - 匿名使用者的編輯署名
|
||||
* ''username'' - 可選的基本驗證使用者名稱
|
||||
* ''password'' - 可選的基本驗證密碼
|
||||
* ''authenticated-user-header'' - 可選的標頭名稱,用於受信任身份驗證
|
||||
* ''authenticated-user-header'' - 可選的 HTTP 請求功能參數名稱,用於受信任身份驗證
|
||||
* ''readers'' - 允許讀取此維基,以逗號分隔的使用者名稱的清單
|
||||
* ''writers'' - 允許寫入此維基,以逗號分隔的使用者名稱的清單
|
||||
* ''csrf-disable'' - 設定為 "yes" 以停用 CSRF 檢查 (預設為 "no")
|
||||
|
@ -529,3 +529,7 @@ HuanC Fu, @hffqyd, 2023/03/03
|
||||
Michelle Saad, @michsa, 2023-03-08
|
||||
|
||||
Yukai Chou, @muzimuzhi, 2023-04-07
|
||||
|
||||
Carmine Guida, @carmineguida, 2023-05-17
|
||||
|
||||
Tavin Cole, @tavin, 2023/05/25
|
||||
|
@ -62,7 +62,7 @@ CecilyStoryView.prototype.remove = function(widget) {
|
||||
duration = $tw.utils.getAnimationDuration();
|
||||
// Remove the widget at the end of the transition
|
||||
setTimeout(function() {
|
||||
widget.destroy();
|
||||
widget.removeChildDomNodes();
|
||||
},duration);
|
||||
// Animate the closure
|
||||
$tw.utils.setStyle(targetElement,[
|
||||
|
@ -0,0 +1,4 @@
|
||||
title: $:/language/codemirror/
|
||||
|
||||
showTrailingSpace/hint: Show trailing space
|
||||
showTrailingSpace/info: Trailing space on each line will be decorated as per theme CSS.
|
@ -0,0 +1,3 @@
|
||||
title: $:/config/codemirror/showTrailingSpace
|
||||
type: bool
|
||||
text: true
|
@ -0,0 +1,5 @@
|
||||
.cm-trailingspace {
|
||||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAACCAYAAAB/qH1jAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3QUXCToH00Y1UgAAACFJREFUCNdjPMDBUc/AwNDAAAFMTAwMDA0OP34wQgX/AQBYgwYEx4f9lQAAAABJRU5ErkJggg==);
|
||||
background-position: bottom left;
|
||||
background-repeat: repeat-x;
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: https://codemirror.net/5/LICENSE
|
||||
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
mod(require("../../lib/codemirror"));
|
||||
else if (typeof define == "function" && define.amd) // AMD
|
||||
define(["../../lib/codemirror"], mod);
|
||||
else // Plain browser env
|
||||
mod(CodeMirror);
|
||||
})(function(CodeMirror) {
|
||||
CodeMirror.defineOption("showTrailingSpace", false, function(cm, val, prev) {
|
||||
if (prev == CodeMirror.Init) prev = false;
|
||||
if (prev && !val)
|
||||
cm.removeOverlay("trailingspace");
|
||||
else if (!prev && val)
|
||||
cm.addOverlay({
|
||||
token: function(stream) {
|
||||
for (var l = stream.string.length, i = l; i && /\s/.test(stream.string.charAt(i - 1)); --i) {}
|
||||
if (i > stream.pos) { stream.pos = i; return null; }
|
||||
stream.pos = l;
|
||||
return "trailingspace";
|
||||
},
|
||||
name: "trailingspace"
|
||||
});
|
||||
});
|
||||
});
|
19
plugins/tiddlywiki/codemirror-trailingspace/files/tiddlywiki.files
Executable file
19
plugins/tiddlywiki/codemirror-trailingspace/files/tiddlywiki.files
Executable file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"tiddlers": [
|
||||
{
|
||||
"file": "addon/edit/trailingspace.css",
|
||||
"fields": {
|
||||
"type": "text/css",
|
||||
"title": "$:/plugins/tiddlywiki/codemirror/addon/edit/trailingspace.css",
|
||||
"tags": "[[$:/tags/Stylesheet]]"
|
||||
}
|
||||
},{
|
||||
"file": "addon/edit/trailingspace.js",
|
||||
"fields": {
|
||||
"type": "application/javascript",
|
||||
"title": "$:/plugins/tiddlywiki/codemirror/addon/edit/trailingspace.js",
|
||||
"module-type": "codemirror"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
7
plugins/tiddlywiki/codemirror-trailingspace/plugin.info
Executable file
7
plugins/tiddlywiki/codemirror-trailingspace/plugin.info
Executable file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"title": "$:/plugins/tiddlywiki/codemirror-trailingspace",
|
||||
"name": "CodeMirror Show Trailing Space",
|
||||
"description": "Show trailing space in CodeMirror",
|
||||
"parent-plugin": "$:/plugins/tiddlywiki/codemirror",
|
||||
"list": "readme"
|
||||
}
|
7
plugins/tiddlywiki/codemirror-trailingspace/readme.tid
Executable file
7
plugins/tiddlywiki/codemirror-trailingspace/readme.tid
Executable file
@ -0,0 +1,7 @@
|
||||
title: $:/plugins/tiddlywiki/codemirror-trailingspace/readme
|
||||
|
||||
This plugin contains the [[trailingspace|https://codemirror.net/5/doc/manual.html#addon_trailingspace]]
|
||||
addon for CodeMirror, and provides a default style (red squiggles).
|
||||
|
||||
First install the [[CodeMirror plugin|$:/plugins/tiddlywiki/codemirror]].
|
||||
|
@ -0,0 +1,11 @@
|
||||
title: $:/core/ui/ControlPanel/Settings/codemirror/showTrailingSpace
|
||||
tags: $:/tags/ControlPanel/Settings/CodeMirror
|
||||
caption: {{$:/language/codemirror/showTrailingSpace/hint}}
|
||||
|
||||
\define lingo-base() $:/language/codemirror/showTrailingSpace/
|
||||
<<lingo hint>>
|
||||
|
||||
<$checkbox tiddler="$:/config/codemirror/showTrailingSpace" field="text" checked="true" unchecked="false" default="true">
|
||||
<$link to="$:/config/codemirror/showTrailingSpace"><<lingo info>></$link>
|
||||
</$checkbox>
|
||||
|
@ -10,7 +10,7 @@
|
||||
},{
|
||||
"file": "codemirror.css",
|
||||
"fields": {
|
||||
"type": "text/vnd.tiddlywiki",
|
||||
"type": "text/css",
|
||||
"title": "$:/plugins/tiddlywiki/codemirror/lib/codemirror.css",
|
||||
"tags": "[[$:/tags/Stylesheet]]"
|
||||
}
|
||||
|
@ -80,7 +80,7 @@ StackedListView.prototype.insert = function(widget) {
|
||||
};
|
||||
|
||||
StackedListView.prototype.remove = function(widget) {
|
||||
widget.destroy();
|
||||
widget.removeChildDomNodes();
|
||||
};
|
||||
|
||||
exports.stacked = StackedListView;
|
||||
|
@ -3118,6 +3118,30 @@ select {
|
||||
background: <<colour select-tag-background>>;
|
||||
}
|
||||
|
||||
/*
|
||||
** Translink macro
|
||||
*/
|
||||
|
||||
.tc-translink {
|
||||
background-color: <<colour pre-background>>;
|
||||
border: 1px solid <<colour pre-border>>;
|
||||
padding: 0 3px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
div.tc-translink > div {
|
||||
margin: 1em;
|
||||
}
|
||||
|
||||
div.tc-translink > div > a:first-child > h1 {
|
||||
font-size: 1.2em;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
span.tc-translink > a:first-child {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/*
|
||||
** Classes for displaying globals
|
||||
*/
|
||||
@ -3234,4 +3258,4 @@ select {
|
||||
|
||||
.tc-tiny-v-gap-bottom {
|
||||
margin-bottom: 3px;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user