1
0
mirror of https://github.com/Jermolene/TiddlyWiki5 synced 2025-02-22 14:00:03 +00:00

Make the macrocall widget delegate to the transclude widget

This commit is contained in:
jeremy@jermolene.com 2022-05-08 20:48:33 +01:00
parent 4f2f689ab9
commit 64448ae774
13 changed files with 87 additions and 51 deletions

View File

@ -28,6 +28,8 @@ var AudioParser = function(type,text,options) {
element.attributes.src = {type: "string", value: "data:" + type + ";base64," + text};
}
this.tree = [element];
this.source = text;
this.type = type;
};
exports["audio/ogg"] = AudioParser;

View File

@ -64,6 +64,8 @@ var BinaryParser = function(type,text,options) {
children: [warn, link]
}
this.tree = [element];
this.source = text;
this.type = type;
};
exports["application/octet-stream"] = BinaryParser;

View File

@ -45,6 +45,8 @@ var CsvParser = function(type,text,options) {
this.tree[0].children[0].children[0].children.push(row);
}
}
this.source = text;
this.type = type;
};
exports["text/csv"] = CsvParser;

View File

@ -29,6 +29,8 @@ var HtmlParser = function(type,text,options) {
if($tw.wiki.getTiddlerText("$:/config/HtmlParser/DisableSandbox","no") !== "yes") {
this.tree[0].attributes.sandbox = {type: "string", value: $tw.wiki.getTiddlerText("$:/config/HtmlParser/SandboxTokens","")};
}
this.source = text;
this.type = type;
};
exports["text/html"] = HtmlParser;

View File

@ -28,6 +28,8 @@ var ImageParser = function(type,text,options) {
}
}
this.tree = [element];
this.source = text;
this.type = type;
};
exports["image/svg+xml"] = ImageParser;

View File

@ -25,6 +25,8 @@ var ImageParser = function(type,text,options) {
element.attributes.src = {type: "string", value: "data:application/pdf;base64," + text};
}
this.tree = [element];
this.source = text;
this.type = type;
};
exports["application/pdf"] = ImageParser;

View File

@ -20,6 +20,8 @@ var TextParser = function(type,text,options) {
language: {type: "string", value: type}
}
}];
this.source = text;
this.type = type;
};
exports["text/plain"] = TextParser;

View File

@ -28,6 +28,8 @@ var VideoParser = function(type,text,options) {
element.attributes.src = {type: "string", value: "data:" + type + ";base64," + text};
}
this.tree = [element];
this.source = text;
this.type = type;
};
exports["video/ogg"] = VideoParser;

View File

@ -37,7 +37,7 @@ MacroCallWidget.prototype.render = function(parent,nextSibling) {
Compute the internal state of the widget
*/
MacroCallWidget.prototype.execute = function() {
// Get the parse type if specified
this.macroName = this.parseTreeNode.name || this.getAttribute("$name"),
this.parseType = this.getAttribute("$type","text/vnd.tiddlywiki");
this.renderOutput = this.getAttribute("$output","text/html");
// Merge together the parameters specified in the parse tree with the specified attributes
@ -47,49 +47,26 @@ MacroCallWidget.prototype.execute = function() {
params.push({name: name, value: attribute});
}
});
// Get the macro value
var macroName = this.parseTreeNode.name || this.getAttribute("$name"),
variableInfo = this.getVariableInfo(macroName,{params: params}),
text = variableInfo.text,
parseTreeNodes;
// Are we rendering to HTML?
if(this.renderOutput === "text/html") {
// If so we'll return the parsed macro
// Check if we've already cached parsing this macro
var mode = this.parseTreeNode.isBlock ? "blockParser" : "inlineParser",
parser;
if(variableInfo.srcVariable && variableInfo.srcVariable[mode]) {
parser = variableInfo.srcVariable[mode];
} else {
parser = this.wiki.parseText(this.parseType,text,
{parseAsInline: !this.parseTreeNode.isBlock});
if(variableInfo.isCacheable && variableInfo.srcVariable) {
variableInfo.srcVariable[mode] = parser;
}
}
var parseTreeNodes = parser ? parser.tree : [];
// Wrap the parse tree in a vars widget assigning the parameters to variables named "__paramname__"
var attributes = {};
$tw.utils.each(variableInfo.params,function(param) {
var name = "__" + param.name + "__";
attributes[name] = {
name: name,
type: "string",
value: param.value
};
});
// Make a transclude widget
var positionalName = 0,
parseTreeNodes = [{
type: "vars",
attributes: attributes,
children: parseTreeNodes
type: "transclude",
isBlock: this.parseTreeNode.isBlock
}];
} else if(this.renderOutput === "text/raw") {
parseTreeNodes = [{type: "text", text: text}];
} else {
// Otherwise, we'll render the text
var plainText = this.wiki.renderText("text/plain",this.parseType,text,{parentWidget: this});
parseTreeNodes = [{type: "text", text: plainText}];
}
$tw.utils.addAttributeToParseTreeNode(parseTreeNodes[0],"$variable",this.macroName);
$tw.utils.addAttributeToParseTreeNode(parseTreeNodes[0],"$type",this.parseType);
$tw.utils.addAttributeToParseTreeNode(parseTreeNodes[0],"$output",this.renderOutput);
$tw.utils.each(params,function(param) {
var name = param.name;
if(name) {
if(name.charAt(0) === "$") {
name = "$" + name;
}
$tw.utils.addAttributeToParseTreeNode(parseTreeNodes[0],name,param.value);
} else {
$tw.utils.addAttributeToParseTreeNode(parseTreeNodes[0],(positionalName++) + "",param.value);
}
});
// Construct the child widgets
this.makeChildWidgets(parseTreeNodes);
};

View File

@ -44,9 +44,24 @@ TranscludeWidget.prototype.execute = function() {
// Get the parse tree nodes that we are transcluding
var target = this.getTransclusionTarget(),
parseTreeNodes = target.parseTreeNodes;
this.sourceText = target.source;
this.sourceText = target.text;
this.sourceType = target.type;
this.parseAsInline = target.parseAsInline;
// Process the transclusion according to the output type
switch(this.transcludeOutput || "text/html") {
case "text/html":
// No further processing required
break;
case "text/raw":
// Just return the raw text
parseTreeNodes = [{type: "text", text: this.sourceText}];
break;
default:
// text/plain
var plainText = this.wiki.renderText("text/plain",this.sourceType,this.sourceText,{parentWidget: this});
parseTreeNodes = [{type: "text", text: plainText}];
break;
}
// Set context variables for recursion detection
var recursionMarker = this.makeLegacyRecursionMarker(),
newRecursionMarker = this.makeRecursionMarker();
@ -91,6 +106,7 @@ TranscludeWidget.prototype.collectAttributes = function() {
} else {
this.transcludeVariable = this.getAttribute("$variable");
this.transcludeType = this.getAttribute("$type");
this.transcludeOutput = this.getAttribute("$output","text/html");
this.transcludeTitle = this.getAttribute("$tiddler",this.getVariable("currentTiddler"));
this.transcludeSubTiddler = this.getAttribute("$subtiddler");
this.transcludeField = this.getAttribute("$field");
@ -157,7 +173,7 @@ TranscludeWidget.prototype.collectSlotValueParameters = function() {
Get transcluded parse tree nodes as an object {parser:,text:,type:}
*/
TranscludeWidget.prototype.getTransclusionTarget = function() {
// Parse the text reference
// Determine whether we're being used in inline or block mode
var parseAsInline = !this.parseTreeNode.isBlock;
if(this.transcludeMode === "inline") {
parseAsInline = true;
@ -165,9 +181,11 @@ TranscludeWidget.prototype.getTransclusionTarget = function() {
parseAsInline = false;
}
var parser;
// Get the parse tree
if(this.transcludeVariable) {
// Transcluding a variable
var variableInfo = this.getVariableInfo(this.transcludeVariable,{params: this.getOrderedTransclusionParameters()}),
srcVariable = variableInfo.srcVariable;
srcVariable = variableInfo && variableInfo.srcVariable;
if(srcVariable) {
var mode = parseAsInline ? "inlineParser" : "blockParser";
if(srcVariable.isCacheable && srcVariable[mode]) {
@ -179,6 +197,7 @@ TranscludeWidget.prototype.getTransclusionTarget = function() {
}
}
if(parser) {
// Add parameters widget for functions
if(srcVariable.isFunctionDefinition) {
parser = {
tree: [
@ -186,20 +205,24 @@ TranscludeWidget.prototype.getTransclusionTarget = function() {
type: "parameters",
children: parser.tree
}
]
],
source: parser.source,
type: parser.type
}
$tw.utils.each(srcVariable.params,function(param) {
$tw.utils.addAttributeToParseTreeNode(parser.tree[0],param.name,param["default"])
});
} else if(srcVariable.isMacroDefinition) {
// Wrap the parse tree in a vars widget assigning the parameters to variables named "__paramname__"
// For macros, wrap the parse tree in a vars widget assigning the parameters to variables named "__paramname__"
parser = {
tree: [
{
type: "vars",
children: parser.tree
}
]
],
source: parser.source,
type: parser.type
}
$tw.utils.each(variableInfo.params,function(param) {
$tw.utils.addAttributeToParseTreeNode(parser.tree[0],"__" + param.name + "__",param.value)
@ -208,6 +231,7 @@ TranscludeWidget.prototype.getTransclusionTarget = function() {
}
}
} else {
// Transcluding a text reference
parser = this.wiki.parseTextReference(
this.transcludeTitle,
this.transcludeField,
@ -217,6 +241,7 @@ TranscludeWidget.prototype.getTransclusionTarget = function() {
subTiddler: this.transcludeSubTiddler
});
}
// Return the parse tree
if(parser) {
return {
parser: parser,
@ -226,6 +251,7 @@ TranscludeWidget.prototype.getTransclusionTarget = function() {
type: parser.type
};
} else {
// If there's no parse tree then return the missing slot value
return {
parser: null,
parseTreeNodes: (this.slotValueParseTrees["ts-missing"] || []),
@ -364,7 +390,7 @@ TranscludeWidget.prototype.makeLegacyRecursionMarker = function() {
};
TranscludeWidget.prototype.parserNeedsRefresh = function() {
// TODO: Doesn't consider transcluded variables
// Doesn't need to consider transcluded variables because a parent variable can't change once a widget has been created
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)
};

View File

@ -0,0 +1,17 @@
title: Transclude/Macro/Plain
description: Transcluding a macro as plain text
type: text/vnd.tiddlywiki-multiple
tags: [[$:/tags/wiki-test-spec]]
title: Output
\whitespace trim
<$let currentTab="Jeremy">
<$macrocall $name="currentTab" $type="text/plain" $output="text/plain"/>
|
<$transclude $variable="currentTab" $type="text/plain" $output="text/plain"/>
</$let>
+
title: ExpectedResult
<p>Jeremy|Jeremy</p>

View File

@ -124,7 +124,7 @@ describe("Wiki.parseTextReference tests", function() {
// Non-existent subtiddler of a plugin
expect(parseAndGetSource("$:/ShadowPlugin","text",null,"MyMissingTiddler")).toEqual(null);
// Plain text tiddler
expect(parseAndGetSource("TiddlerNine")).toEqual(undefined);
expect(parseAndGetSource("TiddlerNine")).toEqual("this is plain text");
});
});

View File

@ -74,7 +74,7 @@ describe("Tabs-macro HTML tests", function() {
expect(wiki.renderTiddler("text/html","test-tabs-macro-horizontal")).toBe(expected.fields.text.replace(/\n/g,""));
});
it("should render 'horizontal' tabs from v5.2.2 and up with whitespace trim", function() {
it("should render all 'horizontal' tabs from v5.2.2 and up with whitespace trim", function() {
expect(wiki.renderTiddler("text/html","test-tabs-macro-horizontal-all")).toBe(expectedAll.fields.text.replace(/\n/g,""));
});