mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2024-12-27 18:40:28 +00:00
New insertafter filter operator (#6771)
* Implement insertafter operator (like insertbefore) Currently, the behavior of insertafter if the target is not found is to append the inserted tiddler to the end of the list, like insertbefore does. In the next commit, we'll add a suffix to customize what both insertafter and insertbefore do when the target is not found. * Add failing tests for insertafter suffixes Also includes tests for insertbefore suffixes (start/end), since we'll be implementing both of those at the same time. * Add start/end suffixes for insertafter/before The tests that exercise the start/end suffixes now pass.
This commit is contained in:
parent
4cd3c065e7
commit
18d8173dcc
46
core/modules/filters/insertafter.js
Normal file
46
core/modules/filters/insertafter.js
Normal file
@ -0,0 +1,46 @@
|
||||
/*\
|
||||
title: $:/core/modules/filters/insertafter.js
|
||||
type: application/javascript
|
||||
module-type: filteroperator
|
||||
|
||||
Insert an item after another item in a list
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
/*
|
||||
Order a list
|
||||
*/
|
||||
exports.insertafter = function(source,operator,options) {
|
||||
var results = [];
|
||||
source(function(tiddler,title) {
|
||||
results.push(title);
|
||||
});
|
||||
var target = operator.operands[1] || (options.widget && options.widget.getVariable(operator.suffix || "currentTiddler"));
|
||||
if(target !== operator.operand) {
|
||||
// Remove the entry from the list if it is present
|
||||
var pos = results.indexOf(operator.operand);
|
||||
if(pos !== -1) {
|
||||
results.splice(pos,1);
|
||||
}
|
||||
// Insert the entry after the target marker
|
||||
pos = results.indexOf(target);
|
||||
if(pos !== -1) {
|
||||
results.splice(pos+1,0,operator.operand);
|
||||
} else {
|
||||
var suffix = operator.operands.length > 1 ? operator.suffix : "";
|
||||
if(suffix === "start") {
|
||||
results.splice(0,0,operator.operand);
|
||||
} else {
|
||||
results.push(operator.operand);
|
||||
}
|
||||
}
|
||||
}
|
||||
return results;
|
||||
};
|
||||
|
||||
})();
|
@ -32,7 +32,12 @@ exports.insertbefore = function(source,operator,options) {
|
||||
if(pos !== -1) {
|
||||
results.splice(pos,0,operator.operand);
|
||||
} else {
|
||||
results.push(operator.operand);
|
||||
var suffix = operator.operands.length > 1 ? operator.suffix : "";
|
||||
if(suffix == "start") {
|
||||
results.splice(0,0,operator.operand);
|
||||
} else {
|
||||
results.push(operator.operand);
|
||||
}
|
||||
}
|
||||
}
|
||||
return results;
|
||||
|
@ -747,7 +747,46 @@ Tests the filtering mechanism.
|
||||
|
||||
expect(wiki.filterTiddlers("a [[b c]] +[append{TiddlerSix!!filter}]").join(",")).toBe("a,b c,one,a a,[subfilter{hasList!!list}]");
|
||||
});
|
||||
|
||||
|
||||
it("should handle the insertafter operator", function() {
|
||||
var widget = require("$:/core/modules/widgets/widget.js");
|
||||
var rootWidget = new widget.widget({ type:"widget", children:[ {type:"widget", children:[]} ] },
|
||||
{ wiki:wiki, document:$tw.document});
|
||||
rootWidget.makeChildWidgets();
|
||||
var anchorWidget = rootWidget.children[0];
|
||||
rootWidget.setVariable("myVar","c");
|
||||
rootWidget.setVariable("tidTitle","e");
|
||||
rootWidget.setVariable("tidList","one tid with spaces");
|
||||
|
||||
// Position title specified as suffix.
|
||||
expect(wiki.filterTiddlers("a b c d e f +[insertafter:myVar[f]]",anchorWidget).join(",")).toBe("a,b,c,f,d,e");
|
||||
expect(wiki.filterTiddlers("a b c d e f +[insertafter:myVar<tidTitle>]",anchorWidget).join(",")).toBe("a,b,c,e,d,f");
|
||||
expect(wiki.filterTiddlers("a b c d e f +[insertafter:myVar[gg gg]]",anchorWidget).join(",")).toBe("a,b,c,gg gg,d,e,f");
|
||||
expect(wiki.filterTiddlers("a b c d e +[insertafter:myVar<tidList>]",anchorWidget).join(",")).toBe("a,b,c,one tid with spaces,d,e");
|
||||
expect(wiki.filterTiddlers("a b c d e f +[insertafter:tidTitle{TiddlerOne!!tags}]",anchorWidget).join(",")).toBe("a,b,c,d,e,one,f");
|
||||
|
||||
// Position title specified as parameter.
|
||||
expect(wiki.filterTiddlers("a b c d e +[insertafter[f],[a]]",anchorWidget).join(",")).toBe("a,f,b,c,d,e");
|
||||
expect(wiki.filterTiddlers("a b c d e +[insertafter[f],<myVar>]",anchorWidget).join(",")).toBe("a,b,c,f,d,e");
|
||||
|
||||
// Parameter takes precedence over suffix.
|
||||
expect(wiki.filterTiddlers("a b c d e +[insertafter:myVar[f],[a]]",anchorWidget).join(",")).toBe("a,f,b,c,d,e");
|
||||
|
||||
// No position title.
|
||||
expect(wiki.filterTiddlers("a b c [[with space]] +[insertafter[b]]").join(",")).toBe("a,c,with space,b");
|
||||
|
||||
// Position title does not exist, and no suffix given.
|
||||
expect(wiki.filterTiddlers("a b c d e +[insertafter:foo[b]]").join(",")).toBe("a,c,d,e,b");
|
||||
expect(wiki.filterTiddlers("a b c d e +[insertafter[b],[foo]]").join(",")).toBe("a,c,d,e,b");
|
||||
expect(wiki.filterTiddlers("a b c d e +[insertafter[b],<foo>]").join(",")).toBe("a,c,d,e,b");
|
||||
|
||||
// Position title does not exist, but "start" or "end" given as suffix
|
||||
expect(wiki.filterTiddlers("a b c d e +[insertafter:start[b],[foo]]").join(",")).toBe("b,a,c,d,e");
|
||||
expect(wiki.filterTiddlers("a b c d e +[insertafter:start[b],<foo>]").join(",")).toBe("b,a,c,d,e");
|
||||
expect(wiki.filterTiddlers("a b c d e +[insertafter:end[b],[foo]]").join(",")).toBe("a,c,d,e,b");
|
||||
expect(wiki.filterTiddlers("a b c d e +[insertafter:end[b],<foo>]").join(",")).toBe("a,c,d,e,b");
|
||||
});
|
||||
|
||||
it("should handle the insertbefore operator", function() {
|
||||
var widget = require("$:/core/modules/widgets/widget.js");
|
||||
var rootWidget = new widget.widget({ type:"widget", children:[ {type:"widget", children:[]} ] },
|
||||
@ -775,10 +814,16 @@ Tests the filtering mechanism.
|
||||
// No position title.
|
||||
expect(wiki.filterTiddlers("a b c [[with space]] +[insertbefore[b]]").join(",")).toBe("a,c,with space,b");
|
||||
|
||||
// Position title does not exist.
|
||||
// Position title does not exist, and no suffix given.
|
||||
expect(wiki.filterTiddlers("a b c d e +[insertbefore:foo[b]]").join(",")).toBe("a,c,d,e,b");
|
||||
expect(wiki.filterTiddlers("a b c d e +[insertbefore[b],[foo]]").join(",")).toBe("a,c,d,e,b");
|
||||
expect(wiki.filterTiddlers("a b c d e +[insertbefore[b],<foo>]").join(",")).toBe("a,c,d,e,b");
|
||||
|
||||
// Position title does not exist, but "start" or "end" given as suffix
|
||||
expect(wiki.filterTiddlers("a b c d e +[insertbefore:start[b],[foo]]").join(",")).toBe("b,a,c,d,e");
|
||||
expect(wiki.filterTiddlers("a b c d e +[insertbefore:start[b],<foo>]").join(",")).toBe("b,a,c,d,e");
|
||||
expect(wiki.filterTiddlers("a b c d e +[insertbefore:end[b],[foo]]").join(",")).toBe("a,c,d,e,b");
|
||||
expect(wiki.filterTiddlers("a b c d e +[insertbefore:end[b],<foo>]").join(",")).toBe("a,c,d,e,b");
|
||||
});
|
||||
|
||||
it("should handle the move operator", function() {
|
||||
|
@ -0,0 +1,28 @@
|
||||
created: 20220223004441865
|
||||
modified: 20220223004441865
|
||||
tags: [[Operator Examples]] [[insertafter Operator]]
|
||||
title: insertafter Operator (Examples)
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
\define after-title() Friday
|
||||
\define missing-title() Yesterday
|
||||
\define display-variable(name)
|
||||
''<$text text=<<__name__>>/>'': <code><$text text={{{ [<__name__>getvariable[]] }}}/></code>
|
||||
\end
|
||||
|
||||
These examples use the following predefined variables:
|
||||
|
||||
* <<display-variable after-title>>
|
||||
* <<display-variable missing-title>>
|
||||
|
||||
<<.operator-example 1 """[list[Days of the Week]insertafter[Today]]""">>
|
||||
|
||||
<<.operator-example 2 """[list[Days of the Week]insertafter[Today],[Tuesday]]""">>
|
||||
|
||||
<<.operator-example 3 """[list[Days of the Week]insertafter[Today],<after-title>]""">>
|
||||
|
||||
<<.operator-example 4 """[list[Days of the Week]insertafter:after-title[Today]]""">>
|
||||
|
||||
<<.operator-example 5 """[list[Days of the Week]insertafter[Today],<missing-title>]""">>
|
||||
|
||||
<<.operator-example 6 """[list[Days of the Week]insertafter:missing-title[Today]]""">>
|
31
editions/tw5.com/tiddlers/filters/insertafter Operator.tid
Normal file
31
editions/tw5.com/tiddlers/filters/insertafter Operator.tid
Normal file
@ -0,0 +1,31 @@
|
||||
caption: insertafter
|
||||
created: 20170406090122441
|
||||
modified: 20220223004441865
|
||||
op-input: a [[selection of titles|Title Selection]]
|
||||
op-output: the input tiddler list with the new entry inserted
|
||||
op-parameter: the <<.op insertafter>> operator accepts 1 or 2 parameters, see below for details
|
||||
op-purpose: insert an item <<.place T>> into a list immediately after an item <<.place A>>
|
||||
op-suffix: (optional) the name of a variable containing the title of the tiddler after which this one should be inserted
|
||||
tags: [[Filter Operators]] [[Order Operators]] [[Listops Operators]]
|
||||
title: insertafter Operator
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
<<.from-version "5.2.3">>
|
||||
|
||||
The <<.op insertafter>> operator requires at least one parameter which specifies the title to insert into the input list. A second parameter can be used to specify the title after which the new title should be inserted.
|
||||
|
||||
```
|
||||
insertafter:<after-title-variable>[<title>],[<after-title>]
|
||||
```
|
||||
|
||||
* ''title'' : a title <<.place T>> to insert in the input list.
|
||||
* ''after-title'' : (optional). Insert <<.place T>> after this title <<.place A>> in the input list.
|
||||
* ''after-title-variable'' : (optional). The name of a variable specifying <<.place A>> instead of the `after-title` parameter.
|
||||
|
||||
If the item <<.place A>> isn't present in the input list then the new item is inserted at the end of the list. <<.from-version "5.2.3">> The suffixes ''start'' and ''end'' can be spedified to control where the new item is inserted when <<.place A>> is not found. The suffix ''end'' is the default, inserting the new item at the end of the list. The suffix ''start'' will cause the new item to be inserted at the start of the list when <<.place A>> is not found.
|
||||
|
||||
<<.tip "Either [[parameter|Filter Parameter]] can be a string, a text reference or a variable">>
|
||||
|
||||
<<.tip "If <<.place A>> is specified as both a suffix and a parameter, the parameter takes precedence">>
|
||||
|
||||
<<.operator-examples "insertafter">>
|
@ -5,7 +5,7 @@ op-input: a [[selection of titles|Title Selection]]
|
||||
op-output: the input tiddler list with the new entry inserted
|
||||
op-parameter: <<.from-version "5.2.2">> the <<.op insertbefore>> operator accepts 1 or 2 parameters, see below for details
|
||||
op-purpose: insert an item <<.place T>> into a list immediately before an item <<.place B>>
|
||||
op-suffix: (optional) the name of a variable containing the title of the tiddler before which this one should be inserted
|
||||
op-suffix: <<.from-version "5.2.3">> (optional) the name of a variable containing the title of the tiddler before which this one should be inserted
|
||||
tags: [[Filter Operators]] [[Order Operators]] [[Listops Operators]]
|
||||
title: insertbefore Operator
|
||||
type: text/vnd.tiddlywiki
|
||||
@ -14,15 +14,21 @@ type: text/vnd.tiddlywiki
|
||||
|
||||
The <<.op insertbefore>> operator requires at least one parameter which specifies the title to insert into the input list. A second parameter can be used to specify the title before which the new title should be inserted.
|
||||
|
||||
<<.from-version "5.2.3">>
|
||||
|
||||
Using the suffix to specify <<.place B>>, the title before which the new title should be inserted, is deprecated. Instead, the two-parameter form is recommended. If the two-parameter form is used, the suffixes ''start'' and ''end'' can be used to specify where the item should be inserted if <<.place B>> is not found.
|
||||
|
||||
```
|
||||
insertbefore:<before-title-variable>[<title>],[<before-title>]
|
||||
insertbefore:<before-title-variable>[<title>]
|
||||
insertbefore:<missing-location>[<title>],[<before-title>]
|
||||
```
|
||||
|
||||
* ''title'' : a title <<.place T>> to insert in the input list.
|
||||
* ''before-title'' : (optional). Insert <<.place T>> before this title <<.place B>> in the input list.
|
||||
* ''before-title-variable'' : (optional). The name of a variable specifying <<.place B>> instead of the `before-title` parameter.
|
||||
* ''missing-location'' : (optional). Either `start` or `end`: where to insert <<.place T>> if <<.place B>> is not found in the list.
|
||||
|
||||
If the item <<.place B>> isn't present in the input list then the new item is inserted at the end of the list.
|
||||
If the item <<.place B>> isn't present in the input list then the new item is inserted at the end of the list. <<.from-version "5.2.3">> The suffixes ''start'' and ''end'' can be spedified to control where the new item is inserted when <<.place B>> is not found. The suffix ''end'' is the default, inserting the new item at the end of the list. The suffix ''start'' will cause the new item to be inserted at the start of the list when <<.place B>> is not found.
|
||||
|
||||
<<.tip "Either [[parameter|Filter Parameter]] can be a string, a text reference or a variable">>
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user