1
0
mirror of https://github.com/Jermolene/TiddlyWiki5 synced 2026-01-23 11:24:40 +00:00

Compare commits

..

1 Commits

Author SHA1 Message Date
jeremy@jermolene.com
df286ecfe6 Fixes for JSON operators 2022-12-09 18:28:12 +00:00
620 changed files with 14938 additions and 11560 deletions

View File

@@ -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.8
TW5_BUILD_VERSION=v5.2.4
fi
echo "Using TW5_BUILD_VERSION as [$TW5_BUILD_VERSION]"
@@ -359,14 +359,14 @@ node $TW5_BUILD_TIDDLYWIKI \
# Delete any existing static content
rm -rf $TW5_BUILD_OUTPUT/languages/de-AT/static/*
rm -rf $TW5_BUILD_OUTPUT/languages/de-DE/static/*
rm -rf $TW5_BUILD_OUTPUT/languages/es-ES/static/*
rm -rf $TW5_BUILD_OUTPUT/languages/fr-FR/static/*
rm -rf $TW5_BUILD_OUTPUT/languages/ja-JP/static/*
rm -rf $TW5_BUILD_OUTPUT/languages/ko-KR/static/*
rm -rf $TW5_BUILD_OUTPUT/languages/zh-Hans/static/*
rm -rf $TW5_BUILD_OUTPUT/languages/zh-Hant/static/*
rm $TW5_BUILD_OUTPUT/languages/de-AT/static/*
rm $TW5_BUILD_OUTPUT/languages/de-DE/static/*
rm $TW5_BUILD_OUTPUT/languages/es-ES/static/*
rm $TW5_BUILD_OUTPUT/languages/fr-FR/static/*
rm $TW5_BUILD_OUTPUT/languages/ja-JP/static/*
rm $TW5_BUILD_OUTPUT/languages/ko-KR/static/*
rm $TW5_BUILD_OUTPUT/languages/zh-Hans/static/*
rm $TW5_BUILD_OUTPUT/languages/zh-Hant/static/*
# /languages/de-AT/index.html Demo wiki with de-AT language
# /languages/de-AT/empty.html Empty wiki with de-AT language

View File

@@ -2,4 +2,4 @@
# Remove any output files
find . -regex "^./editions/.*/output/.*" -delete
find . -regex "^./editions/[a-z0-9\.-]*/output/.*" -delete

View File

@@ -313,7 +313,7 @@ $tw.utils.getLocationHash = function() {
var idx = href.indexOf('#');
if(idx === -1) {
return "#";
} else if(href.substr(idx + 1,1) === "#" || href.substr(idx + 1,3) === "%23") {
} else if(idx < href.length-1 && href[idx+1] === '#') {
// Special case: ignore location hash if it itself starts with a #
return "#";
} else {
@@ -375,7 +375,7 @@ $tw.utils.stringifyList = function(value) {
var result = new Array(value.length);
for(var t=0, l=value.length; t<l; t++) {
var entry = value[t] || "";
if(entry.match(/[^\S\xA0]/mg)) {
if(entry.indexOf(" ") !== -1) {
result[t] = "[[" + entry + "]]";
} else {
result[t] = entry;
@@ -1881,7 +1881,7 @@ A default set of files for TiddlyWiki to ignore during load.
This matches what NPM ignores, and adds "*.meta" to ignore tiddler
metadata files.
*/
$tw.boot.excludeRegExp = /^\.DS_Store$|^.*\.meta$|^\..*\.swp$|^\._.*$|^\.git$|^\.github$|^\.vscode$|^\.hg$|^\.lock-wscript$|^\.svn$|^\.wafpickle-.*$|^CVS$|^npm-debug\.log$/;
$tw.boot.excludeRegExp = /^\.DS_Store$|^.*\.meta$|^\..*\.swp$|^\._.*$|^\.git$|^\.hg$|^\.lock-wscript$|^\.svn$|^\.wafpickle-.*$|^CVS$|^npm-debug\.log$/;
/*
Load all the tiddlers recursively from a directory, including honouring `tiddlywiki.files` files for drawing in external files. Returns an array of {filepath:,type:,tiddlers: [{..fields...}],hasMetaFile:}. Note that no file information is returned for externally loaded tiddlers, just the `tiddlers` property.
@@ -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,rootPath) {
var processFile = function(filename,isTiddlerFile,fields,isEditableFile) {
var extInfo = $tw.config.fileExtensionInfo[path.extname(filename)],
type = (extInfo || {}).type || fields.type || "text/plain",
typeInfo = $tw.config.contentTypeInfo[type] || {},
@@ -1941,12 +1941,6 @@ $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;
@@ -2029,7 +2023,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,dirSpec.path);
processFile(thisPath,dirSpec.isTiddlerFile,dirSpec.fields,dirSpec.isEditableFile);
}
}
} else {
@@ -2414,7 +2408,6 @@ $tw.boot.initStartup = function(options) {
$tw.utils.registerFileType("video/webm","base64",".webm");
$tw.utils.registerFileType("video/mp4","base64",".mp4");
$tw.utils.registerFileType("audio/mp3","base64",".mp3");
$tw.utils.registerFileType("audio/mpeg","base64");
$tw.utils.registerFileType("text/markdown","utf8",[".md",".markdown"],{deserializerType:"text/x-markdown"});
$tw.utils.registerFileType("text/x-markdown","utf8",[".md",".markdown"]);
$tw.utils.registerFileType("application/enex+xml","utf8",".enex");

View File

@@ -4,7 +4,7 @@ type: text/plain
TiddlyWiki created by Jeremy Ruston, (jeremy [at] jermolene [dot] com)
Copyright (c) 2004-2007, Jeremy Ruston
Copyright (c) 2007-2023, UnaMesa Association
Copyright (c) 2007-2022, UnaMesa Association
All rights reserved.
Redistribution and use in source and binary forms, with or without

View File

@@ -1,12 +0,0 @@
title: $:/core/images/save-button-dynamic
tags: $:/tags/Image
<svg width="22pt" height="22pt" class="tc-image-save-button-dynamic tc-image-button" viewBox="0 0 128 128">
<g class="tc-image-save-button-dynamic-clean">
<path fill-rule="evenodd" 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"/>
</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>

View File

@@ -1,13 +1,11 @@
title: $:/language/Docs/Fields/
_canonical_uri: The full URI of an external image tiddler
author: Name of the author of a plugin
bag: The name of the bag from which a tiddler came
caption: The text to be displayed on a tab or button
code-body: The view template will display the tiddler as code if set to ''yes''
color: The CSS color value associated with a tiddler
component: The name of the component responsible for an [[alert tiddler|AlertMechanism]]
core-version: For a plugin, indicates what version of TiddlyWiki with which it is compatible
current-tiddler: Used to cache the top tiddler in a [[history list|HistoryMechanism]]
created: The date a tiddler was created
creator: The name of the person who created a tiddler
@@ -24,9 +22,7 @@ list-before: If set, the title of a tiddler before which this tiddler should be
list-after: If set, the title of the tiddler after which this tiddler should be added to the ordered list of tiddler titles, or at the end of the list if this field is present but empty
modified: The date and time at which a tiddler was last modified
modifier: The tiddler title associated with the person who last modified a tiddler
module-type: For javascript tiddlers, specifies what kind of module it is
name: The human readable name associated with a plugin tiddler
parent-plugin: For a plugin, specifies which plugin of which it is a sub-plugin
plugin-priority: A numerical value indicating the priority of a plugin tiddler
plugin-type: The type of plugin in a plugin tiddler
revision: The revision of the tiddler held at the server

View File

@@ -40,7 +40,6 @@ Error/RetrievingSkinny: Error retrieving skinny tiddler list
Error/SavingToTWEdit: Error saving to TWEdit
Error/WhileSaving: Error while saving
Error/XMLHttpRequest: XMLHttpRequest error code
Error/ZoominTextNode: Story View Error: It appears you tried to interact with a tiddler that displays in a custom container. This is most likely caused by using `$:/tags/StoryTiddlerTemplateFilter` with a template that contains text or whitespace at the start. Please use the pragma `\whitespace trim` and ensure the whole contents of the tiddler is wrapped in a single HTML element. The text that caused this issue:
InternalJavaScriptError/Title: Internal JavaScript Error
InternalJavaScriptError/Hint: Well, this is embarrassing. It is recommended that you restart TiddlyWiki by refreshing your browser
LayoutSwitcher/Description: Open the layout switcher

View File

@@ -0,0 +1,21 @@
title: $:/language/Modals/SaveInstructions
subtitle: Save your work
footer: <$button message="tm-close-tiddler">Close</$button>
help: https://tiddlywiki.com/static/SavingChanges.html
Your changes to this wiki need to be saved as a ~TiddlyWiki HTML file.
!!! Desktop browsers
# Select ''Save As'' from the ''File'' menu
# Choose a filename and location
#* Some browsers also require you to explicitly specify the file saving format as ''Webpage, HTML only'' or similar
# Close this tab
!!! Smartphone browsers
# Create a bookmark to this page
#* If you've got iCloud or Google Sync set up then the bookmark will automatically sync to your desktop where you can open it and save it as above
# Close this tab
//If you open the bookmark again in Mobile Safari you will see this message again. If you want to go ahead and use the file, just click the ''close'' button below//

View File

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

View File

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

View File

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

View File

@@ -30,7 +30,7 @@ exports.textPrimitives.wikiLink = exports.textPrimitives.upperLetter + "+" +
exports.textPrimitives.upperLetter +
exports.textPrimitives.anyLetter + "*";
exports.htmlEntities = {quot:34, dollar:36, amp:38, apos:39, lt:60, gt:62, nbsp:160, iexcl:161, cent:162, pound:163, curren:164, yen:165, brvbar:166, sect:167, uml:168, copy:169, ordf:170, laquo:171, not:172, shy:173, reg:174, macr:175, deg:176, plusmn:177, sup2:178, sup3:179, acute:180, micro:181, para:182, middot:183, cedil:184, sup1:185, ordm:186, raquo:187, frac14:188, frac12:189, frac34:190, iquest:191, Agrave:192, Aacute:193, Acirc:194, Atilde:195, Auml:196, Aring:197, AElig:198, Ccedil:199, Egrave:200, Eacute:201, Ecirc:202, Euml:203, Igrave:204, Iacute:205, Icirc:206, Iuml:207, ETH:208, Ntilde:209, Ograve:210, Oacute:211, Ocirc:212, Otilde:213, Ouml:214, times:215, Oslash:216, Ugrave:217, Uacute:218, Ucirc:219, Uuml:220, Yacute:221, THORN:222, szlig:223, agrave:224, aacute:225, acirc:226, atilde:227, auml:228, aring:229, aelig:230, ccedil:231, egrave:232, eacute:233, ecirc:234, euml:235, igrave:236, iacute:237, icirc:238, iuml:239, eth:240, ntilde:241, ograve:242, oacute:243, ocirc:244, otilde:245, ouml:246, divide:247, oslash:248, ugrave:249, uacute:250, ucirc:251, uuml:252, yacute:253, thorn:254, yuml:255, OElig:338, oelig:339, Scaron:352, scaron:353, Yuml:376, fnof:402, circ:710, tilde:732, Alpha:913, Beta:914, Gamma:915, Delta:916, Epsilon:917, Zeta:918, Eta:919, Theta:920, Iota:921, Kappa:922, Lambda:923, Mu:924, Nu:925, Xi:926, Omicron:927, Pi:928, Rho:929, Sigma:931, Tau:932, Upsilon:933, Phi:934, Chi:935, Psi:936, Omega:937, alpha:945, beta:946, gamma:947, delta:948, epsilon:949, zeta:950, eta:951, theta:952, iota:953, kappa:954, lambda:955, mu:956, nu:957, xi:958, omicron:959, pi:960, rho:961, sigmaf:962, sigma:963, tau:964, upsilon:965, phi:966, chi:967, psi:968, omega:969, thetasym:977, upsih:978, piv:982, ensp:8194, emsp:8195, thinsp:8201, zwnj:8204, zwj:8205, lrm:8206, rlm:8207, ndash:8211, mdash:8212, lsquo:8216, rsquo:8217, sbquo:8218, ldquo:8220, rdquo:8221, bdquo:8222, dagger:8224, Dagger:8225, bull:8226, hellip:8230, permil:8240, prime:8242, Prime:8243, lsaquo:8249, rsaquo:8250, oline:8254, frasl:8260, euro:8364, image:8465, weierp:8472, real:8476, trade:8482, alefsym:8501, larr:8592, uarr:8593, rarr:8594, darr:8595, harr:8596, crarr:8629, lArr:8656, uArr:8657, rArr:8658, dArr:8659, hArr:8660, forall:8704, part:8706, exist:8707, empty:8709, nabla:8711, isin:8712, notin:8713, ni:8715, prod:8719, sum:8721, minus:8722, lowast:8727, radic:8730, prop:8733, infin:8734, ang:8736, and:8743, or:8744, cap:8745, cup:8746, int:8747, there4:8756, sim:8764, cong:8773, asymp:8776, ne:8800, equiv:8801, le:8804, ge:8805, sub:8834, sup:8835, nsub:8836, sube:8838, supe:8839, oplus:8853, otimes:8855, perp:8869, sdot:8901, lceil:8968, rceil:8969, lfloor:8970, rfloor:8971, lang:9001, rang:9002, loz:9674, spades:9824, clubs:9827, hearts:9829, diams:9830 };
exports.htmlEntities = {quot:34, amp:38, apos:39, lt:60, gt:62, nbsp:160, iexcl:161, cent:162, pound:163, curren:164, yen:165, brvbar:166, sect:167, uml:168, copy:169, ordf:170, laquo:171, not:172, shy:173, reg:174, macr:175, deg:176, plusmn:177, sup2:178, sup3:179, acute:180, micro:181, para:182, middot:183, cedil:184, sup1:185, ordm:186, raquo:187, frac14:188, frac12:189, frac34:190, iquest:191, Agrave:192, Aacute:193, Acirc:194, Atilde:195, Auml:196, Aring:197, AElig:198, Ccedil:199, Egrave:200, Eacute:201, Ecirc:202, Euml:203, Igrave:204, Iacute:205, Icirc:206, Iuml:207, ETH:208, Ntilde:209, Ograve:210, Oacute:211, Ocirc:212, Otilde:213, Ouml:214, times:215, Oslash:216, Ugrave:217, Uacute:218, Ucirc:219, Uuml:220, Yacute:221, THORN:222, szlig:223, agrave:224, aacute:225, acirc:226, atilde:227, auml:228, aring:229, aelig:230, ccedil:231, egrave:232, eacute:233, ecirc:234, euml:235, igrave:236, iacute:237, icirc:238, iuml:239, eth:240, ntilde:241, ograve:242, oacute:243, ocirc:244, otilde:245, ouml:246, divide:247, oslash:248, ugrave:249, uacute:250, ucirc:251, uuml:252, yacute:253, thorn:254, yuml:255, OElig:338, oelig:339, Scaron:352, scaron:353, Yuml:376, fnof:402, circ:710, tilde:732, Alpha:913, Beta:914, Gamma:915, Delta:916, Epsilon:917, Zeta:918, Eta:919, Theta:920, Iota:921, Kappa:922, Lambda:923, Mu:924, Nu:925, Xi:926, Omicron:927, Pi:928, Rho:929, Sigma:931, Tau:932, Upsilon:933, Phi:934, Chi:935, Psi:936, Omega:937, alpha:945, beta:946, gamma:947, delta:948, epsilon:949, zeta:950, eta:951, theta:952, iota:953, kappa:954, lambda:955, mu:956, nu:957, xi:958, omicron:959, pi:960, rho:961, sigmaf:962, sigma:963, tau:964, upsilon:965, phi:966, chi:967, psi:968, omega:969, thetasym:977, upsih:978, piv:982, ensp:8194, emsp:8195, thinsp:8201, zwnj:8204, zwj:8205, lrm:8206, rlm:8207, ndash:8211, mdash:8212, lsquo:8216, rsquo:8217, sbquo:8218, ldquo:8220, rdquo:8221, bdquo:8222, dagger:8224, Dagger:8225, bull:8226, hellip:8230, permil:8240, prime:8242, Prime:8243, lsaquo:8249, rsaquo:8250, oline:8254, frasl:8260, euro:8364, image:8465, weierp:8472, real:8476, trade:8482, alefsym:8501, larr:8592, uarr:8593, rarr:8594, darr:8595, harr:8596, crarr:8629, lArr:8656, uArr:8657, rArr:8658, dArr:8659, hArr:8660, forall:8704, part:8706, exist:8707, empty:8709, nabla:8711, isin:8712, notin:8713, ni:8715, prod:8719, sum:8721, minus:8722, lowast:8727, radic:8730, prop:8733, infin:8734, ang:8736, and:8743, or:8744, cap:8745, cup:8746, int:8747, there4:8756, sim:8764, cong:8773, asymp:8776, ne:8800, equiv:8801, le:8804, ge:8805, sub:8834, sup:8835, nsub:8836, sube:8838, supe:8839, oplus:8853, otimes:8855, perp:8869, sdot:8901, lceil:8968, rceil:8969, lfloor:8970, rfloor:8971, lang:9001, rang:9002, loz:9674, spades:9824, clubs:9827, hearts:9829, diams:9830 };
exports.htmlVoidElements = "area,base,br,col,command,embed,hr,img,input,keygen,link,meta,param,source,track,wbr".split(",");

View File

@@ -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 + "px";
this.iframeNode.style.height = (newHeight + 14) + "px"; // +14 for the border on the textarea
}
} 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 + "px";
this.iframeNode.style.height = (fixedHeight + 14) + "px";
}
}
};
@@ -177,11 +177,9 @@ FramedEngine.prototype.fixHeight = function() {
Focus the engine node
*/
FramedEngine.prototype.focus = function() {
if(this.domNode.focus) {
if(this.domNode.focus && this.domNode.select) {
this.domNode.focus();
}
if(this.domNode.select) {
$tw.utils.setSelectionByPosition(this.domNode,this.widget.editFocusSelectFromStart,this.widget.editFocusSelectFromEnd);
this.domNode.select();
}
};

View File

@@ -119,12 +119,10 @@ SimpleEngine.prototype.fixHeight = function() {
/*
Focus the engine node
*/
SimpleEngine.prototype.focus = function() {
if(this.domNode.focus) {
SimpleEngine.prototype.focus = function() {
if(this.domNode.focus && this.domNode.select) {
this.domNode.focus();
}
if(this.domNode.select) {
$tw.utils.setSelectionByPosition(this.domNode,this.widget.editFocusSelectFromStart,this.widget.editFocusSelectFromEnd);
this.domNode.select();
}
};

View File

@@ -180,8 +180,6 @@ function editTextWidgetFactory(toolbarEngine,nonToolbarEngine) {
this.editMinHeight = this.getAttribute("minHeight",DEFAULT_MIN_TEXT_AREA_HEIGHT);
this.editFocusPopup = this.getAttribute("focusPopup");
this.editFocus = this.getAttribute("focus");
this.editFocusSelectFromStart = $tw.utils.parseNumber(this.getAttribute("focusSelectFromStart","0"));
this.editFocusSelectFromEnd = $tw.utils.parseNumber(this.getAttribute("focusSelectFromEnd","0"));
this.editTabIndex = this.getAttribute("tabindex");
this.editCancelPopups = this.getAttribute("cancelPopups","") === "yes";
this.editInputActions = this.getAttribute("inputActions");
@@ -220,7 +218,7 @@ function editTextWidgetFactory(toolbarEngine,nonToolbarEngine) {
EditTextWidget.prototype.refresh = function(changedTiddlers) {
var changedAttributes = this.computeAttributes();
// Completely rerender if any of our attributes have changed
if(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedAttributes["default"] || changedAttributes["class"] || changedAttributes.placeholder || changedAttributes.size || changedAttributes.autoHeight || changedAttributes.minHeight || changedAttributes.focusPopup || changedAttributes.rows || changedAttributes.tabindex || changedAttributes.cancelPopups || changedAttributes.inputActions || changedAttributes.refreshTitle || changedAttributes.autocomplete || changedTiddlers[HEIGHT_MODE_TITLE] || changedTiddlers[ENABLE_TOOLBAR_TITLE] || changedTiddlers["$:/palette"] || changedAttributes.disabled || changedAttributes.fileDrop) {
if(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedAttributes["default"] || changedAttributes["class"] || changedAttributes.placeholder || changedAttributes.size || changedAttributes.autoHeight || changedAttributes.minHeight || changedAttributes.focusPopup || changedAttributes.rows || changedAttributes.tabindex || changedAttributes.cancelPopups || changedAttributes.inputActions || changedAttributes.refreshTitle || changedAttributes.autocomplete || changedTiddlers[HEIGHT_MODE_TITLE] || changedTiddlers[ENABLE_TOOLBAR_TITLE] || changedAttributes.disabled || changedAttributes.fileDrop) {
this.refreshSelf();
return true;
} else if (changedTiddlers[this.editRefreshTitle]) {

View File

@@ -25,10 +25,20 @@ exports.cascade = function(operationSubFunction,options) {
if(!filterFnList[index]) {
filterFnList[index] = options.wiki.compileFilter(filter);
}
var output = filterFnList[index](options.wiki.makeTiddlerIterator([title]),widget.makeFakeWidgetWithVariables({
"currentTiddler": "" + title,
"..currentTiddler": widget.getVariable("currentTiddler","")
}));
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);
}
}
});
if(output.length !== 0) {
result = output[0];
return false;

View File

@@ -19,13 +19,23 @@ exports.filter = function(operationSubFunction,options) {
var resultsToRemove = [],
index = 0;
results.each(function(title) {
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
}));
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);
}
}
});
if(filtered.length === 0) {
resultsToRemove.push(title);
}

View File

@@ -21,13 +21,23 @@ 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]),widget.makeFakeWidgetWithVariables({
"currentTiddler": "" + title,
"..currentTiddler": widget.getVariable("currentTiddler",""),
"index": "" + index,
"revIndex": "" + (inputTitles.length - 1 - index),
"length": "" + inputTitles.length
}));
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);
}
}
});
if(filtered.length && flatten) {
$tw.utils.each(filtered,function(value) {
results.push(value);

View File

@@ -18,14 +18,24 @@ exports.reduce = function(operationSubFunction,options) {
var accumulator = "",
index = 0;
results.each(function(title) {
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
}));
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);
}
}
});
if(list.length > 0) {
accumulator = "" + list[0];
}

View File

@@ -25,10 +25,20 @@ exports.sort = function(operationSubFunction,options) {
indexes = new Array(inputTitles.length),
compareFn;
results.each(function(title) {
var key = operationSubFunction(options.wiki.makeTiddlerIterator([title]),widget.makeFakeWidgetWithVariables({
"currentTiddler": "" + title,
"..currentTiddler": widget.getVariable("currentTiddler")
}));
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);
}
}
});
sortKeys.push(key[0] || "");
});
results.clear();

View File

@@ -255,21 +255,19 @@ 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]) {
// 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]"];
operatorFunction = filterOperators.field;
} 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.evaluateVariable(varTree.name,{params: varTree.params, source: source})[0] || "";
operand.value = widget.getVariable(varTree.name,{params:varTree.params,defaultValue: ""});
} else {
operand.value = operand.text;
}

View File

@@ -16,22 +16,6 @@ Filter operator for applying decodeURIComponent() to each item.
Export our filter functions
*/
exports.decodebase64 = function(source,operator,options) {
var results = [];
source(function(tiddler,title) {
results.push($tw.utils.base64Decode(title));
});
return results;
};
exports.encodebase64 = function(source,operator,options) {
var results = [];
source(function(tiddler,title) {
results.push($tw.utils.base64Encode(title));
});
return results;
};
exports.decodeuricomponent = function(source,operator,options) {
var results = [];
source(function(tiddler,title) {
@@ -43,7 +27,7 @@ exports.decodeuricomponent = function(source,operator,options) {
exports.encodeuricomponent = function(source,operator,options) {
var results = [];
source(function(tiddler,title) {
results.push($tw.utils.encodeURIComponentExtended(title));
results.push(encodeURIComponent(title));
});
return results;
};

View File

@@ -20,10 +20,18 @@ exports.filter = function(source,operator,options) {
results = [],
target = operator.prefix !== "!";
source(function(tiddler,title) {
var list = filterFn.call(options.wiki,options.wiki.makeTiddlerIterator([title]),options.widget.makeFakeWidgetWithVariables({
"currentTiddler": "" + title,
"..currentTiddler": options.widget.getVariable("currentTiddler","")
}));
var list = filterFn.call(options.wiki,options.wiki.makeTiddlerIterator([title]),{
getVariable: function(name) {
switch(name) {
case "currentTiddler":
return "" + title;
case "..currentTiddler":
return options.widget.getVariable("currentTiddler");
default:
return options.widget.getVariable(name);
}
}
});
if((list.length > 0) === target) {
results.push(title);
}

View File

@@ -1,32 +0,0 @@
/*\
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;
};
})();

View File

@@ -176,11 +176,7 @@ function getDataItem(data,indexes) {
var item = data;
for(var i=0; i<indexes.length; i++) {
if(item !== undefined) {
if(item !== null && ["number","string","boolean"].indexOf(typeof item) === -1) {
item = item[indexes[i]];
} else {
item = undefined;
}
item = item[indexes[i]];
}
}
return item;

View File

@@ -26,14 +26,26 @@ exports.reduce = function(source,operator,options) {
accumulator = operator.operands[1] || "";
for(var index=0; index<results.length; index++) {
var title = results[index],
list = filterFn.call(options.wiki,options.wiki.makeTiddlerIterator([title]),options.widget.makeFakeWidgetWithVariables({
"currentTiddler": "" + title,
"..currentTiddler": options.widget.getVariable("currentTiddler"),
"accumulator": "" + accumulator,
"index": "" + index,
"revIndex": "" + (results.length - 1 - index),
"length": "" + results.length
}));
list = filterFn.call(options.wiki,options.wiki.makeTiddlerIterator([title]),{
getVariable: function(name) {
switch(name) {
case "currentTiddler":
return "" + title;
case "..currentTiddler":
return options.widget.getVariable("currentTiddler");
case "accumulator":
return "" + accumulator;
case "index":
return "" + index;
case "revIndex":
return "" + (results.length - 1 - index);
case "length":
return "" + results.length;
default:
return options.widget.getVariable(name);
}
}
});
if(list.length > 0) {
accumulator = "" + list[0];
}

View File

@@ -25,10 +25,18 @@ exports.sortsub = function(source,operator,options) {
inputTitles.push(title);
var r = filterFn.call(options.wiki,function(iterator) {
iterator(options.wiki.getTiddler(title),title);
},options.widget.makeFakeWidgetWithVariables({
"currentTiddler": "" + title,
"..currentTiddler": options.widget.getVariable("currentTiddler")
}));
},{
getVariable: function(name) {
switch(name) {
case "currentTiddler":
return "" + title;
case "..currentTiddler":
return options.widget.getVariable("currentTiddler");
default:
return options.widget.getVariable(name);
}
}
});
sortKeys.push(r[0] || "");
});
// Rather than sorting the titles array, we'll sort the indexes so that we can consult both arrays

View File

@@ -74,113 +74,6 @@ 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 = [];
@@ -291,4 +184,4 @@ exports.charcode = function(source,operator,options) {
return [chars.join("")];
};
})();
})();

View File

@@ -1,45 +0,0 @@
/*\
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);
};
})();

View File

@@ -32,18 +32,18 @@ FieldIndexer.prototype.setMaxIndexedValueLength = function(length) {
FieldIndexer.prototype.addIndexMethods = function() {
var self = this;
// get all tiddlers, including those overwrite shadow tiddlers
this.wiki.each.byField = function(name,value) {
var lookup = self.lookup(name,value);
var titles = self.wiki.allTitles(),
lookup = self.lookup(name,value);
return lookup && lookup.filter(function(title) {
return self.wiki.tiddlerExists(title)
return titles.indexOf(title) !== -1;
});
};
// get shadow tiddlers, including shadow tiddlers that is overwritten
this.wiki.eachShadow.byField = function(name,value) {
var lookup = self.lookup(name,value);
var titles = self.wiki.allShadowTitles(),
lookup = self.lookup(name,value);
return lookup && lookup.filter(function(title) {
return self.wiki.isShadowTiddler(title)
return titles.indexOf(title) !== -1;
});
};
this.wiki.eachTiddlerPlusShadows.byField = function(name,value) {

View File

@@ -28,8 +28,6 @@ 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;

View File

@@ -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,8 +64,6 @@ var BinaryParser = function(type,text,options) {
children: [warn, link]
}
this.tree = [element];
this.source = text;
this.type = type;
};
exports["application/octet-stream"] = BinaryParser;

View File

@@ -52,8 +52,6 @@ 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;

View File

@@ -29,8 +29,6 @@ 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;

View File

@@ -28,8 +28,6 @@ var ImageParser = function(type,text,options) {
}
}
this.tree = [element];
this.source = text;
this.type = type;
};
exports["image/svg+xml"] = ImageParser;

View File

@@ -123,36 +123,6 @@ 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);
@@ -205,36 +175,7 @@ exports.parseMacroParameter = function(source,pos) {
};
/*
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:}
Look for a macro invocation. Returns null if not found, or {type: "macrocall", name:, parameters:, start:, end:}
*/
exports.parseMacroInvocation = function(source,pos) {
var node = {

View File

@@ -15,7 +15,7 @@ The PDF parser embeds a PDF viewer
var ImageParser = function(type,text,options) {
var element = {
type: "element",
tag: "iframe",
tag: "embed",
attributes: {}
},
src;
@@ -25,8 +25,6 @@ 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;

View File

@@ -20,8 +20,6 @@ var TextParser = function(type,text,options) {
language: {type: "string", value: type}
}
}];
this.source = text;
this.type = type;
};
exports["text/plain"] = TextParser;

View File

@@ -28,8 +28,6 @@ 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;

View File

@@ -1,97 +0,0 @@
/*\
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;
};
})();

View File

@@ -93,6 +93,9 @@ 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);
}

View File

@@ -25,7 +25,7 @@ Instantiate parse rule
exports.init = function(parser) {
this.parser = parser;
// Regexp to match
this.matchRegExp = /\\import[^\S\n]/mg;
this.matchRegExp = /^\\import[^\S\n]/mg;
};
/*

View File

@@ -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.parseMacroInvocationAsTransclusion(this.parser.source,nextStart);
var nextCall = $tw.utils.parseMacroInvocation(this.parser.source,nextStart);
if(nextCall) {
var c = this.parser.source.charAt(nextCall.end);
// Ensure EOL after parsed macro

View File

@@ -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.parseMacroInvocationAsTransclusion(this.parser.source,nextStart);
this.nextCall = $tw.utils.parseMacroInvocation(this.parser.source,nextStart);
if(this.nextCall) {
return nextStart;
}

View File

@@ -27,7 +27,7 @@ Instantiate parse rule
exports.init = function(parser) {
this.parser = parser;
// Regexp to match
this.matchRegExp = /\\define\s+([^(\s]+)\(\s*([^)]*)\)(\s*\r?\n)?/mg;
this.matchRegExp = /^\\define\s+([^(\s]+)\(\s*([^)]*)\)(\s*\r?\n)?/mg;
};
/*
@@ -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\\n\\r]*\\\\end[^\\S\\n\\r]*(?:" + $tw.utils.escapeRegExp(this.match[1]) + ")?(?:$|\\r?\\n))","mg");
reEnd = new RegExp("(\\r?\\n\\\\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
var parseTreeNodes = [{
return [{
type: "set",
attributes: {},
attributes: {
name: {type: "string", value: this.match[1]},
value: {type: "string", value: text}
},
children: [],
params: params,
isMacroDefinition: true
}];
$tw.utils.addAttributeToParseTreeNode(parseTreeNodes[0],"name",this.match[1]);
$tw.utils.addAttributeToParseTreeNode(parseTreeNodes[0],"value",text);
return parseTreeNodes;
};
})();

View File

@@ -1,60 +0,0 @@
/*\
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
}];
};
})();

View File

@@ -26,7 +26,7 @@ Instantiate parse rule
exports.init = function(parser) {
this.parser = parser;
// Regexp to match
this.matchRegExp = /\\parsermode[^\S\n]/mg;
this.matchRegExp = /^\\parsermode[^\S\n]/mg;
};
/*

View File

@@ -26,7 +26,7 @@ Instantiate parse rule
exports.init = function(parser) {
this.parser = parser;
// Regexp to match
this.matchRegExp = /\\rules[^\S\n]/mg;
this.matchRegExp = /^\\rules[^\S\n]/mg;
};
/*

View File

@@ -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,22 +31,13 @@ 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]),
params = this.match[3] ? this.match[3].split("|") : [];
textRef = $tw.utils.trim(this.match[1]);
// 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) {
@@ -57,14 +48,14 @@ exports.parse = function() {
tiddlerNode = {
type: "tiddler",
attributes: {
tiddler: {name: "tiddler", type: "string", value: targetTitle}
tiddler: {type: "string", value: targetTitle}
},
isBlock: true,
children: [transcludeNode]
};
}
if(template) {
transcludeNode.attributes["$tiddler"] = {name: "$tiddler", type: "string", value: template};
transcludeNode.attributes.tiddler = {type: "string", value: template};
if(textRef) {
return [tiddlerNode];
} else {
@@ -72,12 +63,12 @@ exports.parse = function() {
}
} else {
if(textRef) {
transcludeNode.attributes["$tiddler"] = {name: "$tiddler", type: "string", value: targetTitle};
transcludeNode.attributes.tiddler = {type: "string", value: targetTitle};
if(targetField) {
transcludeNode.attributes["$field"] = {name: "$field", type: "string", value: targetField};
transcludeNode.attributes.field = {type: "string", value: targetField};
}
if(targetIndex) {
transcludeNode.attributes["$index"] = {name: "$index", type: "string", value: targetIndex};
transcludeNode.attributes.index = {type: "string", value: targetIndex};
}
return [tiddlerNode];
} else {

View File

@@ -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,21 +31,12 @@ 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]),
params = this.match[3] ? this.match[3].split("|") : [];
textRef = $tw.utils.trim(this.match[1]);
// 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) {
@@ -56,13 +47,13 @@ exports.parse = function() {
tiddlerNode = {
type: "tiddler",
attributes: {
tiddler: {name: "tiddler", type: "string", value: targetTitle}
tiddler: {type: "string", value: targetTitle}
},
children: [transcludeNode]
};
}
if(template) {
transcludeNode.attributes["$tiddler"] = {name: "$tiddler", type: "string", value: template};
transcludeNode.attributes.tiddler = {type: "string", value: template};
if(textRef) {
return [tiddlerNode];
} else {
@@ -70,12 +61,12 @@ exports.parse = function() {
}
} else {
if(textRef) {
transcludeNode.attributes["$tiddler"] = {name: "$tiddler", type: "string", value: targetTitle};
transcludeNode.attributes.tiddler = {type: "string", value: targetTitle};
if(targetField) {
transcludeNode.attributes["$field"] = {name: "$field", type: "string", value: targetField};
transcludeNode.attributes.field = {type: "string", value: targetField};
}
if(targetIndex) {
transcludeNode.attributes["$index"] = {name: "$index", type: "string", value: targetIndex};
transcludeNode.attributes.index = {type: "string", value: targetIndex};
}
return [tiddlerNode];
} else {

View File

@@ -26,7 +26,7 @@ Instantiate parse rule
exports.init = function(parser) {
this.parser = parser;
// Regexp to match
this.matchRegExp = /\\whitespace[^\S\n]/mg;
this.matchRegExp = /^\\whitespace[^\S\n]/mg;
};
/*

View File

@@ -32,7 +32,6 @@ 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;
@@ -47,7 +46,7 @@ var WikiParser = function(type,text,options) {
this.source = text || "";
this.sourceLength = this.source.length;
// Flag for ignoring whitespace
this.configTrimWhiteSpace = options.configTrimWhiteSpace !== undefined ? options.configTrimWhiteSpace : false;
this.configTrimWhiteSpace = false;
// Parser mode
this.parseAsInline = options.parseAsInline;
// Set current parse position

View File

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

View File

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

View File

@@ -21,7 +21,6 @@ exports.handler = function(request,response,state) {
username: state.authenticatedUsername || state.server.get("anon-username") || "",
anonymous: !state.authenticatedUsername,
read_only: !state.server.isAuthorized("writers",state.authenticatedUsername),
logout_is_available: false,
space: {
recipe: "default"
},

View File

@@ -87,6 +87,13 @@ exports.startup = function() {
}
});
}
// If we're being viewed on a data: URI then give instructions for how to save
if(document.location.protocol === "data:") {
$tw.rootWidget.dispatchEvent({
type: "tm-modal",
param: "$:/language/Modals/SaveInstructions"
});
}
};
})();

View File

@@ -17,10 +17,6 @@ var easing = "cubic-bezier(0.645, 0.045, 0.355, 1)"; // From http://easings.net/
var ZoominListView = function(listWidget) {
var self = this;
this.listWidget = listWidget;
this.textNodeLogger = new $tw.utils.Logger("zoomin story river view", {
enable: true,
colour: 'red'
});
// Get the index of the tiddler that is at the top of the history
var history = this.listWidget.wiki.getTiddlerDataCached(this.listWidget.historyTitle,[]),
targetTiddler;
@@ -52,10 +48,7 @@ ZoominListView.prototype.navigateTo = function(historyInfo) {
var listItemWidget = this.listWidget.children[listElementIndex],
targetElement = listItemWidget.findFirstDomNode();
// Abandon if the list entry isn't a DOM element (it might be a text node)
if(!targetElement) {
return;
} else if (targetElement.nodeType === Node.TEXT_NODE) {
this.logTextNodeRoot(targetElement);
if(!targetElement || targetElement.nodeType === Node.TEXT_NODE) {
return;
}
// Make the new tiddler be position absolute and visible so that we can measure it
@@ -137,10 +130,7 @@ function findTitleDomNode(widget,targetClass) {
ZoominListView.prototype.insert = function(widget) {
var targetElement = widget.findFirstDomNode();
// Abandon if the list entry isn't a DOM element (it might be a text node)
if(!targetElement) {
return;
} else if (targetElement.nodeType === Node.TEXT_NODE) {
this.logTextNodeRoot(targetElement);
if(!targetElement || targetElement.nodeType === Node.TEXT_NODE) {
return;
}
// Make the newly inserted node position absolute and hidden
@@ -183,21 +173,16 @@ ZoominListView.prototype.remove = function(widget) {
var toWidgetDomNode = toWidget && toWidget.findFirstDomNode();
// Set up the tiddler we're moving back in
if(toWidgetDomNode) {
if (toWidgetDomNode.nodeType === Node.TEXT_NODE) {
this.logTextNodeRoot(toWidgetDomNode);
toWidgetDomNode = null;
} else {
$tw.utils.addClass(toWidgetDomNode,"tc-storyview-zoomin-tiddler");
$tw.utils.setStyle(toWidgetDomNode,[
{display: "block"},
{transformOrigin: "50% 50%"},
{transform: "translateX(0px) translateY(0px) scale(10)"},
{transition: $tw.utils.roundTripPropertyName("transform") + " " + duration + "ms " + easing + ", opacity " + duration + "ms " + easing},
{opacity: "0"},
{zIndex: "500"}
]);
this.currentTiddlerDomNode = toWidgetDomNode;
}
$tw.utils.addClass(toWidgetDomNode,"tc-storyview-zoomin-tiddler");
$tw.utils.setStyle(toWidgetDomNode,[
{display: "block"},
{transformOrigin: "50% 50%"},
{transform: "translateX(0px) translateY(0px) scale(10)"},
{transition: $tw.utils.roundTripPropertyName("transform") + " " + duration + "ms " + easing + ", opacity " + duration + "ms " + easing},
{opacity: "0"},
{zIndex: "500"}
]);
this.currentTiddlerDomNode = toWidgetDomNode;
}
// Animate them both
// Force layout
@@ -221,10 +206,6 @@ ZoominListView.prototype.remove = function(widget) {
return true; // Indicate that we'll delete the DOM node
};
ZoominListView.prototype.logTextNodeRoot = function(node) {
this.textNodeLogger.log($tw.language.getString("Error/ZoominTextNode") + " " + node.textContent);
};
exports.zoomin = ZoominListView;
})();

View File

@@ -402,7 +402,6 @@ Syncer.prototype.handleLazyLoadEvent = function(title) {
// Mark the tiddler as needing loading, and having already been lazily loaded
this.titlesToBeLoaded[title] = true;
this.titlesHaveBeenLazyLoaded[title] = true;
this.processTaskQueue();
}
}
};

View File

@@ -28,24 +28,6 @@ exports.domMatchesSelector = function(node,selector) {
return node.matches ? node.matches(selector) : node.msMatchesSelector(selector);
};
/*
Select text in a an input or textarea (setSelectionRange crashes on certain input types)
*/
exports.setSelectionRangeSafe = function(node,start,end,direction) {
try {
node.setSelectionRange(start,end,direction);
} catch(e) {
node.select();
}
};
/*
Select the text in an input or textarea by position
*/
exports.setSelectionByPosition = function(node,selectFromStart,selectFromEnd) {
$tw.utils.setSelectionRangeSafe(node,selectFromStart,node.value.length - selectFromEnd);
};
exports.removeChildren = function(node) {
while(node.hasChildNodes()) {
node.removeChild(node.firstChild);

View File

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

View File

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

View File

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

View File

@@ -34,10 +34,6 @@ ElementWidget.prototype.render = function(parent,nextSibling) {
if($tw.config.htmlUnsafeElements.indexOf(this.tag) !== -1) {
this.tag = "safe-" + this.tag;
}
// Restrict tag name to digits, letts and dashes
this.tag = this.tag.replace(/[^0-9a-zA-Z\-]/mg,"");
// Default to a span
this.tag = this.tag || "span";
// Adjust headings by the current base level
var headingLevel = ["h1","h2","h3","h4","h5","h6"].indexOf(this.tag);
if(headingLevel !== -1) {

View File

@@ -1,30 +0,0 @@
/*\
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;
})();

View File

@@ -42,16 +42,10 @@ Compute the internal state of the widget
GenesisWidget.prototype.execute = function() {
var self = this;
// Collect attributes
this.genesisType = this.getAttribute("$type");
this.genesisType = this.getAttribute("$type","element");
this.genesisRemappable = this.getAttribute("$remappable","yes") === "yes";
this.genesisNames = this.getAttribute("$names","");
this.genesisValues = this.getAttribute("$values","");
this.genesisIsBlock = this.getAttribute("$mode",this.parseTreeNode.isBlock && "block") === "block";
// Do not create a child widget if the $type attribute is missing or blank
if(!this.genesisType) {
this.makeChildWidgets(this.parseTreeNode.children);
return;
}
// Construct parse tree
var isElementWidget = this.genesisType.charAt(0) !== "$",
nodeType = isElementWidget ? "element" : this.genesisType.substr(1),
@@ -61,7 +55,6 @@ GenesisWidget.prototype.execute = function() {
tag: nodeTag,
attributes: {},
orderedAttributes: [],
isBlock: this.genesisIsBlock,
children: this.parseTreeNode.children || [],
isNotRemappable: !this.genesisRemappable
}];

View File

@@ -52,44 +52,38 @@ ImportVariablesWidget.prototype.execute = function(tiddlerList) {
var parser = widgetPointer.wiki.parseTiddler(title,{parseAsInline:true});
if(parser) {
var parseTreeNode = parser.tree[0];
while(parseTreeNode && ["setvariable","set","parameters"].indexOf(parseTreeNode.type) !== -1) {
while(parseTreeNode && parseTreeNode.type === "set") {
var node = {
type: "set",
attributes: parseTreeNode.attributes,
params: parseTreeNode.params,
isMacroDefinition: parseTreeNode.isMacroDefinition,
isFunctionDefinition: parseTreeNode.isFunctionDefinition,
isProcedureDefinition: parseTreeNode.isProcedureDefinition,
isWidgetDefinition: parseTreeNode.isWidgetDefinition,
configTrimWhiteSpace: parseTreeNode.configTrimWhiteSpace
isMacroDefinition: parseTreeNode.isMacroDefinition
};
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];
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(){};
}
widgetPointer = widgetPointer.children[0];
}
parseTreeNode = parseTreeNode.children && parseTreeNode.children[0];
}

View File

@@ -53,9 +53,7 @@ LetWidget.prototype.computeAttributes = function() {
name = attribute.name;
// Now that it's prepped, we're allowed to look this variable up
// when defining later variables
if(value !== undefined) {
self.currentValueFor[name] = value;
}
self.currentValueFor[name] = value;
});
// Run through again, setting variables and looking for differences
$tw.utils.each(this.currentValueFor,function(value,name) {

View File

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

View File

@@ -37,7 +37,7 @@ MacroCallWidget.prototype.render = function(parent,nextSibling) {
Compute the internal state of the widget
*/
MacroCallWidget.prototype.execute = function() {
this.macroName = this.parseTreeNode.name || this.getAttribute("$name"),
// Get the parse type if specified
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,26 +47,49 @@ MacroCallWidget.prototype.execute = function() {
params.push({name: name, value: attribute});
}
});
// Make a transclude widget
var positionalName = 0,
parseTreeNodes = [{
type: "transclude",
isBlock: this.parseTreeNode.isBlock
}];
$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);
// 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 {
$tw.utils.addAttributeToParseTreeNode(parseTreeNodes[0],(positionalName++) + "",param.value);
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
};
});
parseTreeNodes = [{
type: "vars",
attributes: attributes,
children: parseTreeNodes
}];
} 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}];
}
// Construct the child widgets
this.makeChildWidgets(parseTreeNodes);
};

View File

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

View File

@@ -227,7 +227,10 @@ NavigatorWidget.prototype.handleDeleteTiddlerEvent = function(event) {
originalTitle = tiddler ? tiddler.fields["draft.of"] : "",
originalTiddler = originalTitle ? this.wiki.getTiddler(originalTitle) : undefined,
confirmationTitle,
win = event.event && event.event.view ? event.event.view : window;
win = event.event && event.event.view ? event.event.view : window;
if(!tiddler) {
return false;
}
// Check if the tiddler we're deleting is in draft mode
if(originalTitle) {
// If so, we'll prompt for confirmation referencing the original tiddler
@@ -237,7 +240,7 @@ NavigatorWidget.prototype.handleDeleteTiddlerEvent = function(event) {
confirmationTitle = title;
}
// Seek confirmation
if(((originalTitle && this.wiki.getTiddler(originalTitle)) || (tiddler && ((tiddler.fields.text || "") !== ""))) && !win.confirm($tw.language.getString(
if((this.wiki.getTiddler(originalTitle) || (tiddler.fields.text || "") !== "") && !win.confirm($tw.language.getString(
"ConfirmDeleteTiddler",
{variables:
{title: confirmationTitle}
@@ -254,10 +257,8 @@ NavigatorWidget.prototype.handleDeleteTiddlerEvent = function(event) {
this.removeTitleFromStory(storyList,originalTitle);
}
// Invoke the hook function and delete this tiddler
if(tiddler) {
$tw.hooks.invokeHook("th-deleting-tiddler",tiddler);
this.wiki.deleteTiddler(title);
}
$tw.hooks.invokeHook("th-deleting-tiddler",tiddler);
this.wiki.deleteTiddler(title);
// Remove the closed tiddler from the story
this.removeTitleFromStory(storyList,title);
this.saveStoryList(storyList);
@@ -499,8 +500,7 @@ NavigatorWidget.prototype.handleImportTiddlersEvent = function(event) {
// Get the tiddlers
var tiddlers = $tw.utils.parseJSONSafe(event.param,[]);
// Get the current $:/Import tiddler
var paramObject = event.paramObject || {},
importTitle = event.importTitle || paramObject.importTitle || IMPORT_TITLE,
var importTitle = event.importTitle ? event.importTitle : IMPORT_TITLE,
importTiddler = this.wiki.getTiddler(importTitle),
importData = this.wiki.getTiddlerData(importTitle,{}),
newFields = new Object({
@@ -541,7 +541,7 @@ NavigatorWidget.prototype.handleImportTiddlersEvent = function(event) {
newFields.text = JSON.stringify(importData,null,$tw.config.preferences.jsonSpaces);
this.wiki.addTiddler(new $tw.Tiddler(importTiddler,newFields));
// Update the story and history details
var autoOpenOnImport = event.autoOpenOnImport || paramObject.autoOpenOnImport || this.getVariable("tv-auto-open-on-import");
var autoOpenOnImport = event.autoOpenOnImport ? event.autoOpenOnImport : this.getVariable("tv-auto-open-on-import");
if(autoOpenOnImport !== "no") {
var storyList = this.getStoryList(),
history = [];

View File

@@ -1,96 +0,0 @@
/*\
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;
})();

View File

@@ -48,17 +48,7 @@ SetWidget.prototype.execute = function() {
this.setValue = this.getAttribute("value");
this.setEmptyValue = this.getAttribute("emptyValue");
// Set context variable
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());
}
this.setVariable(this.setName,this.getValue(),this.parseTreeNode.params,!!this.parseTreeNode.isMacroDefinition);
// Construct the child widgets
this.makeChildWidgets();
};

View File

@@ -1,82 +0,0 @@
/*\
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;
})();

View File

@@ -37,349 +37,46 @@ TranscludeWidget.prototype.render = function(parent,nextSibling) {
Compute the internal state of the widget
*/
TranscludeWidget.prototype.execute = function() {
// 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
// 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
var parseAsInline = !this.parseTreeNode.isBlock;
if(this.transcludeMode === "inline") {
parseAsInline = true;
} else if(this.transcludeMode === "block") {
parseAsInline = false;
}
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(
var parser = this.wiki.parseTextReference(
this.transcludeTitle,
this.transcludeField,
this.transcludeIndex,
{
parseAsInline: parseAsInline,
subTiddler: this.transcludeSubTiddler,
defaultType: this.transcludeType
});
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);
}
// Set 'thisTiddler'
this.setVariable("thisTiddler",this.transcludeTitle);
// Return the parse tree
// Check for recursion
if(parser) {
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];
if(this.parentWidget && this.parentWidget.hasVariable("transclusion",recursionMarker)) {
parseTreeNodes = [{type: "error", attributes: {
"$message": {type: "string", value: $tw.language.getString("Error/RecursiveTransclusion")}
}}];
}
}
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 || [];
}
// Construct the child widgets
this.makeChildWidgets(parseTreeNodes);
};
/*
@@ -402,7 +99,6 @@ 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)
};
@@ -412,7 +108,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) || (!this.transcludeVariable && changedTiddlers[this.transcludeTitle] && this.parserNeedsRefresh())) {
if(($tw.utils.count(changedAttributes) > 0) || (changedTiddlers[this.transcludeTitle] && this.parserNeedsRefresh())) {
this.refreshSelf();
return true;
} else {

View File

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

View File

@@ -41,7 +41,10 @@ Widget.prototype.initialise = function(parseTreeNode,options) {
this.parseTreeNode = parseTreeNode;
this.wiki = options.wiki;
this.parentWidget = options.parentWidget;
this.variables = Object.create(this.parentWidget ? this.parentWidget.variables : null);
this.variables = Object.create(null);
if(this.parentWidget) {
Object.setPrototypeOf(this.variables,this.parentWidget.variables);
}
this.document = options.document;
this.attributes = {};
this.children = [];
@@ -89,22 +92,9 @@ 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,options) {
options = options || {};
this.variables[name] = {
value: value,
params: params,
isMacroDefinition: !!isMacroDefinition,
isFunctionDefinition: !!options.isFunctionDefinition,
isProcedureDefinition: !!options.isProcedureDefinition,
isWidgetDefinition: !!options.isWidgetDefinition,
configTrimWhiteSpace: !!options.configTrimWhiteSpace
};
Widget.prototype.setVariable = function(name,value,params,isMacroDefinition) {
this.variables[name] = {value: value, params: params, isMacroDefinition: !!isMacroDefinition};
};
/*
@@ -114,7 +104,6 @@ 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:
@@ -123,27 +112,21 @@ text: text of variable, with parameters properly substituted
*/
Widget.prototype.getVariableInfo = function(name,options) {
options = options || {};
var self = this,
actualParams = options.params || [],
variable;
if(options.allowSelfAssigned) {
variable = this.variables[name];
} else {
variable = this.parentWidget && this.parentWidget.variables[name];
}
var actualParams = options.params || [],
parentWidget = this.parentWidget;
// Check for the variable defined in the parent widget (or an ancestor in the prototype chain)
if(variable) {
var originalValue = variable.value,
if(parentWidget && name in parentWidget.variables) {
var variable = parentWidget.variables[name],
originalValue = variable.value,
value = originalValue,
params = [];
// Only substitute parameter and variable references if this variable was defined with the \define pragma
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
if(variable.isMacroDefinition) {
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);
value = this.substituteVariableReferences(value,options);
}
return {
text: value,
@@ -153,13 +136,8 @@ 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: text,
srcVariable: {}
text: this.evaluateMacroModule(name,actualParams,options.defaultValue)
};
};
@@ -170,11 +148,6 @@ 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 || [];
@@ -187,7 +160,7 @@ Widget.prototype.resolveVariableParameters = function(formalParams,actualParams)
paramInfo = formalParams[p];
paramValue = undefined;
for(var m=0; m<actualParams.length; m++) {
if(typeof actualParams[m] !== "string" && actualParams[m].name === paramInfo.name) {
if(actualParams[m].name === paramInfo.name) {
paramValue = actualParams[m].value;
}
}
@@ -196,8 +169,7 @@ Widget.prototype.resolveVariableParameters = function(formalParams,actualParams)
nextAnonParameter++;
}
if(paramValue === undefined && nextAnonParameter < actualParams.length) {
var param = actualParams[nextAnonParameter++];
paramValue = typeof param === "string" ? param : param.value;
paramValue = actualParams[nextAnonParameter++].value;
}
// If we've still not got a value, use the default, if any
paramValue = paramValue || paramInfo["default"] || "";
@@ -291,103 +263,12 @@ Widget.prototype.getStateQualifier = function(name) {
};
/*
Make a fake widget with specified variables, suitable for variable lookup in filters
Compute the current values of the attributes of the widget. Returns a hashmap of the names of the attributes that have changed
*/
Widget.prototype.makeFakeWidgetWithVariables = function(variables) {
var self = this;
return {
getVariable: function(name,opts) {
if($tw.utils.hop(variables,name)) {
return variables[name];
} else {
opts = opts || {};
opts.variables = variables;
return self.getVariable(name,opts);
};
},
getVariableInfo: function(name,opts) {
if($tw.utils.hop(variables,name)) {
return {
text: variables[name]
};
} else {
opts = opts || {};
opts.variables = variables;
return self.getVariableInfo(name,opts);
};
},
makeFakeWidgetWithVariables: self.makeFakeWidgetWithVariables,
evaluateVariable: self.evaluateVariable,
resolveVariableParameters: self.resolveVariableParameters,
wiki: self.wiki
};
};
/*
Evaluate a variable and associated actual parameters and result the resulting array.
The way that the variable is evaluated depends upon its type:
* Functions are evaluated as parameterised filter strings
* Macros are returned as plain text with substitution of parameters
* Procedures and widgets are returned as plain text
Options are:
params - the actual parameters may be one of:
* an array of values that may be an anonymous string value, or a {name:, value:} pair
* a hashmap of {name: value} pairs
* a function invoked with parameters (name,index) that returns a parameter value by name or position
source - iterator for source tiddlers
*/
Widget.prototype.evaluateVariable = function(name,options) {
options = options || {};
var params = options.params || [];
// Get the details of the variable (includes processing text substitution for macros
var variableInfo = this.getVariableInfo(name,{params: params,defaultValue: ""});
// Process function parameters
var variables = Object.create(null);
if(variableInfo.srcVariable && variableInfo.srcVariable.isFunctionDefinition) {
// Apply default parameter values
$tw.utils.each(variableInfo.srcVariable.params,function(param,index) {
if(param["default"]) {
variables[param.name] = param["default"];
}
});
if($tw.utils.isArray(params)) {
// Parameters are an array of values or {name:, value:} pairs
$tw.utils.each(this.resolveVariableParameters(variableInfo.srcVariable.params,params),function(param) {
variables[param.name] = param.value;
});
} else if(typeof params === "function") {
// Parameters are passed via a function
$tw.utils.each(variableInfo.srcVariable.params,function(param,index) {
variables[param.name] = params(param.name,index) || param["default"] || "";
});
} else {
// Parameters are a hashmap
$tw.utils.each(params,function(value,name) {
variables[name] = value;
});
}
return this.wiki.filterTiddlers(variableInfo.text,this.makeFakeWidgetWithVariables(variables),options.source);
} else {
return [variableInfo.text];
}
};
/*
Compute the current values of the attributes of the widget. Returns a hashmap of the names of the attributes that have changed.
Options include:
filterFn: only include attributes where filterFn(name) returns true
*/
Widget.prototype.computeAttributes = function(options) {
options = options || {};
Widget.prototype.computeAttributes = function() {
var changedAttributes = {},
self = this;
$tw.utils.each(this.parseTreeNode.attributes,function(attribute,name) {
if(options.filterFn) {
if(!options.filterFn(name)) {
return;
}
}
var value = self.computeAttribute(attribute);
if(self.attributes[name] !== value) {
self.attributes[name] = value;
@@ -398,21 +279,13 @@ Widget.prototype.computeAttributes = function(options) {
};
Widget.prototype.computeAttribute = function(attribute) {
var self = this,
value;
var value;
if(attribute.type === "filtered") {
value = this.wiki.filterTiddlers(attribute.filter,this)[0] || "";
} else if(attribute.type === "indirect") {
value = this.wiki.getTextReference(attribute.textReference,"",this.getVariable("currentTiddler"));
} else if(attribute.type === "macro") {
var variableInfo = this.getVariableInfo(attribute.value.name,{params: attribute.value.params});
if(variableInfo.srcVariable && variableInfo.srcVariable.isFunctionDefinition) {
// It is a function definition. Go through each of the defined parameters, and make a variable with the value of the corresponding provided parameter
var paramArray = this.resolveVariableParameters(variableInfo.srcVariable.params,attribute.value.params);
value = this.evaluateVariable(attribute.value.name,{params: paramArray})[0] || "";
} else {
value = variableInfo.text;
}
value = this.getVariable(attribute.value.name,{params: attribute.value.params});
} else { // String attribute
value = attribute.value;
}
@@ -540,34 +413,7 @@ options include:
variables: optional hashmap of variables to wrap around the widget
*/
Widget.prototype.makeChildWidget = function(parseTreeNode,options) {
var self = this;
options = options || {};
// Check whether this node type is defined by a custom widget definition
var variableDefinitionName = "$" + parseTreeNode.type;
if(this.variables[variableDefinitionName]) {
var isOverrideable = function() {
// Widget is overrideable if it has a double dollar user defined name, or if it is an existing JS widget and we're not in safe mode
return parseTreeNode.type.charAt(0) === "$" || (!!self.widgetClasses[parseTreeNode.type] && !$tw.safeMode);
};
if(!parseTreeNode.isNotRemappable && isOverrideable()) {
var variableInfo = this.getVariableInfo(variableDefinitionName,{allowSelfAssigned: true});
if(variableInfo && variableInfo.srcVariable && variableInfo.srcVariable.value && variableInfo.srcVariable.isWidgetDefinition) {
var newParseTreeNode = {
type: "transclude",
children: parseTreeNode.children,
isBlock: parseTreeNode.isBlock
};
$tw.utils.addAttributeToParseTreeNode(newParseTreeNode,"$variable",variableDefinitionName);
$tw.utils.each(parseTreeNode.attributes,function(attr,name) {
// If the attribute starts with a dollar then add an extra dollar so that it doesn't clash with the $xxx attributes of transclude
name = name.charAt(0) === "$" ? "$" + name : name;
$tw.utils.addAttributeToParseTreeNode(newParseTreeNode,$tw.utils.extend({},attr,{name: name}));
});
parseTreeNode = newParseTreeNode;
}
}
}
// Get the widget class for this node type
var WidgetClass = this.widgetClasses[parseTreeNode.type];
if(!WidgetClass) {
WidgetClass = this.widgetClasses.text;

View File

@@ -988,8 +988,7 @@ exports.parseText = function(type,text,options) {
return new Parser(type,text,{
parseAsInline: options.parseAsInline,
wiki: this,
_canonical_uri: options._canonical_uri,
configTrimWhiteSpace: options.configTrimWhiteSpace
_canonical_uri: options._canonical_uri
});
};
@@ -1029,11 +1028,10 @@ exports.parseTextReference = function(title,field,index,options) {
};
exports.getTextReferenceParserInfo = function(title,field,index,options) {
var defaultType = options.defaultType || "text/vnd.tiddlywiki",
tiddler,
var tiddler,
parserInfo = {
sourceText : null,
parserType : defaultType
parserType : "text/vnd.tiddlywiki"
};
if(options.subTiddler) {
tiddler = this.getSubTiddler(title,options.subTiddler);
@@ -1079,20 +1077,19 @@ exports.makeWidget = function(parser,options) {
children: []
},
currWidgetNode = widgetNode;
// Create let variable widget for variables
if($tw.utils.count(options.variables) > 0) {
var letVariableWidget = {
type: "let",
// Create set variable widgets for each variable
$tw.utils.each(options.variables,function(value,name) {
var setVariableWidget = {
type: "set",
attributes: {
name: {type: "string", value: name},
value: {type: "string", value: value}
},
children: []
};
$tw.utils.each(options.variables,function(value,name) {
$tw.utils.addAttributeToParseTreeNode(letVariableWidget,name,"" + value);
});
currWidgetNode.children = [letVariableWidget];
currWidgetNode = letVariableWidget;
}
currWidgetNode.children = [setVariableWidget];
currWidgetNode = setVariableWidget;
});
// Add in the supplied parse tree nodes
currWidgetNode.children = parser ? parser.tree : [];
// Create the widget

View File

@@ -14,7 +14,6 @@ extension: .html
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<meta name="generator" content="TiddlyWiki" />
<meta name="tiddlywiki-version" content="{{$:/core/templates/version}}" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="format-detection" content="telephone=no">
<link id="faviconLink" rel="shortcut icon" href="favicon.ico">
<title>{{$:/core/wiki/title}}</title>

View File

@@ -1,14 +1,10 @@
title: $:/core/save/all-external-js
\whitespace trim
\import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]
\define saveTiddlerFilter()
[is[tiddler]] -[prefix[$:/state/popup/]] -[prefix[$:/temp/]] -[prefix[$:/HistoryList]] -[status[pending]plugin-type[import]] -[[$:/core]] -[[$:/boot/boot.css]] -[type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] +[sort[title]] $(publishFilter)$
\end
<!-- Important: core library is provided by serving URI encoded $:/core/templates/tiddlywiki5.js -->
\define defaultCoreURL() %24%3A%2Fcore%2Ftemplates%2Ftiddlywiki5.js
<$let coreURL={{{ [[coreURL]is[variable]then<coreURL>else<defaultCoreURL>] }}}>
{{$:/core/templates/tiddlywiki5-external-js.html}}
</$let>

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,48 +0,0 @@
title: $:/core/ui/VisibleTransclude
<!--
Import this component to make all the child transclusions visible.
Block transclusions are shown in red, and inline transclusions are shown in green.
-->
\widget $transclude()
<!-- Use a parameters widget so that we can access the `$params` data -->
<$parameters tiddler="" $$tiddler="" mode="" $$mode="" $parseMode="@parseMode" $params="@params">
<!-- Replicate the logic of the transclude widget to determine the output mode, and hence the tag and colour to use for output -->
<$let
mode={{{ [[$mode]is[variable]then<$mode>!is[blank]] :else[[mode]is[variable]then<mode>!is[blank]] :else[<@parseMode>] }}}
outputTag={{{ [<mode>match[inline]then[span]else[div]] }}}
outputColour={{{ [<mode>match[inline]then[green]else[red]] }}}
>
<!-- Use divs or spans according to the mode -->
<$genesis $type=<<outputTag>> style="color:white;padding:4px;" style.background=<<outputColour>>>
<$genesis $type=<<outputTag>> style="display: inline-block;">
<div style="background:white;color:black;font-size: 12px;line-height:1.2;text-align:left;font-weight:normal;padding:4px;margin:4px;">
<!-- Render the parameters to the transclusion -->
<$list filter="[<@params>jsonindexes[]]" emptyMessage="(none)">
<div>
<$text text=<<currentTiddler>>/><$text text=": "/><$text text={{{ [<@params>jsonget<currentTiddler>] }}}/>
</div>
</$list>
</div>
</$genesis>
<$genesis $type=<<outputTag>> style="background:white;color:black;padding:4px;">
<!-- Look for a parameter starting with $ to determine if we are in legacy mode -->
<$list filter="[<@params>jsonindexes[]] :filter[<currentTiddler>prefix[$]] +[limit[1]]" variable="ignore" emptyMessage="""
<!-- Legacy mode: we render the transclusion without a dollar sign for recursionMarker and mode -->
<$genesis $type="$transclude" $remappable="no" $names="[<@params>jsonindexes[]]" $values="[<@params>jsonindexes[]] :map[<@params>jsonget<currentTiddler>]" recursionMarker="no" mode=<<mode>>>
<!-- Reach back up to the grandparent transclusion to get the correct slot value -->
<$slot $name="ts-raw" $depth="2"/>
</$genesis>
""">
<!-- Non-legacy mode: we use dollar signs for the recursionMarker and mode -->
<$genesis $type="$transclude" $remappable="no" $names="[<@params>jsonindexes[]]" $values="[<@params>jsonindexes[]] :map[<@params>jsonget<currentTiddler>]" $$recursionMarker="no" $$mode=<<mode>>>
<!-- Reach back up to the grandparent transclusion to get the correct slot fill value -->
<$slot $name="ts-raw" $depth="2"/>
</$genesis>
</$list>
</$genesis>
</$genesis>
</$let>
</$parameters>
\end

View File

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

View File

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

View File

@@ -46,7 +46,9 @@ title: $:/core/ui/EditTemplate
<$keyboard key="((cancel-edit-tiddler))" actions=<<cancel-delete-tiddler-actions "cancel">> tag="div">
<$keyboard key="((save-tiddler))" actions=<<save-tiddler-actions>> tag="div">
<$list filter="[all[shadows+tiddlers]tag[$:/tags/EditTemplate]!has[draft.of]]" variable="listItem">
<$set name="tv-config-toolbar-class" filter="[<tv-config-toolbar-class>] [<listItem>encodeuricomponent[]addprefix[tc-btn-]]">
<$transclude tiddler=<<listItem>>/>
</$set>
</$list>
</$keyboard>
</$keyboard>

View File

@@ -7,6 +7,6 @@ $:/config/EditToolbarButtons/Visibility/$(listItem)$
\whitespace trim
<div class="tc-tiddler-title tc-tiddler-edit-title">
<$view field="title"/>
<span class="tc-tiddler-controls tc-titlebar"><$list filter="[all[shadows+tiddlers]tag[$:/tags/EditToolbar]!has[draft.of]]" variable="listItem"><$let tv-config-toolbar-class={{{ [enlist<tv-config-toolbar-class>] [<listItem>encodeuricomponent[]addprefix[tc-btn-]] +[join[ ]]}}}><$reveal type="nomatch" state=<<config-title>> text="hide"><$transclude tiddler=<<listItem>>/></$reveal></$let></$list></span>
<span class="tc-tiddler-controls tc-titlebar"><$list filter="[all[shadows+tiddlers]tag[$:/tags/EditToolbar]!has[draft.of]]" variable="listItem"><$reveal type="nomatch" state=<<config-title>> text="hide"><$transclude tiddler=<<listItem>>/></$reveal></$list></span>
<div style="clear: both;"></div>
</div>

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,6 +1,6 @@
title: $:/core/ui/Buttons/save-wiki
tags: $:/tags/PageControls
caption: {{$:/core/images/save-button-dynamic}} {{$:/language/Buttons/SaveWiki/Caption}}
caption: {{$:/core/images/save-button}} {{$:/language/Buttons/SaveWiki/Caption}}
description: {{$:/language/Buttons/SaveWiki/Hint}}
\whitespace trim
@@ -10,7 +10,7 @@ description: {{$:/language/Buttons/SaveWiki/Hint}}
</$wikify>
<span class="tc-dirty-indicator">
<$list filter="[<tv-config-toolbar-icons>match[yes]]">
{{$:/core/images/save-button-dynamic}}
{{$:/core/images/save-button}}
</$list>
<$list filter="[<tv-config-toolbar-text>match[yes]]">
<span class="tc-btn-text">

View File

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

View File

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

View File

@@ -6,7 +6,7 @@ description: {{$:/language/Buttons/NewHere/Hint}}
\whitespace trim
\define newHereActions()
\whitespace trim
<$set name="tags" filter="[<currentTiddler>] [enlist{$:/config/NewTiddler/Tags}]">
<$set name="tags" filter="[<currentTiddler>] [{$:/config/NewTiddler/Tags}]">
<$action-sendmessage $message="tm-new-tiddler" tags=<<tags>>/>
</$set>
\end

View File

@@ -1,6 +1,6 @@
title: $:/config/OfficialPluginLibrary
tags: $:/tags/PluginLibrary
url: https://tiddlywiki.com/library/v5.2.8/index.html
url: https://tiddlywiki.com/library/v5.2.4/index.html
caption: {{$:/language/OfficialPluginLibrary}}
{{$:/language/OfficialPluginLibrary/Hint}}

View File

@@ -4,5 +4,5 @@ title: $:/snippets/download-wiki-button
\whitespace trim
<$button class="tc-btn-big-green">
<$action-sendmessage $message="tm-download-file" $param="$:/core/save/all" filename="index.html"/>
<<lingo Full/Caption>>&#32;{{$:/core/images/save-button-dynamic}}
<<lingo Full/Caption>>&#32;{{$:/core/images/save-button}}
</$button>

View File

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

Some files were not shown because too many files have changed in this diff Show More