0 votes
by (720 points)

Hi there. I've been making simple custom macros. For example to do a macro like this <<macroname 1 2 3 >>, I'd use:

macros.macroname = {
    handler: function(place, macroName, params, parser) {
      var html = "";
      html += "param[0] "+params[0]+"<br>";
      html += "param[1] "+params[1]+"<br>";
      html += "param[2] "+params[2]+"<br>";
      new Wikifier(place, html);
    },
};

However, I want to do a macro in this format:

<<macroname 1 2 3 >> 

  (some multi-line content)

<</macroname>>

Where the content between is used by the macro in some way. (I don't know the word for this, so I don't even know what to search for.) How do I do this?

1 Answer

+1 vote
by (44.7k points)
selected by
 
Best answer

How to do this is explained in the Macro API and MacroContext API sections of the SugarCube documentation.  So, to correct your above code, you should do:

Macro.add('macroname', {
	handler: function() {
		var html = "";
		html += "param[0] "+this.args[0]+"<br>";
		html += "param[1] "+this.args[1]+"<br>";
		html += "param[2] "+this.args[2]+"<br>";
		$(this.output).wiki(html);
	}
});

So then if you did "<<macroname 1 2 3>>" it would output:

param[0] 1
param[1] 2
param[2] 3

As for displaying the contents of a macro, you have to add "tags" to define names for any blocks of content you want to have inside the macro, or "null" if you only want the one main block.  Then to get the code block's contents you use "this.payload[N].contents", where "N" is the number of the block of content (starting with zero).  You can use "this.payload.length" to determine how many blocks of content the code has within that macro.  For a simple example, modifying the above code to include a content block gives you this code:

Macro.add('macroname', {
	tags: null,
	handler: function() {
		var html = "";
		html += "param[0] "+this.args[0]+"<br>";
		html += "param[1] "+this.args[1]+"<br>";
		html += "param[2] "+this.args[2]+"<br>";
		html += "content: "+this.payload[0].contents+"<br>";
		$(this.output).wiki(html);
	}
});

So then if you did "<<macroname 1 2 3>>test<</macroname>>" it would output:

param[0] 1
param[1] 2
param[2] 3
content: test

You could add multiple content blocks by adding an array of strings to the "tags" parameter in the definition, instead of using "null" there, and you can tell what tag name is being used in a code block by checking "this.payload[N].name" and any parameters passed in to that tag by checking the values in the "this.payload[N].args" array.

Hope that helps!  :-)

by (720 points)
That does help, thank you.
...