Last modified by Simon Urli on 2023/10/10

From version 84.1
edited by Denis Gervalle
on 2013/02/20
Change comment: Update the WYSIWYG special code advice
To version 85.3
edited by Denis Gervalle
on 2013/02/23
Change comment: There is no comment for this version

Summary

Details

Page properties
Syntax
... ... @@ -1,1 +1,1 @@
1 -XWiki 1.0
1 +XWiki 2.1
Content
... ... @@ -1,111 +1,95 @@
1 -#startfloatingbox()
2 -*Contents*
3 -#toc ("2" "3" "")
4 -#endfloatingbox()
1 +{{box cssClass="floatinginfobox" title="**Contents**"}}
2 +{{toc/}}
3 +{{/box}}
5 5  
6 -Wiki macros allow macro authors to develop reusable and distributable macro modules. There is no java code involved; hence no compiling or packaging. Macro author simply needs to create a wiki page according to a particular specification and that's all!
5 +Wiki macros allow macro authors to develop reusable and distributable macro modules. There is no java code involved; hence no compiling or packaging. The macro author simply needs to create a wiki page according to a particular specification and that's all!
7 7  
8 -1.1 Prerequisites
7 += Macro Visibility and Rights =
9 9  
10 -* Wiki macros are only available on XWiki Enterprise 2.0M2 and later versions
9 +There are 3 levels of visibility for a macro:
11 11  
12 -1.1 Macro Visibility and Rights
13 -
14 -There are 3 levels of visibility for a macro:
15 15  * farm (if we're in a multiwiki environment), meaning that the macro will be available in all the wikis of the farm
16 16  * wiki, which means that the macro will be available in its wiki
17 -* user, which means that the macro will only be available to the which is its author.
13 +* user, which means that the macro will only be available to the user which is its author
18 18  
19 19  The rights required to create macros are different depending on the visibility we want for our macro:
20 -* the macro author needs to have *programming* rights for a macro available in the whole *farm*
21 -* the macro author needs to have *admin* rights for a macro available in its *wiki*
16 +
17 +* the macro author needs to have **programming** rights for a macro available in the whole **farm**
18 +* the macro author needs to have **admin** rights for a macro available in its **wiki**
22 22  * no special rights besides the obvious right to edit the page are needed for a macro available only to its author.
23 23  
24 -1.1.1 Using protected API in wiki macros
21 +== Using protected API in wiki macros ==
25 25  
26 -Also, if the macro needs to use [protected API>platform:DevGuide.Scripting#HXWikiCoreAccess], the author of the macro will need to have programming rights. Note that the macro will always be executed with the rights of its author, and not with the rights of the author of the calling document (the document using the macro). Specifically, if the macro uses protected API, only the macro author needs to have programming rights, not all the authors of the documents that call this macro.
23 +Also, if the macro needs to use [[protected API>>Scripting||anchor="HXWikiCoreAccess"]], the author of the macro will need to have programming rights. Note that the macro will always be executed with the rights of its author, and not with the rights of the author of the calling document (the document using the macro). Specifically, if the macro uses protected API, only the macro author needs to have programming rights, not all the authors of the documents that call this macro.
27 27  
28 -1.1 Hello Macro
25 += Hello Macro =
29 29  
30 30  We are going to start with a very simple xwiki/2.0 wiki macro which prints a greeting message to the document content. It isn't a very useful macro but the idea is to get you familiarised with the wiki macro creation process.
31 31  
32 -1.1.1 Definition
29 +== Definition ==
33 33  
34 -Wiki macros are defined using objects of type XWiki.WikiMacroClass. You define a wiki macro by creating a new wiki page and attaching it an object of type XWiki.WikiMacroClass. This class contains following fields:
31 +Wiki macros are defined using objects of type ##XWiki.WikiMacroClass##. You define a wiki macro by creating a new wiki page and attaching to it an object of type ##XWiki.WikiMacroClass##. This class contains the following fields:
35 35  
36 36  * Macro id: Id of the macro to be used by users when invoking your macro from wiki code
37 -
38 38  * Macro name: Name of the macro to be displayed on the wysiwyg editor
39 -
40 40  * Macro description: A short description of the macro to be displayed on the WYSIWYG editor
41 -
42 42  * Default category: Default category under which this macro should be listed
43 -
44 44  * Supports inline mode: Whether the macro can be used in an inline context or not
45 -
46 46  * Macro content type: Whether this macro should support a body or not
47 -
48 48  * Content description: A short description about the macro's content to be displayed on the WYSIWYG editor
49 -
50 50  * Macro code: The actual wiki code that will be evaluated when the macro is executed, can be any xwiki content (should be in the same syntax as the document)
51 51  
52 52  Now we can define our hello macro as shown below:
53 53  
54 -{image:macro1.png}
44 +[[image:macro1.png]]
55 55  
56 -1.1.1 Invocation
46 +== Invocation ==
57 57  
58 -A wiki macro can be invoked just like any other macro is invoked. Since we are writing a xwiki/2.0 wiki macro, we can invoke our hello macro as below:
48 +A wiki macro can be invoked just like any other macro is invoked. Since we are writing a xwiki/2.0 wiki macro, we can invoke our **hello macro** as below:
59 59  
60 -{code}
61 -{{hello/}}
62 -{code}
50 +{{code}}{{hello/}}{{/code}}
63 63  
64 64  And if you view the result it would say "Hello World!" (of course).
65 65  
66 -1.1.1 Parameters
54 +== Parameters ==
67 67  
68 -Introducing a parameter to a wiki macro is pretty straight forward; you simply need to add an object of type XWiki.WikiMacroParameterClass into your wiki macro document (one object per parameter). This class contains several fields that allow you to define your parameter clearly:
56 +Introducing a parameter to a wiki macro is pretty straight forward; you simply need to add an object of type ##XWiki.WikiMacroParameterClass## into your wiki macro document (one object per parameter). This class contains several fields that allow you to define your parameter clearly:
69 69  
70 70  * Parameter name: Name of the parameter, users will refer this name when invoking your macro with parameters
71 -
72 72  * Parameter description: A short description of the parameter, this description will be made available on the WYSIWYG editor
73 -
74 74  * Parameter mandatory: Indicates if this particular parameter is mandatory, wiki macro will fail to execute if a mandatory parameter is missing
75 75  
76 -Now we're going to extend our hello macro with a parameter. We will introduce a parameter named ~~greetUser~~ that will indicate if the greeting message should be tailored for current user viewing the page. The definition of the parameter is show below:
62 +Now we're going to extend our **hello macro** with a parameter. We will introduce a parameter named //greetUser// that will indicate if the greeting message should be tailored for the current user viewing the page. The definition of the parameter is shown below:
77 77  
78 -{image:macro3.png}
64 +[[image:macro3.png]]
79 79  
80 -A macro parameter defined this way can be accessed from any scripting language within the macro code. For an example, we are going to utilize our ~~greetUser~~ parameter within hello macro as below:
66 +A macro parameter defined this way can be accessed from any scripting language within the macro code. For example, we are going to utilize our //greetUser// parameter within **hello macro** as shown below:
81 81  
82 -{image:macro4.png}
68 +[[image:macro4.png]]
83 83  
84 -As you might have realized already, direct binding of parameters is not supported at the moment. That is, you cannot access ~~greetUser~~ parameter with *$greetUser*. Instead you must use *$xcontext.macro.params.greetUser*. We plan to introduce some form of direct parameter binding in near future.
70 +As you might have realized already, direct binding of parameters is not supported at the moment. That is, you cannot access //greetUser// parameter with **$greetUser**. Instead you must use **$xcontext.macro.params.greetUser**. We plan to introduce some form of direct parameter binding in near future.
85 85  
86 -Finally, we can test our new version of hello macro with the following invocation:
72 +Finally, we can test our new version of **hello macro** with the following invocation:
87 87  
88 -{code}
89 -{{hello greetUser="true"/}}
90 -{code}
74 +{{code language="none"}}{{hello greetUser="true"/}}{{/code}}
91 91  
92 -1.1 WYSIWYG Access
76 += WYSIWYG Access =
93 93  
94 -A wiki macros is treated just like any other rendering macro in the system. As such, the moment you save your wiki macro it will be available to the users through the WYSIWYG editor's *Insert Macro* dialog box:
78 +A wiki macros is treated just like any other rendering macro in the system. As such, the moment you save your wiki macro it will be available to the users through the WYSIWYG editor's **Insert Macro** dialog box:
95 95  
96 -{image:macro2.png}
80 +[[image:macro2.png]]
97 97  
98 -{image:macro5.png}
82 +[[image:macro5.png]]
99 99  
100 -1.1.1 Special code for WYSIWYG edit mode
84 +== Special code for WYSIWYG edit mode ==
101 101  
102 102  Even in edit mode, the WYSIWYG editor will execute the macro and feed the result back into the document. If your macro use some JSX, these will not be loaded. But, if your macro produce some Javascript that use those JSX or manipulate the document's DOM (injecting new elements, moving existing elements, removing elements, etc.), you may want to protect the content in WYSIWYG edit mode in order to prevent the performed transformation to get saved. Here is how you can prevent this behavior:
103 103  
104 -{code}
88 +{{code language="velocity"}}
105 105  {{velocity}}
106 106  #if("$xcontext.action" != "edit")
107 107  {{html}}
108 - <script type=${dq}text/javascript${dq}>
92 + <script type="text/javascript">
109 109  //<![CDATA[
110 110  ... some javascript ...
111 111  // ]]>
... ... @@ -115,21 +115,18 @@
115 115  ##
116 116  ## Rest of the code.
117 117  {{velocity}}
118 -{code}
102 +{{/code}}
119 119  
120 -1.1 Scripting Tips
104 += Scripting Tips =
121 121  
122 -Following are few useful hints if you plan to do advanced scripting inside your wiki macros:
106 +Following are a few useful hints if you plan to do advanced scripting inside your wiki macros:
123 123  
124 -* Access parameters: Use the context object (Ex. \$xcontext.macro.params.param1)
125 -
126 -* Access macro body (if your macro defines one): Use the context object (Ex. \$xcontext.macro.content)
127 -
128 -* Access [MacroTransformationContext>http://svn.xwiki.org/svnroot/xwiki/platform/core/trunk/xwiki-rendering/xwiki-rendering-api/src/main/java/org/xwiki/rendering/transformation/MacroTransformationContext.java]: Use the context object (Ex. \$xcontext.macro.context)
129 -
130 -* Since 2.4M1, it's possible to directly return the desired list of rendering Blocks without having to render them first to let them be parsed back by the macro transformation. The benefits are that it could be a lots quicker and most of all it means supporting syntax which does not provide any renderer. It also make possible to generate some XDOM which is impossible to write in any some syntax. For example the following wiki macro is generating a LinkBlock targeting a relative URL:
131 -
132 -{code}
108 +* Access parameters: Use the context object (Ex. ##$xcontext.macro.params.param1##)
109 +* Access macro body (if your macro defines one): Use the context object (Ex. ##$xcontext.macro.content##)
110 +* Access [[MacroTransformationContext>>http://svn.xwiki.org/svnroot/xwiki/platform/core/trunk/xwiki-rendering/xwiki-rendering-api/src/main/java/org/xwiki/rendering/transformation/MacroTransformationContext.java]]: Use the context object (Ex. ##$xcontext.macro.context##)
111 +* Since 2.4M1, it's possible to directly return the desired list of rendering blocks without having to render them first to let them be parsed back by the macro transformation. The benefits are that it could be a lots quicker and most of all it means supporting syntax which does not provide any renderer. It also makes it possible to generate some XDOM which is impossible to write in any some syntax. For example the following wiki macro is generating a LinkBlock targeting a relative URL:
112 +(((
113 +{{code language="groovy"}}
133 133  {{groovy}}
134 134  import java.util.Collections;
135 135  import org.xwiki.rendering.listener.Link;
... ... @@ -146,11 +146,11 @@
146 146  {{/groovy}}
147 147  
148 148  This text will not appear in the result.
149 -{code}
150 -
151 -* If you are using \$xcontext.macro.content in your velocity macro, that content will not be able to support scripting, since nested scripting is not supported. To workaround that limitation, thanks to the above, you may do the parsing yourself using the rendering service. Here is a small sample:
152 -
153 -{code}
130 +{{/code}}
131 +)))
132 +* If you are using ##$xcontext.macro.content## in your velocity macro, that content will not be able to support scripting, since nested scripting is not supported. To workaround that limitation, thanks to the above, you may do the parsing yourself using the rendering service. Here is a small sample:
133 +(((
134 +{{code languege="velocity"}}
154 154  {{velocity output="no"}}
155 155  ## get the macro content in a velocity string
156 156  #set($wikiresult = $xcontext.macro.content)
... ... @@ -159,17 +159,19 @@
159 159  ## parse the string and return the resulting blocks
160 160  #set($xcontext.macro.result = $services.rendering.parse($wikiresult, $xwiki.getCurrentContentSyntaxId()).getChildren())
161 161  {{/velocity}}
162 -{code}
143 +{{/code}}
144 +)))
145 += Troubleshooting =
163 163  
164 -1.1 Troubleshooting
147 +== A Pitfall of Optional Parameters ==
165 165  
166 -1.1.1 A Pitfall of Optional Parameters
149 +{{info}}
150 +This pitfall has been fixed in XWiki 2.2
151 +{{/info}}
167 167  
168 -#info("This pitfall has been fixed in XWiki 2.2")
169 -
170 170  There is a common pitfall for using optional paramters. The following macro code contains a not so obvious bug:
171 171  
172 -{code}
155 +{{code languege="velocity"}}
173 173  {{velocity}}
174 174  #set($greetUser=$xcontext.macro.params.greetUser)
175 175  #if ("true" == $greetUser && "XWiki.XWikiGuest" != "$xcontext.user" )
... ... @@ -178,22 +178,22 @@
178 178   Hello world!
179 179  #end
180 180  <img src="$image" width="$width" />
181 -{code}
164 +{{/code}}
182 182  
183 183  If we invoke it twice in a row:
184 184  
185 -{code}
168 +{{code}}
186 186  {{hello greetUser="true" /}}
187 187  {{hello /}}
188 -{code}
171 +{{/code}}
189 189  
190 190  The second invocation will not print "Hello World!" as we'd expect. But it will print the same result as the first invocation. The reasons are:
191 -* Macro parameters are implemented as global parameters. So, they remains the same across multiple macro invocations.
192 -* If $xcontext.macro.params.greetUser contains "null", it will not be assigned to $greetUser. This is different from C/C++ or Java.
193 193  
175 +* Macro parameters are implemented as global parameters. So, they remain the same across multiple macro invocations.
176 +* If ##$xcontext.macro.params.greetUser## contains "null", it will not be assigned to ##$greetUser##. This is different from C/C++ or Java.
177 +
194 194  So in order to get around it, you can use:
195 195  
196 -{code}
180 +{{code}}
197 197  #set($greetUser="$!xcontext.macro.params.greetUser")
198 -{code}
199 -
182 +{{/code}}
XWiki.XWikiComments[0]
Comment
... ... @@ -1,3 +1,1 @@
1 -Note
2 -parameters are of type string.
3 -passing other types like a list of string will fail.
1 +Note parameters are of type string. passing other types like a list of string will fail.

Get Connected