From 21b10a225f29134d4c786de2420bf65fdcfedc03 Mon Sep 17 00:00:00 2001 From: "jeremy@jermolene.com" Date: Sun, 24 Apr 2022 21:24:38 +0100 Subject: [PATCH] Initial commit Everything is draft. --- core/modules/widgets/parameters.js | 74 ++++++++ core/modules/widgets/slot.js | 71 ++++++++ core/modules/widgets/ubertransclude.js | 168 ++++++++++++++++++ core/modules/widgets/widget.js | 37 ++++ .../CustomWidget-OverrideUbertransclude.tid | 35 ++++ .../ubertransclusion/CustomWidget-Simple.tid | 31 ++++ .../CustomWidget-TextWidgetOverride.tid | 33 ++++ .../CustomWidget-VariableAttribute.tid | 31 ++++ .../ubertransclusion/Parameterised-Simple.tid | 21 +++ .../Parameterised-Slotted-Missing.tid | 24 +++ .../Parameterised-Slotted.tid | 27 +++ .../jasmine/run-wiki-based-tests.js | 96 ++++++++++ 12 files changed, 648 insertions(+) create mode 100644 core/modules/widgets/parameters.js create mode 100644 core/modules/widgets/slot.js create mode 100644 core/modules/widgets/ubertransclude.js create mode 100644 editions/test/tiddlers/tests/data/ubertransclusion/CustomWidget-OverrideUbertransclude.tid create mode 100644 editions/test/tiddlers/tests/data/ubertransclusion/CustomWidget-Simple.tid create mode 100644 editions/test/tiddlers/tests/data/ubertransclusion/CustomWidget-TextWidgetOverride.tid create mode 100644 editions/test/tiddlers/tests/data/ubertransclusion/CustomWidget-VariableAttribute.tid create mode 100644 editions/test/tiddlers/tests/data/ubertransclusion/Parameterised-Simple.tid create mode 100644 editions/test/tiddlers/tests/data/ubertransclusion/Parameterised-Slotted-Missing.tid create mode 100644 editions/test/tiddlers/tests/data/ubertransclusion/Parameterised-Slotted.tid create mode 100644 plugins/tiddlywiki/jasmine/run-wiki-based-tests.js diff --git a/core/modules/widgets/parameters.js b/core/modules/widgets/parameters.js new file mode 100644 index 000000000..da39c509d --- /dev/null +++ b/core/modules/widgets/parameters.js @@ -0,0 +1,74 @@ +/*\ +title: $:/core/modules/widgets/parameters.js +type: application/javascript +module-type: widget + +Widget for definition of transclusion parameters + +\*/ +(function(){ + +/*jslint node: true, browser: true */ +/*global $tw: false */ +"use strict"; + +var Widget = require("$:/core/modules/widgets/widget.js").widget, + UberTranscludeWidget = require("$:/core/modules/widgets/ubertransclude.js").ubertransclude; + +var ParametersWidget = function(parseTreeNode,options) { + // Initialise + this.initialise(parseTreeNode,options); +}; + +/* +Inherit from the base widget class +*/ +ParametersWidget.prototype = Object.create(Widget.prototype); + +/* +Render this widget into the DOM +*/ +ParametersWidget.prototype.render = function(parent,nextSibling) { + // Call the constructor + Widget.call(this); + this.parentDomNode = parent; + this.computeAttributes(); + this.execute(); + this.renderChildren(parent,nextSibling); +}; + +/* +Compute the internal state of the widget +*/ +ParametersWidget.prototype.execute = function() { + var self = this; + // Find the parent transclusion + var transclusionWidget = this.parentWidget; + while(transclusionWidget && !(transclusionWidget instanceof UberTranscludeWidget)) { + transclusionWidget = transclusionWidget.parentWidget; + } + // Process each parameter + if(transclusionWidget) { + $tw.utils.each(this.attributes,function(value,name) { + self.setVariable(name,transclusionWidget.getTransclusionParameter(name,value)); + }); + } + // Construct the child widgets + this.makeChildWidgets(); +}; + +/* +Refresh the widget by ensuring our attributes are up to date +*/ +ParametersWidget.prototype.refresh = function(changedTiddlers) { + var changedAttributes = this.computeAttributes(); + if(Object.keys(changedAttributes).length) { + this.refreshSelf(); + return true; + } + return this.refreshChildren(changedTiddlers); +}; + +exports.parameters = ParametersWidget; + +})(); diff --git a/core/modules/widgets/slot.js b/core/modules/widgets/slot.js new file mode 100644 index 000000000..9fb9ccfac --- /dev/null +++ b/core/modules/widgets/slot.js @@ -0,0 +1,71 @@ +/*\ +title: $:/core/modules/widgets/slot.js +type: application/javascript +module-type: widget + +Widget for definition of slots within transcluded content. The values provided by the translusion are passed to the slot. + +\*/ +(function(){ + +/*jslint node: true, browser: true */ +/*global $tw: false */ +"use strict"; + +var Widget = require("$:/core/modules/widgets/widget.js").widget, + UberTranscludeWidget = require("$:/core/modules/widgets/ubertransclude.js").ubertransclude; + +var SlotWidget = function(parseTreeNode,options) { + // Initialise + this.initialise(parseTreeNode,options); +}; + +/* +Inherit from the base widget class +*/ +SlotWidget.prototype = Object.create(Widget.prototype); + +/* +Render this widget into the DOM +*/ +SlotWidget.prototype.render = function(parent,nextSibling) { + // Call the constructor + Widget.call(this); + this.parentDomNode = parent; + this.computeAttributes(); + this.execute(); + this.renderChildren(parent,nextSibling); +}; + +/* +Compute the internal state of the widget +*/ +SlotWidget.prototype.execute = function() { + var self = this; + this.slotName = this.getAttribute("$name"); + // Find the parent transclusion + var transclusionWidget = this.parentWidget; + while(transclusionWidget && !(transclusionWidget instanceof UberTranscludeWidget)) { + transclusionWidget = transclusionWidget.parentWidget; + } + // Get the parse tree nodes comprising the slot contents + var parseTreeNodes = transclusionWidget.getTransclusionSlotValue(this.slotName,this.parseTreeNode.children); + // Construct the child widgets + this.makeChildWidgets(parseTreeNodes); +}; + +/* +Refresh the widget by ensuring our attributes are up to date +*/ +SlotWidget.prototype.refresh = function(changedTiddlers) { + var changedAttributes = this.computeAttributes(); + if(changedAttributes["$name"]) { + this.refreshSelf(); + return true; + } + return this.refreshChildren(changedTiddlers); +}; + +exports.slot = SlotWidget; + +})(); diff --git a/core/modules/widgets/ubertransclude.js b/core/modules/widgets/ubertransclude.js new file mode 100644 index 000000000..2ece2a0ff --- /dev/null +++ b/core/modules/widgets/ubertransclude.js @@ -0,0 +1,168 @@ +/*\ +title: $:/core/modules/widgets/ubertransclude.js +type: application/javascript +module-type: widget + +Ubertransclude widget + +\*/ +(function(){ + +/*jslint node: true, browser: true */ +/*global $tw: false */ +"use strict"; + +var Widget = require("$:/core/modules/widgets/widget.js").widget; + +var UberTranscludeWidget = function(parseTreeNode,options) { + this.initialise(parseTreeNode,options); +}; + +/* +Inherit from the base widget class +*/ +UberTranscludeWidget.prototype = new Widget(); + +/* +Render this widget into the DOM +*/ +UberTranscludeWidget.prototype.render = function(parent,nextSibling) { + this.parentDomNode = parent; + this.computeAttributes(); + this.execute(); + this.renderChildren(parent,nextSibling); +}; + +/* +Compute the internal state of the widget +*/ +UberTranscludeWidget.prototype.execute = function() { + var self = this; + // Get our parameters + this.transcludeVariable = this.getAttribute("$variable"); + this.transcludeType = this.getAttribute("$type"); + this.transcludeTitle = this.getAttribute("$tiddler",this.getVariable("currentTiddler")); + this.transcludeSubTiddler = this.getAttribute("$subtiddler"); + this.transcludeField = this.getAttribute("$field"); + this.transcludeIndex = this.getAttribute("$index"); + this.transcludeMode = this.getAttribute("$mode"); + this.recursionMarker = this.getAttribute("$recursionMarker","yes"); + // Find the value widgets in our parse tree + this.slotValueParseTrees = Object.create(null); + this.slotValueParseTrees.missing = this.parseTreeNode.children; + var searchParseTreeNodes = function(nodes) { + $tw.utils.each(nodes,function(node) { + if(node.type === "value" && node.tag === "$value") { + if(node.attributes["$name"] && node.attributes["$name"].type === "string") { + var slotValueName = node.attributes["$name"].value; + self.slotValueParseTrees[slotValueName] = node.children; + } + } else { + searchParseTreeNodes(node.children); + } + }); + }; + searchParseTreeNodes(this.parseTreeNode.children); + // Parse the text reference + var parseAsInline = !this.parseTreeNode.isBlock; + if(this.transcludeMode === "inline") { + parseAsInline = true; + } else if(this.transcludeMode === "block") { + parseAsInline = false; + } + var parser; + if(this.transcludeVariable) { + parser = this.wiki.parseText(this.transcludeType,this.getVariable(this.transcludeVariable,""),{parseAsInline: !this.parseTreeNode.isBlock}); + } else { + parser = this.wiki.parseTextReference( + this.transcludeTitle, + this.transcludeField, + this.transcludeIndex, + { + parseAsInline: parseAsInline, + subTiddler: this.transcludeSubTiddler + }); + } + var parseTreeNodes = parser ? parser.tree : this.parseTreeNode.children; + this.sourceText = parser ? parser.source : null; + this.parserType = parser? parser.type : null; + // Set context variables for recursion detection + var recursionMarker = this.makeRecursionMarker(); + if(this.recursionMarker === "yes") { + this.setVariable("ubertransclusion",recursionMarker); + } + // Check for recursion + if(parser) { + if(this.parentWidget && this.parentWidget.hasVariable("ubertransclusion",recursionMarker)) { + parseTreeNodes = [{type: "element", tag: "span", attributes: { + "class": {type: "string", value: "tc-error"} + }, children: [ + {type: "text", text: $tw.language.getString("Error/RecursiveTransclusion")} + ]}]; + } + } + // Construct the child widgets + this.makeChildWidgets(parseTreeNodes); +}; + +/* +Fetch the value of a parameter +*/ +UberTranscludeWidget.prototype.getTransclusionParameter = function(name,defaultValue) { + if(name.charAt(0) === "$") { + name = "$" + name; + } + return this.getAttribute(name,defaultValue); +}; + +/* +Fetch the value of a slot +*/ +UberTranscludeWidget.prototype.getTransclusionSlotValue = function(name,defaultParseTreeNodes) { + if(name && this.slotValueParseTrees[name]) { + return this.slotValueParseTrees[name]; + } else { + return defaultParseTreeNodes || []; + } +}; + +/* +Compose a string comprising the title, field and/or index to identify this transclusion for recursion detection +*/ +UberTranscludeWidget.prototype.makeRecursionMarker = function() { + var output = []; + output.push("{"); + output.push(this.getVariable("currentTiddler",{defaultValue: ""})); + output.push("|"); + output.push(this.transcludeTitle || ""); + output.push("|"); + output.push(this.transcludeField || ""); + output.push("|"); + output.push(this.transcludeIndex || ""); + output.push("|"); + output.push(this.transcludeSubTiddler || ""); + output.push("}"); + return output.join(""); +}; + +UberTranscludeWidget.prototype.parserNeedsRefresh = function() { + var parserInfo = this.wiki.getTextReferenceParserInfo(this.transcludeTitle,this.transcludeField,this.transcludeIndex,{subTiddler:this.transcludeSubTiddler}); + return (this.sourceText === undefined || parserInfo.sourceText !== this.sourceText || parserInfo.parserType !== this.parserType) +}; + +/* +Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering +*/ +UberTranscludeWidget.prototype.refresh = function(changedTiddlers) { + var changedAttributes = this.computeAttributes(); + if(($tw.utils.count(changedAttributes) > 0) || (changedTiddlers[this.transcludeTitle] && this.parserNeedsRefresh())) { + this.refreshSelf(); + return true; + } else { + return this.refreshChildren(changedTiddlers); + } +}; + +exports.ubertransclude = UberTranscludeWidget; + +})(); diff --git a/core/modules/widgets/widget.js b/core/modules/widgets/widget.js index 0aefbada8..a3f6c75a8 100755 --- a/core/modules/widgets/widget.js +++ b/core/modules/widgets/widget.js @@ -387,7 +387,44 @@ options include: variables: optional hashmap of variables to wrap around the widget */ Widget.prototype.makeChildWidget = function(parseTreeNode,options) { + var self = this; options = options || {}; + // Check whether this node type is defined by a custom macro definition + var variableDefinitionName = "<$" + parseTreeNode.type + ">"; + if(parseTreeNode.type !== "ubertransclude" && this.variables[variableDefinitionName] && this.variables[variableDefinitionName].value) { + var newParseTreeNode = { + type: "ubertransclude", + tag: "$ubertransclude", + attributes: { + "$variable": {name: "$variable", type: "string", value: variableDefinitionName} + }, + children: [ + { + type: "value", + tag: "$value", + attributes: { + "$name": {name: "$name", type: "string", value: "body"} + }, + children: parseTreeNode.children + } + ] + }; + newParseTreeNode.orderedAttributes = [newParseTreeNode.attributes["$variable"]]; + newParseTreeNode.children[0].orderedAttributes = [newParseTreeNode.children[0].attributes["$name"]]; + $tw.utils.each(parseTreeNode.orderedAttributes,function(attr) { + // If the attribute starts with a dollar then add an extra dollar so that it doesn't clash with the $xxx attributes of ubertransclude + var name = attr.name.charAt(0) === "$" ? "$" + attr.name : attr.name, + newAttr = { + name: name, + type: attr.type, + value: attr.value + }; + newParseTreeNode.attributes[name] = newAttr; + newParseTreeNode.orderedAttributes.push(newAttr); + }); + parseTreeNode = newParseTreeNode; + } + // Get the widget class for this node type var WidgetClass = this.widgetClasses[parseTreeNode.type]; if(!WidgetClass) { WidgetClass = this.widgetClasses.text; diff --git a/editions/test/tiddlers/tests/data/ubertransclusion/CustomWidget-OverrideUbertransclude.tid b/editions/test/tiddlers/tests/data/ubertransclusion/CustomWidget-OverrideUbertransclude.tid new file mode 100644 index 000000000..a5bdd4d51 --- /dev/null +++ b/editions/test/tiddlers/tests/data/ubertransclusion/CustomWidget-OverrideUbertransclude.tid @@ -0,0 +1,35 @@ +title: Ubertransclude/CustomWidget/OverrideUbertransclude +description: Custom widget definition attempting to override ubertransclude +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +<$ubertransclude $tiddler='TiddlerOne' one='Ferret'> + +_ +title: TiddlerZero + +Antelope +_ +title: TiddlerOne + +\whitespace trim + +<$set name="<$ubertransclude>" value="""\whitespace trim + <$parameters one='Jaguar'> + <$text text=<>/> + <$slot $name="body"> + Whale + + """ +> + <$ubertransclude $tiddler="TiddlerZero"> + Crocodile + + +_ +title: ExpectedResult + +

Antelope

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/ubertransclusion/CustomWidget-Simple.tid b/editions/test/tiddlers/tests/data/ubertransclusion/CustomWidget-Simple.tid new file mode 100644 index 000000000..b370a5af8 --- /dev/null +++ b/editions/test/tiddlers/tests/data/ubertransclusion/CustomWidget-Simple.tid @@ -0,0 +1,31 @@ +title: Ubertransclude/CustomWidget/Simple +description: Custom widget definition +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +<$ubertransclude $tiddler='TiddlerOne' one='Ferret'> + +_ +title: TiddlerOne + +\whitespace trim + +<$set name="<$mywidget>" value="""\whitespace trim + <$parameters one='Jaguar'> + <$text text=<>/> + <$slot $name="body"> + Whale + + """ +> + <$mywidget one="Dingo"> + Crocodile + + +_ +title: ExpectedResult + +

DingoCrocodile

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/ubertransclusion/CustomWidget-TextWidgetOverride.tid b/editions/test/tiddlers/tests/data/ubertransclusion/CustomWidget-TextWidgetOverride.tid new file mode 100644 index 000000000..0db27ece5 --- /dev/null +++ b/editions/test/tiddlers/tests/data/ubertransclusion/CustomWidget-TextWidgetOverride.tid @@ -0,0 +1,33 @@ +title: Ubertransclude/CustomWidget/TextWidgetOverride +description: Custom widget definition redefining the text widget +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +<$ubertransclude $tiddler='TiddlerOne'> + +_ +title: TiddlerOne + +\whitespace trim + +<$set name="<$text>" value="""\whitespace trim + <$parameters text='Jaguar'> + <$set name="<$text>" value=""> + <$text text=<>/> + <$slot $name="body"> + Whale + + + """ +> + <$text text="Dingo"> + Crocodile + + +_ +title: ExpectedResult + +

DingoCrocodile

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/ubertransclusion/CustomWidget-VariableAttribute.tid b/editions/test/tiddlers/tests/data/ubertransclusion/CustomWidget-VariableAttribute.tid new file mode 100644 index 000000000..b7d6a4942 --- /dev/null +++ b/editions/test/tiddlers/tests/data/ubertransclusion/CustomWidget-VariableAttribute.tid @@ -0,0 +1,31 @@ +title: Ubertransclude/CustomWidget/VariableAttribute +description: Custom widget definition using an attribute called $variable +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +<$ubertransclude $tiddler='TiddlerOne' one='Ferret'> + +_ +title: TiddlerOne + +\whitespace trim + +<$set name="<$mywidget>" value="""\whitespace trim + <$parameters $variable='Jaguar'> + <$text text=<<$variable>>/> + <$slot $name="body"> + Whale + + """ +> + <$mywidget $variable="Dingo"> + Crocodile + + +_ +title: ExpectedResult + +

DingoCrocodile

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/ubertransclusion/Parameterised-Simple.tid b/editions/test/tiddlers/tests/data/ubertransclusion/Parameterised-Simple.tid new file mode 100644 index 000000000..7fc5bfe85 --- /dev/null +++ b/editions/test/tiddlers/tests/data/ubertransclusion/Parameterised-Simple.tid @@ -0,0 +1,21 @@ +title: Ubertransclude/Parameterised/Simple +description: Simple parameterised transclusion +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +<$ubertransclude $tiddler='TiddlerOne' one='Ferret'/> +<$ubertransclude $tiddler='TiddlerOne'/> +_ +title: TiddlerOne + +\whitespace trim +<$parameters one='Jaguar'> + <$text text=<>/> + +_ +title: ExpectedResult + +

FerretJaguar

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/ubertransclusion/Parameterised-Slotted-Missing.tid b/editions/test/tiddlers/tests/data/ubertransclusion/Parameterised-Slotted-Missing.tid new file mode 100644 index 000000000..bf671f875 --- /dev/null +++ b/editions/test/tiddlers/tests/data/ubertransclusion/Parameterised-Slotted-Missing.tid @@ -0,0 +1,24 @@ +title: Ubertransclude/Parameterised/Slotted/Missing +description: Parameterised transclusion with slotted missing values +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +<$ubertransclude $tiddler='TiddlerOne' one='Ferret'> + +_ +title: TiddlerOne + +\whitespace trim +<$parameters one='Jaguar'> + <$text text=<>/> + <$slot $name="content"> + Whale + + +_ +title: ExpectedResult + +

FerretWhale

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/ubertransclusion/Parameterised-Slotted.tid b/editions/test/tiddlers/tests/data/ubertransclusion/Parameterised-Slotted.tid new file mode 100644 index 000000000..f87a3509d --- /dev/null +++ b/editions/test/tiddlers/tests/data/ubertransclusion/Parameterised-Slotted.tid @@ -0,0 +1,27 @@ +title: Ubertransclude/Parameterised/Slotted +description: Parameterised transclusion with slotted values +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +<$ubertransclude $tiddler='TiddlerOne' one='Ferret'> + <$value $name="content"> + Hippopotamus + + +_ +title: TiddlerOne + +\whitespace trim +<$parameters one='Jaguar'> + <$text text=<>/> + <$slot $name="content"> + Whale + + +_ +title: ExpectedResult + +

FerretHippopotamus

\ No newline at end of file diff --git a/plugins/tiddlywiki/jasmine/run-wiki-based-tests.js b/plugins/tiddlywiki/jasmine/run-wiki-based-tests.js new file mode 100644 index 000000000..1ef806aa8 --- /dev/null +++ b/plugins/tiddlywiki/jasmine/run-wiki-based-tests.js @@ -0,0 +1,96 @@ +/*\ +title: $:/plugins/tiddlywiki/jasmine/run-wiki-based-tests.js +type: application/javascript +tags: [[$:/tags/test-spec]] + +Tests the wiki based tests + +\*/ +(function(){ + +/*jslint node: true, browser: true */ +/*global $tw: false */ +"use strict"; + +var TEST_WIKI_TIDDLER_FILTER = "[type[text/vnd.tiddlywiki-multiple]tag[$:/tags/wiki-test-spec]]"; + +var widget = require("$:/core/modules/widgets/widget.js"); + +describe("Wiki-based tests", function() { + + // Step through the test tiddlers + var tests = $tw.wiki.filterTiddlers(TEST_WIKI_TIDDLER_FILTER); + $tw.utils.each(tests,function(title) { + var tiddler = $tw.wiki.getTiddler(title); + it(tiddler.fields.title + ": " + tiddler.fields.description, function() { + // Add our tiddlers + var wiki = new $tw.Wiki(); + wiki.addTiddlers(readMultipleTiddlersTiddler(title)); + // Complain if we don't have the ouput and expected results + if(!wiki.tiddlerExists("Output")) { + throw "Missing 'Output' tiddler"; + } + if(!wiki.tiddlerExists("ExpectedResult")) { + throw "Missing 'ExpectedResult' tiddler"; + } + // Construct the widget node + var text = "{{Output}}\n\n"; + var widgetNode = createWidgetNode(parseText(text,wiki),wiki); + // Render the widget node to the DOM + var wrapper = renderWidgetNode(widgetNode); + // Test the rendering + expect(wrapper.innerHTML).toBe(wiki.getTiddlerText("ExpectedResult")); + }); + }); + + function readMultipleTiddlersTiddler(title) { + var rawTiddlers = $tw.wiki.getTiddlerText(title).split("\n_\n"); + var 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; + } + + function createWidgetNode(parseTreeNode,wiki) { + return new widget.widget(parseTreeNode,{ + wiki: wiki, + document: $tw.fakeDocument + }); + } + + function parseText(text,wiki,options) { + var parser = wiki.parseText("text/vnd.tiddlywiki",text,options); + return parser ? {type: "widget", children: parser.tree} : undefined; + } + + function renderWidgetNode(widgetNode) { + $tw.fakeDocument.setSequenceNumber(0); + var wrapper = $tw.fakeDocument.createElement("div"); + widgetNode.render(wrapper,null); +// console.log(require("util").inspect(wrapper,{depth: 8})); + return wrapper; + } + + function refreshWidgetNode(widgetNode,wrapper,changes) { + var changedTiddlers = {}; + if(changes) { + $tw.utils.each(changes,function(title) { + changedTiddlers[title] = true; + }); + } + widgetNode.refresh(changedTiddlers,wrapper,null); +// console.log(require("util").inspect(wrapper,{depth: 8})); + } + +}); + +})();