1
0
mirror of https://github.com/Jermolene/TiddlyWiki5 synced 2024-11-30 05:19:57 +00:00

Refactor compound tiddler handling into data widget

And add some tests for the data widget
This commit is contained in:
jeremy@jermolene.com 2023-04-17 11:13:35 +01:00
parent 6c9b8116bd
commit 683ec33004
15 changed files with 210 additions and 90 deletions

View File

@ -31,7 +31,12 @@ DataWidget.prototype.render = function(parent,nextSibling) {
this.parentDomNode = parent;
this.computeAttributes();
this.execute();
var domNode = this.document.createTextNode("");
parent.insertBefore(domNode,nextSibling);
this.renderChildren(parent,nextSibling);
// Children must have been rendered before we can read the data values
domNode.textContent = JSON.stringify(this.readDataTiddlerValues());
this.domNodes.push(domNode);
};
/*
@ -52,29 +57,75 @@ DataWidget.prototype.readDataTiddlerValues = function() {
// Read any attributes not prefixed with $
$tw.utils.each(this.attributes,function(value,name) {
if(name.charAt(0) !== "$") {
item[name] = value;
item[name] = value;
}
});
// Deal with $tiddler or $filter attributes
var titles;
item = new $tw.Tiddler(item);
// Deal with $tiddler, $filter or $compound-tiddler attributes
var tiddlers = [],title;
if(this.hasAttribute("$tiddler")) {
titles = [this.getAttribute("$tiddler")];
} else if(this.hasAttribute("$filter")) {
titles = this.wiki.filterTiddlers(this.getAttribute("$filter"));
title = this.getAttribute("$tiddler");
if(title) {
tiddlers.push(this.wiki.getTiddler(title));
}
}
if(titles) {
var results = [];
$tw.utils.each(titles,function(title,index) {
var tiddler = self.wiki.getTiddler(title),
fields;
if(tiddler) {
fields = tiddler.getFieldStrings();
}
results.push($tw.utils.extend({},fields,item));
})
return results;
if(this.hasAttribute("$filter")) {
var filter = this.getAttribute("$filter");
if(filter) {
var titles = this.wiki.filterTiddlers(filter);
$tw.utils.each(titles,function(title) {
var tiddler = self.wiki.getTiddler(title);
tiddlers.push(tiddler);
});
}
}
if(this.hasAttribute("$compound-tiddler")) {
title = this.getAttribute("$compound-tiddler");
if(title) {
tiddlers.push.apply(tiddlers,this.extractCompoundTiddler(title));
}
}
// Convert the literal item to field strings
item = item.getFieldStrings();
if(tiddlers.length === 0) {
if(Object.keys(item).length > 0 && !!item.title) {
return [item];
} else {
return [];
}
} else {
return [item];
var results = [];
$tw.utils.each(tiddlers,function(tiddler,index) {
var fields = tiddler.getFieldStrings();
results.push($tw.utils.extend({},fields,item));
});
return results;
}
};
/*
Helper to extract tiddlers from text/vnd.tiddlywiki-multiple tiddlers
*/
DataWidget.prototype.extractCompoundTiddler = function(title) {
var tiddler = this.wiki.getTiddler(title);
if(tiddler && tiddler.fields.type === "text/vnd.tiddlywiki-multiple") {
var text = tiddler.fields.text || "",
rawTiddlers = text.split("\n+\n"),
tiddlers = [];
$tw.utils.each(rawTiddlers,function(rawTiddler) {
var fields = Object.create(null),
split = rawTiddler.split(/\r?\n\r?\n/mg);
if(split.length >= 1) {
fields = $tw.utils.parseFields(split[0],fields);
}
if(split.length >= 2) {
fields.text = split.slice(1).join("\n\n");
}
tiddlers.push(new $tw.Tiddler(fields));
});
return tiddlers;
} else {
return [];
}
};

View File

@ -53,20 +53,12 @@ TestCaseWidget.prototype.render = function(parent,nextSibling) {
Array.prototype.push.apply(tiddlers,widget.readDataTiddlerValues());
});
this.testcaseWiki.addTiddlers(tiddlers);
// Load tiddlers from the optional testcaseTiddler
if(this.testcaseTiddler) {
var tiddler = this.wiki.getTiddler(this.testcaseTiddler);
if(tiddler && tiddler.fields.type === "text/vnd.tiddlywiki-multiple") {
var tiddlers = this.extractMultipleTiddlers(tiddler.fields.text);
this.testcaseWiki.addTiddlers(tiddlers);
}
}
// Unpack plugin tiddlers
this.testcaseWiki.readPluginInfo();
this.testcaseWiki.registerPluginTiddlers("plugin");
this.testcaseWiki.unpackPluginTiddlers();
this.testcaseWiki.addIndexersToWiki();
// Gemerate a `transclusion` variable that depends on the values of the payload tiddlers so that the template can easily make unique state tiddlers
// Generate a `transclusion` variable that depends on the values of the payload tiddlers so that the template can easily make unique state tiddlers
this.setVariable("transclusion",$tw.utils.hashString(this.testcaseWiki.getTiddlersAsJson("[all[tiddlers]]")));
// Generate a `testcaseInfo` variable that contains information about the subwiki in JSON format
var testcaseInfoData = {
@ -80,24 +72,6 @@ TestCaseWidget.prototype.render = function(parent,nextSibling) {
this.renderChildren(parent,nextSibling);
};
TestCaseWidget.prototype.extractMultipleTiddlers = function(text) {
// Duplicates code found in $:/plugins/tiddlywiki/jasmine/run-wiki-based-tests.js
var rawTiddlers = text.split("\n+\n"),
tiddlers = [];
$tw.utils.each(rawTiddlers,function(rawTiddler) {
var fields = Object.create(null),
split = rawTiddler.split(/\r?\n\r?\n/mg);
if(split.length >= 1) {
fields = $tw.utils.parseFields(split[0],fields);
}
if(split.length >= 2) {
fields.text = split.slice(1).join("\n\n");
}
tiddlers.push(fields);
});
return tiddlers;
};
/*
Render a test case
*/
@ -126,7 +100,6 @@ TestCaseWidget.prototype.testcaseRawTiddler = function(parent,nextSibling,title,
Compute the internal state of the widget
*/
TestCaseWidget.prototype.execute = function() {
this.testcaseTiddler = this.getAttribute("testcase-tiddler");
this.testcaseTemplate = this.getAttribute("template","$:/core/ui/testcases/DefaultTemplate");
// Make child widgets
var parseTreeNodes = [{

View File

@ -0,0 +1,25 @@
title: Data/ImportCompound
type: text/vnd.tiddlywiki-multiple
tags: [[$:/tags/wiki-test-spec]]
description: Importing a compound payload tiddler and adding custom fields
title: Description
text: Importing a compound payload tiddler and adding custom fields
+
title: Output
\whitespace trim
<$data $compound-tiddler="Compound" custom="Alpha"/>
+
title: Compound
type: text/vnd.tiddlywiki-multiple
tags: [[$:/tags/wiki-test-spec]]
title: Payload Tiddler
tags: Alpha Beta Gamma
This is a payload tiddler from a compound tiddler
+
title: ExpectedResult
<p>[{"title":"Payload Tiddler","tags":"Alpha Beta Gamma","text":"This is a payload tiddler from a compound tiddler","custom":"Alpha"}]</p>

View File

@ -0,0 +1,26 @@
title: Data/ImportFilter
type: text/vnd.tiddlywiki-multiple
tags: [[$:/tags/wiki-test-spec]]
description: Importing a payload filter and adding custom fields
title: Description
text: Importing a payload filter and adding custom fields
+
title: Output
\whitespace trim
<$data $filter="[tag[Definitions]]" custom="Alpha"/>
+
title: HelloThere
tags: Definitions
This is the tiddler HelloThere
+
title: AnotherDefinition
tags: Definitions
This is the tiddler AnotherDefinition
+
title: ExpectedResult
<p>[{"title":"AnotherDefinition","tags":"Definitions","text":"This is the tiddler AnotherDefinition","custom":"Alpha"},{"title":"HelloThere","tags":"Definitions","text":"This is the tiddler HelloThere","custom":"Alpha"}]</p>

View File

@ -0,0 +1,21 @@
title: Data/ImportTiddler
type: text/vnd.tiddlywiki-multiple
tags: [[$:/tags/wiki-test-spec]]
description: Importing a payload tiddler and adding custom fields
title: Description
text: Importing a payload tiddler and adding custom fields
+
title: Output
\whitespace trim
<$data $tiddler="HelloThere" custom="Alpha"/>
+
title: HelloThere
tags: Definitions
This is the tiddler HelloThere
+
title: ExpectedResult
<p>[{"title":"HelloThere","tags":"Definitions","text":"This is the tiddler HelloThere","custom":"Alpha"}]</p>

View File

@ -0,0 +1,16 @@
title: Data/Simple
type: text/vnd.tiddlywiki-multiple
tags: [[$:/tags/wiki-test-spec]]
description: Standalone data widget to create individual tiddlers
title: Description
text: Standalone data widget to create individual tiddlers
+
title: Output
\whitespace trim
<$data title="Epsilon" text="Theta"/>
+
title: ExpectedResult
<p>[{"title":"Epsilon","text":"Theta"}]</p>

View File

@ -16,6 +16,7 @@ A demo of the geospatial functionality is [ext[available here|./plugins/tiddlywi
It also includes a number of new features that are intended for eventual inclusion in the core:
* TestCaseWidget, TestCaseTranscludeWidget and TestCaseViewWidget
* Enhancements to the existing DataWidget
* [[jsonset Operator]]
* [[setquerystring Operator]]
* [[WidgetMessage: tm-http-request]]

View File

@ -14,23 +14,22 @@ The data widget is used with the <<.wlink TestCaseWidget>> widget and the [[Inne
The content of the data widget is rendered as if the data widget were not present. It supports the following attributes:
|!Attribute |!Description |
|<<.attr $tiddler>> |The title of a tiddler to be used as a payload tiddler (optional) |
|<<.attr $filter>> |A filter string identifying tiddlers to be used as payload tiddlers (optional) |
|<<.attr $tiddler>> |Optional title of a tiddler to be used as a payload tiddler (optional) |
|<<.attr $filter>> |Optional filter string identifying tiddlers to be used as payload tiddlers (optional) |
|<<.attr $compound-tiddler>> |Optional title of a tiddler containing payload tiddlers in `text/vnd.tiddlywiki-multiple` format (see below) |
|//any attribute<br>not starting<br>with $// |Field values to be assigned to the payload tiddler(s) |
The data widget can be used in three different ways:
The data widget is not rendered when used within the <<.wlink TestCaseWidget>> widget or the [[Innerwiki Plugin]] but for ease of testing, when used elsewhere it renders a JSON representation of the payload tiddlers.
* Without the `$tiddler` or `$filter` attributes, the remaining attributes provide the fields for a single payload tiddler
* With the `$tiddler` attribute present, the payload tiddler takes its fields from that tiddler with the remaining attributes overriding those fields
* With the `$filter` attribute present, the payload is a copy of all of the tiddlers identified by the filter, with the remaining attributes overriding those fields of each one
This example injects a tiddler with the title "Epsilon" and the text "Theta":
Without any of the attributes <<.attr $tiddler>>, <<.attr $filter>> or <<.attr $compound-tiddler>>, any attributes whose name does not start with $ are used as the field values for creating a single new tiddler. For example, here a tiddler with the title "Epsilon" and the text "Theta" is created:
```
<$data title="Epsilon" text="Theta"/>
```
This example injects a copy of the "HelloThere" tiddler with the addition of the field "custom" set to "Alpha":
If any of the attributes <<.attr $tiddler>>, <<.attr $filter>> or <<.attr $compound-tiddler>> are specified then they are used to generate base tiddlers that are then modified with the addition of fields derived from any attributes whose name does not start with $.
This example, here we specify a copy of the "HelloThere" tiddler with the addition of the field "custom" set to "Alpha":
```
<$data $tiddler="HelloThere" custom="Alpha"/>
@ -41,3 +40,26 @@ This example injects all image tiddlers with the addition of the field "custom"
```
<$data $filter="[is[image]]" custom="Beta"/>
```
! Compound Tiddlers
Compound tiddlers provide a way to easily create multiple tiddlers from within a single tiddler. They are contained in tiddlers of type `text/vnd.tiddlywiki-multiple`. The text field consists of a series of tiddlers in the same format as `.tid` files, each separated by a line containing a single `+` character.
For example:
```
title: First
tags: one two
This is the first tiddler
+
title: Second
tags: three four
This is the second tiddler
+
title: third
tags: five six
This is the third tiddler
```

View File

@ -14,38 +14,15 @@ The testcase widget creates an independent subwiki loaded with specified tiddler
The content of the `<$testcase>` widget is not displayed but instead is scanned for <<.wlink DataWidget>> widgets that define the payload tiddlers to be included in the test case.
|!Attribute |!Description |
|<<.attr testcase-tiddler>> |Optional title of a tiddler containing a test case in `text/vnd.tiddlywiki-multiple` format (see below) |
|<<.attr template>> |Optional title of the template used to display the testcase (defaults to $:/core/ui/testcases/DefaultTemplate) |
! State Handling
The `<$testcase>` widget sets the variable `transclusion` to a hash that reflects the names and values of all the payload tiddlers. This makes easier for test case templates to create unique state tiddler titles using the [[qualify Macro]] or QualifyWidget.
! Payload Tiddlers
The payload tiddlers are the tiddler values that are loaded into the subwiki that is created to run the tests.
The payload tiddlers can be created in two different ways:
* Tiddlers values specfied via <<.wlink DataWidget>> widgets within the body of the `<$testcase>` widget
* As multiple tiddlers embedded within a single tiddler of type `text/vnd.tiddlywiki-multiple` whose title is given in the <<.attr testcase-tiddler>> attribute
The special tiddler type `text/vnd.tiddlywiki-multiple` is intended to simplify creating test cases that require several tiddlers. The text field consists of a series of tiddlers in the same format as `.tid` files, each separated by a line containing a single `+` character.
For example:
```
title: First
tags: one two
This is the first tiddler
+
title: Second
tags: three four
This is the second tiddler
+
title: third
tags: five six
This is the third tiddler
```
The payload tiddlers are the tiddler values that are loaded into the subwiki that is created to run the tests. They are created via <<.wlink DataWidget>> widgets within the body of the `<$testcase>` widget.
! Test Case Templates
@ -55,9 +32,11 @@ The default test case template $:/core/ui/testcases/DefaultTemplate displays a s
The `<$testcase>` widget assigns a value to the `transclusion` variable that depends on the combined values of all the payload tiddlers. This means that using the `<<qualify>>` macro within a test case template will generate a unique value for each of multiple test cases within the same tiddler.
! Test Case Variables
The `<$testcase>` widget also assigns a block of information about the subwiki in JSON format to a the variable `testcaseInfo`. It contains the following properties:
* ''titles'': an array of the titles of all the tiddlers in the subwiki (excluding shadow tiddlers)
* ''tiddlers'': a hashmap by title of an array of all the field names of each tiddler in the subwiki (does not include shadow tiddlers unless they have been overridden)
! Test Case Conventions

View File

@ -8,6 +8,7 @@ The `geodistance` operator calculates the distance between two points in [[GeoJS
!! Examples
<$testcase testcase-tiddler="$:/plugins/tiddlywiki/geospatial/tests/operators/geodistance">
<$testcase>
<$data $compound-tiddler="$:/plugins/tiddlywiki/geospatial/tests/operators/geodistance"/>
<$data $tiddler="$:/plugins/tiddlywiki/geospatial"/>
</$testcase>

View File

@ -10,6 +10,7 @@ Each input list item is interpreted as a [[GeoJSON Point Feature]] and the opera
!! Examples
<$testcase testcase-tiddler="$:/plugins/tiddlywiki/geospatial/tests/operators/geolookup">
<$testcase>
<$data $compound-tiddler="$:/plugins/tiddlywiki/geospatial/tests/operators/geolookup"/>
<$data $tiddler="$:/plugins/tiddlywiki/geospatial"/>
</$testcase>

View File

@ -8,6 +8,7 @@ The `geonearestpoint` operator determines the point in a list that is nearest to
!! Examples
<$testcase testcase-tiddler="$:/plugins/tiddlywiki/geospatial/tests/operators/geonearestpoint">
<$testcase>
<$data $compound-tiddler="$:/plugins/tiddlywiki/geospatial/tests/operators/geonearestpoint"/>
<$data $tiddler="$:/plugins/tiddlywiki/geospatial"/>
</$testcase>

View File

@ -16,6 +16,7 @@ Any operands that cannot be interpreted as a valid number will be interpreted as
!! Examples
<$testcase testcase-tiddler="$:/plugins/tiddlywiki/geospatial/tests/operators/geopoint">
<$testcase>
<$data $compound-tiddler="$:/plugins/tiddlywiki/geospatial/tests/operators/geopoint"/>
<$data $tiddler="$:/plugins/tiddlywiki/geospatial"/>
</$testcase>

View File

@ -8,6 +8,7 @@ The `olc-decode` operator converts an [[OpenLocationCode|https://github.com/goog
!! Examples
<$testcase testcase-tiddler="$:/plugins/tiddlywiki/geospatial/tests/operators/olc-decode">
<$testcase>
<$data $compound-tiddler="$:/plugins/tiddlywiki/geospatial/tests/operators/olc-decode"/>
<$data $tiddler="$:/plugins/tiddlywiki/geospatial"/>
</$testcase>

View File

@ -8,6 +8,7 @@ The `old-encode` operator converts separate latitude and longitude numbers into
!! Examples
<$testcase testcase-tiddler="$:/plugins/tiddlywiki/geospatial/tests/operators/olc-encode">
<$testcase>
<$data $compound-tiddler="$:/plugins/tiddlywiki/geospatial/tests/operators/olc-encode"/>
<$data $tiddler="$:/plugins/tiddlywiki/geospatial"/>
</$testcase>