1
0
mirror of https://github.com/Jermolene/TiddlyWiki5 synced 2025-01-27 09:24:45 +00:00

Added ability to transclude fields of data tiddlers

This allows us to transclude colours into CSS
This commit is contained in:
Jeremy Ruston 2013-01-15 17:50:47 +00:00
parent 965cebf195
commit baff901685
7 changed files with 110 additions and 47 deletions

View File

@ -33,7 +33,11 @@ exports.parse = function() {
// Move past the match // Move past the match
this.parser.pos = this.matchRegExp.lastIndex; this.parser.pos = this.matchRegExp.lastIndex;
// Get the match details // Get the match details
var targetTitle = $tw.utils.trim(this.match[1]), var textRef = $tw.utils.trim(this.match[1]),
tr = $tw.utils.parseTextReference(textRef),
targetTitle = tr.title,
targetField = tr.field,
targetIndex = tr.index,
tooltip = this.match[2], tooltip = this.match[2],
template = $tw.utils.trim(this.match[3]), template = $tw.utils.trim(this.match[3]),
style = this.match[4], style = this.match[4],
@ -47,6 +51,12 @@ exports.parse = function() {
}, },
isBlock: true isBlock: true
}; };
if(targetField) {
node.attributes.field = {type: "string", value: targetField};
}
if(targetIndex) {
node.attributes.index = {type: "string", value: targetIndex};
}
if(tooltip) { if(tooltip) {
node.attributes.tooltip = {type: "string", value: tooltip}; node.attributes.tooltip = {type: "string", value: tooltip};
} }

View File

@ -33,7 +33,11 @@ exports.parse = function() {
// Move past the match // Move past the match
this.parser.pos = this.matchRegExp.lastIndex; this.parser.pos = this.matchRegExp.lastIndex;
// Get the match details // Get the match details
var targetTitle = $tw.utils.trim(this.match[1]), var textRef = $tw.utils.trim(this.match[1]),
tr = $tw.utils.parseTextReference(textRef),
targetTitle = tr.title,
targetField = tr.field,
targetIndex = tr.index,
tooltip = this.match[2], tooltip = this.match[2],
template = $tw.utils.trim(this.match[3]), template = $tw.utils.trim(this.match[3]),
style = this.match[4], style = this.match[4],
@ -46,6 +50,12 @@ exports.parse = function() {
target: {type: "string", value: targetTitle} target: {type: "string", value: targetTitle}
} }
}; };
if(targetField) {
node.attributes.field = {type: "string", value: targetField};
}
if(targetIndex) {
node.attributes.index = {type: "string", value: targetIndex};
}
if(tooltip) { if(tooltip) {
node.attributes.tooltip = {type: "string", value: tooltip}; node.attributes.tooltip = {type: "string", value: tooltip};
} }

View File

@ -349,26 +349,30 @@ exports.hyphenateCss = function(propName) {
}; };
/* /*
Parse a text reference in the format "title!!field" into its constituent parts Parse a text reference of one of these forms:
* title
* !!field
* title!!field
* title##index
* etc
Returns an object with the following fields, all optional:
* title: tiddler title
* field: tiddler field name
* index: JSON property index
*/ */
exports.parseTextReference = function(textRef) { exports.parseTextReference = function(textRef) {
// Look for a metadata field separator // Separate out the title, field name and/or JSON indices
var pos = textRef.indexOf("!!"); var reTextRef = /^\s*([^\s!#]+)?(?:(?:!!([^\s]+))|(?:##([^\s]+)))?\s*/mg,
if(pos !== -1) { match = reTextRef.exec(textRef);
if(pos === 0) { if(match && reTextRef.lastIndex === textRef.length) {
// Just a field // Return the parts
return { return {
field: textRef.substring(2) title: match[1],
}; field: match[2],
} else { index: match[3]
// Field and title };
return {
title: textRef.substring(0,pos),
field: textRef.substring(pos + 2)
};
}
} else { } else {
// Otherwise, we've just got a title // If we couldn't parse it (eg it started with a)
return { return {
title: textRef title: textRef
}; };

View File

@ -57,7 +57,8 @@ TranscludeWidget.prototype.generate = function() {
var tr, templateParseTree, templateTiddler; var tr, templateParseTree, templateTiddler;
// Get the render target details // Get the render target details
this.targetTitle = this.renderer.getAttribute("target",this.renderer.getContextTiddlerTitle()); this.targetTitle = this.renderer.getAttribute("target",this.renderer.getContextTiddlerTitle());
this.targetField = this.renderer.getAttribute("field","text"); this.targetField = this.renderer.getAttribute("field");
this.targetIndex = this.renderer.getAttribute("index");
// Get the render tree for the template // Get the render tree for the template
this.templateTitle = undefined; this.templateTitle = undefined;
if(this.renderer.parseTreeNode.children && this.renderer.parseTreeNode.children.length > 0) { if(this.renderer.parseTreeNode.children && this.renderer.parseTreeNode.children.length > 0) {
@ -67,21 +68,27 @@ TranscludeWidget.prototype.generate = function() {
this.templateTitle = this.renderer.getAttribute("template",this.targetTitle); this.templateTitle = this.renderer.getAttribute("template",this.targetTitle);
// Check for recursion // Check for recursion
if(this.renderer.checkContextRecursion({ if(this.renderer.checkContextRecursion({
tiddlerTitle: this.targetTitle, tiddlerTitle: this.targetTitle,
templateTitle: this.templateTitle templateTitle: this.templateTitle
})) { })) {
templateParseTree = [{type: "text", text: "Tiddler recursion error in transclude widget"}]; templateParseTree = [{type: "text", text: "Tiddler recursion error in transclude widget"}];
} else { } else {
var parser; var parser;
if(this.targetField === "text") { if(this.targetField === "text" || (!this.targetField && !this.targetIndex)) {
parser = this.renderer.renderTree.wiki.parseTiddler(this.templateTitle,{parseAsInline: !this.renderer.parseTreeNode.isBlock}) parser = this.renderer.renderTree.wiki.parseTiddler(this.templateTitle,{parseAsInline: !this.renderer.parseTreeNode.isBlock});
} else { } else {
var tiddler = this.renderer.renderTree.wiki.getTiddler(this.targetTitle), var tiddler,text;
if(this.targetField) {
tiddler = this.renderer.renderTree.wiki.getTiddler(this.targetTitle);
text = tiddler ? tiddler.fields[this.targetField] : ""; text = tiddler ? tiddler.fields[this.targetField] : "";
if(text === undefined) { if(text === undefined) {
text = "" text = "";
}
parser = this.renderer.renderTree.wiki.parseText("text/vnd.tiddlywiki",text,{parseAsInline: !this.renderer.parseTreeNode.isBlock});
} else if(this.targetIndex) {
text = this.renderer.renderTree.wiki.extractTiddlerDataItem(this.targetTitle,this.targetIndex,"");
parser = this.renderer.renderTree.wiki.parseText("text/plain",text);
} }
parser = this.renderer.renderTree.wiki.parseText("text/vnd.tiddlywiki",text,{parseAsInline: !this.renderer.parseTreeNode.isBlock});
} }
templateParseTree = parser ? parser.tree : []; templateParseTree = parser ? parser.tree : [];
} }

View File

@ -28,18 +28,24 @@ last dispatched. Each entry is a hashmap containing two fields:
/* /*
Get the value of a text reference. Text references can have any of these forms: Get the value of a text reference. Text references can have any of these forms:
<tiddlertitle> <tiddlertitle>
<tiddlertitle>##<fieldname> <tiddlertitle>!!<fieldname>
##<fieldname> - specifies a field of the current tiddlers !!<fieldname> - specifies a field of the current tiddlers
<tiddlertitle>##<field>
*/ */
exports.getTextReference = function(textRef,defaultText,currTiddlerTitle) { exports.getTextReference = function(textRef,defaultText,currTiddlerTitle) {
var tr = $tw.utils.parseTextReference(textRef), var tr = $tw.utils.parseTextReference(textRef),
title = tr.title || currTiddlerTitle, title = tr.title || currTiddlerTitle;
field = tr.field || "text", if(tr.field) {
tiddler = this.getTiddler(title); var tiddler = this.getTiddler(title);
if(tiddler && $tw.utils.hop(tiddler.fields,field)) { if(tiddler && $tw.utils.hop(tiddler.fields,tr.field)) {
return tiddler.fields[field]; return tiddler.fields[tr.field];
} else {
return defaultText;
}
} else if(tr.index) {
return this.extractTiddlerDataItem(title,tr.index,defaultText);
} else { } else {
return defaultText; return this.getTiddlerText(title);
} }
}; };
@ -283,24 +289,46 @@ exports.getTiddlersWithTag = function(tag) {
Get a tiddlers content as a JavaScript object. How this is done depends on the type of the tiddler: Get a tiddlers content as a JavaScript object. How this is done depends on the type of the tiddler:
application/json: the tiddler JSON is parsed into an object application/json: the tiddler JSON is parsed into an object
application/x-tiddler-dictionary: the tiddler is parsed as sequence of name:value pairs
Other types currently just return null. Other types currently just return null.
*/ */
exports.getTiddlerData = function(title,defaultData) { exports.getTiddlerData = function(title,defaultData) {
var tiddler = this.tiddlers[title], var tiddler = this.tiddlers[title],
data; data;
if(tiddler && tiddler.fields.text && tiddler.fields.type === "application/json") { if(tiddler && tiddler.fields.text) {
// JSON tiddler switch(tiddler.fields.type) {
try { case "application/json":
data = JSON.parse(tiddler.fields.text); // JSON tiddler
} catch(ex) { try {
return defaultData; data = JSON.parse(tiddler.fields.text);
} catch(ex) {
return defaultData;
}
return data;
case "application/x-tiddler-dictionary":
return $tw.utils.parseFields(tiddler.fields.text);
} }
return data;
} }
return defaultData; return defaultData;
}; };
/*
Extract an indexed field from within a data tiddler
*/
exports.extractTiddlerDataItem = function(title,index,defaultText) {
var data = this.getTiddlerData(title,{}),
text;
if(data && $tw.utils.hop(data,index)) {
text = data[index];
}
if(typeof text === "string" || typeof text === "number") {
return text.toString();
} else {
return defaultText;
}
};
/* /*
Set a tiddlers content to a JavaScript object. Currently this is done by setting the tiddler's type to "application/json" and setting the text to the JSON text of the data. Set a tiddlers content to a JavaScript object. Currently this is done by setting the tiddler's type to "application/json" and setting the text to the JSON text of the data.
*/ */
@ -619,11 +647,11 @@ exports.handleSyncerEvent = function(event) {
/* /*
Trigger a load for a tiddler if it is skinny. Returns the text, or undefined if the tiddler is missing, null if the tiddler is being lazily loaded. Trigger a load for a tiddler if it is skinny. Returns the text, or undefined if the tiddler is missing, null if the tiddler is being lazily loaded.
*/ */
exports.getTiddlerText = function(title) { exports.getTiddlerText = function(title,defaultText) {
var tiddler = this.getTiddler(title); var tiddler = this.getTiddler(title);
// Return undefined if the tiddler isn't found // Return undefined if the tiddler isn't found
if(!tiddler) { if(!tiddler) {
return undefined; return defaultText;
} }
if(tiddler.fields.text !== undefined) { if(tiddler.fields.text !== undefined) {
// Just return the text if we've got it // Just return the text if we've got it

View File

@ -24,7 +24,7 @@ html body {
.tw-tiddler-frame { .tw-tiddler-frame {
padding: 30px 30px 30px 30px; padding: 30px 30px 30px 30px;
margin: 0px; margin: 0px;
background-color: #fff; background-color: {{$:/core/styles/colours##primary}};
border-left: 1px solid #ddd; border-left: 1px solid #ddd;
border-right: 1px solid #ddd; border-right: 1px solid #ddd;
border-bottom: 1px solid #ddd; border-bottom: 1px solid #ddd;

View File

@ -0,0 +1,4 @@
title: $:/core/styles/colours
type: application/x-tiddler-dictionary
primary: #80ffff