Compare commits

..
Author SHA1 Message Date
Mario Pietsch 5e81f21fc3 Fix typos in macro calls 2026-09-16 23:20:31 +02:00
359 changed files with 1275 additions and 7591 deletions
+1 -1
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.5.0.
TW5_BUILD_VERSION=v5.4.1.
fi
echo "Using TW5_BUILD_VERSION as [$TW5_BUILD_VERSION]"
+5 -33
View File
@@ -217,11 +217,6 @@ exports.generateTiddlerFileInfo = function(tiddler,options) {
fileInfo.isEditableFile = true;
fileInfo.originalpath = options.fileInfo.originalpath;
}
// Propagate the pinFilepath flag (so generateTiddlerFilepath can short-circuit
// FileSystemPaths and write back to the original location)
if(options.fileInfo && !!options.fileInfo.pinFilepath) {
fileInfo.pinFilepath = true;
}
// Check if the tiddler has any unsafe fields that can't be expressed in a .tid or .meta file: containing control characters, or leading/trailing whitespace
var hasUnsafeFields = false;
$tw.utils.each(tiddler.getFieldStrings(),function(value,fieldName) {
@@ -324,16 +319,9 @@ exports.generateTiddlerFilepath = function(title,options) {
extension = options.extension || "",
originalpath = (options.fileInfo && options.fileInfo.originalpath) ? options.fileInfo.originalpath : "",
overwrite = options.fileInfo && options.fileInfo.overwrite || false,
pinFilepath = !!(options.fileInfo && options.fileInfo.pinFilepath),
filepath;
// If the tiddler's filepath is pinned via tiddlywiki.files, the originalpath
// wins and the path filters are skipped entirely.
if(pinFilepath && originalpath) {
var pinnedExt = path.extname(originalpath);
filepath = originalpath.substring(0,originalpath.length - pinnedExt.length);
}
// Check if any of the pathFilters applies
if(!filepath && options.pathFilters && options.wiki) {
if(options.pathFilters && options.wiki) {
$tw.utils.each(options.pathFilters,function(filter) {
if(!filepath) {
var source = options.wiki.makeTiddlerIterator([title]),
@@ -348,14 +336,13 @@ exports.generateTiddlerFilepath = function(title,options) {
//Use the originalpath without the extension
var ext = path.extname(originalpath);
filepath = originalpath.substring(0,originalpath.length - ext.length);
// normalise "\" to "/" so the sanitiser keeps subdirectories
// (it strips "\", not "/") instead of flattening them.
filepath = filepath.split(path.sep).join("/");
} else if(!filepath) {
filepath = title;
// Remove any forward or backward slashes so we don't create directories
filepath = filepath.replace(/\/|\\/g,"_");
}
// Replace any Windows control codes
filepath = filepath.replace(/^(con|prn|aux|nul|com[0-9]|lpt[0-9])$/i,"_$1_");
// Replace any leading spaces with the same number of underscores
filepath = filepath.replace(/^ +/,function (u) { return u.replace(/ /g, "_");});
//If the path does not start with "." or ".." && a path seperator, then
@@ -365,23 +352,8 @@ exports.generateTiddlerFilepath = function(title,options) {
}
// Replace any Unicode control codes
filepath = filepath.replace(/[\x00-\x1f\x80-\x9f]/g,"_");
// Replace any characters that can't be used in cross-platform filenames.
if(!pinFilepath) {
filepath = $tw.utils.transliterate(filepath.replace(/<|>|~|\:|\"|\||\?|\*|\^|\\/g,"_"));
}
// Per segment (catches "sub/CON"), MUST be after transliterate which can create a
// reserved name. Reserved names are wrapped on every path incl pinned;
// trailing dots/spaces (Windows strips) fixed for generated names, not pinned.
filepath = filepath.split("/").map(function(segment) {
if(segment === "" || segment === "." || segment === "..") {
return segment;
}
segment = segment.replace(/^(con|prn|aux|nul|com[0-9]|lpt[0-9])$/i,"_$1_");
if(!pinFilepath) {
segment = segment.replace(/[. ]+$/,function(u) { return u.replace(/[. ]/g,"_"); });
}
return segment;
}).join("/");
// Replace any characters that can't be used in cross-platform filenames
filepath = $tw.utils.transliterate(filepath.replace(/<|>|~|\:|\"|\||\?|\*|\^/g,"_"));
// Replace any dots or spaces at the end of the extension with the same number of underscores
extension = extension.replace(/[\. ]+$/, function (u) { return u.replace(/[\. ]/g, "_");});
// Truncate the extension if it is too long
+5 -4
View File
@@ -9,14 +9,15 @@ Serve tiddlers over http
"use strict";
let fs, path, crypto, zlib, URL;
let fs, url, path, querystring, crypto, zlib;
if($tw.node) {
fs = require("fs"),
url = require("url"),
path = require("path"),
querystring = require("querystring"),
crypto = require("crypto"),
zlib = require("zlib");
URL = require("url").URL;
}
/*
@@ -259,8 +260,8 @@ Server.prototype.requestHandler = function(request,response,options) {
state.wiki = options.wiki || self.wiki;
state.boot = options.boot || self.boot;
state.server = self;
state.urlInfo = new URL(request.url, "http://localhost");
state.queryParameters = Object.fromEntries(state.urlInfo.searchParams);
state.urlInfo = url.parse(request.url);
state.queryParameters = querystring.parse(state.urlInfo.query);
state.pathPrefix = options.pathPrefix || this.get("path-prefix") || "";
// Enable CORS
if(this.corsEnable) {
+2 -7
View File
@@ -58,14 +58,10 @@ LayoutSwitcher/Caption: Layout
LoadedModules/Caption: Loaded Modules
LoadedModules/Hint: These are the currently loaded tiddler modules linked to their source tiddlers. Any italicised modules lack a source tiddler, typically because they were setup during the boot process.
Palette/Caption: Palette
Palette/Customisations/Prompt: Customisations for the current palette: <<palette-link>>
Palette/Customisations/Reset/Caption: reset customisations
Palette/Editor/Customised/Prompt: This palette has customisations that override the entries marked below
Palette/Editor/Customised/Entry: overridden by a customisation
Palette/Editor/Clone/Caption: clone
Palette/Editor/Clone/Prompt: It is recommended that you clone this shadow palette before editing it
Palette/Editor/Delete/Hint: delete this entry from the current palette
Palette/Editor/Names/External/Show: Show inherited palette entries
Palette/Editor/Names/External/Show: Show color names that are not part of the current palette
Palette/Editor/Prompt/Modified: This shadow palette has been modified
Palette/Editor/Prompt: Editing
Palette/Editor/Reset/Caption: reset
@@ -259,5 +255,4 @@ ViewTemplateTags/Caption: View Template Tags
ViewTemplateTags/Hint: This rule cascade is used by the default view template to dynamically choose the template for displaying the tags area of a tiddler.
WikiInformation/Caption: Wiki Information
WikiInformation/Hint: This page summarises high level information about the configuration of this ~TiddlyWiki. It is designed to enable users to quickly share relevant aspects of the configuration of their ~TiddlyWiki with others, for example when seeking help in one of the forums. No private or personal information is included, and nothing is shared without being explicitly copied and pasted elsewhere
WikiInformation/Drag/Caption: Drag this link to copy this tool to another wiki
WikiInformation/Generate/Caption: Click to generate wiki information report
WikiInformation/Drag/Caption: Drag this link to copy this tool to another wiki
-2
View File
@@ -30,8 +30,6 @@ Error/DeserializeOperator/MissingOperand: Filter Error: Missing operand for 'des
Error/DeserializeOperator/UnknownDeserializer: Filter Error: Unknown deserializer provided as operand for the 'deserialize' operator
Error/Filter: Filter error
Error/FilterSyntax: Syntax error in filter expression
Error/FilterPragma: Filter Error: Unknown filter pragma
Error/FilterPragmaPosition: Filter Error: Filter pragmas are only allowed at the start of a filter
Error/FilterRunPrefix: Filter Error: Unknown prefix for filter run
Error/IsFilterOperator: Filter Error: Unknown parameter for the 'is' filter operator
Error/FormatFilterOperator: Filter Error: Unknown suffix for the 'format' filter operator
+1 -1
View File
@@ -78,6 +78,7 @@ class BackgroundActionTracker {
fnProcess: (changes) => {
if(this.hasChanged) {
this.hasChanged = false;
console.log("Processing background action", this.title);
const tiddler = this.wiki.getTiddler(this.title);
let doActions = true;
if(tiddler && tiddler.fields.platforms) {
@@ -88,7 +89,6 @@ class BackgroundActionTracker {
}
}
if(doActions) {
console.log("Processing background action", this.title);
this.wiki.invokeActionString(
this.actions,
null,
+2 -1
View File
@@ -31,7 +31,8 @@ function FramedEngine(options) {
this.parentNode.insertBefore(this.iframeNode,this.nextSibling);
this.iframeDoc = this.iframeNode.contentWindow.document;
// (Firefox requires us to put some empty content in the iframe)
var colorScheme = (this.widget.wiki.getTiddler("$:/temp/palette-colours") || {fields: {}}).fields["color-scheme"] || "light";
var paletteTitle = this.widget.wiki.getTiddlerText("$:/palette");
var colorScheme = (this.widget.wiki.getTiddler(paletteTitle) || {fields: {}}).fields["color-scheme"] || "light";
this.iframeDoc.open();
this.iframeDoc.write("<!DOCTYPE html><html><head><meta name='color-scheme' content='" + colorScheme + "'></head><body></body></html>");
this.iframeDoc.close();
+1 -9
View File
@@ -28,12 +28,7 @@ function SimpleEngine(options) {
if(this.widget.editTag === "textarea") {
this.domNode.appendChild(this.widget.document.createTextNode(this.value));
} else {
if(this.widget.editType === "color") {
// The <input type="color"> element requires a six digit hex value
this.domNode.value = $tw.utils.convertCSSColorToRGBString(this.value);
} else {
this.domNode.value = this.value;
}
this.domNode.value = this.value;
}
// Set the attributes
if(this.widget.editType && this.widget.editTag !== "textarea") {
@@ -88,9 +83,6 @@ Update the DomNode with the new text
*/
SimpleEngine.prototype.updateDomNodeText = function(text) {
try {
if(this.widget.editType === "color") {
text = $tw.utils.convertCSSColorToRGBString(text);
}
this.domNode.value = text;
} catch(e) {
// Ignore
+2 -29
View File
@@ -210,29 +210,6 @@ function editTextWidgetFactory(toolbarEngine,nonToolbarEngine) {
this.editShowToolbar = this.wiki.getTiddlerText(ENABLE_TOOLBAR_TITLE,"yes");
this.editShowToolbar = (this.editShowToolbar === "yes") && !!(this.children && this.children.length > 0) && (!this.document.isTiddlyWikiFakeDom);
};
EditTextWidget.prototype.updateDomNodeClasses = function() {
var domNodeClasses = this.engine.domNode.className.split(/\s+/).filter(Boolean),
oldClasses = this.editClass.split(/\s+/).filter(Boolean),
newClasses;
this.editClass = this.getAttribute("class","");
newClasses = this.editClass.split(/\s+/).filter(Boolean);
// Remove classes assigned from the old value of the class attribute
domNodeClasses = domNodeClasses.filter(function(className) {
return !oldClasses.includes(className);
});
// Add new classes from the updated class attribute
domNodeClasses = domNodeClasses.concat(
newClasses.filter(function(className) {
return !domNodeClasses.includes(className);
})
);
this.engine.domNode.className = domNodeClasses.join(" ");
};
/*
Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering
@@ -240,19 +217,15 @@ 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.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] || changedTiddlers["$:/palette"] || changedAttributes.disabled || changedAttributes.fileDrop) {
this.refreshSelf();
return true;
} else if(changedAttributes["default"] || changedTiddlers[this.editRefreshTitle]) {
this.editDefault = this.getAttribute("default");
} else if(changedTiddlers[this.editRefreshTitle]) {
this.engine.updateDomNodeText(this.getEditInfo().value);
} else if(changedTiddlers[this.editTitle]) {
var editInfo = this.getEditInfo();
this.updateEditor(editInfo.value,editInfo.type);
}
if(changedAttributes["class"]) {
this.updateDomNodeClasses();
}
this.engine.fixHeight();
if(this.editShowToolbar) {
return this.refreshChildren(changedTiddlers);
@@ -13,15 +13,14 @@ Export our filter prefix function
exports.intersection = function(operationSubFunction) {
return function(results,source,widget) {
if(results.length !== 0) {
const secondRunResults = operationSubFunction(source,widget),
secondRunSet = new Set(secondRunResults),
firstRunResults = results.toArray();
var secondRunResults = operationSubFunction(source,widget);
var firstRunResults = results.toArray();
results.clear();
firstRunResults.forEach((title) => {
if(secondRunSet.has(title)) {
$tw.utils.each(firstRunResults,function(title) {
if(secondRunResults.indexOf(title) !== -1) {
results.push(title);
}
});
}
};
};
};
+20 -15
View File
@@ -13,28 +13,33 @@ Export our filter prefix function
exports.sort = function(operationSubFunction,options) {
return function(results,source,widget) {
if(results.length > 0) {
const suffixes = options.suffixes,
var suffixes = options.suffixes,
sortType = (suffixes[0] && suffixes[0][0]) ? suffixes[0][0] : "string",
invert = suffixes[1] ? suffixes[1].includes("reverse") : false,
isCaseSensitive = suffixes[1] ? suffixes[1].includes("casesensitive") : false,
invert = suffixes[1] ? (suffixes[1].indexOf("reverse") !== -1) : false,
isCaseSensitive = suffixes[1] ? (suffixes[1].indexOf("casesensitive") !== -1) : false,
inputTitles = results.toArray(),
sortKeys = [],
compareFn = $tw.utils.makeCompareFunction(sortType,{defaultType: "string", invert:invert, isCaseSensitive:isCaseSensitive});
results.each((title) => {
const key = operationSubFunction(
options.wiki.makeTiddlerIterator([title]),
widget.makeFakeWidgetWithVariables({
"currentTiddler": "" + title,
"..currentTiddler": widget.getVariable("currentTiddler",{defaultValue:""})
})
);
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",{defaultValue:""})
}));
sortKeys.push(key[0] || "");
});
results.clear();
// Prepare an array of indexes to sort
let indexes = Array.from(inputTitles.keys());
indexes.sort((a,b) => compareFn(sortKeys[a],sortKeys[b]));
indexes.forEach((index) => {
for(var t=0; t<inputTitles.length; t++) {
indexes[t] = t;
}
// Sort the indexes
compareFn = $tw.utils.makeCompareFunction(sortType,{defaultType: "string", invert:invert, isCaseSensitive:isCaseSensitive});
indexes = indexes.sort(function(a,b) {
return compareFn(sortKeys[a],sortKeys[b]);
});
// Add to results in correct order
$tw.utils.each(indexes,function(index) {
results.push(inputTitles[index]);
});
}
+46 -88
View File
@@ -146,16 +146,14 @@ exports.parseFilter = function(filterString) {
match;
var whitespaceRegExp = /(\s+)/mg,
// Groups:
// 1 - pragma
// 2 - pragma suffix
// 3 - entire filter run prefix
// 4 - filter run prefix name
// 5 - filter run prefix suffixes
// 6 - opening square bracket following filter run prefix
// 7 - double quoted string following filter run prefix
// 8 - single quoted string following filter run prefix
// 9 - anything except for whitespace and square brackets
operandRegExp = /(?:::(\w+)(?:\:(\w+))?(?=\s|$)|((?:\+|\-|~|(?:=>?)|:(\w+)(?:\:([\w\:, ]*))?)?)(?:(\[)|(?:"([^"]*)")|(?:'([^']*)')|([^\s\[\]]+)))/mg;
// 1 - entire filter run prefix
// 2 - filter run prefix itself
// 3 - filter run prefix suffixes
// 4 - opening square bracket following filter run prefix
// 5 - double quoted string following filter run prefix
// 6 - single quoted string following filter run prefix
// 7 - anything except for whitespace and square brackets
operandRegExp = /((?:\+|\-|~|(?:=>?)|\:(\w+)(?:\:([\w\:, ]*))?)?)(?:(\[)|(?:"([^"]*)")|(?:'([^']*)')|([^\s\[\]]+))/mg;
while(p < filterString.length) {
// Skip any whitespace
whitespaceRegExp.lastIndex = p;
@@ -172,23 +170,18 @@ exports.parseFilter = function(filterString) {
};
match = operandRegExp.exec(filterString);
if(match && match.index === p) {
// If there is a filter run prefix
if(match[1]) {
// If there is a filter pragma
operation.pragma = match[1];
operation.suffix = match[2];
p = match.index + match[0].length;
} else if(match[3]) {
// If there is a filter run prefix
operation.prefix = match[3];
operation.prefix = match[1];
p = p + operation.prefix.length;
// Name for named prefixes
if(match[4]) {
operation.namedPrefix = match[4];
if(match[2]) {
operation.namedPrefix = match[2];
}
// Suffixes for filter run prefix
if(match[5]) {
if(match[3]) {
operation.suffixes = [];
$tw.utils.each(match[5].split(":"),function(subsuffix) {
$tw.utils.each(match[3].split(":"),function(subsuffix) {
operation.suffixes.push([]);
$tw.utils.each(subsuffix.split(","),function(entry) {
entry = $tw.utils.trim(entry);
@@ -200,7 +193,7 @@ exports.parseFilter = function(filterString) {
}
}
// Opening square bracket
if(match[6]) {
if(match[4]) {
p = parseFilterOperation(operation.operators,filterString,p);
} else {
p = match.index + match[0].length;
@@ -210,9 +203,9 @@ exports.parseFilter = function(filterString) {
p = parseFilterOperation(operation.operators,filterString,p);
}
// Quoted strings and unquoted title
if(match[7] || match[8] || match[9]) { // Double quoted string, single quoted string or unquoted title
if(match[5] || match[6] || match[7]) { // Double quoted string, single quoted string or unquoted title
operation.operators.push(
{operator: "title", operands: [{text: match[7] || match[8] || match[9]}]}
{operator: "title", operands: [{text: match[5] || match[6] || match[7]}]}
);
}
results.push(operation);
@@ -237,26 +230,23 @@ exports.getFilterRunPrefixes = function() {
return this.filterRunPrefixes;
};
exports.filterTiddlers = function(filterString,widget,source,options) {
var fn = this.compileFilter(filterString,options);
exports.filterTiddlers = function(filterString,widget,source) {
var fn = this.compileFilter(filterString);
return fn.call(this,source,widget);
};
/*
Compile a filter into a function with the signature fn(source,widget,options) where:
Compile a filter into a function with the signature fn(source,widget) where:
source: an iterator function for the source tiddlers, called source(iterator), where iterator is called as iterator(tiddler,title)
widget: an optional widget node for retrieving the current tiddler etc.
*/
exports.compileFilter = function(filterString,options) {
var defaultFilterRunPrefix = (options || {}).defaultFilterRunPrefix || "or",
seenNonPragmaOperation = false;
var cacheKey = filterString + "|" + defaultFilterRunPrefix;
exports.compileFilter = function(filterString) {
if(!this.filterCache) {
this.filterCache = Object.create(null);
this.filterCacheCount = 0;
}
if(this.filterCache[cacheKey] !== undefined) {
return this.filterCache[cacheKey];
if(this.filterCache[filterString] !== undefined) {
return this.filterCache[filterString];
}
var filterParseTree;
try {
@@ -306,7 +296,7 @@ exports.compileFilter = function(filterString,options) {
var varTree = $tw.utils.parseFilterVariable(operand.text);
var resultList = widgetClass.evaluateVariable(widget,varTree.name,{params: varTree.params, source: source});
if((resultList.length > 0 && resultList[0] !== undefined) || resultList.length === 0) {
operand.multiValue = resultList || [];
operand.multiValue = widgetClass.evaluateVariable(widget,varTree.name,{params: varTree.params, source: source}) || [];
operand.value = operand.multiValue[0] || "";
} else {
operand.value = "";
@@ -335,8 +325,7 @@ exports.compileFilter = function(filterString,options) {
regexp: operator.regexp
},{
wiki: self,
widget: widget,
defaultFilterRunPrefix: defaultFilterRunPrefix
widget: widget
});
if($tw.utils.isArray(results)) {
accumulator = self.makeTiddlerIterator(results);
@@ -357,60 +346,29 @@ exports.compileFilter = function(filterString,options) {
var filterRunPrefixes = self.getFilterRunPrefixes();
// Wrap the operator functions in a wrapper function that depends on the prefix
operationFunctions.push((function() {
if(operation.pragma) {
// Pragmas are only allowed at the start of a filter, before any runs
if(seenNonPragmaOperation) {
return function(results,source,widget) {
results.clear();
results.push($tw.language.getString("Error/FilterPragmaPosition"));
};
}
switch(operation.pragma) {
case "defaultprefix":
defaultFilterRunPrefix = operation.suffix || "or";
break;
default:
var options = {wiki: self, suffixes: operation.suffixes || []};
switch(operation.prefix || "") {
case "": // No prefix means that the operation is unioned into the result
return filterRunPrefixes["or"](operationSubFunction, options);
case "=": // The results of the operation are pushed into the result without deduplication
return filterRunPrefixes["all"](operationSubFunction, options);
case "-": // The results of this operation are removed from the main result
return filterRunPrefixes["except"](operationSubFunction, options);
case "+": // This operation is applied to the main results so far
return filterRunPrefixes["and"](operationSubFunction, options);
case "~": // This operation is unioned into the result only if the main result so far is empty
return filterRunPrefixes["else"](operationSubFunction, options);
case "=>": // This operation is applied to the main results so far, and the results are assigned to a variable
return filterRunPrefixes["let"](operationSubFunction, options);
default:
if(operation.namedPrefix && filterRunPrefixes[operation.namedPrefix]) {
return filterRunPrefixes[operation.namedPrefix](operationSubFunction, options);
} else {
return function(results,source,widget) {
results.clear();
results.push($tw.language.getString("Error/FilterPragma"));
results.push($tw.language.getString("Error/FilterRunPrefix"));
};
}
return function(results,source,widget) {
// Dummy response
};
} else {
seenNonPragmaOperation = true;
var options = {wiki: self, suffixes: operation.suffixes || []};
switch(operation.prefix || "") {
case "": // Use the default filter run prefix if none is specified
if(filterRunPrefixes[defaultFilterRunPrefix]) {
return filterRunPrefixes[defaultFilterRunPrefix](operationSubFunction, options);
} else {
return function(results,source,widget) {
results.clear();
results.push($tw.language.getString("Error/FilterRunPrefix"));
};
}
case "=": // The results of the operation are pushed into the result without deduplication
return filterRunPrefixes["all"](operationSubFunction, options);
case "-": // The results of this operation are removed from the main result
return filterRunPrefixes["except"](operationSubFunction, options);
case "+": // This operation is applied to the main results so far
return filterRunPrefixes["and"](operationSubFunction, options);
case "~": // This operation is unioned into the result only if the main result so far is empty
return filterRunPrefixes["else"](operationSubFunction, options);
case "=>": // This operation is applied to the main results so far, and the results are assigned to a variable
return filterRunPrefixes["let"](operationSubFunction, options);
default:
if(operation.namedPrefix && filterRunPrefixes[operation.namedPrefix]) {
return filterRunPrefixes[operation.namedPrefix](operationSubFunction, options);
} else {
return function(results,source,widget) {
results.clear();
results.push($tw.language.getString("Error/FilterRunPrefix"));
};
}
}
}
}
})());
});
@@ -449,7 +407,7 @@ exports.compileFilter = function(filterString,options) {
this.filterCache = Object.create(null);
this.filterCacheCount = 0;
}
this.filterCache[cacheKey] = fnMeasured;
this.filterCache[filterString] = fnMeasured;
this.filterCacheCount++;
return fnMeasured;
};
-21
View File
@@ -1,21 +0,0 @@
/*\
title: $:/core/modules/filters/changecount.js
type: application/javascript
module-type: filteroperator
Filter operator for retrieving the changecount for each title in the list.
\*/
"use strict";
/*
Export our filter function
*/
exports.changecount = function(source,operator,options) {
var results = [];
source(function(tiddler,title) {
results.push(options.wiki.getChangeCount(title) + "");
});
return results;
};
-158
View File
@@ -1,158 +0,0 @@
/*\
title: $:/core/modules/filters/colour-ops.js
type: application/javascript
module-type: filteroperator
Filter operators for colour operations
\*/
"use strict";
var Color = require("$:/core/modules/utils/dom/color.js").Color,
colourSpacesList = Object.keys(Color.spaces),
hueAdjustersList = ["raw","increasing","decreasing","longer","shorter"];
exports["colour-lighten"] = makeSerialColourOperator(function (colour, operator, options) {
return colour.lighten($tw.utils.parseNumber(operator.operand)).display().toString();
});
exports["colour-darken"] = makeSerialColourOperator(function (colour, operator, options) {
return colour.darken($tw.utils.parseNumber(operator.operand)).display().toString();
});
exports["colour-get-oklch"] = makeSerialColourOperator(function (colour, operator, options) {
var prop = ((operator.suffixes || [])[0] || ["l"])[0];
if(["l","c","h"].indexOf(prop) !== -1) {
colour = colour.oklch[prop];
// Hue is null for achromatic colours
if(colour === null || colour === undefined || Number.isNaN(colour)) {
return "";
}
}
return colour.toString();
});
exports["colour-set-oklch"] = makeSerialColourOperator(function (colour, operator, options) {
var prop = ((operator.suffixes || [])[0] || ["l"])[0];
if(["l","c","h"].indexOf(prop) !== -1) {
colour.oklch[prop] = $tw.utils.parseNumber(operator.operand);
}
return colour.display().toString();
});
exports["colour-set-alpha"] = makeSerialColourOperator(function (colour, operator, options) {
colour.alpha = $tw.utils.parseNumber(operator.operand);
return colour.display().toString();
});
exports["colour-composite"] = makeSerialColourOperator(function (colour, operator, options) {
// Composite each translucent input colour over the backdrop given in the operand
var backdrop = $tw.utils.parseCSSColorObject(operator.operand);
if(backdrop && colour.alpha < 1) {
var alpha = colour.alpha;
colour.alpha = 1;
colour = backdrop.mix(colour,alpha,{space: "srgb"});
}
return colour.display().toString();
});
exports["colour-contrast"] = makeParallelColourOperator(function (colours, operator, options) {
var colourContrasts = [];
$tw.utils.each(colours,function(colour,index) {
if(!colour) {
colour = $tw.utils.parseCSSColorObject("white");
colours[index] = colour;
}
if(index > 0) {
colourContrasts.push(colour.contrast(colours[index - 1],"DeltaPhi").toString());
}
});
return colourContrasts;
});
exports["colour-best-contrast"] = makeParallelColourOperator(function (colours, operator, options, originalColours) {
var bestContrast = 0,
bestColour = null;
if(colours.length < 2) {
return [];
}
var targetColour = colours[colours.length - 1];
if(!targetColour) {
return [];
}
for(var t=0; t<colours.length; t++) {
var colour = colours[t];
if(colour) {
var contrast = colour.contrast(targetColour,"DeltaPhi");
if(contrast > bestContrast) {
bestContrast = contrast;
bestColour = originalColours[t];
}
}
}
if(bestColour) {
return [bestColour];
} else {
return [];
}
});
exports["colour-interpolate"] = function(source,operator,options) {
// Get the colour space suffix
var space = ((((operator.suffixes || [])[0] || ["srgb"])[0]) || "").toLowerCase();
if(colourSpacesList.indexOf(space) === -1) {
space = "lch";
}
// Get the hue adjuster suffix
var hueAdjuster = ((((operator.suffixes || [])[1] || ["shorter"])[0]) || "").toLowerCase();
if(hueAdjustersList.indexOf(hueAdjuster) === -1) {
hueAdjuster = "shorter";
}
// Get the colours
if(operator.operands.length < 2) {
return [];
}
var colourA = $tw.utils.parseCSSColorObject(operator.operands[0]),
colourB = $tw.utils.parseCSSColorObject(operator.operands[1]);
if(!colourA || !colourB) {
return [];
}
var rangefn = colourA.range(colourB,{space: space, hue: hueAdjuster});
// Cycle through the weights
var results = [];
source(function(tiddler,title) {
var index = $tw.utils.parseNumber(title);
var colour = rangefn(index);
results.push(colour.display().toString());
});
return results;
};
function makeSerialColourOperator(fn) {
return function (source, operator, options) {
var results = [];
source(function (tiddler, title) {
var c = $tw.utils.parseCSSColorObject(title);
if(c) {
c = fn(c, operator, options);
results.push(c);
} else {
results.push("");
}
});
return results;
};
}
function makeParallelColourOperator(fn) {
return function (source, operator, options) {
var originalColours = [],
colours = [];
source(function (tiddler, title) {
originalColours.push(title);
colours.push($tw.utils.parseCSSColorObject(title));
});
return fn(colours, operator, options, originalColours);
};
}
+1 -3
View File
@@ -13,9 +13,7 @@ Filter operator returning those input titles that pass a subfilter
Export our filter function
*/
exports.filter = function(source,operator,options) {
var suffixes = operator.suffixes || [],
defaultFilterRunPrefix = (suffixes[0] && suffixes[0][0]) || options.defaultFilterRunPrefix || "or",
filterFn = options.wiki.compileFilter(operator.operand,{defaultFilterRunPrefix}),
var filterFn = options.wiki.compileFilter(operator.operand),
results = [],
target = operator.prefix !== "!";
source(function(tiddler,title) {
+54 -30
View File
@@ -9,56 +9,69 @@ Filter operators for manipulating the current selection list
"use strict";
/*
Fetch titles from the current list
*/
const prepare_results = (source) => {
const results = [];
source((tiddler,title) => results.push(title));
return results;
};
/*
Order a list
*/
exports.order = function(source,operator,options) {
const results = prepare_results(source);
return operator.operand.toLowerCase() === "reverse" ?
results.reverse() :
results;
var results = [];
if(operator.operand.toLowerCase() === "reverse") {
source(function(tiddler,title) {
results.unshift(title);
});
} else {
source(function(tiddler,title) {
results.push(title);
});
}
return results;
};
/*
Reverse list
*/
exports.reverse = function(source,operator,options) {
return prepare_results(source).reverse();
var results = [];
source(function(tiddler,title) {
results.unshift(title);
});
return results;
};
/*
First entry/entries in list
*/
exports.first = function(source,operator,options) {
const count = $tw.utils.getInt(operator.operand,1);
return prepare_results(source).slice(0,count);
var count = $tw.utils.getInt(operator.operand,1),
results = [];
source(function(tiddler,title) {
results.push(title);
});
return results.slice(0,count);
};
/*
Last entry/entries in list
*/
exports.last = function(source,operator,options) {
const count = $tw.utils.getInt(operator.operand,1);
return count === 0 ?
[] :
prepare_results(source).slice(-count);
var count = $tw.utils.getInt(operator.operand,1),
results = [];
if(count === 0) return results;
source(function(tiddler,title) {
results.push(title);
});
return results.slice(-count);
};
/*
All but the first entry/entries of the list
*/
exports.rest = function(source,operator,options) {
const count = $tw.utils.getInt(operator.operand,1);
return prepare_results(source).slice(count);
var count = $tw.utils.getInt(operator.operand,1),
results = [];
source(function(tiddler,title) {
results.push(title);
});
return results.slice(count);
};
exports.butfirst = exports.rest;
exports.bf = exports.rest;
@@ -67,9 +80,12 @@ exports.bf = exports.rest;
All but the last entry/entries of the list
*/
exports.butlast = function(source,operator,options) {
const count = $tw.utils.getInt(operator.operand,1),
results = prepare_results(source),
index = count === 0 ? results.length : -count;
var count = $tw.utils.getInt(operator.operand,1),
results = [];
source(function(tiddler,title) {
results.push(title);
});
var index = count === 0 ? results.length : -count;
return results.slice(0,index);
};
exports.bl = exports.butlast;
@@ -78,14 +94,22 @@ exports.bl = exports.butlast;
The nth member of the list
*/
exports.nth = function(source,operator,options) {
const count = $tw.utils.getInt(operator.operand,1);
return prepare_results(source).slice(count - 1,count);
var count = $tw.utils.getInt(operator.operand,1),
results = [];
source(function(tiddler,title) {
results.push(title);
});
return results.slice(count - 1,count);
};
/*
The zero based nth member of the list
*/
exports.zth = function(source,operator,options) {
const count = $tw.utils.getInt(operator.operand,0);
return prepare_results(source).slice(count,count + 1);
};
var count = $tw.utils.getInt(operator.operand,0),
results = [];
source(function(tiddler,title) {
results.push(title);
});
return results.slice(count,count + 1);
};
+32 -17
View File
@@ -13,22 +13,37 @@ Filter operator for checking if a title starts with a prefix
Export our filter function
*/
exports.prefix = function(source,operator,options) {
const results = [],
suffixes = (operator.suffixes || [])[0] || [],
caseInsensitive = suffixes.includes("caseinsensitive"),
negate = operator.prefix === "!";
const operand = caseInsensitive ?
operator.operand.toLowerCase() :
operator.operand;
source((tiddler,title) => {
const value = caseInsensitive ? title.toLowerCase() : title,
matches = value.startsWith(operand);
if(negate ? !matches : matches) {
results.push(title);
var results = [],
suffixes = (operator.suffixes || [])[0] || [];
if(suffixes.indexOf("caseinsensitive") !== -1) {
var operand = operator.operand.toLowerCase();
if(operator.prefix === "!") {
source(function(tiddler,title) {
if(title.toLowerCase().substr(0,operand.length) !== operand) {
results.push(title);
}
});
} else {
source(function(tiddler,title) {
if(title.toLowerCase().substr(0,operand.length) === operand) {
results.push(title);
}
});
}
});
} else {
if(operator.prefix === "!") {
source(function(tiddler,title) {
if(title.substr(0,operator.operand.length) !== operator.operand) {
results.push(title);
}
});
} else {
source(function(tiddler,title) {
if(title.substr(0,operator.operand.length) === operator.operand) {
results.push(title);
}
});
}
}
return results;
};
};
+12 -7
View File
@@ -14,13 +14,13 @@ Export our filter function
*/
exports.sortsub = function(source,operator,options) {
// Compile the subfilter
let filterFn = options.wiki.compileFilter(operator.operand);
var filterFn = options.wiki.compileFilter(operator.operand);
// Collect the input titles and the corresponding sort keys
let inputTitles = [],
var inputTitles = [],
sortKeys = [];
source(function(tiddler,title) {
inputTitles.push(title);
let r = filterFn.call(options.wiki,function(iterator) {
var r = filterFn.call(options.wiki,function(iterator) {
iterator(options.wiki.getTiddler(title),title);
},options.widget.makeFakeWidgetWithVariables({
"currentTiddler": "" + title,
@@ -29,12 +29,17 @@ exports.sortsub = function(source,operator,options) {
sortKeys.push(r[0] || "");
});
// Rather than sorting the titles array, we'll sort the indexes so that we can consult both arrays
let indexes = Array.from(inputTitles.keys());
var indexes = new Array(inputTitles.length);
for(var t=0; t<inputTitles.length; t++) {
indexes[t] = t;
}
// Sort the indexes
let compareFn = $tw.utils.makeCompareFunction(operator.suffix,{defaultType: "string",invert: operator.prefix === "!"});
indexes = indexes.sort((a,b) => compareFn(sortKeys[a],sortKeys[b]));
var compareFn = $tw.utils.makeCompareFunction(operator.suffix,{defaultType: "string",invert: operator.prefix === "!"});
indexes = indexes.sort(function(a,b) {
return compareFn(sortKeys[a],sortKeys[b]);
});
// Make the results array in order
let results = [];
var results = [];
$tw.utils.each(indexes,function(index) {
results.push(inputTitles[index]);
});
+13 -26
View File
@@ -91,35 +91,22 @@ function diffLineWordMode(text1,text2,mode) {
return diffs;
}
exports.makepatches = function(source, operator, options) {
const suffixes = operator.suffixes || [],
[modeArg = [], formatArg = []] = suffixes,
modeSuffix = modeArg[0] || operator.suffix || "",
mode = ["lines", "words"].includes(modeSuffix) ? modeSuffix : "",
isJson = formatArg[0] === "json",
results = [];
source((tiddler, title) => {
if (isJson) {
const diffs = (mode === "lines" || mode === "words")
? diffLineWordMode(title, operator.operand, mode)
: dmp.diffMain(title, operator.operand);
const jsonOutput = diffs.map(([typeCode, text]) => ({
type: typeCode === 1 ? "insert" : (typeCode === -1 ? "delete" : "equal"),
text
}));
results.push(JSON.stringify(jsonOutput));
exports.makepatches = function(source,operator,options) {
var suffix = operator.suffix || "",
result = [];
source(function(tiddler,title) {
let diffs, patches;
if(suffix === "lines" || suffix === "words") {
diffs = diffLineWordMode(title,operator.operand,suffix);
patches = dmp.patchMake(title,diffs);
} else {
const patches = (mode === "lines" || mode === "words")
? dmp.patchMake(title, diffLineWordMode(title, operator.operand, mode))
: dmp.patchMake(title, operator.operand);
results.push(dmp.patchToText(patches));
patches = dmp.patchMake(title,operator.operand);
}
Array.prototype.push.apply(result,[dmp.patchToText(patches)]);
});
return results;
return result;
};
exports.applypatches = makeStringBinaryOperator(
@@ -248,4 +235,4 @@ exports.charcode = function(source,operator,options) {
}
});
return [chars.join("")];
};
};
+4 -7
View File
@@ -13,14 +13,11 @@ Filter operator returning its operand evaluated as a filter
Export our filter function
*/
exports.subfilter = function(source,operator,options) {
var suffixes = operator.suffixes || [],
defaultFilterRunPrefix = (suffixes[0] && suffixes[0][0]) || options.defaultFilterRunPrefix || "or";
var list = options.wiki.filterTiddlers(operator.operand,options.widget,source,{defaultFilterRunPrefix});
var list = options.wiki.filterTiddlers(operator.operand,options.widget,source);
if(operator.prefix === "!") {
const results = [],
listSet = new Set(list);
source((tiddler,title) => {
if(!listSet.has(title)) {
var results = [];
source(function(tiddler,title) {
if(list.indexOf(title) === -1) {
results.push(title);
}
});
+31 -17
View File
@@ -13,27 +13,41 @@ Filter operator for checking if a title ends with a suffix
Export our filter function
*/
exports.suffix = function(source,operator,options) {
const results = [],
var results = [],
suffixes = (operator.suffixes || [])[0] || [];
if(!operator.operand) {
source((tiddler,title) => {
source(function(tiddler,title) {
results.push(title);
});
return results;
}
const caseInsensitive = suffixes.indexOf("caseinsensitive") !== -1,
negate = operator.prefix === "!",
operand = caseInsensitive ? operator.operand.toLowerCase() : operator.operand;
source((tiddler,title) => {
const value = caseInsensitive ? title.toLowerCase() : title,
matches = value.endsWith(operand);
if(negate ? !matches : matches) {
results.push(title);
} else if(suffixes.indexOf("caseinsensitive") !== -1) {
var operand = operator.operand.toLowerCase();
if(operator.prefix === "!") {
source(function(tiddler,title) {
if(title.toLowerCase().substr(-operand.length) !== operand) {
results.push(title);
}
});
} else {
source(function(tiddler,title) {
if(title.toLowerCase().substr(-operand.length) === operand) {
results.push(title);
}
});
}
});
} else {
if(operator.prefix === "!") {
source(function(tiddler,title) {
if(title.substr(-operator.operand.length) !== operator.operand) {
results.push(title);
}
});
} else {
source(function(tiddler,title) {
if(title.substr(-operator.operand.length) === operator.operand) {
results.push(title);
}
});
}
}
return results;
};
+5 -4
View File
@@ -22,11 +22,12 @@ exports.tag = function(source,operator,options) {
});
} else {
// Old semantics:
var tiddlers;
if(operator.prefix === "!") {
// Returns a copy of the input if operator.operand is missing
const excludeTagSet = new Set(options.wiki.getTiddlersWithTag(operator.operand));
tiddlers = options.wiki.getTiddlersWithTag(operator.operand);
source(function(tiddler,title) {
if(!excludeTagSet.has(title)) {
if(tiddlers.indexOf(title) === -1) {
results.push(title);
}
});
@@ -38,9 +39,9 @@ exports.tag = function(source,operator,options) {
return indexedResults;
}
} else {
const includeTagSet = new Set(options.wiki.getTiddlersWithTag(operator.operand));
tiddlers = options.wiki.getTiddlersWithTag(operator.operand);
source(function(tiddler,title) {
if(includeTagSet.has(title)) {
if(tiddlers.indexOf(title) !== -1) {
results.push(title);
}
});
+81 -76
View File
@@ -11,18 +11,20 @@ Extended filter operators to manipulate the current list.
/*
Fetch titles from the current list
*/
const prepare_results = (source) => {
const results = [];
source((tiddler,title) => results.push(title));
*/
var prepare_results = function (source) {
var results = [];
source(function (tiddler, title) {
results.push(title);
});
return results;
};
/*
Moves a number of items from the tail of the current list before the item named in the operand
*/
exports.putbefore = function(source,operator) {
const results = prepare_results(source),
*/
exports.putbefore = function (source, operator) {
var results = prepare_results(source),
index = results.indexOf(operator.operand),
count = $tw.utils.getInt(operator.suffix,1);
return (index === -1) ?
@@ -32,9 +34,9 @@ exports.putbefore = function(source,operator) {
/*
Moves a number of items from the tail of the current list after the item named in the operand
*/
exports.putafter = function(source,operator) {
const results = prepare_results(source),
*/
exports.putafter = function (source, operator) {
var results = prepare_results(source),
index = results.indexOf(operator.operand),
count = $tw.utils.getInt(operator.suffix,1);
return (index === -1) ?
@@ -44,9 +46,9 @@ exports.putafter = function(source,operator) {
/*
Replaces the item named in the operand with a number of items from the tail of the current list
*/
exports.replace = function(source,operator) {
const results = prepare_results(source),
*/
exports.replace = function (source, operator) {
var results = prepare_results(source),
index = results.indexOf(operator.operand),
count = $tw.utils.getInt(operator.suffix,1);
return (index === -1) ?
@@ -56,39 +58,39 @@ exports.replace = function(source,operator) {
/*
Moves a number of items from the tail of the current list to the head of the list
*/
exports.putfirst = function(source,operator) {
const results = prepare_results(source),
*/
exports.putfirst = function (source, operator) {
var results = prepare_results(source),
count = $tw.utils.getInt(operator.suffix,1);
return [...results.slice(-count), ...results.slice(0, -count)];
return results.slice(-count).concat(results.slice(0, -count));
};
/*
Moves a number of items from the head of the current list to the tail of the list
*/
exports.putlast = function(source,operator) {
const results = prepare_results(source),
*/
exports.putlast = function (source, operator) {
var results = prepare_results(source),
count = $tw.utils.getInt(operator.suffix,1);
return [...results.slice(count), ...results.slice(0, count)];
return results.slice(count).concat(results.slice(0, count));
};
/*
Moves the item named in the operand a number of places forward or backward in the list
*/
exports.move = function(source,operator) {
const results = prepare_results(source),
*/
exports.move = function (source, operator) {
var results = prepare_results(source),
index = results.indexOf(operator.operand),
count = $tw.utils.getInt(operator.suffix,1),
marker = results.splice(index, 1),
offset = (index + count) > 0 ? index + count : 0;
offset = (index + count) > 0 ? index + count : 0;
return results.slice(0, offset).concat(marker).concat(results.slice(offset));
};
/*
Returns the items from the current list that are after the item named in the operand
*/
exports.allafter = function(source,operator) {
const results = prepare_results(source),
*/
exports.allafter = function (source, operator) {
var results = prepare_results(source),
index = results.indexOf(operator.operand);
return (index === -1) ? [] :
(operator.suffix) ? results.slice(index) :
@@ -97,9 +99,9 @@ exports.allafter = function(source,operator) {
/*
Returns the items from the current list that are before the item named in the operand
*/
exports.allbefore = function(source,operator) {
const results = prepare_results(source),
*/
exports.allbefore = function (source, operator) {
var results = prepare_results(source),
index = results.indexOf(operator.operand);
return (index === -1) ? [] :
(operator.suffix) ? results.slice(0, index + 1) :
@@ -108,9 +110,9 @@ exports.allbefore = function(source,operator) {
/*
Appends the items listed in the operand array to the tail of the current list
*/
exports.append = function(source,operator) {
const append = $tw.utils.parseStringArray(operator.operand,"true"),
*/
exports.append = function (source, operator) {
var append = $tw.utils.parseStringArray(operator.operand, "true"),
results = prepare_results(source),
count = parseInt(operator.suffix) || append.length;
return (append.length === 0) ? results :
@@ -120,9 +122,9 @@ exports.append = function(source,operator) {
/*
Prepends the items listed in the operand array to the head of the current list
*/
exports.prepend = function(source,operator) {
const prepend = $tw.utils.parseStringArray(operator.operand,"true"),
*/
exports.prepend = function (source, operator) {
var prepend = $tw.utils.parseStringArray(operator.operand, "true"),
results = prepare_results(source),
count = $tw.utils.getInt(operator.suffix,prepend.length);
return (prepend.length === 0) ? results :
@@ -132,19 +134,21 @@ exports.prepend = function(source,operator) {
/*
Returns all items from the current list except the items listed in the operand array
*/
exports.remove = function(source, operator) {
const array = $tw.utils.parseStringArray(operator.operand, "true"),
results = prepare_results(source);
if(array.length === 0) {
return results;
}
const count = parseInt(operator.suffix, 10) || array.length,
targetItems = operator.prefix ? array.slice(-count).reverse() : array.slice(0, count);
for(const item of targetItems) {
const index = results.indexOf(item);
*/
exports.remove = function (source, operator) {
var array = $tw.utils.parseStringArray(operator.operand, "true"),
results = prepare_results(source),
count = parseInt(operator.suffix) || array.length,
p,
len,
index;
len = array.length - 1;
for(p = 0; p < count; ++p) {
if(operator.prefix) {
index = results.indexOf(array[len - p]);
} else {
index = results.indexOf(array[p]);
}
if(index !== -1) {
results.splice(index, 1);
}
@@ -154,38 +158,40 @@ exports.remove = function(source, operator) {
/*
Returns all items from the current list sorted in the order of the items in the operand array
*/
exports.sortby = function(source,operator) {
const results = prepare_results(source);
*/
exports.sortby = function (source, operator) {
var results = prepare_results(source);
if(!results || results.length < 2) {
return results;
}
const lookup = $tw.utils.parseStringArray(operator.operand,"true"),
// The "end" suffix places unlisted titles last, the default is first
unlisted = operator.suffix === "end" ? lookup.length : -1,
position = (title) => {
const index = lookup.indexOf(title);
return index === -1 ? unlisted : index;
};
return results.sort((a,b) => position(a) - position(b));
var lookup = $tw.utils.parseStringArray(operator.operand, "true");
results.sort(function (a, b) {
return lookup.indexOf(a) - lookup.indexOf(b);
});
return results;
};
/*
Removes all duplicate items from the current list
*/
exports.unique = function(source, operator) {
return Array.from(new Set(prepare_results(source)));
*/
exports.unique = function (source, operator) {
var results = prepare_results(source);
var set = results.reduce(function (a, b) {
if(a.indexOf(b) < 0) {
a.push(b);
}
return a;
}, []);
return set;
};
const cycleValueInArray = function(results,operands,stepSize) {
let resultsIndex,
var cycleValueInArray = function(results,operands,stepSize) {
var resultsIndex,
step = stepSize || 1,
i = 0,
opLength = operands.length,
nextOperandIndex;
const opLength = operands.length;
for(; i < opLength; i++) {
for(i; i < opLength; i++) {
resultsIndex = results.indexOf(operands[i]);
if(resultsIndex !== -1) {
break;
@@ -207,19 +213,18 @@ const cycleValueInArray = function(results,operands,stepSize) {
/*
Toggles an item in the current list.
*/
*/
exports.toggle = function(source,operator) {
return cycleValueInArray(prepare_results(source),operator.operands);
};
exports.cycle = function(source,operator) {
const results = prepare_results(source),
operands = operator.operand.length ? $tw.utils.parseStringArray(operator.operand,"true") : [""];
let step = $tw.utils.getInt(operator.operands[1] || "",1);
var results = prepare_results(source),
operands = (operator.operand.length ? $tw.utils.parseStringArray(operator.operand, "true") : [""]),
step = $tw.utils.getInt(operator.operands[1]||"",1);
if(step < 0) {
operands.reverse();
step = Math.abs(step);
}
return cycleValueInArray(results,operands,step);
};
};
+2 -3
View File
@@ -88,11 +88,10 @@ BackSubIndexer.prototype.update = function(updateDescriptor) {
var newTargets = [],
oldTargets = [],
self = this;
// System tiddlers are never indexed as sources, matching the _init() scan
if(updateDescriptor.old.exists && !this.wiki.isSystemTiddler(updateDescriptor.old.tiddler.fields.title)) {
if(updateDescriptor.old.exists) {
oldTargets = this._getTarget(updateDescriptor.old.tiddler);
}
if(updateDescriptor.new.exists && !this.wiki.isSystemTiddler(updateDescriptor.new.tiddler.fields.title)) {
if(updateDescriptor.new.exists) {
newTargets = this._getTarget(updateDescriptor.new.tiddler);
}
+11 -12
View File
@@ -26,26 +26,25 @@ exports.params = [
Run the macro
*/
exports.run = function(target,fallbackTarget,colourA,colourB) {
var rgbTarget = $tw.utils.parseCSSColorObject(target) || $tw.utils.parseCSSColorObject(fallbackTarget);
var rgbTarget = $tw.utils.parseCSSColor(target) || $tw.utils.parseCSSColor(fallbackTarget);
if(!rgbTarget) {
return colourA;
}
var rgbColourA = $tw.utils.parseCSSColorObject(colourA),
rgbColourB = $tw.utils.parseCSSColorObject(colourB);
var rgbColourA = $tw.utils.parseCSSColor(colourA),
rgbColourB = $tw.utils.parseCSSColor(colourB);
if(rgbColourA && !rgbColourB) {
return colourA;
return rgbColourA;
}
if(rgbColourB && !rgbColourA) {
return colourB;
return rgbColourB;
}
if(!rgbColourA && !rgbColourB) {
// If neither colour is readable, return a crude inverse of the target
rgbTarget.srgb.r = 1 - rgbTarget.srgb.r;
rgbTarget.srgb.g = 1 - rgbTarget.srgb.g;
rgbTarget.srgb.b = 1 - rgbTarget.srgb.b;
return rgbTarget.display();
return [255 - rgbTarget[0],255 - rgbTarget[1],255 - rgbTarget[2],rgbTarget[3]];
}
var aContrast = rgbColourA.contrast(rgbTarget,"DeltaPhi"),
bContrast = rgbColourB.contrast(rgbTarget,"DeltaPhi");
return aContrast > bContrast ? colourA : colourB;
// Colour brightness formula derived from http://www.w3.org/WAI/ER/WD-AERT/#color-contrast
var brightnessTarget = rgbTarget[0] * 0.299 + rgbTarget[1] * 0.587 + rgbTarget[2] * 0.114,
brightnessA = rgbColourA[0] * 0.299 + rgbColourA[1] * 0.587 + rgbColourA[2] * 0.114,
brightnessB = rgbColourB[0] * 0.299 + rgbColourB[1] * 0.587 + rgbColourB[2] * 0.114;
return Math.abs(brightnessTarget - brightnessA) > Math.abs(brightnessTarget - brightnessB) ? colourA : colourB;
};
+56 -68
View File
@@ -221,7 +221,7 @@ exports.parseMacroInvocationAsTransclusion = function(source,pos) {
orderedAttributes: []
};
// Define our regexps
var reVarName = /([^\s>"'=]+)/y;
var reVarName = /([^\s>"'=:]+)/y;
// Skip whitespace
pos = $tw.utils.skipWhiteSpace(source,pos);
// Look for a double opening angle bracket
@@ -269,7 +269,7 @@ exports.parseMVVReferenceAsTransclusion = function(source,pos) {
orderedAttributes: []
};
// Define our regexps
var reVarName = /([^\s>"'=)]+)/y;
var reVarName = /([^\s>"'=:)]+)/y;
// Skip whitespace
pos = $tw.utils.skipWhiteSpace(source,pos);
// Look for a double opening parenthesis
@@ -528,79 +528,67 @@ exports.parseAttribute = function(source,pos) {
pos = token.end;
// Skip whitespace
pos = $tw.utils.skipWhiteSpace(source,pos);
do {
// Look for a string literal
var stringLiteral = $tw.utils.parseStringLiteral(source,pos);
if(stringLiteral) {
pos = stringLiteral.end;
node.type = "string";
node.value = stringLiteral.value;
break;
}
// Look for a string literal
var stringLiteral = $tw.utils.parseStringLiteral(source,pos);
if(stringLiteral) {
pos = stringLiteral.end;
node.type = "string";
node.value = stringLiteral.value;
} else {
// Look for a filtered value
var filteredValue = $tw.utils.parseTokenRegExp(source,pos,reFilteredValue);
if(filteredValue) {
pos = filteredValue.end;
node.type = "filtered";
node.filter = filteredValue.match[1];
break;
} else {
// Look for an indirect value
var indirectValue = $tw.utils.parseTokenRegExp(source,pos,reIndirectValue);
if(indirectValue) {
pos = indirectValue.end;
node.type = "indirect";
node.textReference = indirectValue.match[1];
} else {
// Look for a macro invocation value
var macroInvocation = $tw.utils.parseMacroInvocationAsTransclusion(source,pos);
if(macroInvocation) {
pos = macroInvocation.end;
node.type = "macro";
node.value = macroInvocation;
} else {
// Look for an MVV reference value
var mvvReference = $tw.utils.parseMVVReferenceAsTransclusion(source,pos);
if(mvvReference) {
pos = mvvReference.end;
node.type = "macro";
node.value = mvvReference;
node.isMVV = true;
} else {
var substitutedValue = $tw.utils.parseTokenRegExp(source,pos,reSubstitutedValue);
if(substitutedValue) {
pos = substitutedValue.end;
node.type = "substituted";
node.rawValue = substitutedValue.match[1] || substitutedValue.match[2];
} else {
// Look for a unquoted value
var unquotedValue = $tw.utils.parseTokenRegExp(source,pos,reUnquotedAttribute);
if(unquotedValue) {
pos = unquotedValue.end;
node.type = "string";
node.value = unquotedValue.match[1];
} else if(source.charAt(pos) === "<" && source.charAt(pos + 1) === "<" && source.indexOf(">>",pos) !== -1) {
// Value looks like a macro invocation (starts with << with a closing >> ahead) but does not parse as one. Return null so the enclosing tag fails to parse rather than silently binding the attribute to "true" and treating the remainder as further attributes (restores v5.3.8 behaviour)
return null;
} else {
node.type = "string";
node.value = "true";
}
}
}
}
}
}
// Look for an indirect value
var indirectValue = $tw.utils.parseTokenRegExp(source,pos,reIndirectValue);
if(indirectValue) {
pos = indirectValue.end;
node.type = "indirect";
node.textReference = indirectValue.match[1];
break;
}
// Look for a macro invocation value
var macroInvocation = $tw.utils.parseMacroInvocationAsTransclusion(source,pos);
if(macroInvocation) {
pos = macroInvocation.end;
node.type = "macro";
node.value = macroInvocation;
break;
}
// Look for an MVV reference value
var mvvReference = $tw.utils.parseMVVReferenceAsTransclusion(source,pos);
if(mvvReference) {
pos = mvvReference.end;
node.type = "macro";
node.value = mvvReference;
node.isMVV = true;
break;
}
// Look for a substituted value
var substitutedValue = $tw.utils.parseTokenRegExp(source,pos,reSubstitutedValue);
if(substitutedValue) {
pos = substitutedValue.end;
node.type = "substituted";
node.rawValue = substitutedValue.match[1] || substitutedValue.match[2];
break;
}
// Look for a unquoted value
var unquotedValue = $tw.utils.parseTokenRegExp(source,pos,reUnquotedAttribute);
if(unquotedValue) {
pos = unquotedValue.end;
node.type = "string";
node.value = unquotedValue.match[1];
break;
}
if(source.charAt(pos) === "<" && source.charAt(pos + 1) === "<" && source.indexOf(">>",pos) !== -1) {
// Value looks like a macro invocation (starts with << with a closing >> ahead) but does not parse as one. Return null so the enclosing tag fails to parse rather than silently binding the attribute to "true" and treating the remainder as further attributes (restores v5.3.8 behaviour)
return null;
}
node.type = "string";
node.value = "true";
} while(false);
}
} else {
// If there is no equals sign or colon, then this is an attribute with no value, defaulting to "true"
node.type = "string";
@@ -25,7 +25,7 @@ exports.init = function(parser) {
};
exports.parse = function() {
var reEnd = /(^|\r?\n)```$/mg;
var reEnd = /(\r?\n```$)/mg;
var languageStart = this.parser.pos + 3,
languageEnd = languageStart + this.match[1].length;
// Move past the match
+9 -29
View File
@@ -4,6 +4,7 @@ type: application/javascript
module-type: startup
Browser message handling
\*/
"use strict";
@@ -17,20 +18,6 @@ exports.synchronous = true;
/*
Load a specified url as an iframe and call the callback when it is loaded. If the url is already loaded then the existing iframe instance is used
*/
// Ensure the callback fires once, whether by PLUGIN-LIBRARY-READY or onload (legacy)
function flushCallbacks(iframeInfo, err) {
if(iframeInfo.status !== "loaded") {
iframeInfo.status = err ? "error" : "loaded";
saveIFrameInfoTiddler(iframeInfo);
var cb;
while((cb = iframeInfo.callbacks.shift())) {
cb(err, iframeInfo);
}
}
}
function loadIFrame(url,callback) {
// Check if iframe already exists
var iframeInfo = $tw.browserMessaging.iframeInfoMap[url];
@@ -43,8 +30,7 @@ function loadIFrame(url,callback) {
iframeInfo = {
url: url,
status: "loading",
domNode: iframe,
callbacks: [callback]
domNode: iframe
};
$tw.browserMessaging.iframeInfoMap[url] = iframeInfo;
saveIFrameInfoTiddler(iframeInfo);
@@ -52,18 +38,19 @@ function loadIFrame(url,callback) {
iframe.style.display = "none";
iframe.setAttribute("library","true");
document.body.appendChild(iframe);
// Set up onload. Legacy fallback: if PLUGIN-LIBRARY-READY never arrives, onload triggers the flush later
// Set up onload
iframe.onload = function() {
flushCallbacks(iframeInfo);
iframeInfo.status = "loaded";
saveIFrameInfoTiddler(iframeInfo);
callback(null,iframeInfo);
};
iframe.onerror = function() {
flushCallbacks(iframeInfo, "Cannot load iframe");
callback("Cannot load iframe");
};
try {
iframe.src = url;
} catch(ex) {
flushCallbacks(iframeInfo, ex);
callback(ex);
}
}
}
@@ -73,7 +60,7 @@ Unload library iframe for given url
*/
function unloadIFrame(url){
var iframes = document.getElementsByTagName("iframe");
for(var t = iframes.length - 1; t >= 0; t--) {
for(var t=iframes.length-1; t--; t>=0) {
var iframe = iframes[t];
if(iframe.getAttribute("library") === "true" &&
iframe.getAttribute("src") === url) {
@@ -160,13 +147,6 @@ exports.startup = function() {
// console.log("browser-messaging: Received message from",event.origin);
// console.log("browser-messaging: Message content",event.data);
switch(event.data.verb) {
case "PLUGIN-LIBRARY-READY":
$tw.utils.each($tw.browserMessaging.iframeInfoMap, function(info) {
if(info && info.domNode && info.domNode.contentWindow === event.source) {
flushCallbacks(info);
}
});
break;
case "GET-RESPONSE":
if(event.data.status.charAt(0) === "2") {
if(event.data.cookies) {
+1 -2
View File
@@ -15,8 +15,7 @@ var getCellInfo = function(text, start, length, SEPARATOR) {
var isCellQuoted = text.charAt(start) === QUOTE;
var cellStart = isCellQuoted ? start + 1 : start;
// A quote licenses a separator inside the cell, so only an unquoted cell reads an immediate separator as empty
if(!isCellQuoted && text.charAt(cellStart) === SEPARATOR) {
if(text.charAt(i) === SEPARATOR) {
return [cellStart, cellStart, false];
}
-62
View File
@@ -1,62 +0,0 @@
/*\
title: $:/core/modules/utils/color-utils.js
type: application/javascript
module-type: utils
Color.js related utilities
\*/
"use strict";
var Color = require("$:/core/modules/utils/dom/color.js").Color;
/*
For backwards compatibility
*/
exports.parseCSSColor = function(colourString) {
var c = exports.parseCSSColorObject(colourString);
if(c) {
var rgb = c.srgb;
// Return components in the 0-255 range, matching the legacy csscolorparser.
// Clamp because Color.js can emit out-of-gamut sRGB components (e.g. from P3 inputs).
return [
Math.round(Math.max(0,Math.min(255,rgb[0] * 255))),
Math.round(Math.max(0,Math.min(255,rgb[1] * 255))),
Math.round(Math.max(0,Math.min(255,rgb[2] * 255))),
c.alpha
];
} else {
return null;
}
};
/*
Preferred way to parse a Color.js colour
*/
exports.parseCSSColorObject = function(colourString) {
var c = null;
try {
c = new Color(colourString);
} catch(e) {
// Return null if there is an error
}
return c;
};
/*
Convert a CSS colour to an RGB string suitable for use with the <input type="color"> element
*/
exports.convertCSSColorToRGBString = function(colourString) {
// The <input type="color"> element only accepts six digit hex values, so we
// discard any alpha channel and fall back to black for unparseable input
var rgb = exports.parseCSSColor(colourString);
if(rgb) {
return "#" + rgb.slice(0,3).map(function(component) {
return ("0" + component.toString(16)).slice(-2);
}).join("");
} else {
return "#000000";
}
};
-21
View File
@@ -1,21 +0,0 @@
MIT License
Copyright (c) 2021 Lea Verou, Chris Lilley
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
File diff suppressed because one or more lines are too long
@@ -1,21 +0,0 @@
{
"tiddlers": [
{
"file": "color.global.min.v0.6.1.js",
"fields": {
"type": "application/javascript",
"title": "$:/core/modules/utils/dom/color.js",
"module-type": "library"
},
"prefix": "",
"suffix": ";\nexports.Color = Color;"
},
{
"file": "LICENSE",
"fields": {
"type": "text/plain",
"title": "$:/core/modules/utils/dom/color.js/license"
}
}
]
}
+200
View File
@@ -0,0 +1,200 @@
// (c) Dean McNamee <dean@gmail.com>, 2012.
//
// https://github.com/deanm/css-color-parser-js
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
// http://www.w3.org/TR/css3-color/
var kCSSColorTable = {
"transparent": [0,0,0,0], "aliceblue": [240,248,255,1],
"antiquewhite": [250,235,215,1], "aqua": [0,255,255,1],
"aquamarine": [127,255,212,1], "azure": [240,255,255,1],
"beige": [245,245,220,1], "bisque": [255,228,196,1],
"black": [0,0,0,1], "blanchedalmond": [255,235,205,1],
"blue": [0,0,255,1], "blueviolet": [138,43,226,1],
"brown": [165,42,42,1], "burlywood": [222,184,135,1],
"cadetblue": [95,158,160,1], "chartreuse": [127,255,0,1],
"chocolate": [210,105,30,1], "coral": [255,127,80,1],
"cornflowerblue": [100,149,237,1], "cornsilk": [255,248,220,1],
"crimson": [220,20,60,1], "cyan": [0,255,255,1],
"darkblue": [0,0,139,1], "darkcyan": [0,139,139,1],
"darkgoldenrod": [184,134,11,1], "darkgray": [169,169,169,1],
"darkgreen": [0,100,0,1], "darkgrey": [169,169,169,1],
"darkkhaki": [189,183,107,1], "darkmagenta": [139,0,139,1],
"darkolivegreen": [85,107,47,1], "darkorange": [255,140,0,1],
"darkorchid": [153,50,204,1], "darkred": [139,0,0,1],
"darksalmon": [233,150,122,1], "darkseagreen": [143,188,143,1],
"darkslateblue": [72,61,139,1], "darkslategray": [47,79,79,1],
"darkslategrey": [47,79,79,1], "darkturquoise": [0,206,209,1],
"darkviolet": [148,0,211,1], "deeppink": [255,20,147,1],
"deepskyblue": [0,191,255,1], "dimgray": [105,105,105,1],
"dimgrey": [105,105,105,1], "dodgerblue": [30,144,255,1],
"firebrick": [178,34,34,1], "floralwhite": [255,250,240,1],
"forestgreen": [34,139,34,1], "fuchsia": [255,0,255,1],
"gainsboro": [220,220,220,1], "ghostwhite": [248,248,255,1],
"gold": [255,215,0,1], "goldenrod": [218,165,32,1],
"gray": [128,128,128,1], "green": [0,128,0,1],
"greenyellow": [173,255,47,1], "grey": [128,128,128,1],
"honeydew": [240,255,240,1], "hotpink": [255,105,180,1],
"indianred": [205,92,92,1], "indigo": [75,0,130,1],
"ivory": [255,255,240,1], "khaki": [240,230,140,1],
"lavender": [230,230,250,1], "lavenderblush": [255,240,245,1],
"lawngreen": [124,252,0,1], "lemonchiffon": [255,250,205,1],
"lightblue": [173,216,230,1], "lightcoral": [240,128,128,1],
"lightcyan": [224,255,255,1], "lightgoldenrodyellow": [250,250,210,1],
"lightgray": [211,211,211,1], "lightgreen": [144,238,144,1],
"lightgrey": [211,211,211,1], "lightpink": [255,182,193,1],
"lightsalmon": [255,160,122,1], "lightseagreen": [32,178,170,1],
"lightskyblue": [135,206,250,1], "lightslategray": [119,136,153,1],
"lightslategrey": [119,136,153,1], "lightsteelblue": [176,196,222,1],
"lightyellow": [255,255,224,1], "lime": [0,255,0,1],
"limegreen": [50,205,50,1], "linen": [250,240,230,1],
"magenta": [255,0,255,1], "maroon": [128,0,0,1],
"mediumaquamarine": [102,205,170,1], "mediumblue": [0,0,205,1],
"mediumorchid": [186,85,211,1], "mediumpurple": [147,112,219,1],
"mediumseagreen": [60,179,113,1], "mediumslateblue": [123,104,238,1],
"mediumspringgreen": [0,250,154,1], "mediumturquoise": [72,209,204,1],
"mediumvioletred": [199,21,133,1], "midnightblue": [25,25,112,1],
"mintcream": [245,255,250,1], "mistyrose": [255,228,225,1],
"moccasin": [255,228,181,1], "navajowhite": [255,222,173,1],
"navy": [0,0,128,1], "oldlace": [253,245,230,1],
"olive": [128,128,0,1], "olivedrab": [107,142,35,1],
"orange": [255,165,0,1], "orangered": [255,69,0,1],
"orchid": [218,112,214,1], "palegoldenrod": [238,232,170,1],
"palegreen": [152,251,152,1], "paleturquoise": [175,238,238,1],
"palevioletred": [219,112,147,1], "papayawhip": [255,239,213,1],
"peachpuff": [255,218,185,1], "peru": [205,133,63,1],
"pink": [255,192,203,1], "plum": [221,160,221,1],
"powderblue": [176,224,230,1], "purple": [128,0,128,1],
"red": [255,0,0,1], "rosybrown": [188,143,143,1],
"royalblue": [65,105,225,1], "saddlebrown": [139,69,19,1],
"salmon": [250,128,114,1], "sandybrown": [244,164,96,1],
"seagreen": [46,139,87,1], "seashell": [255,245,238,1],
"sienna": [160,82,45,1], "silver": [192,192,192,1],
"skyblue": [135,206,235,1], "slateblue": [106,90,205,1],
"slategray": [112,128,144,1], "slategrey": [112,128,144,1],
"snow": [255,250,250,1], "springgreen": [0,255,127,1],
"steelblue": [70,130,180,1], "tan": [210,180,140,1],
"teal": [0,128,128,1], "thistle": [216,191,216,1],
"tomato": [255,99,71,1], "turquoise": [64,224,208,1],
"violet": [238,130,238,1], "wheat": [245,222,179,1],
"white": [255,255,255,1], "whitesmoke": [245,245,245,1],
"yellow": [255,255,0,1], "yellowgreen": [154,205,50,1]}
function clamp_css_byte(i) { // Clamp to integer 0 .. 255.
i = Math.round(i); // Seems to be what Chrome does (vs truncation).
return i < 0 ? 0 : i > 255 ? 255 : i;
}
function clamp_css_float(f) { // Clamp to float 0.0 .. 1.0.
return f < 0 ? 0 : f > 1 ? 1 : f;
}
function parse_css_int(str) { // int or percentage.
if (str[str.length - 1] === '%')
return clamp_css_byte(parseFloat(str) / 100 * 255);
return clamp_css_byte(parseInt(str));
}
function parse_css_float(str) { // float or percentage.
if (str[str.length - 1] === '%')
return clamp_css_float(parseFloat(str) / 100);
return clamp_css_float(parseFloat(str));
}
function css_hue_to_rgb(m1, m2, h) {
if (h < 0) h += 1;
else if (h > 1) h -= 1;
if (h * 6 < 1) return m1 + (m2 - m1) * h * 6;
if (h * 2 < 1) return m2;
if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6;
return m1;
}
function parseCSSColor(css_str) {
// Remove all whitespace, not compliant, but should just be more accepting.
var str = css_str.replace(/ /g, '').toLowerCase();
// Color keywords (and transparent) lookup.
if (str in kCSSColorTable) return kCSSColorTable[str].slice(); // dup.
// #abc and #abc123 syntax.
if (str[0] === '#') {
if (str.length === 4) {
var iv = parseInt(str.substr(1), 16); // TODO(deanm): Stricter parsing.
if (!(iv >= 0 && iv <= 0xfff)) return null; // Covers NaN.
return [((iv & 0xf00) >> 4) | ((iv & 0xf00) >> 8),
(iv & 0xf0) | ((iv & 0xf0) >> 4),
(iv & 0xf) | ((iv & 0xf) << 4),
1];
} else if (str.length === 7) {
var iv = parseInt(str.substr(1), 16); // TODO(deanm): Stricter parsing.
if (!(iv >= 0 && iv <= 0xffffff)) return null; // Covers NaN.
return [(iv & 0xff0000) >> 16,
(iv & 0xff00) >> 8,
iv & 0xff,
1];
}
return null;
}
var op = str.indexOf('('), ep = str.indexOf(')');
if (op !== -1 && ep + 1 === str.length) {
var fname = str.substr(0, op);
var params = str.substr(op+1, ep-(op+1)).split(',');
var alpha = 1; // To allow case fallthrough.
switch (fname) {
case 'rgba':
if (params.length !== 4) return null;
alpha = parse_css_float(params.pop());
// Fall through.
case 'rgb':
if (params.length !== 3) return null;
return [parse_css_int(params[0]),
parse_css_int(params[1]),
parse_css_int(params[2]),
alpha];
case 'hsla':
if (params.length !== 4) return null;
alpha = parse_css_float(params.pop());
// Fall through.
case 'hsl':
if (params.length !== 3) return null;
var h = (((parseFloat(params[0]) % 360) + 360) % 360) / 360; // 0 .. 1
// NOTE(deanm): According to the CSS spec s/l should only be
// percentages, but we don't bother and let float or percentage.
var s = parse_css_float(params[1]);
var l = parse_css_float(params[2]);
var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s;
var m1 = l * 2 - m2;
return [clamp_css_byte(css_hue_to_rgb(m1, m2, h+1/3) * 255),
clamp_css_byte(css_hue_to_rgb(m1, m2, h) * 255),
clamp_css_byte(css_hue_to_rgb(m1, m2, h-1/3) * 255),
alpha];
default:
return null;
}
}
return null;
}
try { exports.parseCSSColor = parseCSSColor } catch(e) { }
@@ -0,0 +1,3 @@
title: $:/core/modules/utils/dom/csscolorparser.js
type: application/javascript
module-type: utils
+5 -6
View File
@@ -164,16 +164,15 @@ exports.forceLayout = function(element) {
Pulse an element for debugging purposes
*/
exports.pulseElement = function(element) {
var eventName = $tw.utils.convertEventName("animationEnd");
// Event handler to remove the class at the end
element.addEventListener(eventName,function handler(event) {
element.removeEventListener(eventName,handler,false);
$tw.utils.removeClass(element,"tc-pulse");
element.addEventListener($tw.browser.animationEnd,function handler(event) {
element.removeEventListener($tw.browser.animationEnd,handler,false);
$tw.utils.removeClass(element,"pulse");
},false);
// Apply the pulse class
$tw.utils.removeClass(element,"tc-pulse");
$tw.utils.removeClass(element,"pulse");
$tw.utils.forceLayout(element);
$tw.utils.addClass(element,"tc-pulse");
$tw.utils.addClass(element,"pulse");
};
/*
+2 -13
View File
@@ -115,9 +115,7 @@ var TW_Element = function(tag, namespace) {
this.children = [];
this._style = {}; // Internal style object
this.style = new TW_Style(this); // Proxy for style management
// createElementNS with empty-string or null normalises to null (no namespace) per spec.
// https://dom.spec.whatwg.org/#dom-document-createelementns
this.namespaceURI = namespace !== undefined ? (namespace || null) : "http://www.w3.org/1999/xhtml";
this.namespaceURI = namespace || "http://www.w3.org/1999/xhtml";
};
@@ -208,16 +206,7 @@ TW_Element.prototype.addEventListener = function(type,listener,useCapture) {
Object.defineProperty(TW_Element.prototype, "tagName", {
get: function() {
if(!this.tag) {
return "";
}
// HTML elements report uppercase tagName per DOM spec. Other namespaces
// preserve case. Fakedom only models HTML documents.
// https://dom.spec.whatwg.org/#dom-element-tagname
if(this.namespaceURI === "http://www.w3.org/1999/xhtml") {
return this.tag.toUpperCase();
}
return this.tag;
return this.tag || "";
}
});
+2 -2
View File
@@ -62,8 +62,8 @@ SendMessageWidget.prototype.invokeAction = function(triggeringWidget,event) {
var paramObject = Object.create(null);
// Add names/values pairs if present
if(this.actionNames && this.actionValues) {
var names = this.wiki.filterTiddlers(this.actionNames,this,null,{defaultFilterRunPrefix: "all"}),
values = this.wiki.filterTiddlers(this.actionValues,this,null,{defaultFilterRunPrefix: "all"});
var names = this.wiki.filterTiddlers(this.actionNames,this),
values = this.wiki.filterTiddlers(this.actionValues,this);
$tw.utils.each(names,function(name,index) {
paramObject[name] = values[index] || "";
});
@@ -56,10 +56,10 @@ Invoke the action associated with this widget
*/
SetMultipleFieldsWidget.prototype.invokeAction = function(triggeringWidget,event) {
var tiddler = this.wiki.getTiddler(this.actionTiddler),
names, values = this.wiki.filterTiddlers(this.actionValues,this,null,{defaultFilterRunPrefix: "all"});
names, values = this.wiki.filterTiddlers(this.actionValues,this);
if(this.actionFields) {
var additions = {};
names = this.wiki.filterTiddlers(this.actionFields,this,null,{defaultFilterRunPrefix: "all"});
names = this.wiki.filterTiddlers(this.actionFields,this);
$tw.utils.each(names,function(fieldname,index) {
additions[fieldname] = values[index] || "";
});
@@ -68,7 +68,7 @@ SetMultipleFieldsWidget.prototype.invokeAction = function(triggeringWidget,event
this.wiki.addTiddler(new $tw.Tiddler(creationFields,tiddler,{title: this.actionTiddler},modificationFields,additions));
} else if(this.actionIndexes) {
var data = this.wiki.getTiddlerData(this.actionTiddler,Object.create(null));
names = this.wiki.filterTiddlers(this.actionIndexes,this,null,{defaultFilterRunPrefix: "all"});
names = this.wiki.filterTiddlers(this.actionIndexes,this);
$tw.utils.each(names,function(name,index) {
data[name] = values[index] || "";
});
+5 -19
View File
@@ -151,24 +151,10 @@ ButtonWidget.prototype.getBoundingClientRect = function() {
};
ButtonWidget.prototype.isSelected = function() {
var currentValue;
if(this.setTitle) {
if(this.setField) {
// The state tiddler usually does not exist until the button is first clicked
var tiddler = this.wiki.getTiddler(this.setTitle);
currentValue = tiddler ? tiddler.getFieldString(this.setField) : undefined;
} else if(this.setIndex) {
currentValue = this.wiki.extractTiddlerDataItem(this.setTitle,this.setIndex);
} else {
currentValue = this.wiki.getTiddlerText(this.setTitle);
}
if(!currentValue) {
currentValue = this.defaultSetValue || this.getVariable("currentTiddler");
}
} else {
currentValue = this.wiki.getTextReference(this.set,this.defaultSetValue,this.getVariable("currentTiddler"));
}
return currentValue === this.setTo;
return this.setTitle ? (this.setField ? this.wiki.getTiddler(this.setTitle).getFieldString(this.setField) === this.setTo :
(this.setIndex ? this.wiki.extractTiddlerDataItem(this.setTitle,this.setIndex) === this.setTo :
this.wiki.getTiddlerText(this.setTitle))) || this.defaultSetValue || this.getVariable("currentTiddler") :
this.wiki.getTextReference(this.set,this.defaultSetValue,this.getVariable("currentTiddler")) === this.setTo;
};
ButtonWidget.prototype.isPoppedUp = function() {
@@ -281,7 +267,7 @@ Selectively refreshes the widget if needed. Returns true if the widget or any of
*/
ButtonWidget.prototype.refresh = function(changedTiddlers) {
var changedAttributes = this.computeAttributes();
if(changedAttributes.tooltip || changedAttributes.actions || changedAttributes.to || changedAttributes.message || changedAttributes.param || changedAttributes.set || changedAttributes.setTo || changedAttributes.popup || changedAttributes.hover || changedAttributes.selectedClass || changedAttributes.style || changedAttributes.dragFilter || changedAttributes.dragTiddler || (this.set && changedTiddlers[this.set]) || (this.setTitle && changedTiddlers[this.setTitle]) || (this.popup && changedTiddlers[this.popup]) || (this.popupTitle && changedTiddlers[this.popupTitle]) || changedAttributes.popupAbsCoords || changedAttributes.setTitle || changedAttributes.setField || changedAttributes.setIndex || changedAttributes.popupTitle || changedAttributes.disabled || changedAttributes["default"]) {
if(changedAttributes.tooltip || changedAttributes.actions || changedAttributes.to || changedAttributes.message || changedAttributes.param || changedAttributes.set || changedAttributes.setTo || changedAttributes.popup || changedAttributes.hover || changedAttributes.selectedClass || changedAttributes.style || changedAttributes.dragFilter || changedAttributes.dragTiddler || (this.set && changedTiddlers[this.set]) || (this.popup && changedTiddlers[this.popup]) || (this.popupTitle && changedTiddlers[this.popupTitle]) || changedAttributes.popupAbsCoords || changedAttributes.setTitle || changedAttributes.setField || changedAttributes.setIndex || changedAttributes.popupTitle || changedAttributes.disabled || changedAttributes["default"]) {
this.refreshSelf();
return true;
} else {
+1 -1
View File
@@ -22,7 +22,7 @@ Inherit from the base widget class
DiffTextWidget.prototype = new Widget();
DiffTextWidget.prototype.invisibleCharacters = {
"\n": "\n",
"\n": "↩︎\n",
"\r": "⇠",
"\t": "⇥\t"
};
+4 -4
View File
@@ -72,8 +72,8 @@ GenesisWidget.prototype.execute = function() {
this.attributeNames = [];
this.attributeValues = [];
if(this.genesisNames && this.genesisValues) {
this.attributeNames = this.wiki.filterTiddlers(self.genesisNames,this,null,{defaultFilterRunPrefix: "all"});
this.attributeValues = this.wiki.filterTiddlers(self.genesisValues,this,null,{defaultFilterRunPrefix: "all"});
this.attributeNames = this.wiki.filterTiddlers(self.genesisNames,this);
this.attributeValues = this.wiki.filterTiddlers(self.genesisValues,this);
$tw.utils.each(this.attributeNames,function(varname,index) {
$tw.utils.addAttributeToParseTreeNode(parseTreeNodes[0],varname,self.attributeValues[index] || "");
});
@@ -103,8 +103,8 @@ GenesisWidget.prototype.refresh = function(changedTiddlers) {
var changedAttributes = this.computeAttributes(),
filterNames = this.getAttribute("$names",""),
filterValues = this.getAttribute("$values",""),
attributeNames = this.wiki.filterTiddlers(filterNames,this,null,{defaultFilterRunPrefix: "all"}),
attributeValues = this.wiki.filterTiddlers(filterValues,this,null,{defaultFilterRunPrefix: "all"});
attributeNames = this.wiki.filterTiddlers(filterNames,this),
attributeValues = this.wiki.filterTiddlers(filterValues,this);
if($tw.utils.count(changedAttributes) > 0 || !$tw.utils.isArrayEqual(this.attributeNames,attributeNames) || !$tw.utils.isArrayEqual(this.attributeValues,attributeValues)) {
this.refreshSelf();
return true;
+1 -2
View File
@@ -99,8 +99,7 @@ LinkWidget.prototype.renderLink = function(parent,nextSibling) {
wikiLinkText = this.wiki.filterTiddlers(wikilinkTransformFilter,this,function(iterator) {
iterator(self.wiki.getTiddler(self.to),self.to);
})[0];
}
if(!wikiLinkText) {
} else {
// Expand the tv-wikilink-template variable to construct the href
var wikiLinkTemplateMacro = this.getVariable("tv-wikilink-template"),
wikiLinkTemplate = wikiLinkTemplateMacro ? wikiLinkTemplateMacro.trim() : "#$uri_encoded$";
+4 -4
View File
@@ -49,8 +49,8 @@ SetMultipleVariablesWidget.prototype.setVariables = function() {
this.variableNames = [];
this.variableValues = [];
if(filterNames && filterValues) {
this.variableNames = this.wiki.filterTiddlers(filterNames,this,null,{defaultFilterRunPrefix: "all"});
this.variableValues = this.wiki.filterTiddlers(filterValues,this,null,{defaultFilterRunPrefix: "all"});
this.variableNames = this.wiki.filterTiddlers(filterNames,this);
this.variableValues = this.wiki.filterTiddlers(filterValues,this);
$tw.utils.each(this.variableNames,function(varname,index) {
self.setVariable(varname,self.variableValues[index]);
});
@@ -63,8 +63,8 @@ Refresh the widget by ensuring our attributes are up to date
SetMultipleVariablesWidget.prototype.refresh = function(changedTiddlers) {
var filterNames = this.getAttribute("$names",""),
filterValues = this.getAttribute("$values",""),
variableNames = this.wiki.filterTiddlers(filterNames,this,null,{defaultFilterRunPrefix: "all"}),
variableValues = this.wiki.filterTiddlers(filterValues,this,null,{defaultFilterRunPrefix: "all"});
variableNames = this.wiki.filterTiddlers(filterNames,this),
variableValues = this.wiki.filterTiddlers(filterValues,this);
if(!$tw.utils.isArrayEqual(this.variableNames,variableNames) || !$tw.utils.isArrayEqual(this.variableValues,variableValues)) {
this.refreshSelf();
return true;
-10
View File
@@ -1,10 +0,0 @@
title: $:/palettes/AutoToggle
name: AutoToggle
description: Automatically switch between dark and light modes
tags: $:/tags/Palette
type: application/x-tiddler-dictionary
color-scheme: [{$:/info/browser/darkmode}!match[yes]then[light]else[dark]]
customisations: $:/palettes/AutoToggle/Customisations
palette-import@light: $:/palettes/TwentyTwenties
palette-import@dark: $:/palettes/TwentyTwenties/Dark
category: 2026
@@ -1,25 +0,0 @@
title: $:/palettes/AutoToggle/Customisations
\procedure layer-input-actions()
<$action-setfield $tiddler=<<layerTitle>> palette-import={{$:/palette}}/>
\end layer-input-actions
\procedure set-imported-palette(field)
<$select field=<<field>> default={{{ [[$:/temp/palette-consolidated]get<field>] }}} actions=<<layer-input-actions>>>
<$list filter="[all[shadows+tiddlers]tag[$:/tags/Palette]sort[name]] -[{$:/palette}]">
<option value=<<currentTiddler>>><$view field="name"><$view field="title"/></$view></option>
</$list>
</$select>
\end set-imported-palette
This palette can be used to automatically switch between two palettes based on the browser's dark mode setting.
<$let layerTitle={{{ [function[tf.palette-customisations-layer]] }}}>
<$tiddler tiddler=<<layerTitle>>>
Light palette: <<set-imported-palette field:"palette-import@light">>
Dark palette: <<set-imported-palette field:"palette-import@dark">>
</$tiddler>
</$let>
@@ -1,6 +1,5 @@
title: $:/palettes/Blanca
name: Blanca
category: Legacy
color-scheme: light
description: A clean white palette to let you focus
tags: $:/tags/Palette
@@ -1,6 +1,5 @@
title: $:/palettes/Blue
name: Blue
category: Legacy
color-scheme: light
description: A blue theme
tags: $:/tags/Palette
@@ -1,6 +1,5 @@
title: $:/palettes/Muted
name: Muted
category: Legacy
color-scheme: light
description: Bright tiddlers on a muted background
tags: $:/tags/Palette
@@ -1,6 +1,5 @@
title: $:/palettes/ContrastDark
name: Contrast (Dark)
category: Legacy
color-scheme: dark
description: High contrast and unambiguous (dark version)
tags: $:/tags/Palette
@@ -1,6 +1,5 @@
title: $:/palettes/ContrastLight
name: Contrast (Light)
category: Legacy
color-scheme: light
description: High contrast and unambiguous (light version)
tags: $:/tags/Palette
@@ -2,7 +2,6 @@ title: $:/palettes/CupertinoDark
tags: $:/tags/Palette
color-scheme: dark
name: Cupertino Dark
category: Legacy
description: A macOS inspired dark palette
type: application/x-tiddler-dictionary
@@ -2,7 +2,6 @@ created: 20150402111612188
description: Good with dark photo backgrounds
modified: 20150402112344080
name: DarkPhotos
category: Legacy
tags: $:/tags/Palette
title: $:/palettes/DarkPhotos
type: application/x-tiddler-dictionary
@@ -2,7 +2,6 @@ title: $:/palettes/DesertSand
tags: $:/tags/Palette
color-scheme: light
name: Desert Sand
category: Legacy
description: A desert sand palette
type: application/x-tiddler-dictionary
@@ -1,7 +1,6 @@
color-scheme: dark
description: An inky color scheme for prose and code
name: FlexokiDark
category: Legacy
tags: $:/tags/Palette
title: $:/palettes/FlexokiDark
type: application/x-tiddler-dictionary
@@ -1,6 +1,5 @@
title: $:/palettes/FlexokiLight
name: FlexokiLight
category: Legacy
description: An inky color scheme for prose and code
tags: $:/tags/Palette
type: application/x-tiddler-dictionary
@@ -1,6 +1,5 @@
title: $:/palettes/GruvboxDark
name: Gruvbox Dark
category: Legacy
color-scheme: dark
description: Retro groove color scheme
tags: $:/tags/Palette
@@ -1,6 +1,5 @@
title: $:/palettes/Nord
name: Nord
category: Legacy
color-scheme: dark
description: An arctic, north-bluish color palette.
tags: $:/tags/Palette
@@ -1,6 +1,5 @@
title: $:/palettes/Rocker
name: Rocker
category: Legacy
color-scheme: dark
description: A dark theme
tags: $:/tags/Palette
@@ -1,6 +1,5 @@
title: $:/palettes/SolarFlare
name: Solar Flare
category: Legacy
color-scheme: light
description: Warm, relaxing earth colours
tags: $:/tags/Palette
@@ -1,6 +1,5 @@
title: $:/palettes/SolarizedDark
tags: $:/tags/Palette
category: Legacy
type: application/x-tiddler-dictionary
description: Precision dark colors for machines and people
license: MIT, Ethan Schoonover, https://github.com/altercation/solarized/blob/master/LICENSE
@@ -4,7 +4,6 @@ type: application/x-tiddler-dictionary
description: Precision colors for machines and people
license: MIT, Ethan Schoonover, https://github.com/altercation/solarized/blob/master/LICENSE
name: SolarizedLight
category: Legacy
color-scheme: light
alert-background: #eee8d5
@@ -4,7 +4,6 @@ type: application/x-tiddler-dictionary
description: Cold, spartan day colors
name: Spartan Day
color-scheme: light
category: Legacy
alert-background: <<colour background>>
alert-border: <<colour very-muted-foreground>>
@@ -4,7 +4,6 @@ type: application/x-tiddler-dictionary
description: Dark spartan colors
name: Spartan Night
color-scheme: dark
category: Legacy
alert-background: <<colour background>>
alert-border: <<colour very-muted-foreground>>
-226
View File
@@ -1,226 +0,0 @@
title: $:/palettes/TwentyTwenties
name: TwentyTwenties
description: Modern and flexible
tags: $:/tags/Palette
type: application/x-tiddler-dictionary
color-scheme: light
customisations: $:/palettes/TwentyTwenties/Customisations
palette-import: $:/palettes/Vanilla
category: 2026
# Background and foreground colours, which are interpolated as required
base-paper: #FFFCF0
base-background: #f0d5c6
base-ink: #333344
?base-paper-ink: [tf.check-colour-contrast[base-paper],[base-ink],[45]]
?base-background-ink: [tf.check-colour-contrast[base-background],[base-ink],[45]]
# Primary colour, used for links and other accented elements
base-primary: #5778d8
?base-paper-primary: [tf.check-colour-contrast[base-paper],[base-primary],[45]]
?base-background-primary: [tf.check-colour-contrast[base-background],[base-primary],[45]]
# Secondary colour, used for alerts and other secondary elements
base-secondary: #f0e48a
?base-ink-secondary: [tf.check-colour-contrast[base-ink],[base-secondary],[45]]
# Tertiary base colour, used for monospaced text and other tertiary elements
base-tertiary: rgb(183, 95, 95)
?base-paper-tertiary: [tf.check-colour-contrast[base-paper],[base-tertiary],[45]]
# Basic spectrum colours
base-black: #100F0F
base-red: #D14D41
base-orange: #DA702C
base-yellow: #D0A215
base-green: #879A39
base-cyan: #3AA99F
base-blue: #4385BE
base-purple: #8B7EC8
base-magenta: #CE5D97
base-white: #FFFCF0
# Darker variants
# base-red: #AF3029
# base-orange: #BC5215
# base-yellow: #AD8301
# base-green: #66800B
# base-cyan: #24837B
# base-blue: #205EA6
# base-purple: #5E409D
# base-magenta: #A02F6F
# Palette definitions
alert-background: [tf.colour[base-secondary]]
alert-border: [tf.interpolate-colours[base-ink],[alert-background],[0.6]]
alert-highlight: [tf.interpolate-colours[base-ink],[base-primary],[0.3]]
alert-muted-foreground: [tf.interpolate-colours[base-ink],[alert-background],[0.4]]
background: [tf.colour[base-paper]]
blockquote-bar: [tf.colour[muted-foreground]]
button-background:
button-border:
button-foreground:
code-background: [tf.interpolate-colours[base-paper],[base-tertiary],[0.1]]
code-border: [tf.interpolate-colours[base-paper],[base-tertiary],[0.6]]
code-foreground: [tf.colour[base-tertiary]]
diff-delete-background: [tf.colour[base-red]]
diff-delete-foreground: [tf.colour[foreground]]
diff-equal-background:
diff-equal-foreground: [tf.colour[foreground]]
diff-insert-background: [tf.colour[base-green]]
diff-insert-foreground: [tf.colour[foreground]]
diff-invisible-background:
diff-invisible-foreground: [tf.colour[muted-foreground]]
dirty-indicator: [tf.colour[base-tertiary]]
download-background: [tf.interpolate-colours[base-paper],[base-green],[0.6]]
download-foreground: [tf.interpolate-colours[base-ink],[base-green],[0.1]]
dragger-background: [tf.colour[foreground]]
dragger-foreground: [tf.colour[background]]
dropdown-background: [tf.colour[background]]
dropdown-border: [tf.colour[muted-foreground]]
dropdown-tab-background-selected: [tf.colour[background]]
dropdown-tab-background: [tf.interpolate-colours[base-paper],[base-ink],[0.9]]
dropzone-background: [tf.colour[base-secondary]colour-set-alpha[0.7]]
external-link-background-hover: inherit
external-link-background-visited: inherit
external-link-background: inherit
external-link-foreground-hover: inherit
external-link-foreground-visited: [tf.colour[primary]]
external-link-foreground: [tf.colour[primary]]
footnote-target-background: [tf.interpolate-colours[base-paper],[base-ink],[0.2]]
foreground: [tf.colour[base-ink]]
highlight-background: [tf.interpolate-colours[base-paper],[base-yellow],[0.5]]
highlight-foreground: [tf.interpolate-colours[base-yellow],[base-ink],[0.8]]
menubar-background: #5778d8
menubar-foreground: #fff
message-background: [tf.interpolate-colours[base-paper],[base-blue],[0.2]]
message-border: [tf.interpolate-colours[base-blue],[base-ink],[0.5]]
message-foreground: [tf.interpolate-colours[base-blue],[base-ink],[0.8]]
modal-backdrop: [tf.colour[foreground]]
modal-background: [tf.colour[background]]
modal-border: #999999
modal-footer-background: #f5f5f5
modal-footer-border: #dddddd
modal-header-border: #eeeeee
muted-foreground: [tf.interpolate-colours[base-paper],[base-ink],[0.3]]
network-activity-foreground: #448844
notification-background: [tf.colour[base-tertiary]colour-set-oklch:l[0.9]]
notification-border: [tf.colour[base-tertiary]colour-set-oklch:l[0.2]]
page-background: [tf.colour[base-background]]
pre-background: [tf.interpolate-colours[base-paper],[base-tertiary],[0.1]]
pre-border: [tf.interpolate-colours[base-paper],[base-tertiary],[0.6]]
primary: [tf.colour[base-primary]]
select-tag-background:
select-tag-foreground:
selection-background:
selection-foreground:
sidebar-button-foreground: [tf.colour[sidebar-controls-foreground]]
sidebar-controls-foreground-hover: [tf.interpolate-colours[base-ink],[base-background],[0.2]]
sidebar-controls-foreground: [tf.interpolate-colours[base-ink],[base-background],[0.8]]
sidebar-foreground-shadow: inherit
sidebar-foreground: =[tf.colour[base-ink]] =[tf.colour[base-paper]] =[tf.colour[base-background]] +[colour-best-contrast[]]
sidebar-muted-foreground-hover: [tf.colour[sidebar-muted-foreground]colour-set-oklch:l[0.3]]
sidebar-muted-foreground: [tf.interpolate-colours[foreground],[page-background],[0.6]]
sidebar-tab-background-selected: [tf.colour[tab-background-selected]]
sidebar-tab-background: [tf.colour[tab-background]]
sidebar-tab-border-selected: [tf.colour[tab-border-selected]]
sidebar-tab-border: [tf.colour[tab-border]]
sidebar-tab-divider: [tf.colour[tab-divider]]
sidebar-tab-foreground-selected: [tf.colour[tab-foreground-selected]]
sidebar-tab-foreground: [tf.colour[tab-foreground]]
sidebar-tiddler-link-foreground-hover: [tf.colour[sidebar-tiddler-link-foreground]colour-set-oklch:l[0.5]]
sidebar-tiddler-link-foreground: =[tf.colour[base-primary]] =[tf.colour[base-secondary]] =[tf.colour[base-tertiary]] =[tf.colour[base-background]] +[colour-best-contrast[]]
site-title-foreground: [tf.colour[tiddler-title-foreground]]
stability-deprecated: #ff0000
stability-experimental: #c07c00
stability-legacy: #0000ff
stability-stable: #008000
static-alert-foreground: #aaaaaa
tab-background-selected: [tf.colour[background]]
tab-background: [tf.interpolate-colours[base-paper],[base-ink],[0.2]]
tab-border-selected: [tf.colour[muted-foreground]]
tab-border: [tf.colour[muted-foreground]]
tab-divider: [tf.colour[muted-foreground]]
tab-foreground-selected: [tf.colour[tab-foreground]]
tab-foreground: [tf.colour[foreground]]
table-border: [tf.colour[foreground]]
table-footer-background: [tf.interpolate-colours[background],[foreground],[0.2]]
table-header-background: [tf.interpolate-colours[background],[foreground],[0.1]]
tag-background: [tf.interpolate-colours[base-paper],[base-yellow],[0.9]]
tag-foreground: [tf.interpolate-colours[base-yellow],[base-ink],[0.8]]
testcase-accent-level-1: #c1eaff
testcase-accent-level-2: #E3B740
testcase-accent-level-3: #5FD564
tiddler-background: [tf.colour[background]]
tiddler-border: [tf.interpolate-colours[base-paper],[base-background],[0.5]]
tiddler-controls-foreground-hover: [tf.interpolate-colours[background],[foreground],[0.7]]
tiddler-controls-foreground-selected: [tf.interpolate-colours[background],[foreground],[0.9]]
tiddler-controls-foreground: [tf.interpolate-colours[background],[foreground],[0.5]]
tiddler-editor-background: #f8f8f8
tiddler-editor-border-image: #ffffff
tiddler-editor-border: #cccccc
tiddler-editor-fields-even: #e0e8e0
tiddler-editor-fields-odd: #f0f4f0
tiddler-info-background: #f8f8f8
tiddler-info-border: #dddddd
tiddler-info-tab-background: #f8f8f8
tiddler-link-background: [tf.colour[background]]
tiddler-link-foreground: [tf.colour[primary]]
tiddler-subtitle-foreground: [tf.interpolate-colours[background],[foreground],[0.6]]
tiddler-title-foreground: [tf.interpolate-colours[background],[foreground],[0.9]]
toolbar-cancel-button:
toolbar-close-button:
toolbar-delete-button:
toolbar-done-button:
toolbar-edit-button:
toolbar-info-button:
toolbar-new-button:
toolbar-options-button:
toolbar-save-button:
tour-chooser-button-foreground: <<colour very-muted-foreground>>
tour-chooser-button-hover-background: <<colour muted-foreground>>
tour-chooser-button-hover-foreground: <<colour background>>
tour-chooser-button-selected-background: <<colour primary>>
tour-chooser-button-selected-foreground: <<colour background>>
tour-chooser-dropdown-foreground: <<colour very-muted-foreground>>
tour-chooser-item-background: <<colour background>>
tour-chooser-item-border: <<colour muted-foreground>>
tour-chooser-item-foreground: <<colour foreground>>
tour-chooser-item-shadow: <<colour muted-foreground>>
tour-chooser-item-start-background: <<colour download-background>>
tour-chooser-item-start-foreground: <<colour background>>
tour-chooser-item-start-hover-background: <<colour primary>>
tour-chooser-item-start-hover-foreground: <<colour background>>
tour-fullscreen-background: <<colour page-background>>
tour-fullscreen-controls-foreground: <<colour muted-foreground>>
tour-navigation-buttons-back-background: red
tour-navigation-buttons-back-foreground: white
tour-navigation-buttons-hint-background: purple
tour-navigation-buttons-hint-foreground: white
tour-navigation-buttons-hover-background: <<colour foreground>>
tour-navigation-buttons-hover-foreground: <<colour background>>
tour-navigation-buttons-next-background: purple
tour-navigation-buttons-next-foreground: white
tour-overlay-background: #cbfff8
tour-overlay-border: #228877
tour-step-heading-background: none
tour-step-task-background: <<colour download-background>>
tour-step-task-foreground: <<colour download-foreground>>
untagged-background: #999999
very-muted-foreground: #888888
wikilist-background: #e5e5e5
wikilist-button-background: #acacac
wikilist-button-foreground: #000000
wikilist-button-open-hover: green
wikilist-button-open: #4fb82b
wikilist-button-remove-hover: red
wikilist-button-remove: #d85778
wikilist-button-reveal-hover: blue
wikilist-button-reveal: #5778d8
wikilist-droplink-dragover: [tf.colour[base-secondary]colour-set-alpha[0.7]]
wikilist-info: #000000
wikilist-item: #ffffff
wikilist-title-svg: [tf.colour[wikilist-title]]
wikilist-title: #666666
wikilist-toolbar-background: #d3d3d3
wikilist-toolbar-foreground: #888888
wikilist-url: #aaaaaa
@@ -1,25 +0,0 @@
title: $:/palettes/TwentyTwenties/Customisations
\procedure layer-input-actions()
<$action-setfield $tiddler=<<layerTitle>> palette-import={{$:/palette}}/>
\end layer-input-actions
\procedure entry(name,description)
<$text text=<<description>>/>: <$edit-text tiddler=<<layerTitle>> index=<<name>> type="color" tag="input" default={{{ [function[colour],<name>] }}} inputActions=<<layer-input-actions>>/>
\end entry
<$let layerTitle={{{ [function[tf.palette-customisations-layer]] }}}>
<<entry name:"base-paper" description:"Paper">>
<<entry name:"base-background" description:"Page background">>
<<entry name:"base-ink" description:"Ink">>
<<entry name:"base-primary" description:"Primary">>
<<entry name:"base-secondary" description:"Secondary">>
<<entry name:"base-tertiary" description:"Tertiary">>
</$let>
-12
View File
@@ -1,12 +0,0 @@
title: $:/palettes/TwentyTwenties/Dark
name: TwentyTwenties Dark
description: Modern and flexible, Darkish
tags: $:/tags/Palette
type: application/x-tiddler-dictionary
color-scheme: dark
palette-import: $:/palettes/TwentyTwenties
category: 2026
base-paper: #111122
base-background: #f5f0f9
base-ink: #8C8F80
-12
View File
@@ -1,12 +0,0 @@
title: $:/palettes/TwentyTwenties/Green
name: TwentyTwenties (Green)
description: Modern and flexible, Greenish
tags: $:/tags/Palette
type: application/x-tiddler-dictionary
color-scheme: light
palette-import: $:/palettes/TwentyTwenties
category: 2026
base-paper: rgb(188, 255, 161)
base-background: rgb(94, 192, 145)
base-primary: #6e803c
-13
View File
@@ -1,13 +0,0 @@
title: $:/palettes/TwentyTwenties/GreenP3
name: TwentyTwenties (Green P3)
description: Modern and flexible, Greenish and super bright
tags: $:/tags/Palette
type: application/x-tiddler-dictionary
color-scheme: light
palette-import: $:/palettes/TwentyTwenties
category: 2026
base-paper: color(display-p3 0.281 1 0.584 / 1)
base-background: color(display-p3 1 1 0 / 1)
base-primary: color(display-p3 1 0.563 1 / 1)
@@ -5,7 +5,6 @@ type: application/x-tiddler-dictionary
name: Twilight
description: Delightful, soft darkness.
color-scheme: dark
category: Legacy
alert-background: rgb(255, 255, 102)
alert-border: rgb(232, 232, 125)
-1
View File
@@ -4,7 +4,6 @@ description: Pale and unobtrusive
tags: $:/tags/Palette
type: application/x-tiddler-dictionary
color-scheme: light
category: Legacy
alert-background: #ffe476
alert-border: #b99e2f
-12
View File
@@ -1,12 +0,0 @@
title: $:/palettes/VanillaCherry
name: Vanilla Cherry
category: 2026
description: Pale and unobtrusive with a cherry on top
tags: $:/tags/Palette
type: application/x-tiddler-dictionary
color-scheme: light
palette-import: $:/palettes/Vanilla
primary: rgb(224, 32, 86)
menubar-foreground: #fff
menubar-background: <<colour primary>>
@@ -1,7 +0,0 @@
title: $:/palettes/background/contrast-tests
type: application/x-tiddler-dictionary
tags: $:/tags/BackgroundPalette
?background-foreground-contrast: [tf.check-colour-contrast[background],[foreground],[45]]
?alert-contrast: [tf.check-colour-contrast[alert-background],[foreground],[45]]
?code-contrast: [tf.check-colour-contrast[code-background],[code-foreground],[45]]
+4 -4
View File
@@ -1,11 +1,11 @@
title: $:/core/stylesheets/custom-properties
\rules only transcludeinline macrocallinline html transcludeblock filteredtranscludeinline
\rules only transcludeinline macrocallinline html transcludeblock
/* Tiddlywiki's CSS properties */
:root {
<$list filter="[[$:/temp/palette-colours]indexes[]!prefix[?]]">
<$list filter="[[$:/palettes/Vanilla]indexes[]]">
--tpc-<<currentTiddler>>: <$transclude $variable="colour" $mode="inline" name=<<currentTiddler>>/>;
</$list>
@@ -21,10 +21,10 @@ title: $:/core/stylesheets/custom-properties
--tp-story-left: {{$:/themes/tiddlywiki/vanilla/metrics/storyleft}};
--tp-story-top: {{$:/themes/tiddlywiki/vanilla/metrics/storytop}};
--tp-story-right: {{$:/themes/tiddlywiki/vanilla/metrics/storyright}};
--tp-story-width: {{$:/themes/tiddlywiki/vanilla/metrics/storywidth}};
--tp-story-width: {{$:/themes/tiddlywiki/vanilla/metrics/storyrwidth}};
--tp-tiddler-width: {{$:/themes/tiddlywiki/vanilla/metrics/tiddlerwidth}};
--tp-sidebar-breakpoint: {{$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint}};
--tp-sidebar-width: {{$:/themes/tiddlywiki/vanilla/metrics/sidebarwidth}};
--tp-animation-duration: {{{ [{$:/config/AnimationDuration}addsuffix[ms]] }}};
}
}
-3
View File
@@ -1,3 +0,0 @@
title: $:/core/templates/plain-text
<$text text=<<text>>/>
-3
View File
@@ -1,3 +0,0 @@
title: $:/core/templates/rendered-text
<<text>>
+3 -5
View File
@@ -4,15 +4,13 @@ description: create a new journal tiddler
\whitespace trim
\function get-tags() [<textFieldTags>] [<tagsFieldTags>] +[join[ ]]
<$let journalTitle=<<now format={{$:/config/NewJournal/Title}}>>
textFieldTags={{$:/config/NewJournal/Tags}}
tagsFieldTags={{$:/config/NewJournal/Tags!!tags}}
journalText={{$:/config/NewJournal/Text}}
>
<$let journalTitleTemplate={{$:/config/NewJournal/Title}} textFieldTags={{$:/config/NewJournal/Tags}} tagsFieldTags={{$:/config/NewJournal/Tags!!tags}} journalText={{$:/config/NewJournal/Text}}>
<$wikify name="journalTitle" text="<$transclude $variable='now' format=<<journalTitleTemplate>>/>">
<$reveal type="nomatch" state=<<journalTitle>> text="">
<$action-sendmessage $message="tm-new-tiddler" title=<<journalTitle>> tags=<<get-tags>> text={{{ [<journalTitle>get[]] }}}/>
</$reveal>
<$reveal type="match" state=<<journalTitle>> text="">
<$action-sendmessage $message="tm-new-tiddler" title=<<journalTitle>> tags=<<get-tags>> text=<<journalText>>/>
</$reveal>
</$wikify>
</$let>
+1 -1
View File
@@ -6,5 +6,5 @@ caption: {{$:/language/ControlPanel/Appearance/Caption}}
{{$:/language/ControlPanel/Appearance/Hint}}
<div class="tc-control-panel">
<$macrocall $name="tabs" tabsList="[all[shadows+tiddlers]tag[$:/tags/ControlPanel/Appearance]!has[draft.of]]" default="$:/core/ui/ControlPanel/Palette" explicitState="$:/state/tab--1963855381"/>
<$macrocall $name="tabs" tabsList="[all[shadows+tiddlers]tag[$:/tags/ControlPanel/Appearance]!has[draft.of]]" default="$:/core/ui/ControlPanel/Theme" explicitState="$:/state/tab--1963855381"/>
</div>
+17 -1
View File
@@ -2,4 +2,20 @@ title: $:/core/ui/ControlPanel/Palette
tags: $:/tags/ControlPanel/Appearance
caption: {{$:/language/ControlPanel/Palette/Caption}}
{{$:/PaletteManager}}
\define lingo-base() $:/language/ControlPanel/Palette/
{{$:/snippets/paletteswitcher}}
<$reveal type="nomatch" state="$:/state/ShowPaletteEditor" text="yes">
<$button set="$:/state/ShowPaletteEditor" setTo="yes"><<lingo ShowEditor/Caption>></$button>
</$reveal>
<$reveal type="match" state="$:/state/ShowPaletteEditor" text="yes">
<$button set="$:/state/ShowPaletteEditor" setTo="no"><<lingo HideEditor/Caption>></$button>
{{$:/PaletteManager}}
</$reveal>
+3 -3
View File
@@ -108,10 +108,10 @@ tags: $:/tags/EditTemplate
storeTitle=<<newFieldNameInputTiddler>>
searchListState=<<newFieldNameSelectionTiddler>>
>
<div class=`tc-edit-field-add-name-wrapper ${ [<newFieldNameTiddler>get[text]] :intersection[<storyTiddler>fields[]] :then[[tc-edit-field-exists]] }$`>
<div class="tc-edit-field-add-name-wrapper">
<$transclude $variable="keyboard-driven-input"
cancelPopups="yes"
class="tc-edit-texteditor tc-popup-handle"
class=`tc-edit-texteditor tc-popup-handle ${ [<newFieldNameTiddler>get[text]] :intersection[<storyTiddler>fields[]] :then[[tc-edit-field-exists]] }$`
configTiddlerFilter="[[$:/config/EditMode/fieldname-filter]]"
default=""
focus={{{ [{!!draft.of}is[tiddler]then{$:/config/AutoFocusEdit}match[fields]then[true]] :else[{$:/config/AutoFocus}match[fields]then[true]] :else[[false]] }}}
@@ -178,4 +178,4 @@ tags: $:/tags/EditTemplate
</$let>
</$let>
</div>
</$let>
</$let>
+24 -19
View File
@@ -6,25 +6,30 @@ tags: $:/tags/EditTemplate
\procedure lingo-base() $:/language/EditTemplate/
\procedure tag-body-inner(colour,fallbackTarget,colourA,colourB,icon,tagField:"tags")
<$let foregroundColor=<<contrastcolour target=<<colour>> fallbackTarget=<<fallbackTarget>> colourA=<<colourA>> colourB=<<colourB>> >>
backgroundColor=<<colour>>
>
<span class="tc-tag-label tc-tag-list-item tc-small-gap-right"
data-tag-title=<<currentTiddler>>
style=`color:$(foregroundColor)$; fill:$(foregroundColor)$; background-color:$(backgroundColor)$;`
>
<$transclude tiddler=<<icon>>/>
<$view field="title" format="text"/>
<$button class="tc-btn-invisible tc-remove-tag-button"
style.fill=<<foregroundColor>>
<$wikify name="foregroundColor"
text="""<$macrocall $name="contrastcolour"
target=<<colour>>
fallbackTarget=<<fallbackTarget>>
colourA=<<colourA>>
colourB=<<colourB>>/>
"""
>
<$let backgroundColor=<<colour>> >
<span class="tc-tag-label tc-tag-list-item tc-small-gap-right"
data-tag-title=<<currentTiddler>>
style=`color:$(foregroundColor)$; fill:$(foregroundColor)$; background-color:$(backgroundColor)$;`
>
<$action-listops $tiddler=<<saveTiddler>> $field=<<tagField>> $subfilter="-[{!!title}]"/>
<!-- Touch a temp tiddler so that the tag remove animation fires instantly. Otherwise it's delayed by the typing timeout duration -->
<$action-setfield $tiddler="$:/temp/tags-edit-refresh" text=<<currentTiddler>>/>
{{$:/core/images/close-button}}
</$button>
</span>
</$let>
<$transclude tiddler=<<icon>>/>
<$view field="title" format="text"/>
<$button class="tc-btn-invisible tc-remove-tag-button"
style.fill=<<foregroundColor>>
>
<$action-listops $tiddler=<<saveTiddler>> $field=<<tagField>> $subfilter="-[{!!title}]"/>
{{$:/core/images/close-button}}
</$button>
</span>
</$let>
</$wikify>
\end
\procedure tag-body(colour,palette,icon,tagField:"tags")
@@ -43,7 +48,7 @@ tags: $:/tags/EditTemplate
<$list filter="[<currentTiddler>get<tagField>enlist-input[]sort[title]]" storyview="pop">
<$macrocall $name="tag-body"
colour={{{ [<currentTiddler>] :cascade[all[shadows+tiddlers]tag[$:/tags/TiddlerColourFilter]!is[draft]get[text]] }}}
palette="$:/temp/palette-colours"
palette={{$:/palette}}
icon={{{ [<currentTiddler>] :cascade[all[shadows+tiddlers]tag[$:/tags/TiddlerIconFilter]!is[draft]get[text]] }}}
tagField=<<tagField>>
/>
-105
View File
@@ -1,105 +0,0 @@
title: $:/PaletteEditor
\define lingo-base() $:/language/ControlPanel/Palette/Editor/
\define describePaletteColour(colour)
<$transclude tiddler="$:/language/Docs/PaletteColours/$colour$"><$text text="$colour$"/></$transclude>
\end
\define edit-colour-placeholder()
edit $(colourName)$
\end
\define colour-tooltip(showhide) $showhide$ editor for $(newColourName)$
\define resolve-colour(macrocall)
\import $:/core/macros/utils
\whitespace trim
<$wikify name="name" text="""$macrocall$""">
<<name>>
</$wikify>
\end
\define delete-colour-index-actions() <$action-setfield $index=<<colourName>>/>
\define palette-manager-colour-row-segment()
\whitespace trim
<$edit-text index=<<colourName>> tag="input" placeholder=<<edit-colour-placeholder>> default=""/>
<br>
<$edit-text index=<<colourName>> type="color" tag="input" class="tc-palette-manager-colour-input"/>
<$list filter="[<currentTiddler>getindex<colourName>removeprefix[<<]removesuffix[>>]] [<currentTiddler>getindex<colourName>removeprefix[<$]removesuffix[/>]]" variable="ignore">
<$set name="state" value={{{ [[$:/state/palettemanager/]addsuffix<currentTiddler>addsuffix[/]addsuffix<colourName>] }}}>
<$wikify name="newColourName" text="""<$macrocall $name="resolve-colour" macrocall={{{ [<currentTiddler>getindex<colourName>] }}}/>""">
<$reveal state=<<state>> type="nomatch" text="show">
<$button tooltip=<<colour-tooltip show>> aria-label=<<colour-tooltip show>> class="tc-btn-invisible" set=<<state>> setTo="show">{{$:/core/images/down-arrow}}<$text text=<<newColourName>> class="tc-small-gap-left"/></$button><br>
</$reveal>
<$reveal state=<<state>> type="match" text="show">
<$button tooltip=<<colour-tooltip hide>> aria-label=<<colour-tooltip show>> class="tc-btn-invisible" actions="""<$action-deletetiddler $tiddler=<<state>>/>""">{{$:/core/images/up-arrow}}<$text text=<<newColourName>> class="tc-small-gap-left"/></$button><br>
</$reveal>
<$reveal state=<<state>> type="match" text="show">
<$set name="colourName" value=<<newColourName>>>
<br>
<<palette-manager-colour-row-segment>>
<br><br>
</$set>
</$reveal>
</$wikify>
</$set>
</$list>
\end
\define palette-manager-colour-row()
\whitespace trim
<tr>
<td>
<span style="float:right;">
<$button tooltip={{$:/language/ControlPanel/Palette/Editor/Delete/Hint}} aria-label={{$:/language/ControlPanel/Palette/Editor/Delete/Hint}} class="tc-btn-invisible" actions=<<delete-colour-index-actions>>>
{{$:/core/images/delete-button}}</$button>
</span>
''<$macrocall $name="describePaletteColour" colour=<<colourName>>/>''<br/>
<$macrocall $name="colourName" $output="text/plain"/>
<%if [<layerTitle>getindex<colourName>] %>
<br/><em><<lingo Customised/Entry>></em>
<%endif%>
</td>
<td>
<<palette-manager-colour-row-segment>>
</td>
</tr>
\end
\define palette-manager-table()
\whitespace trim
<table>
<tbody>
<$set name="colorList" filter="[{$:/state/palettemanager/showexternal}match[yes]]"
value="[all[shadows+tiddlers]tag[$:/tags/Palette]indexes[]]" emptyValue="[<currentTiddler>indexes[]]">
<$list filter=<<colorList>> variable="colourName"> <<palette-manager-colour-row>> </$list>
</$set>
</tbody>
</table>
\end
\whitespace trim
<$set name="currentTiddler" value={{$:/palette}}>
<$let layerTitle={{{ [function[tf.palette-customisations-layer]] }}}>
<<lingo Prompt>>&#32;<$link to={{$:/palette}}><$macrocall $name="currentTiddler" $output="text/plain"/></$link>
<$list filter="[function[tf.palette-customisations-layer]is[tiddler]]" variable="listItem">
<<lingo Customised/Prompt>>
&#32;
<$button actions="""<$action-deletetiddler $tiddler=<<layerTitle>>/>""">{{$:/language/ControlPanel/Palette/Customisations/Reset/Caption}}</$button>
</$list>
<$list filter="[all[current]is[shadow]is[tiddler]]" variable="listItem">
<<lingo Prompt/Modified>>
&#32;
<$button message="tm-delete-tiddler" param={{$:/palette}}><<lingo Reset/Caption>></$button>
</$list>
<$list filter="[all[current]is[shadow]!is[tiddler]]" variable="listItem">
<<lingo Clone/Prompt>>
</$list>
<$button message="tm-new-tiddler" param={{$:/palette}}><<lingo Clone/Caption>></$button>
<$checkbox tiddler="$:/state/palettemanager/showexternal" field="text" checked="yes" unchecked="no"><span class="tc-small-gap-left"><<lingo Names/External/Show>></span></$checkbox>
<<palette-manager-table>>
</$let>
+87 -43
View File
@@ -1,50 +1,94 @@
title: $:/PaletteManager
\define lingo-base() $:/language/ControlPanel/Palette/
\define lingo-base() $:/language/ControlPanel/Palette/Editor/
\define describePaletteColour(colour)
<$transclude tiddler="$:/language/Docs/PaletteColours/$colour$"><$text text="$colour$"/></$transclude>
\end
\define edit-colour-placeholder()
edit $(colourName)$
\end
\define colour-tooltip(showhide) $showhide$ editor for $(newColourName)$
<!-- Used by the language string Customisations/Prompt -->
\procedure palette-link()
<$tiddler tiddler={{$:/palette}}>
<$link to={{!!title}}>
<$view field="name" format="text">
<$view field="title" format="text"/>
</$view>
</$link>
</$tiddler>
\end palette-link
<$transclude $tiddler="$:/snippets/paletteswitcher" thumbnails="yes"/>
{{$:/snippets/palettetests}}
<$let
resolvedPalette={{{ [{$:/palette}is[tiddler]] [{$:/palette}is[shadow]] :else[[$:/palettes/Vanilla]] }}}
paletteCustomisations={{{ [<resolvedPalette>get[customisations]] :else[[$:/temp/palette-consolidated]get[customisations]] }}}
layerTitle={{{ [function[tf.palette-customisations-layer]] }}}
>
<%if [<paletteCustomisations>!match[]] %>
<div>
<<lingo Customisations/Prompt>>
<$transclude $tiddler=<<paletteCustomisations>> $mode="block"/>
</div>
<%endif%>
<%if [<layerTitle>is[tiddler]] %>
<div>
<$button actions="""<$action-deletetiddler $tiddler=<<layerTitle>>/>"""><<lingo Customisations/Reset/Caption>></$button>
</div>
<%endif%>
</$let>
<$reveal type="nomatch" state="$:/state/ShowPaletteEditor" text="yes">
<$button set="$:/state/ShowPaletteEditor" setTo="yes"><<lingo ShowEditor/Caption>></$button>
\define resolve-colour(macrocall)
\import $:/core/macros/utils
\whitespace trim
<$wikify name="name" text="""$macrocall$""">
<<name>>
</$wikify>
\end
\define delete-colour-index-actions() <$action-setfield $index=<<colourName>>/>
\define palette-manager-colour-row-segment()
\whitespace trim
<$edit-text index=<<colourName>> tag="input" placeholder=<<edit-colour-placeholder>> default=""/>
<br>
<$edit-text index=<<colourName>> type="color" tag="input" class="tc-palette-manager-colour-input"/>
<$list filter="[<currentTiddler>getindex<colourName>removeprefix[<<]removesuffix[>>]] [<currentTiddler>getindex<colourName>removeprefix[<$]removesuffix[/>]]" variable="ignore">
<$set name="state" value={{{ [[$:/state/palettemanager/]addsuffix<currentTiddler>addsuffix[/]addsuffix<colourName>] }}}>
<$wikify name="newColourName" text="""<$macrocall $name="resolve-colour" macrocall={{{ [<currentTiddler>getindex<colourName>] }}}/>""">
<$reveal state=<<state>> type="nomatch" text="show">
<$button tooltip=<<colour-tooltip show>> aria-label=<<colour-tooltip show>> class="tc-btn-invisible" set=<<state>> setTo="show">{{$:/core/images/down-arrow}}<$text text=<<newColourName>> class="tc-small-gap-left"/></$button><br>
</$reveal>
<$reveal type="match" state="$:/state/ShowPaletteEditor" text="yes">
<$button set="$:/state/ShowPaletteEditor" setTo="no"><<lingo HideEditor/Caption>></$button>
{{$:/PaletteEditor}}
<$reveal state=<<state>> type="match" text="show">
<$button tooltip=<<colour-tooltip hide>> aria-label=<<colour-tooltip show>> class="tc-btn-invisible" actions="""<$action-deletetiddler $tiddler=<<state>>/>""">{{$:/core/images/up-arrow}}<$text text=<<newColourName>> class="tc-small-gap-left"/></$button><br>
</$reveal>
<$reveal state=<<state>> type="match" text="show">
<$set name="colourName" value=<<newColourName>>>
<br>
<<palette-manager-colour-row-segment>>
<br><br>
</$set>
</$reveal>
</$wikify>
</$set>
</$list>
\end
\define palette-manager-colour-row()
\whitespace trim
<tr>
<td>
<span style="float:right;">
<$button tooltip={{$:/language/ControlPanel/Palette/Editor/Delete/Hint}} aria-label={{$:/language/ControlPanel/Palette/Editor/Delete/Hint}} class="tc-btn-invisible" actions=<<delete-colour-index-actions>>>
{{$:/core/images/delete-button}}</$button>
</span>
''<$macrocall $name="describePaletteColour" colour=<<colourName>>/>''<br/>
<$macrocall $name="colourName" $output="text/plain"/>
</td>
<td>
<<palette-manager-colour-row-segment>>
</td>
</tr>
\end
\define palette-manager-table()
\whitespace trim
<table>
<tbody>
<$set name="colorList" filter="[{$:/state/palettemanager/showexternal}match[yes]]"
value="[all[shadows+tiddlers]tag[$:/tags/Palette]indexes[]]" emptyValue="[<currentTiddler>indexes[]]">
<$list filter=<<colorList>> variable="colourName"> <<palette-manager-colour-row>> </$list>
</$set>
</tbody>
</table>
\end
\whitespace trim
<$set name="currentTiddler" value={{$:/palette}}>
<<lingo Prompt>>&#32;<$link to={{$:/palette}}><$macrocall $name="currentTiddler" $output="text/plain"/></$link>
<$list filter="[all[current]is[shadow]is[tiddler]]" variable="listItem">
<<lingo Prompt/Modified>>
&#32;
<$button message="tm-delete-tiddler" param={{$:/palette}}><<lingo Reset/Caption>></$button>
</$list>
<$list filter="[all[current]is[shadow]!is[tiddler]]" variable="listItem">
<<lingo Clone/Prompt>>
</$list>
<$button message="tm-new-tiddler" param={{$:/palette}}><<lingo Clone/Caption>></$button>
<$checkbox tiddler="$:/state/palettemanager/showexternal" field="text" checked="yes" unchecked="no"><span class="tc-small-gap-left"><<lingo Names/External/Show>></span></$checkbox>
<<palette-manager-table>>
-19
View File
@@ -1,19 +0,0 @@
title: $:/core/ui/Palettes/Preview/Alert
tags: $:/tags/Preview/Page
\whitespace trim
<div class="tc-palette-preview-thumbnail-alert" style.background-color=<<colour alert-background>>>
<div class="tc-palette-preview-thumbnail-alert-border" style.border-color=<<colour alert-border>>>
<div style.color=<<colour foreground>>>
<div class="tc-palette-preview-thumbnail-alert-subtitle" style.color=<<colour alert-muted-foreground>>>
Lorem Ipsum
<div class="tc-palette-preview-thumbnail-alert-highlight" style.color=<<colour alert-highlight>>>
(Count: 1)
</div>
</div>
<div class="tc-palette-preview-thumbnail-alert-body">
Lorem Ipsum Dolor Sit Amet Consectetur Adipiscing Elit Sed Do Eiusmod Tempor Incididunt.
</div>
</div>
</div>
</div>
-55
View File
@@ -1,55 +0,0 @@
title: $:/core/ui/Palettes/Preview/Helpers
tags: $:/tags/Preview/Helpers
\whitespace trim
\procedure palette-preview-component-list(tag)
<$list filter="[all[shadows+tiddlers]tag<tag>!has[draft.of]]" variable="componentTitle">
<$transclude $tiddler=<<componentTitle>> title=<<title>>/>
</$list>
\end palette-preview-component-list
\procedure tab-set(tabTitles,colourPrefix:"")
<div class="tc-palette-preview-thumbnail-tab-set">
<div class="tc-palette-preview-thumbnail-tab-buttons">
<$list filter="[enlist<tabTitles>]" variable="tabTitle" counter="tabIndex">
<%if [<tabIndex>match[1]] %>
<span
class="tc-palette-preview-thumbnail-tab-button"
style.border-color={{{ [<colourPrefix>addsuffix[tab-border-selected]] :map[function[colour],<currentTiddler>] }}}
style.color={{{ [<colourPrefix>addsuffix[tab-foreground-selected]] :map[function[colour],<currentTiddler>] }}}
style.background-color={{{ [<colourPrefix>addsuffix[tab-background-selected]] :map[function[colour],<currentTiddler>] }}}
>
<$text text=<<tabTitle>>/>
</span>
<%else%>
<span
class="tc-palette-preview-thumbnail-tab-button"
style.border-color={{{ [<colourPrefix>addsuffix[tab-border]] :map[function[colour],<currentTiddler>] }}}
style.color={{{ [<colourPrefix>addsuffix[tab-foreground]] :map[function[colour],<currentTiddler>] }}}
style.background-color={{{ [<colourPrefix>addsuffix[tab-background]] :map[function[colour],<currentTiddler>] }}}
>
<$text text=<<tabTitle>>/>
</span>
<%endif%>
</$list>
</div>
<div
class="tc-palette-preview-thumbnail-tab-divider"
style.border-color={{{ [<colourPrefix>addsuffix[tab-divider]] :map[function[colour],<currentTiddler>] }}}
>
</div>
</div>
\end tab-set
\procedure link(text)
<span class="tc-palette-preview-thumbnail-tiddler-link" style.color=<<colour primary>>>
<$text text=<<text>>/>
</span>
\end link
\procedure sidebar-link(text)
<span class="tc-palette-preview-thumbnail-tiddler-link" style.color=<<colour sidebar-tiddler-link-foreground>>>
<$text text=<<text>>/>
</span>
\end sidebar-link
-11
View File
@@ -1,11 +0,0 @@
title: $:/core/ui/Palettes/Preview/Notification
tags: $:/tags/Preview/PageOptional
\whitespace trim
<div class="tc-palette-preview-thumbnail-notification" style.background-color=<<colour notification-background>>>
<div class="tc-palette-preview-thumbnail-notification-border" style.border-color=<<colour notification-border>>>
<div class="tc-palette-preview-thumbnail-notification-body" style.color=<<colour foreground>>>
Lorem Ipsum Dolor Sit Amet Consectetur
</div>
</div>
</div>
@@ -1,8 +0,0 @@
title: $:/core/ui/Palettes/Preview/Sidebar/Search
tags: $:/tags/Preview/SideBar
\whitespace trim
<div class="tc-palette-preview-thumbnail-sidebar-search" style.background-color=<<colour background>>>
<div class="tc-palette-preview-thumbnail-sidebar-search-box">
</div>
</div>
@@ -1,7 +0,0 @@
title: $:/core/ui/Palettes/Preview/Sidebar/Subtitle
tags: $:/tags/Preview/SideBar
\whitespace trim
<div class="tc-palette-preview-thumbnail-sidebar-subtitle">
a non-linear personal web notebook
</div>
-18
View File
@@ -1,18 +0,0 @@
title: $:/core/ui/Palettes/Preview/Sidebar/Tabs
tags: $:/tags/Preview/SideBar
\whitespace trim
\procedure recent-links()
HelloThere Community Portal GettingStarted Development Download Filters Palettes Plugins Macros Templates Themes Stylesheets SystemTiddlers
\end recent-links
<<tab-set "Magna Placerat Ligula Imperdiet" "sidebar-">>
<div class="tc-palette-preview-thumbnail-sidebar-list">
<$list filter="[enlist<recent-links>]">
<div>
<$transclude $variable="sidebar-link" text=<<currentTiddler>>/>
</div>
</$list>
</div>
@@ -1,7 +0,0 @@
title: $:/core/ui/Palettes/Preview/Sidebar/Title
tags: $:/tags/Preview/SideBar
\whitespace trim
<div class="tc-palette-preview-thumbnail-sidebar-title" style.color=<<colour site-title-foreground>>>
~TiddlyWiki
</div>
-7
View File
@@ -1,7 +0,0 @@
title: $:/core/ui/Palettes/Preview/SideBar
tags: $:/tags/Preview/Page
\whitespace trim
<div class="tc-palette-preview-thumbnail-sidebar" style.color=<<colour sidebar-foreground>>>
<<palette-preview-component-list "$:/tags/Preview/SideBar">>
</div>
-9
View File
@@ -1,9 +0,0 @@
title: $:/core/ui/Palettes/Preview/Story
tags: $:/tags/Preview/Page
\whitespace trim
<div class="tc-palette-preview-thumbnail-story">
<$list filter="HelloThere GettingStarted" variable="title">
<<palette-preview-component-list "$:/tags/Preview/Story">>
</$list>
</div>
-10
View File
@@ -1,10 +0,0 @@
title: $:/core/ui/Palettes/Preview/Tiddler
tags: $:/tags/Preview/Story
\parameters (title)
\whitespace trim
<div class="tc-palette-preview-thumbnail-tiddler-border" style.border-color=<<colour tiddler-border>>>
<div class="tc-palette-preview-thumbnail-tiddler" style.background-color=<<colour tiddler-background>>>
<<palette-preview-component-list "$:/tags/Preview/Tiddler">>
</div>
</div>
-15
View File
@@ -1,15 +0,0 @@
title: $:/core/ui/Palettes/Preview/Tiddler/Body
tags: $:/tags/Preview/Tiddler
\whitespace trim
<div class="tc-palette-preview-thumbnail-tiddler-body" style.color=<<colour foreground>>>
<%if [<title>match[HelloThere]] %>
Lorem ipsum dolor sit amet, <<link "consectetur adipiscing elit">>. Cras non arcu ultricies, egestas odio tempus, vestibulum ipsum. Praesent diam lorem, elementum in venenatis eget, tincidunt quis lacus. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Etiam efficitur velit tortor, sit amet tristique felis viverra sit amet. <<link "Nullam posuere facilisis purus sed">> consectetur. Integer vel elit euismod, posuere ligula et, dictum tellus. Donec in odio diam. Sed metus magna, placerat at ligula et, imperdiet sagittis ex.
<%else%>
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
<<tab-set "Sed Metus Magna Placerat Ligula Imperdiet">>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras non arcu ultricies, egestas odio tempus, vestibulum ipsum. Praesent diam lorem, elementum in venenatis eget, tincidunt quis lacus. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.
<%endif%>
</div>
@@ -1,14 +0,0 @@
title: $:/core/ui/Palettes/Preview/Tiddler/Header
tags: $:/tags/Preview/Tiddler
\whitespace trim
<div class="tc-palette-preview-thumbnail-tiddler-header">
<div class="tc-palette-preview-thumbnail-tiddler-title" style.color=<<colour tiddler-title-foreground>>>
<$text text=<<title>>/>
</div>
<div class="tc-palette-preview-thumbnail-tiddler-toolbar" style.fill=<<colour tiddler-controls-foreground>>>
{{$:/core/images/down-arrow}}
{{$:/core/images/edit-button}}
{{$:/core/images/close-button}}
</div>
</div>
@@ -1,7 +0,0 @@
title: $:/core/ui/Palettes/Preview/Tiddler/Subtitle
tags: $:/tags/Preview/Tiddler
\whitespace trim
<div class="tc-palette-preview-thumbnail-tiddler-subtitle" style.color=<<colour tiddler-subtitle-foreground>>>
Motovun Jack
</div>
@@ -1,11 +0,0 @@
title: $:/core/ui/Palettes/ViewTemplateBody
<div style.width="220px">
{{||$:/snippets/currpalettepreview}}
</div>
''<$view field="name" format="text"/>''
<br>
<$view field="description" format="text"/>
+4 -2
View File
@@ -16,13 +16,15 @@ title: $:/core/ui/TagPickerTagTemplate
<$set name="backgroundColor"
value={{{ [<currentTiddler>] :cascade[all[shadows+tiddlers]tag[$:/tags/TiddlerColourFilter]!is[draft]get[text]] }}}
>
<$let foregroundColor=<<contrastcolour target=<<backgroundColor>> fallbackTarget=<<fallbackTarget>> colourA=<<colourA>> colourB=<<colourB>> >> >
<$wikify name="foregroundColor"
text="""<$macrocall $name="contrastcolour" target=<<backgroundColor>> fallbackTarget=<<fallbackTarget>> colourA=<<colourA>> colourB=<<colourB>>/>"""
>
<span class="tc-tag-label tc-btn-invisible"
style=<<tag-pill-styles>>
data-tag-title=<<currentTiddler>>
>
{{||$:/core/ui/TiddlerIcon}}<$view field="title" format="text"/>
</span>
</$let>
</$wikify>
</$set>
</$button>
+1
View File
@@ -7,6 +7,7 @@ title: $:/core/ui/TagTemplate
tag=<<currentTiddler>>
icon={{{ [<currentTiddler>] :cascade[all[shadows+tiddlers]tag[$:/tags/TiddlerIconFilter]!is[draft]get[text]] }}}
colour={{{ [<currentTiddler>] :cascade[all[shadows+tiddlers]tag[$:/tags/TiddlerColourFilter]!is[draft]get[text]] }}}
palette={{$:/palette}}
element-tag="$button"
element-attributes="""popup=<<qualify "$:/state/popup/tag">> dragFilter="[subfilter{$:/core/config/TagPillDragFilter}]" tag='span'"""
/>
+3 -4
View File
@@ -6,6 +6,7 @@ description: {{$:/language/Buttons/NewJournalHere/Hint}}
\whitespace trim
\procedure journalButton()
<$button tooltip={{$:/language/Buttons/NewJournalHere/Hint}} aria-label={{$:/language/Buttons/NewJournalHere/Caption}} class=<<tv-config-toolbar-class>>>
<$wikify name="journalTitle" text="""<$transclude $variable="now" format=<<journalTitleTemplate>>/>""">
<$action-sendmessage $message="tm-new-tiddler" title=<<journalTitle>> tags=`[[$(currentTiddlerTag)$]] $(journalTags)$`/>
<%if [<tv-config-toolbar-icons>match[yes]] %>
{{$:/core/images/new-journal-button}}
@@ -15,11 +16,9 @@ description: {{$:/language/Buttons/NewJournalHere/Hint}}
<$text text={{$:/language/Buttons/NewJournalHere/Caption}}/>
</span>
<%endif%>
</$wikify>
</$button>
\end
<$let journalTitle=<<now format={{$:/config/NewJournal/Title}}>>
journalTags={{$:/config/NewJournal/Tags}}
currentTiddlerTag=<<currentTiddler>>
>
<$let journalTitleTemplate={{$:/config/NewJournal/Title}} journalTags={{$:/config/NewJournal/Tags}} currentTiddlerTag=<<currentTiddler>>>
<<journalButton>>
</$let>

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