diff --git a/bin/build-site.sh b/bin/build-site.sh index 7f56e6d30..b77a18434 100755 --- a/bin/build-site.sh +++ b/bin/build-site.sh @@ -5,7 +5,7 @@ # Default to the current version number for building the plugin library if [ -z "$TW5_BUILD_VERSION" ]; then - TW5_BUILD_VERSION=v5.2.6 + TW5_BUILD_VERSION=v5.2.8 fi echo "Using TW5_BUILD_VERSION as [$TW5_BUILD_VERSION]" diff --git a/bin/clean.sh b/bin/clean.sh index 522479edb..5a56e1971 100755 --- a/bin/clean.sh +++ b/bin/clean.sh @@ -2,4 +2,4 @@ # Remove any output files -find . -regex "^./editions/[a-z0-9\.-]*/output/.*" -delete +find . -regex "^./editions/.*/output/.*" -delete diff --git a/boot/boot.js b/boot/boot.js index 89fafce6a..44dd5b4e3 100644 --- a/boot/boot.js +++ b/boot/boot.js @@ -1920,7 +1920,7 @@ $tw.loadTiddlersFromSpecification = function(filepath,excludeRegExp) { // Read the specification var filesInfo = $tw.utils.parseJSONSafe(fs.readFileSync(filepath + path.sep + "tiddlywiki.files","utf8")); // Helper to process a file - var processFile = function(filename,isTiddlerFile,fields,isEditableFile) { + var processFile = function(filename,isTiddlerFile,fields,isEditableFile,rootPath) { var extInfo = $tw.config.fileExtensionInfo[path.extname(filename)], type = (extInfo || {}).type || fields.type || "text/plain", typeInfo = $tw.config.contentTypeInfo[type] || {}, @@ -1941,6 +1941,12 @@ $tw.loadTiddlersFromSpecification = function(filepath,excludeRegExp) { } else { var value = tiddler[name]; switch(fieldInfo.source) { + case "subdirectories": + value = path.relative(rootPath, filename).split('/').slice(0, -1); + break; + case "filepath": + value = path.relative(rootPath, filename); + break; case "filename": value = path.basename(filename); break; @@ -2023,7 +2029,7 @@ $tw.loadTiddlersFromSpecification = function(filepath,excludeRegExp) { var thisPath = path.relative(filepath, files[t]), filename = path.basename(thisPath); if(filename !== "tiddlywiki.files" && !metaRegExp.test(filename) && fileRegExp.test(filename)) { - processFile(thisPath,dirSpec.isTiddlerFile,dirSpec.fields,dirSpec.isEditableFile); + processFile(thisPath,dirSpec.isTiddlerFile,dirSpec.fields,dirSpec.isEditableFile,dirSpec.path); } } } else { diff --git a/core/modules/editor/engines/framed.js b/core/modules/editor/engines/framed.js index b4f700f2b..948890645 100644 --- a/core/modules/editor/engines/framed.js +++ b/core/modules/editor/engines/framed.js @@ -162,13 +162,13 @@ FramedEngine.prototype.fixHeight = function() { if(this.widget.editAutoHeight) { if(this.domNode && !this.domNode.isTiddlyWikiFakeDom) { var newHeight = $tw.utils.resizeTextAreaToFit(this.domNode,this.widget.editMinHeight); - this.iframeNode.style.height = (newHeight + 14) + "px"; // +14 for the border on the textarea + this.iframeNode.style.height = newHeight + "px"; } } else { var fixedHeight = parseInt(this.widget.wiki.getTiddlerText(HEIGHT_VALUE_TITLE,"400px"),10); fixedHeight = Math.max(fixedHeight,20); this.domNode.style.height = fixedHeight + "px"; - this.iframeNode.style.height = (fixedHeight + 14) + "px"; + this.iframeNode.style.height = fixedHeight + "px"; } } }; diff --git a/core/modules/filterrunprefixes/cascade.js b/core/modules/filterrunprefixes/cascade.js index da6894d21..486e75f45 100644 --- a/core/modules/filterrunprefixes/cascade.js +++ b/core/modules/filterrunprefixes/cascade.js @@ -25,20 +25,10 @@ exports.cascade = function(operationSubFunction,options) { if(!filterFnList[index]) { filterFnList[index] = options.wiki.compileFilter(filter); } - var output = filterFnList[index](options.wiki.makeTiddlerIterator([title]),{ - getVariable: function(name,opts) { - opts = opts || {}; - opts.variables = { - "currentTiddler": "" + title, - "..currentTiddler": widget.getVariable("currentTiddler") - }; - if(name in opts.variables) { - return opts.variables[name]; - } else { - return widget.getVariable(name,opts); - } - } - }); + var output = filterFnList[index](options.wiki.makeTiddlerIterator([title]),widget.makeFakeWidgetWithVariables({ + "currentTiddler": "" + title, + "..currentTiddler": widget.getVariable("currentTiddler","") + })); if(output.length !== 0) { result = output[0]; return false; diff --git a/core/modules/filterrunprefixes/filter.js b/core/modules/filterrunprefixes/filter.js index 783b699c2..4ab057109 100644 --- a/core/modules/filterrunprefixes/filter.js +++ b/core/modules/filterrunprefixes/filter.js @@ -19,23 +19,13 @@ exports.filter = function(operationSubFunction,options) { var resultsToRemove = [], index = 0; results.each(function(title) { - var filtered = operationSubFunction(options.wiki.makeTiddlerIterator([title]),{ - getVariable: function(name,opts) { - opts = opts || {}; - opts.variables = { - "currentTiddler": "" + title, - "..currentTiddler": widget.getVariable("currentTiddler"), - "index": "" + index, - "revIndex": "" + (results.length - 1 - index), - "length": "" + results.length - }; - if(name in opts.variables) { - return opts.variables[name]; - } else { - return widget.getVariable(name,opts); - } - } - }); + var filtered = operationSubFunction(options.wiki.makeTiddlerIterator([title]),widget.makeFakeWidgetWithVariables({ + "currentTiddler": "" + title, + "..currentTiddler": widget.getVariable("currentTiddler",""), + "index": "" + index, + "revIndex": "" + (results.length - 1 - index), + "length": "" + results.length + })); if(filtered.length === 0) { resultsToRemove.push(title); } diff --git a/core/modules/filterrunprefixes/map.js b/core/modules/filterrunprefixes/map.js index efcb5b534..b756d6699 100644 --- a/core/modules/filterrunprefixes/map.js +++ b/core/modules/filterrunprefixes/map.js @@ -21,23 +21,13 @@ exports.map = function(operationSubFunction,options) { flatten = (suffixes[0] && suffixes[0][0] === "flat") ? true : false; results.clear(); $tw.utils.each(inputTitles,function(title) { - var filtered = operationSubFunction(options.wiki.makeTiddlerIterator([title]),{ - getVariable: function(name,opts) { - opts = opts || {}; - opts.variables = { - "currentTiddler": "" + title, - "..currentTiddler": widget.getVariable("currentTiddler"), - "index": "" + index, - "revIndex": "" + (inputTitles.length - 1 - index), - "length": "" + inputTitles.length - }; - if(name in opts.variables) { - return opts.variables[name]; - } else { - return widget.getVariable(name,opts); - } - } - }); + var filtered = operationSubFunction(options.wiki.makeTiddlerIterator([title]),widget.makeFakeWidgetWithVariables({ + "currentTiddler": "" + title, + "..currentTiddler": widget.getVariable("currentTiddler",""), + "index": "" + index, + "revIndex": "" + (inputTitles.length - 1 - index), + "length": "" + inputTitles.length + })); if(filtered.length && flatten) { $tw.utils.each(filtered,function(value) { results.push(value); diff --git a/core/modules/filterrunprefixes/reduce.js b/core/modules/filterrunprefixes/reduce.js index 8fe819e3f..ee2998837 100644 --- a/core/modules/filterrunprefixes/reduce.js +++ b/core/modules/filterrunprefixes/reduce.js @@ -18,24 +18,14 @@ exports.reduce = function(operationSubFunction,options) { var accumulator = "", index = 0; results.each(function(title) { - var list = operationSubFunction(options.wiki.makeTiddlerIterator([title]),{ - getVariable: function(name,opts) { - opts = opts || {}; - opts.variables = { - "currentTiddler": "" + title, - "..currentTiddler": widget.getVariable("currentTiddler"), - "index": "" + index, - "revIndex": "" + (results.length - 1 - index), - "length": "" + results.length, - "accumulator": "" + accumulator - }; - if(name in opts.variables) { - return opts.variables[name]; - } else { - return widget.getVariable(name,opts); - } - } - }); + var list = operationSubFunction(options.wiki.makeTiddlerIterator([title]),widget.makeFakeWidgetWithVariables({ + "currentTiddler": "" + title, + "..currentTiddler": widget.getVariable("currentTiddler"), + "index": "" + index, + "revIndex": "" + (results.length - 1 - index), + "length": "" + results.length, + "accumulator": "" + accumulator + })); if(list.length > 0) { accumulator = "" + list[0]; } diff --git a/core/modules/filterrunprefixes/sort.js b/core/modules/filterrunprefixes/sort.js index 6865b175c..d8d376126 100644 --- a/core/modules/filterrunprefixes/sort.js +++ b/core/modules/filterrunprefixes/sort.js @@ -25,20 +25,10 @@ exports.sort = function(operationSubFunction,options) { indexes = new Array(inputTitles.length), compareFn; results.each(function(title) { - var key = operationSubFunction(options.wiki.makeTiddlerIterator([title]),{ - getVariable: function(name,opts) { - opts = opts || {}; - opts.variables = { - "currentTiddler": "" + title, - "..currentTiddler": widget.getVariable("currentTiddler") - }; - if(name in opts.variables) { - return opts.variables[name]; - } else { - return widget.getVariable(name,opts); - } - } - }); + var key = operationSubFunction(options.wiki.makeTiddlerIterator([title]),widget.makeFakeWidgetWithVariables({ + "currentTiddler": "" + title, + "..currentTiddler": widget.getVariable("currentTiddler") + })); sortKeys.push(key[0] || ""); }); results.clear(); diff --git a/core/modules/filters.js b/core/modules/filters.js index 1bb5fe9ff..b705c994c 100644 --- a/core/modules/filters.js +++ b/core/modules/filters.js @@ -255,19 +255,21 @@ exports.compileFilter = function(filterString) { var operands = [], operatorFunction; if(!operator.operator) { + // Use the "title" operator if no operator is specified operatorFunction = filterOperators.title; } else if(!filterOperators[operator.operator]) { - operatorFunction = filterOperators.field; + // Unknown operators treated as "[unknown]" - at run time we can distinguish between a custom operator and falling back to the default "field" operator + operatorFunction = filterOperators["[unknown]"]; } else { + // Use the operator function operatorFunction = filterOperators[operator.operator]; } - $tw.utils.each(operator.operands,function(operand) { if(operand.indirect) { operand.value = self.getTextReference(operand.text,"",currTiddlerTitle); } else if(operand.variable) { var varTree = $tw.utils.parseFilterVariable(operand.text); - operand.value = widget.getVariable(varTree.name,{params:varTree.params,defaultValue: ""}); + operand.value = widget.evaluateVariable(varTree.name,{params: varTree.params, source: source})[0] || ""; } else { operand.value = operand.text; } diff --git a/core/modules/filters/filter.js b/core/modules/filters/filter.js index 9b69fd83a..f15cbefc5 100644 --- a/core/modules/filters/filter.js +++ b/core/modules/filters/filter.js @@ -20,19 +20,10 @@ exports.filter = function(source,operator,options) { results = [], target = operator.prefix !== "!"; source(function(tiddler,title) { - var list = filterFn.call(options.wiki,options.wiki.makeTiddlerIterator([title]),{ - getVariable: function(name,opts) { - opts = opts || {}; - switch(name) { - case "currentTiddler": - return "" + title; - case "..currentTiddler": - return options.widget.getVariable("currentTiddler"); - default: - return options.widget.getVariable(name,opts); - } - } - }); + var list = filterFn.call(options.wiki,options.wiki.makeTiddlerIterator([title]),options.widget.makeFakeWidgetWithVariables({ + "currentTiddler": "" + title, + "..currentTiddler": options.widget.getVariable("currentTiddler","") + })); if((list.length > 0) === target) { results.push(title); } diff --git a/core/modules/filters/function.js b/core/modules/filters/function.js new file mode 100644 index 000000000..f6a8c034d --- /dev/null +++ b/core/modules/filters/function.js @@ -0,0 +1,32 @@ +/*\ +title: $:/core/modules/filters/function.js +type: application/javascript +module-type: filteroperator + +Filter operator returning those input titles that are returned from a function + +\*/ +(function(){ + +/*jslint node: true, browser: true */ +/*global $tw: false */ +"use strict"; + +/* +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); + if(variableInfo && variableInfo.srcVariable && variableInfo.srcVariable.isFunctionDefinition) { + return options.widget.evaluateVariable(functionName,{params: operator.operands.slice(1), source: source}); + } + // Return the input list if the function wasn't found + var results = []; + source(function(tiddler,title) { + results.push(title); + }); + return results; +}; + +})(); diff --git a/core/modules/filters/reduce.js b/core/modules/filters/reduce.js index 50c501f08..efe8aea4a 100644 --- a/core/modules/filters/reduce.js +++ b/core/modules/filters/reduce.js @@ -26,27 +26,14 @@ exports.reduce = function(source,operator,options) { accumulator = operator.operands[1] || ""; for(var index=0; index 0) { accumulator = "" + list[0]; } diff --git a/core/modules/filters/sortsub.js b/core/modules/filters/sortsub.js index e9f676daa..d328be09c 100644 --- a/core/modules/filters/sortsub.js +++ b/core/modules/filters/sortsub.js @@ -25,19 +25,10 @@ exports.sortsub = function(source,operator,options) { inputTitles.push(title); var r = filterFn.call(options.wiki,function(iterator) { iterator(options.wiki.getTiddler(title),title); - },{ - getVariable: function(name,opts) { - opts = opts || {}; - switch(name) { - case "currentTiddler": - return "" + title; - case "..currentTiddler": - return options.widget.getVariable("currentTiddler"); - default: - return options.widget.getVariable(name,opts); - } - } - }); + },options.widget.makeFakeWidgetWithVariables({ + "currentTiddler": "" + title, + "..currentTiddler": options.widget.getVariable("currentTiddler") + })); sortKeys.push(r[0] || ""); }); // Rather than sorting the titles array, we'll sort the indexes so that we can consult both arrays diff --git a/core/modules/filters/strings.js b/core/modules/filters/strings.js index 60a36265d..538dd0597 100644 --- a/core/modules/filters/strings.js +++ b/core/modules/filters/strings.js @@ -74,6 +74,113 @@ exports.join = makeStringReducingOperator( },null ); +var dmp = require("$:/core/modules/utils/diff-match-patch/diff_match_patch.js"); + +exports.levenshtein = makeStringBinaryOperator( + function(a,b) { + var dmpObject = new dmp.diff_match_patch(), + diffs = dmpObject.diff_main(a,b); + return [dmpObject.diff_levenshtein(diffs) + ""]; + } +); + +// these two functions are adapted from https://github.com/google/diff-match-patch/wiki/Line-or-Word-Diffs +function diffLineWordMode(text1,text2,mode) { + var dmpObject = new dmp.diff_match_patch(); + var a = diffPartsToChars(text1,text2,mode); + var lineText1 = a.chars1; + var lineText2 = a.chars2; + var lineArray = a.lineArray; + var diffs = dmpObject.diff_main(lineText1,lineText2,false); + dmpObject.diff_charsToLines_(diffs,lineArray); + return diffs; +} + +function diffPartsToChars(text1,text2,mode) { + var lineArray = []; + var lineHash = {}; + lineArray[0] = ''; + + function diff_linesToPartsMunge_(text,mode) { + var chars = ''; + var lineStart = 0; + var lineEnd = -1; + var lineArrayLength = lineArray.length, + regexpResult; + var searchRegexp = /\W+/g; + while(lineEnd < text.length - 1) { + if(mode === "words") { + regexpResult = searchRegexp.exec(text); + lineEnd = searchRegexp.lastIndex; + if(regexpResult === null) { + lineEnd = text.length; + } + lineEnd = --lineEnd; + } else { + lineEnd = text.indexOf('\n', lineStart); + if(lineEnd == -1) { + lineEnd = text.length - 1; + } + } + var line = text.substring(lineStart, lineEnd + 1); + + if(lineHash.hasOwnProperty ? lineHash.hasOwnProperty(line) : (lineHash[line] !== undefined)) { + chars += String.fromCharCode(lineHash[line]); + } else { + if (lineArrayLength == maxLines) { + line = text.substring(lineStart); + lineEnd = text.length; + } + chars += String.fromCharCode(lineArrayLength); + lineHash[line] = lineArrayLength; + lineArray[lineArrayLength++] = line; + } + lineStart = lineEnd + 1; + } + return chars; + } + var maxLines = 40000; + var chars1 = diff_linesToPartsMunge_(text1,mode); + maxLines = 65535; + var chars2 = diff_linesToPartsMunge_(text2,mode); + return {chars1: chars1, chars2: chars2, lineArray: lineArray}; +}; + +exports.makepatches = function(source,operator,options) { + var dmpObject = new dmp.diff_match_patch(), + suffix = operator.suffix || "", + result = []; + + source(function(tiddler,title) { + var diffs, patches; + if(suffix === "lines" || suffix === "words") { + diffs = diffLineWordMode(title,operator.operand,suffix); + patches = dmpObject.patch_make(title,diffs); + } else { + patches = dmpObject.patch_make(title,operator.operand); + } + Array.prototype.push.apply(result,[dmpObject.patch_toText(patches)]); + }); + + return result; +}; + +exports.applypatches = makeStringBinaryOperator( + function(a,b) { + var dmpObject = new dmp.diff_match_patch(), + patches; + try { + patches = dmpObject.patch_fromText(b); + } catch(e) { + } + if(patches) { + return [dmpObject.patch_apply(patches,a)[0]]; + } else { + return [a]; + } + } +); + function makeStringBinaryOperator(fnCalc) { return function(source,operator,options) { var result = []; @@ -184,4 +291,4 @@ exports.charcode = function(source,operator,options) { return [chars.join("")]; }; -})(); +})(); \ No newline at end of file diff --git a/core/modules/filters/unknown.js b/core/modules/filters/unknown.js new file mode 100644 index 000000000..21856766b --- /dev/null +++ b/core/modules/filters/unknown.js @@ -0,0 +1,45 @@ +/*\ +title: $:/core/modules/filters/unknown.js +type: application/javascript +module-type: filteroperator + +Filter operator for handling unknown filter operators. + +Not intended to be used directly by end users, hence the square brackets around the name. + +\*/ +(function(){ + +/*jslint node: true, browser: true */ +/*global $tw: false */ +"use strict"; + +var fieldFilterOperatorFn = require("$:/core/modules/filters/field.js").field; + +/* +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.prefix === "!") { + var results = []; + source(function(tiddler,title) { + if(list.indexOf(title) === -1) { + results.push(title); + } + }); + return results; + } else { + return list; + } + } + } + // Otherwise, use the "field" operator + return fieldFilterOperatorFn(source,operator,options); +}; + +})(); diff --git a/core/modules/parsers/audioparser.js b/core/modules/parsers/audioparser.js index 95380bf80..5eb2ff985 100644 --- a/core/modules/parsers/audioparser.js +++ b/core/modules/parsers/audioparser.js @@ -28,6 +28,8 @@ var AudioParser = function(type,text,options) { element.attributes.src = {type: "string", value: "data:" + type + ";base64," + text}; } this.tree = [element]; + this.source = text; + this.type = type; }; exports["audio/ogg"] = AudioParser; diff --git a/core/modules/parsers/binaryparser.js b/core/modules/parsers/binaryparser.js index fb3d38678..60e7b5ef0 100644 --- a/core/modules/parsers/binaryparser.js +++ b/core/modules/parsers/binaryparser.js @@ -23,7 +23,7 @@ var BinaryParser = function(type,text,options) { children: [{ type: "transclude", attributes: { - tiddler: {type: "string", value: BINARY_WARNING_MESSAGE} + "$tiddler": {type: "string", value: BINARY_WARNING_MESSAGE} } }] }; @@ -38,7 +38,7 @@ var BinaryParser = function(type,text,options) { children: [{ type: "transclude", attributes: { - tiddler: {type: "string", value: EXPORT_BUTTON_IMAGE} + "$tiddler": {type: "string", value: EXPORT_BUTTON_IMAGE} } }] }; @@ -64,6 +64,8 @@ var BinaryParser = function(type,text,options) { children: [warn, link] } this.tree = [element]; + this.source = text; + this.type = type; }; exports["application/octet-stream"] = BinaryParser; diff --git a/core/modules/parsers/csvparser.js b/core/modules/parsers/csvparser.js index 40431d0ae..f40b5f0e5 100644 --- a/core/modules/parsers/csvparser.js +++ b/core/modules/parsers/csvparser.js @@ -52,6 +52,8 @@ var CsvParser = function(type,text,options) { tag = "td"; this.tree[0].children[0].children[0].children.push(row); } + this.source = text; + this.type = type; }; exports["text/csv"] = CsvParser; diff --git a/core/modules/parsers/htmlparser.js b/core/modules/parsers/htmlparser.js index 206ab9c78..24c9f5d3e 100644 --- a/core/modules/parsers/htmlparser.js +++ b/core/modules/parsers/htmlparser.js @@ -29,6 +29,8 @@ var HtmlParser = function(type,text,options) { if($tw.wiki.getTiddlerText("$:/config/HtmlParser/DisableSandbox","no") !== "yes") { this.tree[0].attributes.sandbox = {type: "string", value: $tw.wiki.getTiddlerText("$:/config/HtmlParser/SandboxTokens","")}; } + this.source = text; + this.type = type; }; exports["text/html"] = HtmlParser; diff --git a/core/modules/parsers/imageparser.js b/core/modules/parsers/imageparser.js index e3b8fb60a..a964a4ba8 100644 --- a/core/modules/parsers/imageparser.js +++ b/core/modules/parsers/imageparser.js @@ -28,6 +28,8 @@ var ImageParser = function(type,text,options) { } } this.tree = [element]; + this.source = text; + this.type = type; }; exports["image/svg+xml"] = ImageParser; diff --git a/core/modules/parsers/parseutils.js b/core/modules/parsers/parseutils.js index 1c7525588..6a0902c6f 100644 --- a/core/modules/parsers/parseutils.js +++ b/core/modules/parsers/parseutils.js @@ -84,8 +84,7 @@ exports.parseTokenString = function(source,pos,token) { }; /* -Look for a token matching a regex at a specified position. Returns null if not found, otherwise returns {type: "regexp", match:, start:, end:,} -Use the "Y" (sticky) flag to avoid searching the entire rest of the string +Look for a token matching a regex. Returns null if not found, otherwise returns {type: "regexp", match:, start:, end:,} */ exports.parseTokenRegExp = function(source,pos,reToken) { var node = { @@ -124,6 +123,36 @@ exports.parseStringLiteral = function(source,pos) { } }; +/* +Returns an array of {name:} with an optional "default" property. Options include: +requireParenthesis: require the parameter definition to be wrapped in parenthesis +*/ +exports.parseParameterDefinition = function(paramString,options) { + options = options || {}; + if(options.requireParenthesis) { + var parenMatch = /^\s*\((.*)\)\s*$/g.exec(paramString); + if(!parenMatch) { + return []; + } + paramString = parenMatch[1]; + } + var params = [], + reParam = /\s*([^:),\s]+)(?:\s*:\s*(?:"""([\s\S]*?)"""|"([^"]*)"|'([^']*)'|([^,"'\s]+)))?/mg, + paramMatch = reParam.exec(paramString); + while(paramMatch) { + // Save the parameter details + var paramInfo = {name: paramMatch[1]}, + defaultValue = paramMatch[2] || paramMatch[3] || paramMatch[4] || paramMatch[5]; + if(defaultValue !== undefined) { + paramInfo["default"] = defaultValue; + } + params.push(paramInfo); + // Look for the next parameter + paramMatch = reParam.exec(paramString); + } + return params; +}; + exports.parseMacroParameters = function(node,source,pos) { // Process parameters var parameter = $tw.utils.parseMacroParameter(source,pos); @@ -146,7 +175,7 @@ exports.parseMacroParameter = function(source,pos) { start: pos }; // Define our regexp - var reMacroParameter = /(?:([A-Za-z0-9\-_]+)\s*:)?(?:\s*(?:"""([\s\S]*?)"""|"([^"]*)"|'([^']*)'|\[\[([^\]]*)\]\]|((?:(?:>(?!>))|[^\s>"'])+)))/y; + var reMacroParameter = /(?:([A-Za-z0-9\-_]+)\s*:)?(?:\s*(?:"""([\s\S]*?)"""|"([^"]*)"|'([^']*)'|\[\[([^\]]*)\]\]|((?:(?:>(?!>))|[^\s>"'])+)))/g; // Skip whitespace pos = $tw.utils.skipWhiteSpace(source,pos); // Look for the parameter @@ -176,7 +205,36 @@ exports.parseMacroParameter = function(source,pos) { }; /* -Look for a macro invocation. Returns null if not found, or {type: "macrocall", name:, parameters:, start:, end:} +Look for a macro invocation. Returns null if not found, or {type: "transclude", attributes:, start:, end:} +*/ +exports.parseMacroInvocationAsTransclusion = function(source,pos) { + var node = $tw.utils.parseMacroInvocation(source,pos); + if(node) { + var positionalName = 0, + transclusion = { + type: "transclude", + start: node.start, + end: node.end + }; + $tw.utils.addAttributeToParseTreeNode(transclusion,"$variable",node.name); + $tw.utils.each(node.params,function(param) { + var name = param.name; + if(name) { + if(name.charAt(0) === "$") { + name = "$" + name; + } + $tw.utils.addAttributeToParseTreeNode(transclusion,{name: name,type: "string", value: param.value, start: param.start, end: param.end}); + } else { + $tw.utils.addAttributeToParseTreeNode(transclusion,{name: (positionalName++) + "",type: "string", value: param.value, start: param.start, end: param.end}); + } + }); + return transclusion; + } + return node; +}; + +/* +Look for a macro invocation. Returns null if not found, or {type: "macrocall", name:, params:, start:, end:} */ exports.parseMacroInvocation = function(source,pos) { var node = { @@ -185,7 +243,7 @@ exports.parseMacroInvocation = function(source,pos) { params: [] }; // Define our regexps - var reMacroName = /([^\s>"'=]+)/y; + var reMacroName = /([^\s>"'=]+)/g; // Skip whitespace pos = $tw.utils.skipWhiteSpace(source,pos); // Look for a double less than sign @@ -222,7 +280,7 @@ exports.parseFilterVariable = function(source) { params: [], }, pos = 0, - reName = /([^\s"']+)/y; + reName = /([^\s"']+)/g; // If there is no whitespace or it is an empty string then there are no macro parameters if(/^\S*$/.test(source)) { node.name = source; @@ -247,10 +305,10 @@ exports.parseAttribute = function(source,pos) { start: pos }; // Define our regexps - var reAttributeName = /([^\/\s>"'=]+)/y, - reUnquotedAttribute = /([^\/\s<>"'=]+)/y, - reFilteredValue = /\{\{\{([\S\s]+?)\}\}\}/y, - reIndirectValue = /\{\{([^\}]+)\}\}/y; + var reAttributeName = /([^\/\s>"'=]+)/g, + reUnquotedAttribute = /([^\/\s<>"'=]+)/g, + reFilteredValue = /\{\{\{([\S\s]+?)\}\}\}/g, + reIndirectValue = /\{\{([^\}]+)\}\}/g; // Skip whitespace pos = $tw.utils.skipWhiteSpace(source,pos); // Get the attribute name diff --git a/core/modules/parsers/pdfparser.js b/core/modules/parsers/pdfparser.js index 19d4253d7..c7830bf69 100644 --- a/core/modules/parsers/pdfparser.js +++ b/core/modules/parsers/pdfparser.js @@ -25,6 +25,8 @@ var ImageParser = function(type,text,options) { element.attributes.src = {type: "string", value: "data:application/pdf;base64," + text}; } this.tree = [element]; + this.source = text; + this.type = type; }; exports["application/pdf"] = ImageParser; diff --git a/core/modules/parsers/textparser.js b/core/modules/parsers/textparser.js index 4f55f6f0c..06b08f30f 100644 --- a/core/modules/parsers/textparser.js +++ b/core/modules/parsers/textparser.js @@ -20,6 +20,8 @@ var TextParser = function(type,text,options) { language: {type: "string", value: type} } }]; + this.source = text; + this.type = type; }; exports["text/plain"] = TextParser; diff --git a/core/modules/parsers/videoparser.js b/core/modules/parsers/videoparser.js index f1c281c7c..1c8a38bb2 100644 --- a/core/modules/parsers/videoparser.js +++ b/core/modules/parsers/videoparser.js @@ -28,6 +28,8 @@ var VideoParser = function(type,text,options) { element.attributes.src = {type: "string", value: "data:" + type + ";base64," + text}; } this.tree = [element]; + this.source = text; + this.type = type; }; exports["video/ogg"] = VideoParser; diff --git a/core/modules/parsers/wikiparser/rules/fnprocdef.js b/core/modules/parsers/wikiparser/rules/fnprocdef.js new file mode 100644 index 000000000..5d0a8878b --- /dev/null +++ b/core/modules/parsers/wikiparser/rules/fnprocdef.js @@ -0,0 +1,97 @@ +/*\ +title: $:/core/modules/parsers/wikiparser/rules/fnprocdef.js +type: application/javascript +module-type: wikirule + +Wiki pragma rule for function, procedure and widget definitions + +``` +\function name(param:defaultvalue,param2:defaultvalue) +definition text +\end + +\procedure name(param:defaultvalue,param2:defaultvalue) +definition text +\end + +\widget $mywidget(param:defaultvalue,param2:defaultvalue) +definition text +\end +``` + +\*/ +(function(){ + +/*jslint node: true, browser: true */ +/*global $tw: false */ +"use strict"; + +exports.name = "fnprocdef"; +exports.types = {pragma: true}; + +/* +Instantiate parse rule +*/ +exports.init = function(parser) { + this.parser = parser; + // Regexp to match + this.matchRegExp = /^\\(function|procedure|widget)\s+([^(\s]+)\((\s*([^)]*))?\)(\s*\r?\n)?/mg; +}; + +/* +Parse the most recent match +*/ +exports.parse = function() { + // Move past the macro name and parameters + this.parser.pos = this.matchRegExp.lastIndex; + // Parse the parameters + var params = []; + if(this.match[3]) { + params = $tw.utils.parseParameterDefinition(this.match[4]); + } + // Is this a multiline definition? + var reEnd; + if(this.match[5]) { + // If so, the end of the body is marked with \end + reEnd = new RegExp("(\\r?\\n\\\\end[^\\S\\n\\r]*(?:" + $tw.utils.escapeRegExp(this.match[2]) + ")?(?:$|\\r?\\n))","mg"); + } else { + // Otherwise, the end of the definition is marked by the end of the line + reEnd = /($|\r?\n)/mg; + // Move past any whitespace + this.parser.pos = $tw.utils.skipWhiteSpace(this.parser.source,this.parser.pos); + } + // Find the end of the definition + reEnd.lastIndex = this.parser.pos; + var text, + endMatch = reEnd.exec(this.parser.source); + if(endMatch) { + text = this.parser.source.substring(this.parser.pos,endMatch.index); + this.parser.pos = endMatch.index + endMatch[0].length; + } else { + // We didn't find the end of the definition, so we'll make it blank + text = ""; + } + // Save the macro definition + var parseTreeNodes = [{ + type: "set", + attributes: {}, + children: [], + params: params + }]; + $tw.utils.addAttributeToParseTreeNode(parseTreeNodes[0],"name",this.match[2]); + $tw.utils.addAttributeToParseTreeNode(parseTreeNodes[0],"value",text); + if(this.match[1] === "function") { + parseTreeNodes[0].isFunctionDefinition = true; + } else if(this.match[1] === "procedure") { + parseTreeNodes[0].isProcedureDefinition = true; + } else if(this.match[1] === "widget") { + parseTreeNodes[0].isWidgetDefinition = true; + } + if(this.parser.configTrimWhiteSpace) { + parseTreeNodes[0].configTrimWhiteSpace = true; + } + return parseTreeNodes; +}; + +})(); + \ No newline at end of file diff --git a/core/modules/parsers/wikiparser/rules/html.js b/core/modules/parsers/wikiparser/rules/html.js index fdaae03ba..64469e3b2 100644 --- a/core/modules/parsers/wikiparser/rules/html.js +++ b/core/modules/parsers/wikiparser/rules/html.js @@ -48,7 +48,7 @@ exports.parse = function() { // Advance the parser position to past the tag this.parser.pos = tag.end; // Check for an immediately following double linebreak - var hasLineBreak = !tag.isSelfClosing && !!$tw.utils.parseTokenRegExp(this.parser.source,this.parser.pos,/([^\S\n\r]*\r?\n(?:[^\S\n\r]*\r?\n|$))/y); + var hasLineBreak = !tag.isSelfClosing && !!$tw.utils.parseTokenRegExp(this.parser.source,this.parser.pos,/([^\S\n\r]*\r?\n(?:[^\S\n\r]*\r?\n|$))/g); // Set whether we're in block mode tag.isBlock = this.is.block || hasLineBreak; // Parse the body if we need to @@ -78,7 +78,7 @@ exports.parseTag = function(source,pos,options) { orderedAttributes: [] }; // Define our regexps - var reTagName = /([a-zA-Z0-9\-\$]+)/y; + var reTagName = /([a-zA-Z0-9\-\$]+)/g; // Skip whitespace pos = $tw.utils.skipWhiteSpace(source,pos); // Look for a less than sign @@ -93,9 +93,6 @@ exports.parseTag = function(source,pos,options) { return null; } node.tag = token.match[1]; - if(node.tag.slice(1).indexOf("$") !== -1) { - return null; - } if(node.tag.charAt(0) === "$") { node.type = node.tag.substr(1); } @@ -129,7 +126,7 @@ exports.parseTag = function(source,pos,options) { pos = token.end; // Check for a required line break if(options.requireLineBreak) { - token = $tw.utils.parseTokenRegExp(source,pos,/([^\S\n\r]*\r?\n(?:[^\S\n\r]*\r?\n|$))/y); + token = $tw.utils.parseTokenRegExp(source,pos,/([^\S\n\r]*\r?\n(?:[^\S\n\r]*\r?\n|$))/g); if(!token) { return null; } diff --git a/core/modules/parsers/wikiparser/rules/image.js b/core/modules/parsers/wikiparser/rules/image.js index 9bfce99d2..6b379d9c5 100644 --- a/core/modules/parsers/wikiparser/rules/image.js +++ b/core/modules/parsers/wikiparser/rules/image.js @@ -116,7 +116,7 @@ exports.parseImage = function(source,pos) { // Skip whitespace pos = $tw.utils.skipWhiteSpace(source,pos); // Get the source up to the terminating `]]` - token = $tw.utils.parseTokenRegExp(source,pos,/(?:([^|\]]*?)\|)?([^\]]+?)\]\]/y); + token = $tw.utils.parseTokenRegExp(source,pos,/(?:([^|\]]*?)\|)?([^\]]+?)\]\]/g); if(!token) { return null; } diff --git a/core/modules/parsers/wikiparser/rules/macrocallblock.js b/core/modules/parsers/wikiparser/rules/macrocallblock.js index 6f50fdbb0..a2c10e04a 100644 --- a/core/modules/parsers/wikiparser/rules/macrocallblock.js +++ b/core/modules/parsers/wikiparser/rules/macrocallblock.js @@ -27,7 +27,7 @@ exports.findNextMatch = function(startPos) { var nextStart = startPos; // Try parsing at all possible macrocall openers until we match while((nextStart = this.parser.source.indexOf("<<",nextStart)) >= 0) { - var nextCall = $tw.utils.parseMacroInvocation(this.parser.source,nextStart); + var nextCall = $tw.utils.parseMacroInvocationAsTransclusion(this.parser.source,nextStart); if(nextCall) { var c = this.parser.source.charAt(nextCall.end); // Ensure EOL after parsed macro diff --git a/core/modules/parsers/wikiparser/rules/macrocallinline.js b/core/modules/parsers/wikiparser/rules/macrocallinline.js index 165a70dce..e9f79f09e 100644 --- a/core/modules/parsers/wikiparser/rules/macrocallinline.js +++ b/core/modules/parsers/wikiparser/rules/macrocallinline.js @@ -27,7 +27,7 @@ exports.findNextMatch = function(startPos) { var nextStart = startPos; // Try parsing at all possible macrocall openers until we match while((nextStart = this.parser.source.indexOf("<<",nextStart)) >= 0) { - this.nextCall = $tw.utils.parseMacroInvocation(this.parser.source,nextStart); + this.nextCall = $tw.utils.parseMacroInvocationAsTransclusion(this.parser.source,nextStart); if(this.nextCall) { return nextStart; } diff --git a/core/modules/parsers/wikiparser/rules/macrodef.js b/core/modules/parsers/wikiparser/rules/macrodef.js index 1d7ac9211..74a94a385 100644 --- a/core/modules/parsers/wikiparser/rules/macrodef.js +++ b/core/modules/parsers/wikiparser/rules/macrodef.js @@ -58,7 +58,7 @@ exports.parse = function() { var reEnd; if(this.match[3]) { // If so, the end of the body is marked with \end - reEnd = new RegExp("(\\r?\\n\\s*\\\\end[^\\S\\n\\r]*(?:" + $tw.utils.escapeRegExp(this.match[1]) + ")?(?:$|\\r?\\n))","mg"); + reEnd = new RegExp("(\\r?\\n[^\\S\\n\\r]*\\\\end[^\\S\\n\\r]*(?:" + $tw.utils.escapeRegExp(this.match[1]) + ")?(?:$|\\r?\\n))","mg"); } else { // Otherwise, the end of the definition is marked by the end of the line reEnd = /($|\r?\n)/mg; @@ -77,16 +77,16 @@ exports.parse = function() { text = ""; } // Save the macro definition - return [{ + var parseTreeNodes = [{ type: "set", - attributes: { - name: {type: "string", value: this.match[1]}, - value: {type: "string", value: text} - }, + attributes: {}, children: [], params: params, isMacroDefinition: true }]; + $tw.utils.addAttributeToParseTreeNode(parseTreeNodes[0],"name",this.match[1]); + $tw.utils.addAttributeToParseTreeNode(parseTreeNodes[0],"value",text); + return parseTreeNodes; }; })(); diff --git a/core/modules/parsers/wikiparser/rules/parameters.js b/core/modules/parsers/wikiparser/rules/parameters.js new file mode 100644 index 000000000..561c1c545 --- /dev/null +++ b/core/modules/parsers/wikiparser/rules/parameters.js @@ -0,0 +1,60 @@ +/*\ +title: $:/core/modules/parsers/wikiparser/rules/parameters.js +type: application/javascript +module-type: wikirule + +Wiki pragma rule for parameter definitions + +``` +\parameters(param:defaultvalue,param2:defaultvalue) +definition text +``` + +\*/ +(function(){ + +/*jslint node: true, browser: true */ +/*global $tw: false */ +"use strict"; + +exports.name = "parameters"; +exports.types = {pragma: true}; + +/* +Instantiate parse rule +*/ +exports.init = function(parser) { + this.parser = parser; + // Regexp to match + this.matchRegExp = /^\\parameters\s*\(([^)]*)\)\s*\r?\n/mg; +}; + +/* +Parse the most recent match +*/ +exports.parse = function() { + // Move past the macro name and parameters + this.parser.pos = this.matchRegExp.lastIndex; + // Parse the parameters + var params = $tw.utils.parseParameterDefinition(this.match[1]); + var attributes = Object.create(null), + orderedAttributes = []; + $tw.utils.each(params,function(param) { + var name = param.name; + // Parameter names starting with dollar must be escaped to double dollars for the parameters widget + if(name.charAt(0) === "$") { + name = "$" + name; + } + var attribute = {name: name, type: "string", value: param["default"] || ""}; + attributes[name] = attribute; + orderedAttributes.push(attribute); + }); + // Save the macro definition + return [{ + type: "parameters", + attributes: attributes, + orderedAttributes: orderedAttributes + }]; +}; + +})(); diff --git a/core/modules/parsers/wikiparser/rules/transcludeblock.js b/core/modules/parsers/wikiparser/rules/transcludeblock.js index 56a4f63b8..c033c2440 100644 --- a/core/modules/parsers/wikiparser/rules/transcludeblock.js +++ b/core/modules/parsers/wikiparser/rules/transcludeblock.js @@ -23,7 +23,7 @@ exports.types = {block: true}; exports.init = function(parser) { this.parser = parser; // Regexp to match - this.matchRegExp = /\{\{([^\{\}\|]*)(?:\|\|([^\|\{\}]+))?\}\}(?:\r?\n|$)/mg; + this.matchRegExp = /\{\{([^\{\}\|]*)(?:\|\|([^\|\{\}]+))?(?:\|([^\{\}]+))?\}\}(?:\r?\n|$)/mg; }; exports.parse = function() { @@ -31,13 +31,22 @@ exports.parse = function() { this.parser.pos = this.matchRegExp.lastIndex; // Get the match details var template = $tw.utils.trim(this.match[2]), - textRef = $tw.utils.trim(this.match[1]); + textRef = $tw.utils.trim(this.match[1]), + params = this.match[3] ? this.match[3].split("|") : []; // Prepare the transclude widget var transcludeNode = { type: "transclude", attributes: {}, isBlock: true }; + $tw.utils.each(params,function(paramValue,index) { + var name = "" + index; + transcludeNode.attributes[name] = { + name: name, + type: "string", + value: paramValue + } + }); // Prepare the tiddler widget var tr, targetTitle, targetField, targetIndex, tiddlerNode; if(textRef) { @@ -48,14 +57,14 @@ exports.parse = function() { tiddlerNode = { type: "tiddler", attributes: { - tiddler: {type: "string", value: targetTitle} + tiddler: {name: "tiddler", type: "string", value: targetTitle} }, isBlock: true, children: [transcludeNode] }; } if(template) { - transcludeNode.attributes.tiddler = {type: "string", value: template}; + transcludeNode.attributes["$tiddler"] = {name: "$tiddler", type: "string", value: template}; if(textRef) { return [tiddlerNode]; } else { @@ -63,12 +72,12 @@ exports.parse = function() { } } else { if(textRef) { - transcludeNode.attributes.tiddler = {type: "string", value: targetTitle}; + transcludeNode.attributes["$tiddler"] = {name: "$tiddler", type: "string", value: targetTitle}; if(targetField) { - transcludeNode.attributes.field = {type: "string", value: targetField}; + transcludeNode.attributes["$field"] = {name: "$field", type: "string", value: targetField}; } if(targetIndex) { - transcludeNode.attributes.index = {type: "string", value: targetIndex}; + transcludeNode.attributes["$index"] = {name: "$index", type: "string", value: targetIndex}; } return [tiddlerNode]; } else { diff --git a/core/modules/parsers/wikiparser/rules/transcludeinline.js b/core/modules/parsers/wikiparser/rules/transcludeinline.js index dbf39bfb6..3ce9dc78e 100644 --- a/core/modules/parsers/wikiparser/rules/transcludeinline.js +++ b/core/modules/parsers/wikiparser/rules/transcludeinline.js @@ -23,7 +23,7 @@ exports.types = {inline: true}; exports.init = function(parser) { this.parser = parser; // Regexp to match - this.matchRegExp = /\{\{([^\{\}\|]*)(?:\|\|([^\|\{\}]+))?\}\}/mg; + this.matchRegExp = /\{\{([^\{\}\|]*)(?:\|\|([^\|\{\}]+))?(?:\|([^\{\}]+))?\}\}/mg; }; exports.parse = function() { @@ -31,12 +31,21 @@ exports.parse = function() { this.parser.pos = this.matchRegExp.lastIndex; // Get the match details var template = $tw.utils.trim(this.match[2]), - textRef = $tw.utils.trim(this.match[1]); + textRef = $tw.utils.trim(this.match[1]), + params = this.match[3] ? this.match[3].split("|") : []; // Prepare the transclude widget var transcludeNode = { type: "transclude", attributes: {} }; + $tw.utils.each(params,function(paramValue,index) { + var name = "" + index; + transcludeNode.attributes[name] = { + name: name, + type: "string", + value: paramValue + } + }); // Prepare the tiddler widget var tr, targetTitle, targetField, targetIndex, tiddlerNode; if(textRef) { @@ -47,13 +56,13 @@ exports.parse = function() { tiddlerNode = { type: "tiddler", attributes: { - tiddler: {type: "string", value: targetTitle} + tiddler: {name: "tiddler", type: "string", value: targetTitle} }, children: [transcludeNode] }; } if(template) { - transcludeNode.attributes.tiddler = {type: "string", value: template}; + transcludeNode.attributes["$tiddler"] = {name: "$tiddler", type: "string", value: template}; if(textRef) { return [tiddlerNode]; } else { @@ -61,12 +70,12 @@ exports.parse = function() { } } else { if(textRef) { - transcludeNode.attributes.tiddler = {type: "string", value: targetTitle}; + transcludeNode.attributes["$tiddler"] = {name: "$tiddler", type: "string", value: targetTitle}; if(targetField) { - transcludeNode.attributes.field = {type: "string", value: targetField}; + transcludeNode.attributes["$field"] = {name: "$field", type: "string", value: targetField}; } if(targetIndex) { - transcludeNode.attributes.index = {type: "string", value: targetIndex}; + transcludeNode.attributes["$index"] = {name: "$index", type: "string", value: targetIndex}; } return [tiddlerNode]; } else { diff --git a/core/modules/parsers/wikiparser/wikiparser.js b/core/modules/parsers/wikiparser/wikiparser.js index 4c7419030..bb457b205 100644 --- a/core/modules/parsers/wikiparser/wikiparser.js +++ b/core/modules/parsers/wikiparser/wikiparser.js @@ -32,6 +32,7 @@ options: see below: parseAsInline: true to parse text as inline instead of block wiki: reference to wiki to use _canonical_uri: optional URI of content if text is missing or empty + configTrimWhiteSpace: true to trim whitespace */ var WikiParser = function(type,text,options) { this.wiki = options.wiki; @@ -46,7 +47,7 @@ var WikiParser = function(type,text,options) { this.source = text || ""; this.sourceLength = this.source.length; // Flag for ignoring whitespace - this.configTrimWhiteSpace = false; + this.configTrimWhiteSpace = options.configTrimWhiteSpace !== undefined ? options.configTrimWhiteSpace : false; // Parser mode this.parseAsInline = options.parseAsInline; // Set current parse position diff --git a/core/modules/widgets/fill.js b/core/modules/widgets/fill.js new file mode 100644 index 000000000..de88c95af --- /dev/null +++ b/core/modules/widgets/fill.js @@ -0,0 +1,30 @@ +/*\ +title: $:/core/modules/widgets/fill.js +type: application/javascript +module-type: widget + +Sub-widget used by the transclude widget for specifying values for slots within transcluded content. It doesn't do anything by itself because the transclude widget only ever deals with the parse tree nodes, and doesn't instantiate the widget itself + +\*/ +(function(){ + +/*jslint node: true, browser: true */ +/*global $tw: false */ +"use strict"; + +var Widget = require("$:/core/modules/widgets/widget.js").widget; + +var FillWidget = function(parseTreeNode,options) { + // Initialise + this.initialise(parseTreeNode,options); +}; + +/* +Inherit from the base widget class +*/ +FillWidget.prototype = new Widget(); + +exports.fill = FillWidget; + +})(); + \ No newline at end of file diff --git a/core/modules/widgets/importvariables.js b/core/modules/widgets/importvariables.js index a73abfdcf..aafc8ba8b 100644 --- a/core/modules/widgets/importvariables.js +++ b/core/modules/widgets/importvariables.js @@ -52,38 +52,44 @@ ImportVariablesWidget.prototype.execute = function(tiddlerList) { var parser = widgetPointer.wiki.parseTiddler(title,{parseAsInline:true}); if(parser) { var parseTreeNode = parser.tree[0]; - while(parseTreeNode && parseTreeNode.type === "set") { + while(parseTreeNode && ["setvariable","set","parameters"].indexOf(parseTreeNode.type) !== -1) { var node = { type: "set", attributes: parseTreeNode.attributes, params: parseTreeNode.params, - isMacroDefinition: parseTreeNode.isMacroDefinition + isMacroDefinition: parseTreeNode.isMacroDefinition, + isFunctionDefinition: parseTreeNode.isFunctionDefinition, + isProcedureDefinition: parseTreeNode.isProcedureDefinition, + isWidgetDefinition: parseTreeNode.isWidgetDefinition, + configTrimWhiteSpace: parseTreeNode.configTrimWhiteSpace }; - if (parseTreeNode.isMacroDefinition) { - // Macro definitions can be folded into - // current widget instead of adding - // another link to the chain. - var widget = widgetPointer.makeChildWidget(node); - widget.computeAttributes(); - widget.execute(); - // We SHALLOW copy over all variables - // in widget. We can't use - // $tw.utils.assign, because that copies - // up the prototype chain, which we - // don't want. - $tw.utils.each(Object.keys(widget.variables), function(key) { - widgetPointer.variables[key] = widget.variables[key]; - }); - } else { - widgetPointer.children = [widgetPointer.makeChildWidget(node)]; - // No more regenerating children for - // this widget. If it needs to refresh, - // it'll do so along with the the whole - // importvariable tree. - if (widgetPointer != this) { - widgetPointer.makeChildWidgets = function(){}; + if(parseTreeNode.type === "set" || parseTreeNode.type === "setvariable") { + if(parseTreeNode.isMacroDefinition || parseTreeNode.isProcedureDefinition || parseTreeNode.isWidgetDefinition || parseTreeNode.isFunctionDefinition) { + // Macro definitions can be folded into + // current widget instead of adding + // another link to the chain. + var widget = widgetPointer.makeChildWidget(node); + widget.computeAttributes(); + widget.execute(); + // We SHALLOW copy over all variables + // in widget. We can't use + // $tw.utils.assign, because that copies + // up the prototype chain, which we + // don't want. + $tw.utils.each(Object.keys(widget.variables), function(key) { + widgetPointer.variables[key] = widget.variables[key]; + }); + } else { + widgetPointer.children = [widgetPointer.makeChildWidget(node)]; + // No more regenerating children for + // this widget. If it needs to refresh, + // it'll do so along with the the whole + // importvariable tree. + if (widgetPointer != this) { + widgetPointer.makeChildWidgets = function(){}; + } + widgetPointer = widgetPointer.children[0]; } - widgetPointer = widgetPointer.children[0]; } parseTreeNode = parseTreeNode.children && parseTreeNode.children[0]; } diff --git a/core/modules/widgets/let.js b/core/modules/widgets/let.js index dd3aa137a..2b2886530 100644 --- a/core/modules/widgets/let.js +++ b/core/modules/widgets/let.js @@ -53,7 +53,9 @@ LetWidget.prototype.computeAttributes = function() { name = attribute.name; // Now that it's prepped, we're allowed to look this variable up // when defining later variables - self.currentValueFor[name] = value; + if(value !== undefined) { + self.currentValueFor[name] = value; + } }); // Run through again, setting variables and looking for differences $tw.utils.each(this.currentValueFor,function(value,name) { @@ -74,9 +76,7 @@ LetWidget.prototype.getVariableInfo = function(name,options) { text: this.currentValueFor[name] }; } - return Widget.prototype.getVariableInfo.call(this,name,$tw.utils.extend(Object.create(null),options,{ - defaultValue: "" - })); + return Widget.prototype.getVariableInfo.call(this,name,options); }; /* diff --git a/core/modules/widgets/macrocall.js b/core/modules/widgets/macrocall.js index 9de2e5d67..e49eadfe0 100644 --- a/core/modules/widgets/macrocall.js +++ b/core/modules/widgets/macrocall.js @@ -37,7 +37,7 @@ MacroCallWidget.prototype.render = function(parent,nextSibling) { Compute the internal state of the widget */ MacroCallWidget.prototype.execute = function() { - // Get the parse type if specified + this.macroName = this.parseTreeNode.name || this.getAttribute("$name"), this.parseType = this.getAttribute("$type","text/vnd.tiddlywiki"); this.renderOutput = this.getAttribute("$output","text/html"); // Merge together the parameters specified in the parse tree with the specified attributes @@ -47,49 +47,26 @@ MacroCallWidget.prototype.execute = function() { params.push({name: name, value: attribute}); } }); - // Get the macro value - var macroName = this.parseTreeNode.name || this.getAttribute("$name"), - variableInfo = this.getVariableInfo(macroName,{params: params}), - text = variableInfo.text, - parseTreeNodes; - // Are we rendering to HTML? - if(this.renderOutput === "text/html") { - // If so we'll return the parsed macro - // Check if we've already cached parsing this macro - var mode = this.parseTreeNode.isBlock ? "blockParser" : "inlineParser", - parser; - if(variableInfo.srcVariable && variableInfo.srcVariable[mode]) { - parser = variableInfo.srcVariable[mode]; - } else { - parser = this.wiki.parseText(this.parseType,text, - {parseAsInline: !this.parseTreeNode.isBlock}); - if(variableInfo.isCacheable && variableInfo.srcVariable) { - variableInfo.srcVariable[mode] = parser; - } - } - var parseTreeNodes = parser ? parser.tree : []; - // Wrap the parse tree in a vars widget assigning the parameters to variables named "__paramname__" - var attributes = {}; - $tw.utils.each(variableInfo.params,function(param) { - var name = "__" + param.name + "__"; - attributes[name] = { - name: name, - type: "string", - value: param.value - }; - }); + // Make a transclude widget + var positionalName = 0, parseTreeNodes = [{ - type: "vars", - attributes: attributes, - children: parseTreeNodes + type: "transclude", + isBlock: this.parseTreeNode.isBlock }]; - } else if(this.renderOutput === "text/raw") { - parseTreeNodes = [{type: "text", text: text}]; - } else { - // Otherwise, we'll render the text - var plainText = this.wiki.renderText("text/plain",this.parseType,text,{parentWidget: this}); - parseTreeNodes = [{type: "text", text: plainText}]; - } + $tw.utils.addAttributeToParseTreeNode(parseTreeNodes[0],"$variable",this.macroName); + $tw.utils.addAttributeToParseTreeNode(parseTreeNodes[0],"$type",this.parseType); + $tw.utils.addAttributeToParseTreeNode(parseTreeNodes[0],"$output",this.renderOutput); + $tw.utils.each(params,function(param) { + var name = param.name; + if(name) { + if(name.charAt(0) === "$") { + name = "$" + name; + } + $tw.utils.addAttributeToParseTreeNode(parseTreeNodes[0],name,param.value); + } else { + $tw.utils.addAttributeToParseTreeNode(parseTreeNodes[0],(positionalName++) + "",param.value); + } + }); // Construct the child widgets this.makeChildWidgets(parseTreeNodes); }; diff --git a/core/modules/widgets/parameters.js b/core/modules/widgets/parameters.js new file mode 100644 index 000000000..69194cb9e --- /dev/null +++ b/core/modules/widgets/parameters.js @@ -0,0 +1,96 @@ +/*\ +title: $:/core/modules/widgets/parameters.js +type: application/javascript +module-type: widget + +Widget for definition of transclusion parameters + +\*/ +(function(){ + +/*jslint node: true, browser: true */ +/*global $tw: false */ +"use strict"; + +var Widget = require("$:/core/modules/widgets/widget.js").widget, + TranscludeWidget = require("$:/core/modules/widgets/transclude.js").transclude; + +var ParametersWidget = function(parseTreeNode,options) { + // Initialise + this.initialise(parseTreeNode,options); +}; + +/* +Inherit from the base widget class +*/ +ParametersWidget.prototype = new Widget(); + +/* +Render this widget into the DOM +*/ +ParametersWidget.prototype.render = function(parent,nextSibling) { + // Call the constructor + Widget.call(this); + this.parentDomNode = parent; + this.computeAttributes(); + this.execute(); + this.renderChildren(parent,nextSibling); +}; + +/* +Compute the internal state of the widget +*/ +ParametersWidget.prototype.execute = function() { + var self = this; + this.parametersDepth = Math.max(parseInt(this.getAttribute("$depth","1"),10) || 1,1); + // Find the parent transclusions + var pointer = this.parentWidget, + depth = this.parametersDepth; + while(pointer) { + if(pointer instanceof TranscludeWidget) { + depth--; + if(depth <= 0) { + break; + } + } + pointer = pointer.parentWidget; + } + // Process each parameter + if(pointer instanceof TranscludeWidget) { + // Get the value for each defined parameter + $tw.utils.each($tw.utils.getOrderedAttributesFromParseTreeNode(self.parseTreeNode),function(attr,index) { + var name = attr.name; + // If the attribute name starts with $$ then reduce to a single dollar + if(name.substr(0,2) === "$$") { + name = name.substr(1); + } + var value = pointer.getTransclusionParameter(name,index,self.getAttribute(attr.name,"")); + self.setVariable(name,value); + }); + // Assign any metaparameters + $tw.utils.each(pointer.getTransclusionMetaParameters(),function(getValue,name) { + var variableName = self.getAttribute("$" + name); + if(variableName) { + self.setVariable(variableName,getValue(name)); + } + }); + } + // Construct the child widgets + this.makeChildWidgets(); +}; + +/* +Refresh the widget by ensuring our attributes are up to date +*/ +ParametersWidget.prototype.refresh = function(changedTiddlers) { + var changedAttributes = this.computeAttributes(); + if(Object.keys(changedAttributes).length) { + this.refreshSelf(); + return true; + } + return this.refreshChildren(changedTiddlers); +}; + +exports.parameters = ParametersWidget; + +})(); diff --git a/core/modules/widgets/setvariable.js b/core/modules/widgets/setvariable.js index cc97067c7..f8e98f390 100755 --- a/core/modules/widgets/setvariable.js +++ b/core/modules/widgets/setvariable.js @@ -48,7 +48,17 @@ SetWidget.prototype.execute = function() { this.setValue = this.getAttribute("value"); this.setEmptyValue = this.getAttribute("emptyValue"); // Set context variable - this.setVariable(this.setName,this.getValue(),this.parseTreeNode.params,!!this.parseTreeNode.isMacroDefinition); + if(this.parseTreeNode.isMacroDefinition) { + this.setVariable(this.setName,this.getValue(),this.parseTreeNode.params,true); + } else if(this.parseTreeNode.isFunctionDefinition) { + this.setVariable(this.setName,this.getValue(),this.parseTreeNode.params,undefined,{isFunctionDefinition: true}); + } else if(this.parseTreeNode.isProcedureDefinition) { + this.setVariable(this.setName,this.getValue(),this.parseTreeNode.params,undefined,{isProcedureDefinition: true, configTrimWhiteSpace: this.parseTreeNode.configTrimWhiteSpace}); + } else if(this.parseTreeNode.isWidgetDefinition) { + this.setVariable(this.setName,this.getValue(),this.parseTreeNode.params,undefined,{isWidgetDefinition: true, configTrimWhiteSpace: this.parseTreeNode.configTrimWhiteSpace}); + } else { + this.setVariable(this.setName,this.getValue()); + } // Construct the child widgets this.makeChildWidgets(); }; diff --git a/core/modules/widgets/slot.js b/core/modules/widgets/slot.js new file mode 100644 index 000000000..6fc402ac2 --- /dev/null +++ b/core/modules/widgets/slot.js @@ -0,0 +1,82 @@ +/*\ +title: $:/core/modules/widgets/slot.js +type: application/javascript +module-type: widget + +Widget for definition of slots within transcluded content. The values provided by the translusion are passed to the slot. + +\*/ +(function(){ + +/*jslint node: true, browser: true */ +/*global $tw: false */ +"use strict"; + +var Widget = require("$:/core/modules/widgets/widget.js").widget, + TranscludeWidget = require("$:/core/modules/widgets/transclude.js").transclude; + +var SlotWidget = function(parseTreeNode,options) { + // Initialise + this.initialise(parseTreeNode,options); +}; + +/* +Inherit from the base widget class +*/ +SlotWidget.prototype = new Widget(); + +/* +Render this widget into the DOM +*/ +SlotWidget.prototype.render = function(parent,nextSibling) { + // Call the constructor + Widget.call(this); + this.parentDomNode = parent; + this.computeAttributes(); + this.execute(); + this.renderChildren(parent,nextSibling); +}; + +/* +Compute the internal state of the widget +*/ +SlotWidget.prototype.execute = function() { + var self = this; + this.slotName = this.getAttribute("$name"); + this.slotDepth = parseInt(this.getAttribute("$depth","1"),10) || 1; + // Find the parent transclusions + var pointer = this.parentWidget, + depth = this.slotDepth; + while(pointer) { + if(pointer instanceof TranscludeWidget) { + depth--; + if(depth <= 0) { + break; + } + } + pointer = pointer.parentWidget; + } + var parseTreeNodes = [{type: "text", attributes: {text: {type: "string", value: "Missing slot reference!"}}}]; + if(pointer instanceof TranscludeWidget) { + // Get the parse tree nodes comprising the slot contents + parseTreeNodes = pointer.getTransclusionSlotFill(this.slotName,this.parseTreeNode.children); + } + // Construct the child widgets + this.makeChildWidgets(parseTreeNodes); +}; + +/* +Refresh the widget by ensuring our attributes are up to date +*/ +SlotWidget.prototype.refresh = function(changedTiddlers) { + var changedAttributes = this.computeAttributes(); + if(changedAttributes["$name"] || changedAttributes["$depth"]) { + this.refreshSelf(); + return true; + } + return this.refreshChildren(changedTiddlers); +}; + +exports.slot = SlotWidget; + +})(); diff --git a/core/modules/widgets/transclude.js b/core/modules/widgets/transclude.js index de8877e86..b0a84a13a 100755 --- a/core/modules/widgets/transclude.js +++ b/core/modules/widgets/transclude.js @@ -37,48 +37,349 @@ TranscludeWidget.prototype.render = function(parent,nextSibling) { Compute the internal state of the widget */ TranscludeWidget.prototype.execute = function() { - // Get our parameters - this.transcludeTitle = this.getAttribute("tiddler",this.getVariable("currentTiddler")); - this.transcludeSubTiddler = this.getAttribute("subtiddler"); - this.transcludeField = this.getAttribute("field"); - this.transcludeIndex = this.getAttribute("index"); - this.transcludeMode = this.getAttribute("mode"); - this.recursionMarker = this.getAttribute("recursionMarker","yes"); - // Parse the text reference + // Get our attributes, string parameters, and slot values into properties of the widget object + this.collectAttributes(); + this.collectStringParameters(); + this.collectSlotFillParameters(); + // Get the parse tree nodes that we are transcluding + var target = this.getTransclusionTarget(), + parseTreeNodes = target.parseTreeNodes; + this.sourceText = target.text; + this.sourceType = target.type; + this.parseAsInline = target.parseAsInline; + // Process the transclusion according to the output type + switch(this.transcludeOutput || "text/html") { + case "text/html": + // No further processing required + break; + case "text/raw": + // Just return the raw text + parseTreeNodes = [{type: "text", text: this.sourceText}]; + break; + default: + // text/plain + var plainText = this.wiki.renderText("text/plain",this.sourceType,this.sourceText,{parentWidget: this}); + parseTreeNodes = [{type: "text", text: plainText}]; + break; + } + // Set the legacy transclusion context variables only if we're not transcluding a variable + if(!this.transcludeVariable) { + var recursionMarker = this.makeRecursionMarker(); + this.setVariable("transclusion",recursionMarker); + } + // Construct the child widgets + this.makeChildWidgets(parseTreeNodes); +}; + +/* +Collect the attributes we need, in the process determining whether we're being used in legacy mode +*/ +TranscludeWidget.prototype.collectAttributes = function() { + var self = this; + // Detect legacy mode + this.legacyMode = true; + $tw.utils.each(this.attributes,function(value,name) { + if(name.charAt(0) === "$") { + self.legacyMode = false; + } + }); + // Get the attributes for the appropriate mode + if(this.legacyMode) { + this.transcludeTitle = this.getAttribute("tiddler",this.getVariable("currentTiddler")); + this.transcludeSubTiddler = this.getAttribute("subtiddler"); + this.transcludeField = this.getAttribute("field"); + this.transcludeIndex = this.getAttribute("index"); + this.transcludeMode = this.getAttribute("mode"); + this.recursionMarker = this.getAttribute("recursionMarker","yes"); + } else { + this.transcludeVariable = this.getAttribute("$variable"); + this.transcludeType = this.getAttribute("$type"); + this.transcludeOutput = this.getAttribute("$output","text/html"); + this.transcludeTitle = this.getAttribute("$tiddler",this.getVariable("currentTiddler")); + this.transcludeSubTiddler = this.getAttribute("$subtiddler"); + this.transcludeField = this.getAttribute("$field"); + this.transcludeIndex = this.getAttribute("$index"); + this.transcludeMode = this.getAttribute("$mode"); + this.recursionMarker = this.getAttribute("$recursionMarker","yes"); + } +}; + +/* +Collect string parameters +*/ +TranscludeWidget.prototype.collectStringParameters = function() { + var self = this; + this.stringParametersByName = Object.create(null); + if(!this.legacyMode) { + $tw.utils.each(this.attributes,function(value,name) { + if(name.charAt(0) === "$") { + if(name.charAt(1) === "$") { + // Attributes starting $$ represent parameters starting with a single $ + name = name.slice(1); + } else { + // Attributes starting with a single $ are reserved for the widget + return; + } + } + self.stringParametersByName[name] = value; + }); + } +}; + +/* +Collect slot value parameters +*/ +TranscludeWidget.prototype.collectSlotFillParameters = function() { + var self = this; + this.slotFillParseTrees = Object.create(null); + if(this.legacyMode) { + this.slotFillParseTrees["ts-missing"] = this.parseTreeNode.children; + } else { + this.slotFillParseTrees["ts-raw"] = this.parseTreeNode.children; + var noFillWidgetsFound = true, + searchParseTreeNodes = function(nodes) { + $tw.utils.each(nodes,function(node) { + if(node.type === "fill") { + if(node.attributes["$name"] && node.attributes["$name"].type === "string") { + var slotValueName = node.attributes["$name"].value; + self.slotFillParseTrees[slotValueName] = node.children || []; + } + noFillWidgetsFound = false; + } else { + searchParseTreeNodes(node.children); + } + }); + }; + searchParseTreeNodes(this.parseTreeNode.children); + if(noFillWidgetsFound) { + this.slotFillParseTrees["ts-missing"] = this.parseTreeNode.children; + } + } +}; + +/* +Get transcluded parse tree nodes as an object {parser:,text:,type:} +*/ +TranscludeWidget.prototype.getTransclusionTarget = function() { + var self = this; + // Determine whether we're being used in inline or block mode var parseAsInline = !this.parseTreeNode.isBlock; if(this.transcludeMode === "inline") { parseAsInline = true; } else if(this.transcludeMode === "block") { parseAsInline = false; } - var parser = this.wiki.parseTextReference( + 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: [{ + 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; + } + $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 { + // Transcluding a text reference + parser = this.wiki.parseTextReference( this.transcludeTitle, this.transcludeField, this.transcludeIndex, { parseAsInline: parseAsInline, - subTiddler: this.transcludeSubTiddler - }), - parseTreeNodes = parser ? parser.tree : this.parseTreeNode.children; - this.sourceText = parser ? parser.source : null; - this.parserType = parser? parser.type : null; - // Set context variables for recursion detection - var recursionMarker = this.makeRecursionMarker(); - if(this.recursionMarker === "yes") { - this.setVariable("transclusion",recursionMarker); + subTiddler: this.transcludeSubTiddler, + defaultType: this.transcludeType + }); } // Set 'thisTiddler' this.setVariable("thisTiddler",this.transcludeTitle); - // Check for recursion + // Return the parse tree if(parser) { - if(this.parentWidget && this.parentWidget.hasVariable("transclusion",recursionMarker)) { - parseTreeNodes = [{type: "error", attributes: { - "$message": {type: "string", value: $tw.language.getString("Error/RecursiveTransclusion")} - }}]; + return { + parser: parser, + parseTreeNodes: parser.tree, + parseAsInline: parseAsInline, + text: parser.source, + type: parser.type + }; + } else { + // If there's no parse tree then return the missing slot value + return { + parser: null, + parseTreeNodes: (this.slotFillParseTrees["ts-missing"] || []), + parseAsInline: parseAsInline, + text: null, + type: null + }; + } +}; + +/* +Fetch all the string parameters as an ordered array of {name:, value:} where the name is optional +*/ +TranscludeWidget.prototype.getOrderedTransclusionParameters = function() { + var result = []; + // Collect the parameters + for(var name in this.stringParametersByName) { + var value = this.stringParametersByName[name]; + result.push({name: name, value: value}); + } + // Sort numerical parameter names first + result.sort(function(a,b) { + var aIsNumeric = !isNaN(a.name), + bIsNumeric = !isNaN(b.name); + if(aIsNumeric && bIsNumeric) { + return a.name - b.name; + } else if(aIsNumeric) { + return -1; + } else if(bIsNumeric) { + return 1; + } else { + return a.name === b.name ? 0 : (a.name < b.name ? -1 : 1); + } + }); + // Remove names from numerical parameters + $tw.utils.each(result,function(param,index) { + if(!isNaN(param.name)) { + delete param.name; + } + }); + return result; +}; + +/* +Fetch the value of a parameter +*/ +TranscludeWidget.prototype.getTransclusionParameter = function(name,index,defaultValue) { + if(name in this.stringParametersByName) { + return this.stringParametersByName[name]; + } else { + var name = "" + index; + if(name in this.stringParametersByName) { + return this.stringParametersByName[name]; } } - // Construct the child widgets - this.makeChildWidgets(parseTreeNodes); + return defaultValue; +}; + +/* +Get one of the special parameters to be provided by the parameters widget +*/ +TranscludeWidget.prototype.getTransclusionMetaParameters = function() { + var self = this; + return { + "parseMode": function() { + return self.parseAsInline ? "inline" : "block"; + }, + "parseTreeNodes": function() { + return JSON.stringify(self.parseTreeNode.children || []); + }, + "slotFillParseTreeNodes": function() { + return JSON.stringify(self.slotFillParseTrees); + }, + "params": function() { + return JSON.stringify(self.stringParametersByName); + } + }; +}; + +/* +Fetch the value of a slot +*/ +TranscludeWidget.prototype.getTransclusionSlotFill = function(name,defaultParseTreeNodes) { + if(name && this.slotFillParseTrees[name] && this.slotFillParseTrees[name].length > 0) { + return this.slotFillParseTrees[name]; + } else { + return defaultParseTreeNodes || []; + } }; /* @@ -101,6 +402,7 @@ TranscludeWidget.prototype.makeRecursionMarker = function() { }; TranscludeWidget.prototype.parserNeedsRefresh = function() { + // Doesn't need to consider transcluded variables because a parent variable can't change once a widget has been created var parserInfo = this.wiki.getTextReferenceParserInfo(this.transcludeTitle,this.transcludeField,this.transcludeIndex,{subTiddler:this.transcludeSubTiddler}); return (this.sourceText === undefined || parserInfo.sourceText !== this.sourceText || parserInfo.parserType !== this.parserType) }; @@ -110,7 +412,7 @@ Selectively refreshes the widget if needed. Returns true if the widget or any of */ TranscludeWidget.prototype.refresh = function(changedTiddlers) { var changedAttributes = this.computeAttributes(); - if(($tw.utils.count(changedAttributes) > 0) || (changedTiddlers[this.transcludeTitle] && this.parserNeedsRefresh())) { + if(($tw.utils.count(changedAttributes) > 0) || (!this.transcludeVariable && changedTiddlers[this.transcludeTitle] && this.parserNeedsRefresh())) { this.refreshSelf(); return true; } else { diff --git a/core/modules/widgets/widget.js b/core/modules/widgets/widget.js index 60f55e8bb..741914fdc 100755 --- a/core/modules/widgets/widget.js +++ b/core/modules/widgets/widget.js @@ -41,10 +41,7 @@ Widget.prototype.initialise = function(parseTreeNode,options) { this.parseTreeNode = parseTreeNode; this.wiki = options.wiki; this.parentWidget = options.parentWidget; - this.variables = Object.create(null); - if(this.parentWidget) { - Object.setPrototypeOf(this.variables,this.parentWidget.variables); - } + this.variables = Object.create(this.parentWidget ? this.parentWidget.variables : null); this.document = options.document; this.attributes = {}; this.children = []; @@ -92,9 +89,22 @@ name: name of the variable value: value of the variable params: array of {name:, default:} for each parameter isMacroDefinition: true if the variable is set via a \define macro pragma (and hence should have variable substitution performed) +options includes: + isProcedureDefinition: true if the variable is set via a \procedure pragma (and hence should not have variable substitution performed) + isFunctionDefinition: true if the variable is set via a \function pragma (and hence should not have variable substitution performed) + isWidgetDefinition: true if the variable is set via a \widget pragma (and hence should not have variable substitution performed) */ -Widget.prototype.setVariable = function(name,value,params,isMacroDefinition) { - this.variables[name] = {value: value, params: params, isMacroDefinition: !!isMacroDefinition}; +Widget.prototype.setVariable = function(name,value,params,isMacroDefinition,options) { + options = options || {}; + this.variables[name] = { + value: value, + params: params, + isMacroDefinition: !!isMacroDefinition, + isFunctionDefinition: !!options.isFunctionDefinition, + isProcedureDefinition: !!options.isProcedureDefinition, + isWidgetDefinition: !!options.isWidgetDefinition, + configTrimWhiteSpace: !!options.configTrimWhiteSpace + }; }; /* @@ -104,6 +114,7 @@ options: see below Options include params: array of {name:, value:} for each parameter defaultValue: default value if the variable is not defined +allowSelfAssigned: if true, includes the current widget in the context chain instead of just the parent Returns an object with the following fields: @@ -112,21 +123,27 @@ text: text of variable, with parameters properly substituted */ Widget.prototype.getVariableInfo = function(name,options) { options = options || {}; - var actualParams = options.params || [], - parentWidget = this.parentWidget; + var self = this, + actualParams = options.params || [], + variable; + if(options.allowSelfAssigned) { + variable = this.variables[name]; + } else { + variable = this.parentWidget && this.parentWidget.variables[name]; + } // Check for the variable defined in the parent widget (or an ancestor in the prototype chain) - if(parentWidget && name in parentWidget.variables) { - var variable = parentWidget.variables[name], - originalValue = variable.value, + if(variable) { + var originalValue = variable.value, value = originalValue, - params = this.resolveVariableParameters(variable.params,actualParams); - // Substitute any parameters specified in the definition - $tw.utils.each(params,function(param) { - value = $tw.utils.replaceString(value,new RegExp("\\$" + $tw.utils.escapeRegExp(param.name) + "\\$","mg"),param.value); - }); - // Only substitute variable references if this variable was defined with the \define pragma + params = []; + // Only substitute parameter and variable references if this variable was defined with the \define pragma if(variable.isMacroDefinition) { - value = this.substituteVariableReferences(value,options); + params = self.resolveVariableParameters(variable.params,actualParams); + // Substitute any parameters specified in the definition + $tw.utils.each(params,function(param) { + value = $tw.utils.replaceString(value,new RegExp("\\$" + $tw.utils.escapeRegExp(param.name) + "\\$","mg"),param.value); + }); + value = self.substituteVariableReferences(value,options); } return { text: value, @@ -136,8 +153,13 @@ Widget.prototype.getVariableInfo = function(name,options) { }; } // If the variable doesn't exist in the parent widget then look for a macro module + var text = this.evaluateMacroModule(name,actualParams); + if(text === undefined) { + text = options.defaultValue; + } return { - text: this.evaluateMacroModule(name,actualParams,options.defaultValue) + text: text, + srcVariable: {} }; }; @@ -148,6 +170,11 @@ Widget.prototype.getVariable = function(name,options) { return this.getVariableInfo(name,options).text; }; +/* +Maps actual parameters onto formal parameters, returning an array of {name:,value:} objects +formalParams - Array of {name:,default:} (default value is optional) +actualParams - Array of string values or {name:,value:} (name is optional) +*/ Widget.prototype.resolveVariableParameters = function(formalParams,actualParams) { formalParams = formalParams || []; actualParams = actualParams || []; @@ -160,7 +187,7 @@ Widget.prototype.resolveVariableParameters = function(formalParams,actualParams) paramInfo = formalParams[p]; paramValue = undefined; for(var m=0; m 0) { + var letVariableWidget = { + type: "let", attributes: { - name: {type: "string", value: name}, - value: {type: "string", value: value} }, children: [] }; - currWidgetNode.children = [setVariableWidget]; - currWidgetNode = setVariableWidget; - }); + $tw.utils.each(options.variables,function(value,name) { + $tw.utils.addAttributeToParseTreeNode(letVariableWidget,name,"" + value); + }); + currWidgetNode.children = [letVariableWidget]; + currWidgetNode = letVariableWidget; + } // Add in the supplied parse tree nodes currWidgetNode.children = parser ? parser.tree : []; // Create the widget diff --git a/core/templates/external-js/save-all-external-js.tid b/core/templates/external-js/save-all-external-js.tid index 2616fed20..193b6e90c 100644 --- a/core/templates/external-js/save-all-external-js.tid +++ b/core/templates/external-js/save-all-external-js.tid @@ -5,7 +5,10 @@ title: $:/core/save/all-external-js \define saveTiddlerFilter() [is[tiddler]] -[prefix[$:/state/popup/]] -[prefix[$:/temp/]] -[prefix[$:/HistoryList]] -[status[pending]plugin-type[import]] -[[$:/core]] -[[$:/boot/boot.css]] -[type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] +[sort[title]] $(publishFilter)$ \end + + \define defaultCoreURL() %24%3A%2Fcore%2Ftemplates%2Ftiddlywiki5.js + <$let coreURL={{{ [[coreURL]is[variable]thenelse] }}}> {{$:/core/templates/tiddlywiki5-external-js.html}} diff --git a/core/ui/Components/VisibleTransclude.tid b/core/ui/Components/VisibleTransclude.tid new file mode 100644 index 000000000..cbc981abe --- /dev/null +++ b/core/ui/Components/VisibleTransclude.tid @@ -0,0 +1,48 @@ +title: $:/core/ui/VisibleTransclude + + +\widget $transclude() + +<$parameters tiddler="" $$tiddler="" mode="" $$mode="" $parseMode="@parseMode" $params="@params"> + + <$let + mode={{{ [[$mode]is[variable]then<$mode>!is[blank]] :else[[mode]is[variable]then!is[blank]] :else[<@parseMode>] }}} + outputTag={{{ [match[inline]then[span]else[div]] }}} + outputColour={{{ [match[inline]then[green]else[red]] }}} + > + + <$genesis $type=<> style="color:white;padding:4px;" style.background=<>> + <$genesis $type=<> style="display: inline-block;"> +
+ + <$list filter="[<@params>jsonindexes[]]" emptyMessage="(none)"> +
+ <$text text=<>/><$text text=": "/><$text text={{{ [<@params>jsonget] }}}/> +
+ +
+ + <$genesis $type=<> style="background:white;color:black;padding:4px;"> + + <$list filter="[<@params>jsonindexes[]] :filter[prefix[$]] +[limit[1]]" variable="ignore" emptyMessage=""" + + <$genesis $type="$transclude" $remappable="no" $names="[<@params>jsonindexes[]]" $values="[<@params>jsonindexes[]] :map[<@params>jsonget]" recursionMarker="no" mode=<>> + + <$slot $name="ts-raw" $depth="2"/> + + """> + + <$genesis $type="$transclude" $remappable="no" $names="[<@params>jsonindexes[]]" $values="[<@params>jsonindexes[]] :map[<@params>jsonget]" $$recursionMarker="no" $$mode=<>> + + <$slot $name="ts-raw" $depth="2"/> + + + + + + +\end diff --git a/core/ui/ViewToolbar/new-here.tid b/core/ui/ViewToolbar/new-here.tid index 25721f5fd..31e8e4158 100644 --- a/core/ui/ViewToolbar/new-here.tid +++ b/core/ui/ViewToolbar/new-here.tid @@ -6,7 +6,7 @@ description: {{$:/language/Buttons/NewHere/Hint}} \whitespace trim \define newHereActions() \whitespace trim -<$set name="tags" filter="[] [{$:/config/NewTiddler/Tags}]"> +<$set name="tags" filter="[] [enlist{$:/config/NewTiddler/Tags}]"> <$action-sendmessage $message="tm-new-tiddler" tags=<>/> \end diff --git a/core/wiki/config/OfficialPluginLibrary.tid b/core/wiki/config/OfficialPluginLibrary.tid index cddb5e1fc..20bb13d0d 100644 --- a/core/wiki/config/OfficialPluginLibrary.tid +++ b/core/wiki/config/OfficialPluginLibrary.tid @@ -1,6 +1,6 @@ title: $:/config/OfficialPluginLibrary tags: $:/tags/PluginLibrary -url: https://tiddlywiki.com/library/v5.2.6/index.html +url: https://tiddlywiki.com/library/v5.2.8/index.html caption: {{$:/language/OfficialPluginLibrary}} {{$:/language/OfficialPluginLibrary/Hint}} diff --git a/core/wiki/macros/tabs.tid b/core/wiki/macros/tabs.tid index f439e541d..bc8a0255f 100644 --- a/core/wiki/macros/tabs.tid +++ b/core/wiki/macros/tabs.tid @@ -60,4 +60,4 @@ code-body: yes -\end +\end \ No newline at end of file diff --git a/editions/de-AT/tiddlers/beispiele/TaskManagement.tid b/editions/de-AT/tiddlers/beispiele/TaskManagement.tid index 2bc4bd0c0..159676eae 100644 --- a/editions/de-AT/tiddlers/beispiele/TaskManagement.tid +++ b/editions/de-AT/tiddlers/beispiele/TaskManagement.tid @@ -1,11 +1,11 @@ created: 20140923173639039 creator: pmario -modified: 20140924155046340 +modified: 20230307080008193 modifier: pmario title: TaskManagement type: text/vnd.tiddlywiki -In dieser Edition sind folgende Task Management Varianten beschreiben: +In dieser Edition sind folgende Task Management Varianten beschrieben: <> diff --git a/editions/de-AT/tiddlers/beispiele/done.tid b/editions/de-AT/tiddlers/beispiele/done.tid index 9972856b7..626fa3f33 100644 --- a/editions/de-AT/tiddlers/beispiele/done.tid +++ b/editions/de-AT/tiddlers/beispiele/done.tid @@ -2,7 +2,7 @@ color: #37d011 created: 20140923104300415 creator: pmario icon: $:/core/images/done-button -modified: 20140923105208878 +modified: 20230307080039831 modifier: ChrisK tags: done title: done @@ -12,5 +12,5 @@ Diese Tag wird verwendet um "Tasks" als erledigt zu markieren. Siehe auch: -* [[Task Management]] .. Beispiel +* [[Task Management|TaskManagement]] .. Beispiel * [[Tag Manager|$:/TagManager]] .. Zuweisung der Farben und Symbole \ No newline at end of file diff --git a/editions/de-AT/tiddlers/howto/Importieren von Tiddlern.tid b/editions/de-AT/tiddlers/howto/Importieren von Tiddlern.tid new file mode 100644 index 000000000..e9ea480b4 --- /dev/null +++ b/editions/de-AT/tiddlers/howto/Importieren von Tiddlern.tid @@ -0,0 +1,6 @@ +created: 20230307080413903 +modified: 20230307080417122 +title: Importieren von Tiddlern +type: text/vnd.tiddlywiki + +https://tiddlywiki.com/#Importing%20Tiddlers \ No newline at end of file diff --git a/editions/de-AT/tiddlers/howto/Liste aller HowTo's.tid b/editions/de-AT/tiddlers/howto/Liste aller HowTo's.tid index 9dcc7e62a..0c88f3e1e 100644 --- a/editions/de-AT/tiddlers/howto/Liste aller HowTo's.tid +++ b/editions/de-AT/tiddlers/howto/Liste aller HowTo's.tid @@ -1,11 +1,11 @@ created: 20140918094051245 creator: pmario -modified: 20140918094948642 +modified: 20230307080301079 modifier: pmario tags: Referenz title: Liste aller HowTo's type: text/vnd.tiddlywiki -Hier finden Sie eine Auflistung aller HowTo's +Hier finden Sie eine Auflistung aller ~HowTo's <> \ No newline at end of file diff --git a/editions/de-AT/tiddlers/konzept/Tagging.tid b/editions/de-AT/tiddlers/konzept/Tagging.tid new file mode 100644 index 000000000..fa28765ba --- /dev/null +++ b/editions/de-AT/tiddlers/konzept/Tagging.tid @@ -0,0 +1,6 @@ +created: 20230307081437974 +modified: 20230307081439303 +title: Tagging +type: text/vnd.tiddlywiki + +https://tiddlywiki.com/#Tagging \ No newline at end of file diff --git a/editions/de-AT/tiddlers/system/$__themes_tiddlywiki_vanilla_options_sidebarlayout.tid b/editions/de-AT/tiddlers/system/$__themes_tiddlywiki_vanilla_options_sidebarlayout.tid new file mode 100644 index 000000000..66a4cbad8 --- /dev/null +++ b/editions/de-AT/tiddlers/system/$__themes_tiddlywiki_vanilla_options_sidebarlayout.tid @@ -0,0 +1,6 @@ +created: 20230307080103029 +modified: 20230307080103029 +title: $:/themes/tiddlywiki/vanilla/options/sidebarlayout +type: text/vnd.tiddlywiki + +fluid-fixed \ No newline at end of file diff --git a/editions/de-AT/tiddlers/widgets/ListWidget.tid b/editions/de-AT/tiddlers/widgets/ListWidget.tid new file mode 100644 index 000000000..44430e62c --- /dev/null +++ b/editions/de-AT/tiddlers/widgets/ListWidget.tid @@ -0,0 +1,7 @@ +created: 20230307081923415 +modified: 20230307081953759 +tags: Widgets +title: ListWidget +type: text/vnd.tiddlywiki + +https://tiddlywiki.com/#ListWidget \ No newline at end of file diff --git a/editions/de-AT/tiddlers/widgets/TranscludeWidget.tid b/editions/de-AT/tiddlers/widgets/TranscludeWidget.tid new file mode 100644 index 000000000..e2e0cbdaf --- /dev/null +++ b/editions/de-AT/tiddlers/widgets/TranscludeWidget.tid @@ -0,0 +1,7 @@ +created: 20230307082002353 +modified: 20230307082023207 +tags: Widgets +title: TranscludeWidget +type: text/vnd.tiddlywiki + +https://tiddlywiki.com/#TranscludeWidget \ No newline at end of file diff --git a/editions/de-AT/tiddlers/wikitext/Bilder in WikiText.tid b/editions/de-AT/tiddlers/wikitext/Bilder in WikiText.tid index 1a2407ad8..53ffd37d1 100644 --- a/editions/de-AT/tiddlers/wikitext/Bilder in WikiText.tid +++ b/editions/de-AT/tiddlers/wikitext/Bilder in WikiText.tid @@ -1,7 +1,7 @@ caption: Bilder created: 20131205160221762 creator: pmario -modified: 20140921170652909 +modified: 20230307081713229 modifier: pmario tags: WikiText title: Bilder in WikiText @@ -25,7 +25,7 @@ oder Wenn die Bildquelle der Titel eines existierenden Tiddlers ist, dann wird dieser direkt angezeigt. Ansonsten wird die Quelle als URL angesehen und ein HTML `` Element wird erzeugt. Das `src` Attribut wird auf die [[URL]] gesetzt. -Ein [[Tooltip]] kann ebenfalls angegeben werden: +Ein Tooltip kann ebenfalls angegeben werden: ``` [img[Ich bin der Tooltip text|Motovun Jack.jpg]] @@ -33,7 +33,7 @@ Ein [[Tooltip]] kann ebenfalls angegeben werden: [img width=100 [Ich bin der Tooltip text|Motovun Jack.jpg]] -Attribute wie zB: CSS Klassen oder die Höhe und Breite können ebenfalls angegeben werden. +Attribute wie z.B: CSS Klassen oder die Höhe und Breite können ebenfalls angegeben werden. ``` [img width=64 [Motovun Jack.jpg]] diff --git a/editions/de-AT/tiddlers/wikitext/Makros in WikiText.tid b/editions/de-AT/tiddlers/wikitext/Makros in WikiText.tid index dd336588e..c2141999a 100644 --- a/editions/de-AT/tiddlers/wikitext/Makros in WikiText.tid +++ b/editions/de-AT/tiddlers/wikitext/Makros in WikiText.tid @@ -1,7 +1,7 @@ caption: Makros created: 20131205160746466 creator: pmario -modified: 20140922124415476 +modified: 20230307080132949 modifier: ChrisK tags: WikiText title: Makros in WikiText @@ -15,7 +15,7 @@ Hallo, Ich bin $name$ und lebe in $adresse$ Hallo, Ich bin $name$ und würde gerne mal wieder nach $adresse$ fahren:) \end -!! Makros Definieren +!! Makros definieren !!! Für die Ungeduldigen @@ -76,7 +76,7 @@ Für einzeilige Makros kann die `\end` Markierung entfallen! * Makros können mit dem ImportVariablesWidget importiert werden. (Für geübte Anwender) -!! Makros Verwenden +!! Makros verwenden ``` <> diff --git a/editions/de-AT/tiddlers/wikitext/Transclusion in WikiText.tid b/editions/de-AT/tiddlers/wikitext/Transclusion in WikiText.tid new file mode 100644 index 000000000..bb8798ebf --- /dev/null +++ b/editions/de-AT/tiddlers/wikitext/Transclusion in WikiText.tid @@ -0,0 +1,7 @@ +created: 20230307081757660 +modified: 20230307081814992 +tags: WikiText +title: Transclusion in WikiText +type: text/vnd.tiddlywiki + +https://tiddlywiki.com/#Transclusion%20in%20WikiText \ No newline at end of file diff --git a/editions/prerelease/tiddlers/$__StoryList.tid b/editions/prerelease/tiddlers/$__StoryList.tid deleted file mode 100644 index d1a1e959f..000000000 --- a/editions/prerelease/tiddlers/$__StoryList.tid +++ /dev/null @@ -1,5 +0,0 @@ -created: 20201222190149806 -list: [[Release 5.1.23]] -modified: 20201222190149806 -title: $:/StoryList -type: text/vnd.tiddlywiki \ No newline at end of file diff --git a/editions/prerelease/tiddlers/Release 5.3.0.tid b/editions/prerelease/tiddlers/Release 5.3.0.tid new file mode 100644 index 000000000..63a57cd4d --- /dev/null +++ b/editions/prerelease/tiddlers/Release 5.3.0.tid @@ -0,0 +1,83 @@ +caption: 5.3.0 +created: 20230419103154368 +modified: 20230419103154368 +tags: ReleaseNotes +title: Release 5.3.0 +type: text/vnd.tiddlywiki + +//[[See GitHub for detailed change history of this release|https://github.com/Jermolene/TiddlyWiki5/compare/master...parameterised-transclusions]]// + +! About v5.3.0 + +This pre-release introduces a number of significant improvements and new features related to some of TiddlyWiki's most fundamental components: macros, widgets, operators and transclusion. + +! Introduction to v5.3.0 + +The motivation of these changes is to fix one of ~TiddlyWiki 5's early design flaws: the reliance on macros using textual substitution as the primary way to modularise and reuse wikitext and filters. + +Experience has shown that while macros are a good match for a small number of tasks, they are brittle and error prone for many common operations. See [[Macro Pitfalls]] for a discussion of the problems that accompany this approach. Over the years we have introduced mitigations for the worst problems but these have come at a cost of increased complexity. + +The changes in this release provide powerful new ways to achieve common tasks, and unlock completely new capabilities that were previously impossible in wikitext. + +* [[Procedures]], which are essentially what macros should have been; they work in exactly the same way except that parameters are exposed as simple variables (without the double underscores) and no textual substitution takes place +* [[Custom Widgets]], allowing the creation of widgets in wikitext, and the redefinition of built-in widgets +* [[Functions]], a new way to encapsulate filter expressions with named parameters, including the ability to make custom filter operators +* Parameterised [[Transclusions|Transclusion]], allowing strings and wikitext trees to be passed to transclusions + +The approach taken by this release is to add new functionality by extending and augmenting the system without disturbing existing functionality. All of these changes are thus intended to be backwards compatible. While they represent a new field of opportunities for wikitext authors, it is possible for authors to ignore all these new features and continue to use ~TiddlyWiki 5 in the way that they have always done. + +These changes lay the groundwork for macros and related features to be deprecated (which is the point at which users are advised not to use old features, and instead given clear pointers to the equivalent modern functionality). + +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. + +! Plugin Improvements + +* + +! Translation improvement + +Improvements to the following translations: + +* + +! Accessibility Improvements + +* + +! Usability Improvements + +* + +! Widget Improvements + +* + +! Filter improvements + +* + +! Hackability Improvements + +* + +! Bug Fixes + +* + +! Developer Improvements + +* + +! Node.js Improvements + +* + +! Performance Improvements + +* +! Acknowledgements + +[[@Jermolene|https://github.com/Jermolene]] would like to thank the contributors to this release who have generously given their time to help improve TiddlyWiki: + +<<.contributors """ +""">> diff --git a/editions/prerelease/tiddlers/system/PrereleaseOfficialPluginLibrary.tid b/editions/prerelease/tiddlers/system/PrereleaseOfficialPluginLibrary.tid index b9ffb0fce..510d876d0 100644 --- a/editions/prerelease/tiddlers/system/PrereleaseOfficialPluginLibrary.tid +++ b/editions/prerelease/tiddlers/system/PrereleaseOfficialPluginLibrary.tid @@ -1,6 +1,6 @@ title: $:/config/OfficialPluginLibrary tags: $:/tags/PluginLibrary -url: https://tiddlywiki.com/prerelease/library/v5.2.6/index.html +url: https://tiddlywiki.com/prerelease/library/v5.2.8/index.html caption: {{$:/language/OfficialPluginLibrary}} (Prerelease) The prerelease version of the official ~TiddlyWiki plugin library at tiddlywiki.com. Plugins, themes and language packs are maintained by the core team. diff --git a/editions/server-external-js/tiddlers/config/$__DefaultTiddlers.tid b/editions/server-external-js/tiddlers/config/$__DefaultTiddlers.tid new file mode 100644 index 000000000..a1f1a0a27 --- /dev/null +++ b/editions/server-external-js/tiddlers/config/$__DefaultTiddlers.tid @@ -0,0 +1,7 @@ +created: 20230314153132081 +modified: 20230314153243008 +title: $:/DefaultTiddlers +type: text/vnd.tiddlywiki + +GettingStarted +[[Using the external JavaScript template]] diff --git a/editions/server-external-js/tiddlers/config/$__config_SaveWikiButton_Filename.tid b/editions/server-external-js/tiddlers/config/$__config_SaveWikiButton_Filename.tid new file mode 100644 index 000000000..071c85fe9 --- /dev/null +++ b/editions/server-external-js/tiddlers/config/$__config_SaveWikiButton_Filename.tid @@ -0,0 +1,4 @@ +title: $:/config/SaveWikiButton/Filename +type: text/vnd.tiddlywiki + +external-<>.html \ No newline at end of file diff --git a/editions/server-external-js/tiddlers/external/tiddlywiki.files b/editions/server-external-js/tiddlers/external/tiddlywiki.files new file mode 100644 index 000000000..73474d2ce --- /dev/null +++ b/editions/server-external-js/tiddlers/external/tiddlywiki.files @@ -0,0 +1,8 @@ +{ + "tiddlers": [ + { + "file": "../../../tw5.com/tiddlers/webserver/Using the external JavaScript template.tid", + "isTiddlerFile": true + } + ] +} \ No newline at end of file diff --git a/editions/server-external-js/tiddlywiki.info b/editions/server-external-js/tiddlywiki.info index b8d4c37ee..cb02accd5 100644 --- a/editions/server-external-js/tiddlywiki.info +++ b/editions/server-external-js/tiddlywiki.info @@ -2,8 +2,7 @@ "description": "Client-server edition with external tiddlywiki.js", "plugins": [ "tiddlywiki/tiddlyweb", - "tiddlywiki/filesystem", - "tiddlywiki/highlight" + "tiddlywiki/filesystem" ], "themes": [ "tiddlywiki/vanilla", @@ -13,7 +12,7 @@ "listen": [ "--listen","root-tiddler=$:/core/save/all-external-js","use-browser-cache=yes"], "index": [ - "--render","$:/core/save/offline-external-js","index.html","text/plain", + "--render","$:/core/save/offline-external-js","[[external-]addsuffixaddsuffix[.html]]","text/plain", "--render","$:/core/templates/tiddlywiki5.js","[[tiddlywikicore-]addsuffixaddsuffix[.js]]","text/plain"], "static": [ "--render","$:/core/templates/static.template.html","static.html","text/plain", diff --git a/editions/test/tiddlers/tests/data/custom-operators/NestedParameterised.tid b/editions/test/tiddlers/tests/data/custom-operators/NestedParameterised.tid new file mode 100644 index 000000000..3e4d610d0 --- /dev/null +++ b/editions/test/tiddlers/tests/data/custom-operators/NestedParameterised.tid @@ -0,0 +1,24 @@ +title: CustomOperators/NestedParameterised +description: Nested parameterised custom operator usage +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +\function .dividebysomething(first:ignored,factor:0.5) +[divide[2]multiply] +\end + +\function .multiplebysomething(first:ignored,factor:2) +[multiply[2].dividebysomething[],] +\end + +<$text text={{{ [[123].multiplebysomething[]] }}}/> +- +<$text text={{{ [[123].multiplebysomething[x],[4]] }}}/> + ++ +title: ExpectedResult + +

246-492

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/custom-operators/Parameterised.tid b/editions/test/tiddlers/tests/data/custom-operators/Parameterised.tid new file mode 100644 index 000000000..2f8337b0f --- /dev/null +++ b/editions/test/tiddlers/tests/data/custom-operators/Parameterised.tid @@ -0,0 +1,24 @@ +title: CustomOperators/Parameterised +description: Parameterised custom operator usage +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +\function .multiplybysomething(first:ignored,factor:2) +[multiply[2]multiply] +\end + +<$text text={{{ [[123].multiplybysomething[]] }}}/> +- +<$text text={{{ [[123].multiplybysomething[x],[4]] }}}/> +| +<$text text={{{ [[123]function[.multiplybysomething]] }}}/> +- +<$text text={{{ [[123]function[.multiplybysomething],[x],[4]] }}}/> + ++ +title: ExpectedResult + +

492-984|492-984

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/custom-operators/Simple.tid b/editions/test/tiddlers/tests/data/custom-operators/Simple.tid new file mode 100644 index 000000000..089701295 --- /dev/null +++ b/editions/test/tiddlers/tests/data/custom-operators/Simple.tid @@ -0,0 +1,21 @@ +title: CustomOperators/Simple +description: Simple custom operator usage +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim + +\function .multiplybytwo() +[multiply[2]] +\end + +<$text text={{{ [[123].multiplybytwo[]] }}}/> +| +<$text text={{{ [[123]function[.multiplybytwo]] }}}/> + ++ +title: ExpectedResult + +

246|246

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/filters/DiffMergePatch1.tid b/editions/test/tiddlers/tests/data/filters/DiffMergePatch1.tid new file mode 100644 index 000000000..e6e519df5 --- /dev/null +++ b/editions/test/tiddlers/tests/data/filters/DiffMergePatch1.tid @@ -0,0 +1,28 @@ +title: Filters/DiffMergePatch1 +description: Tests for diff-merge-patch derived operators +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +\define text1() +the cat sat on the mat +\end + +\define text2() +the hat saw in every category +\end + +<$text text={{{ [makepatches] }}}/> ++ +title: ExpectedResult + +

@@ -1,22 +1,29 @@ + the +-c ++h + at sa +-t on the mat ++w in every category +

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/filters/DiffMergePatch2.tid b/editions/test/tiddlers/tests/data/filters/DiffMergePatch2.tid new file mode 100644 index 000000000..1fa355573 --- /dev/null +++ b/editions/test/tiddlers/tests/data/filters/DiffMergePatch2.tid @@ -0,0 +1,25 @@ +title: Filters/DiffMergePatch2 +description: Tests for diff-merge-patch derived operators +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +\define text1() +the cat sat on the mat +\end + +\define text2() +the hat saw in every category +\end + +<$let patches={{{ [makepatches] }}}> + +<$text text={{{ [applypatches] }}}/> + + ++ +title: ExpectedResult + +the hat saw in every category \ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/filters/DiffMergePatch3.tid b/editions/test/tiddlers/tests/data/filters/DiffMergePatch3.tid new file mode 100644 index 000000000..87d98e890 --- /dev/null +++ b/editions/test/tiddlers/tests/data/filters/DiffMergePatch3.tid @@ -0,0 +1,22 @@ +title: Filters/DiffMergePatch3 +description: Tests for diff-merge-patch derived operators +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +\define text1() +the cat sat on the mat +\end + +\define patches() +**NOT A VALID PATCH** +\end + +<$text text={{{ [applypatches] }}}/> + ++ +title: ExpectedResult + +the cat sat on the mat \ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/functions/FunctionAttributes.tid b/editions/test/tiddlers/tests/data/functions/FunctionAttributes.tid new file mode 100644 index 000000000..2deb49bdc --- /dev/null +++ b/editions/test/tiddlers/tests/data/functions/FunctionAttributes.tid @@ -0,0 +1,24 @@ +title: Functions/FunctionAttributes +description: Attributes specified as function invocations +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +\function .dividebysomething(factor:0.5) +[divide] +\end + +\function multiplebysomething(first:ignored,factor:2) +[multiply[2].dividebysomething[0.25]] +\end + +<$text text=<>/> +| +<$text text=<>/> + ++ +title: ExpectedResult + +

16|32

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/functions/FunctionOperator.tid b/editions/test/tiddlers/tests/data/functions/FunctionOperator.tid new file mode 100644 index 000000000..e2a0038dc --- /dev/null +++ b/editions/test/tiddlers/tests/data/functions/FunctionOperator.tid @@ -0,0 +1,24 @@ +title: Functions/FunctionOperator +description: Calling a function via the function operator +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +\function .dividebysomething(factor:0.5) +[divide] +\end + +\function multiplebysomething(first:ignored,factor:2) +[multiplymultiply[2].dividebysomething[0.25]] +\end + +<$text text={{{ [[4]function[multiplebysomething]] }}}/> +| +<$text text={{{ [[6]function[multiplebysomething],[ignored],[4]] }}}/> + ++ +title: ExpectedResult + +

64|192

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/functions/MissingFunction.tid b/editions/test/tiddlers/tests/data/functions/MissingFunction.tid new file mode 100644 index 000000000..25498e452 --- /dev/null +++ b/editions/test/tiddlers/tests/data/functions/MissingFunction.tid @@ -0,0 +1,15 @@ +title: Functions/MissingFunction +description: Calling a missing function via the function operator +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim + +<$text text={{{ [[23]function[missing]] }}}/> + ++ +title: ExpectedResult + +23 \ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/functions/RunawayRecursiveFunctions.tid b/editions/test/tiddlers/tests/data/functions/RunawayRecursiveFunctions.tid new file mode 100644 index 000000000..81be22f16 --- /dev/null +++ b/editions/test/tiddlers/tests/data/functions/RunawayRecursiveFunctions.tid @@ -0,0 +1,18 @@ +title: Functions/RunawayRecursiveFunctions +description: Runaway recursive functions +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +\function .buffalo(p) +[.buffalo

] +\end + +<$text text=<<.buffalo 8>>/> + ++ +title: ExpectedResult + +/**-- Excessive filter recursion --**/ \ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/functions/UndefinedParameters.tid b/editions/test/tiddlers/tests/data/functions/UndefinedParameters.tid new file mode 100644 index 000000000..8a2b0a91a --- /dev/null +++ b/editions/test/tiddlers/tests/data/functions/UndefinedParameters.tid @@ -0,0 +1,22 @@ +title: Functions/UndefinedParameters +description: Undefined function parameters +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\function greet(who) +[[hello ]addsuffix] +\end + +<$text text={{{[function[greet],[world]]}}}/> + +<> + +<$text text={{{[function[greet]]}}}/> + +<> ++ +title: ExpectedResult + +hello world

hello world

hello

hello

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/functions/WikifiedFunctions.tid b/editions/test/tiddlers/tests/data/functions/WikifiedFunctions.tid new file mode 100644 index 000000000..733fbdaef --- /dev/null +++ b/editions/test/tiddlers/tests/data/functions/WikifiedFunctions.tid @@ -0,0 +1,36 @@ +title: Functions/WikifiedFunctions +description: Wikified functions +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +\function fn-buffalo(param) +[addsuffix[ with a ''buffalo'']] +\end + +\procedure proc-buffalo(param) +<> with a ''buffalo'' +\end + +\define macro-buffalo(param) +$param$ with a ''buffalo'' +\end + +<> + +<> + +<> + +<$transclude $variable="fn-buffalo" param="Going to lunch" $output="text/plain"/> + +<$transclude $variable="proc-buffalo" param="Going to breakfast" $output="text/plain"/> + +<$transclude $variable="macro-buffalo" param="Going to dinner" $output="text/plain"/> + ++ +title: ExpectedResult + +

Going to lunch with a ''buffalo''

Going to breakfastwith abuffalo

Going to dinner with a buffalo

Going to lunch with a buffalo with a buffaloGoing to dinner with a buffalo \ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/genesis-widget/RedefineLet.tid b/editions/test/tiddlers/tests/data/genesis-widget/RedefineLet.tid new file mode 100644 index 000000000..f6834998d --- /dev/null +++ b/editions/test/tiddlers/tests/data/genesis-widget/RedefineLet.tid @@ -0,0 +1,31 @@ +title: Genesis/RedefineLet +description: Using the genesis widget to override the let widget +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +\widget $let() +\whitespace trim +<$parameters $params="@params"> +<$setmultiplevariables $names="[<@params>jsonindexes[]]" $values="[<@params>jsonindexes[]] :map[<@params>jsongetaddprefix[--]addsuffix[--]]"> +<$slot $name="ts-raw"/> + + +\end +<$let + one="Elephant" + $two="Kangaroo" + $$three="Giraffe" +> +(<$text text=<>/>) +(<$text text=<<$two>>/>) +(<$text text=<<$$three>>/>) + ++ +title: ExpectedResult + +

(--Elephant--) +(--Kangaroo--) +(--Giraffe--)

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/macros/TrailingNewlines.tid b/editions/test/tiddlers/tests/data/macros/TrailingNewlines.tid new file mode 100644 index 000000000..18037fac2 --- /dev/null +++ b/editions/test/tiddlers/tests/data/macros/TrailingNewlines.tid @@ -0,0 +1,22 @@ +title: Macros/TrailingNewlines +description: Trailing newlines in macros must not be dropped +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\define inner() +Paragraph 1 + +Paragraph 2 +\end +\define outer() +<$macrocall $name=inner /> + +\end +<> + ++ +title: ExpectedResult + +

Paragraph 1

Paragraph 2

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/procedures/Nested.tid b/editions/test/tiddlers/tests/data/procedures/Nested.tid new file mode 100644 index 000000000..f63c634af --- /dev/null +++ b/editions/test/tiddlers/tests/data/procedures/Nested.tid @@ -0,0 +1,20 @@ +title: Procedures/Nested +description: Nested Procedures +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +\procedure alpha(x) +\procedure beta(y) +<$text text=<>/> +\end beta +<$transclude $variable="beta" y={{{ [addprefix] }}}/> +\end alpha + +<> ++ +title: ExpectedResult + +

ElephantElephant

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/transclude/CustomWidget-ActionWidget.tid b/editions/test/tiddlers/tests/data/transclude/CustomWidget-ActionWidget.tid new file mode 100644 index 000000000..0be77a9a3 --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/CustomWidget-ActionWidget.tid @@ -0,0 +1,27 @@ +title: Transclude/CustomWidget/ActionWidget +description: Custom widget definition +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +<$transclude $tiddler='Result'> + ++ +title: Actions + +\whitespace trim + +\widget $$action-mywidget(one:'Jaguar') +\whitespace trim +<$action-setfield $tiddler="Result" $field="text" $value=<>/> +\end + +<$$action-mywidget one="Dingo"> + Crocodile + ++ +title: ExpectedResult + +

Dingo

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/transclude/CustomWidget-Fail.tid b/editions/test/tiddlers/tests/data/transclude/CustomWidget-Fail.tid new file mode 100644 index 000000000..3d0759013 --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/CustomWidget-Fail.tid @@ -0,0 +1,26 @@ +title: Transclude/CustomWidget/Fail +description: Custom widget failed definition +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim + +\widget $non-existent-widget(one:'Jaguar') +\whitespace trim +<$text text=<>/> +<$slot $name="ts-raw"> + Whale + +\end +<$non-existent-widget one="Dingo"> + Crocodile + +<$non-existent-widget one="BumbleBee"> + Squirrel + ++ +title: ExpectedResult + +

Undefined widget 'non-existent-widget'Undefined widget 'non-existent-widget'

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/transclude/CustomWidget-Override-Codeblock.tid b/editions/test/tiddlers/tests/data/transclude/CustomWidget-Override-Codeblock.tid new file mode 100644 index 000000000..c4730622b --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/CustomWidget-Override-Codeblock.tid @@ -0,0 +1,29 @@ +title: CustomWidget-Override-Codeblock +description: Usage of genesis widget with attributes starting with dollar signs +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +\import Definition +<$codeblock code="Kangaroo"/> +<$codeblock code={{Subject}}/> +<$let test="Tiger"> +<$codeblock code=<>/> + ++ +title: Definition + +\whitespace trim +\widget $codeblock(code) +<$genesis $type="$codeblock" $remappable="no" code={{{ [addprefix[£]addsuffix[@]] }}}/> +\end ++ +title: Subject + +Python ++ +title: ExpectedResult + +

£Kangaroo@
£Python@
£Tiger@

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/transclude/CustomWidget-OverrideTransclude.tid b/editions/test/tiddlers/tests/data/transclude/CustomWidget-OverrideTransclude.tid new file mode 100644 index 000000000..c57e4a9a1 --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/CustomWidget-OverrideTransclude.tid @@ -0,0 +1,33 @@ +title: Transclude/CustomWidget/OverrideTransclude +description: Custom widget definition attempting to override transclude +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +<$transclude $tiddler='TiddlerOne' one='Ferret'> + ++ +title: TiddlerZero + +Antelope ++ +title: TiddlerOne + +\whitespace trim + +\widget $transclude(one:'Jaguar') +\whitespace trim + <$text text=<>/> + <$slot $name="body"> + Whale + +\end +<$genesis $type="$transclude" $remappable="no" $$tiddler="TiddlerZero"> + Crocodile + ++ +title: ExpectedResult + +

Antelope

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/transclude/CustomWidget-Simple.tid b/editions/test/tiddlers/tests/data/transclude/CustomWidget-Simple.tid new file mode 100644 index 000000000..15d0c8d9e --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/CustomWidget-Simple.tid @@ -0,0 +1,33 @@ +title: Transclude/CustomWidget/Simple +description: Custom widget definition +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +<$transclude $tiddler='TiddlerOne' one='Ferret'> + ++ +title: TiddlerOne + +\whitespace trim + +\widget $$mywidget(one:'Jaguar') +\whitespace trim +<$text text=<>/> +<$slot $name="ts-raw"> + Whale + +\end +<$$mywidget one="Dingo"> + Crocodile + +<$$mywidget one="BumbleBee"> + Squirrel + +<$$mywidget/> ++ +title: ExpectedResult + +

DingoCrocodileBumbleBeeSquirrelJaguarWhale

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/transclude/CustomWidget-Slotted-Empty.tid b/editions/test/tiddlers/tests/data/transclude/CustomWidget-Slotted-Empty.tid new file mode 100644 index 000000000..efd1e7041 --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/CustomWidget-Slotted-Empty.tid @@ -0,0 +1,20 @@ +title: CustomWidget/Slotted/Empty +description: Custom widget with empty slotted values +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +\widget $$mywidget() +<$slot $name=ts-raw>the body is empty +\end + +#<$$mywidget/> +#<$$mywidget> +#<$$mywidget>the body is not empty + ++ +title: ExpectedResult + +
  1. the body is empty
  2. the body is empty
  3. the body is not empty
\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/transclude/CustomWidget-Slotted.tid b/editions/test/tiddlers/tests/data/transclude/CustomWidget-Slotted.tid new file mode 100644 index 000000000..c10e84127 --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/CustomWidget-Slotted.tid @@ -0,0 +1,27 @@ +title: Transclude/CustomWidget/Slotted +description: Custom widget definition +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +\widget $$mywidget(one:'Jaguar') +\whitespace trim +<$text text=<>/> +<$slot $name="ts-stuff"> + Whale + +\end +<$$mywidget one="Dingo"> + <$fill $name="ts-stuff"> + Crocodile + + +<$$mywidget one="BumbleBee"> + Squirrel + ++ +title: ExpectedResult + +

DingoCrocodileBumbleBeeWhale

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/transclude/CustomWidget-TextWidgetOverride.tid b/editions/test/tiddlers/tests/data/transclude/CustomWidget-TextWidgetOverride.tid new file mode 100644 index 000000000..d0a3cc82c --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/CustomWidget-TextWidgetOverride.tid @@ -0,0 +1,27 @@ +title: Transclude/CustomWidget/TextWidgetOverride +description: Custom widget definition redefining the text widget +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +<$transclude $tiddler='TiddlerOne'> + ++ +title: TiddlerOne + +\whitespace trim + +\widget $text(text:'Jaguar') +\whitespace trim +<$genesis $type="$text" $remappable="no" text={{{ [addprefix[≤]addsuffix[≥]] }}}/> +\end + +<$text text="Dingo"/> + +Crocodile ++ +title: ExpectedResult + +

≤Dingo≥≤Jaguar≥

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/transclude/CustomWidget-TextWidgetOverrideWithSlot.tid b/editions/test/tiddlers/tests/data/transclude/CustomWidget-TextWidgetOverrideWithSlot.tid new file mode 100644 index 000000000..c84c5ae9a --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/CustomWidget-TextWidgetOverrideWithSlot.tid @@ -0,0 +1,31 @@ +title: Transclude/CustomWidget/TextWidgetOverrideWithSlot +description: Custom widget definition redefining the text widget +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +<$transclude $tiddler='TiddlerOne'> + ++ +title: TiddlerOne + +\whitespace trim + +\widget $text(text:'Jaguar') +\whitespace trim +<$genesis $type="$text" $remappable="no" text=<>/> +<$set name="$text" value=""> + <$slot $name="ts-raw"> + Whale + + +\end +<$text text="Dingo"> + Crocodile + ++ +title: ExpectedResult + +

DingoCrocodile

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/transclude/CustomWidget-Unoverride-Codeblock.tid b/editions/test/tiddlers/tests/data/transclude/CustomWidget-Unoverride-Codeblock.tid new file mode 100644 index 000000000..c6a834205 --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/CustomWidget-Unoverride-Codeblock.tid @@ -0,0 +1,31 @@ +title: CustomWidget-Unoverride-Codeblock +description: Usage of genesis widget with attributes starting with dollar signs, and unoverriding a core widget +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +\import Definition +<$let $codeblock=""> +<$codeblock code="Kangaroo"/> +<$codeblock code={{Subject}}/> +<$let test="Tiger"> +<$codeblock code=<>/> + + ++ +title: Definition + +\whitespace trim +\widget $codeblock(code) +<$genesis $type="codeblock" $remappable="no" code={{{ [addprefix[£]addsuffix[@]] }}}/> +\end ++ +title: Subject + +Python ++ +title: ExpectedResult + +

Kangaroo
Python
Tiger

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/transclude/CustomWidget-VariableAttribute.tid b/editions/test/tiddlers/tests/data/transclude/CustomWidget-VariableAttribute.tid new file mode 100644 index 000000000..8ef700b41 --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/CustomWidget-VariableAttribute.tid @@ -0,0 +1,29 @@ +title: Transclude/CustomWidget/VariableAttribute +description: Custom widget definition using an attribute called $variable +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +<$transclude $tiddler='TiddlerOne' one='Ferret'> + ++ +title: TiddlerOne + +\whitespace trim + +\widget $$mywidget($variable:'Jaguar') +\whitespace trim +<$text text=<<$variable>>/> +<$slot $name="ts-raw"> + Whale + +\end +<$$mywidget $variable="Dingo"> + Crocodile + ++ +title: ExpectedResult + +

DingoCrocodile

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/transclude/JavaScript-Macro.tid b/editions/test/tiddlers/tests/data/transclude/JavaScript-Macro.tid new file mode 100644 index 000000000..216a89dc8 --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/JavaScript-Macro.tid @@ -0,0 +1,17 @@ +title: Transclude/Macro/JavaScript +description: Transcluding a javascript macro +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim + +<> + +<$macrocall $name="makedatauri" text="Wildebeest" type="text/plain"/> + ++ +title: ExpectedResult + +

data:text/plain,Wildebeest

data:text/plain,Wildebeest

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/transclude/Macro-Plain.tid b/editions/test/tiddlers/tests/data/transclude/Macro-Plain.tid new file mode 100644 index 000000000..410144153 --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/Macro-Plain.tid @@ -0,0 +1,17 @@ +title: Transclude/Macro/Plain +description: Transcluding a macro as plain text +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +<$let currentTab="Jeremy"> +<$macrocall $name="currentTab" $type="text/plain" $output="text/plain"/> +| +<$transclude $variable="currentTab" $type="text/plain" $output="text/plain"/> + ++ +title: ExpectedResult + +

Jeremy|Jeremy

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/transclude/Macro-Simple.tid b/editions/test/tiddlers/tests/data/transclude/Macro-Simple.tid new file mode 100644 index 000000000..71db5efe4 --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/Macro-Simple.tid @@ -0,0 +1,26 @@ +title: Transclude/Macro/Simple +description: Transcluding a macro +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +\define mamacro(one:"red",two:"green") +It is $one$ and $two$ or <<__one__>> and <<__two__>>. +\end + +<$macrocall $name="mamacro"/> + +<$transclude $variable="mamacro"/> + +<$transclude $variable="mamacro" one="orange"/> + +<$transclude $variable="mamacro" 0="pink"/> + +<$transclude $variable="mamacro" one="purple" 1="pink"/> + ++ +title: ExpectedResult + +

It is red and green or red and green.

It is red and green or red and green.

It is orange and green or orange and green.

It is pink and green or pink and green.

It is purple and pink or purple and pink.

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/transclude/MissingTarget.tid b/editions/test/tiddlers/tests/data/transclude/MissingTarget.tid new file mode 100644 index 000000000..8bdc86eaa --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/MissingTarget.tid @@ -0,0 +1,48 @@ +title: Transclude/MissingTarget +description: Transcluding a missing target +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +<$transclude $tiddler='TiddlerOne' one='Ferret'> + <$parameters one='Ferret'> + Badger + <$text text=<>/> + + +<$transclude $tiddler='TiddlerOne' one='Ferret'> + <$fill $name="ts-missing"> + <$parameters one='Ferret'> + Badger + <$text text=<>/> + + + +<$transclude $tiddler='MissingTiddler' one='Ferret'> + <$parameters one='Ferret'> + Badger + <$text text=<>/> + + +<$transclude $tiddler='MissingTiddler' one='Ferret'> + <$fill $name="ts-missing"> + <$parameters one='Ferret'> + Badger + <$text text=<>/> + + + ++ +title: TiddlerOne + +\whitespace trim +<$parameters one='Kangaroo'> + Piranha + <$text text=<>/> + ++ +title: ExpectedResult + +

PiranhaFerretPiranhaFerretBadgerFerretBadgerFerret

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/transclude/Parameterised-Depth.tid b/editions/test/tiddlers/tests/data/transclude/Parameterised-Depth.tid new file mode 100644 index 000000000..064e225c8 --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/Parameterised-Depth.tid @@ -0,0 +1,34 @@ +title: Transclude/Parameterised/Depth +description: Parameterised transclusion using the $depth attribute +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +<$transclude $tiddler='TiddlerOne' one='Ferret'/> +| +<$transclude $tiddler='TiddlerOne'/> +| +<$transclude $tiddler='TiddlerOne' one='Ferret' $$two="Osprey"/> +| +<$transclude $tiddler='TiddlerOne' $$two="Falcon"/> ++ +title: TiddlerOne + +\whitespace trim +{{TiddlerTwo}} ++ +title: TiddlerTwo + +\whitespace trim +<$parameters one='Jaguar' $$two='Piranha' $depth="2"> + <$text text=<>/>:<$text text=<<$two>>/> + +<$parameters one='Leopard' $$two='Coelacanth'> + (<$text text=<>/>|<$text text=<<$two>>/>) + ++ +title: ExpectedResult + +

Ferret:Piranha(Leopard|Coelacanth)|Jaguar:Piranha(Leopard|Coelacanth)|Ferret:Osprey(Leopard|Coelacanth)|Jaguar:Falcon(Leopard|Coelacanth)

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/transclude/Parameterised-Mode.tid b/editions/test/tiddlers/tests/data/transclude/Parameterised-Mode.tid new file mode 100644 index 000000000..04f5bbb04 --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/Parameterised-Mode.tid @@ -0,0 +1,29 @@ +title: Transclude/Parameterised/Mode +description: Parameterised transclusion using the $parseMode attribute +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim + +<$transclude $tiddler='TiddlerOne' one='Ferret'> + +This is a block + + + +<$transclude $tiddler='TiddlerOne'> +This is inline + ++ +title: TiddlerOne + +\whitespace trim +<$parameters $parseMode="@parseMode"> + <$text text=<<@parseMode>>/> + ++ +title: ExpectedResult + +

block

inline

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/transclude/Parameterised-Name-Values.tid b/editions/test/tiddlers/tests/data/transclude/Parameterised-Name-Values.tid new file mode 100644 index 000000000..9d62a7897 --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/Parameterised-Name-Values.tid @@ -0,0 +1,34 @@ +title: Transclude/Parameterised/Name/Values +description: Parameterised transclusion accessing parameters as name/value pairs +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +<$transclude $tiddler="TiddlerOne" 0="" 1="" 2=""/> + +{{TiddlerOne}} +{{TiddlerOne|Ferret}} +{{TiddlerOne|Butterfly|Moth}} +{{TiddlerOne|Beetle|Scorpion|Snake}} +{{TiddlerOne||TiddlerTwo|Beetle|Scorpion|Snake}} ++ +title: TiddlerOne + +\whitespace trim +<$parameters zero='Jaguar' $$one='Lizard' two='Mole' $params="@params"> +<$list filter="[<@params>jsonindexes[]]"> +{<$text text=<>/>: <$text text={{{ [<@params>jsonget] }}}/>} + + ++ +title: TiddlerTwo + +\whitespace trim +\parameters(zero:'Mouse',$one:'Horse',two:'Owl') +(<$transclude $tiddler=<> zero=<> $$one=<<$one>> two=<>/>) ++ +title: ExpectedResult + +

{0:}{1:}{2:}

{0:Ferret}

{0:Butterfly}{1:Moth}

{0:Beetle}{1:Scorpion}{2:Snake}

({$one:Scorpion}{two:Snake}{zero:Beetle})

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/transclude/Parameterised-ParseTreeNodes.tid b/editions/test/tiddlers/tests/data/transclude/Parameterised-ParseTreeNodes.tid new file mode 100644 index 000000000..916e2abfb --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/Parameterised-ParseTreeNodes.tid @@ -0,0 +1,29 @@ +title: Transclude/Parameterised/ParseTreeNodes +description: Parameterised transclusion using the $parseTreeNodes attribute +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim + +<$transclude $tiddler='TiddlerOne' one='Ferret'> + +This is a block + + + +<$transclude $tiddler='TiddlerOne'> +This is inline + ++ +title: TiddlerOne + +\whitespace trim +<$parameters $parseTreeNodes="@parseTreeNodes"> + <$text text=<<@parseTreeNodes>>/> + ++ +title: ExpectedResult + +

[{"type":"element","tag":"p","children":[{"type":"text","text":"This is a block","start":68,"end":83}],"start":68,"end":83}]

[{"type":"text","text":"This is inline","start":136,"end":152}]

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/transclude/Parameterised-Positional-Shortcut-Parameters.tid b/editions/test/tiddlers/tests/data/transclude/Parameterised-Positional-Shortcut-Parameters.tid new file mode 100644 index 000000000..abf444adb --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/Parameterised-Positional-Shortcut-Parameters.tid @@ -0,0 +1,29 @@ +title: Transclude/Parameterised/Positional/Shortcut/Parameters +description: Positional parameterised transclusion using shortcut syntax and parameters pragma +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +{{TiddlerOne}} +{{TiddlerOne|Ferret}} +{{TiddlerOne|Butterfly|Moth}} +{{TiddlerOne|Beetle|Scorpion|Snake}} +{{TiddlerOne||TiddlerTwo|Beetle|Scorpion|Snake}} ++ +title: TiddlerOne + +\whitespace trim +\parameters(zero:Jaguar,one:'Lizard',two:'Mole') +[{<$text text=<>/>}{<$text text=<>/>}{<$text text=<>/>}] ++ +title: TiddlerTwo + +\whitespace trim +\parameters(zero:'Mouse',one:Horse,two:'Owl') +(<$transclude $tiddler=<> zero=<> one=<> two=<>/>) ++ +title: ExpectedResult + +

[{Jaguar}{Lizard}{Mole}]

[{Ferret}{Lizard}{Mole}]

[{Butterfly}{Moth}{Mole}]

[{Beetle}{Scorpion}{Snake}]

([{Beetle}{Scorpion}{Snake}])

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/transclude/Parameterised-Positional-Shortcut.tid b/editions/test/tiddlers/tests/data/transclude/Parameterised-Positional-Shortcut.tid new file mode 100644 index 000000000..7792e6c66 --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/Parameterised-Positional-Shortcut.tid @@ -0,0 +1,29 @@ +title: Transclude/Parameterised/Positional/Shortcut +description: Positional parameterised transclusion using shortcut syntax +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +{{TiddlerOne}} +{{TiddlerOne|Ferret}} +{{TiddlerOne|Butterfly|Moth}} +{{TiddlerOne|Beetle|Scorpion|Snake}} +{{TiddlerOne||TiddlerTwo|Beetle|Scorpion|Snake}} ++ +title: TiddlerOne + +\whitespace trim +<$parameters zero='Jaguar' one='Lizard' two='Mole'>[{<$text text=<>/>}{<$text text=<>/>}{<$text text=<>/>}] ++ +title: TiddlerTwo + +\whitespace trim +<$parameters zero='Mouse' one='Horse' two='Owl'> +(<$transclude $tiddler=<> zero=<> one=<> two=<>/>) + ++ +title: ExpectedResult + +

[{Jaguar}{Lizard}{Mole}]

[{Ferret}{Lizard}{Mole}]

[{Butterfly}{Moth}{Mole}]

[{Beetle}{Scorpion}{Snake}]

([{Beetle}{Scorpion}{Snake}])

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/transclude/Parameterised-Positional-Variables.tid b/editions/test/tiddlers/tests/data/transclude/Parameterised-Positional-Variables.tid new file mode 100644 index 000000000..ad2b7be52 --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/Parameterised-Positional-Variables.tid @@ -0,0 +1,30 @@ +title: Transclude/Parameterised/Positional/Variables +description: Positional parameterised transclusion of variables +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +\function myfunction(alpha:"apple",beta:"banana",gamma:"grenadine") [] +\define mymacro(alpha:"apple",beta:"banana",gamma:"grenadine") $beta$ +\function f(a) [] + +(Functions: +<$text text={{{ [] }}}/> +, +<$text text=<>/> +, +<> +)(Macros: +<$text text={{{ [] }}}/> +, +<$text text=<>/> +, +<> +) + ++ +title: ExpectedResult + +

(Functions:f1,f1,f1)(Macros:banana,banana,banana)

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/transclude/Parameterised-Positional.tid b/editions/test/tiddlers/tests/data/transclude/Parameterised-Positional.tid new file mode 100644 index 000000000..d7eb9090e --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/Parameterised-Positional.tid @@ -0,0 +1,26 @@ +title: Transclude/Parameterised/Positional +description: Positional parameterised transclusion +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +<$transclude $tiddler='TiddlerOne' zero='Ferret'/> +<$transclude zero='Ferret' $tiddler='TiddlerOne'/> +<$transclude $tiddler='TiddlerOne' 0='Pigeon'/> +<$transclude 0='Pigeon' $tiddler='TiddlerOne'/> +<$transclude $tiddler='TiddlerOne' zero='Ferret' 0='Pigeon'/> +<$transclude zero='Ferret' 0='Pigeon' $tiddler='TiddlerOne'/> +<$transclude $tiddler='TiddlerOne'/> ++ +title: TiddlerOne + +\whitespace trim +<$parameters zero='Jaguar'> + <$text text=<>/> + ++ +title: ExpectedResult + +

FerretFerretPigeonPigeonFerretFerretJaguar

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/transclude/Parameterised-Shortcut-Parameters.tid b/editions/test/tiddlers/tests/data/transclude/Parameterised-Shortcut-Parameters.tid new file mode 100644 index 000000000..375964199 --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/Parameterised-Shortcut-Parameters.tid @@ -0,0 +1,20 @@ +title: Transclude/Parameterised/Shortcut/Parameters +description: Simple parameterised transclusion using the parameters pragma +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +<$transclude $tiddler='TiddlerOne' one='Ferret'/> +<$transclude $tiddler='TiddlerOne'/> ++ +title: TiddlerOne + +\whitespace trim +\parameters(one:'Jaguar') +<$text text=<>/> ++ +title: ExpectedResult + +

FerretJaguar

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/transclude/Parameterised-Shortcut.tid b/editions/test/tiddlers/tests/data/transclude/Parameterised-Shortcut.tid new file mode 100644 index 000000000..0499cf2d6 --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/Parameterised-Shortcut.tid @@ -0,0 +1,21 @@ +title: Transclude/Parameterised/Shortcut +description: Simple parameterised transclusion +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +\procedure test(one:'Jaguar') +{<$text text=<>/>} +\end + +<$transclude $variable='test' one='Ferret'/> +<$transclude $variable='test'/> +<> +<> + ++ +title: ExpectedResult + +

{Ferret}{Jaguar}{Rat}{Mouse}

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/transclude/Parameterised-Simple.tid b/editions/test/tiddlers/tests/data/transclude/Parameterised-Simple.tid new file mode 100644 index 000000000..0268f9e59 --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/Parameterised-Simple.tid @@ -0,0 +1,26 @@ +title: Transclude/Parameterised/Simple +description: Simple parameterised transclusion +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +<$transclude $tiddler='TiddlerOne' one='Ferret'/> +| +<$transclude $tiddler='TiddlerOne'/> +| +<$transclude $tiddler='TiddlerOne' one='Ferret' $$two="Osprey"/> +| +<$transclude $tiddler='TiddlerOne' $$two="Falcon"/> ++ +title: TiddlerOne + +\whitespace trim +<$parameters one='Jaguar' $$two='Piranha'> + <$text text=<>/>:<$text text=<<$two>>/> + ++ +title: ExpectedResult + +

Ferret:Piranha|Jaguar:Piranha|Ferret:Osprey|Jaguar:Falcon

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/transclude/Parameterised-SlotFillParseTreeNodes.tid b/editions/test/tiddlers/tests/data/transclude/Parameterised-SlotFillParseTreeNodes.tid new file mode 100644 index 000000000..679748375 --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/Parameterised-SlotFillParseTreeNodes.tid @@ -0,0 +1,29 @@ +title: Transclude/Parameterised/SlotFillParseTreeNodes +description: Parameterised transclusion using the $slotFillParseTreeNodes attribute +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim + +<$transclude $tiddler='TiddlerOne' one='Ferret'> +<$fill $name="one">This is first +<$fill $name="two">But this is second + + +<$transclude $tiddler='TiddlerOne'> +<$fill $name="one">This is first +<$fill $name="two">But this is second + ++ +title: TiddlerOne + +\whitespace trim +<$parameters $slotFillParseTreeNodes="@slotFillParseTreeNodes"> + <$text text={{{ [<@slotFillParseTreeNodes>jsonindexes[]join[,]] }}}/> + ++ +title: ExpectedResult + +

one,ts-raw,two

one,ts-raw

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/transclude/Parameterised-Slotted-Missing.tid b/editions/test/tiddlers/tests/data/transclude/Parameterised-Slotted-Missing.tid new file mode 100644 index 000000000..fe399d572 --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/Parameterised-Slotted-Missing.tid @@ -0,0 +1,24 @@ +title: Transclude/Parameterised/Slotted/Missing +description: Parameterised transclusion with slotted missing values +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +<$transclude $tiddler='TiddlerOne' one='Ferret'> + ++ +title: TiddlerOne + +\whitespace trim +<$parameters one='Jaguar'> + <$text text=<>/> + <$slot $name="content"> + Whale + + ++ +title: ExpectedResult + +

FerretWhale

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/transclude/Parameterised-Slotted.tid b/editions/test/tiddlers/tests/data/transclude/Parameterised-Slotted.tid new file mode 100644 index 000000000..c795621ef --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/Parameterised-Slotted.tid @@ -0,0 +1,27 @@ +title: Transclude/Parameterised/Slotted +description: Parameterised transclusion with slotted values +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +<$transclude $tiddler='TiddlerOne' one='Ferret'> + <$fill $name="content"> + Hippopotamus + + ++ +title: TiddlerOne + +\whitespace trim +<$parameters one='Jaguar'> + <$text text=<>/> + <$slot $name="content"> + Whale + + ++ +title: ExpectedResult + +

FerretHippopotamus

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/transclude/Procedures-Whitespace.tid b/editions/test/tiddlers/tests/data/transclude/Procedures-Whitespace.tid new file mode 100644 index 000000000..d2bded70c --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/Procedures-Whitespace.tid @@ -0,0 +1,25 @@ +title: Transclude/Procedures/Whitespace +description: Procedures should inherit whitespace settings from definition site +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +\procedure testproc() +This is a sentence +\end + +\define testmacro() +This is a sentence +\end +This is a sentence +[<>] +[<>] + ++ +title: ExpectedResult + +

This is a sentence +[This is a sentence] +[This is a sentence ]

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/transclude/Typed.tid b/editions/test/tiddlers/tests/data/transclude/Typed.tid new file mode 100644 index 000000000..c99664b59 --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/Typed.tid @@ -0,0 +1,38 @@ +title: Transclude/Typed +description: Typed transclusion +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\procedure testproc() +This is ''wikitext'' +\end + +<$transclude $variable="testproc"/> +- +<$transclude $variable="testproc" $type="text/plain"/> + +<$transclude $tiddler="Data" $index="testindex"/> +- +<$transclude $tiddler="Data" $index="testindex" $type="text/plain"/> + +<$transclude $tiddler="Data" $field="custom"/> +- +<$transclude $tiddler="Data" $field="custom" $type="text/plain"/> ++ +title: Data +type: application/x-tiddler-dictionary +custom: This is ''wikitext'' + +testindex: This is ''wikitext'' ++ +title: ExpectedResult + +

This is wikitext +- +

This is ''wikitext''

This is wikitext +- +

This is ''wikitext''

This is wikitext +- +

This is ''wikitext''

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/widgets/LetWidgetSelfReferences.tid b/editions/test/tiddlers/tests/data/widgets/LetWidgetSelfReferences.tid new file mode 100644 index 000000000..b81fc7d75 --- /dev/null +++ b/editions/test/tiddlers/tests/data/widgets/LetWidgetSelfReferences.tid @@ -0,0 +1,15 @@ +title: Widgets/LetWidgetSelfReferences +description: Test let widget self references +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +<$let default={{{ [[default]is[variable]then[aa]else[bb]] }}} > +<> + ++ +title: ExpectedResult + +

bb

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/widgets/LetWidgetUndefinedVariable.tid b/editions/test/tiddlers/tests/data/widgets/LetWidgetUndefinedVariable.tid new file mode 100644 index 000000000..e6163d915 --- /dev/null +++ b/editions/test/tiddlers/tests/data/widgets/LetWidgetUndefinedVariable.tid @@ -0,0 +1,15 @@ +title: Widgets/LetWidgetUndefinedVariable +description: Test let widget undefined variable +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +<$let test1=<> test2={{{ [] }}}> +<> + ++ +title: ExpectedResult + +

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/test-filters.js b/editions/test/tiddlers/tests/test-filters.js index 2e5d45d22..e00d0bf8d 100644 --- a/editions/test/tiddlers/tests/test-filters.js +++ b/editions/test/tiddlers/tests/test-filters.js @@ -422,7 +422,7 @@ Tests the filtering mechanism. expect(wiki.filterTiddlers("[[one]tagging[]sort[title]]").join(",")).toBe("Tiddler Three,Tiddler8,TiddlerOne,TiddlerSeventh"); expect(wiki.filterTiddlers("[[one]tagging[]]").join(",")).toBe("Tiddler Three,TiddlerOne,TiddlerSeventh,Tiddler8"); expect(wiki.filterTiddlers("[[two]tagging[]sort[title]]").join(",")).toBe("$:/TiddlerFive,$:/TiddlerTwo,Tiddler Three"); - var fakeWidget = {getVariable: function() {return "one";}}; + var fakeWidget = {wiki: wiki, getVariable: function(name) {return name === "currentTiddler" ? "one": undefined;}}; expect(wiki.filterTiddlers("[all[current]tagging[]]",fakeWidget).join(",")).toBe("Tiddler Three,TiddlerOne,TiddlerSeventh,Tiddler8"); }); @@ -625,7 +625,7 @@ Tests the filtering mechanism. expect(wiki.filterTiddlers("[{!!title}]").join(",")).toBe(""); expect(wiki.filterTiddlers("[prefix{Tiddler8}] +[sort[title]]").join(",")).toBe("Tiddler Three,TiddlerOne"); expect(wiki.filterTiddlers("[modifier{Tiddler8!!test-field}] +[sort[title]]").join(",")).toBe("TiddlerOne"); - var fakeWidget = {wiki: wiki, getVariable: function() {return "Tiddler Three";}}; + var fakeWidget = {wiki: wiki, getVariable: function(name) {return name === "currentTiddler" ? "Tiddler Three": undefined;}}; expect(wiki.filterTiddlers("[modifier{!!modifier}] +[sort[title]]",fakeWidget).join(",")).toBe("$:/TiddlerTwo,a fourth tiddler,one,Tiddler Three"); }); @@ -1071,6 +1071,20 @@ Tests the filtering mechanism. expect(wiki.filterTiddlers("[charcode[9],[10]]").join(" ")).toBe(String.fromCharCode(9) + String.fromCharCode(10)); expect(wiki.filterTiddlers("[charcode[]]").join(" ")).toBe(""); }); + + it("should handle the levenshtein operator", function() { + expect(wiki.filterTiddlers("[[apple]levenshtein[apple]]").join(" ")).toBe("0"); + expect(wiki.filterTiddlers("[[apple]levenshtein[banana]]").join(" ")).toBe("9"); + expect(wiki.filterTiddlers("[[representation]levenshtein[misreprehensionisation]]").join(" ")).toBe("10"); + expect(wiki.filterTiddlers("[[the cat sat on the mat]levenshtein[the hat saw in every category]]").join(" ")).toBe("13"); + }); + + it("should handle the makepatches operator", function() { + expect(wiki.filterTiddlers("[[apple]makepatches[apple]]").join(" ")).toBe(""); + expect(wiki.filterTiddlers("[[apple]makepatches[banana]]").join(" ")).toBe("@@ -1,5 +1,6 @@\n-apple\n+banana\n"); + expect(wiki.filterTiddlers("[[representation]makepatches[misreprehensionisation]]").join(" ")).toBe("@@ -1,13 +1,21 @@\n+mis\n repre\n-sent\n+hensionis\n atio\n"); + expect(wiki.filterTiddlers("[[the cat sat on the mat]makepatches[the hat saw in every category]]").join(" ")).toBe("@@ -1,22 +1,29 @@\n the \n-c\n+h\n at sa\n-t on the mat\n+w in every category\n"); + }); it("should parse filter variable parameters", function(){ expect($tw.utils.parseFilterVariable("currentTiddler")).toEqual( diff --git a/editions/test/tiddlers/tests/test-parsetextreference.js b/editions/test/tiddlers/tests/test-parsetextreference.js index 376ad9ec4..59f885232 100644 --- a/editions/test/tiddlers/tests/test-parsetextreference.js +++ b/editions/test/tiddlers/tests/test-parsetextreference.js @@ -124,7 +124,7 @@ describe("Wiki.parseTextReference tests", function() { // Non-existent subtiddler of a plugin expect(parseAndGetSource("$:/ShadowPlugin","text",null,"MyMissingTiddler")).toEqual(null); // Plain text tiddler - expect(parseAndGetSource("TiddlerNine")).toEqual(undefined); + expect(parseAndGetSource("TiddlerNine")).toEqual("this is plain text"); }); }); diff --git a/editions/test/tiddlers/tests/test-utils.js b/editions/test/tiddlers/tests/test-utils.js index 8b7630a54..d41d5047a 100644 --- a/editions/test/tiddlers/tests/test-utils.js +++ b/editions/test/tiddlers/tests/test-utils.js @@ -188,4 +188,4 @@ describe("Utility tests", function() { }); -})(); +})(); \ No newline at end of file diff --git a/editions/test/tiddlers/tests/test-widget.js b/editions/test/tiddlers/tests/test-widget.js index 2614d6f52..544ed928f 100755 --- a/editions/test/tiddlers/tests/test-widget.js +++ b/editions/test/tiddlers/tests/test-widget.js @@ -143,7 +143,7 @@ describe("Widget module", function() { var wiki = new $tw.Wiki(); // Add a tiddler wiki.addTiddlers([ - {title: "TiddlerOne", text: "<$transclude tiddler='TiddlerTwo'/>\n"}, + {title: "TiddlerOne", text: "<$transclude tiddler='TiddlerTwo'/>"}, {title: "TiddlerTwo", text: "<$transclude tiddler='TiddlerOne'/>"} ]); // Test parse tree @@ -157,7 +157,7 @@ describe("Widget module", function() { // Render the widget node to the DOM var wrapper = renderWidgetNode(widgetNode); // Test the rendering - expect(wrapper.innerHTML).toBe("Recursive transclusion error in transclude widget\n"); + expect(wrapper.innerHTML).toBe("Recursive transclusion error in transclude widget"); }); it("should deal with SVG elements", function() { @@ -683,7 +683,7 @@ describe("Widget module", function() { expect(wrapper.innerHTML).toBe("

New value

"); }); - it("should can mix setWidgets and macros when importing", function() { + it("should support mixed setWidgets and macros when importing", function() { var wiki = new $tw.Wiki(); // Add some tiddlers wiki.addTiddlers([ @@ -699,6 +699,20 @@ describe("Widget module", function() { expect(wrapper.innerHTML).toBe("

Aval Bval Cval

"); }); + it("should skip parameters widgets when importing", function() { + var wiki = new $tw.Wiki(); + // Add some tiddlers + wiki.addTiddlers([ + {title: "B", text: "<$parameters bee=nothing><$set name='B' value='Bval'>\n\ndummy text"}, + ]); + var text = "\\import B\n<>"; + var widgetNode = createWidgetNode(parseText(text,wiki),wiki); + // Render the widget node to the DOM + var wrapper = renderWidgetNode(widgetNode); + // Test the rendering + expect(wrapper.innerHTML).toBe("

Bval

"); + }); + it("can have more than one macroDef variable imported", function() { var wiki = new $tw.Wiki(); wiki.addTiddlers([ diff --git a/editions/test/tiddlers/tests/test-wikitext-parser.js b/editions/test/tiddlers/tests/test-wikitext-parser.js index 7f1551c28..bc3d9acd8 100644 --- a/editions/test/tiddlers/tests/test-wikitext-parser.js +++ b/editions/test/tiddlers/tests/test-wikitext-parser.js @@ -19,7 +19,8 @@ describe("WikiText parser tests", function() { // Define a parsing shortcut var parse = function(text) { - return wiki.parseText("text/vnd.tiddlywiki",text).tree; + var tree = wiki.parseText("text/vnd.tiddlywiki",text).tree; + return tree; }; it("should parse tags", function() { @@ -114,7 +115,70 @@ describe("WikiText parser tests", function() { it("should parse macro definitions", function() { expect(parse("\\define myMacro()\nnothing\n\\end\n")).toEqual( - [ { type : 'set', attributes : { name : { type : 'string', value : 'myMacro' }, value : { type : 'string', value : 'nothing' } }, children : [ ], params : [ ], isMacroDefinition : true } ] + [{"type":"set","attributes":{"name":{"name":"name","type":"string","value":"myMacro"},"value":{"name":"value","type":"string","value":"nothing"}},"children":[],"params":[],"isMacroDefinition":true,"orderedAttributes":[{"name":"name","type":"string","value":"myMacro"},{"name":"value","type":"string","value":"nothing"}]}] + + ); + }); + + it("should parse procedure definitions with no parameters", function() { + expect(parse("\\procedure myMacro()\nnothing\n\\end\n")).toEqual( + + [{"type":"set","attributes":{"name":{"name":"name","type":"string","value":"myMacro"},"value":{"name":"value","type":"string","value":"nothing"}},"children":[],"params":[],"orderedAttributes":[{"name":"name","type":"string","value":"myMacro"},{"name":"value","type":"string","value":"nothing"}],"isProcedureDefinition":true}] + + ); + }); + + it("should parse single line procedure definitions with no parameters", function() { + expect(parse("\\procedure myMacro() nothing\n")).toEqual( + + [{"type":"set","attributes":{"name":{"name":"name","type":"string","value":"myMacro"},"value":{"name":"value","type":"string","value":"nothing"}},"children":[],"params":[],"orderedAttributes":[{"name":"name","type":"string","value":"myMacro"},{"name":"value","type":"string","value":"nothing"}],"isProcedureDefinition":true}] + + ); + }); + + it("should parse procedure definitions with parameters", function() { + expect(parse("\\procedure myMacro(one,two,three,four:elephant)\nnothing\n\\end\n")).toEqual( + + [{"type":"set","attributes":{"name":{"name":"name","type":"string","value":"myMacro"},"value":{"name":"value","type":"string","value":"nothing"}},"children":[],"params":[{"name":"one"},{"name":"two"},{"name":"three"},{"name":"four","default":"elephant"}],"orderedAttributes":[{"name":"name","type":"string","value":"myMacro"},{"name":"value","type":"string","value":"nothing"}],"isProcedureDefinition":true}] + + ); + }); + + it("should parse procedure definitions", function() { + expect(parse("\\procedure myMacro(one:'Jaguar')\n<$text text=<>/>\n\\end\n\n")).toEqual( + + [{"type":"set","attributes":{"name":{"name":"name","type":"string","value":"myMacro"},"value":{"name":"value","type":"string","value":"<$text text=<>/>"}},"children":[],"params":[{"name":"one","default":"Jaguar"}],"orderedAttributes":[{"name":"name","type":"string","value":"myMacro"},{"name":"value","type":"string","value":"<$text text=<>/>"}],"isProcedureDefinition":true}] + + ); + + }); it("should parse function definitions with no parameters", function() { + expect(parse("\\function myMacro()\nnothing\n\\end\n")).toEqual( + + [{"type":"set","attributes":{"name":{"name":"name","type":"string","value":"myMacro"},"value":{"name":"value","type":"string","value":"nothing"}},"children":[],"params":[],"orderedAttributes":[{"name":"name","type":"string","value":"myMacro"},{"name":"value","type":"string","value":"nothing"}],"isFunctionDefinition":true}] + + ); + }); + + it("should parse single line function definitions with no parameters", function() { + expect(parse("\\function myMacro() nothing\n")).toEqual( + + [{"type":"set","attributes":{"name":{"name":"name","type":"string","value":"myMacro"},"value":{"name":"value","type":"string","value":"nothing"}},"children":[],"params":[],"orderedAttributes":[{"name":"name","type":"string","value":"myMacro"},{"name":"value","type":"string","value":"nothing"}],"isFunctionDefinition":true}] + + ); + }); + + it("should parse function definitions with parameters", function() { + expect(parse("\\function myMacro(one,two,three,four:elephant)\nnothing\n\\end\n")).toEqual( + + [{"type":"set","attributes":{"name":{"name":"name","type":"string","value":"myMacro"},"value":{"name":"value","type":"string","value":"nothing"}},"children":[],"params":[{"name":"one"},{"name":"two"},{"name":"three"},{"name":"four","default":"elephant"}],"orderedAttributes":[{"name":"name","type":"string","value":"myMacro"},{"name":"value","type":"string","value":"nothing"}],"isFunctionDefinition":true}] + + ); + }); + + it("should parse function definitions", function() { + expect(parse("\\function myMacro(one:'Jaguar')\n<$text text=<>/>\n\\end\n\n")).toEqual( + + [{"type":"set","attributes":{"name":{"name":"name","type":"string","value":"myMacro"},"value":{"name":"value","type":"string","value":"<$text text=<>/>"}},"children":[],"params":[{"name":"one","default":"Jaguar"}],"orderedAttributes":[{"name":"name","type":"string","value":"myMacro"},{"name":"value","type":"string","value":"<$text text=<>/>"}],"isFunctionDefinition":true}] ); }); @@ -122,7 +186,7 @@ describe("WikiText parser tests", function() { it("should parse comment in pragma area. Comment will be invisible", function() { expect(parse("\n\\define aMacro()\nnothing\n\\end\n")).toEqual( - [ { type : 'set', attributes : { name : { type : 'string', value : 'aMacro' }, value : { type : 'string', value : 'nothing' } }, children : [ ], params : [ ], isMacroDefinition : true } ] + [{"type":"set","attributes":{"name":{"name":"name","type":"string","value":"aMacro"},"value":{"name":"value","type":"string","value":"nothing"}},"children":[],"params":[],"isMacroDefinition":true,"orderedAttributes":[{"name":"name","type":"string","value":"aMacro"},{"name":"value","type":"string","value":"nothing"}]}] ); }); @@ -143,38 +207,38 @@ describe("WikiText parser tests", function() { it("should parse inline macro calls", function() { expect(parse("<><><><>")).toEqual( - [ { type: 'element', tag: 'p', start: 0, end: 35, children: [ { type: 'macrocall', start: 0, params: [ ], name: 'john', end: 8 }, { type: 'macrocall', start: 8, params: [ ], name: 'paul', end: 16 }, { type: 'macrocall', start: 16, params: [ ], name: 'george', end: 26 }, { type: 'macrocall', start: 26, params: [ ], name: 'ringo', end: 35 } ] } ] + [{"type":"element","tag":"p","children":[{"type":"transclude","start":0,"end":8,"attributes":{"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"}]},{"type":"transclude","start":8,"end":16,"attributes":{"$variable":{"name":"$variable","type":"string","value":"paul"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"paul"}]},{"type":"transclude","start":16,"end":26,"attributes":{"$variable":{"name":"$variable","type":"string","value":"george"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"george"}]},{"type":"transclude","start":26,"end":35,"attributes":{"$variable":{"name":"$variable","type":"string","value":"ringo"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"ringo"}]}],"start":0,"end":35}] ); expect(parse("text <>")).toEqual( - [{ type: 'element', tag: 'p', start: 0, end: 92, children: [ { type: 'text', text: 'text ', start: 0, end: 5 }, { type: 'macrocall', name: 'john', start: 5, params: [ { type: 'macro-parameter', start: 11, value: 'val1', name: 'one', end: 20 }, { type: 'macro-parameter', start: 20, value: 'val "2"', name: 'two', end: 35 }, { type: 'macro-parameter', start: 35, value: 'val \'3\'', name: 'three', end: 52 }, { type: 'macro-parameter', start: 52, value: 'val 4"5\'', name: 'four', end: 73 }, { type: 'macro-parameter', start: 73, value: 'val 5', name: 'five', end: 89 } ], end: 92 } ] } ] + [{"type":"element","tag":"p","children":[{"type":"text","text":"text ","start":0,"end":5},{"type":"transclude","start":5,"end":92,"attributes":{"$variable":{"name":"$variable","type":"string","value":"john"},"one":{"name":"one","type":"string","value":"val1","start":11,"end":20},"two":{"name":"two","type":"string","value":"val \"2\"","start":20,"end":35},"three":{"name":"three","type":"string","value":"val '3'","start":35,"end":52},"four":{"name":"four","type":"string","value":"val 4\"5'","start":52,"end":73},"five":{"name":"five","type":"string","value":"val 5","start":73,"end":89}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"},{"name":"one","type":"string","value":"val1","start":11,"end":20},{"name":"two","type":"string","value":"val \"2\"","start":20,"end":35},{"name":"three","type":"string","value":"val '3'","start":35,"end":52},{"name":"four","type":"string","value":"val 4\"5'","start":52,"end":73},{"name":"five","type":"string","value":"val 5","start":73,"end":89}]}],"start":0,"end":92}] ); expect(parse("ignored << carrots <>")).toEqual( - [ { type: 'element', tag: 'p', start: 0, end: 27, children: [ { type: 'text', text: 'ignored << carrots ', start: 0, end: 19 }, { type: 'macrocall', name: 'john', start: 19, params: [ ], end: 27 } ] } ] + [{"type":"element","tag":"p","children":[{"type":"text","text":"ignored << carrots ","start":0,"end":19},{"type":"transclude","start":19,"end":27,"attributes":{"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"}]}],"start":0,"end":27}] ); expect(parse("text <<>")).toEqual( - [ { type: 'element', tag: 'p', start: 0, end: 14, children: [ { type: 'text', text: 'text ', start: 0, end: 5 }, { type: 'macrocall', name: '>")).toEqual( - [ { type: 'element', tag: 'p', start: 0, end: 15, children: [ { type: 'text', text: 'before\n', start: 0, end: 7 }, { type: 'macrocall', start: 7, params: [ ], name: 'john', end: 15 } ] } ] + [{"type":"element","tag":"p","children":[{"type":"text","text":"before\n","start":0,"end":7},{"type":"transclude","start":7,"end":15,"attributes":{"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"}]}],"start":0,"end":15}] ); // A single space will cause it to be inline expect(parse("<> ")).toEqual( - [ { type: 'element', tag: 'p', start: 0, end: 9, children: [ { type: 'macrocall', start: 0, params: [ ], name: 'john', end: 8 }, { type: 'text', text: ' ', start: 8, end: 9 } ] } ] + [{"type":"element","tag":"p","children":[{"type":"transclude","start":0,"end":8,"attributes":{"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"}]},{"type":"text","text":" ","start":8,"end":9}],"start":0,"end":9}] ); expect(parse("text <>' >>")).toEqual( - [ { type: 'element', tag: 'p', start: 0, end: 34, children: [ { type: 'text', text: 'text ', start: 0, end: 5 }, { type: 'macrocall', start: 5, params: [ { type: 'macro-parameter', start: 12, value: 'my <>', name: 'one', end: 31 } ], name: 'outie', end: 34 } ] } ] + [{"type":"element","tag":"p","children":[{"type":"text","text":"text ","start":0,"end":5},{"type":"transclude","start":5,"end":34,"attributes":{"$variable":{"name":"$variable","type":"string","value":"outie"},"one":{"name":"one","type":"string","value":"my <>","start":12,"end":31}},"orderedAttributes":[{"name":"$variable","type":"string","value":"outie"},{"name":"one","type":"string","value":"my <>","start":12,"end":31}]}],"start":0,"end":34}] ); @@ -183,37 +247,37 @@ describe("WikiText parser tests", function() { it("should parse block macro calls", function() { expect(parse("<>\n<>\r\n<>\n<>")).toEqual( - [ { type: 'macrocall', start: 0, name: 'john', params: [ ], end: 8, isBlock: true }, { type: 'macrocall', start: 9, name: 'paul', params: [ ], end: 17, isBlock: true }, { type: 'macrocall', start: 19, name: 'george', params: [ ], end: 29, isBlock: true }, { type: 'macrocall', start: 30, name: 'ringo', params: [ ], end: 39, isBlock: true } ] + [ { type: 'transclude', start: 0, attributes: { $variable: { name: "$variable", type: "string", value: "john" }}, orderedAttributes: [ { name: "$variable", type: "string", value: "john" }], end: 8, isBlock: true }, { type: 'transclude', start: 9, attributes: { $variable: { name: "$variable", type: "string", value: "paul" }}, orderedAttributes: [ { name: "$variable", type: "string", value: "paul" }], end: 17, isBlock: true }, { type: 'transclude', start: 19, attributes: { $variable: { name: "$variable", type: "string", value: "george" }}, orderedAttributes: [ { name: "$variable", type: "string", value: "george" }], end: 29, isBlock: true }, { type: 'transclude', start: 30, attributes: { $variable: { name: "$variable", type: "string", value: "ringo" }}, orderedAttributes: [ { name: "$variable", type: "string", value: "ringo" }], end: 39, isBlock: true } ] ); expect(parse("<>")).toEqual( - [ { type: 'macrocall', start: 0, name: 'john', params: [ { type: 'macro-parameter', start: 6, value: 'val1', name: 'one', end: 15 }, { type: 'macro-parameter', start: 15, value: 'val "2"', name: 'two', end: 30 }, { type: 'macro-parameter', start: 30, value: 'val \'3\'', name: 'three', end: 47 }, { type: 'macro-parameter', start: 47, value: 'val 4"5\'', name: 'four', end: 68 }, { type: 'macro-parameter', start: 68, value: 'val 5', name: 'five', end: 84 }], end: 87, isBlock: true } ] + [{"type":"transclude","start":0,"end":87,"attributes":{"$variable":{"name":"$variable","type":"string","value":"john"},"one":{"name":"one","type":"string","value":"val1","start":6,"end":15},"two":{"name":"two","type":"string","value":"val \"2\"","start":15,"end":30},"three":{"name":"three","type":"string","value":"val '3'","start":30,"end":47},"four":{"name":"four","type":"string","value":"val 4\"5'","start":47,"end":68},"five":{"name":"five","type":"string","value":"val 5","start":68,"end":84}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"},{"name":"one","type":"string","value":"val1","start":6,"end":15},{"name":"two","type":"string","value":"val \"2\"","start":15,"end":30},{"name":"three","type":"string","value":"val '3'","start":30,"end":47},{"name":"four","type":"string","value":"val 4\"5'","start":47,"end":68},{"name":"five","type":"string","value":"val 5","start":68,"end":84}],"isBlock":true}] ); expect(parse("<< carrots\n\n<>")).toEqual( - [ { type: 'element', tag: 'p', start : 0, end : 10, children: [ { type: 'text', text: '<< carrots', start : 0, end : 10 } ] }, { type: 'macrocall', start: 12, params: [ ], name: 'john', end: 20, isBlock: true } ] + [ { type: 'element', tag: 'p', start : 0, end : 10, children: [ { type: 'text', text: '<< carrots', start : 0, end : 10 } ] }, { type: 'transclude', start: 12, attributes: { $variable: {name: "$variable", type:"string", value: "john"} }, orderedAttributes: [ {name: "$variable", type:"string", value: "john"} ], end: 20, isBlock: true } ] ); expect(parse("before\n\n<>")).toEqual( - [ { type: 'element', tag: 'p', start : 0, end : 6, children: [ { type: 'text', text: 'before', start : 0, end : 6 } ] }, { type: 'macrocall', start: 8, name: 'john', params: [ ], end: 16, isBlock: true } ] + [ { type: 'element', tag: 'p', start : 0, end : 6, children: [ { type: 'text', text: 'before', start : 0, end : 6 } ] }, { type: 'transclude', start: 8, attributes: { $variable: {name: "$variable", type:"string", value: "john"} }, orderedAttributes: [ {name: "$variable", type:"string", value: "john"} ], end: 16, isBlock: true } ] ); expect(parse("<>\nafter")).toEqual( - [ { type: 'macrocall', start: 0, name: 'john', params: [ ], end: 8, isBlock: true }, { type: 'element', tag: 'p', start: 9, end: 14, children: [ { type: 'text', text: 'after', start: 9, end: 14 } ] } ] + [ { type: 'transclude', start: 0, attributes: { $variable: {name: "$variable", type:"string", value: "john"} }, orderedAttributes: [ {name: "$variable", type:"string", value: "john"} ], end: 8, isBlock: true }, { type: 'element', tag: 'p', start: 9, end: 14, children: [ { type: 'text', text: 'after', start: 9, end: 14 } ] } ] ); expect(parse("<>")).toEqual( - [ { type: 'macrocall', start: 0, params: [ { type: 'macro-parameter', start: 11, value: '\n\nwikitext\n', name: 'arg', end: 33 } ], name: 'multiline', end: 36, isBlock: true }] + [{"type":"transclude","start":0,"end":36,"attributes":{"$variable":{"name":"$variable","type":"string","value":"multiline"},"arg":{"name":"arg","type":"string","value":"\n\nwikitext\n","start":11,"end":33}},"orderedAttributes":[{"name":"$variable","type":"string","value":"multiline"},{"name":"arg","type":"string","value":"\n\nwikitext\n","start":11,"end":33}],"isBlock":true}] ); expect(parse("<>' >>")).toEqual( - [ { type: 'macrocall', start: 0, params: [ { type: 'macro-parameter', start: 7, value: 'my <>', name: 'one', end: 26 } ], name: 'outie', end: 29, isBlock: true } ] + [ { type: 'transclude', start: 0, attributes: { $variable: {name: "$variable", type:"string", value: "outie"}, one: {name: "one", type:"string", value: "my <>", start: 7, end: 26} }, orderedAttributes: [ {name: "$variable", type:"string", value: "outie"}, {name: "one", type:"string", value: "my <>", start: 7, end: 26} ], end: 29, isBlock: true } ] ); }); @@ -221,23 +285,23 @@ describe("WikiText parser tests", function() { it("should parse tricky macrocall parameters", function() { expect(parse("<am>>")).toEqual( - [ { type: 'macrocall', start: 0, params: [ { type: 'macro-parameter', start: 6, value: 'pa>am', end: 12 } ], name: 'john', end: 14, isBlock: true } ] + [{"type":"transclude","start":0,"end":14,"attributes":{"0":{"name":"0","type":"string","value":"pa>am","start":6,"end":12},"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"},{"name":"0","type":"string","value":"pa>am","start":6,"end":12}],"isBlock":true}] ); expect(parse("< >>")).toEqual( - [ { type: 'macrocall', start: 0, params: [ { type: 'macro-parameter', start: 6, value: 'param>', end: 13 } ], name: 'john', end: 16, isBlock: true } ] + [{"type":"transclude","start":0,"end":16,"attributes":{"0":{"name":"0","type":"string","value":"param>","start":6,"end":13},"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"},{"name":"0","type":"string","value":"param>","start":6,"end":13}],"isBlock":true}] ); expect(parse("<>>")).toEqual( - [ { type: 'element', tag: 'p', start: 0, end: 15, children: [ { type: 'macrocall', start: 0, params: [ { type: 'macro-parameter', start: 6, value: 'param', end: 12 } ], name: 'john', end: 14 }, { type: 'text', text: '>', start: 14, end: 15 } ] } ] + [{"type":"element","tag":"p","children":[{"type":"transclude","start":0,"end":14,"attributes":{"0":{"name":"0","type":"string","value":"param","start":6,"end":12},"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"},{"name":"0","type":"string","value":"param","start":6,"end":12}]},{"type":"text","text":">","start":14,"end":15}],"start":0,"end":15}] ); // equals signs should be allowed expect(parse("<=4 >>")).toEqual( - [ { type: 'macrocall', start: 0, params: [ { type: 'macro-parameter', start: 6, value: 'var>=4', end: 13 } ], name: 'john', end: 16, isBlock: true } ] + [{"type":"transclude","start":0,"end":16,"attributes":{"0":{"name":"0","type":"string","value":"var>=4","start":6,"end":13},"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"},{"name":"0","type":"string","value":"var>=4","start":6,"end":13}],"isBlock":true}] ); diff --git a/editions/test/tiddlers/tests/test-wikitext-tabs-macro.js b/editions/test/tiddlers/tests/test-wikitext-tabs-macro.js index b37f402cc..39f061d11 100644 --- a/editions/test/tiddlers/tests/test-wikitext-tabs-macro.js +++ b/editions/test/tiddlers/tests/test-wikitext-tabs-macro.js @@ -1,7 +1,7 @@ /*\ title: test-wikitext-tabs-macro.js type: application/javascript -tags: [[$:/tags/test-spec]] +tags: [[$:/tags/test-spec-disabled]] Tests the core tabs macro by comparing the HTML output with a stored template. Intended to permit future readability improvements. @@ -74,7 +74,7 @@ describe("Tabs-macro HTML tests", function() { expect(wiki.renderTiddler("text/html","test-tabs-macro-horizontal")).toBe(expected.fields.text.replace(/\n/g,"")); }); - it("should render 'horizontal' tabs from v5.2.2 and up with whitespace trim", function() { + it("should render all 'horizontal' tabs from v5.2.2 and up with whitespace trim", function() { expect(wiki.renderTiddler("text/html","test-tabs-macro-horizontal-all")).toBe(expectedAll.fields.text.replace(/\n/g,"")); }); diff --git a/editions/tw5.com/tiddlers/Saving on Browser with TiddlyStow.tid b/editions/tw5.com/tiddlers/Saving on Browser with TiddlyStow.tid new file mode 100644 index 000000000..870936ffc --- /dev/null +++ b/editions/tw5.com/tiddlers/Saving on Browser with TiddlyStow.tid @@ -0,0 +1,16 @@ +caption: TiddlyStow (experimental) +color: #FF8A65 +created: 20230403170650008 +delivery: Saver +description: Save changes using new versions of Chromium based browsers +method: save +modified: 20230403183020357 +tags: Chrome Edge Opera Saving Linux Mac Windows +title: Saving on Browser with TiddlyStow +type: text/vnd.tiddlywiki +url: https://github.com/btheado/tiddlystow + +''Link:'' {{!!url}} + +Tiddlystow saves TiddlyWiki files locally using the browser file system API (Chrome-based browsers currently). +This is a simple web page for loading a local TiddlyWiki file and storing it back to the same local file requiring no plugins or extensions. \ No newline at end of file diff --git a/editions/tw5.com/tiddlers/Brackets.tid b/editions/tw5.com/tiddlers/concepts/Brackets.tid similarity index 92% rename from editions/tw5.com/tiddlers/Brackets.tid rename to editions/tw5.com/tiddlers/concepts/Brackets.tid index 529adb17e..fee36313c 100644 --- a/editions/tw5.com/tiddlers/Brackets.tid +++ b/editions/tw5.com/tiddlers/concepts/Brackets.tid @@ -10,5 +10,5 @@ WikiText syntax uses a number of different types of brackets. Their names are sh |`()` |Round brackets |Parenthesis |Not used in WikiText | |`[]` |Square brackets |Brackets |[[Links|Linking in WikiText]], [[Filters|Filters]] | |`{}` |Curly brackets |Braces |[[Text references|TextReference]], [[Filtered attributes|HTML in WikiText]] | -|`<>` |Angle brackets |Chevrons |[[HTML elements and widgets|HTML in WikiText]], [[Macros|Macros in WikiText]] | +|`<>` |Angle brackets |Chevrons |[[HTML elements and widgets|HTML in WikiText]], [[Macros]] | diff --git a/editions/tw5.com/tiddlers/concepts/Date Fields.tid b/editions/tw5.com/tiddlers/concepts/Date Fields.tid index 7ffb40c5c..c58398d19 100644 --- a/editions/tw5.com/tiddlers/concepts/Date Fields.tid +++ b/editions/tw5.com/tiddlers/concepts/Date Fields.tid @@ -1,5 +1,5 @@ created: 20150117190213631 -modified: 20201201154211507 +modified: 20230226144641763 tags: Concepts title: Date Fields type: text/vnd.tiddlywiki @@ -21,6 +21,8 @@ Values of date fields are 17 or 18-character strings: To avoid problems arising from differences of time zone, TiddlyWiki always uses [[UTC|https://en.wikipedia.org/wiki/Coordinated_Universal_Time]]. +The [[DateFormat]] template for storage of dates in these fields is `[UTC]YYYY0MM0DD0hh0mm0ss0XXX`. + As an example, the <<.field created>> field of this tiddler has the value <<.value """<$view field="created"/>""">>. Dates can be [[converted to other formats|DateFormat]] for display: diff --git a/editions/tw5.com/tiddlers/concepts/JSONTiddlers.tid b/editions/tw5.com/tiddlers/concepts/JSONTiddlers.tid index caffd063c..1a5a77d17 100644 --- a/editions/tw5.com/tiddlers/concepts/JSONTiddlers.tid +++ b/editions/tw5.com/tiddlers/concepts/JSONTiddlers.tid @@ -8,4 +8,4 @@ A JSON tiddler is a [[data tiddler|DataTiddlers]] containing a [[JSON|JavaScript Its [[ContentType]] is `application/json`. -The [[history list|$:/HistoryList]] is an of a JSON tiddler. +The [[history list|$:/HistoryList]] is an example of a JSON tiddler. diff --git a/editions/tw5.com/tiddlers/concepts/Macros.tid b/editions/tw5.com/tiddlers/concepts/Macros.tid index 1d06f9755..8377046f6 100644 --- a/editions/tw5.com/tiddlers/concepts/Macros.tid +++ b/editions/tw5.com/tiddlers/concepts/Macros.tid @@ -1,31 +1,42 @@ created: 20140211171341271 -modified: 20220505082754270 +modified: 20230419103154328 tags: Concepts Reference title: Macros type: text/vnd.tiddlywiki -A <<.def macro>> is a named snippet of text. WikiText can use the name as a shorthand way of [[transcluding|Transclusion]] the snippet. Such transclusions are known as <<.def "macro calls">>, and each call can supply a different set of parameters that get substituted for special placeholders within the snippet. +!! Introduction -For the syntax, see [[Macros in WikiText]]. +A <<.def macro>> is a named snippet of text. They are typically defined with the [[Pragma: \define]]: -Most macros are in fact just parameterised [[variables|Variables]]. +``` +\define my-macro(parameter:"Default value") +This is the macro, and the parameter is $parameter$. +\end +``` -They are created using the `\define` [[pragma|Pragma]]. (Behind the scenes, this is transformed into a <<.wlink SetWidget>>, i.e. macros and variables are two sides of the same coin.) +The name wrapped in double angled [[brackets|Brackets]] is used a shorthand way of [[transcluding|Transclusion]] the snippet. Such transclusions are known as <<.def "macro calls">>, and each call can supply a different set of parameters: -The snippet and its incoming parameter values are treated as simple strings of characters with no WikiText meaning, at least until the placeholders have been filled in and the macro call has returned. This means that a macro can assemble and return the complete syntax of a ~WikiText component, such as a [[link|Linking in WikiText]]. (See [[Transclusion and Substitution]] for further discussion of this.) +``` +<> +<> +``` -Within a snippet itself, the only markup detected is `$name$` (a placeholder for a macro parameter) and `$(name)$` (a placeholder for a [[variable|Variables]]). +The parameters that are specified in the macro call are substituted for special placeholders within the snippet: -The <<.mlink dumpvariables>> macro lists all variables (including macros) that are available at that position in the widget tree. +* `$parameter-name$` is replaced with the value of the named parameter +* `$(variable-name)$` is replaced with the value of the named [[variable|Variables]]). -An <<.wlink ImportVariablesWidget>> widget can be used to copy macro definitions to another branch of the [[widget tree|Widgets]]. ~TiddlyWiki uses this technique internally to implement global macros -- namely any macros defined in tiddlers with the <<.tag $:/tags/Macro>> tag. +<<.from-version "5.3.0">> Macros have been [[superseded|Macro Pitfalls]] by [[Procedures]], [[Custom Widgets]] and [[Functions]] which together provide more robust and flexible ways to encapsulate and re-use code. It is now recommended to only use macros when textual substitution is specifically required. -The tag <<.tag $:/tags/Macro/View>> is used to define macros that should only be available within the main view template and the preview panel. +!! How Macros Work -The tag <<.tag $:/tags/Macro/View/Body>> is used to define macros that should only be available within the main view template body and the preview panel. +Macros are implemented as a special kind of [[variable|Variables]]. The only thing that distinguishes them from ordinary variables is the way that the parameters are handled. -For maximum flexibility, macros can also be <<.js-macro-link "written as JavaScript modules">>. +!! Using Macros -A similar effect to a parameterised macro call can be produced by setting [[variables|Variables]] around a [[transclusion|Transclusion]]. +* [[Macro Definitions]] describes how to create macros +* [[Macro Calls]] describes how to use macros +* [[Macro Parameter Handling]] describes how macro parameters work +* [[Macro Pitfalls]] describes some of the pitfalls of using macros +* [[Core Macros]] lists the built-in core macros -~TiddlyWiki's core has [[several macros|Core Macros]] built in. diff --git a/editions/tw5.com/tiddlers/concepts/Pragma.tid b/editions/tw5.com/tiddlers/concepts/Pragma.tid index 3a9e1de12..868cf9667 100644 --- a/editions/tw5.com/tiddlers/concepts/Pragma.tid +++ b/editions/tw5.com/tiddlers/concepts/Pragma.tid @@ -1,24 +1,8 @@ + created: 20150219175930000 -modified: 20230117112239663 -tags: Concepts [[WikiText Parser Modes]] +modified: 20220122182842041 +tags: title: Pragma type: text/vnd.tiddlywiki -A <<.def pragma>> is a special component of WikiText that provides control over the way the remaining text is parsed. - -Pragmas occupy lines that start with `\`. They can only appear at the start of the text, but blank lines are allowed between them. If a pragma line appears in the main body of the text, it is treated as if it was ordinary text. -<<.from-version "5.2.6">> Pragmas can have preceding optional whitespace characters. - - -The following pragmas are available: - -;`\define` -: for defining a [[macro|Macros]] -;`\rules` -: for adjusting the set of rules used to parse the text -;`\whitespace trim` or `\whitespace notrim` -: <<.from-version "5.1.15">> Control whether whitespace is trimmed from the start and end of text runs (the default is ''notrim''). This setting can be useful when the whitespace generated by linebreaks disturbs formatting -;`\import ` -: <<.from-version "5.1.18">> Import macro definitions from tiddlers identified by a filter expression -;`\parsermode block` or `\parsermode inline` -: <<.from-version "5.2.4">> Adjust whether the remaining text is parsed in block mode or inline mode. \ No newline at end of file +See [[Pragmas]]. diff --git a/editions/tw5.com/tiddlers/concepts/WikiText.tid b/editions/tw5.com/tiddlers/concepts/WikiText.tid index 6c4ab0b3a..c8d0141bc 100644 --- a/editions/tw5.com/tiddlers/concepts/WikiText.tid +++ b/editions/tw5.com/tiddlers/concepts/WikiText.tid @@ -1,15 +1,15 @@ created: 20131205155227468 -modified: 20140919191220377 +modified: 20230303214711802 tags: Concepts Reference title: WikiText type: text/vnd.tiddlywiki -~WikiText is a concise, expressive way of typing a wide range of text formatting, hypertext and interactive features. It allows you to focus on writing without a complex user interface getting in the way. It is designed to be familiar for users of [[MarkDown|http://daringfireball.net/projects/markdown/]], but with more of a focus on linking and the interactive features. +~WikiText is a concise, expressive way of typing a wide range of text formatting, hypertext and interactive features. It allows you to focus on writing without a complex user interface getting in the way. It is designed to be familiar for users of [[Markdown]] but with more of a focus on linking and the interactive features. -~WikiText can also be inserted to the text field using the [[Editor toolbar]]. +~WikiText can also be inserted to the text field using the [[Editor toolbar]] buttons. -See [[Formatting text in TiddlyWiki]] for an introduction to WikiText. +See [[Formatting in WikiText]] and [[Formatting text in TiddlyWiki]] for an introduction to ~WikiText. -The following elements of WikiText syntax are built into the core: +The following elements of ~WikiText syntax are built into the core: -<> +<> diff --git a/editions/tw5.com/tiddlers/definitions/Markdown.tid b/editions/tw5.com/tiddlers/definitions/Markdown.tid new file mode 100644 index 000000000..8c04a9b35 --- /dev/null +++ b/editions/tw5.com/tiddlers/definitions/Markdown.tid @@ -0,0 +1,10 @@ +created: 20220727090611178 +modified: 20220728191637376 +tags: Definitions +title: Markdown + +<<< +Markdown is a text-to-HTML conversion tool for web writers. Markdown allows you to write using an easy-to-read, easy-to-write plain text format, then convert it to structurally valid XHTML (or HTML). +<<[img width=140 [Tiddlyhost Logo]] + +[[Tiddlyhost.com|https://tiddlyhost.com/]] is a hosting service for TiddlyWiki created by Simon Baird. Once you sign up and confirm your email you can create "sites", (i.e. ~TiddlyWikis), with support for online saving. Sites can be private or public, and you can optionally list them on the taggable and searchable [[Tiddlyhost Hub|https://tiddlyhost.com/hub]] where they'll be discoverable by others. + +Unlike [[TiddlySpot|Saving on TiddlySpot]], [[Tiddlyhost|https://tiddlyhost.com]] is secure, open source, and has proper support for TiddlyWiki5. It also allows uploading existing ~TiddlyWiki files, supports TiddlyWikiClassic, and lets you claim ownership of your ~TiddlySpot sites. For more information see the [[FAQ|https://github.com/simonbaird/tiddlyhost/wiki/FAQ]] and the [[About|https://tiddlyhost.com/about]] page. + +
\ No newline at end of file diff --git a/editions/tw5.com/tiddlers/definitions/Xememex.tid b/editions/tw5.com/tiddlers/definitions/Xememex.tid new file mode 100644 index 000000000..5457f23cc --- /dev/null +++ b/editions/tw5.com/tiddlers/definitions/Xememex.tid @@ -0,0 +1,14 @@ +title: Xememex +tags: Definitions +created: 20230410105035569 +modified: 20230410105035569 + +[img width=340 [Xememex Logo]] + +Xememex is a multiuser TiddlyWiki from [[Federatial]]. It allows large groups of people to work together on intertwingled wikis that can share content. It is implemented as a serverless application on Amazon Web Services. + +The largest customer implementation has hundreds of online wikis with thousands of users. See https://manuals.annafreud.org/ + +Xememex is currently only available under commercial terms from Federatial. Contact [[Jeremy Ruston at Federatial|mailto:jeremy@federatial.com]] for more details. + +
\ No newline at end of file diff --git a/editions/tw5.com/tiddlers/features/DateFormat.tid b/editions/tw5.com/tiddlers/features/DateFormat.tid index 611ff03f4..f918d9a99 100644 --- a/editions/tw5.com/tiddlers/features/DateFormat.tid +++ b/editions/tw5.com/tiddlers/features/DateFormat.tid @@ -1,12 +1,12 @@ created: 20140418142957325 -modified: 20221121131150032 +modified: 20230226144359284 tags: Features title: DateFormat type: text/vnd.tiddlywiki -The default representation of dates is a compact string such as `20211002153802059`. For example, the `created` and `modified` fields are stored like this. +The default representation of dates is a compact string such as <<.value 20211002153802059>>. The associated template is `[UTC]YYYY0MM0DD0hh0mm0ss0XXX`. For example, the <<.field created>> and <<.field modified>> fields are stored like this. -The display format for this string can be controlled with a template. For example, transcluding the `modified` field automatically applies a template to display the date as `Sat Oct 02 2021 17:40:50 GMT+0200 (Central European Summer Time)`. A few widgets and filter operators allow you to manually specify a template, for example the ViewWidget: +The display format for this string can be controlled with a template. For example, transcluding the <<.field modified>> field automatically applies a template to display the date as <<.value "Sat Oct 02 2021 17:40:50 GMT+0200 (Central European Summer Time)">>. A few widgets and filter operators allow you to manually specify a template, for example the ViewWidget: `<$view field=modified format=date template="DDth mmm YYYY 0hh:0mm:0ss" />` @@ -52,7 +52,7 @@ The date string is processed with the following substitutions: Note that other text is passed through unchanged, allowing commas, colons or other separators to be used. -The `{era:BCE||CE}` notation can specify different strings for years that are negative, zero or positive. For example `{era:BC|Z|AD}` would display `BC` for negative years, `AD` for positive years, and `Z` for year zero. +The `{era:BCE||CE}` notation can specify different strings for years that are negative, zero or positive. For example `{era:BC|Z|AD}` would display <<.value BC>> for negative years, <<.value AD>> for positive years, and <<.value Z>> for year zero. ! Examples @@ -61,7 +61,7 @@ The `{era:BCE||CE}` notation can specify different strings for years that are ne |`DDth MMM \M\M\M YYYY` |16th February MMM 2011 | |`DDth mmm YYYY 0hh:0mm:0ss` |16th Feb 2011 11:38:42 | -!! Using `TIMESTAMP` to calculate time difference +!! Using <<.value TIMESTAMP>> to calculate time difference You can calculate the difference between two dates by doing the following: @@ -71,8 +71,9 @@ You can calculate the difference between two dates by doing the following: Here is an example of calculating the number of days that passed between creation and last modification of current tiddler: -* Fields `modified` and `created` contain their respective datetimes in the format `[UTC]YYYY0MM0DD0hh0mm0ssXXX` so convert them to timestamps -* `86400000` is the number of milliseconds in a day (1000 * 60 * 60 * 24) +* Convert the <<.field created>> and <<.field modified>> fields to timestamps +* Divide their difference by <<.value 86400000>> which is the number of milliseconds in a day +** 1000 milliseconds per second × 60 seconds per minute × 60 minutes per hour × 24 hours per day = 86,400,000 milliseconds per day <$macrocall $name=".example" n="0" eg="""<$let timestamp-modified={{{ [{!!modified}format:date[TIMESTAMP]] }}} diff --git a/editions/tw5.com/tiddlers/features/StartupActions.tid b/editions/tw5.com/tiddlers/features/StartupActions.tid index 79a23b3d9..29edb8378 100644 --- a/editions/tw5.com/tiddlers/features/StartupActions.tid +++ b/editions/tw5.com/tiddlers/features/StartupActions.tid @@ -33,7 +33,7 @@ The initial startup actions are useful for customising TiddlyWiki according to e <$action-setfield $tiddler="$:/language" text={{{ [[$:/languages/en-GB]] [plugin-type[language]sort[description]removeprefix[$:/languages/]] +[prefix{$:/info/browser/language}] ~[[en-GB]] +[addprefix[$:/languages/]] }}}/> ``` -Note that global macros are not available within initial startup action tiddlers by default. If you need to access them then you'll need to explicitly include them with an ''import'' [[pragma|Pragma]] at the top of the tiddler: +Note that global macros are not available within initial startup action tiddlers by default. If you need to access them then you'll need to explicitly include them with an [[Pragma: \import]] at the top of the tiddler: ``` \import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]] diff --git a/editions/tw5.com/tiddlers/filters/applypatches Operator.tid b/editions/tw5.com/tiddlers/filters/applypatches Operator.tid new file mode 100644 index 000000000..93bb0258c --- /dev/null +++ b/editions/tw5.com/tiddlers/filters/applypatches Operator.tid @@ -0,0 +1,15 @@ +caption: applypatches +created: 20230304154824762 +modified: 20230304154826621 +op-purpose: applies a set of patches to transform the input +op-input: a [[selection of titles|Title Selection]] +op-parameter: a string containing patches from the [[makepatches Operator]] +op-parameter-name: P +op-output: the transformed input to which the patches <<.place P>> have been applied +tags: [[Filter Operators]] [[String Operators]] +title: applypatches Operator +type: text/vnd.tiddlywiki + +<<.from-version "5.2.6">> + +<<.operator-examples "makepatches and applypatches">> diff --git a/editions/tw5.com/tiddlers/filters/examples/Hamlet.tid b/editions/tw5.com/tiddlers/filters/examples/Hamlet.tid new file mode 100644 index 000000000..da209b035 --- /dev/null +++ b/editions/tw5.com/tiddlers/filters/examples/Hamlet.tid @@ -0,0 +1,11 @@ +created: 20230304161453213 +modified: 20230304162156826 +tags: [[Operator Examples]] +title: Hamlet +type: application/json + +{ + "Shakespeare-old": "Hamlet: Do you see yonder cloud that's almost in shape of a camel?\nPolonius: By the mass, and 'tis like a camel, indeed.\nHamlet: Methinks it is like a weasel.\nPolonius: It is backed like a weasel.\nHamlet: Or like a whale?\nPolonius: Very like a whale.\n-- Shakespeare", + "Shakespeare-new": "Hamlet: Do you see the cloud over there that's almost the shape of a camel?\nPolonius: By golly, it is like a camel, indeed.\nHamlet: I think it looks like a weasel.\nPolonius: It is shaped like a weasel.\nHamlet: Or like a whale?\nPolonius: It's totally like a whale.\n-- Shakespeare", + "Trekkie-old": "Kirk: Do you see yonder cloud that's almost in shape of a Klingon?\nSpock: By the mass, and 'tis like a Klingon, indeed.\nKirk: Methinks it is like a Vulcan.\nSpock: It is backed like a Vulcan.\nKirk: Or like a Romulan?\nSpock: Very like a Romulan.\n-- Trekkie" +} \ No newline at end of file diff --git a/editions/tw5.com/tiddlers/filters/examples/get.tid b/editions/tw5.com/tiddlers/filters/examples/get.tid index c49d876d6..c85a38f3e 100644 --- a/editions/tw5.com/tiddlers/filters/examples/get.tid +++ b/editions/tw5.com/tiddlers/filters/examples/get.tid @@ -1,9 +1,22 @@ created: 20150118134611000 -modified: 20150124201839000 +modified: 20230325163424379 +myfield: tags: [[get Operator]] [[Operator Examples]] title: get Operator (Examples) type: text/vnd.tiddlywiki <<.operator-example 1 "[all[current]get[draft.of]]" "the title of the tiddler of which the current tiddler is a draft">> -<<.operator-example 2 "[get[tags]]">> -<<.operator-example 3 "[each[tags]get[tags]]">> + +<<.operator-example 2 "[get[tags]]" "returns the tags of all tiddlers without de-duplication">> + +<<.operator-example 3 "[get[tags]unique[]]" "returns the tags of all tiddlers with de-duplication">> + +<<.tip """If a data tiddler contains a field with an empty value, the empty string is not appended to the results.""">> + +<<.operator-example 4 "[all[current]get[myfield]]" "the empty value of field <<.field myfield>> is not returned by the <<.olink get>> operator">> + +<<.operator-example 5 "[all[current]has:field[myfield]] :map[get[myfield]]" "also returns the empty string">> +The above example works by first checking if the input title has the field <<.field myfield>> and then using the [[Map Filter Run Prefix]] to replace the title with their value of that field. If the input tiddler does not have the field, an empty <<.em selection>> is returned. The subsequent [[Map Filter Run Prefix]] outputs an empty <<.em string>> when its run returns an empty [[selection|Title Selection]] (because the field is empty). + +<<.operator-example 6 "[all[tiddlers]] :filter[get[created]compare:date:lt{HelloThere!!created}]" "return all tiddlers that are older than [[HelloThere]]">> +The above example demonstrates two different ways of accessing field values in filters: Use <<.olink get>> when the title is not known in advance as with the [[Filter Filter Run Prefix]] where <<.var currentTiddler>> is set to the current input title. Use a [[TextReference]] as an indirect [[Filter Parameter]] when the title is known. diff --git a/editions/tw5.com/tiddlers/filters/examples/getindex.tid b/editions/tw5.com/tiddlers/filters/examples/getindex.tid index 780c09946..6dab64c77 100644 --- a/editions/tw5.com/tiddlers/filters/examples/getindex.tid +++ b/editions/tw5.com/tiddlers/filters/examples/getindex.tid @@ -1,8 +1,19 @@ created: 20150203140000000 -modified: 20170608150301791 +modified: 20230325163543621 tags: [[getindex Operator]] [[Operator Examples]] title: getindex Operator (Examples) type: text/vnd.tiddlywiki -<<.operator-example 1 "[[$:/palettes/Vanilla]getindex[background]]" "returns the value at index ''background'' of the [[DataTiddler|DataTiddlers]] [[$:/palettes/Vanilla]]">> -<<.operator-example 2 "[all[shadows+tiddlers]tag[$:/tags/Palette]getindex[background]]" "returns all background colors defined in any of the ColourPalettes">> \ No newline at end of file +<<.operator-example 1 "[[$:/palettes/Vanilla]getindex[background]]" "returns the value of property <<.value background>> of the [[DataTiddler|DataTiddlers]] [[$:/palettes/Vanilla]]">> + +<<.operator-example 2 "[all[shadows+tiddlers]tag[$:/tags/Palette]getindex[background]]" "returns all background colors defined in any of the ColourPalettes (notice the duplicates in the resulting list)">> + +<<.tip """If a data tiddler contains a property with an empty value, the empty string is not appended to the results.""">> + +<<.operator-example 3 "[[ListopsData]getindex[DataIndex]]" "the empty value of the property <<.field ~DataIndex>> in [[ListopsData]] is not returned by the <<.olink getindex>> operator">> + +<<.operator-example 4 "[[ListopsData]has:index[DataIndex]] :map[getindex[DataIndex]]" "also returns the empty string">> +The above example works by first checking if the input title has the property <<.field ~DataIndex>> and then using the [[Map Filter Run Prefix]] to replace the title with their value of that property. If the input tiddler does not have the property, an empty <<.em selection>> is returned. The subsequent [[Map Filter Run Prefix]] outputs an empty <<.em string>> when its run returns an empty [[selection|Title Selection]] (because the property is empty). + +<<.operator-example 5 "[[$:/palettes/Vanilla]indexes[]] :filter[[$:/palettes/Vanilla]getindexcount[]compare:number:eq[0]]" "returns those colors in [[$:/palettes/Vanilla]] which are defined, but have no value assigned">> +In the above example, <<.olink count>> is used to check if <<.olink getindex>> returns a result (i.e. the corresponding property has a value) or not. \ No newline at end of file diff --git a/editions/tw5.com/tiddlers/filters/examples/levenshtein Operator (Examples).tid b/editions/tw5.com/tiddlers/filters/examples/levenshtein Operator (Examples).tid new file mode 100644 index 000000000..b5049e49c --- /dev/null +++ b/editions/tw5.com/tiddlers/filters/examples/levenshtein Operator (Examples).tid @@ -0,0 +1,21 @@ +created: 20230304183158728 +modified: 20230304183159654 +tags: [[levenshtein Operator]] [[Operator Examples]] +title: levenshtein Operator (Examples) +type: text/vnd.tiddlywiki + +Determine the Levenshtein distance between two words: + +<<.operator-example 1 "[[motel]levenshtein[money]]">> + +List the 10 tiddler titles with the smallest Levenstein distance to "~TiddlyWiki": + +<$macrocall $name='wikitext-example-without-html' +src="""
    +<$list filter="[all[tiddlers]!is[system]] :sort:number[levenshtein[TiddlyWiki]] :and[first[10]]"> +
  • +<$link /> (<$text text={{{ [all[current]levenshtein[TiddlyWiki]] }}} />) +
  • + +
+"""/> \ No newline at end of file diff --git a/editions/tw5.com/tiddlers/filters/examples/makepatches and applypatches Operator (Examples).tid b/editions/tw5.com/tiddlers/filters/examples/makepatches and applypatches Operator (Examples).tid new file mode 100644 index 000000000..a9dd38d6e --- /dev/null +++ b/editions/tw5.com/tiddlers/filters/examples/makepatches and applypatches Operator (Examples).tid @@ -0,0 +1,43 @@ +created: 20230304160331362 +modified: 20230304160332927 +tags: [[makepatches Operator]] [[applypatches Operator]] [[Operator Examples]] +title: makepatches and applypatches Operator (Examples) +type: text/vnd.tiddlywiki + +These examples use the example texts in [[Hamlet]], taken from [[https://neil.fraser.name/software/diff_match_patch/demos/patch.html]] + +|^!Shakespeare's original |@@white-space: pre-wrap;{{Hamlet##Shakespeare-old}}@@ | +|^!Modern English |@@white-space: pre-wrap;{{Hamlet##Shakespeare-new}}@@ | +|^!Trekkie's Copy |@@white-space: pre-wrap;{{Hamlet##Trekkie-old}}@@ | + +
+ +Use `makepatches` to generate the set of patches to transform Shakepeare's original into Modern English: + +<<.operator-example 1 "[{Hamlet##Shakespeare-old}makepatches{Hamlet##Shakespeare-new}]">> + +Use `applypatches` to apply the patches to Shakespeare's original text: + +<<.operator-example 2 "[{Hamlet##Shakespeare-old}makepatches{Hamlet##Shakespeare-new}] :map[{Hamlet##Shakespeare-old}applypatches]">> + +In the above example, the [[Map Filter Run Prefix]] is used to pass the patches information as a parameter to `applypatches`. Inside `:map`, <<.value currentTiddler>> is set to the input title (i.e. the previously generated patches). + +The patch information from the Shakepeare texts can also be used to transform the //Trekkie's Copy// to a Modern English version: + +<<.operator-example 3 "[{Hamlet##Shakespeare-old}makepatches{Hamlet##Shakespeare-new}] :map[{Hamlet##Trekkie-old}applypatches]">> + +The above examples used the character mode of `makepatches`. The `word` mode yields very similar results in this case, even when applied to the //Trekkie's Copy//. + +<<.operator-example 4 "[{Hamlet##Shakespeare-old}makepatches:words{Hamlet##Shakespeare-new}]">> + +<<.operator-example 5 "[{Hamlet##Shakespeare-old}makepatches:words{Hamlet##Shakespeare-new}] :map[{Hamlet##Trekkie-old}applypatches]">> + +The `lines` mode doesn't work as well in this application: + +<<.operator-example 6 "[{Hamlet##Shakespeare-old}makepatches:lines{Hamlet##Shakespeare-new}]">> + +<<.operator-example 7 "[{Hamlet##Shakespeare-old}makepatches:lines{Hamlet##Shakespeare-new}] :map[{Hamlet##Trekkie-old}applypatches]">> + +It is better suited as a very fast algorithm to detect line-wise incremental changes to texts and store only the changes instead of multiple versions of the whole texts. + +
\ No newline at end of file diff --git a/editions/tw5.com/tiddlers/filters/examples/regexp.tid b/editions/tw5.com/tiddlers/filters/examples/regexp.tid index 161df8937..5b18a1613 100644 --- a/editions/tw5.com/tiddlers/filters/examples/regexp.tid +++ b/editions/tw5.com/tiddlers/filters/examples/regexp.tid @@ -17,5 +17,5 @@ The regular expression `[0-9]{2}` matches two consecutive digits. Because it con <$macrocall $name="wikitext-example-without-html" src="""<$set name="digit-pattern" value="[0-9]{2}"> -<]">> +<]" field:"title">> """/> diff --git a/editions/tw5.com/tiddlers/filters/function.tid b/editions/tw5.com/tiddlers/filters/function.tid new file mode 100644 index 000000000..f86d21f4f --- /dev/null +++ b/editions/tw5.com/tiddlers/filters/function.tid @@ -0,0 +1,21 @@ +caption: function +created: 20220909111836951 +modified: 20230419103154328 +op-input: a [[selection of titles|Title Selection]] passed as input to the function <<.place F>> +op-output: the [[selection of titles|Title Selection]] returned from the function <<.place F>> +op-parameter: first parameter is the [[function name|Functions]], subsequent parameters are passed to the function by position +op-parameter-name: F +op-purpose: apply a [[function|Functions]] to the input list, and return the result +tags: [[Filter Operators]] +title: function Operator +type: text/vnd.tiddlywiki + +<<.from-version "5.3.0">> The <<.op function>> operator applies a named [[function|Functions]] to the input titles, and returns the results from the function. The function is invoked once with all of the input titles (in contrast, the [[filter Operator]] invokes its function separately for each input title). + +The first parameter of the <<.op function>> operator specifies the name of the function to be called. Subsequent parameters are passed to the function. + +The mapping between the parameters is //positional//, with each consecutive parameter specified in the function call mapped to the corresponding parameter in the function definition. Any parameters that are not provided are given their default values. + +<<.tip "Compare with the similar [[filter|filter Operator]] and [[subfilter|subfilter Operator]] operators which take a filter strings as their parameter instead of a named function, and does not permit parameters to be passed">> + +<<.operator-examples "function">> diff --git a/editions/tw5.com/tiddlers/filters/get.tid b/editions/tw5.com/tiddlers/filters/get.tid index 8623aa6d6..818f1602f 100644 --- a/editions/tw5.com/tiddlers/filters/get.tid +++ b/editions/tw5.com/tiddlers/filters/get.tid @@ -1,17 +1,17 @@ +caption: get created: 20140426183123179 -modified: 20150203185001000 +modified: 20230309163844434 +op-input: a [[selection of titles|Title Selection]] +op-output: the values of field <<.place F>> in each of the input titles +op-parameter: the name of a [[field|TiddlerFields]] +op-parameter-name: F +op-purpose: select all values of a field in the input titles tags: [[Filter Operators]] [[Field Operators]] title: get Operator type: text/vnd.tiddlywiki -caption: get -op-purpose: select all values of a field in the input titles -op-input: a [[selection of titles|Title Selection]] -op-parameter: the name of a [[field|TiddlerFields]] -op-parameter-name: F -op-output: the values of field <<.place F>> in each of the input titles Each input title is processed in turn. If the corresponding tiddler contains field <<.place F>>, and the value of this field is not empty, then its value is appended to the output. -Unlike most other [[Filter Operators]], the [[selection|Title Selection]] output by <<.op get>> can contain duplicates. To avoid duplicates, use `each[F]get[F]`. +<<.tip "Unlike most other [[Filter Operators]], the [[selection|Title Selection]] output by <<.op get>> can contain duplicates. To avoid duplicates, use `get[F]unique[]`.">> <<.operator-examples "get">> diff --git a/editions/tw5.com/tiddlers/filters/getindex.tid b/editions/tw5.com/tiddlers/filters/getindex.tid index 89ddabb83..225a68252 100644 --- a/editions/tw5.com/tiddlers/filters/getindex.tid +++ b/editions/tw5.com/tiddlers/filters/getindex.tid @@ -1,17 +1,16 @@ +caption: getindex created: 20150203140000000 -modified: 20150203140000000 +modified: 20230309163838670 +op-input: a [[selection of titles|Title Selection]] +op-output: the values of property <<.place P>> in each of the input titles +op-parameter: the name of a [[property|DataTiddlers]] +op-parameter-name: P +op-purpose: select all values of a data property in the input titles tags: [[Filter Operators]] [[Field Operators]] title: getindex Operator -caption: getindex -op-purpose: select all values of a data property in the input titles -<$macrocall $name=".operator-def" -input="a [[selection of titles|Title Selection]]" -parameter="the name of a [[property|DataTiddlers]]" -paramName="P" -output="the values of property <<.place P>> in each of the input titles" -/> +Each input title is processed in turn, and is ignored if it does not denote a [[data tiddler|DataTiddlers]]. If the corresponding tiddler contains property <<.place P>>, and the value of this property is not empty, then its value is appended to the output. -Each input title is processed in turn, and is ignored if it does not denote a [[data tiddler|DataTiddlers]]. If the tiddler contains property <<.place P>>, the value of that property is [[dominantly appended|Dominant Append]] to the output. +<<.tip "Unlike most other [[Filter Operators]], the [[selection|Title Selection]] output by <<.op getindex>> can contain duplicates. To avoid duplicates, use `getindex[P]unique[]`.">> <<.operator-examples "getindex">> diff --git a/editions/tw5.com/tiddlers/filters/has.tid b/editions/tw5.com/tiddlers/filters/has.tid index cccb152ae..f05ae1e05 100644 --- a/editions/tw5.com/tiddlers/filters/has.tid +++ b/editions/tw5.com/tiddlers/filters/has.tid @@ -1,9 +1,9 @@ caption: has created: 20140410103123179 -modified: 20190518145446047 +modified: 20230306143207920 op-input: a [[selection of titles|Title Selection]] -op-neg-output: ''without suffix''
» those input tiddlers in which field <<.place F>> does <<.em not>> exist or has an empty value
''suffix `field`''
» those input tiddlers in which field <<.place F>> does <<.em not>> exist
''suffix `index`''
» those input tiddlers in which index <<.place F>> does <<.em not>> exist -op-output: ''without suffix''
» those input tiddlers in which field <<.place F>> has a non-empty value
''suffix `field`''
» those input tiddlers in which field <<.place F>> exists +op-neg-output: ''without suffix''
» those input tiddlers in which field <<.place F>> does <<.em not>> exist or has an empty value
''suffix `field`''
» those input tiddlers in which field <<.place F>> does <<.em not>> exist
''suffix `index`''
» those input data tiddlers in which index <<.place F>> does <<.em not>> exist +op-output: ''without suffix''
» those input tiddlers in which field <<.place F>> has a non-empty value
''suffix `field`''
» those input tiddlers in which field <<.place F>> exists
''suffix `index`''
» those input data tiddlers in which index <<.place F>> exists op-parameter: the name of a [[field|TiddlerFields]]
''suffix `index`''
» those input tiddlers in which index <<.place F>> exists op-parameter: the name of a [[field|TiddlerFields]] or, optionally an [[index|TextReference]] op-parameter-name: F diff --git a/editions/tw5.com/tiddlers/filters/levenshtein Operator.tid b/editions/tw5.com/tiddlers/filters/levenshtein Operator.tid new file mode 100644 index 000000000..7abc3e4dd --- /dev/null +++ b/editions/tw5.com/tiddlers/filters/levenshtein Operator.tid @@ -0,0 +1,17 @@ +caption: levenshtein +created: 20230304181639768 +modified: 20230304181642365 +op-purpose: determine the Levenshtein distance of the input title(s) and a given string +op-input: a [[selection of titles|Title Selection]] +op-parameter: a string +op-parameter-name: S +op-output: the Levenshtein distance between the input title(s) and <<.place S>> +tags: [[Filter Operators]] [[String Operators]] +title: levenshtein Operator +type: text/vnd.tiddlywiki + +<<.from-version "5.2.6">> + +The Levenshtein distance is a metric for measuring the difference between two strings. Informally, the Levenshtein distance between two strings is the //minimum// number of single-character edits required to change one string into the other. + +<<.operator-examples "levenshtein">> diff --git a/editions/tw5.com/tiddlers/filters/makepatches Operator.tid b/editions/tw5.com/tiddlers/filters/makepatches Operator.tid new file mode 100644 index 000000000..c59284e22 --- /dev/null +++ b/editions/tw5.com/tiddlers/filters/makepatches Operator.tid @@ -0,0 +1,23 @@ +caption: makepatches +created: 20230304122354967 +modified: 20230304122400128 +op-purpose: returns a set of patches that transform the input to a given string +op-input: a [[selection of titles|Title Selection]] +op-parameter: a string of characters +op-parameter-name: S +op-output: a set of patch instructions per input title to be used by the [[applypatches Operator]] to transform the input title(s) into the string <<.place S>> +op-suffix: `lines` to operate in line mode, `words` to operate in word mode. If omitted (default), the algorithm operates in character mode. See notes below. +op-suffix-name: T +tags: [[Filter Operators]] [[String Operators]] +title: makepatches Operator +type: text/vnd.tiddlywiki + +<<.from-version "5.2.6">> + +The difference algorithm operates in character mode by default. This produces the most detailed diff possible. In `words` mode, each word in the input text is transformed into a meta-character, upon which the algorithm then operates. In the default character mode, the filter would find two patches between "ActionWidget" and "Action-Widgets" (the hyphen and the plural s), while in `words` mode, the whole word is found to be changed. In `lines` mode, the meta-character is formed from the whole line, delimited by newline characters, and is found to be changed independent of the number of changes within the line. + +The different modes influence the result when the patches are applied to texts other than the original, as well as the runtime. + +<<.tip "The calculation in `words` mode is roughly 10 times faster than the default character mode, while `lines` mode can be more than 100 times faster than the default.">> + +<<.operator-examples "makepatches and applypatches">> diff --git a/editions/tw5.com/tiddlers/functions/Functions.tid b/editions/tw5.com/tiddlers/functions/Functions.tid new file mode 100644 index 000000000..3b06dddc7 --- /dev/null +++ b/editions/tw5.com/tiddlers/functions/Functions.tid @@ -0,0 +1,28 @@ +created: 20221009124003601 +modified: 20230419103154328 +tags: Concepts Reference +title: Functions +type: text/vnd.tiddlywiki + +!! Introduction + +<<.from-version "5.3.0">> A <<.def function>> is a named snippet of text containing a [[Filter Expression]]. Functions can have named parameters which are available within the function as variables. + +Functions are usually defined with the [[Pragma: \function]]: + +``` +\function my-function(parameter:"2") +[multiply[1.5]] +\end +``` + +Functions can be invoked in several ways: + +* Directly transclude functions with the syntax `<>` +* Assign functions to widget attributes with the syntax `
>>` +* 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]]` + +!! How Functions Work + +Functions are implemented as a special kind of [[variable|Variables]]. The only thing that distinguishes them from ordinary variables is the way that the parameters are handled. diff --git a/editions/tw5.com/tiddlers/hellothere/HelloThere.tid b/editions/tw5.com/tiddlers/hellothere/HelloThere.tid index d80da69c4..d58179819 100644 --- a/editions/tw5.com/tiddlers/hellothere/HelloThere.tid +++ b/editions/tw5.com/tiddlers/hellothere/HelloThere.tid @@ -1,15 +1,23 @@ created: 20130822170200000 list: [[A Gentle Guide to TiddlyWiki]] [[Discover TiddlyWiki]] [[Some of the things you can do with TiddlyWiki]] [[Ten reasons to switch to TiddlyWiki]] Examples [[What happened to the original TiddlyWiki?]] -modified: 20221219184500440 +modified: 20230326083239710 tags: TableOfContents title: HelloThere type: text/vnd.tiddlywiki -!! ''Welcome to TiddlyWiki, a unique [[non-linear|Philosophy of Tiddlers]] notebook for [[capturing|Creating and editing tiddlers]], [[organising|Structuring TiddlyWiki]] and [[sharing|Sharing your tiddlers with others]] complex information'' +!!.tc-hero-heading ''Welcome to TiddlyWiki, a unique [[non-linear|Philosophy of Tiddlers]] notebook for [[capturing|Creating and editing tiddlers]], [[organising|Structuring TiddlyWiki]] and [[sharing|Sharing your tiddlers with others]] complex information'' Use it to keep your [[to-do list|TaskManagementExample]], to plan an [[essay or novel|"TiddlyWiki for Scholars" by Alberto Molina]], or to organise your wedding. Record every thought that crosses your brain, or build a flexible and responsive website. -Unlike conventional online services, TiddlyWiki lets you choose where to keep your data, guaranteeing that in the decades to come you will [[still be able to use|Future Proof]] the notes you take today. +TiddlyWiki lets you choose where to keep your data, guaranteeing that in the decades to come you will [[still be able to use|Future Proof]] the notes you take today. + +!! ''Quick Start'' + +
+<$list filter="[tag[Quick Start]]"> +<$macrocall $name="flex-card" bordercolor={{!!color}} textcolor={{!!text-color}} backgroundcolor={{!!background-color}} captionField="caption" descriptionField="text"/> + +
!! ''Find Out More'' @@ -19,7 +27,7 @@ Unlike conventional online services, TiddlyWiki lets you choose where to keep yo
-!! ''~TiddlyWiki Hubs'' +!! ''Community''
!! ''Testimonials & Reviews'' diff --git a/editions/tw5.com/tiddlers/hellothere/quickstart/Quick Start.tid b/editions/tw5.com/tiddlers/hellothere/quickstart/Quick Start.tid new file mode 100644 index 000000000..ff7bec946 --- /dev/null +++ b/editions/tw5.com/tiddlers/hellothere/quickstart/Quick Start.tid @@ -0,0 +1,2 @@ +title: Quick Start +list: [[Quick Start: Tiddlyhost]] [[Quick Start: Desktop]] [[Quick Start: DIY]] [[Quick Start: Xememex]] \ No newline at end of file diff --git a/editions/tw5.com/tiddlers/hellothere/quickstart/desktop.tid b/editions/tw5.com/tiddlers/hellothere/quickstart/desktop.tid new file mode 100644 index 000000000..c20fa52de --- /dev/null +++ b/editions/tw5.com/tiddlers/hellothere/quickstart/desktop.tid @@ -0,0 +1,10 @@ +title: Quick Start: Desktop +tags: [[Quick Start]] +caption: Desktop +icon: $:/core/images/storyview-zoomin +button-color: #37753e +button-text: Download +background: linear-gradient(90deg,#f0fff1, #ffffff) +link: TiddlyDesktop + +Download the official desktop application for macOS, Windows and Linux \ No newline at end of file diff --git a/editions/tw5.com/tiddlers/hellothere/quickstart/diy.tid b/editions/tw5.com/tiddlers/hellothere/quickstart/diy.tid new file mode 100644 index 000000000..c71bfca27 --- /dev/null +++ b/editions/tw5.com/tiddlers/hellothere/quickstart/diy.tid @@ -0,0 +1,10 @@ +title: Quick Start: DIY +tags: [[Quick Start]] +caption: DIY +icon: $:/core/images/theme-button +button-color: #ff4522 +button-text: Explore +background: linear-gradient(90deg,#fff4f2, #ffffff) +link: GettingStarted + +Find the configuration that is right for you to get the full benefits of ~TiddlyWiki \ No newline at end of file diff --git a/editions/tw5.com/tiddlers/hellothere/quickstart/tiddlyhost.tid b/editions/tw5.com/tiddlers/hellothere/quickstart/tiddlyhost.tid new file mode 100644 index 000000000..75f4184fa --- /dev/null +++ b/editions/tw5.com/tiddlers/hellothere/quickstart/tiddlyhost.tid @@ -0,0 +1,10 @@ +title: Quick Start: Tiddlyhost +tags: [[Quick Start]] +caption: Tiddlyhost +icon: $:/core/images/globe +button-color: #00009a +button-text: Create Account +background: linear-gradient(90deg,#f5f5ff, #ffffff) +link: Tiddlyhost + +The easiest way to get started with an online ~TiddlyWiki \ No newline at end of file diff --git a/editions/tw5.com/tiddlers/hellothere/quickstart/xememex.tid b/editions/tw5.com/tiddlers/hellothere/quickstart/xememex.tid new file mode 100644 index 000000000..7fb562083 --- /dev/null +++ b/editions/tw5.com/tiddlers/hellothere/quickstart/xememex.tid @@ -0,0 +1,10 @@ +title: Quick Start: Xememex +tags: [[Quick Start]] +caption: Xememex +icon: $:/core/images/star-filled +button-color: #bf5fb6 +button-text: Find out more +background: linear-gradient(90deg,#fff1fe, #ffffff) +link: Xememex + +For companies and teams, a multiuser ~TiddlyWiki from Federatial \ No newline at end of file diff --git a/editions/tw5.com/tiddlers/howtos/Formatting List Results as Tables with CSS - Specified Columns Methods.tid b/editions/tw5.com/tiddlers/howtos/Formatting List Results as Tables with CSS - Specified Columns Methods.tid index 817776a1a..853f868a0 100644 --- a/editions/tw5.com/tiddlers/howtos/Formatting List Results as Tables with CSS - Specified Columns Methods.tid +++ b/editions/tw5.com/tiddlers/howtos/Formatting List Results as Tables with CSS - Specified Columns Methods.tid @@ -33,29 +33,17 @@ Note the various places you need to indicate the number of columns ``` @@.fourcolumns -<$list filter="[tag[Filter Operators]]" variable="foo">
-<> +<$list filter="[tag[Filter Operators]]" variable="foo"> +<>
@@ ``` !! Example showing partial list of filter operators - - - @@.fourcolumns -<$list filter="[tag[Filter Operators]limit[24]]" variable="foo">
-<> +<$list filter="[tag[Filter Operators]limit[24]]" variable="foo"> +<>
@@ + diff --git a/editions/tw5.com/tiddlers/howtos/Visible Transclusions.tid b/editions/tw5.com/tiddlers/howtos/Visible Transclusions.tid new file mode 100644 index 000000000..e3f46440e --- /dev/null +++ b/editions/tw5.com/tiddlers/howtos/Visible Transclusions.tid @@ -0,0 +1,14 @@ +created: 20220909111836951 +modified: 20230419103154329 +tags: Learning +title: Visible Transclusions +type: text/vnd.tiddlywiki + +!! Visible Transclusions + +Block transclusions are shown in red, and inline transclusions are shown in green. + +<$button> +<$action-setfield $tiddler="$:/temp/VisibleTransclusions" tags="$:/tags/Macro/View/Body" text={{$:/core/ui/VisibleTransclude}}/> +Click here to make transclusions visible within story river tiddlers + diff --git a/editions/tw5.com/tiddlers/images/New Release Banner.png b/editions/tw5.com/tiddlers/images/New Release Banner.png index 6cacb3e3d..b75c8fc19 100644 Binary files a/editions/tw5.com/tiddlers/images/New Release Banner.png and b/editions/tw5.com/tiddlers/images/New Release Banner.png differ diff --git a/editions/tw5.com/tiddlers/images/Open Collective Logo.tid b/editions/tw5.com/tiddlers/images/Open Collective Logo.tid new file mode 100644 index 000000000..25e91161a --- /dev/null +++ b/editions/tw5.com/tiddlers/images/Open Collective Logo.tid @@ -0,0 +1,4 @@ +title: Open Collective Logo +tags: picture + + \ No newline at end of file diff --git a/editions/tw5.com/tiddlers/images/Reddit Logo.tid b/editions/tw5.com/tiddlers/images/Reddit Logo.tid new file mode 100644 index 000000000..76bb6bf7c --- /dev/null +++ b/editions/tw5.com/tiddlers/images/Reddit Logo.tid @@ -0,0 +1,7 @@ +title: Reddit Logo + + + + + + diff --git a/editions/tw5.com/tiddlers/images/Tiddlyhost Logo.png b/editions/tw5.com/tiddlers/images/Tiddlyhost Logo.png new file mode 100644 index 000000000..f39ac2892 Binary files /dev/null and b/editions/tw5.com/tiddlers/images/Tiddlyhost Logo.png differ diff --git a/editions/tw5.com/tiddlers/images/Tiddlyhost Logo.png.meta b/editions/tw5.com/tiddlers/images/Tiddlyhost Logo.png.meta new file mode 100644 index 000000000..c0f8f256a --- /dev/null +++ b/editions/tw5.com/tiddlers/images/Tiddlyhost Logo.png.meta @@ -0,0 +1,3 @@ +title: Tiddlyhost Logo +type: image/png +tags: picture diff --git a/editions/tw5.com/tiddlers/images/Xememex Logo.svg b/editions/tw5.com/tiddlers/images/Xememex Logo.svg new file mode 100644 index 000000000..7aa281346 --- /dev/null +++ b/editions/tw5.com/tiddlers/images/Xememex Logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/editions/tw5.com/tiddlers/images/Xememex Logo.svg.meta b/editions/tw5.com/tiddlers/images/Xememex Logo.svg.meta new file mode 100644 index 000000000..1eab02541 --- /dev/null +++ b/editions/tw5.com/tiddlers/images/Xememex Logo.svg.meta @@ -0,0 +1,2 @@ +type: image/svg+xml +title: Xememex Logo diff --git a/editions/tw5.com/tiddlers/learning/Introduction to Lists.tid b/editions/tw5.com/tiddlers/learning/Introduction to Lists.tid index dd2a0269c..0cc883e47 100644 --- a/editions/tw5.com/tiddlers/learning/Introduction to Lists.tid +++ b/editions/tw5.com/tiddlers/learning/Introduction to Lists.tid @@ -6,7 +6,7 @@ type: text/vnd.tiddlywiki Making lists of items plays a central role in working with TiddlyWiki. The following is a brief run-through of some of the more common techniques. -~TiddlyWiki [[uses|The Extended Listops Filters]] lists [[internally|ListField]] for many purposes so the word can have several meanings. Here we are concerned with displaying sequences of items, but not necessarily presented as a conventional bullet list. +~TiddlyWiki [[uses|Extended Listops Filters]] lists [[internally|ListField]] for many purposes so the word can have several meanings. Here we are concerned with displaying sequences of items, but not necessarily presented as a conventional bullet list. ! Manually Typed Lists diff --git a/editions/tw5.com/tiddlers/macros/ListMacro.tid b/editions/tw5.com/tiddlers/macros/ListMacro.tid index 33bbb5713..fd7079850 100644 --- a/editions/tw5.com/tiddlers/macros/ListMacro.tid +++ b/editions/tw5.com/tiddlers/macros/ListMacro.tid @@ -15,7 +15,7 @@ Note: Each first [[step|Filter Step]] of a [[filter run|Filter Run]] not given a ;filter : A [[filter|Filters]] selecting which tiddlers to include -;caption +;field : The name of the field to transclude for each list item, defaulting to `caption` ;type : An HTML element to use for the overall list element, defaulting to `ul` diff --git a/editions/tw5.com/tiddlers/macros/import/say-hi-using-variables.tid b/editions/tw5.com/tiddlers/macros/import/say-hi-using-variables.tid index 4aa265fa3..11064f388 100644 --- a/editions/tw5.com/tiddlers/macros/import/say-hi-using-variables.tid +++ b/editions/tw5.com/tiddlers/macros/import/say-hi-using-variables.tid @@ -1,3 +1,4 @@ +code-body: yes created: 20150221145447000 modified: 20150221145626000 title: $:/editions/tw5.com/macro-examples/say-hi-using-variables diff --git a/editions/tw5.com/tiddlers/macros/import/say-hi.tid b/editions/tw5.com/tiddlers/macros/import/say-hi.tid index 2d2d31afc..55db4cc9a 100644 --- a/editions/tw5.com/tiddlers/macros/import/say-hi.tid +++ b/editions/tw5.com/tiddlers/macros/import/say-hi.tid @@ -1,8 +1,9 @@ +code-body: yes created: 20150221145803000 modified: 20150221221536000 title: $:/editions/tw5.com/macro-examples/say-hi type: text/vnd.tiddlywiki -\define sayhi(name:"Bugs Bunny" address:"Rabbit Hole Hill") +\define sayhi(name:"Bugs Bunny",address:"Rabbit Hole Hill") Hi, I'm $name$ and I live in $address$. \end diff --git a/editions/tw5.com/tiddlers/macros/import/tags-of-current-tiddler.tid b/editions/tw5.com/tiddlers/macros/import/tags-of-current-tiddler.tid index b1bfc753c..860ad33db 100644 --- a/editions/tw5.com/tiddlers/macros/import/tags-of-current-tiddler.tid +++ b/editions/tw5.com/tiddlers/macros/import/tags-of-current-tiddler.tid @@ -1,3 +1,4 @@ +code-body: yes created: 20150221145803000 title: $:/editions/tw5.com/macro-examples/tags-of-current-tiddler type: text/vnd.tiddlywiki diff --git a/editions/tw5.com/tiddlers/macros/import/tv-wikilink-tooltip.tid b/editions/tw5.com/tiddlers/macros/import/tv-wikilink-tooltip.tid index 11b442b8c..9687f4b15 100644 --- a/editions/tw5.com/tiddlers/macros/import/tv-wikilink-tooltip.tid +++ b/editions/tw5.com/tiddlers/macros/import/tv-wikilink-tooltip.tid @@ -1,5 +1,5 @@ +code-body: yes created: 20150228120252000 -modified: 20150228120554000 title: $:/editions/tw5.com/macro-examples/tv-wikilink-tooltip type: text/vnd.tiddlywiki diff --git a/editions/tw5.com/tiddlers/nodejs/tiddlywiki.files_Files.tid b/editions/tw5.com/tiddlers/nodejs/tiddlywiki.files_Files.tid index 6086dfebc..87ddf9b40 100644 --- a/editions/tw5.com/tiddlers/nodejs/tiddlywiki.files_Files.tid +++ b/editions/tw5.com/tiddlers/nodejs/tiddlywiki.files_Files.tid @@ -29,6 +29,8 @@ Each field can be specified as either a ''string'' or ''array'' value to be assi ** //extname// the extension of the filename of the file containing the tiddler ** //created// the creation date/time of the file containing the tiddler ** //modified// the modification date/time of the file containing the tiddler +** <<.from-version "5.3.0">> //filepath// the path of the file containing the tiddler, relative to the ''path'' property of the directory (only usable in ''directories'' declarations) +** <<.from-version "5.3.0">> //subdirectories// an array of the subdirectories in the file's path relative, to the ''path'' property of the directory (only usable in ''directories'' declarations) * ''prefix'' - (optional) a string to be prepended to the value of the field * ''suffix'' - (optional) a string to be appended to the value of the field @@ -52,7 +54,7 @@ Directory specifications in the `directories` array may take the following forms ** ''filesRegExp'' - (optional) a [[regular expression|https://developer.mozilla.org/en/docs/Web/JavaScript/Guide/Regular_Expressions]] that matches the filenames of the files that should be processed within the directory ** ''isTiddlerFile'' - (required) if `true`, the file will be treated as a [[tiddler file|TiddlerFiles]] and deserialised to extract the tiddlers. Otherwise, the raw content of the file is assigned to the `text` field without any parsing ** ''isEditableFile'' - <<.from-version "5.1.23">> (optional) if `true`, changes to the tiddler be saved back to the original file. The tiddler will be saved back to the original filepath as long as it does not generate a result from the $:/config/FileSystemPath filters, which will override the final filepath generated if a result is returned from a filter. -** ''searchSubdirectories'' - <<.from-version "5.1.23">> (optional) if `true`, all subdirectories of the //path// are searched recursively for files that match the (optional) //filesRegExp//. If no //filesRegExp// is provided, all files in all subdirectories of the //path// are loaded. Tiddler titles generated via a //source// attribute (see above) will only include the filename, not any of the subdirectories of the path. If this results in multiple files with loaded with the same tiddler title, then only the last file loaded under that tiddler title will be in memory. In order to prevent this, you must have multiple directory objects listed and customise the title field with a //prefix// or //suffix// alongside the //source// attribute. +** ''searchSubdirectories'' - <<.from-version "5.1.23">> (optional) if `true`, all subdirectories of the //path// are searched recursively for files that match the (optional) //filesRegExp//. If no //filesRegExp// is provided, all files in all subdirectories of the //path// are loaded. Tiddler titles generated via the //source// attribute //filename// (see above) will only include the filename, not any of the subdirectories of the path. If this results in multiple files with loaded with the same tiddler title, then only the last file loaded under that tiddler title will be in memory. In order to prevent this, you can use the //filepath// attribute instead of //filename//. Alternately, you can include multiple directory objects and customise the title field with a //prefix// or //suffix// alongside the //source// attribute. ** ''fields'' - (required) an object containing values that override or customise the fields provided in the tiddler file (see above) Fields can also be overridden for particular files by creating a file with the same name plus the suffix `.meta` -- see TiddlerFiles. @@ -95,6 +97,7 @@ This example retrieves all the files with the extension `.pdf` from a folder spe ] } ``` + !! Importing a folder of text files This example retrieves all the files with the extension `.txt` from a folder specified by a relative path. This folder is within the wiki's base directory, and the current config file is in a directory within the wiki's "tiddlers/" directory. So, in this case the path starts with "../../" to traverse upwards two directory levels, and then down into the "externalnotes/" directory. Each tiddler is set up with the following fields: @@ -130,4 +133,39 @@ This will load all text files in the `../../externalnotes/` directory into the w From the examples in [[Customising Tiddler File Naming]] we see that the final `[!tag[externalnote]addprefix[wiki/]]` filter in the $:/config/FileSystemPaths tiddler excludes all tiddlers tagged with `externalnotes` (that have not matched an earlier filter). These tiddlers have their filepath retrieved from the $:/config/OriginalTiddlerPaths generated upon boot startup. -Then, the `[tag[.txt]then[.txt]]` filter in the $:/config/FileSystemExtensions tiddler forces all these tiddlers to be saved back to disk as *.txt and accompanying *.txt.meta files (overriding the normal tiddler-type to file-type mapping). In this case, allowing the snippets of Tiddlywiki wikitext or markdown-text to be saved back to "text" *.txt files. \ No newline at end of file +Then, the `[tag[.txt]then[.txt]]` filter in the $:/config/FileSystemExtensions tiddler forces all these tiddlers to be saved back to disk as *.txt and accompanying *.txt.meta files (overriding the normal tiddler-type to file-type mapping). In this case, allowing the snippets of Tiddlywiki wikitext or markdown-text to be saved back to "text" *.txt files. + +!! Importing and auto-tagging images + +This example imports all the image files in the `files` directory and all its subdirectories as external-image tiddlers, and tags them based on their filepath. Each tiddler is set up with the following fields: + +* ''title'' - set to the URI decoded base filename of the text file +* ''created'' - set to the creation date/time of the text file +* ''modified'' - set to the modification date/time of the text file +* ''type'' - set to `image/jpeg`. There is currently no way to infer the correct ContentType of the image tiddler from the file, but `image/jpeg` tiddlers should render correctly even with png or gif images. As an alternative, you could create separate definitions for jpg, png, and gif files with the `image/jpeg`, `image/png`, and `image/gif` types respectively. +* ''tags'' - generated based on the path of the image relative to the parent directory (`files` in this case). Eg, images in `files/photos` will be tagged with `photos`, those in `files/photos/family` will be tagged with both `photos` and `family`, and those in the root `files` directory will have no tags. +* ''text'' - set to an empty string +* ''_canonical_uri'' - set to the full filepath of the image relative to the wiki root + + +``` +{ + "directories": [ + { + "path": "../../files/", + "filesRegExp": "^.*\\.(?:jpg|jpeg|png|gif)$", + "isTiddlerFile": false, + "searchSubdirectories": true, + "fields": { + "title": {"source": "basename-uri-decoded"}, + "created": {"source": "created"}, + "modified": {"source": "modified"}, + "type": "image/jpeg", + "tags": { "source": "subdirectories" }, + "text": "", + "_canonical_uri": { "source": "filepath", "prefix": "files/" } + } + } + ] +} +``` diff --git a/editions/tw5.com/tiddlers/pragmas/Pragma_ _define.tid b/editions/tw5.com/tiddlers/pragmas/Pragma_ _define.tid new file mode 100644 index 000000000..6058b7905 --- /dev/null +++ b/editions/tw5.com/tiddlers/pragmas/Pragma_ _define.tid @@ -0,0 +1,51 @@ +created: 20220917112233317 +modified: 20230419103154328 +tags: Pragmas +title: Pragma: \define +type: text/vnd.tiddlywiki + +The ''\define'' [[pragma|Pragmas]] is used to [[define macros|Macro Definitions]]. It is a shortcut syntax for the SetVariableWidget. + +The usual form allows macros to span multiple lines. + +``` +\define ([:],[:]...) + +\end [] +``` + +Note that the `\end` marker can optionally specify the name of the macro to which it relates which allows macro definitions to be nested. + +There is also a single line form for shorter macros: + +``` +\define ([:],[:]...) +``` + +The first line of the definition specifies the macro name and any parameters. Each parameter has a name and, optionally, a default value that is used if no value is supplied on a particular call to the macro. + +The lines that follow contain the text of the macro text (i.e. the snippet represented by the macro name), until `\end` appears on a line by itself: + +<$codeblock code={{$:/editions/tw5.com/macro-examples/say-hi}}/> + +Alternatively, the entire definition can be presented on a single line without an `\end` marker: + +``` +\define sayhi(name:"Bugs Bunny") Hi, I'm $name$. +``` + +Macro definitions can be nested by specifying the name of the macro in the `\end` marker. For example: + +< +\end actions +<$button actions=<>> +$caption$ + +\end special-button + +<> +""">> + +A more formal [[presentation|Macro Definition Syntax]] of this syntax is also available. diff --git a/editions/tw5.com/tiddlers/pragmas/Pragma_ _function.tid b/editions/tw5.com/tiddlers/pragmas/Pragma_ _function.tid new file mode 100644 index 000000000..253c8b452 --- /dev/null +++ b/editions/tw5.com/tiddlers/pragmas/Pragma_ _function.tid @@ -0,0 +1,27 @@ +created: 20221009162634214 +modified: 20230419103154329 +tags: Pragmas +title: Pragma: \function +type: text/vnd.tiddlywiki + +<<.from-version "5.3.0">> The ''\function'' [[pragma|Pragmas]] is used to [[define custom functions|Functions]]. It is a shortcut syntax for the SetVariableWidget. + +The usual form allows custom functions to span multiple lines: + +``` +\function ([:],[:]...) + +\end [] +``` + +Note that the `\end` marker can optionally specify the name of the function to which it relates, enabling function definitions to be nested inside procedures, macros or widget definitions. + +There is also a single line form for shorter functions: + +``` +\function ([:],[:]...) +``` + +The first line of the definition specifies the function name and any parameters. Each parameter has a name and, optionally, a default value that is used if no value is supplied on a particular call to the function. The lines that follow contain the text of the function (i.e. the snippet represented by the function name), until `\end` appears on a line by itself: + +See [[Functions]] for more details. \ No newline at end of file diff --git a/editions/tw5.com/tiddlers/pragmas/Pragma_ _import.tid b/editions/tw5.com/tiddlers/pragmas/Pragma_ _import.tid new file mode 100644 index 000000000..5971a5490 --- /dev/null +++ b/editions/tw5.com/tiddlers/pragmas/Pragma_ _import.tid @@ -0,0 +1,17 @@ +created: 20220917113054582 +modified: 20230419103154329 +tags: Pragmas +title: Pragma: \import +type: text/vnd.tiddlywiki + +The ''\import'' [[pragma|Pragmas]] is used to import definitions from other tiddlers that are identified with a filter. It is a shortcut syntax for the ImportVariablesWidget. + +``` +\import +``` + +For example: + +``` +\import [all[shadows+tiddlers]tag[$:/tags/Macro]] +``` diff --git a/editions/tw5.com/tiddlers/pragmas/Pragma_ _parameters.tid b/editions/tw5.com/tiddlers/pragmas/Pragma_ _parameters.tid new file mode 100644 index 000000000..5f32b06eb --- /dev/null +++ b/editions/tw5.com/tiddlers/pragmas/Pragma_ _parameters.tid @@ -0,0 +1,18 @@ +created: 20220917113154900 +modified: 20230419103154329 +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. + +``` +\parameters ([:],[:]...) +``` + +For example: + +``` +\parameters (firstname:"Joe",lastname:"Blogs") +``` + diff --git a/editions/tw5.com/tiddlers/pragmas/Pragma_ _procedure.tid b/editions/tw5.com/tiddlers/pragmas/Pragma_ _procedure.tid new file mode 100644 index 000000000..082bc466d --- /dev/null +++ b/editions/tw5.com/tiddlers/pragmas/Pragma_ _procedure.tid @@ -0,0 +1,55 @@ +created: 20221007132845007 +modified: 20230419103154329 +tags: Pragmas +title: Pragma: \procedure +type: text/vnd.tiddlywiki + +<<.from-version "5.3.0">> The ''\procedure'' [[pragma|Pragmas]] is used to [[define procedures|Procedure Definitions]]. It is a shortcut syntax for the SetVariableWidget with an implicit ParametersWidget. + +The usual form allows procedures to span multiple lines: + +``` +\procedure ([:],[:]...) + +\end [] +``` + +Note that the `\end` marker can optionally specify the name of the procedure to which it relates which allows procedure definitions to be nested. + +There is also a single line form for shorter procedures: + +``` +\define ([:],[:]...) +``` + +The first line of the definition specifies the procedure name and any parameters. Each parameter has a name and, optionally, a default value that is used if no value is supplied on a particular call to the procedure. The lines that follow contain the text of the procedure text (i.e. the snippet represented by the procedure name), until `\end` appears on a line by itself: + +For example: + +``` +\procedure sayhi(name:"Bugs Bunny") +Hi, I'm <>. +\end + +<> +``` + +Alternatively, the entire definition can be presented on a single line without an `\end` marker: + +``` +\procedure sayhi(name:"Bugs Bunny") Hi, I'm <>. +``` + +Procedure definitions can be nested by specifying the name of the procedure in the `\end` marker. For example: + +< +\end actions +<$button actions=<>> +<> + +\end special-button + +<> +""">> \ No newline at end of file diff --git a/editions/tw5.com/tiddlers/pragmas/Pragma_ _rules.tid b/editions/tw5.com/tiddlers/pragmas/Pragma_ _rules.tid new file mode 100644 index 000000000..799c9b71c --- /dev/null +++ b/editions/tw5.com/tiddlers/pragmas/Pragma_ _rules.tid @@ -0,0 +1,25 @@ +created: 20220917112931273 +modified: 20230419103154329 +tags: Pragmas +title: Pragma: \rules +type: text/vnd.tiddlywiki + +The ''\rules'' [[pragma|Pragmas]] adjusts the set of parser rules used to parse the remaining text. + +``` +\rules only|expect +``` + +The list of available parser rules can be consulted in $:/ControlPanel -> Info -> Advanced -> Parsing. + +For example, in stylesheets it is typical to only use the rules associated with macros and transclusions: + +``` +\rules only filteredtranscludeinline transcludeinline macrodef macrocallinline +``` + +Some users prefer not to use CamelCase links: + +``` +\rules except prettylink +``` \ No newline at end of file diff --git a/editions/tw5.com/tiddlers/pragmas/Pragma_ _whitespace.tid b/editions/tw5.com/tiddlers/pragmas/Pragma_ _whitespace.tid new file mode 100644 index 000000000..273a35bea --- /dev/null +++ b/editions/tw5.com/tiddlers/pragmas/Pragma_ _whitespace.tid @@ -0,0 +1,20 @@ +created: 20220917113002350 +modified: 20230419103154329 +tags: Pragmas +title: Pragma: \whitespace +type: text/vnd.tiddlywiki + +<<.from-version "5.1.15">> The ''\whitespace'' [[pragma|Pragmas]] determines how spaces and newlines are treated within wikitext. Note that this only applies to the printable text, and not to other text, such as the values of attributes. + +* ''notrim'' -- whitespace text is not subject to special processing (the default) +* ''trim'' -- whitespace text is removed + +``` +\whitespace trim|notrim +``` + +For example: + +``` +\whitespace trim +``` diff --git a/editions/tw5.com/tiddlers/pragmas/Pragma_ _widget.tid b/editions/tw5.com/tiddlers/pragmas/Pragma_ _widget.tid new file mode 100644 index 000000000..f8e589d4a --- /dev/null +++ b/editions/tw5.com/tiddlers/pragmas/Pragma_ _widget.tid @@ -0,0 +1,27 @@ +created: 20221009121950630 +modified: 20230419103154329 +tags: Pragmas +title: Pragma: \widget +type: text/vnd.tiddlywiki + +<<.from-version "5.3.0">> The ''\widget'' [[pragma|Pragmas]] is used to [[define custom widgets|Custom Widgets]]. It is a shortcut syntax for the SetVariableWidget with an implicit ParametersWidget. + +The usual form allows custom widgets to span multiple lines: + +``` +\widget ([:],[:]...) + +\end [] +``` + +Note that the `\end` marker can optionally specify the name of the widget to which it relates which allows widget definitions to be nested. + +There is also a single line form for shorter widgets: + +``` +\widget ([:],[:]...) +``` + +The first line of the definition specifies the widget name and any parameters. Each parameter has a name and, optionally, a default value that is used if no value is supplied on a particular call to the widget. The lines that follow contain the text of the widget text (i.e. the snippet represented by the widget name), until `\end` appears on a line by itself: + +See [[Custom Widgets]] for more details. \ No newline at end of file diff --git a/editions/tw5.com/tiddlers/pragmas/Pragmas.tid b/editions/tw5.com/tiddlers/pragmas/Pragmas.tid new file mode 100644 index 000000000..46981c51e --- /dev/null +++ b/editions/tw5.com/tiddlers/pragmas/Pragmas.tid @@ -0,0 +1,13 @@ +created: 20220917112416666 +modified: 20230419103154329 +tags: Concepts [[WikiText Parser Modes]] +title: Pragmas +type: text/vnd.tiddlywiki + +A <<.def pragma>> is a special component of WikiText that provides control over the way the remaining text is parsed. + +Pragmas occupy lines that start with `\`. They can only appear at the start of the text of a tiddler, but blank lines and comments are allowed between them. If a pragma appears in the main body of the text, it is treated as if it was ordinary text. + +The following pragmas are available: + +<> diff --git a/editions/tw5.com/tiddlers/procedures/Procedure Calls.tid b/editions/tw5.com/tiddlers/procedures/Procedure Calls.tid new file mode 100644 index 000000000..a6bca3dba --- /dev/null +++ b/editions/tw5.com/tiddlers/procedures/Procedure Calls.tid @@ -0,0 +1,56 @@ +caption: Macro Calls +created: 20221007130006705 +modified: 20230419103154329 +tags: WikiText Procedures +title: Procedure Calls +type: text/vnd.tiddlywiki + +!! Introduction + +This tiddler describes the different ways in which [[procedure|Procedures]] can be called. + +!! Procedure Call Transclusion Shortcut + +To call a [[procedure|Procedures]], place `<<`double angle brackets`>>` around the name and any parameter values. + +``` +<> +``` + +By default, parameters are listed in the same order as in the procedure definition. A parameter can be labelled with its name and a colon to allow them to be listed in a different order. + +If no value is specified for a parameter, the default value given for that parameter in the [[procedure definition|Procedure Definitions]] is used instead. (If no default value was defined, the parameter is blank). + +Each parameter value can be enclosed in `'`single quotes`'`, `"`double quotes`"`, `"""`triple double quotes`"""` or `[[`double square brackets`]]`. Triple double quotes allow a value to contain almost anything. If a value contains no spaces or single or double quotes, it requires no delimiters. + +See the discussion about [[parser modes|WikiText parser mode: macro examples]] + +!! Procedure Calls with <<.wlink TranscludeWidget>> Widget + +The shortcut syntax expands to the <<.wlink TranscludeWidget>> widget with the `$variable` attribute specifying the name of the procedure to transclude. + +``` +<$transclude $variable="my-procedure" param="This is the parameter value"/> +``` + +The widget itself offers greater flexibility than the shortcut syntax, including the ability to specify dynamic parameter values. + +!! Assigning Procedure Calls to Attribute Values + +The text of a procedure can be directly assigned to an attribute of a widget or HTML element. The result of the procedure is not wikified, which means that [[parameter handling|Procedure Parameter Handling]] does not take place. + +``` +
>> +... +
+``` + +!! Using Procedure Calls in Filters + +Procedure calls can be used in filters. The text is not wikified which again means that the parameters will be ignored. + +``` +<$list filter="[]"> +... + +``` \ No newline at end of file diff --git a/editions/tw5.com/tiddlers/procedures/Procedure Definitions.tid b/editions/tw5.com/tiddlers/procedures/Procedure Definitions.tid new file mode 100644 index 000000000..e108f219d --- /dev/null +++ b/editions/tw5.com/tiddlers/procedures/Procedure Definitions.tid @@ -0,0 +1,43 @@ +created: 20221007125701001 +modified: 20230419103154329 +tags: WikiText Procedures +title: Procedure Definitions +type: text/vnd.tiddlywiki + +!! Introduction + +This tiddler describes the different ways in which [[macros|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. + +``` +\define my-procedure(param) +This is the macro text (param=<>) +\end +``` + +!! Procedure Definition with Set Widget + +Procedures are implemented as a special kind of [[variable|Variables]] and so internally are actually defined with a <<.wlink SetWidget>> widget. + +``` +<$set name="my-procedure" value="This is the procedure text"> +... + +``` + +<<.note """that it is not currently possible to specify parameters when defining a procedure with the <<.wlink SetWidget>> widget.""">> + +!! Importing Procedure Definitions + +The [[Pragma: \import]] or <<.wlink ImportVariablesWidget>> widget can be used to copy procedure definitions from another tiddler. + +!! `$:/tags/Macro` Tag + +Global procedures can be defined using the [[SystemTag: $:/tags/Macro]]. + +The tag [[SystemTag: $:/tags/Macro/View]] is used to define procedures that should only be available within the main view template and the preview panel. + +The tag [[SystemTag: $:/tags/Macro/View/Body]] is used to define procedures that should only be available within the main view template body and the preview panel. diff --git a/editions/tw5.com/tiddlers/procedures/Procedure Parameter Handling.tid b/editions/tw5.com/tiddlers/procedures/Procedure Parameter Handling.tid new file mode 100644 index 000000000..f4841e4e9 --- /dev/null +++ b/editions/tw5.com/tiddlers/procedures/Procedure Parameter Handling.tid @@ -0,0 +1,24 @@ +created: 20221007130538285 +modified: 20230419103154329 +tags: WikiText Procedures +title: Procedure Parameter Handling +type: text/vnd.tiddlywiki + +!! Introduction + +[[Procedure|Procedures]] parameters are made available as variables when the procedure contents are wikified. + +!! Accessing Parameters as Variables + +When procedures are wikified, the parameters can be accessed as variables. + +For example: + +<$macrocall $name="wikitext-example-without-html" src="""\procedure say-hi(name,address) +Hi, I'm <> and I live in <
>. +\end + +<> +"""/> + +Accessing parameters as variables only works in procedures that are wikified and not, for example, when a procedure is used as an attribute value. diff --git a/editions/tw5.com/tiddlers/procedures/Procedures.tid b/editions/tw5.com/tiddlers/procedures/Procedures.tid new file mode 100644 index 000000000..15b422647 --- /dev/null +++ b/editions/tw5.com/tiddlers/procedures/Procedures.tid @@ -0,0 +1,35 @@ +created: 20221007124007426 +modified: 20230419103154329 +tags: Concepts Reference +title: Procedures +type: text/vnd.tiddlywiki + +!! Introduction + +<<.from-version "5.3.0">> A <<.def procedure>> is a named snippet of text. They are typically defined with the [[Pragma: \procedure]]: + +``` +\procedure my-procedure(parameter:"Default value") +This is the procedure, and the parameter is <>. +\end +``` + +The name wrapped in double angled [[brackets|Brackets]] is used a shorthand way of [[transcluding|Transclusion]] the snippet. Each of these <<.def "procedure calls">> can supply a different set of parameters: + +``` +<> +<> +``` + +The parameters that are specified in the procedure call are made available as variables. + +!! How Procedures Work + +Procedures are implemented as a special kind of [[variable|Variables]]. The only thing that distinguishes them from ordinary variables is the way that the parameters are handled. + +!! Using Procedures + +* [[Procedure Definitions]] describes how to create procedures +* [[Procedure Calls]] describes how to use procedures +* [[Procedure Parameter Handling]] describes how procedure parameters work + diff --git a/editions/tw5.com/tiddlers/releasenotes/Release 5.1.16.tid b/editions/tw5.com/tiddlers/releasenotes/Release 5.1.16.tid index 03754dbb6..90c62c110 100644 --- a/editions/tw5.com/tiddlers/releasenotes/Release 5.1.16.tid +++ b/editions/tw5.com/tiddlers/releasenotes/Release 5.1.16.tid @@ -112,7 +112,7 @@ Prompted by the [[General Data Protection Regulation (GDPR)|https://en.wikipedia * [[Fixed|https://github.com/Jermolene/TiddlyWiki5/pull/3093]] problem with crash when dragging over TiddlyWiki on some browsers * [[Fixed|https://github.com/Jermolene/TiddlyWiki5/pull/3079]] issue with new journal button * [[Fixed|https://github.com/Jermolene/TiddlyWiki5/pull/3164]] problem with ''filter'' and ''value'' attributes of SetWidget -* [[Fixed|https://github.com/Jermolene/TiddlyWiki5/pull/3190]] problem with numeric operands in the [[The Extended Listops Filters]] +* [[Fixed|https://github.com/Jermolene/TiddlyWiki5/pull/3190]] problem with numeric operands in the [[Extended Listops Filters]] * [[Fixed|https://github.com/Jermolene/TiddlyWiki5/commit/df1f7e9798b5f6c3d2c3fd82e438cbc9713ade04]] problem with "put" saver and 412 return codes * [[Fixed|https://github.com/Jermolene/TiddlyWiki5/pull/3048]] problem with variable references in field values in the edit template * [[Extended|https://github.com/Jermolene/TiddlyWiki5/pull/3219]] behaviour of list-after field so that the tiddler is placed at the end of the list if the list-after field is present but empty diff --git a/editions/prerelease/tiddlers/Release 5.2.6.tid b/editions/tw5.com/tiddlers/releasenotes/Release 5.2.6.tid similarity index 51% rename from editions/prerelease/tiddlers/Release 5.2.6.tid rename to editions/tw5.com/tiddlers/releasenotes/Release 5.2.6.tid index 7bccaa61c..575d9d47b 100644 --- a/editions/prerelease/tiddlers/Release 5.2.6.tid +++ b/editions/tw5.com/tiddlers/releasenotes/Release 5.2.6.tid @@ -1,39 +1,72 @@ caption: 5.2.6 -created: 20230119221001957 -modified: 20230119221001957 +created: 20230320184352916 +modified: 20230320184352916 +released: 20230320184352916 tags: ReleaseNotes title: Release 5.2.6 type: text/vnd.tiddlywiki -//[[See GitHub for detailed change history of this release|https://github.com/Jermolene/TiddlyWiki5/compare/v5.2.5...master]]// +//[[See GitHub for detailed change history of this release|https://github.com/Jermolene/TiddlyWiki5/compare/v5.2.5...v5.2.6]]// + +<<.banner-credits + credit:"""Congratulations to [[StS|https://talk.tiddlywiki.org/u/StS]] for their winning design for the banner for this release (here is the [[competition thread|https://talk.tiddlywiki.org/t/new-release-banner-competition-for-tiddlywiki-v5-2-6/6403/3]] and the [[voting thread|https://talk.tiddlywiki.org/t/vote-for-the-tiddlywiki-banner-v5-2-6/6469]]). +""" + url:"https://raw.githubusercontent.com/Jermolene/TiddlyWiki5/3a2831870b4418b8b01d155b057db5b7485562c1/editions/tw5.com/tiddlers/images/New%20Release%20Banner.png" +>> + +! Major Improvements + +!! Improved Markdown Plugin + +* <<.link-badge-updated "https://github.com/Jermolene/TiddlyWiki5/pull/6528">> the [[Markdown Plugin]] to use the newer and better maintained [[markdown-it|https://github.com/markdown-it/markdown-it]] library. The previous Markdown plugin remains available as "markdown-legacy" + +!! Better Handling of Loss of Network Connectivity with Client Server Configuration + +* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/7169">> integration between the [[BrowserStorage Plugin]] and the client-server configuration to allow changes to be made while offline and then later resynchronised with the server + +!! New Diff-Match-Patch Primitives + +* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/7290">> three new operators exposing previously hidden features of the [[Diff-Match-Patch|https://neil.fraser.name/software/diff_match_patch]] library that is integrated with TiddlyWiki: +** new [[levenshtein Operator]] to calculate the similarity of two strings as the number of characters that need to be inserted, deleted or modified in order to turn one into the other +** new [[makepatches Operator]] and [[applypatches Operator]] that can be used to make and apply patches that represent the difference between two different texts. See the [[examples|makepatches and applypatches Operator (Examples)]] ! Translation Improvements Improvements to the following translations: * Chinese +* German * Italian +* Polish ! Plugin Improvements -* <<.link-badge-updated "https://github.com/Jermolene/TiddlyWiki5/pull/6528">> the [[Markdown Plugin]] to use the newer and better maintained [[markdown-it|https://github.com/markdown-it/markdown-it]] library. The previous Markdown plugin remains available as "markdown-legacy" * <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/7176">> [[Innerwiki Plugin]] to allow the `<$data>` widget to override existing tiddler fields * <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/7207">>, <<.link-badge-here "https://github.com/Jermolene/TiddlyWiki5/commit/c39ef398bffae12c0ed7324d9b6d9d29f0f2f9ff">> and <<.link-badge-here "https://github.com/Jermolene/TiddlyWiki5/commit/8f7441f296351a4dd0852c3c782f8874d398e052">> problem preventing [[Share Plugin]] from working properly +* <<.link-badge-updated "https://github.com/Jermolene/TiddlyWiki5/commit/524cee1489f260375cac8cfe878fdc5942a4596e">> [[XLSX Plugin|XLSX Utilities Edition]] to handle importing numeric fields +* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/commit/81f514116657d0d567be7a4c45762a85beaa8bc0">> Dynannotate plugin crash when using the fake DOM used for static rendering +* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/7281">> bug where pasting text into the CodeMirror editor also opened an `$:/Import` tiddler +* <<.link-badge-improved "https://github.com/Jermolene/TiddlyWiki5/pull/7334">> documentation for the [[Railroad Plugin]] +! Accessibility Improvements + +* <<.link-badge-improved "https://github.com/Jermolene/TiddlyWiki5/pull/7232">> appearance of save wiki button so that it is accessible to users without colour vision ! Usability Improvements * <<.link-badge-improved "https://github.com/Jermolene/TiddlyWiki5/pull/7217">> consistency of tiddler deletion by allowing missing tiddlers to be 'deleted', which just results in them being closed * <<.link-badge-improved "https://github.com/Jermolene/TiddlyWiki5/commit/34643a42790777f1b235f57b5093bb29bd0b3a14">> layout switcher to include an optional icon for each layout * <<.link-badge-removed "https://github.com/Jermolene/TiddlyWiki5/commit/c0615e20ecf7d5d5e66d8a2acd28b80e8d59688d">> [[improvements to table layout|https://github.com/Jermolene/TiddlyWiki5/pull/7010]] from v5.2.5 that have proved to not be backwards compatible +* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/7323">> support for `$` HTML entity ! Widget Improvements -* +* <<.link-badge-extended "https://github.com/Jermolene/TiddlyWiki5/pull/7222">> EditTextWidget to support `focusSelectFromStart` and `focusSelectFromEnd` attributes to give better control over text selection ! Filter improvements * <<.link-badge-extended "https://github.com/Jermolene/TiddlyWiki5/pull/7121">> [[encodeuricomponent Operator]] to encode characters such as `*` that are illegal in Windows filenames +* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/commit/89fd8871b6217634c9896b9402069757ca5ea189">> [[encodebase64 Operator]] and [[decodebase64 Operator]] ! Hackability Improvements @@ -41,6 +74,7 @@ Improvements to the following translations: * <<.link-badge-improved "https://github.com/Jermolene/TiddlyWiki5/pull/7118">> readability of [[tag-picker Macro]] and [[keyboard-driven-input Macro]] * <<.link-badge-improved "https://github.com/Jermolene/TiddlyWiki5/pull/7129">> reliability of [[list-links-draggable Macro]] and [[list-tagged-draggable Macro]] by using the new GenesisWidget instead of textual substitution * <<.link-badge-improved "https://github.com/Jermolene/TiddlyWiki5/pull/7210">> [[external JavaScript core support|Using the external JavaScript template]] to make it possible to save an external JS wiki as a standard single file wiki +* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/7007">> a warning message in the browser console when the Zoomin storyview fails due to the tiddler view template lacking a single containing element ! Bug Fixes @@ -50,43 +84,60 @@ Improvements to the following translations: * <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/7121">> (and <<.link-badge-here "https://github.com/Jermolene/TiddlyWiki5/pull/7219">>) overriding `toc-caption` macro for [[Table-of-Contents Macros]] * <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/7212">> rendering of $:/core/ui/MoreSideBar/Tags when viewed within the story river * <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/7156">> undefined variable crash in [[reduce Operator]], [[filter Operator]] and [[sortsub Operator]] -* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/issues/7153">> GenesisWidget not to create anything if the `$type` attribute is blank or missing +* <<.link-badge-improved "https://github.com/Jermolene/TiddlyWiki5/issues/7153">> GenesisWidget not to create anything if the `$type` attribute is blank or missing +* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/7230">> GenesisWidget to pass `isBlock` flag to the generated widget * <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/issues/7160">> crash using [[jsonget Operator]] with "fixed" as key name * <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/commit/0b39e47ce88c7620b7a66c1553a71efaff06edb9">> importing of MP3 files to match current browser implementations * <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/7122">> crash when attempting to create an element with a blank tag name +* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/7224">> layout issue with "save tiddler" button +* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/commit/3d0ec5b1bdc157f87d65b8c9b76e681c14337eb4">> (and <<.link-badge-here "https://github.com/Jermolene/TiddlyWiki5/commit/4e5c957e975459350cd7df3038e5fb3c7aea859f">>) handling of whitespace in lists to cover all Unicode whitespace characters +* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/7228">> test spacing of parser rule checkboxes in control panel +* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/commit/f249b79e81e51d48364ea8147fe27850df9f577f">> CSS classes assigned to edit toolbar buttons +* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/issues/7247">> usage of broken CSS class `tc-storyview-zoomin-tiddler` in Zoomin story view +* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/7243">> usage of `importTitle` and `autoOpenOnImport` options for [[WidgetMessage: tm-import-tiddlers]] +* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/7276">> fixed text editor refresh when the palette is changed +* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/issues/7270">> crash with LetWidget when referencing a variable that exists but has an undefined value +* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/issues/7354">> unwanted double braces around tags specified in $:/config/NewTiddler/Tags when using "new here" button ! Node.js Improvements -* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/7169">> integration between the [[BrowserStorage Plugin]] and the client-server configuration to allow changes to be made while offline and then later resynchronised with the server * <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/7130">> duplicate fields in internal templates used in client-server configuration * <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/issues/7138">> lazy loading not triggering a sync from the server * <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/commit/bf8e1ca5b0587787bf80692b0213bb7b038c7868">> crash on creating a new tiddler if anonymous users manage to create syncable tiddlers in a read only wiki * <<.link-badge-improved "https://github.com/Jermolene/TiddlyWiki5/commit/95e61688397ff1bc9be04193bc4ce2e3c8c48dce">> handling of logout in the client-server configuration to avoid 404 errors +* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/issues/7238">> problem with saving tiddlers with `_canonical_uri` field as `.tid` files +* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/6953">> missing meta viewport to static river template ! Performance Improvements -* +* <<.link-badge-improved "https://github.com/Jermolene/TiddlyWiki5/pull/7299">> field indexer to more efficiently process lookups ! Acknowledgements [[@Jermolene|https://github.com/Jermolene]] would like to thank the contributors to this release who have generously given their time to help improve TiddlyWiki: <<.contributors """ +andrigamerita AnthonyMuscio BramChen btheado cdruan CrossEye cs8425 +EvidentlyCube fkmiec flibbles GameDungeon +hffqyd jeffrey4l joebordes kookma +linonetwo m42e Marxsal +mateuszwilczek newmedicine +michsa pippep pmario saqimtiaz @@ -94,4 +145,4 @@ Telumire twMat wincentbalin yaisog -""">> +""">> \ No newline at end of file diff --git a/editions/tw5.com/tiddlers/releasenotes/Release 5.2.7.tid b/editions/tw5.com/tiddlers/releasenotes/Release 5.2.7.tid new file mode 100644 index 000000000..62a6b5264 --- /dev/null +++ b/editions/tw5.com/tiddlers/releasenotes/Release 5.2.7.tid @@ -0,0 +1,25 @@ +caption: 5.2.7 +created: 20230326083239710 +modified: 20230326083239710 +released: 20230326083239710 +tags: ReleaseNotes +title: Release 5.2.7 +type: text/vnd.tiddlywiki + +//[[See GitHub for detailed change history of this release|https://github.com/Jermolene/TiddlyWiki5/compare/v5.2.6...v5.2.7]]// + +<<.banner-credits + credit:"""Congratulations to [[StS|https://talk.tiddlywiki.org/u/StS]] for their winning design for the banner for this release (here is the [[competition thread|https://talk.tiddlywiki.org/t/new-release-banner-competition-for-tiddlywiki-v5-2-6/6403/3]] and the [[voting thread|https://talk.tiddlywiki.org/t/vote-for-the-tiddlywiki-banner-v5-2-6/6469]]). +""" + url:"https://raw.githubusercontent.com/Jermolene/TiddlyWiki5/7926af85419ef2f813276a05833598d6d65e2ecd/editions/tw5.com/tiddlers/images/New%20Release%20Banner.png" +>> + +This is a bug fix release intended to resolve a backwards compatibility issue discovered in v5.2.6. See [[this GitHub ticket|https://github.com/Jermolene/TiddlyWiki5/issues/7371]] for the background. + +The issue is that trailing newlines within a macro definitions were being ignored, which affected whether the content were parsed in inline or block mode. + +Since v5.2.7 replaces v5.2.6 that was only released for less than a week, here is the [[release note for v5.2.6|Release 5.2.6]]. + +! Release Note for v5.2.6 + +{{Release 5.2.6}} diff --git a/editions/tw5.com/tiddlers/saving/Saving to a Git service.tid b/editions/tw5.com/tiddlers/saving/Saving to a Git service.tid index 3253d8313..113e2aa8b 100644 --- a/editions/tw5.com/tiddlers/saving/Saving to a Git service.tid +++ b/editions/tw5.com/tiddlers/saving/Saving to a Git service.tid @@ -15,7 +15,7 @@ Saving to a Git service is configured in the [[$:/ControlPanel]] in the ''Git Se * ''Type'' - (mandatory) the type of the service (e.g. GitHub, GitLab) * ''Username'' - (mandatory) the username for the Git service account used for saving changes -* ''Password'' - (mandatory) the OAUTH token or personal access token for the specified account. Note that GitHub deprecated password authetication, permitted authentication methods are shown in the[[API documentation|https://developer.github.com/v3/#authentication]]. +* ''Password'' - (mandatory) the OAUTH token or personal access token for the specified account. Note that GitHub deprecated password authentication, permitted authentication methods are shown in the [[API documentation|https://developer.github.com/v3/#authentication]]. * ''Repository'' - (mandatory) the name of the Git repository. Both the owner name and the repository name must be specified. For example `Jermolene/TiddlyWiki5` * ''Branch'' - (optional) the name of the branch to be used within the Git repository. Defaults to `main` (~GitHub) or `master` (~GitLab)" * ''Path'' - (optional) the path to the target file. Defaults to `/` diff --git a/editions/tw5.com/tiddlers/saving/Saving via a Minimal Web Server.tid b/editions/tw5.com/tiddlers/saving/Saving via a Minimal Web Server.tid new file mode 100644 index 000000000..5bbf79485 --- /dev/null +++ b/editions/tw5.com/tiddlers/saving/Saving via a Minimal Web Server.tid @@ -0,0 +1,49 @@ +caption: tw5-server +color: #70c9a0 +community-author: hffqyd +created: 20230302011710789 +delivery: Server-side Script +description: Web server for saving and uploading +method: save +modified: 20230302055929311 +tags: Android Chrome Firefox [[Internet Explorer]] Linux Mac Opera Safari Saving Windows iOS Edge +title: Saving via a Minimal Web Server +type: text/vnd.tiddlywiki + +A local server for TiddlyWiki5 that saves and backups wikis, inspired by +[[tw5-server.rb | https://gist.github.com/jimfoltz/ee791c1bdd30ce137bc23cce826096da]]. + +tw5-server provides features of: + +* Server for TiddlyWiki5, as well as other files (e.g. images used in TW5 `[img[images/*.png]]`); +* Easy to save wiki via browsers; +* Backup wiki in compress format (.gz), to save disk space; +* Auto clean backups: keep one newest per previous month, keep all backups in current month. +* Upload files/images to server, for use in tiddlywiki as external links. +* Offer binary executable for Linux, macos and windows. + +Download executable script and binary at the github.com [[tw5-server|https://github.com/hffqyd/tw5-server]]. + +! Usage + +```bash +# python script: +python tw5-server.py -p 8000 -d ./ -b backup_dir + +# binary file: +tw5server -a:192.168.0.10 -p:8000 -d:./ -b:backup + +-h usage help +-a address, defautl localhost +-p port, default 8000 +-d directory to servering, default `current dir` +-b backup directory name, default `backup` +-l log saving messages to stdout + +Backups auto-clean strategy: +Keep all backups in current month, keep only the newest one for previous months. +``` + +In Unix/Linux, just excute `./tw5-server.py` (with `chmod +x tw5-server.py`). + +Then go to http://localhost:8000 (or other address:port specified in command) in your web browser, and click on your wiki html file. diff --git a/editions/tw5.com/tiddlers/styleguide/Documentation Macros.tid b/editions/tw5.com/tiddlers/styleguide/Documentation Macros.tid index 0b92d0770..ac5d4ea19 100644 --- a/editions/tw5.com/tiddlers/styleguide/Documentation Macros.tid +++ b/editions/tw5.com/tiddlers/styleguide/Documentation Macros.tid @@ -1,5 +1,5 @@ created: 20150110182600000 -modified: 20211206080809651 +modified: 20230325161424684 tags: [[Improving TiddlyWiki Documentation]] title: Documentation Macros type: text/vnd.tiddlywiki @@ -58,6 +58,13 @@ The following macros are used throughout ~TiddlyWiki's documentation. Their name |.wlink |a link to a widget |<<.wlink ButtonWidget>> | |.wlink2 |a link to a widget, with specified text |<<.wlink2 foo ButtonWidget>> | +!Tabs +|!Macro |!Used for |!Example | +|.doc-tabs |showing a tab set in a documentation tiddler | -- | +|.doc-tab-link |button to activate a tab | -- | +|.widget-attr-link |button with a widget attribute name to activate a tab | -- | + + !User interface |!Macro |!Used for |!Example | diff --git a/editions/tw5.com/tiddlers/styleguide/Reference Tiddlers.tid b/editions/tw5.com/tiddlers/styleguide/Reference Tiddlers.tid index a42fdbe2e..e604761a6 100644 --- a/editions/tw5.com/tiddlers/styleguide/Reference Tiddlers.tid +++ b/editions/tw5.com/tiddlers/styleguide/Reference Tiddlers.tid @@ -1,7 +1,7 @@ created: 20141226192500000 -modified: 20150117152552000 -title: Reference Tiddlers +modified: 20230318160831470 tags: [[Improving TiddlyWiki Documentation]] +title: Reference Tiddlers <<.def "Reference tiddlers">> offer raw information in a comprehensive interlinked way. The reader is likely to be an intermediate or expert user. @@ -13,6 +13,7 @@ There are several subcategories: ;User manual * Presenting technical details of ~WikiText features * Subcategorised: messages, operators, widgets, etc +** Widget documentation should follow the [[Widget Documentation Style Guide]] ;Developer manual * Presenting technical details of ~TiddlyWiki's internal architecture diff --git a/editions/tw5.com/tiddlers/styleguide/Widget Documentation Style Guide.tid b/editions/tw5.com/tiddlers/styleguide/Widget Documentation Style Guide.tid new file mode 100644 index 000000000..924cd90ec --- /dev/null +++ b/editions/tw5.com/tiddlers/styleguide/Widget Documentation Style Guide.tid @@ -0,0 +1,37 @@ +created: 20230318160840043 +modified: 20230325162525198 +tags: [[Reference Tiddlers]] +title: Widget Documentation Style Guide + +Widget documentation generally consists of + +* an introductory summary of the widget's function +* an overview of attributes and how the widget content is handled +* more detailed attribute explanation when required +* examples + +The //Content and Attributes// section should describe how the content of the widget is used, followed by a table of the possible attributes, each with a short description of a single sentence. The attribute names in the table and elsewhere in the tiddler should be rendered with the <<.var .attr>> macro. The <<.var .from-version>> macro should be used as first item in the description to designate the version at which a parameter became available. + +A subsection should be used for parameters that need an //extended description//, possibly with separate examples. When there are more than 2 such subsection necessary, the subsections should be split into their own tiddlers, and the <<.var .doc-tabs>> macro should be used to transclude them into the widget documentation tiddler as tabs. + +* The <<.var .doc-tabs>> macro is used without parameters +* The <<.var .doc-tabs>> macro must not be used more than once within a single documentation tiddler +* The tiddlers to be included in the tab group should be tagged with the respective widget documentation tiddler and have a <<.field description>> field set to <<.value tab>> +* The <<.field caption>> contains the tab button text. It should be as short as possible. For the attribute name, the <<.var .attr>> macro should be used in the <<.field caption>> +* The tab tiddlers should start with a level-2-heading that links to itself, so that they may be opened from within the tabs +* They can contain examples if these are specific to the topic of the subsection + +In the attribute table, the <<.var .widget-attr-link>> macro can be used to turn attributes into a button that activates the respective tab. The <<.var .widget-attr-link>> macro is used like this + +``` +<<.widget-attr-link text: target: >> +``` + +Elsewhere, the <<.var .doc-tab-link>> macro can be used to activate the respective tab + +``` +<<.doc-tab-link text:<display text> target:<title of corresponding tiddler> tooltip:<tooltip to show when hovering over the button> class:<additional classes> >> +``` +The parameters <<.param tooltip>> and <<.param class>> are optional. + +Both link macros scroll to the tab group additionally to setting the selected tab. They can also be used within the tab contents tiddlers themselves. If a tab tiddler is opened outside the tab group, <<.var doc-tab-link>> will open the tiddler containing the tab group if it is not yet open, and scroll to its tab group if it is. \ No newline at end of file diff --git a/editions/tw5.com/tiddlers/system/doc-macros.tid b/editions/tw5.com/tiddlers/system/doc-macros.tid index 28457d3c5..e4a425f9a 100644 --- a/editions/tw5.com/tiddlers/system/doc-macros.tid +++ b/editions/tw5.com/tiddlers/system/doc-macros.tid @@ -1,5 +1,5 @@ created: 20150117152607000 -modified: 20220714133424023 +modified: 20230325141733992 tags: $:/tags/Macro title: $:/editions/tw5.com/doc-macros type: text/vnd.tiddlywiki @@ -61,6 +61,37 @@ type: text/vnd.tiddlywiki \define .toc-tab() <<.tab "TableOfContents">> \define .example-tab(_) <span class="doc-tab">$_$</span> +\define .doc-tabs() +<$macrocall $name="tabs" + tabsList="[tag<currentTiddler>description[tab]]" + default={{{ [tag<currentTiddler>first[]] }}} + explicitState={{{ [<currentTiddler>addprefix[$:/state/tab/]] }}} + class={{{ [[doc-tabs]] [<currentTiddler>encodeuricomponent[]escapecss[]addprefix[doc-tabs-]] +[join[ ]] }}} /> +\end +\define .doc-tab-link(text, target, tooltip:"", class:"") +<!-- figure out where the addressed doc-tabs are --> +<$tiddler tiddler={{{ [<currentTiddler>search:text[.doc-tabs]] :else[<currentTiddler>tags[]search:text[.doc-tabs]first[]] :else[<currentTiddler>] }}} > +<$button class={{{ [[tc-btn-invisible tc-tiddlylink]] [<__class__>] +[join[ ]] }}} + set={{{ [<currentTiddler>addprefix[$:/state/tab/]] }}} + setTo=<<__target__>> + tooltip=<<__tooltip__>>> + <<__text__>> + <!-- if tiddler with tabs is open, scroll to tabs, otherwise open that tiddler (relevant from within tab subtiddlers) --> + <$list filter="[[$:/StoryList]contains<currentTiddler>]" variable="ignore" emptyMessage="<$action-navigate />"> + <$action-sendmessage $message="tm-scroll" selector={{{ [<currentTiddler>encodeuricomponent[]addprefix[.doc-tabs-]] }}} /> + </$list> + <$action-sendmessage $message="tm-scroll" selector={{{ [<currentTiddler>encodeuricomponent[]escapecss[]addprefix[.doc-tabs-]] }}} /> +</$button> +</$tiddler> +\end +\define .widget-attr-link(text, target) +<$macrocall $name=".doc-tab-link" + text={{{ [[<code class="doc-attr">]] [<__text__>] [[</code>]] +[join[]] }}} + class="doc-tab-link" + target=<<__target__>> + tooltip={{{ [[Show more information about the ']] [<__text__>] [[' attribute]] +[join[]] }}} /> +\end + \define .button(_) <span class="doc-button">{{$:/core/ui/Buttons/$_$!!caption}}</span> \define .icon(_) <span class="doc-icon">{{$_$}}</span> @@ -185,4 +216,4 @@ $credit$ </ol> \end -<pre><$view field="text"/></pre> \ No newline at end of file +<pre><$view field="text"/></pre> diff --git a/editions/tw5.com/tiddlers/system/doc-styles.tid b/editions/tw5.com/tiddlers/system/doc-styles.tid index b6d8eeee8..e406abb95 100644 --- a/editions/tw5.com/tiddlers/system/doc-styles.tid +++ b/editions/tw5.com/tiddlers/system/doc-styles.tid @@ -1,5 +1,5 @@ created: 20150117152612000 -modified: 20220617125128201 +modified: 20230325101137075 tags: $:/tags/Stylesheet title: $:/editions/tw5.com/doc-styles type: text/vnd.tiddlywiki @@ -133,6 +133,10 @@ td svg { padding-left: 20px; } +.doc-examples-hard-breaks .doc-example-result li { + white-space: pre-wrap; +} + .doc-bad-example code, .doc-bad-example pre, table.doc-bad-example { background-color:#ffff80; } @@ -281,4 +285,14 @@ ol.doc-github-contributors li { overflow: hidden; text-overflow: ellipsis; } - +.doc-tabs.tc-tab-buttons button { + font-size: 1rem; + padding: 0.5em; +} +.doc-tabs button .doc-attr { + background-color: unset; + color: #666; +} +.doc-tab-link .doc-attr { + color: unset; +} \ No newline at end of file diff --git a/editions/tw5.com/tiddlers/system/static.content.tid b/editions/tw5.com/tiddlers/system/static.content.tid index 50889f0a3..3725b25ac 100644 --- a/editions/tw5.com/tiddlers/system/static.content.tid +++ b/editions/tw5.com/tiddlers/system/static.content.tid @@ -2,6 +2,10 @@ title: $:/core/templates/static.content \define tv-wikilink-template() https://tiddlywiki.com/static/$uri_doubleencoded$.html +<!-- Mastodon verification --> + +<a rel="me" href="https://fosstodon.org/@TiddlyWiki">Mastodon</a> + <!-- For Google, and people without JavaScript--> <$reveal default="yes" text=<<savingEmpty>> type="nomatch"> diff --git a/editions/tw5.com/tiddlers/system/tw5.com-styles.tid b/editions/tw5.com/tiddlers/system/tw5.com-styles.tid index d6d00f86f..f8e54a77c 100644 --- a/editions/tw5.com/tiddlers/system/tw5.com-styles.tid +++ b/editions/tw5.com/tiddlers/system/tw5.com-styles.tid @@ -6,6 +6,10 @@ type: text/vnd.tiddlywiki \rules only filteredtranscludeinline transcludeinline macrodef macrocallinline macrocallblock +.tc-hero-heading a.tc-tiddlylink { + font-weight: bold; +} + .tc-double-spaced-list li { padding-bottom: .5em; padding-top: .5em; @@ -140,26 +144,48 @@ type: text/vnd.tiddlywiki background: <<colour background>>; border-color: rgba(34,36,38,.15); box-shadow: 0 2px 25px 0 rgb(34 36 38 / 5%) inset; + gap: 1em; +} + +.tc-cards.tc-action-card { + text-align: center; + background: none; +} + +.tc-cards.tc-action-card .tc-card-button { + border: 1px solid <<colour foreground>>; + background: <<colour foreground>>; + margin: 0.5em; + border-radius: 6px; + padding: 0.5em; + color: <<colour background>>; + fill: <<colour background>>; +} + +.tc-cards.tc-action-card .tc-card-button svg { + width: 0.65em; + height: 0.65em; + vertical-align: middle; } .tc-tiddlylink.tc-card { font-weight: normal; max-width: 100%; position: relative; - display: flex; - flex-direction: column; background: <<colour background>>; color: <<colour foreground>>; width: 200px; min-height: 0; - padding: 0 0 0.5em 0; - margin: 0.5em; border: none; border-radius: 8px; box-shadow: 0 1px 3px 0 #d4d4d5, 0 0 0 1px #d4d4d5; transition: box-shadow 0.3s ease,transform .3s ease; } +.tc-cards.tc-cards-vertical .tc-tiddlylink.tc-card { + width: 100%; +} + @media (max-width: 500px) { .tc-cards { @@ -180,8 +206,17 @@ type: text/vnd.tiddlywiki } .tc-card-accent { - border-top-left-radius: 8px; - border-top-right-radius: 8px; + height: 100%; + display: flex; + align-items: stretch; + flex-direction: column; + justify-content: stretch; + border-radius: 8px; +} + +.tc-cards.tc-cards-vertical .tc-card-accent { + flex-direction: row; + align-items: center; } .tc-tiddlylink.tc-card:hover { @@ -233,6 +268,8 @@ type: text/vnd.tiddlywiki } .tc-card-image { + border-top-left-radius: 8px; + border-top-right-radius: 8px; line-height: 0; overflow: hidden; } @@ -254,7 +291,19 @@ type: text/vnd.tiddlywiki font-weight: 600; transition: color 0.3s ease-in-out; padding: 0 10px; - margin: 0.5em 0; + margin: 0.5em 0 0.25em 0; +} + +.tc-cards.tc-cards-vertical .tc-card-title { + font-size: 1em; + min-width: 10em; + text-align: right; +} + +.tc-cards.tc-cards-vertical .tc-card-title svg { + width: 1em; + height: 1em; + vertical-align: text-bottom; } .tc-card-subtitle, @@ -270,12 +319,17 @@ type: text/vnd.tiddlywiki .tc-card-body { font-size: 0.9em; line-height: 1.2; - padding: 0 10px; + padding: 0.25em 10px; margin: 0; } +.tc-cards.tc-cards-vertical .tc-card-body { + font-size: 1em; +} + .tc-card-body-wrapper { position: relative; + flex-grow: 1; } .tc-tiddlylink.tc-card.tc-card-quote .tc-card-body:before { @@ -325,3 +379,22 @@ type: text/vnd.tiddlywiki .tc-btn-download:active { box-shadow: none; } + +/* WikiText rules */ + +.multi-columns, +.fourcolumns { + display: block; + column-count: 4; + column-gap: 1em; + -moz-column-count: 4; + -moz-column-gap: 1em; + -webkit-column-count: 4; + -webkit-column-gap: 1em; +} + +@media (max-width: {{$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint}}) { + .multi-columns { + column-count: 2; + } +} \ No newline at end of file diff --git a/editions/tw5.com/tiddlers/system/wikitext-macros.tid b/editions/tw5.com/tiddlers/system/wikitext-macros.tid index a867def4f..7db97bf50 100644 --- a/editions/tw5.com/tiddlers/system/wikitext-macros.tid +++ b/editions/tw5.com/tiddlers/system/wikitext-macros.tid @@ -95,10 +95,10 @@ That renders as: <<tw-code $tiddler$>> \end -\define flex-card(class,bordercolor:"",imageField:"image",captionField:"caption",subtitle:"",descriptionField:"description",linkField:"link") +\define flex-card(class,bordercolor:"",backgroundcolor:"",textcolor:"",imageField:"image",captionField:"caption",subtitle:"",descriptionField:"description",linkField:"link") \whitespace trim <$link class={{{ [<__class__>addprefix[tc-card ]] }}} to={{{ [<currentTiddler>get<__linkField__>else<currentTiddler>] }}}> - <div class="tc-card-accent" style.borderTop={{{ [<__bordercolor__>!is[blank]addprefix[5px solid ]] }}}> + <div class="tc-card-accent" style.borderTop={{{ [<__bordercolor__>!is[blank]addprefix[5px solid ]] }}} style.background={{!!background}} style.backgroundColor=<<__backgroundcolor__>> style.color=<<__textcolor__>> style.fill=<<__textcolor__>>> <$list filter="[<currentTiddler>has[ribbon-text]]" variable="ignore"> <div class="tc-card-ribbon-wrapper"> <div class="tc-card-ribbon" style.backgroundColor={{{ [<currentTiddler>get[ribbon-color]else[red]] }}}> @@ -119,6 +119,7 @@ That renders as: <$text text=<<__subtitle__>>/> </div> </$list> + <div class="tc-card-icon"><$transclude tiddler={{!!icon}}/></div> <div class="tc-card-body-wrapper"> <div class="tc-card-body"> <$transclude field=<<__descriptionField__>> mode="block"/> @@ -126,6 +127,11 @@ That renders as: <div class="tc-card-body-clear"> </div> </div> + <$list filter="[all[current]has[button-text]]" variable="ignore"> + <div class="tc-card-button" style.background-color={{!!button-color}} style.border-color={{!!button-color}}> + <$text text={{!!button-text}}/> {{$:/core/images/chevron-right}} + </div> + </$list> </div> </$link> \end diff --git a/editions/tw5.com/tiddlers/systemtags/SystemTag_ $__tags_ClassFilters_TiddlerTemplate.tid b/editions/tw5.com/tiddlers/systemtags/SystemTag_ $__tags_ClassFilters_TiddlerTemplate.tid index 49ad90100..245e7cbdb 100644 --- a/editions/tw5.com/tiddlers/systemtags/SystemTag_ $__tags_ClassFilters_TiddlerTemplate.tid +++ b/editions/tw5.com/tiddlers/systemtags/SystemTag_ $__tags_ClassFilters_TiddlerTemplate.tid @@ -1,9 +1,14 @@ caption: $:/tags/ClassFilters/TiddlerTemplate created: 20221020035738692 description: marks filters evaluated to dynamically add classes to the page template. -modified: 20221020035933363 +modified: 20230326153057521 tags: SystemTags title: SystemTag: $:/tags/ClassFilters/TiddlerTemplate type: text/vnd.tiddlywiki The [[system tag|SystemTags]] `$:/tags/ClassFilters/TiddlerTemplate` marks filters evaluated to dynamically add their output as CSS classes to the tiddler template. + +The variables available are within each filter: + +* <<.var storyTiddler>>: the tiddler in the story for which the filter should be evaluated. +* <<.var currentTiddler>>: the tiddler holding the filter definition being evaluated. diff --git a/editions/tw5.com/tiddlers/variables/Variable Usage.tid b/editions/tw5.com/tiddlers/variables/Variable Usage.tid new file mode 100644 index 000000000..2166f206a --- /dev/null +++ b/editions/tw5.com/tiddlers/variables/Variable Usage.tid @@ -0,0 +1,154 @@ +created: 20230421020225031 +modified: 20230422144812613 +tags: +title: Variable Usage +type: text/vnd.tiddlywiki + +\define m1(a1) $a1$ - <<__a1__>> - <<a1>> +\procedure p1(a1) $a1$ - <<__a1__>> - <<a1>> +\function f1(a1) "$a1$" "-" [<__a1__>] ="-" [<a1>] :and[join[ ]] + +!Ways to define variables and parameters +|! how declared|! how parameters are defined|! accessing parameter values in the body| +|\define|`()`|`$param$, <<__param__>>`| +|~|<<.wlink ParametersWidget>> or `\parameters`|`<<param>>`| +|<<.wlink SetWidget>>, <<.wlink LetWidget>>, <<.wlink VarsWidget>>|<<.wlink ParametersWidget>> or `\parameters`|`<<param>>`| +|\procedure, \widget|`()`, <<.wlink ParametersWidget>> or `\parameters`|`<<param>>`| +|\function|`()`|`<param>`| +|javascript macros|`exports.params` javascript property array|passed as normal javascript function parameter and so accessed as a normal javascript variable| + +!!Examples +These examples are meant to provide insight into the various ways of defining and using parameters. In many cases they do not illustrate best practices. + +!!! \define + +<$let eg='\define mp1(a1) $a1$ - <<__a1__>> + +\define mp2() <$parameters a1><<a1>></$parameters> + +\define mp3() +\parameters(a1) +<<a1>> +\end + +|<<mp1 foo>>|<<mp2 foo>>|<<mp3 foo>>| +'> +<$macrocall $name="copy-to-clipboard-above-right" src=<<eg>>/> +<$codeblock code=<<eg>>/> +</$let> + +!!! $set, $let, $vars + +<$let eg='<$set name="sp1" value="<$parameters a1><<a1>></$parameters>"> +<$set name="sp2" value=""" +\parameters(a1) +<$parameters a1><<a1>></$parameters> +"""> +<$vars vp1="<$parameters a1><<a1>></$parameters>" vp2=""" +\parameters(a1) +<$parameters a1><<a1>></$parameters> +"""> +<$let lp1="<$parameters a1><<a1>></$parameters>" lp2=""" +\parameters(a1) +<$parameters a1><<a1>></$parameters> +"""> + +|<<sp1 foo>>|<<sp2 foo>>| +|<<vp1 foo>>|<<vp2 foo>>| +|<<lp1 foo>>|<<lp2 foo>>| +</$let> +</$vars> +</$set> +</$set> +'> +<$macrocall $name="copy-to-clipboard-above-right" src=<<eg>>/> +<$codeblock code=<<eg>>/> +</$let> + +!!! \procedure, \widget + +<$let eg='\procedure pp1(a1) <<a1>> + +\procedure pp2() <$parameters a1><<a1>></$parameters> + +\procedure pp3() +\parameters(a1) +<<a1>> +\end + +\procedure wp1(a1) <<a1>> + +\widget wp2() <$parameters a1><<a1>></$parameters> + +\widget wp3() +\parameters(a1) +<<a1>> +\end + +|<<pp1 foo>>|<<pp2 foo>>|<<pp3 foo>>| +|<<wp1 foo>>|<<wp2 foo>>|<<wp3 foo>>| +'> +<$macrocall $name="copy-to-clipboard-above-right" src=<<eg>>/> +<$codeblock code=<<eg>>/> +</$let> + +!!! \function +<$let eg='\function fp1(a1) [<a1>] +|<<fp1 foo>>|'> +<$macrocall $name="copy-to-clipboard-above-right" src=<<eg>>/> +<$codeblock code=<<eg>>/> +</$let> + + +!Behavior of invoked variables depends on how the variable was declared + +|!how invoked|!how declared|!behavior| +|`<$transclude $variable=macro/>` or `<<macro>>` in normal wikitext context|\define|All wikitext and variable substitution and textual substitution takes place| +|~|<<.wlink SetWidget>>, <<.wlink LetWidget>>, <<.wlink VarsWidget>>, \procedure, \widget|All wikitext and variable substitution takes place| +|~|\function|Invoking a function in this way (`<<macro>>`) is a synonym for `<$text text={{{[function[macro]]}}}/>`. As with any filtered transclusion (i.e. triple curly braces), all results except the first are discarded.| +|||| +|widget attribute: `<div class=<<macro>>/>`|\define|Textual substitution of parameters is performed on the body text. No further processing takes place. The result after textual substitution is used as the attribute's value| +|~|<<.wlink SetWidget>>, <<.wlink LetWidget>>, <<.wlink VarsWidget>>, \procedure, \widget|Body text is retrieved as-is and used as the attribute's value.| +|~|\function|When a function is invoked as `<div class=<<macro>>/>`, it is a synonym for `<div class={{{[function[macro]]}}}/>`. As with any filtered transclusion (i.e. triple curly braces), all results except the first are discarded. That first result is used as the attribute's value. Note that functions are recursively processed even when invoked in this form. In other words a filter expression in a function can invoke another function and the processing will continue| +|||| +|filter operator parameter: `[<macro>]`|\define|Textual substitution of parameters is performed on the body text. No further processing takes place. The result after textual substitution is used as the filter operator's parameter.| +|~|<<.wlink SetWidget>>, <<.wlink LetWidget>>, <<.wlink VarsWidget>>, \procedure, \widget|Body text is retrieved as-is and used as the filter operator's parameter.| +|~|\function|The body text of the function is treated as a filter expression and evaluated. The first result is passed to the operator as a parameter. The remaining results are discarded| +|||| +|function call in a filter expression: `[function[macro]]`|\define, <<.wlink SetWidget>>, <<.wlink LetWidget>>, <<.wlink VarsWidget>>, \procedure, \widget|Every function is a variable, but only variables defined using \function are invokable using the <<.olink function>> filter operator. Attempts to use a non-function variable is the same as if the function doesn't exist. The behavior in this case is like the identity function. All filter input is passed unchanged to the output.| +|~|\function|The body text of the function is treated as a filter expression and evaluated. This filter expression can itself contain a function call. Filter expressions can be factored out into functions arbitrarily deep.| + +!! Examples + +Below is an example macro, procedure and function definition. All three forms of parameter substitution `$a1$`, `<<__a1__>>`, and `<<a1>>` are included in each definition. The output helps illustrate when each form of substitution will or will not have affect. + +``` +\define m1(a1) $a1$ - <<__a1__>> - <<a1>> +\procedure p1(a1) $a1$ - <<__a1__>> - <<a1>> +\function f1(a1) $a1$ "-" [<__a1__>] ="-" [<a1>] :and[join[ ]] +``` + +| !Variable transclusion|!output | +| `<<m1 foo>>`|<<m1 foo>>| +| `<<p1 foo>>`|<<p1 foo>>| +| `<<f1 foo>>`|<<f1 foo>>| +| !Widget attribute|!output | +| `<$text text=<<m1 foo>>/>`|<$text text=<<m1 foo>>/>| +| `<$text text=<<p1 foo>>/>`|<$text text=<<p1 foo>>/>| +| `<$text text=<<f1 foo>>/>`|<$text text=<<f1 foo>>/>| +| !Filter operator parameter|!output | +| `[<m1 foo>]`|<$text text={{{[<m1 foo>]}}}/>| +| `[<p1 foo>]`|<$text text={{{[<p1 foo>]}}}/>| +| `[<f1 foo>]`|<$text text={{{[<f1 foo>]}}}/>| +| !Function call in filter expression|!output | +| `[function[m1],[foo]]`|<$text text={{{[function[m1],[foo]]}}}/>| +| `[function[p1],[foo]]`|<$text text={{{[function[p1],[foo]]}}}/>| +| `[function[f1],[foo]]`|<$text text={{{[function[f1],[foo]]}}}/>| + +!Namespaces + +*''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 + *''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. diff --git a/editions/tw5.com/tiddlers/variables/Variables.tid b/editions/tw5.com/tiddlers/variables/Variables.tid index 2e80f2678..65ad96b31 100644 --- a/editions/tw5.com/tiddlers/variables/Variables.tid +++ b/editions/tw5.com/tiddlers/variables/Variables.tid @@ -1,23 +1,142 @@ created: 20141002133113496 -modified: 20221221175615776 -tags: Concepts Reference +modified: 20230422150445336 +tags: Concepts Reference WikiText title: Variables type: text/vnd.tiddlywiki -A <<.def variable>> is a snippet of text that can be accessed by name within a particular branch of the [[widget tree|Widgets]]. The snippet is known as the variable's <<.def value>>. +!! Introduction -A new variable is defined using a <<.wlink SetWidget>> or <<.wlink LetWidget>> widget, and is then available to any of the children of that widget, including transcluded content. A <<.wid set>> widget can reuse an existing name, thus binding a different snippet to that name for the duration of the widget's children. +A <<.def variable>> is a snippet of text that can be accessed by name. The text is referred to as the variable's <<.def value>>. -The <<.wlink ListWidget>> widget by default sets a particular variable <<.var currentTiddler>> to each listed title in turn. +Variables are defined by [[widgets|Widgets]]. Several core widgets define variables, the most common being the <<.wlink SetWidget>>, <<.wlink LetWidget>> and <<.wlink ListWidget>> widgets. -For an overview of how to use variables, see [[Variables in WikiText]]. +The values of variables are available to descendant widgets, including transcluded content. For example, within each tiddler in the main story river the variable "currentTiddler" is set to the title of the tiddler. -Despite the term <<.word variable>>, ''each snippet is a constant string''. The apparent variability is actually the result of the presence of multiple variables with the same name in different parts of the widget tree. +Variables can also be overwritten by descendent widgets defining variables of the same name, thus binding a different snippet to that name for the scope of the children of the widget. -[[Macros]] are a special form of variable whose value can contain placeholders that get filled in with parameters whenever the macro is used. +!! Special Kinds of Variables -By themselves, the snippets are <<.em not>> parsed as WikiText. However, a variable reference will transclude a snippet into a context where ~WikiText parsing <<.em may>> be occurring. Within a snippet, the only markup detected is `$name$` for a macro parameter transclusion and `$(name)$` for a variable transclusion. +There are several special kinds of variable that extend their basic capabilities: -The <<.mlink dumpvariables>> macro lists all variables (including macros) that are available at that position in the widget tree. +* [[Procedures]] are snippets of text that can be passed parameters when wikified +* [[Functions]] are snippets of text containing [[filters|Filters]] with optional named parameters +* [[Custom Widgets]] are snippets of text containing definitions of custom [[widget|Widgets]] +* [[Macros]] are snippets of text that can contain placeholders that are filled in with parameters whenever the macro is used + +Note that these special kinds of variable can only be created with the associated shortcut definition syntax. + +For a more detailed comparison of these special kinds of variables, see [[Variable Usage]]. + +!! Defining Variables + +The following core widgets are commonly used to define variables: + +* <<.wlink LetWidget>> widget -- the easiest way to define multiple variables +* <<.wlink SetWidget>> widget -- the most flexible way to define a single variable +* <<.wlink ParametersWidget>> widget -- used to declare parameter variables within [[procedures|Procedures]] and [[custom widgets|Custom Widgets]] +* <<.wlink ListWidget>> widget -- defines a loop variable and optional counter variable +* <<.wlink SetMultipleVariablesWidget>> widget -- allows creation of multiple variables at once where the names and values are not known in advance + +!! Using Variables + +Once a variable is defined there are several ways to access it. + +!!! Transcluding Variables + +Transcluding a variable renders the text contents of the variable as if it replaced the call. It is a shortcut syntax for the <<.wlink TranscludeWidget>> widget with the `$variable` attribute. + +``` +<<varname>> +``` + +Parameters can be passed to the transclusion as follows: + +``` +<<varname "This is a parameter">> +<<varname param:"This is a parameter">> +<<varname param:"This is a parameter" second:"Another parameter">> +``` + +The handling of these parameters depends on the kind of variable: + +* [[Procedures]] assign the parameters to variables that are available within the procedure +* [[Macros]] replace the text of the special markers `$param$` with the values passed to the macro for those parameters (see [[Macro Parameter Handling]] for the details) + +The parameters are ignored for other kinds of variable. + +!!! Macro Variable Substitutions + +Before the text of a macro is used, the special markers `$(variable)$` are replaced with the values of the named variable. + +!!! Variable Attributes + +Variables can be used as the value of attributes of widgets or HTML elements: + +``` +<div class=<<varname>>> +``` + +Parameters can be passed: + +``` +<div class=<<varname "This is a parameter">>> +... +<div class=<<varname param:"This is a parameter">>> +... +<div class=<<varname param:"This is a parameter" second:"Another parameter">>> +... +``` + +The handling of these parameters depends on the kind of variable: + +* [[Functions]] assign the parameters to variables that are available within the function +* [[Macros]] replace the text of the special markers `$param$` with the values passed to the macro for those parameters (see [[Macro Parameter Handling]] for the details) + +The parameters are ignored for other kinds of variable. + +!!! Variables in Filters + +Variables can be accessed within [[Filters]] using angle brackets to quote the name: + +``` +[<varname>] +``` + +Parameters can be passed in the usual way: + +``` +[<varname "This is a parameter">] +[<varname param:"This is a parameter">] +[<varname param:"This is a parameter" second:"Another parameter">] +... +``` + +!! See Also + +* The <<.mlink dumpvariables>> macro lists all variables that are available at that position in the widget tree +* Complete listing of ~TiddlyWiki's built-in [[Core Variables]] + +!! Examples + +!!! Example of Defining a Variable + +<$macrocall $name=".example" n="1" +eg="""<$set name=animal value=zebra> +<<animal>> +</$set>"""/> + +!!! Example of Defining a Macro + +The `\define` pragma below [[defines a macro|Macro Definitions]] called <<.var tags-of-current-tiddler>>. The macro returns the value of the tiddler's <<.field tags>> field, and can be accessed from anywhere else in the same tiddler (or in any tiddler that [[imports|ImportVariablesWidget]] it). + +<$importvariables filter="$:/editions/tw5.com/macro-examples/tags-of-current-tiddler"> +<$codeblock code={{$:/editions/tw5.com/macro-examples/tags-of-current-tiddler}}/> +<$macrocall $name=".example" n="2" eg="""The tags are: <<tags-of-current-tiddler>>"""/> +</$importvariables> + +!!! Example of Using a Variable as a Filter Parameter + +This example uses the <<.olink backlinks>> [[operator|Filter Operators]] to list all tiddlers that link to this one. + +<$macrocall $name=".example" n="3" eg="""<<list-links filter:"[<currentTiddler>backlinks[]]">>"""/> -~TiddlyWiki's core has [[several variables|Core Variables]] built in. diff --git a/editions/tw5.com/tiddlers/webserver/Using the external JavaScript template.tid b/editions/tw5.com/tiddlers/webserver/Using the external JavaScript template.tid index 1aa61e86a..75b5f1484 100644 --- a/editions/tw5.com/tiddlers/webserver/Using the external JavaScript template.tid +++ b/editions/tw5.com/tiddlers/webserver/Using the external JavaScript template.tid @@ -1,9 +1,13 @@ created: 20180905075846391 -modified: 20221207112242775 +modified: 20230319130830880 tags: [[WebServer Guides]] title: Using the external JavaScript template type: text/vnd.tiddlywiki +<!-- +This tiddler is also included in the "server-external-js" edition. Take care before editing or moving it. +--> + You can use a special template to externalise ~TiddlyWiki's core code into a separate file. This configuration allows the browser to cache the core for improved efficiency. ! Background @@ -60,7 +64,7 @@ The "server-external-js" edition lets you save the snapshot from the command lin tiddlywiki YOUR_WIKI_FOLDER --build index ``` -The files `index.html` and `tiddlywikicore-5.x.x.js` will be saved in your wiki folder's `output` directory. +The files `external-5-x-x.html` and `tiddlywikicore-5.x.x.js` will be saved in your wiki folder's `output` directory. !! Obtaining the ~TiddlyWiki core in the browser diff --git a/editions/tw5.com/tiddlers/widgets/ActionListopsWidget.tid b/editions/tw5.com/tiddlers/widgets/ActionListopsWidget.tid index 4773e8405..2aadfe677 100644 --- a/editions/tw5.com/tiddlers/widgets/ActionListopsWidget.tid +++ b/editions/tw5.com/tiddlers/widgets/ActionListopsWidget.tid @@ -1,25 +1,11 @@ caption: action-listops created: 20141025120850184 -list: efg hlm pqr -modified: 20211115091121133 +modified: 20230301183438774 myfield: -revision: 0 tags: ActionWidgets Widgets title: ActionListopsWidget type: text/vnd.tiddlywiki -\define .operator-rows(filter) -<$list filter="$filter$"><tr> -<td><$link>{{!!caption}}</$link></td> -<td>{{!!op-purpose}} <$list filter="[all[current]tag[Common Operators]]">{{$:/core/images/done-button}}</$list></td> -<td align="center"><$list filter="[all[current]tag[Negatable Operators]]">`!`</$list></td> -</tr></$list> -\end - -\define .group-heading(_) -<tr class="doc-table-subheading"><th colspan="3" align="center">$_$</th></tr> -\end - ! Introduction The ''action-listops'' widget is an [[action widget|ActionWidgets]] that manipulates user lists in any field or data index. ActionWidgets are used within triggering widgets such as the ButtonWidget. @@ -34,9 +20,9 @@ The ''action-listops'' widget is invisible. Any content within it is ignored. |$index |Optional index of a property in a [[data tiddler|DataTiddlers]] index to be manipulated as a list | |$filter |An optional filter expression, the output of which will be saved to the field/index being manipulated | |$subfilter |An optional subfilter expression, which takes the list being manipulated as input, and saves the modified list back to the field/index being manipulated | -|$tags |An optional subfilter expression, which takes the 'tags' field of the target tiddler as input, and saves the modified list of tags back to the 'tags' field | +|$tags |An optional subfilter expression, which takes the <<.field tags>> field of the target tiddler as input, and saves the modified list of tags back to the <<.field tags>> field | -! $filter vs. $subfilter +!! Using $filter or $subfilter Standalone use of the `$subfilter` attribute can be replaced by using a (more complicated) `$filter` attribute value. @@ -46,15 +32,15 @@ For example, the items "abc" and "123" can be appended to the field `myfield` us <$action-listops $field="myfield" $subfilter="abc 123"/> ``` -The same can be achieved using the `$filter` attribute and prepending the [[Filter Run]] `[all[current]get[myfield]enlist-input[]]` to the [[Filter Expression]]: +The same can be achieved using the `$filter` attribute and prepending the [[Filter Run]] `[enlist{!!myfield}]` to the [[Filter Expression]]: ``` -<$action-listops $field="myfield" $filter="[all[current]get[myfield]enlist-input[]] abc 123"/> +<$action-listops $field="myfield" $filter="[enlist{!!myfield}] abc 123"/> ``` The short form is more convenient, but the long form is useful for live-debugging complicated `$subfilter` values using the filter tab of [[$:/AdvancedSearch]]. By using [[$:/AdvancedSearch]], the [[Filter Expression]] can be tested before using ''action-listops'' to modify actual tiddler fields. For this use case, the `all[current]` portion of the expression needs to be changed to select the proper test tiddler. -! $tags vs. $field + $subfilter +!! Using $tags or $subfilter [[Tagging]] is implemented using a tiddler's 'tags' field, so appending the tags "abc" and "123" using the `$tags` attribute like this: @@ -68,110 +54,53 @@ is mostly equivalent to using `$subfilter` along with "tags" for the value of `$ <$action-listops $field="tags" $subfilter="abc 123"/> ``` -! $action-listops widget vs. $action-setfield widget +!! Comparison to [[ActionSetFieldWidget]] -The ActionSetFieldWidget replaces a field's value using `$field`/`$value` attributes. A single ActionSetFieldWidget can be used to set any number of fields by using attributes not starting with $. +In general, ActionSetFieldWidget is better for setting multiple fields at once and for replacing the value of a field, which can also be a list. The ActionListopsWidget is better for modifying a list field based on the existing list and for using a [[Filter Expression]] to derive the value of the field. -The ActionListopsWidget replaces or modifies a single field's value. The new value is generated using filters. +The ~ActionSetFieldWidget sets the value of a field using `$field` and `$value` attribute pairs or attributes that do not start with a `$`. A single ~ActionSetFieldWidget can be used to set any number of fields of a single tiddler. -The following two examples are functionally equivalent: +The ~ActionListopsWidget replaces or modifies a single field's value using filter expressions. + +The following widgets are functionally equivalent: ``` <$action-setfield $field="myfield" $value="abc 123"/> -``` - -``` +<$action-setfield myfield="abc 123"/> <$action-listops $field="myfield" $filter="abc 123"/> ``` +Note that <<.value "abc 123">> in the first two cases is a literal string that is assigned to the field <<.field myfield>>, but in the third case a filter expression which evaluates to the same string. -In general, ActionSetFieldWidget is better for setting multiple fields at once and for replacing a field's value. The ActionListopsWidget is better for modifying a field based on the field's existing value and for using a [[Filter Expression]] to derive the value. +!! Extended Filter Operators -! Extended Filter Operators +A number of [[Extended Listops Filters]] are necessary for the manipulation of lists. These operators have been designed primarily for use in subfilter expressions whereby the modified current list is returned in place of the current list. -A number of [[extended filter operators|The Extended Listops Filters]] are necessary for the manipulation of lists. These operators have been designed primarily for use in subfilter expressions whereby the modified current list is returned in place of the current list. +!! Notes on de-duplication -<table> -<<.group-heading "Listops Operators">> -<tr> -<th align="left">Operator</th> -<th align="left">Purpose</th> -<th></th> -</tr> -<<.operator-rows "[tag[Filter Operators]tag[Listops Operators]tag[Order Operators]!tag[String Operators]!tag[Tag Operators]!tag[Special Operators]sort[]]">> -</table> +In some cases, there may occur unexpected de-duplication of lists. -! Examples +!!! Assignments to the <<.field list>> field -In this example we shall populate and then clear a list in an ordinary field (myfield) of this tiddler (the default.) +When assigning filter results to the <<.field list>> field (default), the generated list is automatically de-duplicated, so + +``` +<$action-listops $filter="[[1]] :and[[1]]"/> +``` +will result in the <<.field list>> field of the current tiddler containing the string <<.value 1>>, but not <<.value "1 1">>. + +!!! Input to the subfilter expression + +The input to the subfilter expression in the `$subfilter` attribute is also de-duplicated. If you rely on lists containing duplicates, consider using this alternative using the `$filter` attribute: <$macrocall $name='wikitext-example-without-html' src="""<$button> -<$action-listops $field="myfield" $subfilter="efg hlm pqr"/> -Populate 'myfield' -</$button> -<$button> -<$action-listops $field="myfield" $subfilter="abc xyz"/> -Append More Items -</$button> -<$button> -<$action-listops $field="myfield" $subfilter="-abc -hlm"/> -Remove Items -</$button> -<$button> -<$action-listops $field="myfield" $filter="[[]]"/> -Clear 'myfield' +<$action-listops $field="myfield" $filter="[enlist:raw{!!myfield}] :all[[abc]]" /> +Add 'abc' to 'myfield' </$button> -<$list filter="[list[!!myfield]]"> +<$list filter="[enlist:raw{!!myfield}]" template="$:/core/ui/ListItemTemplate" /> +"""/> +The [[enlist Operator]] with `raw` suffix will enlist the list saved in <<.field myfield>> of the current tiddler without de-duplication, while e.g. the [[list Operator]] will always de-duplicate. The widget then adds the item <<.value abc>> -- whether or not it is already included in the list -- and replaces the original list in <<.field myfield>>. -</$list>"""/> ---- -In this example we shall append and remove items from a list in an ordinary field (myfield) of this tiddler (the default) and sort the resultant list. We shall then remove some of the appended items and sort the resulting list in reverse order. - -<$macrocall $name='wikitext-example-without-html' -src="""<$button> -<$action-listops $field="myfield" $subfilter="-efg ijk xyz [[this is a title]] +[sort[]]"/> -Mangle List -</$button> -<$button> -<$action-listops $field="myfield" $subfilter="-xyz -[[this is a title]] +[!sort[]]"/> -Unmangle List -</$button> - -<$list filter="[list[!!myfield]]"> - -</$list>"""/> - ---- -In this example we shall append a few tags to the 'tags' field of this tiddler (the default.) We shall then remove some of the appended tags. - -<$macrocall $name='wikitext-example-without-html' -src="""<$button> -<$action-listops $tags="+[append{Days of the Week!!short}] $:/tag1 $:/tag2 $:/tag3"/> -Populate 'tags' -</$button> -<$button> -<$action-listops $tags="+[!remove:2{!!tags}]"/> -Remove Last Two Tags -</$button> -<$button> -<$action-listops $tags="+[!prefix[$:/]]"/> -Remove System Tags -</$button> -<$button> -<$action-listops $tags="-Mon -Tue"/> -Remove Mon and Tue -</$button> -<$button> -<$action-listops $tags="+[prefix[$:/]] ActionWidgets Widgets"/> -Remove User Tags -</$button> -<$button> -<$action-listops $tags="+[[]] ActionWidgets Widgets"/> -Clear Tags -</$button> - -<$list filter="[list[!!tags]]"> - -</$list>"""/> +! [[Examples|ActionListopsWidget (Examples)]] diff --git a/editions/tw5.com/tiddlers/widgets/BrowseWidget.tid b/editions/tw5.com/tiddlers/widgets/BrowseWidget.tid index 83953c26b..28012bd68 100644 --- a/editions/tw5.com/tiddlers/widgets/BrowseWidget.tid +++ b/editions/tw5.com/tiddlers/widgets/BrowseWidget.tid @@ -11,7 +11,7 @@ The browse widget displays an HTML file browser button that allows the user to c ! Content and Attributes -The content of the `<$browse>` widget is ignored. +The content of the <<.wid BrowseWidget>> widget is ignored. |!Attribute |!Description | |multiple |Set to "multiple" to select multiple file upload | @@ -26,10 +26,10 @@ On iPhone/iPad choosing the multiple option will remove the ability to take phot ''e.g.'' ``` -<$browse> +<$browse/> ``` renders as: -<$browse> +<$browse/> diff --git a/editions/tw5.com/tiddlers/widgets/CheckboxWidget (field Mode).tid b/editions/tw5.com/tiddlers/widgets/CheckboxWidget (field Mode).tid new file mode 100644 index 000000000..a0bb2d322 --- /dev/null +++ b/editions/tw5.com/tiddlers/widgets/CheckboxWidget (field Mode).tid @@ -0,0 +1,16 @@ +caption: <<.attr field>> +created: 20230314171223911 +description: tab +modified: 20230317161110431 +tags: CheckboxWidget +title: CheckboxWidget (field Mode) + +!!<<.link "<<.attr field>> Mode" "CheckboxWidget (field Mode)">> + +Using the checkbox widget in field mode requires the <<.attr field>> attribute to specify the name of the field. The <<.attr checked>> and <<.attr unchecked>> attributes specify the values to be assigned to the field to correspond to its checked and unchecked states respectively. The <<.attr default>> attribute is used as a fallback value if the field is missing or contains a value that does not correspond to the value of the <<.attr checked>> or <<.attr unchecked>> attributes. + +This example creates a checkbox that is checked if the field <<.field status>> is equal to <<.value open>> and unchecked if the field is equal to <<.value closed>>. If the field value is undefined then it defaults to <<.value closed>>. + +<<wikitext-example-without-html """<$checkbox field="status" checked="open" unchecked="closed" default="closed"> Is it open?</$checkbox> + +''status:'' {{!!status}}""">> \ No newline at end of file diff --git a/editions/tw5.com/tiddlers/widgets/CheckboxWidget (filter Mode).tid b/editions/tw5.com/tiddlers/widgets/CheckboxWidget (filter Mode).tid new file mode 100644 index 000000000..6ccf95414 --- /dev/null +++ b/editions/tw5.com/tiddlers/widgets/CheckboxWidget (filter Mode).tid @@ -0,0 +1,23 @@ +caption: <<.attr filter>> +created: 20230314174505003 +description: tab +modified: 20230325101447667 +tags: CheckboxWidget +title: CheckboxWidget (filter Mode) + +!!<<.link "<<.attr filter>> Mode" "CheckboxWidget (filter Mode)">> + +Using the checkbox widget in filter mode requires the <<.attr filter>> attribute to contain a filter whose output will determine the checked state of the checkbox. In filter mode, checking the checkbox will not automatically make changes to any field of any tiddler. Instead, you can use the <<.attr actions>> attribute (or the <<.attr checkactions>> and <<.attr uncheckactions>> attributes) to specify what should happen when the checkbox is toggled. It is your responsibility to make sure the actions cause changes to the tiddlers or fields that the filter results depend on, so that the checkbox becomes properly checked or unchecked after the actions have triggered and the filter has updated. + +If the filter returns an empty result, the checkbox will be unchecked. Otherwise, if the filter result is non-empty, the checkbox will be checked. + +However, if either the <<.attr checked>> or <<.attr unchecked>> attributes (or both) are specified, then their values will be looked for in the filter result, instead of considering any non-empty value to mean <<.value checked>>. + +This example creates the same checkbox as in the <<.doc-tab-link "listField mode example" "CheckboxWidget (listField Mode)">>, selecting between <<.value red>> and <<.value green>> in the <<.field colors>> list field, but using filters and actions to make the change. + +<<wikitext-example-without-html """\define checkActions() <$action-listops $field="colors" $subfilter="-red green"/> +\define uncheckActions() <$action-listops $field="colors" $subfilter="red -green"/> +<$checkbox filter="[list[!!colors]]" checked="green" unchecked="red" default="red" checkactions=<<checkActions>> uncheckactions=<<uncheckActions>> > Is "green" in colors?</$checkbox> + +''colors:'' {{!!colors}} +""">> \ No newline at end of file diff --git a/editions/tw5.com/tiddlers/widgets/CheckboxWidget (indeterminate).tid b/editions/tw5.com/tiddlers/widgets/CheckboxWidget (indeterminate).tid new file mode 100644 index 000000000..cb4883900 --- /dev/null +++ b/editions/tw5.com/tiddlers/widgets/CheckboxWidget (indeterminate).tid @@ -0,0 +1,31 @@ +caption: <<.attr indeterminate>> +created: 20230315173145042 +description: tab +modified: 20230317160908743 +tags: CheckboxWidget +title: CheckboxWidget (indeterminate) + +!!<<.link "<<.attr indeterminate>> Checkboxes" "CheckboxWidget (indeterminate)">> + +If both the <<.attr checked>> and <<.attr unchecked>> attributes are specified, but neither one is found in the specified field (or index), the result can be ambiguous. Should the checkbox be checked or unchecked? Normally in such cases the checkbox will be unchecked, but if the <<.attr indeterminate>> attribute is set to <<.value yes>> (default is <<.value no>>), the checkbox will instead be in an "indeterminate" state. An indeterminate checkbox counts as false for most purposes — if you click it, the checkbox will become checked and the <<.attr checkactions>>, if any, will be triggered — but indeterminate checkboxes are displayed differently in the browser. + +This example shows indeterminate checkboxes being used for categories in a shopping list (which could also be sub-tasks in a todo list, or many other things). If only some items in a category are selected, the category checkbox is indeterminate. You can click on the category checkboxes to see how indeterminate states are treated the same as the unchecked state, and clicking the box checks it and applies its check actions (in this case, checking all the boxes in that category). Try editing the <<.field fruits>> and <<.field vegetables>> fields on this tiddler and see what happens to the example when you do. + +<<wikitext-example-without-html """\define check-all(field-name:"items") <$action-listops $field="selected-$field-name$" $filter="[list[!!$field-name$]]" /> +\define uncheck-all(field-name:"items") <$action-listops $field="selected-$field-name$" $filter="[[]]" /> + +<$checkbox filter="[list[!!selected-fruits]count[]]" checked={{{ [list[!!fruits]count[]] }}} unchecked="0" checkactions=<<check-all fruits>> uncheckactions=<<uncheck-all fruits>> indeterminate="yes"> fruits</$checkbox> +<ul style="list-style: none"> +<$list variable="fruit" filter="[list[!!fruits]]"> +<li><$checkbox listField="selected-fruits" checked=<<fruit>>> <<fruit>></$checkbox></li> +</$list> +</ul> +<$checkbox filter="[list[!!selected-vegetables]count[]]" checked={{{ [list[!!vegetables]count[]] }}} unchecked="0" checkactions=<<check-all vegetables>> uncheckactions=<<uncheck-all vegetables>> indeterminate="yes"> veggies</$checkbox> +<ul style="list-style: none"> +<$list variable="veggie" filter="[list[!!vegetables]]"> +<li><$checkbox listField="selected-vegetables" checked=<<veggie>>> <<veggie>></$checkbox></li> +</$list> +</ul> + +<p>Selected veggies: {{!!selected-vegetables}}<br/> +Selected fruits: {{!!selected-fruits}}</p>""">> diff --git a/editions/tw5.com/tiddlers/widgets/CheckboxWidget (index Mode).tid b/editions/tw5.com/tiddlers/widgets/CheckboxWidget (index Mode).tid new file mode 100644 index 000000000..865cff172 --- /dev/null +++ b/editions/tw5.com/tiddlers/widgets/CheckboxWidget (index Mode).tid @@ -0,0 +1,16 @@ +caption: <<.attr index>> +created: 20230314171351122 +description: tab +modified: 20230317160939333 +tags: CheckboxWidget +title: CheckboxWidget (index Mode) + +!!<<.link "<<.attr index>> Mode" "CheckboxWidget (index Mode)">> + +To use the checkbox widget in index mode set the <<.attr index>> attribute to a property of a [[DataTiddler|DataTiddlers]]. The <<.attr checked>> and <<.attr unchecked>> attributes specify the values to be assigned to the property and correspond to its checked and unchecked states respectively. The <<.attr default>> attribute is used as a fallback value if the property is undefined. + +<<.warning "Make sure to set <<.attr tiddler>> correctly, because non-[[DataTiddlers]] will be overwritten without warning">> + +The example below creates a checkbox that is checked if the property in the tiddler [[ExampleData]] by the name of the current tiddler is equal to <<.value selected>> and unchecked if the property is an empty string. If the property is undefined then it defaults to an empty string, meaning the checkbox will be unchecked if the property is missing. + +<$macrocall $name="wikitext-example-without-html" src="""<$checkbox tiddler="ExampleData" index=<<currentTiddler>> checked="selected" unchecked="" default=""> Selected?</$checkbox>"""/> \ No newline at end of file diff --git a/editions/tw5.com/tiddlers/widgets/CheckboxWidget (listField Mode).tid b/editions/tw5.com/tiddlers/widgets/CheckboxWidget (listField Mode).tid new file mode 100644 index 000000000..5d5e67401 --- /dev/null +++ b/editions/tw5.com/tiddlers/widgets/CheckboxWidget (listField Mode).tid @@ -0,0 +1,26 @@ +caption: <<.attr listField>> +created: 20230314171331190 +description: tab +modified: 20230317160948525 +tags: CheckboxWidget +title: CheckboxWidget (listField Mode) + +!!<<.link "<<.attr listField>> Mode" "CheckboxWidget (listField Mode)">> + +Using the checkbox widget in list mode requires the <<.attr listField>> attribute to specify the name of a field containing a list. The <<.attr checked>> attribute specifies the value that should be present or absent in the list when the checkbox is checked or unchecked respectively. If <<.attr checked>> is absent (or empty) but <<.attr unchecked>> is present, then the logic will be inverted: the checkbox will be checked when the <<.attr unchecked>> value is missing from the list, and unchecked when the <<.attr unchecked>> value is found in the list. If both <<.attr checked>> and <<.attr unchecked>> are present, the checkbox will work like a toggle, replacing the <<.attr checked>> value with the <<.attr unchecked>> value and vice-versa. Finally, if neither <<.attr checked>> nor <<.attr unchecked>> is specified, the checkbox will be checked if the field has anything in it, but unchecked if the field is missing or empty. (This is rarely useful. Most of the time you want to specify <<.attr checked>> or <<.attr unchecked>> or both.) + +The <<.attr default>> attribute is used as a fallback for the checkbox state if the field is not defined. + +The following table summarizes the possible combinations: + +| !defined attributes| !<$checkbox tag="void" disabled="yes"/> | !<$checkbox field="tag" checked="void" default="void" disabled="yes" /> | !<$checkbox listField="tag" checked="void" unchecked="invalid" indeterminate="yes" disabled="yes" /> | +| neither| field missing or list empty<br/>no <<.attr default>> defined | field has any value | -- | +| <<.attr checked>>=<<.value item1>>| <<.value item1>> removed from list | <<.value item1>> added to list | -- | +| <<.attr unchecked>>=<<.value item2>>| <<.value item2>> added to list | <<.value item2>> removed from list | -- | +| both| <<.value item1>> removed from list<br/><<.value item2>> added to list | <<.value item1>> added to list<br/><<.value item2>> removed from list | <<.value item1>> not in list<br/><<.value item2>> not in list<br/>no <<.attr default>> defined | + +This example creates a checkbox that is checked if the list field named <<.field colors>> contains <<.value green>> and unchecked if the field contains <<.value red>>. If the field is undefined, or if neither <<.value green>> nor <<.value red>> appears in the field, then it defaults to <<.value green>>, meaning that the checkbox will be checked. + +<<wikitext-example-without-html """<$checkbox listField="colors" checked="green" unchecked="red" default="green"> Is "green" in colors?</$checkbox><br />''colors:'' {{!!colors}}""">> + +Try editing the <<.field colors>> field of this tiddler to see how the example changes. diff --git a/editions/tw5.com/tiddlers/widgets/CheckboxWidget (listIndex Mode).tid b/editions/tw5.com/tiddlers/widgets/CheckboxWidget (listIndex Mode).tid new file mode 100644 index 000000000..109ef90be --- /dev/null +++ b/editions/tw5.com/tiddlers/widgets/CheckboxWidget (listIndex Mode).tid @@ -0,0 +1,32 @@ +caption: <<.attr listIndex>> +created: 20230314174442174 +description: tab +modified: 20230317160929003 +tags: CheckboxWidget +title: CheckboxWidget (listIndex Mode) + +!!<<.link "<<.attr listIndex>> Mode" "CheckboxWidget (listIndex Mode)">> + +Using the checkbox widget in index list mode requires the <<.attr listIndex>> attribute to specify the the property of a [[DataTiddler|DataTiddlers]]. This property contains a list. The <<.attr checked>> attribute specifies the value that should be present or absent in the list when the checkbox is checked or unchecked respectively. If <<.attr checked>> is absent (or empty) but <<.attr unchecked>> is present, then the logic will be inverted: the checkbox will be checked when the <<.attr unchecked>> value is missing from the list, and unchecked when the <<.attr unchecked>> value is found in the list. If both <<.attr checked>> and <<.attr unchecked>> are present, the checkbox will work like a toggle, replacing the <<.attr checked>> value with the <<.attr unchecked>> value and vice-versa. Finally, if neither <<.attr checked>> nor <<.attr unchecked>> is specified, the checkbox will be checked if the field has anything in it, but unchecked if the field is missing or empty. (This is rarely useful. Most of the time you want to specify <<.attr checked>> or <<.attr unchecked>> or both.) + +The <<.attr default>> attribute is used as a fallback for the checkbox state if the property is undefined. + +The following table summarizes the possible combinations: + +| !defined attributes| !<$checkbox tag="void" disabled="yes"/> | !<$checkbox field="tag" checked="void" default="void" disabled="yes" /> | !<$checkbox listField="tag" checked="void" unchecked="invalid" indeterminate="yes" disabled="yes" /> | +| neither| property missing or list empty<br/>no <<.attr default>> defined | property has any value | -- | +| <<.attr checked>>=<<.value item1>>| <<.value item1>> removed from list | <<.value item1>> added to list | -- | +| <<.attr unchecked>>=<<.value item2>>| <<.value item2>> added to list | <<.value item2>> removed from list | -- | +| both| <<.value item1>> removed from list<br/><<.value item2>> added to list | <<.value item1>> added to list<br/><<.value item2>> removed from list | <<.value item1>> not in list<br/><<.value item2>> not in list<br/>no <<.attr default>> defined | + +<<.warning "Make sure to set <<.attr tiddler>> correctly, because non-[[DataTiddlers]] will be overwritten without warning">> + +The example below creates three checkboxes that each control a different value in a property of the ExampleData tiddler. + +<$macrocall $name="wikitext-example-without-html" src="""<$set name=indexName filter="[<currentTiddler>addsuffix[ Colors]]" > +<$checkbox tiddler="ExampleData" listIndex=<<indexName>> checked="green" unchecked="red" default="red"> Green or red?</$checkbox><br/> +<$checkbox tiddler="ExampleData" listIndex=<<indexName>> checked="yellow" unchecked="blue" default="blue"> Yellow or blue?</$checkbox><br/> +<$checkbox tiddler="ExampleData" listIndex=<<indexName>> checked="orange" unchecked="purple" default="purple"> Orange or purple?</$checkbox><br/> +Colors list: <$text text={{{ [[ExampleData]getindex<indexName>] }}} /> +</$set> +"""/> \ No newline at end of file diff --git a/editions/tw5.com/tiddlers/widgets/CheckboxWidget (tag Mode).tid b/editions/tw5.com/tiddlers/widgets/CheckboxWidget (tag Mode).tid new file mode 100644 index 000000000..e2125ebd0 --- /dev/null +++ b/editions/tw5.com/tiddlers/widgets/CheckboxWidget (tag Mode).tid @@ -0,0 +1,18 @@ +caption: <<.attr tag>> +created: 20230314171205017 +description: tab +modified: 20230317161122617 +tags: CheckboxWidget +title: CheckboxWidget (tag Mode) + +!!<<.link "<<.attr tag>> Mode" "CheckboxWidget (tag Mode)">> + +Using the checkbox widget in tag mode requires the <<.attr tag>> attribute to specify the name of the tag. The checkbox will be checked if the tiddler specified in the <<.attr tiddler>> attribute has the specified tag and unchecked if it does not. + +This example creates a checkbox that flips the <<.tag done>> tag on the current tiddler: + +<<wikitext-example-without-html """<$checkbox tag="done"> Is it done?</$checkbox>""">> + +When the attribute <<.attr invertTag>> is set to <<.value yes>>, the checkbox will be checked if the tiddler does <<.em not>> have the specified tag and unchecked if it does. + +<<wikitext-example-without-html """<$checkbox tag="done" invertTag="yes"> Is it not done?</$checkbox>""">> \ No newline at end of file diff --git a/editions/tw5.com/tiddlers/widgets/CheckboxWidget.tid b/editions/tw5.com/tiddlers/widgets/CheckboxWidget.tid index 8f8d35f65..47e83e875 100644 --- a/editions/tw5.com/tiddlers/widgets/CheckboxWidget.tid +++ b/editions/tw5.com/tiddlers/widgets/CheckboxWidget.tid @@ -1,12 +1,13 @@ caption: checkbox -created: 20131024141900000 -modified: 20220402023600000 -tags: Widgets TriggeringWidgets colors: red orange yellow blue +created: 20131024141900000 fruits: bananas oranges grapes -vegetables: carrots potatoes +list: [[CheckboxWidget (tag Mode)]] [[CheckboxWidget (field Mode)]] [[CheckboxWidget (listField Mode)]] [[CheckboxWidget (index Mode)]] [[CheckboxWidget (listIndex Mode)]] [[CheckboxWidget (filter Mode)]] [[CheckboxWidget (indeterminate)]] +modified: 20230316192632667 +tags: Widgets TriggeringWidgets title: CheckboxWidget type: text/vnd.tiddlywiki +vegetables: carrots potatoes ! Introduction @@ -20,111 +21,22 @@ The checkbox widget displays an HTML `<input type="checkbox">` element that is d The content of the `<$checkbox>` widget is displayed within an HTML `<label>` element immediately after the checkbox itself. This means that clicking on the content will toggle the checkbox. |!Attribute |!Description | -|tiddler |Title of the tiddler to manipulate (defaults to the [[current tiddler|Current Tiddler]]) | -|tag |The name of the tag to which the checkbox is bound | -|invertTag |When set to ''yes'', flips the tag binding logic so that the absence of the tag causes the checkbox to be checked | -|field |The name of the field to which the checkbox is bound | -|listField |<<.from-version "5.2.3">> The name of the field that contains the list to which the checkbox is bound | -|index|<<.from-version "5.1.14">> The index of the //tiddler//, a [[DataTiddler|DataTiddlers]], to which the checkbox is bound<<.tip "be sure to set the //tiddler// correctly">>| -|listIndex |<<.from-version "5.2.3">> Like <<.attr index>>, but treats the value as a list the same way that <<.attr listField>> does | -|filter |<<.from-version "5.2.3">> A filter whose output determines the checked state of the checkbox | -|checked |The value of the field corresponding to the checkbox being checked | -|unchecked |The value of the field corresponding to the checkbox being unchecked | -|default |The default value to use if the field is not defined | -|indeterminate |Whether ambiguous values can produce indeterminate checkboxes (see below) | -|class |The class that will be assigned to the label element <$macrocall $name=".tip" _="""<<.from-version "5.2.3">> `tc-checkbox` is always applied by default, as well as `tc-checkbox-checked` when checked"""/> | -|actions |<<.from-version "5.1.14">> A string containing ActionWidgets to be triggered when the status of the checkbox changes (whether it is checked or unchecked) | -|uncheckactions |<<.from-version "5.1.16">> A string containing ActionWidgets to be triggered when the checkbox is unchecked | -|checkactions |<<.from-version "5.1.20">> A string containing ActionWidgets to be triggered when the checkbox is checked | -|disabled|<<.from-version "5.1.23">> Optional, disables the checkbox if set to "yes". Defaults to "no"| +|<<.attr tiddler>> |Title of the tiddler to manipulate (defaults to the [[Current Tiddler]]) | +|<<.widget-attr-link tag "CheckboxWidget (tag Mode)">> |The name of the [[tag|Tagging]] to which the checkbox is bound | +|<<.attr invertTag>> |When set to <<.value yes>>, flips the tag binding logic so that the absence of the tag causes the checkbox to be checked | +|<<.widget-attr-link field "CheckboxWidget (field Mode)">> |The name of the field to which the checkbox is bound | +|<<.widget-attr-link listField "CheckboxWidget (listField Mode)">> |<<.from-version "5.2.3">> The name of the field that contains the list to which the checkbox is bound | +|<<.widget-attr-link index "CheckboxWidget (index Mode)">> |<<.from-version "5.1.14">> The property of the [[DataTiddler|DataTiddlers]] to which the checkbox is bound| +|<<.widget-attr-link listIndex "CheckboxWidget (listIndex Mode)">> |<<.from-version "5.2.3">> Like <<.attr index>>, but treats the value as a list the same way that <<.attr listField>> does | +|<<.widget-attr-link filter "CheckboxWidget (filter Mode)">> |<<.from-version "5.2.3">> A filter whose output determines the checked state of the checkbox | +|<<.attr checked>> |The value of the field corresponding to the checkbox being checked | +|<<.attr unchecked>> |The value of the field corresponding to the checkbox being unchecked | +|<<.attr default>> |The default value to use if the field is not defined | +|<<.widget-attr-link indeterminate "CheckboxWidget (indeterminate)">> |Whether ambiguous values can produce indeterminate checkboxes (see below) | +|<<.attr class>> |The class that will be assigned to the `<label>` element <$macrocall $name=".tip" _="""<<.from-version "5.2.3">> `tc-checkbox` is always applied by default, as well as `tc-checkbox-checked` when checked"""/> | +|<<.attr actions>> |<<.from-version "5.1.14">> A string containing ActionWidgets to be triggered when the status of the checkbox changes (whether it is checked or unchecked) | +|<<.attr uncheckactions>> |<<.from-version "5.1.16">> A string containing ActionWidgets to be triggered when the checkbox is unchecked | +|<<.attr checkactions>> |<<.from-version "5.1.20">> A string containing ActionWidgets to be triggered when the checkbox is checked | +|<<.attr disabled>> |<<.from-version "5.1.23">> Optionally disables the checkbox if set to <<.value yes>> (defaults to <<.value no>>)| -!! Tag Mode - -Using the checkbox widget in tag mode requires the ''tag'' attribute to specify the name of the tag. The ''tiddler'' attribute specifies the tiddler to target, defaulting to the current tiddler if not present. - -This example creates a checkbox that flips the ''done'' tag on the current tiddler: - -<<wikitext-example-without-html """<$checkbox tag="done"> Is it done?</$checkbox>""">> - -!! Field Mode - -Using the checkbox widget in field mode requires the ''field'' attribute to specify the name of the field. The ''checked'' and ''unchecked'' attributes specify the values to be assigned to the field to correspond to its checked and unchecked states respectively. The ''default'' attribute is used as a fallback value if the field is not defined. - -This example creates a checkbox that is checked if the field ''status'' is equal to ''open'' and unchecked if the field is equal to ''closed''. If the field is undefined then it defaults to ''closed'', meaning that the checkbox will be unchecked if the ''status'' field is missing. - -<<wikitext-example-without-html """<$checkbox field="status" checked="open" unchecked="closed" default="closed"> Is it open?</$checkbox><br />''status:'' {{!!status}}""">> - -!! List Mode - -Using the checkbox widget in list mode requires the ''listField'' attribute to specify the name of a field containing a list. The ''checked'' attribute specifies the value that should be present or absent in the list when the checkbox is checked or unchecked respectively. If ''checked'' is absent (or empty) but ''unchecked'' is present, then the logic will be inverted: the checkbox will be checked when the "unchecked" value is missing from the list, and unchecked when the "unchecked" value is found in the list. If both ''checked'' and ''unchecked'' are present, the checkbox will work like a toggle, replacing the ''checked'' value with the ''unchecked'' value and vice-versa. Finally, if neither ''checked'' nor ''unchecked'' is specified, the checkbox will be checked if the field has anything in it, but unchecked if the field is missing or empty. (This is rarely useful; most of the time you'll want to specify ''checked'' or ''unchecked'' or both.) - -The ''default'' attribute is used as a fallback for the checkbox state if the field is not defined. - -This example creates a checkbox that is checked if the list field named ''colors'' contains ''green'' and unchecked if the field contains ''red''. If the field is undefined, or if neither ''green'' nor ''red'' appears in the field, then it defaults to ''green'', meaning that the checkbox will be checked. - -<<wikitext-example-without-html """<$checkbox listField="colors" checked="green" unchecked="red" default="green"> Is it green?</$checkbox><br />''colors:'' {{!!colors}}""">> - -Try editing the ''colors'' field of this tiddler to see how the example changes. - -!! Index Mode - -To use the checkbox widget in index mode set the ''index'' attribute to the index of a [[DataTiddler|DataTiddlers]]. The ''checked'' and ''unchecked'' attributes specify the values to be assigned to the index and correspond to its checked and unchecked states respectively. The ''default'' attribute is used as a fallback value if the index is undefined. - -The example below creates a checkbox that is checked if the index by the name of this tiddler in the tiddler ExampleData is equal to ''selected'' and unchecked if the index is an empty string. If the index is undefined then it defaults to an empty string, meaning the checkbox will be unchecked if the index is missing. - -<$macrocall $name="wikitext-example-without-html" src="""<$checkbox tiddler="ExampleData" index=<<currentTiddler>> checked="selected" unchecked="" default=""> Selected?</$checkbox>"""/> - -!! Index List Mode - -Using the checkbox widget in index list mode requires the ''listIndex'' attribute to specify the the index of a [[DataTiddler|DataTiddlers]] containing a list. The ''checked'' attribute specifies the value that should be present or absent in the list when the checkbox is checked or unchecked respectively. If ''checked'' is absent (or empty) but ''unchecked'' is present, then the logic will be inverted: the checkbox will be checked when the "unchecked" value is missing from the list, and unchecked when the "unchecked" value is found in the list. If both ''checked'' and ''unchecked'' are present, the checkbox will work like a toggle, replacing the ''checked'' value with the ''unchecked'' value and vice-versa. Finally, if neither ''checked'' nor ''unchecked'' is specified, the checkbox will be checked if the field has anything in it, but unchecked if the field is missing or empty. (This is rarely useful; most of the time you'll want to specify ''checked'' or ''unchecked'' or both.) - -The ''default'' attribute is used as a fallback for the checkbox state if the index is undefined. - -The example below creates three checkboxes that each control a different value in an index field of the ExampleData tiddler. - -<$macrocall $name="wikitext-example-without-html" src=""" -<$set name=indexName filter="[<currentTiddler>addsuffix[ Colors]]" > -<$checkbox tiddler="ExampleData" listIndex=<<indexName>> checked="green" unchecked="red" default="red"> Green or red?</$checkbox> <br/> -<$checkbox tiddler="ExampleData" listIndex=<<indexName>> checked="yellow" unchecked="blue" default="blue"> Yellow or blue?</$checkbox> <br/> -<$checkbox tiddler="ExampleData" listIndex=<<indexName>> checked="orange" unchecked="purple" default="purple"> Orange or purple?</$checkbox> <br /> -Colors list: {{{ [[ExampleData]getindex<indexName>] }}} -</$set> -"""/> - -!! Filter Mode - -Using the checkbox widget in filter mode requires the ''filter'' attribute to contain a filter whose output will determine the checked state of the checkbox. In filter mode, checking the checkbox will not automatically make changes to any field of any tiddler. Instead, you can use the ''actions'' attribute (or ''checkactions'' and ''uncheckactions'') to specify what should happen when the checkbox is toggled. It is your responsibility to make sure the actions cause changes to the tiddlers or fields that the filter results depend on, so that the checkbox becomes properly checked or unchecked after the actions have triggered. - -If the filter returns an empty result, the checkbox will be unchecked. Otherwise, if the filter result is non-empty, the checkbox will be checked. However, if either the ''checked'' or ''unchecked'' attributes (or both) are specified, then their values will be looked for in the filter result, instead of considering any non-empty value to mean "checked". - -This example creates the same checkbox as in the list mode example, selecting between ''red'' and ''green'' in the ''colors'' list field, but using filters and actions to make the change. - -<<wikitext-example-without-html """\define checkActions() <$action-listops $field="colors" $subfilter="-red green"/> -\define uncheckActions() <$action-listops $field="colors" $subfilter="red -green"/> -<$checkbox filter="[list[!!colors]]" checked="green" unchecked="red" default="red" checkactions=<<checkActions>> uncheckactions=<<uncheckActions>> > Is "green" in colors?</$checkbox><br />''colors:'' {{!!colors}} -""">> - -!! Indeterminate checkboxes - -If both the ''checked'' and ''unchecked'' attributes are specified, but neither one is found in the specified field (or index), the result can be ambiguous. Should the checkbox be checked or unchecked? Normally in such cases the checkbox will be unchecked, but if the ''indeterminate'' attribute is set to "yes" (default is "no"), the checkbox will instead be in an "indeterminate" state. An indeterminate checkbox counts as false for most purposes — if you click it, the checkbox will become checked and the ''checkactions'', if any, will be triggered — but indeterminate checkboxes are displayed differently in the browser. - -This example shows indeterminate checkboxes being used for categories in a shopping list (which could also be sub-tasks in a todo list, or many other things). If only some items in a category are selected, the category checkbox is indeterminate. You can click on the category checkboxes to see how indeterminate states are treated the same as the unchecked state, and clicking the box checks it and applies its check actions (in this case, checking all the boxes in that category). Try editing the <<.field fruits>> and <<.field vegetables>> fields on this tiddler and see what happens to the example when you do. - -<<wikitext-example-without-html """\define check-all(field-name:"items") <$action-listops $field="selected-$field-name$" $filter="[list[!!$field-name$]]" /> -\define uncheck-all(field-name:"items") <$action-listops $field="selected-$field-name$" $filter="[[]]" /> - -<$checkbox filter="[list[!!selected-fruits]count[]]" checked={{{ [list[!!fruits]count[]] }}} unchecked="0" checkactions=<<check-all fruits>> uncheckactions=<<uncheck-all fruits>> indeterminate="yes"> fruits</$checkbox> -<ul style="list-style: none"> -<$list variable="fruit" filter="[list[!!fruits]]"> -<li><$checkbox listField="selected-fruits" checked=<<fruit>>> <<fruit>></$checkbox></li> -</$list> -</ul> -<$checkbox filter="[list[!!selected-vegetables]count[]]" checked={{{ [list[!!vegetables]count[]] }}} unchecked="0" checkactions=<<check-all vegetables>> uncheckactions=<<uncheck-all vegetables>> indeterminate="yes"> veggies</$checkbox> -<ul style="list-style: none"> -<$list variable="veggie" filter="[list[!!vegetables]]"> -<li><$checkbox listField="selected-vegetables" checked=<<veggie>>> <<veggie>></$checkbox></li> -</$list> -</ul> - -<p>Selected veggies: {{!!selected-vegetables}}<br/> -Selected fruits: {{!!selected-fruits}}</p>""">> +<<.doc-tabs>> diff --git a/editions/tw5.com/tiddlers/widgets/Custom Widgets.tid b/editions/tw5.com/tiddlers/widgets/Custom Widgets.tid new file mode 100644 index 000000000..c220302cf --- /dev/null +++ b/editions/tw5.com/tiddlers/widgets/Custom Widgets.tid @@ -0,0 +1,84 @@ +created: 20221007144237585 +modified: 20230419103154328 +tags: Concepts Reference +title: Custom Widgets +type: text/vnd.tiddlywiki + +!! Introduction + +<<.from-version "5.3.0">> A <<.def "custom widget">> is a special kind of [[procedure|Procedures]] that can be called using the same syntax as widgets. + +Custom widgets can also be used to override built-in JavaScript widgets to customise their behaviour. + +!! Defining Custom Widgets + +Custom widgets are usually defined with the [[Pragma: \widget]]: + +``` +\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` + +!! Using Custom Widgets + +Custom widgets are called in the same way as ordinary built-in widgets: + +``` +<$my-widget/> + +<$my-widget attribute="The parameter"/> +``` + +The attributes that are specified in the widget call are made available as parameter variables. + +!! Accessing Content of Custom Widgets + +Within the definition of a custom widget the content of the calling widget is available via the `<$slot $name="ts-raw"/>` widget. The contents of the <<.wlink SlotWidget>> widget is used as the default content if the widget was called without any content. + +For example: + +<<wikitext-example-without-html """\widget $$mywidget(one:'Jaguar') +<$text text=<<one>>/> +<$slot $name="ts-raw"> + Whale +</$slot> +\end + +<$$mywidget one="Dingo"> + Crocodile +</$$mywidget> + +<$$mywidget/>""">> + +!! How Custom Widgets Work + +Custom widgets are implemented as a special kind of [[variable|Variables]]. The only thing that distinguishes them from ordinary variables is the way that they can be called as a custom widget with attributes mapped to parameters. + +!! Overriding Core ~JavaScript Widgets + +Custom widgets can use the <<.wlink "GenesisWidget">> widget to invoke the original widget, bypassing the override. For example, here we override the <<.wlink CodeBlockWidget>> widget to add `≤≥` symbols around each string of text. + + +<<wikitext-example-without-html """\widget $codeblock(code) +<$genesis $type="$codeblock" $remappable="no" code={{{ [<code>addprefix[≤]addsuffix[≥]] }}}/> +\end + +<$codeblock code="Kangaroo"/> + +<$codeblock code={{$:/SiteTitle}}/> + +``` +Python +``` + +<$let test="Tiger"> +<$codeblock code=<<test>>/> +</$let>""">> diff --git a/editions/tw5.com/tiddlers/widgets/ErrorWidget.tid b/editions/tw5.com/tiddlers/widgets/ErrorWidget.tid index aee5617d2..d6afb86ed 100644 --- a/editions/tw5.com/tiddlers/widgets/ErrorWidget.tid +++ b/editions/tw5.com/tiddlers/widgets/ErrorWidget.tid @@ -1,6 +1,6 @@ caption: error created: 20220909111836951 -modified: 20220909111836951 +modified: 20230419103154328 tags: Widgets title: ErrorWidget type: text/vnd.tiddlywiki diff --git a/editions/tw5.com/tiddlers/widgets/Extended Listops Filters.tid b/editions/tw5.com/tiddlers/widgets/Extended Listops Filters.tid new file mode 100644 index 000000000..4d11b4590 --- /dev/null +++ b/editions/tw5.com/tiddlers/widgets/Extended Listops Filters.tid @@ -0,0 +1,138 @@ +created: 20151014170727812 +days: Fri Wed Mon Tue +dofwks: Mon Tue Wed Thu Fri Sat Sun +item1: six +item2: seven +item3: eight +list: Yesterday Today Tomorrow +marker: Thursday +modified: 20230227175501965 +myfield: Monday Tuesday [[Middle of the Week]] Thursday Friday Saturday Sunday +numbers: 1 2 3 4 five 6 7 8 9 +tags: Filters +title: Extended Listops Filters + +\define .operator-rows(filter) +<$list filter="$filter$"><tr> +<td><$link>{{!!caption}}</$link></td> +<td>{{!!op-purpose}}</td> +<td align="center"><$list filter="[all[current]tag[Common Operators]]">✓</$list></td> +<td align="center"><$list filter="[all[current]tag[Negatable Operators]]">`!`</$list></td> +</tr></$list> +\end + +\define .group-heading(_) +<tr class="doc-table-subheading"><th colspan="4" align="center">$_$</th></tr> +\end + +! Introduction + +A number of filters are used to manipulate lists. + +Some filters are designed to move items from the tail of the list and insert them at specified locations in the list, e.g. [[putafter|putafter Operator]] or [[putbefore|putbefore Operator]]. Items are often appended to the list before using these filters. In general, these filters accept a suffix specifying the number of items to move (default to 1.) + +Some filters are designed to either add or remove from the list, a selected range of items from an array, e.g. [[append|append Operator]] or [[remove|remove Operator]]. These filters are best used with a reference to an array, stored in a field or data index elsewhere in the wiki (they may be used with a simple list of items, provided the items do not include white space.) In general, these filters accept a suffix specifying the number of items to move (default to All.) + +<table> +<<.group-heading "Listops Operators">> +<tr> +<th align="left">Operator</th> +<th align="left">Purpose</th> +<th>✓</th> +<th>`!`</th> +</tr> +<<.operator-rows "[tag[Filter Operators]tag[Listops Operators]tag[Order Operators]!tag[String Operators]!tag[Tag Operators]!tag[Special Operators]sort[]]">> +</table> + +! Examples + +In this example we shall populate the '~DataIndex' index of the tiddler '~MyData' with the names of the days of the week, then clear this list. + +<$macrocall $name='wikitext-example-without-html' +src="""<$button> +<$action-listops $tiddler="ListopsData" $index="DataIndex" $filter="[list[Days of the Week]]"/> +Get days-of-the-week +</$button> +<$button> +<$action-listops $tiddler="ListopsData" $index="DataIndex" $filter="[[]]"/> +Clear +</$button> + +{{ListopsData}}"""/> + +--- +In this example we shall slice the populated list from the 'DaysOfTheWeek' index of the tiddler '~MyData' in order to insert items before and after a marker item (Wednesday) that are first appended to the list. + +<$macrocall $name='wikitext-example-without-html' +src="""<$button> +<$action-listops $tiddler="ListopsData" $index="DataIndex" $subfilter="one two +[putbefore:2[Wednesday]]"/> +Put 2 Items Before Wednesday +</$button> +<$button> +<$action-listops $tiddler="ListopsData" $index="DataIndex" $subfilter="four five +[putafter:2[Wednesday]] three +[putbefore[Wednesday]]"/> +Put One Item Before & Two Items After Wednesday +</$button> + +{{ListopsData}}"""/> + +--- +In this example we shall slice the populated list from the 'DaysOfTheWeek' index of the tiddler '~MyData' in order to replace the marker item (Wednesday) with items which are first appended to the list. We shall then move 3 items to the head of the list which have first been appended to the list from referenced fields. + +<$macrocall $name='wikitext-example-without-html' +src="""<$button> +<$action-listops $tiddler="ListopsData" $index="DataIndex" $subfilter="[[---o]] [[o---]] +[replace:2{!!marker}]"/> +Replace '!!marker' with 2 Items +</$button> +<$button> +<$action-listops $tiddler="ListopsData" $index="DataIndex" $subfilter="[{!!item1}] [{!!item2}] [{!!item3}] +[putfirst:3[]]"/> +Put 3 Items First +</$button> + +{{ListopsData}}"""/> + +--- +In this example we shall slice the populated list from the 'DaysOfTheWeek' index of the tiddler '~MyData' in order to append to the truncated list, items from a referenced field. We shall then remove the first two of the items added. + +<$macrocall $name='wikitext-example-without-html' +src="""|list: |<$view field="list"/> | + +<$button> +<$action-listops $tiddler="ListopsData" $index="DataIndex" $subfilter="+[allbefore:include[Wednesday]] +[prepend{!!list}]"/> +Prepend '!!list' to items before 'Wednesday' +</$button> +<$button> +<$action-listops $tiddler="ListopsData" $index="DataIndex" $subfilter="+[remove:2{!!list}]"/> +Remove first two items in '!!list' from current list +</$button> +<$button> +<$action-listops $tiddler="ListopsData" $index="DataIndex" $subfilter="+[!remove:1{!!list}]"/> +Remove last item in '!!list' from current list +</$button> + +{{ListopsData}}"""/> + +--- +In this example we shall populate the list with numbers, then move items one by one from the head to the tail and from the tail to the head (best seen by clicking the lower buttons several times.) + +This example illustrates that the append[] and prepend[] operators do not enforce unique instances of an item and that, with the next run, any duplicates are removed. + +<$macrocall $name='wikitext-example-without-html' +src="""<$button> +<$action-listops $tiddler="ListopsData" $index="DataIndex" $filter="[[]]" $subfilter="+[append:3{!!numbers}]"/> +Setup some numbers +</$button> +<$button> +<$action-listops $tiddler="ListopsData" $index="DataIndex" $subfilter="+[!append:6{!!numbers}]"/> +Append more numbers +</$button> + +<$button> +<$action-listops $tiddler="ListopsData" $index="DataIndex" $subfilter="+[putfirst:2[]]"/> +Move last 2 items to the head +</$button> +<$button> +<$action-listops $tiddler="ListopsData" $index="DataIndex" $subfilter="+[putlast[]]"/> +Move the head to the last item +</$button> + +{{ListopsData}}"""/> diff --git a/editions/tw5.com/tiddlers/widgets/FillWidget.tid b/editions/tw5.com/tiddlers/widgets/FillWidget.tid new file mode 100644 index 000000000..3fffd51f0 --- /dev/null +++ b/editions/tw5.com/tiddlers/widgets/FillWidget.tid @@ -0,0 +1,21 @@ +caption: fill +created: 20220909111836951 +modified: 20230419103154328 +tags: Widgets +title: FillWidget +type: text/vnd.tiddlywiki + +! Introduction + +<<.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. + +! Attributes + +The content of the <<.wlink FillWidget>> widget is used as the content to be passed to the transclusion. + +|!Attribute |!Description | +|$name |The name of the slot to be filled | + +<<.warning """The $name attribute must be specified as a literal string""">> diff --git a/editions/tw5.com/tiddlers/widgets/ImportVariablesWidget.tid b/editions/tw5.com/tiddlers/widgets/ImportVariablesWidget.tid index a9451bc63..93ae44ae4 100644 --- a/editions/tw5.com/tiddlers/widgets/ImportVariablesWidget.tid +++ b/editions/tw5.com/tiddlers/widgets/ImportVariablesWidget.tid @@ -34,7 +34,7 @@ So-called global macros are implemented within the main page template ([[$:/core ! `\import` Pragma -<<.from-version "5.1.18">> The `\import` [[pragma|Pragma]] is an alternative syntax for using the ImportVariablesWidget. For example, the previous example could be expressed as: +<<.from-version "5.1.18">> The [[Pragma: \import]] is an alternative syntax for using the ImportVariablesWidget. For example, the previous example could be expressed as: ``` \import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]] diff --git a/editions/tw5.com/tiddlers/widgets/MacroCallWidget.tid b/editions/tw5.com/tiddlers/widgets/MacroCallWidget.tid index e163c1d41..e06e3601d 100644 --- a/editions/tw5.com/tiddlers/widgets/MacroCallWidget.tid +++ b/editions/tw5.com/tiddlers/widgets/MacroCallWidget.tid @@ -1,48 +1,31 @@ caption: macrocall created: 20131024141900000 -modified: 20220122193731433 -tags: Widgets +modified: 20230419103154328 +tags: Widgets $:/deprecated title: MacroCallWidget type: text/vnd.tiddlywiki -! Introduction +<<.deprecated-since "5.3.0" "TranscludeWidget">> -The macro call widget provides a more flexible alternative syntax for invoking macros compared to the usual `<<macroname>>` syntax documented in [[Macros in WikiText]]. +The <<.wlink MacroCallWidget>> widget is deprecated. While it will continue to work, users are now advised to use the <<.wlink TranscludeWidget>> widget, converting the `$name` attribute to `$variable`. -For example, a macro called `italicise` that takes a single parameter called `text` would usually be invoked like this: +For example, ``` -<<italicise "Text to be made into italics">> -<<italicise text:"Text to be made into italics">> +<$macrocall $name="my-macro" my-parameter="Elephant"/> ``` -The same macro can be invoked using the macro call widget like this: +should be changed to: ``` -<$macrocall $name="italicise" text="Text to be made into italics"/> -<$macrocall $name="italicise" text={{Title of tiddler containing text to be italicised}}/> -<$macrocall $name="italicise" text=<<textMaker "Another macro to generate the text to be italicised">>/> +<$transclude $variable="my-macro" my-parameter="Elephant"/> ``` -The advantages of the widget formulation are: - -* Macro parameters are specified as widget attributes, thus allowing indirection via `{{title!!field}}`, `<<macroname>>` or `{{{filter}}}` -* The output format can be chosen from several options: -** `text/html` wikifies the result of the macro -** `text/plain` wikifies the result of the macro and then extracts the plain text characters (ie. ignoring HTML tags) -** <<.from-version "5.1.23">> `text/raw` returns the result of the macro, without wikification - -You can see several examples of the macro call widget within the core: - -* Listing module information: [[$:/snippets/modules]] -* Listing field information: [[$:/snippets/allfields]] -* Generating `data:` URIs: [[$:/themes/tiddlywiki/starlight/styles.tid]] - -See also [[WikiText parser mode: macro examples]] +Internally, the <<.wlink MacroCallWidget>> widget is implemented via the <<.wlink TranscludeWidget>> widget. ! Content and Attributes -The content of the `<$macrocall>` widget is ignored. +The content of the <<.wlink MacroCallWidget>> widget is ignored. |!Attribute |!Description | |$name |Name of the macro to invoke | diff --git a/editions/tw5.com/tiddlers/widgets/ParametersWidget.tid b/editions/tw5.com/tiddlers/widgets/ParametersWidget.tid new file mode 100644 index 000000000..8ddee3151 --- /dev/null +++ b/editions/tw5.com/tiddlers/widgets/ParametersWidget.tid @@ -0,0 +1,61 @@ +caption: parameters +created: 20220909111836951 +modified: 20230419103154328 +tags: Widgets +title: ParametersWidget +type: text/vnd.tiddlywiki + +<<.from-version "5.3.0">> The <<.wlink ParametersWidget>> widget is used within transcluded content to declare the parameters to be made available to the <<.wlink TranscludeWidget>> widget. + +There are shortcuts for common scenarios that can often make it unnecessary to use the <<.wlink ParametersWidget>> widget directly: + +* the [[Pragma: \parameters]] +* the [[Pragma: \procedure]] for declaring procedure +* the [[Pragma: \widget]] for declaring custom widgets + +The <<.wlink ParametersWidget>> widget must be used directly in the following situations: + +* When the default value of a parameter must be computed dynamically +* When the `$depth` attribute is used to retrieve parameters from a parent transclusion (see below) + +! Content and Attributes + +The content of the <<.wlink ParametersWidget>> widget is the scope within which the values of the parameters can be accessed as ordinary variables. + +|!Attribute |!Description | +|$depth |The index of the parent transclusion from which to obtain the parameters (defaults to 1). See below | +|$parseMode |Optional name of a variable in which is made available the parse mode of the content of the parent transclusion (the parse mode can be "inline" or "block") | +|$parseTreeNodes |Optional name of a variable in which is made available the JSON representation of the parse tree nodes contained within the parent transclusion | +|$slotFillParseTreeNodes |Optional name of a variable in which is made available the JSON representation of the parse tree nodes corresponding to each fill widget contained within the parent transclusion (as an object where the keys are the slot names and the values are the parse tree nodes) | +|$params |Optional name of a variable in which is made available the JSON representation of the parameters passed to the parent transclusion (as an object where the keys are the parameter names and the values are the coresponding values) | +|//{attributes not starting with $}// |Any attributes that do not start with a dollar are used as parameters, with the value specifying the default to be used for missing parameters | +|//{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. The value specifies the default to be used for missing parameters | + +<<.note "Note the special treatment required for parameters names that start with a `$`; this can be avoided by using one of the pragmas">> + +!! `$depth` Attribute + +By default, the <<.wlink ParametersWidget>> widget retrieves parameters from the immediate parent transclusion. The `$depth` attribute permits access to the parameters of parent transclusions by specifying an index to the parent to be inspected ("1" is the immediate parent, "2" is the parent of that parent, etc.). This is useful in some situations where an intervening transclusion prevents immediate access to desired parameters. + +!! `$parseMode`, `$parseTreeNodes`, `$slotFillParseTreeNodes` and `$params` Attributes + +These attributes provide low level access to the contents of the transcluding widget: + +* The `$params` attribute provides access to the raw parameters provided to the transcluding widget. Represented in JSON as an object with keys of the parameter names and values of the corresponding parameter values +* The `$parseMode` attribute contains `block` or `inline` to indicate whether the contents was parsed in block or inline mode +* The `$parseTreeNodes` attribute provides access to the raw parse tree nodes that represent the contents of the transcluding widget. Represented in JSON as an array of parse tree nodes +* 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 + +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"/>"""/> diff --git a/editions/tw5.com/tiddlers/widgets/SlotWidget.tid b/editions/tw5.com/tiddlers/widgets/SlotWidget.tid new file mode 100644 index 000000000..f7b26e62d --- /dev/null +++ b/editions/tw5.com/tiddlers/widgets/SlotWidget.tid @@ -0,0 +1,19 @@ +caption: slot +created: 20220909111836951 +modified: 20230419103154329 +tags: Widgets +title: SlotWidget +type: text/vnd.tiddlywiki + +! Introduction + +<<.from-version "5.3.0">> The <<.wlink SlotWidget>> widget is used within transcluded content to mark "slots" that the transcluding widget can fill with the <<.wlink FillWidget>> widget. + +See the <<.wlink TranscludeWidget>> widget for details. + +! Attributes + +The content of the <<.wlink SlotWidget>> widget is used as a fallback for the slot content if the corresponding <<.wlink FillWidget>> widget is not found. + +|!Attribute |!Description | +|$name |The name of the slot being defined | diff --git a/editions/tw5.com/tiddlers/widgets/The Extended Listops Filters.tid b/editions/tw5.com/tiddlers/widgets/The Extended Listops Filters.tid index 7e51f4c8c..86b821deb 100644 --- a/editions/tw5.com/tiddlers/widgets/The Extended Listops Filters.tid +++ b/editions/tw5.com/tiddlers/widgets/The Extended Listops Filters.tid @@ -1,114 +1,5 @@ -created: 20151014170727812 -days: Fri Wed Mon Tue -dofwks: Mon Tue Wed Thu Fri Sat Sun -item1: six -item2: seven -item3: eight -list: Yesterday Today Tomorrow -marker: Thursday -modified: 20211114011103356 -myfield: Monday Tuesday [[Middle of the Week]] Thursday Friday Saturday Sunday -numbers: 1 2 3 4 five 6 7 8 9 -tags: Filters +created: 20230301172832597 +modified: 20230301172832597 title: The Extended Listops Filters -! Introduction - -A number of extended filters are necessary to manipulate lists. - -The first set of filters are designed to move items from the tail of the list and insert them at specified locations in the list. Items are often appended to the list before using these filters. In general, these filters accept a suffix specifying the number of items to move (default to 1.) - -A second set of filters are designed to either add or remove from the list, a selected range of items from an array. These filters are best used with a reference to an array, stored in a field or data index elsewhere in the wiki (they may be used with a simple list of items, provided the items do not include white space.) In general, these filters accept a suffix specifying the number of items to move (default to All.) - -! Examples - -In this example we shall populate the '~DataIndex' index of the tiddler '~MyData' with the names of the days of the week, then clear this list. - -<$macrocall $name='wikitext-example-without-html' -src="""<$button> -<$action-listops $tiddler="ListopsData" $index="DataIndex" $filter="[list[Days of the Week]]"/> -Get days-of-the-week -</$button> -<$button> -<$action-listops $tiddler="ListopsData" $index="DataIndex" $filter="[[]]"/> -Clear -</$button> - -{{ListopsData}}"""/> - ---- -In this example we shall slice the populated list from the 'DaysOfTheWeek' index of the tiddler '~MyData' in order to insert items before and after a marker item (Wednesday) that are first appended to the list. - -<$macrocall $name='wikitext-example-without-html' -src="""<$button> -<$action-listops $tiddler="ListopsData" $index="DataIndex" $subfilter="one two +[putbefore:2[Wednesday]]"/> -Put 2 Items Before Wednesday -</$button> -<$button> -<$action-listops $tiddler="ListopsData" $index="DataIndex" $subfilter="four five +[putafter:2[Wednesday]] three +[putbefore[Wednesday]]"/> -Put One Item Before & Two Items After Wednesday -</$button> - -{{ListopsData}}"""/> - ---- -In this example we shall slice the populated list from the 'DaysOfTheWeek' index of the tiddler '~MyData' in order to replace the marker item (Wednesday) with items which are first appended to the list. We shall then move 3 items to the head of the list which have first been appended to the list from referenced fields. - -<$macrocall $name='wikitext-example-without-html' -src="""<$button> -<$action-listops $tiddler="ListopsData" $index="DataIndex" $subfilter="[[---o]] [[o---]] +[replace:2{!!marker}]"/> -Replace '!!marker' with 2 Items -</$button> -<$button> -<$action-listops $tiddler="ListopsData" $index="DataIndex" $subfilter="[{!!item1}] [{!!item2}] [{!!item3}] +[putfirst:3[]]"/> -Put 3 Items First -</$button> - -{{ListopsData}}"""/> - ---- -In this example we shall slice the populated list from the 'DaysOfTheWeek' index of the tiddler '~MyData' in order to append to the truncated list, items from a referenced field. We shall then remove the first two of the items added. - -<$macrocall $name='wikitext-example-without-html' -src="""|list: |<$view field="list"/> | - -<$button> -<$action-listops $tiddler="ListopsData" $index="DataIndex" $subfilter="+[allbefore:include[Wednesday]] +[prepend{!!list}]"/> -Prepend '!!list' to items before 'Wednesday' -</$button> -<$button> -<$action-listops $tiddler="ListopsData" $index="DataIndex" $subfilter="+[remove:2{!!list}]"/> -Remove first two items in '!!list' from current list -</$button> -<$button> -<$action-listops $tiddler="ListopsData" $index="DataIndex" $subfilter="+[!remove:1{!!list}]"/> -Remove last item in '!!list' from current list -</$button> - -{{ListopsData}}"""/> - ---- -In this example we shall populate the list with numbers, then move items one by one from the head to the tail and from the tail to the head (best seen by clicking the lower buttons several times.) - -This example illustrates that the append[] and prepend[] operators do not enforce unique instances of an item and that, with the next run, any duplicates are removed. - -<$macrocall $name='wikitext-example-without-html' -src="""<$button> -<$action-listops $tiddler="ListopsData" $index="DataIndex" $filter="[[]]" $subfilter="+[append:3{!!numbers}]"/> -Setup some numbers -</$button> -<$button> -<$action-listops $tiddler="ListopsData" $index="DataIndex" $subfilter="+[!append:6{!!numbers}]"/> -Append more numbers -</$button> - -<$button> -<$action-listops $tiddler="ListopsData" $index="DataIndex" $subfilter="+[putfirst:2[]]"/> -Move last 2 items to the head -</$button> -<$button> -<$action-listops $tiddler="ListopsData" $index="DataIndex" $subfilter="+[putlast[]]"/> -Move the head to the last item -</$button> - -{{ListopsData}}"""/> +See [[Extended Listops Filters]] \ No newline at end of file diff --git a/editions/tw5.com/tiddlers/widgets/TranscludeWidget.tid b/editions/tw5.com/tiddlers/widgets/TranscludeWidget.tid index 6bc507cae..348de1090 100644 --- a/editions/tw5.com/tiddlers/widgets/TranscludeWidget.tid +++ b/editions/tw5.com/tiddlers/widgets/TranscludeWidget.tid @@ -1,24 +1,178 @@ caption: transclude created: 20130824142500000 -modified: 20220513114759336 +modified: 20230419103154329 tags: Widgets title: TranscludeWidget type: text/vnd.tiddlywiki ! Introduction -The TranscludeWidget dynamically imports content from another tiddler. +The <<.wlink TranscludeWidget>> widget dynamically includes the content from another tiddler or variable, rendering it as if the transclude widget were replaced by the target content. + +The <<.wlink TranscludeWidget>> widget can be used to render content of any type: wikitext, images, videos, etc. + +Transclusion is the underlying mechanism for many higher level wikitext features, such as procedures, custom widgets and macros. + +! Example + +Here is a complete example showing the important features of the <<.wlink TranscludeWidget>> widget: + +``` +\procedure mymacro(name,age) +My name is <<name>> and my age is <<age>>. +\end + +<$transclude $variable="mymacro" name="James" age="19"/> +``` + +* `\procedure` defines a variable as a procedure with two parameters, ''name'' and ''age'' +* The content of the procedure refers to the parameters as variables +* The <<.wlink TranscludeWidget>> widget specifies the variable to transclude, and values for the parameters. + +! Legacy vs. Modern Mode + +The <<.wlink TranscludeWidget>> widget can be used in two modes: + +* <<.from-version "5.3.0">> ''Modern mode'' offers the full capabilities of the <<.wlink TranscludeWidget>> widget, and incorporates the functionality of the <<.wlink MacroCallWidget>> widget. It is indicated by the presence of at least one attribute starting with a dollar sign `$` +* ''Legacy mode'' offers a more limited set of capabilities. It is indicated by the absence of any attributes starting with a dollar sign `$` + +Modern mode is recommended for use in new applications. ! Attributes -|!Attribute |!Description | -|tiddler |The title of the tiddler to transclude (defaults to the current tiddler) | -|field |The field name of the current tiddler (defaults to "text"; if present takes precedence over the index attribute) | -|index |The index of a property in a [[DataTiddler|DataTiddlers]] | -|subtiddler |Optional SubTiddler title when the target tiddler is a [[plugin|Plugins]] (see below) | -|mode |Override the default parsing mode for the transcluded text to "block" or "inline" | +| !Attribute |<| !Description | +| !(modern) | !(legacy) |~| +|$variable |- |Name of the variable to transclude | +|$tiddler |tiddler |The title of the tiddler to transclude (defaults to the current tiddler) | +|$field |field |The field name of the current tiddler (defaults to "text"; if present takes precedence over the index attribute) | +|$index |index |The index of a property in a [[DataTiddler|DataTiddlers]] | +|$subtiddler |subtiddler |Optional SubTiddler title when the target tiddler is a [[plugin|Plugins]] (see below) | +|$mode |mode |Override the default parsing mode for the transcluded text to "block" or "inline" | +|$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'') | +|//{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 | -The TranscludeWidget treats any contained content as a fallback if the target of the transclusion is not defined (ie a missing tiddler or a missing field). +! Basic Operation + +The basic operation of the <<.wlink TranscludeWidget>> widget is as follows: + +|`<$transclude/>` |Transcludes the text field of the current tiddler | +|`<$transclude $variable="alpha"/>` |Transcludes the variable "alpha" (note that procedures, custom widgets and macros are all special types of variable) | +|`<$transclude $tiddler="foo"/>` |Transcludes the text field of the tiddler "foo" | +|`<$transclude $field="bar"/>` |Transcludes the field "bar" of the current tiddler | +|`<$transclude $index="beta"/>` |Transcludes the index "beta" of the current tiddler | +|`<$transclude $tiddler="foo" $index="beta"/>` |Transcludes the index "beta" of the tiddler "foo" | + +! Transclusion Parameters + +Named string parameters can be passed to the <<.wlink TranscludeWidget>> widget. They are made available as variables within the transcluded text. Parameters are only supported in modern mode. + +When invoking a transclusion, parameters are specified as additional attributes that do not start with a dollar sign `$`: + +``` +<$transclude $tiddler="MyTiddler" firstParameter="One" secondParameter="Two"/> +``` + +To pass parameters whose names start with a dollar sign `$`, prefix them with an extra `$`. For example, to pass a parameter called `$tiddler`: + +``` +<$transclude $tiddler="MyTiddler" $$tiddler="One"/> +``` + +There are several different ways to declare parameters within a transclusion: + +* the <<.wlink ParametersWidget>> widget +* the [[Pragma: \parameters]] +* the [[Pragma: \procedure]] for declaring procedure +* the [[Pragma: \widget]] for declaring custom widgets +* the [[Pragma: \define]] for declaring macros + +An example of declaring parameters with the <<.wlink ParametersWidget>> widget: + +``` +<$parameters firstParameter="default" secondParameter="another default"> + Parameters are available here as the variables <<firstParameter>> and <<secondParameter>>. +</$parameters> +``` + +The [[Pragma: \parameters]] can be used as a shortcut syntax for declaring parameters. For example: + +``` +\parameters (firstParameter:"default",secondParameter:"another default") +Parameters are available here as the variables <<firstParameter>> and <<secondParameter>>. +``` + +! Transclusion Slots + +Transcluded content can define special named locations called slots. At the point of transclusion, blocks of wikitext can be passed to the <<.wlink TranscludeWidget>> widget to fill those slots. + +Slots work very similarly to parameters except that they can contain structured wikitext, and not just plain text. The primary advantage of slots over parameters is that the contents do not need to be wrapped in quotation symbols, making it much simpler to pass complex structures. + +For example, here we transclude the tiddler "Example" while using the <<.wlink FillWidget>> widget to pass wikitext blocks to fill the slots called "positive" and "negative": + +``` +<$transclude $tiddler="Example"> + <$fill $name="positive"> + <h1>This is positive</h1> + </$fill> + <$fill $name="negative"> + <h3>This is negative</h3> + </$fill> +</$transclude> +``` + +The tiddler "Example" uses the <<.wlink SlotWidget>> widget to specify the slots to be filled: + +``` +<ol> + <li><$slot $name="positive"/></li> + <li><$slot $name="negative"/></li> +</ol> +``` + +The output will be equivalent to: + +``` +<ol> + <li> + <h1>This is positive</h1> + </li> + <li> + <h3>This is negative</h3> + </li> +</ol> +``` + + +! Missing Transclusion Targets + +The TranscludeWidget uses the special slot `ts-missing` to specify the content to be rendered if the transclusion target is not defined (i.e. a missing tiddler or a missing field). + +For example: + +``` +<$transclude $tiddler="MissingTiddler"> +<$fill $name="ts-missing"> +This content is displayed if `MissingTiddler` is missing. +</$fill> +<$fill $name="other"> +This content is passed to the transclusion as the slot value `other` +</$fill> +</$transclude> +``` + +If no slots values are specified within the <<.wlink TranscludeWidget>> widget then the entire content of the widget is used as the missing content. + +For example: + +``` +<$transclude $tiddler="MissingTiddler"> +This content is displayed if `MissingTiddler` is missing. +</$transclude> +``` ! Parsing modes diff --git a/editions/tw5.com/tiddlers/widgets/examples/ActionListopsWidget (Examples).tid b/editions/tw5.com/tiddlers/widgets/examples/ActionListopsWidget (Examples).tid new file mode 100644 index 000000000..8f8fe8a87 --- /dev/null +++ b/editions/tw5.com/tiddlers/widgets/examples/ActionListopsWidget (Examples).tid @@ -0,0 +1,81 @@ +created: 20230301174431218 +list: efg hlm pqr +modified: 20230301174431218 +myfield: +revision: 0 +title: ActionListopsWidget (Examples) +type: text/vnd.tiddlywiki + +In this example we shall populate and then clear a list in an ordinary field (myfield) of this tiddler (the default). + +<$macrocall $name='wikitext-example-without-html' +src="""<$button> +<$action-listops $field="myfield" $filter="efg hlm pqr"/> +Populate 'myfield' +</$button> +<$button> +<$action-listops $field="myfield" $subfilter="abc xyz"/> +Append More Items +</$button> +<$button> +<$action-listops $field="myfield" $subfilter="-abc -hlm"/> +Remove Items +</$button> +<$button> +<$action-listops $field="myfield" $filter="[[]]"/> +Clear 'myfield' +</$button> + +<$list filter="[list[!!myfield]]"> + +</$list>"""/> + +--- +In this example we shall append and remove items from a list in an ordinary field (myfield) of this tiddler (the default) and sort the resultant list. We shall then remove some of the appended items and sort the resulting list in reverse order. + +<$macrocall $name='wikitext-example-without-html' +src="""<$button> +<$action-listops $field="myfield" $subfilter="-efg ijk xyz [[this is a title]] +[sort[]]"/> +Mangle List +</$button> +<$button> +<$action-listops $field="myfield" $subfilter="-xyz -[[this is a title]] +[!sort[]]"/> +Unmangle List +</$button> + +<$list filter="[list[!!myfield]]"> + +</$list>"""/> + +--- +In this example we shall append a few tags to the 'tags' field of this tiddler (the default). We shall then remove some of the appended tags. + +<$macrocall $name='wikitext-example-without-html' +src="""<$button> +<$action-listops $tags="+[append{Days of the Week!!short}] $:/tag1 $:/tag2 $:/tag3"/> +Populate 'tags' +</$button> +<$button> +<$action-listops $tags="+[!remove:2{!!tags}]"/> +Remove Last Two Tags +</$button> +<$button> +<$action-listops $tags="+[!prefix[$:/]]"/> +Remove System Tags +</$button> +<$button> +<$action-listops $tags="-Mon -Tue"/> +Remove Mon and Tue +</$button> +<$button> +<$action-listops $tags="+[prefix[$:/]] ActionWidgets Widgets"/> +Remove User Tags +</$button> +<$button> +<$action-listops $tags="+[[]] ActionWidgets Widgets"/> +Clear Tags +</$button> + +<$list filter="[list[!!tags]]"> + +</$list>"""/> diff --git a/editions/tw5.com/tiddlers/wikitext/Formatting in WikiText.tid b/editions/tw5.com/tiddlers/wikitext/Formatting in WikiText.tid index 7166c28c8..7ffb4e497 100644 --- a/editions/tw5.com/tiddlers/wikitext/Formatting in WikiText.tid +++ b/editions/tw5.com/tiddlers/wikitext/Formatting in WikiText.tid @@ -1,19 +1,60 @@ caption: Formatting created: 20131205155959399 -modified: 20220513120211686 +modified: 20230303215447403 tags: WikiText title: Formatting in WikiText type: text/vnd.tiddlywiki -Available character formatting includes: +!! Overview -* <code>`backticks`</code> for `code` (<<.icon $:/core/images/mono-line>>) -** Alternatively, <code>``double backticks allows `embedded` backticks``</code><br><br> -* `''bold''` for ''bold text'' (<<.icon $:/core/images/bold>>)<br><br> -* `//italic//` for //italic text// (<<.icon $:/core/images/italic>>)<br><br> -* `__underscore__` for __underscored text__ (<<.icon $:/core/images/underline>>)<br><br> -* `^^superscript^^` for ^^superscripted^^ text (<<.icon $:/core/images/superscript>>)<br><br> -* `,,subscript,,` for ,,subscripted,, text (<<.icon $:/core/images/subscript>>)<br><br> -* `~~strikethrough~~` for ~~strikethrough~~ text (<<.icon $:/core/images/strikethrough>>) +Available character formatting in WikiText includes: -See also: [[Code Blocks in WikiText]] +|Wikitext | Button | Shortcut |Rendered Output |h +|Double single quotes are used for `''bold text''`| <kbd><<.icon $:/core/images/bold>></kbd> | <kbd><<displayshortcuts "((bold))">></kbd> |Double single quotes are used for ''bold text'' | +|Double slashes are used for `//italic text//`| <kbd><<.icon $:/core/images/italic>></kbd> | <kbd><<displayshortcuts "((italic))">></kbd> |Double slashes are used for //italic text//| +|Double underscores are used for `__underlined text__`| <kbd><<.icon $:/core/images/underline>></kbd> | <kbd><<displayshortcuts "((underline))">></kbd> |Double underscores are used for __underlined text__ | +|Double circumflex accents are used for `^^superscripted^^` text | <kbd><<.icon $:/core/images/superscript>></kbd> | <kbd><<displayshortcuts "((superscript))">></kbd> |Double circumflex accents are used for ^^superscripted^^ text | +|Double commas are used for `,,subscripted,,` text | <kbd><<.icon $:/core/images/subscript>></kbd> | <kbd><<displayshortcuts "((subscript))">></kbd> |Double commas are used for ,,subscripted,, text | +|Double tilde signs are used for `~~strikethrough~~` text | <kbd><<.icon $:/core/images/strikethrough>></kbd> | <kbd><<displayshortcuts "((strikethrough))">></kbd> |Double tilde signs are used for ~~strikethrough~~ text | +|Single backticks are used for ```code` `` | <kbd><<.icon $:/core/images/mono-line>></kbd> | <kbd><<displayshortcuts "((mono-line))">></kbd> |Single backticks are used for `code` | +|Double @ characters are used to create a `@@highlight@@` | - | - |Double @ characters are used to create a @@highlight@@ | + +See [[Styles and Classes in WikiText]] for more formatting options + +!! Embedded Backticks + +|Wikitext |Rendered Output|h +|<code>``double backticks allows `embedded` backticks``</code>|``double backticks allows `embedded` backticks``| + +!! Keyboard Shortcuts + +The full list of KeyboardShortcuts can be found in the $:/ControlPanel -> ''Keyboard Shortcuts'' tab. + +!! Semantic Information + +|Wikitext | Resulting HTML Code |h +|Double single quotes are used for `''bold text''`|Double single quotes are used for `<strong>bold text</strong>` | +|Double slashes are used for `//italic text//`|Double slashes are used for `<em>italic text</em>` | +|Double underscores are used for `__underlined text__`|Double underscores are used for `<u>underlined text<u>` | +|Double circumflex accents are used for `^^superscripted^^` text |Double circumflex accents are used for `<sup>superscripted</sup>` text | +|Double commas are used for `,,subscripted,,` text |Double commas are used for `<sub>subscripted</sub>` text | +|Double tilde signs are used for `~~strikethrough~~` text |Double tilde signs are used for `<strike>strikethrough</strike>` text | +|Single backticks are used for ```code` `` |Single backticks are used for `<code>code</code>` | +|Double @ characters are used to create a `@@highlight@@` |Double @ characters are used to create a `<span class="tc-inline-style">highlighted</span>` | + +!! Bold vs Strong + +In TW we use the term "bold" instead of "strong" because most users are used to it. ... The rendering process converts our "bold text" into the STRONG HTML element. + +>The `<strong>` element is for content that is of greater importance, while the `<b>` element is used to draw attention to text without indicating that it's more important. +>https://developer.mozilla.org/en-US/docs/Web/HTML/Element/strong#b_vs._strong + +!! Underline vs. Underscore + +>Use underline to describe text formatting that puts a line under the characters. Use underscore to refer to the underscore character ( _ ). +>https://learn.microsoft.com/en-us/style-guide/a-z-word-list-term-collections/u/underline-vs-underscore + +!! Emphasis vs Italics + +>The `<em>` element represents stress emphasis of its contents, while the `<i>` element represents text that is set off from the normal prose, such as a foreign word, fictional character thoughts, or when the text refers to the definition of a word instead of representing its semantic meaning. (The title of a work, such as the name of a book or movie, should use `<cite>`.) +>https://developer.mozilla.org/en-US/docs/Web/HTML/Element/em#i_vs._em diff --git a/editions/tw5.com/tiddlers/wikitext/HTML Entities.tid b/editions/tw5.com/tiddlers/wikitext/HTML Entities.tid new file mode 100644 index 000000000..59b674575 --- /dev/null +++ b/editions/tw5.com/tiddlers/wikitext/HTML Entities.tid @@ -0,0 +1,66 @@ +created: 20130204165019000 +modified: 20221025124615415 +tags: WikiText +title: HTML Entities +type: text/vnd.tiddlywiki + +!! Summary + +Use HTML entities to enter characters that cannot easily be typed on an ordinary keyboard. They take the form of an ampersand (`&`), an identifying string, and a terminating semi-colon (`;`), e.g. `&` for the ''&'' character. + +!! Markup + +``` +The value of Tiddlers™ cannot even be expressed in £, € or $. +``` + +''Displays as:'' + +The value of Tiddlers™ cannot even be expressed in £, € or $. + +!! Entity References + +Comprehensive lists of html entities can be found at... + +* [[Mozilla Developer Network -- Entities|https://developer.mozilla.org/en-US/docs/Glossary/Entity]] + +* [[HTML Spec official list -- Entities|https://html.spec.whatwg.org/multipage/named-characters.html#named-character-references]] + + +!! Examples Of Common And Useful Entities + +|>|>|>|>|>|>| ! HTML Entities | +| &nbsp; |   | no-break space |    | &apos; | ' | single quote, apostrophe | +| &ndash; | – | en dash |~| &quot; | " | quotation mark | +| &mdash; | — | em dash |~| &prime; | ′ | prime; minutes; feet | +| &hellip; | … | horizontal ellipsis |~| &Prime; | ″ | double prime; seconds; inches | +| &copy; | © | Copyright symbol |~| &lsquo; | ‘ | left single quote | +| &reg; | ® | Registered symbol |~| &rsquo; | ’ | right single quote | +| &trade; | ™ | Trademark symbol |~| &ldquo; | “ | left double quote | +| &dagger; | † | dagger |~| &rdquo; | ” | right double quote | +| &Dagger; | ‡ | double dagger |~| &laquo; | « | left angle quote | +| &para; | ¶ | paragraph sign |~| &raquo; | » | right angle quote | +| &sect; | § | section sign |~| &times; | × | multiplication symbol | +| &uarr; | ↑ | up arrow |~| &darr; | ↓ | down arrow | +| &larr; | ← | left arrow |~| &rarr; | → | right arrow | +| &lArr; | ⇐ | double left arrow |~| &rArr; | ⇒ | double right arrow | +| &harr; | ↔ | left right arrow |~| &hArr; | ⇔ | double left right arrow | + +!! Accented Characters + +The table below shows how accented characters can be built up by //substituting// the +underscore (_) in the second table into the corresponding character. eg: + +|Code |Character |Example |Result |h +|`Ä` |Ä | `Äpfel` |Äpfel | + + +|>|>|>|>|>|>|>|>|>|>|>|>|>|>|>|>|>| ! Accented Characters | +| grave accent | &_grave; | À | à | È | è | Ì | ì | Ò | ò | Ù | ù |   |   |   |   |   |   | +| acute accent | &_acute; | Á | á | É | é | Í | í | Ó | ó | Ú | ú |   |   | Ý | ý |   |   | +| circumflex accent | &_circ; |  | â | Ê | ê | Î | î | Ô | ô | Û | û |   |   |   |   |   |   | +| umlaut mark | &_uml; | Ä | ä | Ë | ë | Ï | ï | Ö | ö | Ü | ü |   |   | Ÿ | ÿ |   |   | +| tilde | &_tilde; | à | ã |   |   |   |   | Õ | õ |   |   | Ñ | ñ |   |   |   |   | +| ring | &_ring; | Å | å |   |   |   |   |   |   |   |   |   |   |   |   |   |   | +| slash | &_slash; |   |   |   |   |   |   | Ø | ø |   |   |   |   |   |   |   |   | +| cedilla | &_cedil; |   |   |   |   |   |   |   |   |   |   |   |   |   |   | Ç | ç | diff --git a/editions/tw5.com/tiddlers/wikitext/HTML in WikiText.tid b/editions/tw5.com/tiddlers/wikitext/HTML in WikiText.tid index d000cd975..ef42f948a 100644 --- a/editions/tw5.com/tiddlers/wikitext/HTML in WikiText.tid +++ b/editions/tw5.com/tiddlers/wikitext/HTML in WikiText.tid @@ -62,7 +62,7 @@ In an extension of conventional HTML syntax, attributes of elements/widgets can * a literal string * a transclusion of a TextReference -* a transclusion of a [[macro/variable|Macros in WikiText]] +* a transclusion of a [[macro/variable|Macros]] * as the result of a [[Filter Expression]] !! Style Attributes @@ -125,7 +125,7 @@ attr={{tiddler!!field}} !! Variable Attribute Values -Variable attribute values are indicated with double angle brackets around a [[macro invocation|Macro Calls in WikiText]]. For example: +Variable attribute values are indicated with double angle brackets around a [[macro invocation|Macro Calls]]. For example: ``` <div title=<<MyMacro "Brian">>> diff --git a/editions/tw5.com/tiddlers/wikitext/Macro Calls in WikiText.tid b/editions/tw5.com/tiddlers/wikitext/Macro Calls in WikiText.tid index b79d98134..0d45612f0 100644 --- a/editions/tw5.com/tiddlers/wikitext/Macro Calls in WikiText.tid +++ b/editions/tw5.com/tiddlers/wikitext/Macro Calls in WikiText.tid @@ -1,26 +1,8 @@ caption: Macro Calls -created: 20150220182252000 -modified: 20220122193853161 -tags: WikiText +created: 20220917074831994 +modified: 20220917074844235 +tags: title: Macro Calls in WikiText type: text/vnd.tiddlywiki -To call a [[macro|Macros]], place `<<`double angle brackets`>>` around the name and any parameter values. - -By default, parameters are listed in the same order as in the macro's definition. A parameter can be labelled with its name, either for clarity or to modify the order. - -If no value is specified for a parameter, the default value given for that parameter in the macro's definition is used instead. (If no default value was defined, the parameter is simply blank.) - -Each parameter value can be enclosed in `'`single quotes`'`, `"`double quotes`"`, `"""`triple double quotes`"""` or `[[`double square brackets`]]`. Triple double quotes allow a value to contain almost anything. If a value contains no spaces or single or double quotes, it requires no delimiters. - -A more formal [[presentation|Macro Call Syntax]] of this syntax is also available. - -The syntax is actually a shorthand for a <<.wlink MacroCallWidget>> widget. The widget itself offers greater flexibility, including the ability to [[transclude|Transclusion]] parameter values or generate them via additional macros. - -As macros are simply parameterised [[variables|Variables]], a variable's value can be inserted using the same techniques. - -[[Examples|Macro Calls in WikiText (Examples)]] and [[more examples|WikiText parser mode: macro examples]] - -!! Named vs.unnamed parameters - -In the wikitext notation, using named parameters is always the safer choice compared to defining values only. Not naming parameters may have confusing side effects. For example, imagine the first parameter of some macro specifies a [[state tiddler|StateMechanism]] while the second one is intended for a [[template|Transclusion with Templates]] tiddler. Should you accidentally forget to define the first parameter or are confused about the order, the next time your macro is run, which might even be triggered using the preview, your template tiddler may inadvertently be overriden with what was intended to be the state. +See [[Macro Calls]]. \ No newline at end of file diff --git a/editions/tw5.com/tiddlers/wikitext/Macro Calls.tid b/editions/tw5.com/tiddlers/wikitext/Macro Calls.tid new file mode 100644 index 000000000..eddf28200 --- /dev/null +++ b/editions/tw5.com/tiddlers/wikitext/Macro Calls.tid @@ -0,0 +1,58 @@ +caption: Macro Calls +created: 20150220182252000 +modified: 20230419103154328 +tags: WikiText Macros +title: Macro Calls +type: text/vnd.tiddlywiki + +!! Introduction + +This tiddler describes the different ways in which [[macros|Macros]] can be called. + +!! Macro Call Transclusion Shortcut + +To call a [[macro|Macros]], place `<<`double angle brackets`>>` around the name and any parameter values. + +``` +<<mymacro param:"This is the parameter value">> +``` + +By default, parameters are listed in the same order as in the macro's definition. A parameter can be labelled with its name and a colon to allow them to be listed in a different order. + +If no value is specified for a parameter, the default value given for that parameter in the [[macro definition|Macro Definitions]] is used instead. (If no default value was defined, the parameter is blank). + +Each parameter value can be enclosed in `'`single quotes`'`, `"`double quotes`"`, `"""`triple double quotes`"""` or `[[`double square brackets`]]`. Triple double quotes allow a value to contain almost anything. If a value contains no spaces or single or double quotes, it requires no delimiters. + +A more formal [[presentation|Macro Call Syntax]] of this syntax is also available. + +See some [[examples|Macro Calls in WikiText (Examples)]] and discussion about [[parser modes|WikiText parser mode: macro examples]]. + +!! Macro Calls with <<.wlink TranscludeWidget>> Widget + +The shortcut syntax expands to the <<.wlink TranscludeWidget>> widget with the `$variable` attribute specifying the name of the macro to transclude. + +``` +<$transclude $variable="mymacro" param="This is the parameter value"/> +``` + +The widget itself offers greater flexibility than the shortcut syntax, including the ability to specify parameter values. + +!! Assigning Macro Calls to Attribute Values + +The result of a macro can be directly assigned to an attribute of a widget or HTML element. The result of the macro is not wikified, but the [[parameter substitution|Macro Parameter Handling]] is performed. + +``` +<div class=<<myclasses "Horizontal">>> +... +</div> +``` + +!! Using Macro Calls in Filters + +Macro calls can be used in filters: + +``` +<$list filter="[<mymacro param:'value'>]"> +... +</$list> +``` \ No newline at end of file diff --git a/editions/tw5.com/tiddlers/wikitext/Macro Definitions in WikiText.tid b/editions/tw5.com/tiddlers/wikitext/Macro Definitions in WikiText.tid index eb74ead1a..9e3d9d1fe 100644 --- a/editions/tw5.com/tiddlers/wikitext/Macro Definitions in WikiText.tid +++ b/editions/tw5.com/tiddlers/wikitext/Macro Definitions in WikiText.tid @@ -1,114 +1,7 @@ -caption: Macro Definitions created: 20150220181617000 -modified: 20221207094236472 -tags: WikiText +modified: 20180820165115455 +tags: title: Macro Definitions in WikiText type: text/vnd.tiddlywiki -A [[macro|Macros]] is defined using a `\define` [[pragma|Pragma]]. Like any pragma, this can only appear at the start of a tiddler. - -The first line of the definition specifies the macro name and any parameters. Each parameter has a name and, optionally, a default value that is used if no value is supplied on a particular call to the macro. - -The lines that follow contain the text of the macro text (i.e. the snippet represented by the macro name), until `\end` appears on a line by itself: - -<$codeblock code={{$:/editions/tw5.com/macro-examples/say-hi}}/> - -Alternatively, the entire definition can be presented on a single line without an `\end` marker: - -``` -\define sayhi(name:"Bugs Bunny") Hi, I'm $name$. -``` - -!! Accessing variables and parameters - -Inside the macro there are several methods for accessing variables defined outside of the macro or parameters from the macro parameter list. - -|syntax|description|h -|`$...$`|Text substitution of a parameter defined in the macro parameters list | -|`<<__...__>>`|Parameter-as-variable access to a parameter defined in the macro parameters list | -|`$(...)$`|Text substitution of a variable defined outside of the macro | -|`<<...>>`|Access to a variable (or other macro) defined outside of the macro | -<br> - -!!! Placeholders `$(...)$` - -The macro can contain placeholders for parameters. These consist of a parameter name between dollar signs, like `$this$`. - -The macro can also contain placeholders for [[variables|Variables]]. These consist of a variable name (or macro name) between dollar signs and round brackets, like `$(this)$`. - -The actual value of the parameter or variable is substituted for the placeholder whenever the macro is called: - -<$importvariables filter="$:/editions/tw5.com/macro-examples/say-hi-using-variables"> -<$codeblock code={{$:/editions/tw5.com/macro-examples/say-hi-using-variables}}/> -<$macrocall $name=".example" n="1" -eg="""<$set name="address" value="Rabbit Hole Hill"> -<<say-hi-using-variables>> -</$set>"""/> -</$importvariables> - -!!! Parameters as Variables `<<__...__>>` - -Parameters in a wikitext macro can be accessed as variables by using the syntax `<<__...__>>`, i.e the parameter name surrounded by double underscores. For example, the example above could also be expressed as: - -``` -\define sayhi(name:"Bugs Bunny") Hi, I'm <$text text=<<__name__>>/>. -``` - -Accessing parameters as variables only works in macros that are wikified and not, for example, when a macro is used as an attribute value. The advantage of the technique is that it avoids the parameter value being substituted into the macro as a literal string, which in turn can help avoid issues with parameters that contain quotes. - -For example, consider this macro. It invokes another macro using the single parameter as an argument for it: - -``` -\define film-quote(line) <$macrocall $name="anothermacro" actor="Bugs Bunny" line="""$line$"""/> -``` - -The code above will fail if the macro is invoked with the argument containing triple double quotes (for example `<<film-quote 'I quote thrice """ - see!?'>>`). Using parameter variables offers a workaround: - -``` -\define film-quote(line) <$macrocall $name="anothermacro" actor="Bugs Bunny" line=<<__line__>>/> -``` - -!! Scope - -Macros are available to the tiddler that defines them, plus any tiddlers that it transcludes. - -To make a macro available to all tiddlers, define it in a tiddler that has the tag <<.tag $:/tags/Macro>>. - -It is also possible to write a macro as a [[JavaScript module|https://tiddlywiki.com/dev/index.html#JavaScript%20Macros]]. ~JavaScript macros are available to all tiddlers, and offer the maximum flexibility. - -A tiddler can manually import macro definitions from a [[selection|Title Selection]] of other tiddlers by using the <<.wlink ImportVariablesWidget>> widget. - -!! Nested Macro Definitions - -Macro definitions can be nested to any number of required levels by specifying the name of the macro in the `\end` marker. Nested macro definitions must appear at the start of the definition that contains them. For example: - -<<wikitext-example-without-html src:"""\define special-button(caption:"Click me") -\define actions() -<$action-sendmessage $message="tm-notify" $param="HelloThere"/> -\end actions -<$button actions=<<actions>>> -$caption$ -</$button> -\end special-button - -<<special-button>> -""">> - -Note that the textual substitution of macro parameters that occurs when the outer macro is rendered will apply to the nested definitions as well. That generally means that textual substitution of macro parameters should not be used within nested macros. - -Parameters of nested macros can also be accessed via the `<<__variablename__>>` syntax. As ordinary variables, these parameters are available within nested child macros (and grandchildren etc). - -For the one-liner macro definition, the `\end` remains unnecessary for the inner macro. For example - -<<wikitext-example-without-html src:"""\define special-button(caption:"Click me") -\define actions() <$action-sendmessage $message="tm-notify" $param="HelloThere"/> -<$button actions=<<actions>>> -$caption$ -</$button> -\end special-button - -<<special-button>> -""">> - -A more formal [[presentation|Macro Definition Syntax]] of this syntax is also available. - +See [[Macro Definitions]]. diff --git a/editions/tw5.com/tiddlers/wikitext/Macro Definitions.tid b/editions/tw5.com/tiddlers/wikitext/Macro Definitions.tid new file mode 100644 index 000000000..a7d297f93 --- /dev/null +++ b/editions/tw5.com/tiddlers/wikitext/Macro Definitions.tid @@ -0,0 +1,67 @@ +created: 20150220181617000 +modified: 20230419103154328 +tags: WikiText Macros +title: Macro Definitions +type: text/vnd.tiddlywiki + +!! Introduction + +This tiddler describes the different ways in which [[macros|Macros]] can be defined. + +!! Macro Definition Pragma + +Macros are created using the [[Pragma: \define]] 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 mymacro(param) +This is the macro text (param=$param$) +\end +``` + +!! Nested Macro Definitions + +Macro definitions can be nested to any number of required levels by specifying the name of the macro in the `\end` marker. Nested macro definitions must appear at the start of the definition that contains them. For example: + +<<wikitext-example-without-html src:"""\define special-button(caption:"Click me") +\define actions() +<$action-sendmessage $message="tm-notify" $param="HelloThere"/> +\end actions +<$button actions=<<actions>>> +$caption$ +</$button> +\end special-button + +<<special-button>> +""">> + +Note that the textual substitution of macro parameters that occurs when the outer macro is rendered will apply to the nested definitions as well. That generally means that textual substitution of macro parameters should not be used within nested macros. + +Parameters of nested macros can also be accessed via the `<<__variablename__>>` syntax. As ordinary variables, these parameters are available within nested child macros (and grandchildren etc). + +!! Macro Definition with Set Widget + +Macros are implemented as a special type of [[variable|Variables]] and so internally are actually defined with a <<.wlink SetWidget>> widget. + +``` +<$set name="mymacro" value="This is the macro text"> +... +</$set> +``` + +<<.note """that it is not currently possible to specify parameters when defining a macro with the <<.wlink SetWidget>> widget.""">> + +!! Importing Macro Definitions + +The [[Pragma: \import]] or <<.wlink ImportVariablesWidget>> widget can be used to copy macro definitions from another tiddler. + +!! `$:/tags/Macro` Tag + +Global macros can be defined using the [[SystemTag: $:/tags/Macro]]. + +The tag [[SystemTag: $:/tags/Macro/View]] is used to define macros that should only be available within the main view template and the preview panel. + +The tag [[SystemTag: $:/tags/Macro/View/Body]] is used to define macros that should only be available within the main view template body and the preview panel. + +!! JavaScript Macros + +Macros can also be <<.js-macro-link "written as JavaScript modules">>. diff --git a/editions/tw5.com/tiddlers/wikitext/Macro Parameter Handling.tid b/editions/tw5.com/tiddlers/wikitext/Macro Parameter Handling.tid new file mode 100644 index 000000000..35655334c --- /dev/null +++ b/editions/tw5.com/tiddlers/wikitext/Macro Parameter Handling.tid @@ -0,0 +1,78 @@ +created: 20220917154902906 +modified: 20230419103154328 +tags: WikiText Macros +title: Macro Parameter Handling +type: text/vnd.tiddlywiki + +!! Introduction + +[[Macros]] parameters are handled in two different ways: + +# Textual substitution is always performed for each parameter before the macro contents is used +# When the macro contents are wikified the parameters are made available as variables. The variable names are formed by wrapping the parameter name with double underscores + +Somewhat confusingly, in some situations both of these mechanisms will occur; this is related to the [[pitfalls of using macros|Macro Pitfalls]]. + +!! Textual Substitution of Parameters and variables + +The following substitutions take place before the text of a macro is used: + +* The pattern `$param$` is replaced with the value of the named parameter +* The pattern `$(variable)$` is replaced with the value of the named variable + +The actual value of the parameter or variable is substituted for the placeholder whenever the macro is called: + +<$macrocall $name="wikitext-example-without-html" src="""\define say-hi-using-parameters(name,address) +Hi, I'm $name$ and I live in $address$. +\end + +<<say-hi-using-parameters name:"Bugs" address:"Rabbit Hole Hill">> +"""/> + +Here's an example using variable substitution: + +<$macrocall $name="wikitext-example-without-html" src="""\define say-hi-using-variables() +Hi, I'm $(name)$ and I live in $(address)$. +\end + +\define name() Bugs + +<$let address="Rabbit Hole Hill"> +<<say-hi-using-variables>> +</$let> +"""/> + +<<.warning """It is important to note that if the text being inserted contains any substitution tokens then they will in turn be processed. This can lead to unexpected results.""">> + +!! Accessing Parameters as Variables + +When macros are wikified, the parameters can be accessed as variables with the name of the parameter wrapped with double underscores. For example, the parameter `address` would be accessed as the variable `__address__`. + +Thus, the example above could also be expressed as: + +<$macrocall $name="wikitext-example-without-html" src="""\define say-hi-using-parameters(name,address) +Hi, I'm <<__name__>> and I live in <<__address__>>. +\end + +<<say-hi-using-parameters name:"Bugs" address:"Rabbit Hole Hill">> +"""/> + +Accessing parameters as variables only works in macros that are wikified and not, for example, when a macro is used as an attribute value. + +!!! Advantages of Accessing Parameters as Variables + +The primary advantage of the technique is that it avoids the parameter value being substituted into the macro as a literal string, which in turn can help avoid issues with parameters that contain quotes. + +For example, consider this macro. It invokes another macro using the single parameter as an argument for it: + +``` +\define film-quote(line) <$macrocall $name="anothermacro" actor="Bugs Bunny" line="""$line$"""/> +``` + +The code above will fail if the macro is invoked with the argument containing triple double quotes (for example `<<film-quote 'I quote thrice """ - see!?'>>`). Using parameter variables offers a workaround: + +``` +\define film-quote(line) <$macrocall $name="anothermacro" actor="Bugs Bunny" line=<<__line__>>/> +``` + +See [[Macro Pitfalls]] for more discussion. diff --git a/editions/tw5.com/tiddlers/wikitext/Macro Pitfalls.tid b/editions/tw5.com/tiddlers/wikitext/Macro Pitfalls.tid new file mode 100644 index 000000000..cd0ed4061 --- /dev/null +++ b/editions/tw5.com/tiddlers/wikitext/Macro Pitfalls.tid @@ -0,0 +1,39 @@ +created: 20220917091428117 +modified: 20230419103154328 +title: Macro Pitfalls +type: text/vnd.tiddlywiki + +! Introduction + +In the early days of TiddlyWiki, [[macros|Macros]] were the best way of encapsulating snippets for reuse, and so they were used extensively. However, they have always suffered from some significant disadvantages that can give rise to errors and poor performance. + +<<.from-version "5.3.0">> Macros have been joined by [[Procedures]], [[Custom Widgets]] and [[Functions]] which together provide more robust and flexible ways to encapsulate and re-use code. It is now recommended to only use macros when textual substitution is specifically required. + +! Shortcomings of Textual Substitution + +TiddlyWiki's handling of [[macro|Macros]] parameters is based on "textual substitution" which means that the string values of the parameters provided when calling a macro are plugged into the macro definition before it is wikified. + +Here's a typical example of the approach in early versions of TiddlyWiki 5. The intention is to provide a macro that takes a single parameter of the title of the tiddler to view: + +``` +\define mymacro(title) +<$codeblock code={{$title$}}/> +\end +``` + +That works for simple cases like `<<mymacro "HelloThere">>` but is subtly brittle. For example, the macro above would fail with tiddler titles containing double closing curly braces. Trying to use it with the title `foo}}bar` would lead to the macro being expanded to the following invalid syntax: + +``` +<$codeblock code={{foo}}bar}}/> +``` + +As a result of this issue, for many years the TiddlyWiki 5 user interface failed if a variety of combinations of special characters were encountered in tiddler titles. + +This issue has been mitigated over the years, particularly by providing access to the macro parameters as variables. However, for backwards compatibility, this was done without affecting the existing syntax, which required us to adopt the clumsy protocol of wrapping the parameter name in double underscores to get the name of the corresponding variable. + +! Performance of Global Macros + +Global [[Macro Definitions]] defined with the [[SystemTag: $:/tags/Macro]] suffer from poor performance because every macro has to be parsed regardless of whether it is actually used. + +Furthermore, the way that definitions are imported means that updating a tiddler tagged [[SystemTag: $:/tags/Macro]] will cause the entire page to be refreshed. + diff --git a/editions/tw5.com/tiddlers/wikitext/Macros in WikiText.tid b/editions/tw5.com/tiddlers/wikitext/Macros in WikiText.tid index a738d5389..16f05a22a 100644 --- a/editions/tw5.com/tiddlers/wikitext/Macros in WikiText.tid +++ b/editions/tw5.com/tiddlers/wikitext/Macros in WikiText.tid @@ -1,11 +1,7 @@ created: 20131205160746466 modified: 20150221094003000 -tags: WikiText +tags: title: Macros in WikiText type: text/vnd.tiddlywiki -caption: Macros -The use of [[macros|Macros]] in WikiText has two distinct aspects: - -* [[Defining macros|Macro Definitions in WikiText]] -* [[Calling macros|Macro Calls in WikiText]] +See [[Macros]]. \ No newline at end of file diff --git a/editions/tw5.com/tiddlers/wikitext/Styles and Classes in WikiText.tid b/editions/tw5.com/tiddlers/wikitext/Styles and Classes in WikiText.tid index 102a19836..eadbd2227 100644 --- a/editions/tw5.com/tiddlers/wikitext/Styles and Classes in WikiText.tid +++ b/editions/tw5.com/tiddlers/wikitext/Styles and Classes in WikiText.tid @@ -5,26 +5,36 @@ title: Styles and Classes in WikiText type: text/vnd.tiddlywiki caption: Styles and Classes -You can use this construction to cause the wrapped content to be assigned specified CSS classes or styles: +Content can be wrapped in `@@`double at signs`@@` to apply specified CSS styles or classes to it. There are multiple ways to use this syntax, as presented below. -<<wikitext-example src:"@@.myStyle -* List One -* List Two +Inline content wrapped in `@@`double at signs`@@` without specifying style or class will be assigned the `.tc-inline-style` and displayed as highlighted text. The foreground and background colours of the highlighted text are defined as `highlight-background` and `highlight-foreground` in the current palette. + +<<wikitext-example src:"@@some highlighted text@@">> + +Style attributes, e.g. `color`, each followed by `;` semicolon can be introduced immediately after the opening `@@`. + +<<wikitext-example src:"@@color:steelblue;background-color:lightcyan;some styled text@@">> + +Similarly a style can be applied to a multiline content: + +<<wikitext-example src:"@@background-color:lightcyan; +* Item one +* Item two @@ ">> -Similar syntax is used to assign styles. For example: +A class may be applied to a multiline content only: -<<wikitext-example src:"@@background-color:red; -* List One -* List Two -@@ -">> - -Multiple styles and classes can be mixed. For example: - -<<wikitext-example src:"@@.tc-tiddler-frame -@@width:400px; -Some text +<<wikitext-example src:"@@.tc-double-spaced-list +* Item one +* Item two +@@">> + +Multiple classes and styles can be used together: + +<<wikitext-example src:"@@.tc-double-spaced-list +@@width:400px;background-color:lightcyan; +* Item one +* Item two @@ ">> diff --git a/editions/tw5.com/tiddlers/wikitext/Transclusion and Substitution.tid b/editions/tw5.com/tiddlers/wikitext/Transclusion and Substitution.tid index c74c68855..8d0a52cdc 100644 --- a/editions/tw5.com/tiddlers/wikitext/Transclusion and Substitution.tid +++ b/editions/tw5.com/tiddlers/wikitext/Transclusion and Substitution.tid @@ -1,5 +1,5 @@ created: 20141018090608643 -modified: 20211117212543789 +modified: 20230419103154329 tags: WikiText title: Transclusion and Substitution type: text/vnd.tiddlywiki @@ -55,6 +55,6 @@ As described in [[Introduction to filter notation]], you can also transclude a v ! Textual Substitution -Textual substitution occurs when the value of a macro/variable is used. It is described in [[Macros in WikiText]]. +Textual substitution occurs when the value of a macro/variable is used. It is described in [[Macros]]. The key difference between substitution and transclusion is that substitution occurs before WikiText parsing. This means that you can use substitution to build WikiText constructions. Transclusions are processed independently, and cannot be combined with adjacent text to define WikiText constructions. diff --git a/editions/tw5.com/tiddlers/wikitext/Transclusion in WikiText.tid b/editions/tw5.com/tiddlers/wikitext/Transclusion in WikiText.tid index f7de5d83d..838cd0ade 100644 --- a/editions/tw5.com/tiddlers/wikitext/Transclusion in WikiText.tid +++ b/editions/tw5.com/tiddlers/wikitext/Transclusion in WikiText.tid @@ -12,6 +12,8 @@ You can incorporate the content of one tiddler within another using the [[Transc * `{{MyTiddler}}` transcludes a single tiddler * `{{MyTiddler||TemplateTitle}}` displays the tiddler through a specified [[TemplateTiddler|TemplateTiddlers]] * `{{||TemplateTitle}}` displays the specified template tiddler without altering the [[current tiddler|Current Tiddler]] +* `{{MyTiddler|Parameter}}` transcludes a single tiddler with a single parameter +* `{{MyTiddler||TemplateTitle|Parameter|SecondParameter}}` transcludes a single tiddler through a specified [[TemplateTiddler|TemplateTiddlers]] with two parameters !! Transcluding Text References @@ -37,7 +39,7 @@ The WikiText transclusion syntax generates a TiddlerWidget wrapped around a Tran ``` <$tiddler tiddler="MyTiddler"> -<$transclude tiddler="MyTemplate" field="myField"/> +<$transclude $tiddler="MyTemplate" $field="myField"/> </$tiddler> ``` diff --git a/editions/tw5.com/tiddlers/wikitext/Variables in WikiText.tid b/editions/tw5.com/tiddlers/wikitext/Variables in WikiText.tid index b2c103507..a412031c3 100644 --- a/editions/tw5.com/tiddlers/wikitext/Variables in WikiText.tid +++ b/editions/tw5.com/tiddlers/wikitext/Variables in WikiText.tid @@ -1,36 +1,7 @@ -caption: Variables created: 20141002141231992 modified: 20150221221850000 -tags: WikiText +tags: title: Variables in WikiText type: text/vnd.tiddlywiki -See also the [[introduction to the concept of variables|Variables]]. - -To transclude the value of a variable, use the [[macro call syntax|Macro Calls in WikiText]] with no parameters. You can also use a <<.wlink MacroCallWidget>> widget. - -A [[macro|Macros]] snippet can contain `$(name)$` as a [[placeholder|Macro Definitions in WikiText]] for which the value of the variable of that name will be substituted. - -A variable's value can be used as a [[filter parameter|Filter Parameter]], or as a [[widget attribute|Widgets in WikiText]]. The latter supports macro parameters. - -!! Example: defining a variable - -<$macrocall $name=".example" n="1" -eg="""<$set name=animal value=zebra> -<<animal>> -</$set>"""/> - -!! Example: defining a macro - -The `\define` pragma below [[defines a macro|Macros in WikiText]] called <<.var tags-of-current-tiddler>>. The macro returns the value of the tiddler's <<.field tags>> field, and can be accessed from anywhere else in the same tiddler (or in any tiddler that [[imports|ImportVariablesWidget]] it). - -<$importvariables filter="$:/editions/tw5.com/macro-examples/tags-of-current-tiddler"> -<$codeblock code={{$:/editions/tw5.com/macro-examples/tags-of-current-tiddler}}/> -<$macrocall $name=".example" n="2" eg="""The tags are: <<tags-of-current-tiddler>>"""/> -</$importvariables> - -!! Example: using a variable as a filter parameter - -This example uses the <<.olink backlinks>> [[operator|Filter Operators]] to list all tiddlers that link to this one. - -<$macrocall $name=".example" n="3" eg="""<<list-links filter:"[<currentTiddler>backlinks[]]">>"""/> +See [[Variables]]. \ No newline at end of file diff --git a/editions/tw5.com/tiddlers/wikitext/parser/Inline Mode WikiText.tid b/editions/tw5.com/tiddlers/wikitext/parser/Inline Mode WikiText.tid index 88afd8372..3e04a01ac 100644 --- a/editions/tw5.com/tiddlers/wikitext/parser/Inline Mode WikiText.tid +++ b/editions/tw5.com/tiddlers/wikitext/parser/Inline Mode WikiText.tid @@ -1,6 +1,6 @@ caption: inline parser mode created: 20220111000108618 -modified: 20220122182842036 +modified: 20220917074925230 tags: [[WikiText Parser Modes]] title: Inline Mode WikiText type: text/vnd.tiddlywiki @@ -14,13 +14,13 @@ These WikiText types can be expressed without an entire line of text. They aren' * [[HTML in WikiText]] * [[Images in WikiText]] * [[Linking in WikiText]] -* [[Macro Calls in WikiText]] +* [[Macro Calls]] * [[Styles and Classes in WikiText]] (single line version only) * [[Transclusion in WikiText]] * [[Variables in WikiText]] * [[Widgets in WikiText]] -<<.tip """[[Macro Calls in WikiText]] and [[Transclusion in WikiText]] will be recognised in block mode if the macro call or transclusion spans an entire line.""">> +<<.tip """[[Macro Calls]] and [[Transclusion in WikiText]] will be recognised in block mode if the macro call or transclusion spans an entire line.""">> <<.tip """The other ''inline mode'' WikiText types are technically <<.em only>> detected while the parser is in ''inline mode''. However, the opening punctuation will also trigger the start of [[Paragraphs in WikiText]] which will automatically cause the parser to go into ''inline mode''. Therefore, practically speaking, it is just as useful to consider these WikiText types as recognised while the parser is in either ''inline mode'' or ''block mode''""">> While processing the //enclosed// text of some of these WikiText types, the parser [[will not look for new WikiText|Places where the parser ignores WikiText]]. But for rest of these WikiText types, the parser will continue in ''inline mode'' for the //enclosed// text. While parsing that text, it might encounter something which [[moves it to block mode|WikiText parser mode transitions]]. \ No newline at end of file diff --git a/editions/tw5.com/tiddlers/wikitext/parser/Places where the parser ignores WikiText.tid b/editions/tw5.com/tiddlers/wikitext/parser/Places where the parser ignores WikiText.tid index afb9db192..d52193148 100644 --- a/editions/tw5.com/tiddlers/wikitext/parser/Places where the parser ignores WikiText.tid +++ b/editions/tw5.com/tiddlers/wikitext/parser/Places where the parser ignores WikiText.tid @@ -8,7 +8,7 @@ type: text/vnd.tiddlywiki Text enclosed by these constructs is skipped by the parser and WikiText punctuation will be ignored: |[[Code Blocks in WikiText]]|One of the main purposes of code blocks is to suppress wikitext expansion. Once the code block starts, the parser will ignore all WikiText punctuation until the code block ends.| -|[[Images in WikiText]]|`[[img|literal image link text]]` - the text enclosed by square braces will be ignored. This means, for example, [[transclusions|Transclusion in WikiText]] and [[macro calls|Macro Calls in WikiText]] cannot be used to dynamically construct the link text| -|[[Linking in WikiText]]|`[[literal link target|literal link text]]` - the text enclosed by square braces will be ignored. This means, for example, [[transclusions|Transclusion in WikiText]] and [[macro calls|Macro Calls in WikiText]] cannot be used to dynamically construct the link target or the link text| -|[[Macro Calls in WikiText]]|`<<mymacro ''notbold'' "literal text" "<<macro_expansion_ignored>>" {{transclusion_ignored}}>>` - while processing the text enclosed by a macro call, the parser will follow special rules for detecting macro parameters. These rules do not include detection of WikiText. However, after the parameters are substituted into the macro definition, the result will be parsed using [[normal rules|Wiki Text Parser Modes]]. This will likely result in the detection of any WikiText.| +|[[Images in WikiText]]|`[[img|literal image link text]]` - the text enclosed by square braces will be ignored. This means, for example, [[transclusions|Transclusion in WikiText]] and [[macro calls|Macro Calls]] cannot be used to dynamically construct the link text| +|[[Linking in WikiText]]|`[[literal link target|literal link text]]` - the text enclosed by square braces will be ignored. This means, for example, [[transclusions|Transclusion in WikiText]] and [[macro calls|Macro Calls]] cannot be used to dynamically construct the link target or the link text| +|[[Macro Calls]]|`<<mymacro ''notbold'' "literal text" "<<macro_expansion_ignored>>" {{transclusion_ignored}}>>` - while processing the text enclosed by a macro call, the parser will follow special rules for detecting macro parameters. These rules do not include detection of WikiText. However, after the parameters are substituted into the macro definition, the result will be parsed using [[normal rules|Wiki Text Parser Modes]]. This will likely result in the detection of any WikiText.| diff --git a/editions/tw5.com/tiddlers/wikitext/parser/WikiText Parser Modes.tid b/editions/tw5.com/tiddlers/wikitext/parser/WikiText Parser Modes.tid index 8056b9493..bd408b977 100644 --- a/editions/tw5.com/tiddlers/wikitext/parser/WikiText Parser Modes.tid +++ b/editions/tw5.com/tiddlers/wikitext/parser/WikiText Parser Modes.tid @@ -6,7 +6,7 @@ type: text/vnd.tiddlywiki In order to display Tiddlers (usually the text field), the WikiText parser reads and interprets the content and applies WikiText rules. The parser has three modes: -* ''pragma mode'' - the parser will recognise only [[pragma mode WikiText|Pragma]] punctuation +* ''pragma mode'' - the parser will recognise only [[pragma mode WikiText|Pragmas]] punctuation * ''block mode'' - the parser will recognise only [[block mode WikiText|Block Mode WikiText]] punctuation * ''inline mode'' - the parser will recognise only [[inline mode WikiText|Inline Mode WikiText]] diff --git a/editions/tw5.com/tiddlers/wikitext/parser/WikiText parser mode transitions.tid b/editions/tw5.com/tiddlers/wikitext/parser/WikiText parser mode transitions.tid index 009c3d3f3..6150fbf63 100644 --- a/editions/tw5.com/tiddlers/wikitext/parser/WikiText parser mode transitions.tid +++ b/editions/tw5.com/tiddlers/wikitext/parser/WikiText parser mode transitions.tid @@ -27,11 +27,11 @@ This is a <<.em rough>> diagram whose lines mostly correspond to the parser mode By default the parser starts in [[block mode|Block Mode WikiText]]. However, a tiddler can instead be transcluded with [[inline mode|Inline Mode WikiText]] in which case [[block mode WikiText|Block Mode WikiText]] will not be recognised. -At the start of text only, the parser will also recognise any [[pragma mode WikiText|Pragma]]. +At the start of text only, the parser will also recognise any [[pragma mode WikiText|Pragmas]]. !! Transitions from pragma mode -At the start of text, the parser will recognise any [[pragma|Pragma]]. If none are found then it will move to [[inline|Inline Mode WikiText]] or [[block|Block Mode WikiText]] mode depending on the transclusion mode. If any [[pragma|Pragma]] are found then it will continue looking for [[pragma|Pragma]] until it finds one or more blank lines not followed by the start of a new pragma. +At the start of text, the parser will recognise any [[pragma|Pragmas]]. If none are found then it will move to [[inline|Inline Mode WikiText]] or [[block|Block Mode WikiText]] mode depending on the transclusion mode. If any [[pragma|Pragmas]] are found then it will continue looking for [[pragma|Pragmas]] until it finds one or more blank lines not followed by the start of a new pragma. !! Transitions from block mode diff --git a/editions/tw5.com/tiddlers/wikitext/parser/WikiText parser mode_ macro examples.tid b/editions/tw5.com/tiddlers/wikitext/parser/WikiText parser mode_ macro examples.tid index 07a08db46..7224ddb81 100644 --- a/editions/tw5.com/tiddlers/wikitext/parser/WikiText parser mode_ macro examples.tid +++ b/editions/tw5.com/tiddlers/wikitext/parser/WikiText parser mode_ macro examples.tid @@ -25,7 +25,7 @@ then </$macrocall>""">> </tbody></table> -The list syntax is recognised in [[block mode|Block Mode WikiText]] and the enclosed contents are parsed using [[inline mode|Inline Mode WikiText]]. When the parser encounters a [[wikitext macro call|Macro Calls in WikiText]] it will use the current parse mode to parse the contents of the macro. The contents of the macro contains table syntax which is only recognised in [[block mode|Block Mode WikiText]]. +The list syntax is recognised in [[block mode|Block Mode WikiText]] and the enclosed contents are parsed using [[inline mode|Inline Mode WikiText]]. When the parser encounters a [[wikitext macro call|Macro Calls]] it will use the current parse mode to parse the contents of the macro. The contents of the macro contains table syntax which is only recognised in [[block mode|Block Mode WikiText]]. Therefore, in #1 above the table syntax is not recognised. In #2 above, the blank line after the open `div` tag moves the parser back into [[block mode|Block Mode WikiText]], the macro call inherits it and the table is recognised. diff --git a/editions/tw5.com/tiddlywiki.info b/editions/tw5.com/tiddlywiki.info index 1de8bdc87..7379908ee 100644 --- a/editions/tw5.com/tiddlywiki.info +++ b/editions/tw5.com/tiddlywiki.info @@ -52,7 +52,7 @@ "--render","[!is[system]]","[encodeuricomponent[]addprefix[static/]addsuffix[.html]]","text/plain","$:/core/templates/static.tiddler.html", "--render","$:/core/templates/static.template.css","static/static.css","text/plain"], "external-js": [ - "--render","$:/core/save/offline-external-js","index.html","text/plain", + "--render","$:/core/save/offline-external-js","[[external-]addsuffix<version>addsuffix[.html]]","text/plain", "--render","$:/core/templates/tiddlywiki5.js","[[tiddlywikicore-]addsuffix<version>addsuffix[.js]]","text/plain"] }, "config": { diff --git a/licenses/cla-individual.md b/licenses/cla-individual.md index 290fa85f5..df194361e 100644 --- a/licenses/cla-individual.md +++ b/licenses/cla-individual.md @@ -519,3 +519,13 @@ Scott Sauye, @CrossEye, 2023-01-04 Marcus Winter, @yaisog, 2023-01-07 Ethan Weller, @gamedungeon, 2023-01-17 + +Mateusz Wilczek, @mateuszwilczek, 2023/02/16 + +Andrea Octo, @andrigamerita, 2023/02/24 + +HuanC Fu, @hffqyd, 2023/03/03 + +Michelle Saad, @michsa, 2023-03-08 + +Yukai Chou, @muzimuzhi, 2023-04-07 diff --git a/package.json b/package.json index 1d0d46415..3d9444256 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "tiddlywiki", "preferGlobal": "true", - "version": "5.2.6-prerelease", + "version": "5.3.0-prerelease", "author": "Jeremy Ruston <jeremy@jermolene.com>", "description": "a non-linear personal web notebook", "contributors": [ diff --git a/plugins/tiddlywiki/dynannotate/config/LegacySelectionTracker.tid b/plugins/tiddlywiki/dynannotate/config/LegacySelectionTracker.tid new file mode 100644 index 000000000..83a547633 --- /dev/null +++ b/plugins/tiddlywiki/dynannotate/config/LegacySelectionTracker.tid @@ -0,0 +1,3 @@ +title: $:/config/Dynannotate/LegacySelectionTracker/Enable + +no diff --git a/plugins/tiddlywiki/dynannotate/config/SelectionTracker.tid b/plugins/tiddlywiki/dynannotate/config/SelectionTracker.tid new file mode 100644 index 000000000..6162c992c --- /dev/null +++ b/plugins/tiddlywiki/dynannotate/config/SelectionTracker.tid @@ -0,0 +1,3 @@ +title: $:/config/Dynannotate/SelectionTracker/Enable + +no diff --git a/plugins/tiddlywiki/dynannotate/docs/readme.tid b/plugins/tiddlywiki/dynannotate/docs/readme.tid index 487c25561..ff0483a79 100644 --- a/plugins/tiddlywiki/dynannotate/docs/readme.tid +++ b/plugins/tiddlywiki/dynannotate/docs/readme.tid @@ -25,7 +25,7 @@ The `<$dynannotate>` widget uses the selection tracker to support a popup that d |popup |Popup state tiddler to be used to trigger a popup when an annotation is clicked | |search |Search text to be highlighted within the widget | |searchDisplay |"overlay" or "snippet" (see below) | -|searchMode |"normal" (default), "regexp" or "whitespace" (see below) | +|searchMode |"literal" (default), "regexp", "whitespace", "words" or "some" (see below) | |searchMinLength |Optional minimum length of search string | |searchCaseSensitive |"yes" (the default) for a case sensitive search, or "no" for a case insensitive search| |searchClass |Optional CSS class to be added to search overlays | @@ -46,9 +46,10 @@ The values supported by the `searchDisplay` attribute are: The search modes supported by the `searchMode` attribute are: -* `normal` - a literal string of plain text to match +* `literal` or `normal` - a literal string of plain text to match (default). * `regexp` - a JavaScript-style regular expression (without the quoting backslashes and flags) -* `whitespace` - a literal string to match while normalising runs of whitespace. This allows `a. b` to match `a. b` +* `whitespace` - a literal string to match while normalising runs of whitespace. Thus `A B` matches `A B`. +* `words` or `some` - treats the search string as a list of tokens separated by whitespace, and matches all tokens (regardless of ordering and whether there is other text in between) When the selection popup is triggered, the currently selected text can be found in the tiddler named in the `selection` attribute, with the disambiguating prefix and suffix in the tiddlers named in the `selectionPrefix` and `selectionPopup` tiddlers. Note that the selection text will be an empty string if the selection popup was triggered in response to a click (ie zero width selection). @@ -95,7 +96,7 @@ Note that using the `annotate-tiddler` field to associate an annotation with the !! Selection Trackers -The following configuration tiddlers can be used to control whether the selection trackers are enabled when the following configuration tiddlers are set to ''yes'' (the default). +The selection trackers are enabled when the following configuration tiddlers are set to ''yes''. * $:/config/Dynannotate/SelectionTracker/Enable for the main selection tracker * $:/config/Dynannotate/LegacySelectionTracker/Enable for the legacy selection tracker diff --git a/plugins/tiddlywiki/dynannotate/examples/simple.tid b/plugins/tiddlywiki/dynannotate/examples/simple.tid index aa1837b78..59a8d7e1d 100644 --- a/plugins/tiddlywiki/dynannotate/examples/simple.tid +++ b/plugins/tiddlywiki/dynannotate/examples/simple.tid @@ -10,16 +10,33 @@ caption: Simple $example$ \end +\define search-example-code() +<!-- +The inline filters update the displayed codeblock to reflect the choices the user has made in the UI. +The rules pragma is used here to evaluate only these filters, but leave everything else untouched. +The tabs and linebreaks within the parameters to addprefix, though maybe confusing, help with the readability of the codeblock output. +--> +\rules only filteredtranscludeinline +<$dynannotate + search="{{{ [{$:/temp/dynannotate-example/search}!is[blank]else[The human mind]] }}}"{{{ [{$:/temp/dynannotate-example/searchMode}!search::some[literal normal]addprefix[ + searchMode="]addsuffix["]] }}} + searchCaseSensitive="{{{ [{$:/temp/dynannotate-example/searchCaseSensitive}!is[blank]else[yes]] }}}"{{{ [{$:/temp/dynannotate-example/searchClass}!is[blank]addprefix[ + searchClass="]addsuffix["]] }}} +> +<$transclude tiddler="$:/plugins/tiddlywiki/dynannotate/example-text-1" mode="block"/> +<$transclude tiddler="$:/plugins/tiddlywiki/dynannotate/example-text-2" mode="block"/> +</$dynannotate> +\end + <div class="tc-dynannotation-example-info"> -!! Simple annotation +!! Annotations with `target` -We use the `target*` attributes to specify a target string for the annotation and optionally a prefix and suffix for disambiguating multiple occurances. +We use the `target*` attributes to specify a target string for the annotation and optionally a prefix and suffix for disambiguating multiple occurences. </div> -<<show-example """ -<$dynannotate +<<show-example """<$dynannotate target="the" targetPrefix="Yet " targetSuffix=" speed" @@ -30,55 +47,35 @@ We use the `target*` attributes to specify a target string for the annotation an <div class="tc-dynannotation-example-info"> -!! Plain text searching +!! Highlights with `search` -We use the `search` attribute to specify a search string for highlighting: +We use the `search` attribute to specify a search string for highlighting. + +The search type can be set with the `searchMode` and `searchCaseSensitive` attributes. + +We can style the highlights with the `searchClass` attribute, which has some predefined values. </div> -<<show-example """ +|tc-table-no-border tc-dynannotate-search-parameters|k +|search term |<$edit-text tiddler="$:/temp/dynannotate-example/search" field="text" tag="input" default="The human mind" />| +|search mode |<$select tiddler="$:/temp/dynannotate-example/searchMode" field="text" default="literal"><option value="literal">literal</option><option value="normal">normal</option><option value="regexp">regexp</option><option value="whitespace">whitespace</option><option value="some">some</option><option value="words">words</option></$select> | +|case sensitive |<$checkbox tiddler="$:/temp/dynannotate-example/searchCaseSensitive" field="text" checked="yes" unchecked="no" default="yes"> <$text text={{{ [{$:/temp/dynannotate-example/searchCaseSensitive}!is[blank]else[yes]] }}} /></$checkbox> | +|search class |<$select tiddler="$:/temp/dynannotate-example/searchClass" field="text" default=""><option value="">(none)</option><option value="tc-dynannotation-search-overlay-animated">tc-dynannotation-search-overlay-animated</option><option value="tc-dynannotation-search-overlay-blurred">tc-dynannotation-search-overlay-blurred</option></$select> | + <$dynannotate - search="the" + search={{{ [{$:/temp/dynannotate-example/search}!is[blank]else[The human mind]] }}} + searchMode={{{ [{$:/temp/dynannotate-example/searchMode}] }}} + searchCaseSensitive={{{ [{$:/temp/dynannotate-example/searchCaseSensitive}!is[blank]else[yes]] }}} + searchClass={{{ [{$:/temp/dynannotate-example/searchClass}] }}} > <$transclude tiddler="$:/plugins/tiddlywiki/dynannotate/example-text-1" mode="block"/> +<$transclude tiddler="$:/plugins/tiddlywiki/dynannotate/example-text-2" mode="block"/> </$dynannotate> -""">> -<div class="tc-dynannotation-example-info"> - -!! Regular expression searching - -We use the `mode` attribute set to `regexp` to highlight matches of a regular expression: - -</div> - -<<show-example """ -<$dynannotate - search="the|an" - searchMode="regexp" - searchClass="tc-dynannotation-search-overlay-blurred" -> -<$transclude tiddler="$:/plugins/tiddlywiki/dynannotate/example-text-1" mode="block"/> -</$dynannotate> -""">> - -<div class="tc-dynannotation-example-info"> - -!! Normalised whitespace searching - -We use the `mode` attribute set to `whitespace` to search for a string with whitespace normalised (ie runs of whitespace are collapsed to a single space for matching purposes): - -</div> - -<<show-example """ -<$dynannotate - search="does not work that way. It operates" - searchMode="whitespace" - searchClass="tc-dynannotation-search-overlay-animated" -> -<$transclude tiddler="$:/plugins/tiddlywiki/dynannotate/example-text-1" mode="block"/> -</$dynannotate> -""">> +<$wikify name="wikifiedCode" text=<<search-example-code>> mode="block" output="text"> +<$codeblock code=<<wikifiedCode>>/> +</$wikify> <div class="tc-dynannotation-example-info"> @@ -90,8 +87,7 @@ Annotation tiddlers can be used to describe annotations. This example references <<list-links "[all[shadows+tiddlers]annotate-tiddler[$:/plugins/tiddlywiki/dynannotate/example-text-1]]">> -<<show-example """ -<$dynannotate +<<show-example """<$dynannotate filter="[all[shadows+tiddlers]annotate-tiddler[$:/plugins/tiddlywiki/dynannotate/example-text-1]]" > <$transclude tiddler="$:/plugins/tiddlywiki/dynannotate/example-text-1" mode="block"/> diff --git a/plugins/tiddlywiki/dynannotate/examples/viewtemplate-text.tid b/plugins/tiddlywiki/dynannotate/examples/viewtemplate-text.tid index 15588c420..81c3c2b25 100644 --- a/plugins/tiddlywiki/dynannotate/examples/viewtemplate-text.tid +++ b/plugins/tiddlywiki/dynannotate/examples/viewtemplate-text.tid @@ -34,6 +34,7 @@ title: $:/plugins/tiddlywiki/dynannotate/examples/viewtemplate/text selectionPopup={{{ [<currentTiddler>addprefix[$:/state/dynannotate/popup-selection/]] }}} search={{$:/temp/search}} searchClass="tc-dynannotation-search-overlay-blurred" + searchCaseSensitive="no" searchMinLength={{$:/config/Search/MinLength}} > <$transclude mode="block"> diff --git a/plugins/tiddlywiki/dynannotate/examples/viewtemplate.tid b/plugins/tiddlywiki/dynannotate/examples/viewtemplate.tid index a0b99eb79..150a6f88f 100644 --- a/plugins/tiddlywiki/dynannotate/examples/viewtemplate.tid +++ b/plugins/tiddlywiki/dynannotate/examples/viewtemplate.tid @@ -1,28 +1,69 @@ -title: $:/plugins/tiddlywiki/dynannotate/examples/viewtemplate -tags: $:/tags/dynannotateExamples caption: View Template +tags: $:/tags/dynannotateExamples +title: $:/plugins/tiddlywiki/dynannotate/examples/viewtemplate + +\define show-example(example) +<$codeblock code=<<__example__>>/> + +//''Displays as:''// + +$example$ +\end <div class="tc-dynannotation-example-info"> !! Using Dynannotate in the view template -This example shows how to override the core view template with a custom template that includes dynannotate. It is disabled by default but can be enabled by clicking the button below. (Clicking the button below copies the custom view template from $:/plugins/tiddlywiki/dynannotate/examples/viewtemplate/text to $:/core/ui/ViewTemplate/body). +This example shows how to override the core view template with a custom template that includes dynannotate. It is disabled by default but can be enabled by clicking the corresponding button below. The example transcludes the [[Searching in TiddlyWiki|$:/plugins/tiddlywiki/dynannotate/searching-in-tiddlywiki]] tiddler for illustration purposes, but the chosen view template is applied to all open tiddlers. -Once enabled, this example demonstrates several features: +Once enabled, this example demonstrates several features of Dynannotate: -* Highlighting of search results within tiddler bodies -* Creating annotations on any tiddler by selecting text and then clicking a colour in the resulting dropdown +* Highlight text within tiddler bodies -- any text entered in the sidebar search input will be highlighted (in all tiddlers) +* Create annotations (on any tiddler) by selecting text and then clicking //Create annotation// in the resulting dropdown + +(Clicking the buttons below either puts the custom body view template [[$:/plugins/tiddlywiki/dynannotate/examples/viewtemplate/text]] in front of the default in the [[View Template Body Cascade|https://tiddlywiki.com/#View%20Template%20Body%20Cascade]] or removes it from the cascade). </div> <$button> -<$action-setfield $tiddler="$:/config/ViewTemplateTitleFilters/dynannotate" tags="$:/tags/ViewTemplateTitleFilter" text="[[$:/plugins/tiddlywiki/dynannotate/examples/viewtemplate/text]]" list-before="$:/config/ViewTemplateBodyFilters/default"/> +<$action-setfield $tiddler="$:/config/ViewTemplateBodyFilters/dynannotate" tags="$:/tags/ViewTemplateBodyFilter" text="[[$:/plugins/tiddlywiki/dynannotate/examples/viewtemplate/text]]" list-before="$:/config/ViewTemplateBodyFilters/default"/> Click here to use the custom view template </$button> <$button> -<$action-deletetiddler $tiddler="$:/config/ViewTemplateTitleFilters/dynannotate"/> +<$action-deletetiddler $tiddler="$:/config/ViewTemplateBodyFilters/dynannotate"/> Click here to revert to the core view template </$button> -<$codeblock code={{$:/plugins/tiddlywiki/dynannotate/examples/viewtemplate/text}}/> \ No newline at end of file +<p/> + +<div class="tc-dynannotation-example-info"> + +!! Using Dynannotate to highlight text on a per-tiddler basis + +Using state tiddlers containing the text which is to be highlighted, Dynannotate highlights can be applied on a per-tiddler basis when used in the body view template. This can also be combined with the [[GenesisWidget]] to insert the Dynannotate widget into the DOM only when such a highlight is configured. + +This example uses a transcluded tiddler, but Dynannotate could be added to the view template (to show highlights in all parts of a tiddler) or to the body view template (to show highlights only in the tiddler body) in the same way. Note how in this example, Dynannotate only affects the transcluded content. + +</div> + +<<show-example """<$button set="$:/state/dynannotate/examples/viewtemplate" setTo="tiddler">Highlight "tiddler"</$button> +<$button set="$:/state/dynannotate/examples/viewtemplate" setTo="created">Highlight "created"</$button> +<$button set="$:/state/dynannotate/examples/viewtemplate" setTo="">Clear highlights</$button> +<p/> +<$let dynannotateText={{$:/state/dynannotate/examples/viewtemplate}}> + <$genesis $type={{{ [<dynannotateText>!is[blank]then[$dynannotate]] }}} + search=<<dynannotateText>> + searchDisplay="overlay" + searchClass="tc-dynannotation-search-overlay-animated" + searchCaseSensitive="no"> + <div class="tc-dynannotate-example-frame"> + + !! `$:/core/ui/ControlPanel/TiddlerFields`: + <$transclude tiddler="$:/core/ui/ControlPanel/TiddlerFields" mode="block" /> + </div> + </$genesis> +</$let> +""">> + +When used in the view template, the state tiddler title could be derived from the current tiddler, e.g. `<$let dynannotateText={{{ [<currentTiddler>addprefix[$:/state/dynannotate/]get[text]] }}}>`, to configure highlights for each tiddler separately. diff --git a/plugins/tiddlywiki/dynannotate/modules/textmap.js b/plugins/tiddlywiki/dynannotate/modules/textmap.js index 9f9dbbbe3..934ceb0ff 100644 --- a/plugins/tiddlywiki/dynannotate/modules/textmap.js +++ b/plugins/tiddlywiki/dynannotate/modules/textmap.js @@ -15,7 +15,7 @@ Structure for modelling mapping between a string and its representation in the D var PREFIX_SUFFIX_LENGTH = 50; /* -Build a map of the text content of a dom node and its descendents: +Build a map of the text content of a DOM node and its descendants: string: concatenation of the text content of child nodes metadata: array of {start,end,domNode} where start and end identify position in the string @@ -60,7 +60,7 @@ exports.TextMap.prototype.locateMetadata = function(position) { }; /* -Search for the first occurance of a target string within the textmap of a dom node +Search for the first occurrence of a target string within the textmap of a DOM node Returns an object with the following properties: startNode: node containing the start of the text @@ -92,10 +92,10 @@ exports.TextMap.prototype.findText = function(targetString,targetPrefix,targetSu }; /* -Search for all occurances of a string within the textmap of a dom node +Search for all occurrences of a string within the textmap of a DOM node Options include: - mode: "normal", "regexp" or "whitespace" + mode: "normal", "literal", "regexp", "whitespace", "some" or "words" caseSensitive: true if the search should be case sensitive Returns an array of objects with the following properties: @@ -121,6 +121,11 @@ exports.TextMap.prototype.search = function(searchString,options) { regExpString = "(" + searchString.split(/\s+/g).filter(function(word) { return !!word }).map($tw.utils.escapeRegExp).join("\\s+") + ")"; + } else if(options.mode === "words" || options.mode === "some") { + // Match any word separated by whitespace + regExpString = "(" + searchString.split(/\s+/g).filter(function(word) { + return !!word + }).map($tw.utils.escapeRegExp).join("|") + ")"; } else { // Normal search regExpString = "(" + $tw.utils.escapeRegExp(searchString) + ")"; diff --git a/plugins/tiddlywiki/dynannotate/styles.tid b/plugins/tiddlywiki/dynannotate/styles.tid index cd635eed5..8b13eba58 100644 --- a/plugins/tiddlywiki/dynannotate/styles.tid +++ b/plugins/tiddlywiki/dynannotate/styles.tid @@ -34,6 +34,16 @@ tags: [[$:/tags/Stylesheet]] animation: ta-dynannotation-search-overlay-animated 12s linear infinite; } +.tc-dynannotate-example-frame { + border: 1px solid black; + border-radius: 20px; + padding: 1em; +} + +.tc-control-panel table.tc-dynannotate-search-parameters, .tc-control-panel table.tc-dynannotate-search-parameters input { + width: initial; +} + .tc-dynannotate-snippet-highlight { background: #efef53; } diff --git a/plugins/tiddlywiki/filesystem/filesystemadaptor.js b/plugins/tiddlywiki/filesystem/filesystemadaptor.js index 0692fb2fe..1779855df 100644 --- a/plugins/tiddlywiki/filesystem/filesystemadaptor.js +++ b/plugins/tiddlywiki/filesystem/filesystemadaptor.js @@ -140,7 +140,7 @@ FileSystemAdaptor.prototype.deleteTiddler = function(title,callback,options) { } } // Remove the tiddler from self.boot.files & return null adaptorInfo - self.deleteTiddlerInCache(title); + self.removeTiddlerFileInfo(title); return callback(null,null); }); } else { @@ -151,8 +151,8 @@ FileSystemAdaptor.prototype.deleteTiddler = function(title,callback,options) { /* Delete a tiddler in cache, without modifying file system. */ -FileSystemAdaptor.prototype.deleteTiddlerInCache = function(title) { - // Only delete the tiddler if we have writable information for the file +FileSystemAdaptor.prototype.removeTiddlerFileInfo = function(title) { + // Only delete the tiddler info if we have writable information for the file if(this.boot.files[title]) { delete this.boot.files[title]; }; diff --git a/plugins/tiddlywiki/markdown/wrapper.js b/plugins/tiddlywiki/markdown/wrapper.js index cceb39138..98c5c2ae3 100755 --- a/plugins/tiddlywiki/markdown/wrapper.js +++ b/plugins/tiddlywiki/markdown/wrapper.js @@ -6,17 +6,13 @@ module-type: parser Wraps up the markdown-it parser for use as a Parser in TiddlyWiki \*/ -(function(realRequire){ +(function(){ /*jslint node: true, browser: true */ /*global $tw: false */ "use strict"; -var require = function(m) { - return realRequire("$:/plugins/tiddlywiki/markdown/" + m + ".js"); -}; - -var MarkdownIt = require("markdown-it"); +var MarkdownIt = require("./markdown-it"); function parseAsBoolean(tiddlerName) { return $tw.wiki.getTiddlerText(tiddlerName,"false").trim().toLowerCase() === "true"; @@ -61,8 +57,10 @@ function setupWikiRules(pluginOptions) { return rulesInfo; } + var WikiParser = require("$:/core/modules/parsers/wikiparser/wikiparser.js")["text/vnd.tiddlywiki"]; + // first pass: get all rule classes - var wikiParser = new $tw.Wiki.parsers["text/vnd.tiddlywiki"](null, '', {parseAsInline: true, wiki: $tw.wiki}); + var wikiParser = new WikiParser(null, '', {parseAsInline: true, wiki: $tw.wiki}); // restore all possible rules from each rule class wikiParser.pragmaRules = collectAllRules(wikiParser.pragmaRuleClasses,'pragma'); @@ -100,12 +98,12 @@ function setupWikiRules(pluginOptions) { // Creates markdown-it parser function createMarkdownEngine(markdownItOptions, pluginOptions) { var md = new MarkdownIt(markdownItOptions) - .use(require("markdown-it-sub")) - .use(require("markdown-it-sup")) - .use(require("markdown-it-ins")) - .use(require("markdown-it-mark")) - .use(require("markdown-it-footnote")) - .use(require("markdown-it-deflist")); + .use(require("./markdown-it-sub")) + .use(require("./markdown-it-sup")) + .use(require("./markdown-it-ins")) + .use(require("./markdown-it-mark")) + .use(require("./markdown-it-footnote")) + .use(require("./markdown-it-deflist")); var results = setupWikiRules(pluginOptions); @@ -116,10 +114,10 @@ function createMarkdownEngine(markdownItOptions, pluginOptions) { MarkdownParser.prototype.inlineRules = results.inlineRules; if(pluginOptions.renderWikiText && $tw.modules.titles["$:/plugins/tiddlywiki/katex/katex.min.js"]) { - md.use(require("markdown-it-katex")); + md.use(require("./markdown-it-katex")); } - md.use(require("markdown-it-tiddlywiki"),{ + md.use(require("./markdown-it-tiddlywiki"),{ renderWikiText: pluginOptions.renderWikiText, blockRules: results.blockRules, inlineRules: results.inlineRules @@ -263,4 +261,4 @@ function MarkdownParser(type,text,options) { exports["text/markdown"] = MarkdownParser; exports["text/x-markdown"] = MarkdownParser; -})(require); +})(); diff --git a/plugins/tiddlywiki/railroad/doc/example-transclusion.tid b/plugins/tiddlywiki/railroad/doc/example-transclusion.tid new file mode 100644 index 000000000..f8d1144b1 --- /dev/null +++ b/plugins/tiddlywiki/railroad/doc/example-transclusion.tid @@ -0,0 +1,3 @@ +title: $:/plugins/tiddlywiki/railroad/example-transclusion + +"railroad transclusion example" text \ No newline at end of file diff --git a/plugins/tiddlywiki/railroad/doc/syntax.tid b/plugins/tiddlywiki/railroad/doc/syntax.tid index fc0d8d87f..0e6e809dd 100644 --- a/plugins/tiddlywiki/railroad/doc/syntax.tid +++ b/plugins/tiddlywiki/railroad/doc/syntax.tid @@ -2,6 +2,7 @@ created: 20150103184022184 modified: 20150119220342000 title: $:/plugins/tiddlywiki/railroad/syntax + The railroad widget uses a special notation to construct the components defined below. `x` and `y` here stand for any component. @@ -12,9 +13,28 @@ Names (as opposed to quoted strings) are available when a value starts with a le ; sequence : <$railroad text=""" ["<-"] {x} ["->"] """/> + * A sequence of components * The `<-` and `->` delimiters allow you to force a single component to be treated as a sequence. This is occasionally useful for spacing a diagram out +examples + +<<< + +``` +x y z sequence +``` +<$railroad text=""" x y z """/> + +``` +<-x y z-> explicit sequence +``` + +<$railroad text=""" <- x y z -> """/> + +<<< + + --- ; optional @@ -22,6 +42,24 @@ Names (as opposed to quoted strings) are available when a value starts with a le * A component that can be omitted * The colon makes `x` appear straight ahead +examples + +<<< + +``` +[:x] optional, normally included +``` +<$railroad text=""" [:x] """/> + +``` +[x] optional, normally omitted +``` + +<$railroad text=""" [x] """/> + +<<< + + --- ; repeated @@ -29,12 +67,62 @@ Names (as opposed to quoted strings) are available when a value starts with a le * A list of one or more `x` * The `+` suffix adds `y` as a separator between each `x` and the next +examples + +<<< + +``` +{x} one or more +``` +<$railroad text=""" {x} """/> + +``` +{x +","} one or more, comma-separated +``` + +<$railroad text=""" {x +","} """/> + +<<< + + --- ; optional repeated : <$railroad text=""" "[{" [":"] x [:"+" y] "}]" """/> * An optional list of `x`, i.e. a list of zero or more `x` +examples + +<<< + +``` +[{:x}] zero or more, normally included +``` + +<$railroad text=""" [{:x}] """/> + +``` +[{:x +","}] zero or more, comma-separated, normally included +``` + +<$railroad text=""" [{:x +","}] """/> + +``` +[{x}] zero or more, normally omitted +``` + +<$railroad text=""" [{x}] """/> + +``` +[{x +","}] zero or more, comma-separated, normally omitted +``` + +<$railroad text=""" [{x +","}] """/> + +<<< + + + --- ; choice @@ -42,6 +130,25 @@ Names (as opposed to quoted strings) are available when a value starts with a le * A set of alternatives * The colon indicates which branch appears straight ahead. By default, it's the first branch +examples + +<<< + +``` +(x|y|z) alternatives +``` + +<$railroad text=""" (x|y|z) """/> + +``` +(x|:y|z) alternatives, normally y +``` + +<$railroad text=""" (x|:y|z) """/> + +<<< + + --- ; string / terminal @@ -49,36 +156,117 @@ Names (as opposed to quoted strings) are available when a value starts with a le * A literal or terminal component * This follows the normal ~TiddlyWiki rules for quoted strings +examples + +<<< + +``` +"x" terminal +``` + +<$railroad text=""" "x" """/> + +<<< + + --- ; nonterminal : <$railroad text=""" (name | "<" string ">") """/> * A nonterminal component, i.e. the name of another diagram +examples + +<<< + +``` +<"x"> nonterminal +``` + +<$railroad text=""" <"x"> """/> + +<<< + + --- ; comment : <$railroad text=""" "/" string "/" """/> * A comment +examples + +<<< + +``` +/ "comment" / comment +``` + +<$railroad text=""" / "comment" / """/> + +<<< + + --- ; dummy : <$railroad text=""" "-" """/> * The absence of a component +examples + +<<< + +``` +- dummy +``` + +<$railroad text=""" - """/> + +<<< + + --- ; link : <$railroad text=""" "[[" x "|" (name|string) "]]" """/> * A link to the tiddler title or URI given by the string or name +examples + +<<< + +``` +[[x|"tiddler"]] link +``` + +<$railroad text=""" [[x|"tiddler"]] """/> + +<<< + + --- ; transclusion : <$railroad text=""" "{{" (name|string) "}}" """/> * Treats the content of another tiddler as diagram syntax and transcludes it into the current diagram +examples + +<<< + +``` +{{"$:/plugins/tiddlywiki/railroad/example-transclusion"}} transclusion + +// "railroad transclusion example" text <- text in the tidlder + +``` + +<$railroad text=""" {{ "$:/plugins/tiddlywiki/railroad/example-transclusion" }} """/> + +<<< + + --- ; arrow pragma @@ -86,14 +274,76 @@ Names (as opposed to quoted strings) are available when a value starts with a le * Controls whether repeat paths have an arrow on them * Can be toggled on and off in mid-diagram, if desired +examples + +<<< +``` +<$railroad text=""" +\arrow yes +[{:x}] +"""/> + +``` + +<$railroad text="""\arrow yes [{:x}] """/> + +``` +<$railroad text=""" +\arrow no +[{:x}] +"""/> +``` + +<$railroad text="""\arrow no [{:x}] """/> + +<<< + + --- ; debug pragma : <$railroad text=""" "\debug" """/> * Causes the diagram to display its parse tree +examples + +<<< + +``` +\debug +x +``` + +<$railroad text="""\debug x """/> + +<<< + + --- ; start/end pragma : <$railroad text=""" ("\start" |: "\end") ("none" |: "single" | "double") """/> * Controls the style of the diagram's startpoint or endpoint +examples + +<<< + +``` +\start none x +``` + +<$railroad text=""" \start none x """/> + +``` +\start double +\end double + x +``` + +<$railroad text=""" \start double +\end double +x +"""/> + +<<< + diff --git a/plugins/tiddlywiki/railroad/parser.js b/plugins/tiddlywiki/railroad/parser.js index bb55b57b8..013d898d7 100644 --- a/plugins/tiddlywiki/railroad/parser.js +++ b/plugins/tiddlywiki/railroad/parser.js @@ -5,6 +5,8 @@ module-type: library Parser for the source of a railroad diagram. +x y z sequence +<-x y z-> explicit sequence [:x] optional, normally included [x] optional, normally omitted {x} one or more @@ -13,8 +15,6 @@ Parser for the source of a railroad diagram. [{:x +","}] zero or more, comma-separated, normally included [{x}] zero or more, normally omitted [{x +","}] zero or more, comma-separated, normally omitted -x y z sequence -<-x y z-> explicit sequence (x|y|z) alternatives (x|:y|z) alternatives, normally y "x" terminal diff --git a/readme.md b/readme.md index fb82c6b4e..828c5e736 100644 --- a/readme.md +++ b/readme.md @@ -1,7 +1,15 @@ <p>Welcome to <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/TiddlyWiki.html">TiddlyWiki</a>, a non-linear personal web notebook that anyone can use and keep forever, independently of any corporation.</p><p><a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/TiddlyWiki.html">TiddlyWiki</a> is a complete interactive wiki in <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/JavaScript.html">JavaScript</a>. It can be used as a single HTML file in the browser or as a powerful Node.js application. It is highly customisable: the entire user interface is itself implemented in hackable <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/WikiText.html">WikiText</a>.</p><p>Learn more and see it in action at <a class="tc-tiddlylink-external" href="https://tiddlywiki.com/" rel="noopener noreferrer" target="_blank">https://tiddlywiki.com/</a></p><p>Developer documentation is in progress at <a class="tc-tiddlylink-external" href="https://tiddlywiki.com/dev/" rel="noopener noreferrer" target="_blank">https://tiddlywiki.com/dev/</a></p><h1 class="">Join the Community</h1><p> <h2 class="">Official Forums</h2><p>The new official forum for talking about TiddlyWiki: requests for help, announcements of new releases and plugins, debating new features, or just sharing experiences. You can participate via the associated website, or subscribe via email.</p><p><a class="tc-tiddlylink-external" href="https://talk.tiddlywiki.org/" rel="noopener noreferrer" target="_blank">https://talk.tiddlywiki.org/</a></p><p>Note that talk.tiddlywiki.org is a community run service that we host and maintain ourselves. The modest running costs are covered by community contributions.</p><p>For the convenience of existing users, we also continue to operate the original TiddlyWiki group (hosted on Google Groups since 2005):</p><p><a class="tc-tiddlylink-external" href="https://groups.google.com/group/TiddlyWiki" rel="noopener noreferrer" target="_blank">https://groups.google.com/group/TiddlyWiki</a></p><h2 class="">Developer Forums</h2><p>There are several resources for developers to learn more about <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/TiddlyWiki.html">TiddlyWiki</a> and to discuss and contribute to its development.</p><ul><li><a class="tc-tiddlylink-external" href="https://tiddlywiki.com/dev" rel="noopener noreferrer" target="_blank">tiddlywiki.com/dev</a> is the official developer documentation</li><li>Get involved in the <a class="tc-tiddlylink-external" href="https://github.com/Jermolene/TiddlyWiki5" rel="noopener noreferrer" target="_blank">development on GitHub</a><ul><li><a class="tc-tiddlylink-external" href="https://github.com/Jermolene/TiddlyWiki5/discussions" rel="noopener noreferrer" target="_blank">Discussions</a> are for Q&A and open-ended discussion</li><li><a class="tc-tiddlylink-external" href="https://github.com/Jermolene/TiddlyWiki5/issues" rel="noopener noreferrer" target="_blank">Issues</a> are for raising bug reports and proposing specific, actionable new ideas</li></ul></li><li>The older TiddlyWikiDev Google Group is now closed in favour of <a class="tc-tiddlylink-external" href="https://github.com/Jermolene/TiddlyWiki5/discussions" rel="noopener noreferrer" target="_blank">GitHub Discussions</a> but remains a useful archive: <a class="tc-tiddlylink-external" href="https://groups.google.com/group/TiddlyWikiDev" rel="noopener noreferrer" target="_blank">https://groups.google.com/group/TiddlyWikiDev</a><ul><li>An enhanced group search facility is available on <a class="tc-tiddlylink-external" href="https://www.mail-archive.com/tiddlywikidev@googlegroups.com/" rel="noopener noreferrer" target="_blank">mail-archive.com</a></li></ul></li><li>Follow <a class="tc-tiddlylink-external" href="http://twitter.com/#!/TiddlyWiki" rel="noopener noreferrer" target="_blank">@TiddlyWiki on Twitter</a> for the latest news</li><li>Chat at <a class="tc-tiddlylink-external" href="https://gitter.im/TiddlyWiki/public" rel="noopener noreferrer" target="_blank">https://gitter.im/TiddlyWiki/public</a> (development room coming soon)</li></ul><h2 class="">Other Forums</h2><ul><li><a class="tc-tiddlylink-external" href="https://www.reddit.com/r/TiddlyWiki5/" rel="noopener noreferrer" target="_blank">TiddlyWiki Subreddit</a></li><li>Chat with Gitter at <a class="tc-tiddlylink-external" href="https://gitter.im/TiddlyWiki/public" rel="noopener noreferrer" target="_blank">https://gitter.im/TiddlyWiki/public</a> !</li><li>Chat on Discord at <a class="tc-tiddlylink-external" href="https://discord.gg/HFFZVQ8" rel="noopener noreferrer" target="_blank">https://discord.gg/HFFZVQ8</a></li></ul><h3 class="">Documentation</h3><p>There is also a discussion group specifically for discussing <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/TiddlyWiki.html">TiddlyWiki</a> documentation improvement initiatives: <a class="tc-tiddlylink-external" href="https://groups.google.com/group/tiddlywikidocs" rel="noopener noreferrer" target="_blank">https://groups.google.com/group/tiddlywikidocs</a> </p> -</p><h1 class="">Installing <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/TiddlyWiki.html">TiddlyWiki</a> on Node.js</h1><ol><li>Install <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/Node.js.html">Node.js</a><ul><li>Linux: <blockquote><div><em>Debian/Ubuntu</em>:<br><code>apt install nodejs</code><br>May need to be followed up by:<br><code>apt install npm</code></div><div><em>Arch Linux</em><br><code>yay -S tiddlywiki</code> <br>(installs node and tiddlywiki)</div></blockquote></li><li>Mac<blockquote><div><code>brew install node</code></div></blockquote></li><li>Android<blockquote><div><a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/Serving%2520TW5%2520from%2520Android.html">Termux for Android</a></div></blockquote></li><li>Other <blockquote><div>See <a class="tc-tiddlylink-external" href="http://nodejs.org" rel="noopener noreferrer" target="_blank">http://nodejs.org</a></div></blockquote></li></ul></li><li>Open a command line terminal and type:<blockquote><div><code>npm install -g tiddlywiki</code></div><div>If it fails with an error you may need to re-run the command as an administrator:</div><div><code>sudo npm install -g tiddlywiki</code> (Mac/Linux)</div></blockquote></li><li>Ensure TiddlyWiki is installed by typing:<blockquote><div><code>tiddlywiki --version</code></div></blockquote><ul><li>In response, you should see <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/TiddlyWiki.html">TiddlyWiki</a> report its current version (eg "5.2.5". You may also see other debugging information reported.)</li></ul></li><li>Try it out:<ol><li><code>tiddlywiki mynewwiki --init server</code> to create a folder for a new wiki that includes server-related components</li><li><code>tiddlywiki mynewwiki --listen</code> to start <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/TiddlyWiki.html">TiddlyWiki</a></li><li>Visit <a class="tc-tiddlylink-external" href="http://127.0.0.1:8080/" rel="noopener noreferrer" target="_blank">http://127.0.0.1:8080/</a> in your browser</li><li>Try editing and creating tiddlers</li></ol></li><li>Optionally, make an offline copy:<ul><li>click the <span class="doc-icon"><svg class="tc-image-save-button tc-image-button" height="22pt" viewBox="0 0 128 128" width="22pt"><path d="M120.783 34.33c4.641 8.862 7.266 18.948 7.266 29.646 0 35.347-28.653 64-64 64-35.346 0-64-28.653-64-64 0-35.346 28.654-64 64-64 18.808 0 35.72 8.113 47.43 21.03l2.68-2.68c3.13-3.13 8.197-3.132 11.321-.008 3.118 3.118 3.121 8.193-.007 11.32l-4.69 4.691zm-12.058 12.058a47.876 47.876 0 013.324 17.588c0 26.51-21.49 48-48 48s-48-21.49-48-48 21.49-48 48-48c14.39 0 27.3 6.332 36.098 16.362L58.941 73.544 41.976 56.578c-3.127-3.127-8.201-3.123-11.32-.005-3.123 3.124-3.119 8.194.006 11.319l22.617 22.617a7.992 7.992 0 005.659 2.347c2.05 0 4.101-.783 5.667-2.349l44.12-44.12z" fill-rule="evenodd"></path></svg></span> <strong>save changes</strong> button in the sidebar, <strong>OR</strong></li><li><code>tiddlywiki mynewwiki --build index</code></li></ul></li></ol><p>The <code>-g</code> flag causes <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/TiddlyWiki.html">TiddlyWiki</a> to be installed globally. Without it, <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/TiddlyWiki.html">TiddlyWiki</a> will only be available in the directory where you installed it.</p><p><div class="doc-icon-block"><div class="doc-block-icon"><svg class="tc-image-warning tc-image-button" height="22pt" viewBox="0 0 128 128" width="22pt"><path d="M57.072 11c3.079-5.333 10.777-5.333 13.856 0l55.426 96c3.079 5.333-.77 12-6.928 12H8.574c-6.158 0-10.007-6.667-6.928-12l55.426-96zM64 37c-4.418 0-8 3.582-8 7.994v28.012C56 77.421 59.59 81 64 81c4.418 0 8-3.582 8-7.994V44.994C72 40.579 68.41 37 64 37zm0 67a8 8 0 100-16 8 8 0 000 16z" fill-rule="evenodd"></path></svg></div> If you are using Debian or Debian-based Linux and you are receiving a <code>node: command not found</code> error though node.js package is installed, you may need to create a symbolic link between <code>nodejs</code> and <code>node</code>. Consult your distro's manual and <code>whereis</code> to correctly create a link. See github <a class="tc-tiddlylink-external" href="http://github.com/Jermolene/TiddlyWiki5/issues/1434" rel="noopener noreferrer" target="_blank">issue 1434</a>. <br><br>Example Debian v8.0: <code>sudo ln -s /usr/bin/nodejs /usr/bin/node</code></div></p><p><br> +</p><h1 class="">Installing <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/TiddlyWiki.html">TiddlyWiki</a> on Node.js</h1><ol><li>Install <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/Node.js.html">Node.js</a><ul><li>Linux: <blockquote><div><em>Debian/Ubuntu</em>:<br><code>apt install nodejs</code><br>May need to be followed up by:<br><code>apt install npm</code></div><div><em>Arch Linux</em><br><code>yay -S tiddlywiki</code> <br>(installs node and tiddlywiki)</div></blockquote></li><li>Mac<blockquote><div><code>brew install node</code></div></blockquote></li><li>Android<blockquote><div><a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/Serving%2520TW5%2520from%2520Android.html">Termux for Android</a></div></blockquote></li><li>Other <blockquote><div>See <a class="tc-tiddlylink-external" href="http://nodejs.org" rel="noopener noreferrer" target="_blank">http://nodejs.org</a></div></blockquote></li></ul></li><li>Open a command line terminal and type:<blockquote><div><code>npm install -g tiddlywiki</code></div><div>If it fails with an error you may need to re-run the command as an administrator:</div><div><code>sudo npm install -g tiddlywiki</code> (Mac/Linux)</div></blockquote></li><li>Ensure TiddlyWiki is installed by typing:<blockquote><div><code>tiddlywiki --version</code></div></blockquote><ul><li>In response, you should see <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/TiddlyWiki.html">TiddlyWiki</a> report its current version (eg "5.2.7". You may also see other debugging information reported.)</li></ul></li><li>Try it out:<ol><li><code>tiddlywiki mynewwiki --init server</code> to create a folder for a new wiki that includes server-related components</li><li><code>tiddlywiki mynewwiki --listen</code> to start <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/TiddlyWiki.html">TiddlyWiki</a></li><li>Visit <a class="tc-tiddlylink-external" href="http://127.0.0.1:8080/" rel="noopener noreferrer" target="_blank">http://127.0.0.1:8080/</a> in your browser</li><li>Try editing and creating tiddlers</li></ol></li><li>Optionally, make an offline copy:<ul><li>click the <span class="doc-icon"><svg class="tc-image-save-button-dynamic tc-image-button" height="22pt" viewBox="0 0 128 128" width="22pt"> +<g class="tc-image-save-button-dynamic-clean"> +<path d="M120.783 34.33c4.641 8.862 7.266 18.948 7.266 29.646 0 35.347-28.653 64-64 64-35.346 0-64-28.653-64-64 0-35.346 28.654-64 64-64 18.808 0 35.72 8.113 47.43 21.03l2.68-2.68c3.13-3.13 8.197-3.132 11.321-.008 3.118 3.118 3.121 8.193-.007 11.32l-4.69 4.691zm-12.058 12.058a47.876 47.876 0 013.324 17.588c0 26.51-21.49 48-48 48s-48-21.49-48-48 21.49-48 48-48c14.39 0 27.3 6.332 36.098 16.362L58.941 73.544 41.976 56.578c-3.127-3.127-8.201-3.123-11.32-.005-3.123 3.124-3.119 8.194.006 11.319l22.617 22.617a7.992 7.992 0 005.659 2.347c2.05 0 4.101-.783 5.667-2.349l44.12-44.12z" fill-rule="evenodd"></path> +</g> +<g class="tc-image-save-button-dynamic-dirty"> +<path d="M64.856912,0 C100.203136,0 128.856912,28.653776 128.856912,64 C128.856912,99.346224 100.203136,128 64.856912,128 C29.510688,128 0.856911958,99.346224 0.856911958,64 C0.856911958,28.653776 29.510688,0 64.856912,0 Z M64.856912,16 C38.347244,16 16.856912,37.490332 16.856912,64 C16.856912,90.509668 38.347244,112 64.856912,112 C91.3665799,112 112.856912,90.509668 112.856912,64 C112.856912,37.490332 91.3665799,16 64.856912,16 Z"></path> +<circle cx="65" cy="64" r="32"></circle> +</g> +</svg></span> <strong>save changes</strong> button in the sidebar, <strong>OR</strong></li><li><code>tiddlywiki mynewwiki --build index</code></li></ul></li></ol><p>The <code>-g</code> flag causes <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/TiddlyWiki.html">TiddlyWiki</a> to be installed globally. Without it, <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/TiddlyWiki.html">TiddlyWiki</a> will only be available in the directory where you installed it.</p><p><div class="doc-icon-block"><div class="doc-block-icon"><svg class="tc-image-warning tc-image-button" height="22pt" viewBox="0 0 128 128" width="22pt"><path d="M57.072 11c3.079-5.333 10.777-5.333 13.856 0l55.426 96c3.079 5.333-.77 12-6.928 12H8.574c-6.158 0-10.007-6.667-6.928-12l55.426-96zM64 37c-4.418 0-8 3.582-8 7.994v28.012C56 77.421 59.59 81 64 81c4.418 0 8-3.582 8-7.994V44.994C72 40.579 68.41 37 64 37zm0 67a8 8 0 100-16 8 8 0 000 16z" fill-rule="evenodd"></path></svg></div> If you are using Debian or Debian-based Linux and you are receiving a <code>node: command not found</code> error though node.js package is installed, you may need to create a symbolic link between <code>nodejs</code> and <code>node</code>. Consult your distro's manual and <code>whereis</code> to correctly create a link. See github <a class="tc-tiddlylink-external" href="http://github.com/Jermolene/TiddlyWiki5/issues/1434" rel="noopener noreferrer" target="_blank">issue 1434</a>. <br><br>Example Debian v8.0: <code>sudo ln -s /usr/bin/nodejs /usr/bin/node</code></div></p><p><br> <div class="doc-icon-block"><div class="doc-block-icon"><svg class="tc-image-tip tc-image-button" height="22pt" viewBox="0 0 128 128" width="22pt"><path d="M64 128.242c35.346 0 64-28.654 64-64 0-35.346-28.654-64-64-64-35.346 0-64 28.654-64 64 0 35.346 28.654 64 64 64zm11.936-36.789c-.624 4.129-5.73 7.349-11.936 7.349-6.206 0-11.312-3.22-11.936-7.349C54.33 94.05 58.824 95.82 64 95.82c5.175 0 9.67-1.769 11.936-4.366zm0 4.492c-.624 4.13-5.73 7.349-11.936 7.349-6.206 0-11.312-3.22-11.936-7.349 2.266 2.597 6.76 4.366 11.936 4.366 5.175 0 9.67-1.769 11.936-4.366zm0 4.456c-.624 4.129-5.73 7.349-11.936 7.349-6.206 0-11.312-3.22-11.936-7.349 2.266 2.597 6.76 4.366 11.936 4.366 5.175 0 9.67-1.769 11.936-4.366zm0 4.492c-.624 4.13-5.73 7.349-11.936 7.349-6.206 0-11.312-3.22-11.936-7.349 2.266 2.597 6.76 4.366 11.936 4.366 5.175 0 9.67-1.769 11.936-4.366zM64.3 24.242c11.618 0 23.699 7.82 23.699 24.2S75.92 71.754 75.92 83.576c0 5.873-5.868 9.26-11.92 9.26s-12.027-3.006-12.027-9.26C51.973 71.147 40 65.47 40 48.442s12.683-24.2 24.301-24.2z" fill-rule="evenodd"></path></svg></div> You can also install prior versions like this: <br><code> npm install -g tiddlywiki@5.1.13</code></div> </p><h1 class="">Using <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/TiddlyWiki.html">TiddlyWiki</a> on Node.js</h1><p>TiddlyWiki5 includes a set of commands for use on the command line to perform an extensive set of operations based on <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/TiddlyWikiFolders.html">TiddlyWikiFolders</a>, <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/TiddlerFiles.html">TiddlerFiles</a>.</p><p>For example, the following command loads the tiddlers from a TiddlyWiki HTML file and then saves one of them in static HTML:</p><pre><code>tiddlywiki --verbose --load mywiki.html --rendertiddler ReadMe ./readme.html</code></pre><p>Running <code>tiddlywiki</code> from the command line boots the TiddlyWiki kernel, loads the core plugins and establishes an empty wiki store. It then sequentially processes the command line arguments from left to right. The arguments are separated with spaces.</p><p><a class="tc-tiddlylink tc-tiddlylink-resolves doc-from-version" href="https://tiddlywiki.com/static/Release%25205.1.20.html"><svg class="tc-image-warning tc-image-button" height="22pt" viewBox="0 0 128 128" width="22pt"><path d="M57.072 11c3.079-5.333 10.777-5.333 13.856 0l55.426 96c3.079 5.333-.77 12-6.928 12H8.574c-6.158 0-10.007-6.667-6.928-12l55.426-96zM64 37c-4.418 0-8 3.582-8 7.994v28.012C56 77.421 59.59 81 64 81c4.418 0 8-3.582 8-7.994V44.994C72 40.579 68.41 37 64 37zm0 67a8 8 0 100-16 8 8 0 000 16z" fill-rule="evenodd"></path></svg> New in: 5.1.20</a> First, there can be zero or more plugin references identified by the prefix <code>+</code> for plugin names or <code>++</code> for a path to a plugin folder. These plugins are loaded in addition to any specified in the <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/TiddlyWikiFolders.html">TiddlyWikiFolder</a>.</p><p>The next argument is the optional path to the <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/TiddlyWikiFolders.html">TiddlyWikiFolder</a> to be loaded. If not present, then the current directory is used.</p><p>The commands and their individual arguments follow, each command being identified by the prefix <code>--</code>.</p><pre><code>tiddlywiki [+<pluginname> | ++<pluginpath>] [<wikipath>] [--<command> [<arg>[,<arg>]]]</code></pre><p>For example:</p><pre><code>tiddlywiki --version tiddlywiki +plugins/tiddlywiki/filesystem +plugins/tiddlywiki/tiddlyweb mywiki --listen diff --git a/themes/tiddlywiki/vanilla/base.tid b/themes/tiddlywiki/vanilla/base.tid index 98097296a..f63384ee9 100644 --- a/themes/tiddlywiki/vanilla/base.tid +++ b/themes/tiddlywiki/vanilla/base.tid @@ -3118,6 +3118,36 @@ select { background: <<colour select-tag-background>>; } +/* +** Classes for displaying globals +*/ + +.tc-global-tiddler-body { + padding: 0.25em; + border: 1px solid <<colour foreground>>; + background-color: <<colour muted-foreground>>; + border-radius: 3px; +} + +.tc-global-tiddler-body-heading { + margin: 0 0 0.25em 0; + font-weight: normal; +} + +.tc-global-tiddler-body-type { + margin: 0 0 0.25em 0; + border-bottom: 1px solid <<colour foreground>>; +} + +.tc-global-tiddler-body-details { + background-color: <<colour background>>; +} + +.tc-global-tiddler-body pre { + margin: 0; + border: 1px solid <<colour foreground>>; +} + /* ** Utility classes for SVG icons */