Optimizes filterrunprefixes & filters using ES2017 (#9943)

* refactor: use ES2017 to optimize filter run prefixes

* chore: eslint

* chore: eslint

* fix: added missing file

* refactor: prefix, suffix and subfilter operators

* refactor: further improvements using new String methods

* docs: added changenote

* chore: renamed docs tiddler

* chore: renamed docs tiddler
This commit is contained in:
Saq Imtiaz
2026-07-28 12:32:48 +02:00
committed by GitHub
parent 94b046b8cb
commit 45d2ca948a
7 changed files with 66 additions and 76 deletions
@@ -13,14 +13,15 @@ Export our filter prefix function
exports.intersection = function(operationSubFunction) {
return function(results,source,widget) {
if(results.length !== 0) {
var secondRunResults = operationSubFunction(source,widget);
var firstRunResults = results.toArray();
const secondRunResults = operationSubFunction(source,widget),
secondRunSet = new Set(secondRunResults),
firstRunResults = results.toArray();
results.clear();
$tw.utils.each(firstRunResults,function(title) {
if(secondRunResults.indexOf(title) !== -1) {
firstRunResults.forEach((title) => {
if(secondRunSet.has(title)) {
results.push(title);
}
});
}
};
};
};
+15 -20
View File
@@ -13,33 +13,28 @@ Export our filter prefix function
exports.sort = function(operationSubFunction,options) {
return function(results,source,widget) {
if(results.length > 0) {
var suffixes = options.suffixes,
const suffixes = options.suffixes,
sortType = (suffixes[0] && suffixes[0][0]) ? suffixes[0][0] : "string",
invert = suffixes[1] ? (suffixes[1].indexOf("reverse") !== -1) : false,
isCaseSensitive = suffixes[1] ? (suffixes[1].indexOf("casesensitive") !== -1) : false,
invert = suffixes[1] ? suffixes[1].includes("reverse") : false,
isCaseSensitive = suffixes[1] ? suffixes[1].includes("casesensitive") : false,
inputTitles = results.toArray(),
sortKeys = [],
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:""})
}));
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:""})
})
);
sortKeys.push(key[0] || "");
});
results.clear();
// Prepare an array of indexes to sort
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) {
let indexes = Array.from(inputTitles.keys());
indexes.sort((a,b) => compareFn(sortKeys[a],sortKeys[b]));
indexes.forEach((index) => {
results.push(inputTitles[index]);
});
}
+3 -4
View File
@@ -15,7 +15,7 @@ Export our filter function
exports.prefix = function(source,operator,options) {
const results = [],
suffixes = (operator.suffixes || [])[0] || [],
caseInsensitive = suffixes.indexOf("caseinsensitive") !== -1,
caseInsensitive = suffixes.includes("caseinsensitive"),
negate = operator.prefix === "!";
const operand = caseInsensitive ?
@@ -23,9 +23,8 @@ exports.prefix = function(source,operator,options) {
operator.operand;
source((tiddler,title) => {
const value = caseInsensitive ? title.toLowerCase() : title;
const matches = value.startsWith(operand);
const value = caseInsensitive ? title.toLowerCase() : title,
matches = value.startsWith(operand);
if(negate ? !matches : matches) {
results.push(title);
}
+7 -12
View File
@@ -14,13 +14,13 @@ Export our filter function
*/
exports.sortsub = function(source,operator,options) {
// Compile the subfilter
var filterFn = options.wiki.compileFilter(operator.operand);
let filterFn = options.wiki.compileFilter(operator.operand);
// Collect the input titles and the corresponding sort keys
var inputTitles = [],
let inputTitles = [],
sortKeys = [];
source(function(tiddler,title) {
inputTitles.push(title);
var r = filterFn.call(options.wiki,function(iterator) {
let r = filterFn.call(options.wiki,function(iterator) {
iterator(options.wiki.getTiddler(title),title);
},options.widget.makeFakeWidgetWithVariables({
"currentTiddler": "" + title,
@@ -29,17 +29,12 @@ 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
var indexes = new Array(inputTitles.length);
for(var t=0; t<inputTitles.length; t++) {
indexes[t] = t;
}
let indexes = Array.from(inputTitles.keys());
// Sort the indexes
var compareFn = $tw.utils.makeCompareFunction(operator.suffix,{defaultType: "string",invert: operator.prefix === "!"});
indexes = indexes.sort(function(a,b) {
return compareFn(sortKeys[a],sortKeys[b]);
});
let compareFn = $tw.utils.makeCompareFunction(operator.suffix,{defaultType: "string",invert: operator.prefix === "!"});
indexes = indexes.sort((a,b) => compareFn(sortKeys[a],sortKeys[b]));
// Make the results array in order
var results = [];
let results = [];
$tw.utils.each(indexes,function(index) {
results.push(inputTitles[index]);
});
+5 -4
View File
@@ -13,11 +13,12 @@ Filter operator returning its operand evaluated as a filter
Export our filter function
*/
exports.subfilter = function(source,operator,options) {
var list = options.wiki.filterTiddlers(operator.operand,options.widget,source);
const list = options.wiki.filterTiddlers(operator.operand,options.widget,source);
if(operator.prefix === "!") {
var results = [];
source(function(tiddler,title) {
if(list.indexOf(title) === -1) {
const results = [],
listSet = new Set(list);
source((tiddler,title) => {
if(!listSet.has(title)) {
results.push(title);
}
});
+17 -31
View File
@@ -13,41 +13,27 @@ Filter operator for checking if a title ends with a suffix
Export our filter function
*/
exports.suffix = function(source,operator,options) {
var results = [],
const results = [],
suffixes = (operator.suffixes || [])[0] || [];
if(!operator.operand) {
source(function(tiddler,title) {
source((tiddler,title) => {
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;
}
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);
}
});
return results;
};
@@ -0,0 +1,13 @@
change-category: filters
change-type: enhancement
created: 20260726124618748
description: Optimizes filterrun prefixes and select filters using modern JavaScript.
github-contributors: saqimtiaz
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/issues/9943
modified: 20260726130207664
release: 5.5.0
tags: $:/tags/ChangeNote
title: $:/changenotes/5.5.0/#9943
type: text/vnd.tiddlywiki
* The `intersection` and `sort` filterrun prefixes, and the `prefix`, `sortsub`, `subfilter` and `suffix` operators have been optimized using more modern JavaScript (ES2017).